How it differs from the legacy macro postback
Affiliates have an existing single-URL GET mechanism with macros like{subid}, {amount}, {txn_id} — that one is unchanged and still works.
The system documented here is additive:
Legacy postback_url | Outbound Postback URLs (this page) | |
|---|---|---|
| Method | GET with query macros | POST with JSON body |
| URLs | One per affiliate | One per event |
| Auth | None | HMAC X-EF-Signature (+ optional Bearer token) |
| Retries | Best-effort, no log | Queued + exponential backoff + delivery log |
| Events | Purchase only | Purchase, refund, chargeback, renewal, cancel |
| Affiliate types | affcenter only | All affiliate types |
Configuration
In Affiliates → Edit affiliate → Postback URLs you’ll find:- HMAC Signing Secret — auto-generated per affiliate. Used to verify each request. Keep it secret. You can rotate it at any time; old endpoints will start failing signature checks until they pick up the new secret.
- Per-event Postback URLs — one row per supported event. Each row has:
URL—https://example.com/webhooks/affiliate-purchaseBearer Token (optional)— sent asAuthorization: Bearer …if setEnabled— toggle without losing the URL
- Send test — fires a synthetic payload (with
"test": true) for that event. - Recent Deliveries — log of every attempt with HTTP status, payload, response body, and a manual retry button.
Supported events
| Event key | When it fires |
|---|---|
purchase | A purchase conversion is approved for this affiliate. |
refund | An order or order line is refunded. |
chargeback | A chargeback is recorded against the order. |
subscription_renewal | A recurring subscription is successfully billed. |
subscription_renewal_failed | A recurring billing attempt fails. |
subscription_cancel | The subscription is cancelled or stopped. |
shipped, abandon, or
failed_payment — those aren’t commission-bearing events.
Request format
HTTP
Signature verification
The signature isHMAC_SHA256(secret, "<X-EF-Timestamp>.<raw_body>"), hex-encoded
and prefixed with sha256=.
Always verify both the signature and the timestamp (reject anything older
than ~5 minutes to defeat replays).
Response handling
Return any 2xx response to acknowledge delivery. Anything else (timeouts, non-2xx, network errors) is recorded as a failure and retried with exponential backoff at 1m, 5m, 30m, 2h, 12h (5 attempts total) before being markeddead. Dead deliveries can be manually retried from the Recent Deliveries log.
Payload schema
Every event uses the same envelope. Numeric amounts may be negative for clawback events (refund, chargeback, subscription_renewal_failed).
Field reference
| Field | Notes |
|---|---|
event | One of the supported event keys above. |
event_id | Unique, prefixed ef_aff_evt_…. Use it to dedupe on your side. |
occurred_at | ISO-8601, server time of the underlying conversion event. |
test | true for “Send test” payloads, false for live events. |
affiliate.* | Identifies the affiliate the conversion is attributed to. |
offer.name | The funnel title — typically what you see as your “offer name”. |
offer.funnel_code | Stable, URL-safe slug of the funnel. |
amount | Order amount in the currency below. Negative for clawbacks. |
commission | The affiliate’s calculated commission for this event. |
transaction.transaction_id | Gateway transaction id when available. |
transaction.conversion_code | ElasticFunnels conversion identifier. |
transaction.original_conversion_code | For refunds/chargebacks: the original purchase’s conversion code. |
tracking.subid … subid5 | Affiliate-defined subids captured from the click. |
tracking.click_code | EF’s click identifier; correlate with your own click logs. |
What’s deliberately not in the payload
- Customer name, email, phone, address, IP — affiliates don’t need PII to reconcile.
- Product-level details (SKUs, line items, shipping/billing).
- Anything specific to the underlying gateway.
Operational details
- Deliveries are processed asynchronously.
- Failed deliveries are retried automatically after their backoff window has elapsed.
- The Recent Deliveries section in the affiliate form shows delivery attempts and outcomes.
- Rotating the signing secret immediately invalidates the old one. Coordinate the change with your affiliate before rotating in production.
Testing locally
Point a URL at webhook.site orngrok, hit Send
test for the event you want, and you’ll see the payload + headers arrive
within seconds.