Affiliate Postbacks

Server to server postbacks on recorded, approved and reversed conversions, with macro substitution and a retry queue.

Affiliate Postbacks

Serious affiliates run their own tracker, and they need to know what happened on your side without logging in to look. A postback is a server-to-server call from Offer Capsule to a URL the affiliate supplies, fired when something happens to one of their conversions. Their tracker learns about the conversion within seconds, with the click id, the payout, the status, the order details, and their own sub ids filled in - which means their optimisation runs on your data instead of their guesses.

Global and per-offer URLs

An affiliate can register a global postback URL that fires for every offer they run, or a URL scoped to one specific offer, or both. Global is the sane default for an affiliate with one tracker; per-offer matters when an affiliate is running different offers through different systems, or when one advertiser relationship needs its own endpoint. Each postback is independently active or inactive, so one can be switched off without touching the others.

The three events

Each postback registration names the event that fires it:

  • Conversion Recorded - fires the moment the conversion lands, while it is still Pending. Fastest signal, not yet a promise of payment.
  • Conversion Approved - fires when the conversion is approved and funds. This is the one most affiliates want, because it is the event that means money.
  • Conversion Reversed - fires when an approved conversion is clawed back for a chargeback or a scrub, so the affiliate's own numbers can be corrected rather than staying permanently wrong.

An affiliate can register different URLs for different events, which is how a tracker that wants a pending ping and a separate confirmed ping is wired up.

Macros

The URL is a template. Anything in braces is substituted at fire time:

  • {click_id} - the click the conversion attributes to.
  • {offer_id} - the offer.
  • {order_id} and {order_amount} - the advertiser's transaction reference and value.
  • {payout} and {revenue} - the frozen amounts on the conversion.
  • {status} - the lifecycle status as text.
  • {sub1} through {subN} - every captured sub id by position.
  • {segment:Name} - the same values addressed by segment name.

Two rules keep this safe. Every substituted value is URL-encoded, so an order id with a space or an ampersand in it cannot break the affiliate's query string. And a token that does not resolve collapses to empty rather than being forwarded as a literal brace, so a typo in a template never sends an affiliate's tracker a value that looks like a macro. See sub id tracking for where the sub id values come from.

Delivery that survives a bad day

Postbacks are queued rather than fired inline, and drained by a background sender that never runs on the tracker hot path. Each queued postback records its attempt count, the last HTTP response code, and the last error. A call that fails is retried on an exponential backoff, so a tracker that is briefly down gets the notification when it comes back instead of losing it. Attempts are capped, and a postback that exhausts them is moved to a dead status with its last error attached, rather than retrying forever or disappearing. One bad endpoint never blocks the rest of the batch, and a URL that is not a valid HTTP or HTTPS address is dead-lettered immediately with the reason recorded.

Affiliates manage their own

Postbacks are self-service. Affiliates add, edit, and disable their own URLs in the affiliate portal, hard-scoped to their own account, so an affiliate can only ever see and change their own postbacks. That removes the most common support ticket in an offer network - "please update my postback URL" - and it means an affiliate can test a change without waiting on anyone. See the affiliate portal.

Related: the conversion lifecycle for what the three events mean, and the API for pulling stats rather than being pushed events.