Deep Linking
Create Links
Create deep links with per-platform destinations and metadata for rich social previews.
Create a link
The CLI walks you through link creation interactively, or you can pass flags directly:
# Interactive — prompts for each field
rift links create
# Non-interactive — pass flags directly
rift links create \
--web-url https://example.com/promo/summer-sale \
--ios-deep-link myapp://promo/summer-sale \
--android-deep-link myapp://promo/summer-sale \
--custom-id summer-sale \
--preview-title "Summer Sale — 50% Off" \
--preview-description "Limited time offer on all products" \
--preview-image-url https://example.com/promo-banner.jpgThe CLI outputs the link ID and URL, and suggests rift links test to preview how it resolves across platforms:
rift links test summer-salesummer-sale) require a verified custom domain. They are unique per tenant — different tenants can use the same slug on their own domains (e.g. go.acme.com/summer-sale and go.brand.com/summer-sale). Links with custom IDs resolve via your custom domain, not the primary riftl.ink/r/ path.If you omit custom_id, Rift auto-generates a short ID (e.g. A1B2C3D4). Auto-generated links work for all tenants and resolve via riftl.ink/r/A1B2C3D4 — no custom domain required.
How resolution works
When a user clicks the link, Rift detects their platform and serves a smart landing page that:
- iOS — attempts to open the deep link, falls back to the App Store
- Android — attempts to open the deep link, falls back to the Play Store
- Desktop — redirects to the web URL
The landing page includes your app branding (from app registration) and OG tags from social_previewfor rich social previews.
Download QR codes
QR codes are generated from the link's canonical Rift URL and support Dub-style styling parameters.
# CLI
rift links qr summer-sale \
--format png \
--output summer-sale.png \
--size 600 \
--level H \
--fg-color '#111827' \
--bg-color '#ffffff' \
--logo https://example.com/logo.png
# HTTP
curl -L "https://api.riftl.ink/v1/links/summer-sale/qr.png?size=600&level=H&fgColor=%23111827&bgColor=%23ffffff&logo=https%3A%2F%2Fexample.com%2Flogo.png" \
-H "Authorization: Bearer rl_live_YOUR_KEY" \
-o summer-sale.pngUse qr.svg instead of qr.png for SVG output. Supported options: logo, size, level, fgColor,bgColor, hideLogo, margin,dotType, cornerSquareType, cornerDotType,shape, dotColor, cornerSquareColor, and cornerDotColor.
JSON resolution for agents
Agents sending Accept: application/json receive all destinations, social preview fields, and metadata as JSON. Use your custom domain for custom IDs:
# Custom ID via custom domain
curl https://go.yourcompany.com/summer-sale \
-H "Accept: application/json"
# Auto-generated ID via primary domain
curl https://api.riftl.ink/r/A1B2C3D4 \
-H "Accept: application/json"
{
"link_id": "summer-sale",
"ios_deep_link": "myapp://promo/summer-sale",
"android_deep_link": "myapp://promo/summer-sale",
"web_url": "https://example.com/promo/summer-sale",
"ios_store_url": "https://apps.apple.com/app/id123456789",
"android_store_url": "https://play.google.com/store/apps/details?id=com.example.myapp",
"social_preview": {
"title": "Summer Sale — 50% Off",
"description": "Limited time offer on all products",
"image_url": "https://example.com/promo-banner.jpg"
},
"metadata": { "campaign": "summer-sale" },
"agent_context": {
"action": "purchase",
"cta": "Get 50% Off",
"description": "Summer clearance sale on all products with free shipping"
},
"_rift_meta": {
"context": "This is a Rift deep link...",
"source": "tenant_asserted",
"status": "active",
"tenant_domain": "go.yourcompany.com",
"tenant_verified": true
}
}Handle incoming links
iOS — SceneDelegate or AppDelegate
// SceneDelegate.swift
func scene(_ scene: UIScene,
continue userActivity: NSUserActivity) {
guard userActivity.activityType ==
NSUserActivityTypeBrowsingWeb,
let url = userActivity.webpageURL else { return }
let linkId = url.path
.trimmingCharacters(in: CharacterSet(charactersIn: "/"))
handleDeepLink(linkId: linkId)
}Android — Intent handling
// MainActivity.kt
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
intent?.data?.let { uri ->
val linkId = uri.path?.trimStart('/')
if (linkId != null) handleDeepLink(linkId)
}
}