Step-by-step guide to integrate the WarpLink iOS SDK into your app. You'll go from zero to working deep links in under 30 minutes.
- iOS 15+, Swift 5.9+, Xcode 15+
- A physical iOS device (Universal Links do not work on the iOS Simulator)
Sign up at warplink.app. The free tier includes 10,000 clicks per month.
- In the WarpLink dashboard, go to Settings > Apps
- Click Add App and select iOS
- Fill in your app details:
- Bundle ID (e.g.,
com.yourcompany.yourapp) - Team ID (found in Apple Developer portal under Membership)
- App Store URL (or leave blank during development)
- Bundle ID (e.g.,
- Save the app. WarpLink generates the Apple App Site Association (AASA) file automatically.
- Go to Settings > API Keys in the dashboard
- Click Create API Key
- Copy your key (format:
wl_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxx) - Store it securely — you'll use this to configure the SDK
- In Xcode, go to File > Add Package Dependencies...
- Enter:
https://github.com/WarpLinkApp/warplink-ios-sdk - Select Up to Next Major Version and click Add Package
dependencies: [
.package(url: "https://github.com/WarpLinkApp/warplink-ios-sdk", from: "1.0.1")
]- Select your app target
- Go to Signing & Capabilities
- Click + Capability and add Associated Domains
- Add the domain:
applinks:aplnk.to
- Go to developer.apple.com > Certificates, Identifiers & Profiles
- Select your App ID
- Enable Associated Domains capability
- Regenerate your provisioning profile if needed
Note: WarpLink currently supports the
aplnk.todomain. Custom domains will be supported in a future SDK update.
Initialize the SDK as early as possible in your app lifecycle.
SwiftUI:
import SwiftUI
import WarpLink
@main
struct MyApp: App {
init() {
WarpLink.configure(apiKey: "wl_live_your_api_key_here_abcdefgh")
}
var body: some Scene {
WindowGroup {
ContentView()
}
}
}UIKit:
import UIKit
import WarpLink
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
WarpLink.configure(apiKey: "wl_live_your_api_key_here_abcdefgh")
return true
}
}You can also pass options for debug logging or a custom match window:
WarpLink.configure(
apiKey: "wl_live_your_api_key_here_abcdefgh",
options: WarpLinkOptions(debugLogging: true, matchWindowHours: 48)
)When a user taps a WarpLink URL and your app is installed, iOS opens your app with the URL. Handle it to resolve the deep link.
SwiftUI:
@main
struct MyApp: App {
init() {
WarpLink.configure(apiKey: "wl_live_your_api_key_here_abcdefgh")
}
var body: some Scene {
WindowGroup {
ContentView()
.onOpenURL { url in
WarpLink.handleDeepLink(url) { result in
switch result {
case .success(let deepLink):
// Route based on destination or deep link URL
navigateTo(deepLink.destination)
case .failure(let error):
print("Error: \(error.localizedDescription)")
}
}
}
}
}
}UIKit (SceneDelegate):
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
func scene(_ scene: UIScene, continue userActivity: NSUserActivity) {
guard let url = userActivity.webpageURL else { return }
WarpLink.handleDeepLink(url) { result in
switch result {
case .success(let deepLink):
navigateTo(deepLink.destination)
case .failure(let error):
print("Error: \(error.localizedDescription)")
}
}
}
}The completion handler is always called on the main thread, so you can safely update UI from it.
Deferred deep links work when a user clicks a WarpLink URL, installs your app from the App Store, and opens it for the first time. The SDK matches the install back to the original click.
Call checkDeferredDeepLink once, early in your app's first-launch flow:
WarpLink.checkDeferredDeepLink { result in
switch result {
case .success(let deepLink):
if let deepLink = deepLink {
// User arrived via a WarpLink — route to intended content
navigateTo(deepLink.destination)
} else {
// No deferred deep link — show default onboarding
}
case .failure(let error):
print("Deferred deep link error: \(error.localizedDescription)")
}
}The SDK automatically detects first launch and caches the result. Subsequent calls return the cached result without a network request.
See Deferred Deep Links for details on confidence scores and edge cases.
- Go to Links in the WarpLink dashboard
- Click Create Link
- Set the destination URL (e.g.,
https://yourapp.com/product/123) - Optionally set an iOS deep link URL (e.g.,
myapp://product/123) - Copy the generated short link (e.g.,
https://aplnk.to/abc123)
curl -X POST https://api.warplink.app/v1/links \
-H "Authorization: Bearer wl_live_your_api_key_here_abcdefgh" \
-H "Content-Type: application/json" \
-d '{
"destination_url": "https://yourapp.com/product/123",
"ios_url": "myapp://product/123"
}'Universal Links do not work on the iOS Simulator. You must test on a physical device.
- Build and run your app on a physical iOS device
- Open the test link in Safari on the device (or send it via Messages/Notes)
- Tap the link — your app should open and the deep link callback should fire
- Check the Xcode console for
[WarpLink]log messages if you enableddebugLogging
- Delete your app from the test device
- Open the test link in Safari — you'll be redirected to the App Store (or a fallback URL during development)
- Install the app via Xcode (or TestFlight)
- Launch the app —
checkDeferredDeepLinkshould return the matched deep link
- Enable debug logging:
WarpLinkOptions(debugLogging: true) - Check Xcode console for
[WarpLink]prefixed messages - Verify AASA is served correctly:
curl https://aplnk.to/.well-known/apple-app-site-association - See Troubleshooting for common issues
- API Reference — full documentation of all public types and methods
- Error Handling — how to handle every error case
- Attribution — understanding confidence scores and match types