Skip to content
GET or POST/api/postback/{program}/{token} You call us

You call DataFlair. You write a client for this API. DataFlair does not call your server.

Postback contract ​

A postback tells DataFlair Stats that one player did something: registered, made a first deposit, or made another deposit. You send one request for each event, from your server. DataFlair records it against the affiliate and the program.

Endpoint ​

text
GET or POST https://{stats-host}/api/postback/{program}/{token}

Copy the full URL from the Stats app: open the program, go to Integrations, and find the Postback endpoint card. The card also shows the masked token and has the Generate token and Regenerate token buttons.

Both methods work. A POST sends a JSON body. A GET sends the same fields as query parameters, which suits operators that fire a URL pixel. DataFlair merges the query string and the body, so the field names are the same either way.

Send Accept: application/json on every request so errors come back as JSON.

Authentication ​

The {token} in the URL authenticates the request. Each program has its own token. It is 64 hexadecimal characters and is separate from the API key DataFlair uses to pull your reports.

  • Treat the full URL as a secret. Send postbacks from your server. Do not put the URL in client-side code.
  • If the token is wrong or missing, DataFlair answers 401.
  • Regenerate token in the app makes the old token stop working at once. Update your integration with the new URL.

Signed requests (optional) ​

A POST can carry a signature in place of the token in the URL. Use the URL without the token segment, /api/postback/{program}, and add two headers:

HeaderValue
X-Postback-TimestampThe current Unix time in seconds, as digits.
X-Postback-SignatureThe lowercase hexadecimal HMAC-SHA256 of {timestamp}.{raw request body}, with your postback token as the key.

DataFlair rejects a timestamp more than 300 seconds away from its own clock. Signing is for POST only. A GET postback uses the token in the URL.

What you send ​

bash
curl -X POST "https://{stats-host}/api/postback/12/YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{
    "affiliate_id": "AFF-00042",
    "conversion_type": "ftd",
    "postback_id": "pb_001",
    "amount": 25.00,
    "status": "approved"
  }'
bash
curl -G "https://{stats-host}/api/postback/12/YOUR_TOKEN" \
  -H "Accept: application/json" \
  --data-urlencode 'affiliate_id=AFF-00042' \
  --data-urlencode 'conversion_type=ftd' \
  --data-urlencode 'postback_id=pb_001' \
  --data-urlencode 'amount=25.00' \
  --data-urlencode 'status=approved'

The request builder fills in these commands for you. It does not send them.

Fields ​

FieldTypeRequiredMeaning
affiliate_idstringyesThe DataFlair affiliate ID, for example AFF-00042. The affiliate must be approved for the program. aff_id is accepted in its place when the program has no field mapping.
conversion_typestringyesOne of registration, ftd, deposit. See Conversion types.
postback_idstringyesYour unique id for this event. Up to 255 characters. See Idempotency.
amountnumbernoThe amount, zero or more. Defaults to 0.
currencystringnoA currency code, up to 8 characters. DataFlair stores it as you send it.
player_idstringnoYour internal player reference. Up to 255 characters.
occurred_atdatetimenoWhen the event happened in your system. DataFlair reports the conversion on this date when it is present. Without it, DataFlair uses the time it received the request.
sub_idstringnoThe sub_id you received on the landing page. Up to 100 characters. Letters, digits, _ and - only. See Tracking links.
tracking_idstringnoThe tracking_id you received on the landing page, in the form TL- followed by letters or digits.
statusstringnoOne of approved, pending, rejected, hold, adjusted. Defaults to approved. See Status values.
kyc_statusstringnoThe player's KYC state: pending, verified or rejected.
kyc_verifiedbooleannoA shorter form of kyc_status. true means verified and false means pending. kyc_status wins when you send both.
df_click_idstringnoA DataFlair click id in the form dfc_ followed by 16 hexadecimal characters. Send it back as sub_id instead.

DataFlair ignores any other field. It records the source IP address of the request itself.

What you get back ​

A new conversion:

json
{
  "success": true,
  "conversion_id": 42,
  "commission_id": 17
}

commission_id is null when no commission record was created.

A repeat of a postback_id DataFlair already has:

json
{
  "success": true,
  "duplicate": true,
  "conversion_id": 42,
  "commission_id": 17,
  "message": "Postback already processed (idempotent)."
}

Errors ​

Every error body has "success": false and an error code. A message describes it.

StatuserrorWhat caused itWhat to do
401unauthorizedThe token is wrong, or the URL has no token and no valid signature. The message says which: Invalid postback token., No postback token in URL. Expected: /api/postback/{program}/{token}, or Invalid or expired postback signature.Check the URL. Check that the token was not regenerated.
404program_not_foundThe program does not exist or is not active.Check the program id. Ask the operator to activate the program.
422validation_errorA field is missing or invalid. The errors object lists each field.Fix the fields named in errors.
422affiliate_not_foundThe affiliate is not approved for this program.Send the affiliate_id you received on the landing page.
422tracking_link_not_foundThe tracking_id is not valid for this program or affiliate.Send the tracking_id you received, or leave it out.
429noneYou sent more than 60 requests in one second with the same token. The response has a Retry-After header.Wait, then retry with the same postback_id.
429noneThe same postback_id arrived twice at the same moment. The message is Concurrent delivery of the same postback_id; retry shortly.Retry with the same postback_id.
5xxnoneA server error.Retry with the same postback_id.

A validation_error looks like this:

json
{
  "success": false,
  "error": "validation_error",
  "message": "Request validation failed.",
  "errors": {
    "conversion_type": ["The selected conversion type is invalid."]
  }
}

Conversion types ​

TypeMeaning
registrationA player account was created.
ftdThe player's first deposit.
depositA later deposit.

Postbacks carry these acquisition events only. DataFlair does not accept cashout in a postback. Withdrawals and revenue reach DataFlair through the Operator Reporting API, which DataFlair pulls.

Timeouts and retries ​

The rate limit is 60 requests per second for each token. When the URL has no token, the limit applies to each source IP address.

Retry a 5xx, a 429 and a timeout with the same postback_id. Do not retry a 401, a 404 or a 422 until you have fixed the cause. The Idempotency page explains why a retry is safe.

Test this ​

Check the endpoint, fire a test postback and replay a logged one from the Stats app. See Testing postbacks.

Docs version 1.0.1