Deep Links API
The deep links API lets SDKs resolve routes, claim deferred deep links after app install, and retrieve basic app information. These endpoints are domain-resolved (no API key required) and use the /api/ path prefix.
Resolve a link
Section titled “Resolve a link”Turn a link into the route and token it means.
POST /api/pathAuth: None (hostname-resolved)
Why an app needs this
Section titled “Why an app needs this”An app receives the URL that was tapped, exactly as written. That is fine while
the URL is readable: /merchant/abc123 says “merchant” and the app can route
it. A short link is the same route written as a code, /imbwmum/abc123, and
nothing in it says “merchant”, nor can the code be worked out on the device.
An app parsing the path itself sees a first segment it has never heard of and does nothing, so the link opens the app and then appears to fail: no error, no screen, no clue. Short links are what the dashboard offers for sharing and what a QR code carries, so this is not a rare path.
Ask here instead. A readable URL comes back unchanged, so an app can resolve
everything rather than guessing which kind it has. Every SDK wraps this as
links.resolve(url).
Request body:
Send either a path, which is what an app holds, or a prefix and token.
{ "path": "/imbwmum/abc123"}| Field | Required | Description |
|---|---|---|
path | A path or a whole URL, as the app received it. Resolves short codes and prefixes that place their token | |
prefix | A route prefix or short code, if you are not sending a path | |
token | The token, when sending a prefix |
Response 200:
{ "route": { "prefix": "merchant/{token}/reviews", "name": "Merchant Reviews", "template": "none", "link_type": "dynamic" }, "token": "abc123", "deep_link_path": "/merchant/abc123/reviews", "appspace": { "name": "My App", "slug": "my-app" }}token is what the link carried, which an app cannot work out for itself from a
short link. deep_link_path is the canonical path, with the token wherever the
route’s prefix puts it, which is what to route on.
Errors:
| Status | Error |
|---|---|
400 | Provide a path, or a prefix and token |
404 | Route not found, or No app configured for this domain |
404 | Route not found |
Claim deferred link by token
Section titled “Claim deferred link by token”After a user installs your app via a deep link, the SDK calls this endpoint to retrieve the original link destination. On Android, the token comes from the Play Store install referrer string, where it is stored as the tolk_token parameter (e.g. tolk_token=abc123).
GET /api/deferred/claim?token=abc123Auth: None (hostname-resolved)
Query parameters:
| Param | Required | Description |
|---|---|---|
token | Yes | The referrer token from the Play Store install |
user_id | No | Optional user ID for analytics attribution |
Response 200:
{ "deep_link_path": "/merchant/abc123", "appspace_id": "64f0a1b2c3d4e5f60718"}If the claimed path is a referral link (/ref/<code>), the response includes referral data:
{ "deep_link_path": "/ref/ABC123", "appspace_id": "64f0a1b2c3d4e5f60718", "referrer_id": "user_456", "referral_code": "ABC123"}Errors:
| Status | Error |
|---|---|
400 | Missing token parameter |
404 | No matching deferred link found |
404 | This deferred link was already claimed... |
404 | This deferred link has expired... |
All three failures return 404, so an SDK that maps 404 to an empty result keeps working
unchanged. Only the message narrows, which is enough to tell the common cases apart when you
are debugging.
Send device signals
Section titled “Send device signals”Update an existing deferred link record with client-side device signals. This improves fingerprint matching accuracy for iOS, where the Play Store referrer token is not available.
POST /api/deferred/signalsAuth: None (hostname-resolved)
Request body:
{ "token": "abc123", "timezone": "America/New_York", "language": "en-US", "screen_width": 390, "screen_height": 844}| Field | Required | Description |
|---|---|---|
token | Yes | The deferred link token |
timezone | No | IANA timezone name |
language | No | BCP 47 language tag |
screen_width | No | Screen width in logical pixels |
screen_height | No | Screen height in logical pixels |
device_pixel_ratio | No | devicePixelRatio on web, UIScreen.scale on iOS, display density on Android |
os_version | No | Compared on the major component only |
Response 200:
{ "updated": true }Claim deferred link by signals
Section titled “Claim deferred link by signals”Claim a deferred deep link using multi-signal fingerprint matching. Used by the iOS SDK, which cannot read the Play Store referrer token.
POST /api/deferred/claim-by-signalsAuth: None (hostname-resolved)
Request body:
Signal matching only considers clicks from the last 2 hours. It requires at least two of the signals below to agree, and those must be more than half of the ones both sides supplied. Clicks older than 15 minutes must agree on everything comparable. Country and IP geolocation are not part of the score.
{ "appspace_id": "64f0a1b2c3d4e5f60718", "timezone": "America/New_York", "language": "en-US", "screen_width": 390, "screen_height": 844}| Field | Required | Description |
|---|---|---|
appspace_id | Yes | Your Appspace ID, copied from the dashboard under Settings. Not your subdomain or slug. |
timezone | No | IANA timezone name |
language | No | BCP 47 language tag |
screen_width | No | Screen width in logical pixels |
screen_height | No | Screen height in logical pixels |
Response 200:
{ "deep_link_path": "/merchant/abc123", "appspace_id": "64f0a1b2c3d4e5f60718"}Referral data is included when applicable (same as token-based claiming).
Errors:
| Status | Error |
|---|---|
400 | Missing appspace_id |
403 | appspace_id does not match this domain (the ID belongs to a different Appspace than the host you called) |
403 | Unknown appspace_id... (the ID does not name any Appspace, usually a subdomain or slug passed by mistake) |
404 | No matching deferred link found (the ID is valid, but no click is waiting for this device) |
Get app info
Section titled “Get app info”Retrieve basic information about the app associated with the current domain. Used by SDKs to get store URLs without requiring an API key.
GET /api/app/infoAuth: None (hostname-resolved)
Response 200:
{ "name": "My App", "slug": "my-app", "ios_app_store_url": "https://apps.apple.com/...", "android_play_store_url": "https://play.google.com/...", "web_fallback_url": "https://myapp.com"}Errors:
| Status | Error |
|---|---|
404 | No app configured for this domain |
Get banner config
Section titled “Get banner config”Retrieve smart banner configuration for the banner.js script. This is the endpoint that the website smart banner script calls automatically.
GET /api/banner/configAuth: None (hostname-resolved)
Query parameters:
| Param | Required | Description |
|---|---|---|
user_id | No | Enables segment-targeted banner filtering |
Response 200:
{ "enabled": true, "app_name": "My App", "app_icon": "https://...", "install_url": "/install", "banners": [ { "id": "banner_id", "label": "summer-promo", "title": "Download the app", "body": "Get 20% off your first order", "action_url": "https://example.com/download", "cta_text": "Get the App", "background_color": "#ffffff", "text_color": "#000000", "position": "top", "dismiss_days": 7, "priority": 10 } ]}If the Appspace is not found or banners fail to load: { "enabled": false, "banners": [] }.