Install & initialize
Three steps: register the app in your OptoLink org, ship the associated-domains entitlement, add the SDK and initialize it. When you're done, a link tap opens your app directly and the SDK hands you the link data.
Flutter app? Use the OptoLink Flutter plugin, which channels this SDK → Flutter install.
This page covers the app-side work only; step ① is the only part that touches the portal.
Requirements
- iOS 15+ deployment target in your app.
- A CLIENT-tier API key (
opl_sdk_…), minted in the OptoLink portal. - An OptoLink backend at v2.1.0 or newer.
- Xcode with your app target signed against a real Apple Developer team (associated domains need one).
① Register the app in the portal
During portal onboarding (set up your organization), fill in the IOS app config for your org:
| Field | Value | Example |
|---|---|---|
bundleId | Your app's bundle identifier, from the Xcode target's Signing & Capabilities | com.example.shop |
teamId | Your Apple Developer Team ID, from the same screen (Team) | A1B2C3D4E5 |
storeUrl | Your App Store listing URL | https://apps.apple.com/app/id123456789 |
The backend builds the apple-app-site-association file for your link domain from this config, so what you enter here is what iOS verifies against. Your links are served from your org's link domain — the examples below use links.yourdomain.com (see custom domains for org-owned domains).
Also mint a CLIENT-tier key (opl_sdk_…) on the API keys page; the SDK authenticates with it.
② Add the associated-domains entitlement
In Xcode, select the app target, Signing & Capabilities → + Capability → Associated Domains, and add your link domain with the applinks: prefix:
<key>com.apple.developer.associated-domains</key>
<array>
<string>applinks:links.yourdomain.com</string>
</array>
At install time iOS fetches https://links.yourdomain.com/.well-known/apple-app-site-association and checks that it names your app. The OptoLink backend serves that file for you, built from the AppConfig you registered in step ①; you don't host it. Publication through Apple's CDN can lag about 25 minutes after a config change, so a freshly registered app may not verify immediately.
Links tapped before verification succeeds still work: Safari stays on the OptoLink redirect page, which copies the attribution token for the deferred match (see the quickstart).
Using OptoLink's default share domain instead of your own? Same entitlement with applinks:<default-domain-host>; the backend serves an aggregated file there, one entry per org with an iOS config.
③ Add the dependency and initialize
Add the package in Xcode via File → Add Package Dependencies… with the distribution URL below, or declare it in Package.swift:
dependencies: [
.package(url: "https://github.com/Optomatica/optolink-ios-sdk.git", from: "0.1.0"),
],
targets: [
.target(name: "YourApp", dependencies: [
.product(name: "OptoLink", package: "optolink-ios-sdk"),
]),
]
Initialize once at app launch, and wire both ingestion surfaces into handle(url:) — iOS picks the delivery route per launch, so an app needs both wired:
import SwiftUI
import OptoLink
@main
struct ShopApp: App {
init() {
Task {
await OptoLink.initialize(config: OptoLinkConfig(
apiKey: "opl_sdk_…", // CLIENT-tier key from the portal
orgKey: "acme",
baseUrl: URL(string: "https://api.optolink.app")!
))
}
}
var body: some Scene {
WindowGroup { ContentView() }
.onOpenURL { OptoLink.instance().handle(url: $0) }
.onContinueUserActivity(NSUserActivityTypeBrowsingWeb) { activity in
if let url = activity.webpageURL { OptoLink.instance().handle(url: url) }
}
}
}
The key has no env-var fallback; orgKey is the middle segment of your canonical links. Point baseUrl at your deployment — https://api.optolink.app is the intended public default, not live yet.
handle(url:) is safe to call before initialize finishes; an early URL parks and is processed once initialization completes.
The first-launch deferred match reads your clipboard. On iOS 16+ the SDK checks the pasteboard silently first (detectPatterns) and reads only when a link URL is actually there, so installs that didn't come from a click never see a prompt; installs from a click get the system paste dialog once; tap Allow. On iOS 15 the SDK reads directly, and iOS shows its non-blocking paste banner instead. Expected platform behavior. Set clipboardEnabled = false in OptoLinkConfig to skip the clipboard leg.
Verify the wiring by collecting links from a view: the quickstart takes it from here.