Postback parameters
Every parameter the postback URL accepts, every response it returns, and what to paste into your offer source's postback field.
A postback is a URL your offer source calls when someone converts. It is the only way conversions get into PostbackX, and it needs no API key.
The URL#
https://postbacks.postbackx.com/postback?click_id={click_id}&payout={payout}GET and POST both work. POST accepts either application/json or application/x-www-form-urlencoded, using the same parameter names.
What you actually paste into your offer source depends on where it stored the click id. If you appended it as sub5 on your offer URL, that is what its macro will be called:
https://postbacks.postbackx.com/postback?click_id={sub5}&payout={payout}&transaction_id={transaction_id}The {...} parts are your offer source's own macros — it substitutes real values when it fires. Every platform names them differently, so copy them from its documentation, not from here.
Parameters#
Only click_id is required. Every alias below is accepted as an equal alternative, because offer sources disagree about what these fields are called.
| Parameter | Aliases | Required | Description |
|---|---|---|---|
click_id | aff_sub | Yes | The click this conversion belongs to — the value PostbackX put into your offer URL. |
payout | amount | No | Revenue for this conversion, as a decimal. Defaults to 0. |
transaction_id | txn_id, order_id | No | The offer source's own id for the conversion. Used to recognise repeat deliveries. |
event_name | event | No | Which conversion action fired, e.g. lead or purchase. Falls back to the campaign's default event. |
sub1 … sub5 | No | Pass-through values, stored on the conversion for your own reporting. | |
adv1 … adv10 | No | Advertiser custom parameters, forwarded to Facebook's Conversions API to improve match quality. |
Any other parameter you add is stored on the conversion as well. Offer sources each have their own extra fields, so rather than maintain a list of them, PostbackX keeps whatever it is given.
Responses#
The status codes are worth reading before you go looking for a bug, because two of them are deliberately not errors.
| Status | Meaning | Body |
|---|---|---|
200 | Recorded. | success: true with conversion_id, click_id, processing_time_ms |
200 | Already recorded — a duplicate delivery. | success: true, duplicate: true |
202 | Accepted, queued, and will be processed shortly. | success: true, accepted: true |
400 | No click_id, or a body that could not be parsed. | success: false with error |
404 | That click id does not exist. | success: false |
410 | The click is more than 90 days old. | success: false |
500 | Something failed on our side. | success: false |
Why duplicates and outages return 2xx#
Most offer sources treat any non-2xx response as a failure and retry — some for days. That behavior is useful when a postback genuinely did not arrive, and harmful when it did.
So a duplicate returns 200: the conversion is already recorded, the retry has served its purpose, and there is nothing to gain from another attempt. And if the database is briefly unreachable, the postback is queued and answered 202 rather than failing — the conversion is safe, and telling the offer source otherwise would produce a retry storm on top of an outage.
Treat 200 and 202 alike: the conversion is accounted for.
Duplicate detection#
A conversion is considered a duplicate when its click id, transaction id and event name all match one already recorded.
This is why transaction_id is worth sending even though it is optional. With it, repeat deliveries of the same conversion collapse into one, and two genuinely different sales on the same click stay separate. Without it, PostbackX cannot tell those two situations apart, and counts them as one conversion.
The event name being part of the key is what lets one click produce both a lead and a later purchase.
Testing it#
Fire a postback by hand, substituting a real click id from your Clicks report:
curl -i "https://postbacks.postbackx.com/postback?click_id=REAL_CLICK_ID&payout=18.00&event_name=lead&transaction_id=manual-test-1"A 200 with a conversion_id means the whole chain works. Run it again and you should get duplicate: true — proof that deduplication is doing its job.
If you get 400, the click id was empty: check that your offer source's macro matches the parameter you are sending it in. If you get 404, the id does not exist — a typo, or a click from a different organization.
For what to do when postbacks are not arriving at all, see Conversions are missing.