
Publisher docs
Integrate your app with 
The same integration guide publishers see inside the dashboard.
Worked example
One user, one two-goal offer, and every request you would actually receive.
Worked example, end to end
One user, one offer, every request you would actually receive, with real-shaped values you can trace from step to step. This example is an Offers API placement running a two-goal offer ("signup", then "deposit") and the shipped default templates. The cast:
- Your user:
u123(theuser_idyou sent on the feed call). - The offer: id
64f3b2a1c9d4e5f601234567, paying you $2.50 for signup and $7.50 for deposit; your placement margin leaves the user reward at $1.25 / $3.75. - Your shared secret:
kq8Zw3vN7Rp2(what you swapped in forYOUR_SECRETwhen you saved the templates).
- 1u123 opens the offer. You linked them to the feed's
trackingUrl; we record the click and mint its id:b3f1c9a2-7e44-4f1a-9c2d-0a6e8d5b21c7. Everything that follows hangs off that one id. - 2The signup goal is approved → we GET your primary postback URL. With the default template, every param is present; note
points=arriving empty (no coin step on this channel) andevent=signup:Your handler: status isPrimary postback: goal 1 (signup)https://your-site.com/postback?key=kq8Zw3vN7Rp2&user_id=u123&tx=b3f1c9a2-7e44-4f1a-9c2d-0a6e8d5b21c7&points=&payout=1.25¤cy=USD&offer_id=64f3b2a1c9d4e5f601234567&status=approved&event=signup
approved, the pair (b3f1c9a2…,signup) is new → store it, convertpayout=1.25into your currency, credit u123, answer200. - 3A week later u123 deposits → a second, separate credit on the same click. Same
tx, differentevent:The pair (Primary postback: goal 2 (deposit)https://your-site.com/postback?key=kq8Zw3vN7Rp2&user_id=u123&tx=b3f1c9a2-7e44-4f1a-9c2d-0a6e8d5b21c7&points=&payout=3.75¤cy=USD&offer_id=64f3b2a1c9d4e5f601234567&status=approved&event=deposit
b3f1c9a2…,deposit) is new → credit again. A handler deduping ontxalone would have answered "already processed" here and silently kept u123's deposit reward. That is the bug the pair exists to prevent. - 4The signup conversion is charged back → a reversal arrives, on your reversal URL only, never on the URL above. With the default reversal template:Read it carefully against step 2:Reversal postback (separate URL)
https://your-site.com/reversal?key=kq8Zw3vN7Rp2&user_id=u123&tx=b3f1c9a2-7e44-4f1a-9c2d-0a6e8d5b21c7&event=d9c1e6b0-2f7a-4c3e-8a11-6f2b8c4d7e90&coins=0&points=0&payout=2.00&reason=chargeback&status=reversed
txis the same click id, so you can join it to the credits you stored, buteventis now a fresh delivery UUID, not "signup", andcoins=0andpoints=0because an Offers API conversion has no coin layer;payout=2.00carries the full USD value credited at approval, which is the amount to take back. Your handler: status isreversed→ take the reversal branch, check the UUIDd9c1e6b0…is unseen (dedupe key on this channel), record it, take back what you credited for the signup, answer200. If the delivery is retried, the same UUID arrives again and your check swallows it.
On a hosted wall the ids are identical; only the amounts change: points arrives filled (the amount in your currency), coins shows the coin grant, and currency is your currency's name instead of USD. Same click id in tx, same goal id in event, and a reversal's tx joins to your stored credits the same way. See Dedupe keys per channel.