> ## Documentation Index
> Fetch the complete documentation index at: https://www.dynamic.xyz/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Open deep links

> Open cross-platform deep links from a Dynamic JavaScript SDK extension.

The `openDeeplink` service on `DynamicCore` opens a URL in the right way for the current platform. Use it from an extension to send a user to a mobile wallet app, or to trigger a redirect that comes back to your app.

## Access the service

```typescript theme={"system"}
import { getCore } from "@dynamic-labs-sdk/client/core";
import type { DynamicClient } from "@dynamic-labs-sdk/client";

const open = async (url: string, client?: DynamicClient) => {
  await getCore(client).openDeeplink(url);
};
```

`openDeeplink` is a function of type `(url: string) => Promise<void>`.

## Platform behavior

<Tabs>
  <Tab title="Web">
    On web, the SDK uses `window.location.assign` to navigate to the deep link in the same tab. This avoids extra `about:blank` tabs when the wallet redirects back to the app.
  </Tab>

  <Tab title="React Native">
    On React Native, there is no default browser location API. Pass a platform opener when creating the client:

    ```typescript theme={"system"}
    import { createDynamicClient } from "@dynamic-labs-sdk/client";
    import * as Linking from "expo-linking"; // or from "react-native"

    const client = createDynamicClient({
      environmentId: "YOUR_ENVIRONMENT_ID",
      coreConfig: {
        openDeeplink: async (url) => {
          await Linking.openURL(url);
        },
      },
    });
    ```
  </Tab>
</Tabs>

## Usage in an extension

Extensions can wrap `openDeeplink` in a helper that builds the URL and then opens it:

```typescript theme={"system"}
import {
  getDefaultClient,
  hasExtension,
} from "@dynamic-labs-sdk/client/core";
import { getCore } from "@dynamic-labs-sdk/client/core";
import type { DynamicClient } from "@dynamic-labs-sdk/client";

const MY_WALLET_EXTENSION_KEY = "myWallet";

export const openMyWalletDeposit = (
  url: string,
  client: DynamicClient = getDefaultClient()
): Promise<void> => {
  if (!hasExtension({ extensionKey: MY_WALLET_EXTENSION_KEY }, client)) {
    throw new Error("My Wallet extension is not registered");
  }

  return getCore(client).openDeeplink(url);
};
```

## QR codes on desktop and mobile web

The same URL passed to `openDeeplink` can be encoded as a QR code on desktop or mobile web, where the user's wallet app scans it instead of the page opening the link directly. Render the QR code with any QR library and use the same deep-link URL as the value.

```typescript theme={"system"}
import { createMyWalletDepositUrl } from "./createMyWalletDepositUrl";

const url = createMyWalletDepositUrl({ flow }).toString();

// On mobile native or mobile web, open the wallet app directly:
await openMyWalletDeposit(url);

// On desktop, show a QR code containing the same URL.
```

## Security notes

* Only open URLs from trusted sources.
* Reject schemes that can execute script, such as `javascript:` or `data:`.
* If your extension accepts a `returnUrl`, validate it against a known allow-list.
