HTTP API

The SDKs make two small JSON requests. If no SDK fits your stack, you can make them yourself. This page is the full contract.

Prefer an SDK where you can. Writing your own client means you own the hard parts: getting Apple's token on the first launch, sending it within its 24 hours, keeping it through crashes and network loss, and retrying without counting an install twice.


Basics

Base URLhttps://ingest.fload.com
AuthYour write key in the X-Fload-Write-Key header
BodyJSON, with Content-Type: application/json
Calls fromYour app or your own server. Browsers aren't supported: the host answers no CORS requests

Report an install

POST /attribution/v1/installs, once per install, on its first launch.

iOS

Get Apple's token with AAAttribution.attributionToken() on the phone, then send it:

bash
curl -X POST https://ingest.fload.com/attribution/v1/installs \
  -H "Content-Type: application/json" \
  -H "X-Fload-Write-Key: fload_pk_…" \
  -d '{
    "requestId": "b7f3c2a8-5d1e-4c6b-9a0f-2e8d4b1c7a65",
    "installReference": "4e9a1f60-2c7b-4d3e-8f5a-91b0c6d2e7f8",
    "platform": "ios",
    "appId": "com.northwind.pocketbudget",
    "appVersion": "2.3.0",
    "appBuild": "231",
    "osVersion": "18.1",
    "deviceModel": "iPhone16,2",
    "locale": "en-GB",
    "sdk": { "name": "pocketbudget-custom", "version": "1.0.0" },
    "firstLaunchAt": "2026-11-06T09:12:44Z",
    "appleAds": {
      "status": "token",
      "token": "<the base64 token from attributionToken()>",
      "tokenCreatedAt": "2026-11-06T09:12:45Z"
    }
  }'

Fload swaps the token with Apple on its server, so your app never calls Apple's attribution API.

Android

Read the Play Install Referrer with Google's Install Referrer library, then send what it returns. Convert Google's seconds to ISO 8601 times:

bash
curl -X POST https://ingest.fload.com/attribution/v1/installs \
  -H "Content-Type: application/json" \
  -H "X-Fload-Write-Key: fload_pk_…" \
  -d '{
    "requestId": "c1d8e4f2-7a3b-4e9c-b5d0-6f2a8c1e3b47",
    "installReference": "9b2e7c41-5f8a-4d6e-a3c1-0d7f2b9e4a58",
    "platform": "android",
    "appId": "com.northwind.pocketbudget",
    "appVersion": "2.3.0",
    "appBuild": "231",
    "osVersion": "15",
    "deviceModel": "Google Pixel 8",
    "locale": "en-GB",
    "sdk": { "name": "pocketbudget-custom", "version": "1.0.0" },
    "firstLaunchAt": "2026-11-06T09:12:44Z",
    "playReferrer": {
      "status": "ok",
      "referrer": "utm_source=google-play&utm_medium=organic",
      "referrerClickAt": "2026-11-06T09:10:02Z",
      "installBeginAt": "2026-11-06T09:11:30Z",
      "googlePlayInstant": false
    }
  }'

Install fields

FieldRequiredWhat it is
requestIdYesAn id you make for this request. Send the same one on every retry, so Fload counts the install once
installReferenceYesA random id you make once per install and keep. 8 to 128 characters: letters, digits and . _ : -
platformYesios or android
appIdYesBundle id or package name
sdkYesname and version of your client, up to 64 characters each
firstLaunchAtYesThe phone's time of the first launch, ISO 8601
appleAdsiOS onlySee below. iOS sends this and never playReferrer
playReferrerAndroid onlySee below. Android sends this and never appleAds
appVersion, appBuild, osVersion, deviceModel, localeNoUp to 64 characters each
appUserIdNoYour app user id, if you have it before the first send. Up to 256 characters

appleAds

FieldWhat it is
statustoken when you have one. token_error when Apple's call failed, unsupported_os below iOS 14.3, token_expired when the token is over 24 hours old and you're sending the install without it
tokenApple's base64 token. Send it only with status: "token", and always with it
tokenCreatedAtWhen the phone got the token, ISO 8601

playReferrer

FieldWhat it is
statusok, unavailable (Play's service didn't answer, or the app isn't from Play), not_supported (no Play Store) or error
referrerThe raw referrer string, as Google returns it
referrerClickAt, installBeginAtGoogle's click and install-begin times
referrerClickServerAt, installBeginServerAtThe same times from Google's server, when present
installVersionThe app version first installed, when present
googlePlayInstantWhether the user tried the instant app

POST /attribution/v1/identify, whenever your app user id becomes known or changes, for example after login:

bash
curl -X POST https://ingest.fload.com/attribution/v1/identify \
  -H "Content-Type: application/json" \
  -H "X-Fload-Write-Key: fload_pk_…" \
  -d '{
    "requestId": "e5a9b3c7-1d4f-4a8e-9c2b-7f0d3e6a1b84",
    "installReference": "4e9a1f60-2c7b-4d3e-8f5a-91b0c6d2e7f8",
    "platform": "ios",
    "appUserId": "user_123"
  }'

Pass RevenueCat's app user id, so Fload can match the install to revenue. Fload keeps every id an install has had. An identify that arrives before its install is kept and linked when the install arrives.


Responses

StatusMeaningWhat to do
202Accepted. Also returned for an exact repeatDelete the request from your queue
400The body doesn't match the contractDon't retry. Fix the request
401Fload doesn't know this keyKeep the request. Check the key, and retry later
410The key was revokedStop sending with this key for good
413The body is too largeDon't retry
429Too many requestsRetry after the seconds in Retry-After
5xxFload had a problemRetry with backoff

A 202 body is { "accepted": true }. Fload ignores fields it doesn't know, so adding your own never breaks a request.

Retries

  • Back off exponentially with jitter. The SDKs start at 2 seconds and double up to 6 hours.
  • Repeat the same requestId on every retry.
  • Keep the request on disk until you get a 202, so a crash or a closed app doesn't lose it.
  • Apple's token lives 24 hours. If you can't send it in time, send the install with status: "token_expired" and no token. Fload still counts it.