WarpLink
Trust and reliability

SDK Data Flow

For SDK 1.1.0: the fields each SDK sends on validate, resolve, and attribution match, what the server stores, redacted payloads, and URL redaction advice.

This guide lists every request the WarpLink SDKs make, the fields in each request, and what we store from it. It is written for SDK 1.1.0 on iOS, Android, React Native, and Flutter. React Native and Flutter call the native SDKs, so they send the same fields. A later SDK release can change a field. When it does, this page changes with it.

The SDK reads no advertising identifier (no IDFA and no Android advertising ID). It sends requests only to the API address in its apiEndpoint option, which defaults to https://api.warplink.app/v1. Retention periods are in the retention table on the privacy page.

The three requests

Every request carries Authorization: Bearer <SDK key> and a User-Agent of the form WarpLink-iOS/1.1.0 or WarpLink-Android/1.1.0. The server also sees the request's source IP address and the standard connection data every web request carries.

RequestWhenPurpose
GET /v1/sdk/validateAt configure(), unless a recent successful result is cachedCheck the key and fetch your verified link domains
GET /v1/links/resolve/{slug}When a link is tappedTurn the tapped link into its destination and deep link
POST /v1/attribution/matchOnce at first launch, and again on a later launch if the first attempt got no definitive answerMatch the install to the link that led to it

Validate

The request has no body and no query. The response carries three fields.

We store nothing from this request except the key's last-used time. Rate limiting and request logs see it as they see any other request.

Resolve

The SDK sends the slug in the path, the link's host in domain, and the query string of the tapped URL in params. It also sends a random identifier for the tap in a header. The identifier is created for each tap, repeated on every retry of that tap, and not tied to a person or a device.

A resolve from an SDK key with an SDK user agent records one click. The click record holds:

FieldValue
link_id, org_id, clicked_atThe link, its organization, and the time
ip_hashA keyed hash of the source IP address. The address itself is not stored.
country, region, cityApproximate location, derived from the IP address by the edge network
device_type, osmobile, and iOS or Android from the SDK user agent
sourceapp_open
Click identifierThe tap identifier, so the retries of one tap count once

The click record has no referrer, browser, or UTM values, and the params string is not stored in it. The params string is part of the request URL, so treat it as data that reaches our servers.

Attribution match

The SDK sends the device signals it needs to match an install to a tap. These are all of the fields.

iOS:

Android:

FieldWhat it is
accept_languageThe device's preferred language
timezone_offset, timezoneThe offset in minutes and the IANA zone name
fingerprint_versionWhich of the above the SDK could send: basic, enriched, or enriched_tz
device_idiOS only: the vendor identifier (IDFV). It is shared by every app from one developer account on a device. Android sends none.
referrerAndroid only: the link identifier from the Play Install Referrer, when one exists
app_bundle_id, app_package_nameWhich of your apps is asking
is_reinstallWhether this device had run the app before. On iOS it comes from a Keychain marker.
sdk_version, platformThe SDK release and the operating system

Like resolve, the request carries the X-WarpLink-Tap-Id header: a random identifier for one attribution attempt, repeated on its retries. The server stores it on the install record, so a retried request returns the same install, unless the request is a reinstall, in which case a new install can be created.

The SDK does not send the IP address, because it cannot know its own public address. The server reads the address from the request.

What we store from a match

RecordFields
InstallLink, organization, and app. Platform. device_fingerprint (a keyed hash, see below). match_type, match_confidence. Install and attribution times. device_id (the IDFV on iOS). The matched click identifier, the tap identifier, and is_reinstall. The routing the match answered with: destination, deep link, and custom parameters.
AttemptOrganization, app, platform, SDK version, which method ran, fingerprint_version, whether it matched, a failure reason, the number of candidate clicks, a coarse class of the IP address (cgnat, ipv6, or ipv4), and is_reinstall. An attempt record holds no IP address, no device identifier, and no fingerprint.
Deferred entryWritten at click time, not by the SDK: the fingerprint key, link, destination, deep link, custom parameters, and the entry's expiry. It lives only for the link's match window, 6 hours by default and 24 at most.

The IP address is not stored in install, attempt, or click records.

The hashing key

The IP hash in a click and the fingerprint in an install are HMAC-SHA256 values. The key is a single server-side secret. The SDK never holds it, and no request or response carries it. The same key is used for all organizations, so the same IP address produces the same hash everywhere in our systems. A hash is a pseudonym. Anyone who knows the key and a candidate address can recompute it, so we treat hashes as personal data and keep them under the retention rules in the privacy page.

The fingerprint is built from the source IP address, the normalized language, and the time zone. It describes a network at a moment, not a person.

The tapped URL is data that moves through several places. Its host and slug appear in the resolve path. Its query string goes to us in params. UTM values in the URL are stored in click records. The URL also appears in message logs, browser history, and referrer headers.

  • Do not put an email address, phone number, user ID, name, or token in a link's slug, query string, UTM values, or destination.
  • Use opaque identifiers that mean nothing outside your own systems, and look up the person on your server.
  • Do not use custom parameters for secrets. They reach the app through the SDK and are stored with the install.
  • A referral or invite link should carry a random code, not an account identifier.
  • If you suspect that personal data went into a link, edit the link and ask us to delete the affected records at privacy@warplink.app.

What stays on the device

The SDK keeps its own state on the device: the cached attribution result, completion markers, the cached link domains, and the time of the last key check. On iOS it also keeps a Keychain marker for is_reinstall. The iOS SDK ships a privacy manifest that declares the vendor identifier and is_reinstall, with tracking set to false. Use these lists when you complete your app store privacy answers.

Related pages: Abuse protection and threat model, Attribution accuracy, and the privacy policy.

On this page