Knowledge Base Server postbacks (S2S)

What is a postback, in plain words

A postback is a tiny notification one system sends to another to say: "an event just happened on my side". A registration, a deposit, a decline — all of those are events. A postback is how they travel between systems in real time.

In our platform postbacks flow in two directions:

  • Advertiser → us. A player registers or makes a deposit — the advertiser pings us, and we record a conversion.
  • Us → affiliate. Once the conversion is recorded and passes our checks (filters, optimization, manual review), we ping the affiliate's tracker URL so they see the same event in their reports.

Technically a postback is just an HTTP URL one system calls on another. No file uploads, no manual exports — data shows up instantly.

The whole picture

Let's walk one registration through the full chain:

  1. The affiliate sends traffic through their tracking link (it contains our click_id).
  2. The user clicks and lands on the advertiser's page.
  3. The user registers. The advertiser fires a postback to us with that click_id and the event "registration".
  4. We catch the postback, match it to the right click and affiliate, and calculate the payout.
  5. If the conversion passes our rules (filters, optimization, manager approval), we fire a postback to the affiliate's tracker URL.
  6. The affiliate sees the conversion in their own dashboard and gets paid against our reports.

The golden rule: every postback URL must carry the click_id. It's the "ticket number" that tells the receiving system which click the event belongs to. Without it the postback can't be attached to anything.

Step 1. Set up the advertiser

Goal of this step: whenever something happens on the advertiser's side (registration, deposit, etc.), they automatically hit our URL and hand us the conversion.

What to give the advertiser

Send them this template — note that it's our URL; we receive, they don't.

https://sftshrt.space/postback?click_id={CLICK_ID}&goal=reg

Two things to call out:

  • {CLICK_ID} is a placeholder on their side. They have to substitute the actual click_id we passed to them with the traffic. Different ad servers spell that placeholder differently: {clickid}, [clickid], %CLICK_ID%, and so on. Ask their integration team for the exact syntax.
  • goal=reg means "registration". For a deposit it would be goal=dep, for FTD goal=ftd, etc. The goal aliases are agreed up front and live in the offer's Goals tab.

If the advertiser sends a deposit amount

https://sftshrt.space/postback?click_id={CLICK_ID}&goal=dep&deposit_sum={AMOUNT}&currency=USD

If they pass the real deposit amount, add deposit_sum and an explicit currency. The payout to the affiliate is still computed from the offer's payout rules — but you'll have real-deposit numbers handy for analytics.

If the advertiser reports declines

https://sftshrt.space/postback?click_id={CLICK_ID}&goal=dep&status=declined&declined_reason=duplicate

For a decline we need both status=declined and a non-empty declined_reason (one word or a short sentence is fine). We deliberately refuse declines without a reason — otherwise traffic-quality analytics fall apart.

Step 2. Set up the affiliate

Goal: every time we approve a conversion, the affiliate's tracker receives a hit on their postback URL and shows the event on their side.

What to ask the affiliate for

Their tracker's postback URL — the URL we should hit when a conversion happens. The URL must contain our macros, short placeholders in curly braces like {click_id} that we will replace with real values at send time.

https://tracker.partner.com/postback?cid={click_id}&goal={goal}&amount={payout}&currency={currency}&sub1={sub1}

On the left of = is whatever the affiliate's tracker expects. On the right is our macro in curly braces — we'll substitute it.

Where to plug it in

Two flavors — pick what fits the case:

  • Global affiliate postback — one URL for all the affiliate's offers. Lives on the affiliate's card → Postbacks tab. Use this when their tracker is uniform across offers.
  • Offer-specific postback — set on the offer's card → Postbacks tab. Useful when this one offer needs a different URL or a different parameter set.

If the affiliate has both a global and an offer-specific postback for the same offer, only the offer-specific one fires. It always wins over the global one.

Hard requirement

The URL must include the {sub1} macro. Most trackers use sub1 as their own attribution key, and we refuse to save URLs without it — that's a safeguard against silently broken integrations.

Macros: what they are and which ones exist

A macro is a "magic word in curly braces" we replace with a real value when we fire the postback. For example, {click_id} in the affiliate's URL becomes something like abc-123-xyz for one specific conversion.

The ones you'll actually use

Macro What we put there
{click_id} The click's "ticket number". Always include this — it's the primary key for attribution.
{goal} The goal that fired: reg, dep, ftd, etc.
{payout} Affiliate's payout in the offer's currency. {revenue} and {sum} are aliases.
{currency} Currency code (USD, EUR, …). Defaults to USD.
{status} Lifecycle status: approved, declined, pending, hold.
{sub1}{sub8} Arbitrary values the affiliate themselves passed in the tracking link.
{deposit_sum} Player's real deposit amount (if the advertiser passed it).
{country} Player's country (ISO-2, e.g. DE).
{conversion_id} Our internal conversion ID. Handy for cross-system reconciliation.

Less common ones

Macro What we put there
{offer_id} Our internal offer ID.
{offer_name} The offer's name.
{aff_id} Our internal affiliate ID.
{source} Traffic source if it was passed in the click.
{creative_id} Creative ID if it was passed in the click.
{ip} Player's IP at click time.
{user_agent} Browser / device at click time.
{datetime} Conversion timestamp in UTC.

Any macro that's not on these lists will be rejected when the URL is saved — we'd rather fail loud than silently misfire on a typo.

How to verify it works

Two convenient places inside the platform:

  • Offer card → Postbacks tab. There's a "Send test" button that fires a real postback to the affiliate using the latest available click_id. The conversion won't show up in statistics, but the affiliate sees it in their tracker.
  • Postbacks → Logs. Every incoming request and every outgoing attempt is logged. You can see the URL before and after substitution, the affiliate's response, and the latency.

To let the advertiser send a clean test without polluting statistics, ask them to add is_test=1 to the URL. Such conversions land in logs but never reach reports or finance.

When something isn't working

The advertiser's conversions don't arrive

  1. Open Postbacks → Logs. Was there any request from the advertiser at all? If not, they haven't wired the URL up — double-check what you sent them.
  2. If a request arrived but the log reads click_id_not_replaced, the advertiser is sending the literal string {CLICK_ID} instead of the real value. They need to use their own substitution placeholder.
  3. If you see an "unknown goal" error, the alias doesn't match the offer's goals. Go to the offer's Goals tab and align with the advertiser.

The affiliate doesn't receive postbacks from us

  1. Filter logs by type "outgoing" for this affiliate/offer. No rows? The conversion is probably not approved yet, or it got cut by optimization — check the conversion itself.
  2. Rows exist, but HTTP response isn't 2xx? Copy the URL and open it in a browser; the tracker's response usually tells you exactly what's wrong.
  3. Outgoing URL looks weird (a macro wasn't replaced)? The affiliate has a typo in the macro name. Open their postback and fix it.

About 90% of issues are either a wrong placeholder on the advertiser's side or a typo in the affiliate's macro. Before pinging support, peek at the logs — they almost always point straight at the broken step.