Skip to content

Postback URLs

A Postback URL is an HTTP endpoint that OpenPartner pings every time a conversion lands on your account. If you run paid traffic through an ad tracker, this is how OpenPartner closes the loop with that tracker so your ROAS / EPC / cost reports stay accurate.

If you don’t run paid traffic — most creators don’t — you can skip this page.

Postbacks in the partner sidebar.

When you’d want one

You’re running media (Facebook, TikTok, native, search) into a partner link, and you use:

  • Voluum, Bemob, RedTrack, BinomTracker, FunnelFlux, or another self-hosted tracker
  • A bespoke logging service that records conversions per click
  • A spreadsheet pipeline triggered by a webhook receiver (Zapier / Make.com / n8n)

OpenPartner already records the click → conversion → commission chain on its own side. The postback is for when you need that signal also delivered to a system you control.

How it works

  1. You configure a URL on Postbacks with macro placeholders like {click_id}, {commission_amount}.
  2. When a commission accrues / approves / pays out, OpenPartner substitutes the real values into the URL and fires a plain GET request.
  3. Your tracker logs the conversion against the click ID it remembers from the click-out.

The fire is fire-and-forget — your tracker being slow or down won’t block OpenPartner’s own attribution. Failed deliveries are tracked as a per-postback failureCount so you can spot a misconfigured endpoint.

Events you can subscribe to

Only the conversion ledger fires on the partner side. Partner-state events (partner.activated, partnership.approved, payout.created) are tenant-scoped and surface through the brand’s outbound webhooks instead.

EventFires when
commission.accruedA conversion attributes to you and a Commission row is created. Also fires for the smaller commission a partial refund leaves (see Refunds), and for your share of a recruit’s commission (see Recruiter commissions). Most trackers want this one.
commission.approvedHoldback period ended (or admin manually approved) — the commission is now eligible for payout.
commission.paidPayout transferred.
commission.reversedRefund / chargeback / manual reversal.

Refunds

When the brand reports a refund or chargeback on a conversion you earned on:

  • Full refund: commission.reversed fires for your commission.
  • Partial refund: commission.reversed fires for the original commission, then commission.accrued for a new one worth the share the customer kept. Both carry the same {click_id}, {event_id} and {transaction_id}; the new one has its own {commission_id} and {commission_amount}. If the original was already approved, commission.approved fires for the new one too.
  • After you’ve been paid: nothing fires. The paid commission stays paid.

Trackers that de-duplicate on the transaction id (RedTrack’s txid, for example) may drop the second commission.accrued as a repeat. If your tracker should reflect partial refunds, send it {commission_id} as the transaction id instead of {transaction_id}, and fire commission.reversed to it too, so the original is cancelled and the smaller one counts.

Recruiter commissions

If you recruit partners, your share of a recruit’s commission fires the same commission.* events. Those postbacks carry nothing of the recruit’s sale: the click, sub-ID, event and sale value are the recruit’s, and none of them matches anything in your tracker. So on a recruiter commission, {click_id}, {sub_id}, {event_id}, {transaction_id} and {sale_amount} stay literal in the URL, as typed.

{commission_id}, {commission_amount}, {currency}, {status}, {program_id} and {event_type} fill in as usual. If your tracker needs a click id on every conversion, send {commission_id} instead, or ignore requests where {click_id} arrives literally.

Available macros

Macro values are URL-encoded at fire time. Unknown macros stay literal in the URL — so typos are visible rather than silently dropping a parameter.

MacroDescription
{click_id}Originating click. Present on every commission event except a recruiter commission.
{sub_id}Your own sub-ID from the link (…?sub_id=abc123), so your tracker can match its click. Empty when the link had none.
{status}pending, approved, reversed or paid: which change fired it (commission.accrued is pending).
{partner_id}Your partner ID.
{commission_id}The Commission row id.
{commission_amount}Decimal amount in major units (e.g. 12.50).
{sale_amount}The sale’s value in major units (e.g. 60.00). Empty when the event has no value.
{currency}3-letter ISO currency code.
{event_id}The Event row that drove the commission.
{transaction_id}Alias for {event_id} — many trackers expect this name.
{event_type}invoice_paid, signup, or whatever custom type the brand sent.
{program_id}The program the commission came through.
{payout_id}Only present on commission.paid.

Security

OpenPartner postbacks are unsigned — that matches how every affiliate tracker on the market consumes them. If you want to verify the request actually came from OpenPartner (rather than a third party hitting your tracker URL directly), add a shared secret as a query parameter when you configure the postback:

https://your-tracker.example/?cid={click_id}&payout={commission_amount}&secret=YOUR_SHARED_SECRET

Your tracker can refuse requests where secret doesn’t match the value you stored. The secret travels in the URL, so make sure your tracker only accepts it over HTTPS.

Example: Voluum

https://YOUR-DOMAIN.voluumtrk.com/postback?cid={click_id}&payout={commission_amount}

Voluum’s cid is the click identifier you passed into the link-out. OpenPartner’s {click_id} is also stamped into the original _cref cookie, so as long as the partner-side landing page captures cref and forwards it to Voluum as their click id, the loop closes.

Example: RedTrack

https://YOUR-DOMAIN.rdtk.io/postback?clickid={click_id}&sum={commission_amount}&txid={transaction_id}

RedTrack uses txid for transaction de-duplication — the {transaction_id} macro maps onto the OpenPartner Event id, which is unique per conversion.

Example: Bemob

https://YOUR-DOMAIN.bemobtrk.com/postback?cid={click_id}&payout={commission_amount}&txid={transaction_id}&type={event_type}

Example: bespoke webhook receiver

https://internal.your-stack.example/op?
partner={partner_id}&
click={click_id}&
amount={commission_amount}&
currency={currency}&
event={event_type}&
secret=YOUR_SHARED_SECRET

Reading the audit counters

Each postback row carries rolling counters: Fired, Success, Failed, Last fired, Last status. If Failed is climbing, your tracker is rejecting the request — common reasons:

  • Tracker requires HTTPS and you configured http://.
  • Tracker requires a specific click-id format and {click_id} doesn’t match (some trackers reject ULIDs because they expect a UUID).
  • Wrong query parameter names — check the tracker’s postback doc, not OpenPartner’s.

When this is the wrong tool

Postbacks are for partner-side trackers. If you want to:

  • Send conversion data to the brand’s Slack / CRM / data warehouse — that’s the brand’s problem; they configure outbound webhooks under Admin → Webhooks.
  • Pull a one-time list of every commission you’ve earned — use GET /partners/<your id>/commissions with a partner API key, not a streaming postback.
  • Authenticate strongly — postbacks are URL-shaped, no HMAC. Use the brand’s outbound webhooks if you control the receiver and want signed payloads.