POST

Conversion postback

Report a conversion for a Buzz Links session. The server resolves the link from session_id (last qualified click). Do not send link_id.

Endpoint

POST${BASE_URL}/user/conversions/postback

Headers

HeaderRequiredDescription
Content-Typerequiredapplication/json
X-Buzz-KeyrequiredProject API key id for this campaign
X-Buzz-TimestamprequiredUnix seconds. Same ±300s window as in-app webhooks
X-Buzz-SignaturerequiredHMAC over trim(timestamp) + "\n" + sha256hex(canonicalJSON(body))

Request body

FieldTypeDescription
idempotency_keystringNon-empty. Unique per campaign for deduplication — safe for retries
session_idstringNon-empty. Must match an attributed Buzz Links session
campaign_idintegerMust match the API key's campaign and the attributed session's campaign
conversion_codestringMax 64 chars. Must match an active conversion type (and destination rules where applicable)
metadataobjectoptional Serialized JSON up to 8 KB
Capture session_id from the Buzz Link flow on the client and send it from your backend with the postback. If the session is unknown or never had a qualified click, the conversion is unattributed.

Complete example

conversion-postback.js
const body = {
  idempotency_key: 'order_' + Date.now(),
  session_id: SESSION_ID,
  campaign_id: CAMPAIGN_ID,
  conversion_code: 'signup_complete',
  metadata: { plan: 'pro' },
};

const ts = Math.floor(Date.now() / 1000);
const signature = signRequest(PROJECT_SECRET, ts, body);

const res = await fetch(`${BASE_URL}/user/conversions/postback`, {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'X-Buzz-Key': PROJECT_KEY_ID,       // Note: X-Buzz-Key, not X-Buzz-Key-Id
    'X-Buzz-Timestamp': String(ts),
    'X-Buzz-Signature': signature,
  },
  body: JSON.stringify(body),
});

Success response

200 OK
{
  "status": 200,
  "message": "Success !",
  "data": {
    "success": true,
    "received": true,
    "message": "Conversion accepted; processing in background. Use idempotency_key for idempotency.",
    "conversion_event_id": null
  }
}

Responses

200Accepted. data.received === true. Qualification and points decided asynchronously.
400Validation failure — missing fields, bad campaign_id, or metadata over 8 KB.
403Postback disabled, invalid/revoked key, signature failure, timestamp window exceeded, or campaign mismatch.
429Rate limit exceeded (60 req/min per key).
Use a stable idempotency_key per business event so retries never double-count.
← Previous
In-app webhooks
Next →
Buzzdrop tasks