Postback URLs do not replace the Automations module — they are complementary. Automations are great for branching logic, retries with conditions, and connecting many third-party services. Postback URLs are great for “fire-and-forget” event forwarding.
Where to configure
In your brand:- Go to Settings → Merchants → pick a merchant → Edit.
- Open the Postback URLs tab.
- For each event you care about, set:
- Postback URL —
https://your-app.example.com/webhooks/elasticfunnels - Bearer Token (optional) — sent as
Authorization: Bearer <token>so you can do basic auth from a reverse proxy. - Enabled — must be checked for the URL to fire.
- Postback URL —
- Use the Send test button next to each URL to deliver a sample payload right away.
- The Recent deliveries section shows status, HTTP code, attempts, the exact payload that was sent, and lets you retry failed deliveries manually.
Supported events
| Event key | Fires when |
|---|---|
purchase | A new approved purchase / order is recorded |
refund | A refund (full or partial) is recorded |
chargeback | A chargeback is recorded |
subscription_renewal | A recurring charge succeeds |
subscription_renewal_failed | A recurring charge fails (decline, processor error, etc.) |
subscription_cancel | A subscription is cancelled (by the customer, the merchant, or dunning) |
subscription_change | A subscription is upgraded / downgraded / paused |
abandon | Cart abandonment is recorded |
failed_payment | An initial payment attempt fails (not a renewal — see above) |
shipped | A tracking number is assigned to an order for the first time |
event field and on the X-EF-Event header.
Request format
Every request looks like this:| Header | Purpose |
|---|---|
X-EF-Event | The event name (same as event in the body). |
X-EF-Delivery-Id | Unique ID for this delivery attempt (use it for idempotency on your side). |
X-EF-Timestamp | Unix timestamp of when the signature was computed. |
X-EF-Signature | sha256= + HMAC-SHA256 of <timestamp>.<raw_body> using your merchant’s signing secret. |
X-EF-Brand-Id | The brand the merchant belongs to. |
X-EF-Merchant-Id | The merchant the postback came from. |
Authorization | Optional bearer token, only sent if you configured one for that URL. |
Verifying the signature
Reject any request whose recomputed signature does not matchX-EF-Signature. Always compare with a constant-time function (hash_equals in PHP, crypto.timingSafeEqual in Node, etc.). It is also a good idea to reject requests whose X-EF-Timestamp is more than a few minutes in the past or future.
Response handling
- Return any
2xxstatus to acknowledge the delivery. The body is ignored (but stored in the deliveries log for debugging — keep it under a few KB). - Any non-2xx response, timeout, or connection error counts as a failure.
- Failed deliveries are retried automatically with exponential backoff:
1m → 5m → 30m → 2h → 12h(up to 5 attempts). After the final failure the delivery is marked dead and stops retrying. You can re-queue it manually from the Postback URLs tab. - Each delivery has a unique
X-EF-Delivery-Id. Use it to dedupe on your end.
Standardized payload
All events share the same envelope. Fields that don’t apply to a given event are present butnull. The full schema:
Event-specific notes
refund/chargeback—amounts.totalis negative for the refunded portion, andorder.original_conversion_codereferences the original purchase row.subscription_renewal_failed—order.subscription.retry_countandorder.subscription.next_charge_atreflect the dunning schedule, andmeta.payment_statuswill typically befailedwith a populatedorder.subscription.decline_reason.subscription_cancel—order.subscription.statusiscancelledandorder.subscription.cancel_reasonis filled when available.shipped— fires the first time a tracking number is set on an order.shipping.tracking_number,shipping.tracking_url, andshipping.carrierare populated. We dedupe per order so you only get oneshippedevent.abandon—order.statusisabandonedandcustomermay be partially populated depending on how far the visitor got in checkout.test— Postbacks fired from the Send test button or originating from a sandbox merchant settest: true. Use it to gate side effects in your handler.
Example: minimal Express.js handler
Operational details
- Deliveries are processed asynchronously so they do not block the gateway request that triggered them.
- Failed deliveries are retried automatically after the configured backoff window has elapsed.
- The Postback URLs tab shows recent deliveries, including the URL, payload, headers, response body, attempts, and final status.
- The signing secret is stored encrypted at rest. Rotating it invalidates all previous signatures immediately — only do it if you can update your verifier in lockstep.