Attribution
Attribution API endpoint to match an app install to the link click that drove it, using device signals, fingerprints, or referrers.
Attribution Match
Match a new app install to a previously recorded link click. The match cascade tries strategies in order: referrer, device ID (IDFV), fingerprint, and raw device signals.
This endpoint requires the attribution:write scope, which is granted only on SDK keys. An API key created in the dashboard cannot request that scope, so it is rejected with a 403. See Authentication for the difference between the two key types.
Provide a referrer link ID, a device_id, a pre-computed fingerprint, or raw device signals (accept_language + timezone_offset, with timezone alongside them where the platform can supply it). When raw signals are provided, the server derives the IP address from the request and computes the fingerprint from the IP, the normalized primary language, and the timezone. The SDKs use the raw-signals path: they never send a pre-computed fingerprint or an IP. user_agent and screen dimensions are no longer part of the fingerprint.
timezone is the IANA zone name, for example America/Toronto. SDKs that collect a zone name send it next to timezone_offset, and its presence selects the enriched_tz fingerprint variant. That variant scores higher than the enriched offset variant because the zone name carries far more entropy (roughly 340 zones against 38 offsets) and does not shift at a daylight-saving boundary. Older SDKs send the offset only and stay on enriched. basic covers signals that carry neither.
A probabilistic match is bounded by the link's match window, which defaults to 6 hours and is capped at 24. Past 24 hours nothing is matched. Deterministic matches read stored install records instead, so the window does not apply to them.
is_reinstall marks an install that arrived on a device which had already completed attribution for the same app. A reinstall is a real install: it is attributed again, on every platform, and it counts once in your install numbers. The flag only says which kind of install it was. Send true when a device-level marker that outlives an app delete says the device has been attributed before and the current install has not yet completed its own check. The field is optional, and an absent value is read as false, so SDK versions that predate it keep working unchanged.
A successful response carries match_guaranteed, which is true only for a deterministic match (the referrer or device ID branch). Gate sensitive actions such as automatic sign-in or showing personal data on that field rather than on a match_confidence threshold. A probabilistic match is a best guess from a fingerprint shaped by the network rather than the device, so it can name the wrong user however high the score reads.
/attribution/matchMatch an app install to a link click
Request Body
| Field | Type | Description |
|---|---|---|
fingerprint | string | Pre-computed SHA-256 fingerprint hex string, case-insensitive. Optional; SDKs use the raw-signals path instead. |
platform* | "ios" | "android" | |
fingerprint_version* | "basic" | "enriched" | "enriched_tz" | Which fingerprint the SDK's signals support. `enriched_tz` uses the IANA zone, `enriched` the minute offset, `basic` neither. |
sdk_version* | string | |
device_id | string | IDFV (iOS) or equivalent device identifier. Deterministic match; takes precedence over the fingerprint. |
referrer | string | The WarpLink link ID carried in the Play install referrer as utm_content. Send the parsed link ID, not the raw referrer string. Deterministic match; takes precedence over the fingerprint. |
accept_language | string | Raw device preferred language (e.g. "en-US"). Required for the fingerprint path. The server normalizes it to the primary subtag. |
timezone_offset | integer | Timezone offset in minutes, JS getTimezoneOffset() convention (UTC+2 is -120). Sent alongside `timezone`; used as the fallback when no IANA zone is available. |
timezone | string | IANA timezone name, e.g. `America/Toronto`. Preferred over `timezone_offset`: it carries far more entropy and does not shift at a daylight-saving boundary. Sent by SDK versions that collect a zone name; older SDKs send the offset only. |
app_bundle_id | string | iOS bundle identifier of the calling app. Optional. Without it an install is matched across the whole organization, which is ambiguous once the organization has more than one app. |
app_package_name | string | Android package name of the calling app. Optional. Without it an install is matched across the whole organization, which is ambiguous once the organization has more than one app. |
is_reinstall | boolean | True when this device already completed WarpLink attribution for this app under an earlier install. A reinstall counts as an install and is attributed again on every platform; this only labels it. Optional, and absent means false: SDKs older than the field never send it. |
Responses
200Attribution result
400Validation error
| Field | Type | Description |
|---|---|---|
error* | object |
401Unauthorized
| Field | Type | Description |
|---|---|---|
error* | object |
403Forbidden. The API key is missing the attribution:write scope.
| Field | Type | Description |
|---|---|---|
error* | object |
500Internal error
| Field | Type | Description |
|---|---|---|
error* | object |