# Deeplinking

### Introduction

It's common in mobile calling apps that a call can be started from a link, that should start the app and dial in immediately. This can be accomplished by [universal links on iOS](https://developer.apple.com/ios/universal-links/). The setup needs to be done in your hosting app, while the StreamVideo SDK allows for a call to be invoked from a universal link.

### App ID setup

In order to support universal links, you need to have paid Apple developer account. On the Apple developer website, you will need to add the "associated domains" for your app id.

Next, you need to enable the "Associated Domains" capability for your app in Xcode, and specify an app link, in the format `applinks:{host}`.

Next, you need to upload `apple-app-site-association` file, either to the root directory of your website, or in the `.wellKnown` directory. The AASA (short for apple-app-site-association) is a JSON file that lives on your website and associates your domain with your native app.

In its simplest form, your AASA file should have the following format:

```swift
{
  "applinks": {
    "apps": [],
    "details": [{
      "appID": "{your_team_id}.{your_bundle_id}",
      "paths": [
        "*"
      ]
    }]
  }
}
```

You can also specify exact paths if you want to have a stricter control over which ones can invoke your app. You can also specify several apps on the same domain.

Before proceeding, please make sure that the uploaded file is a valid one, and it's deployed at the right place. For this, you can use Apple's [validation tool](https://search.developer.apple.com/appsearch-validation-tool).

### iOS Code

The minimal data the link that should invoke the call should contain are the call id and type. In your iOS app, you should parse the parameters of your link, and use those to start a call from our `CallViewModel`. Additionally, you should already have a user logged in, since if you're app was not running, you will need to setup the `StreamVideo` client with a user first.

One example of how your URL should look like could be this: `https://{host}/{path}/{some_call_id}?type={some_call_type}`.

If you are using SwiftUI, the easiest way to handle these links is to attach the `onOpenURL` modifier:

```swift
YourView()
    .onOpenURL { url in
        handleDeepLink(from: url)
    }

private func handleDeepLink(from url: URL) {
    if appState.userState == .notLoggedIn {
        return
    }
    let callId = url.lastPathComponent
    let queryParams = url.queryParameters
    let callType = queryParams["type"] ?? "default"
    appState.deeplinkInfo = DeeplinkInfo(callId: callId, callType: callType)
}
```

In this example, we are keeping the app state in a simple struct, that contains information about a `@Published` `deeplinkInfo`. The `DeeplinkInfo` type contains information about the `callId` and the `callType`.

Next, your SwiftUI view that hosts the calling functionality, can react to changes of the `deeplinkInfo` and join a call accordingly.

```swift
ViewThatHostsCall()
    .onReceive(appState.$deeplinkInfo, perform: { deeplinkInfo in
        if deeplinkInfo != .empty {
              callViewModel.joinCall(callType: deeplinkInfo.callType, callId: deeplinkInfo.callId)
              appState.deeplinkInfo = .empty
          }
    })
```

If you are using `UIKit`, you will need to implement a similar logic in `application:continueUserActivity:restorationHandler`, in your `AppDelegate`.


---

This page was last updated at 2026-07-13T13:43:22.922Z.

For the most recent version of this documentation, visit [https://getstream.io/video/docs/ios/advanced/deeplinking/](https://getstream.io/video/docs/ios/advanced/deeplinking/).