Skip to main content



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. 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:

"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.

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:

.onOpenURL { url in
handleDeepLink(from: url)

private func handleDeepLink(from url: URL) {
if appState.userState == .notLoggedIn {
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.

.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.

Did you find this page helpful?