Overview
Real-time notifications for transaction, token, and merchant lifecycle events, delivered by legacy webhooks or, by invitation, by Svix.
Webhooks provide real-time notifications for completed transaction and token events. You can configure webhooks to receive notifications for specific events, such as when a sale transaction is completed or a token is created.
Each event type is separate, so you can choose to subscribe to only the events you want to receive notifications for.
Each event is sent as a POST request to the endpoint URLs you configure, and each endpoint chooses which event types it subscribes to. The request body contains a JSON payload with the details of the event.
Configured transaction webhooks report outcomes across payment channels without depending on the customer's browser. A session or local validation error might not produce a transaction webhook. Use verified webhooks and authenticated transaction retrieval to maintain your payment records.
Two delivery methods
Webhooks reach you by one of two delivery methods. The event payload is identical on both. Only the transport, the way you configure endpoints, and the signature differ.
| Legacy webhooks | The delivery method every merchant has today. Support configures your endpoints, and each delivery is signed with the x-fsk-wh-chksm checksum. | Legacy webhooks |
| Svix webhooks (invite only) | Self-service endpoints in the partner portal, signed deliveries with replay protection, and a portal to inspect and replay failed deliveries. Available by invitation. | Svix webhooks (invite only) |
Svix webhooks are invite only. Unless Svix is enabled for your account, you are on legacy webhooks, and that is the delivery method to build against. To ask for Svix, see Requesting access.
Side by side
| Legacy webhooks | Svix webhooks | |
|---|---|---|
| Availability | Every merchant, today | Invite only |
| Who sets it up | Support, on your behalf | You, self-service, in the partner portal |
| Signature headers | x-fsk-wh-chksm |
svix-id, svix-timestamp, svix-signature |
| Signature algorithm | HMAC-SHA256 over the raw body, lowercase hex | HMAC-SHA256 over {svix-id}.{svix-timestamp}.{body}, base64 |
| Secret | Shared secret provided out-of-band by support | Per-endpoint signing secret (whsec_...), shown in the portal, rotatable |
| Replay protection | None - the signature has no time component | Yes - timestamp tolerance enforced by the Svix libraries |
| Retries | Retried on failure, but not on a published schedule | Automatic, exponential backoff over roughly a day |
| Inspect and replay failed deliveries | No - contact support | Yes, from the portal |
| Events | Transaction and token events | Transaction, token, and merchant lifecycle events |
| Event payload | Identical | Identical |
The payload is the same on both. Only the transport and the signature differ. Whichever you are on, the JSON body you parse and the event catalog you handle are the same - you do not need two parsers.
Tell from the headers
If you are not sure which delivery method your endpoint is on, capture one delivery and look at its request headers:
POST /webhooks HTTP/1.1
Content-Type: application/json
x-fsk-wh-chksm: 862c6f2473c97472be4262b04670e777b2ed145d12d8a1c79ffc52ea9cfe7f0f
You are on legacy webhooks. Follow Verifying the checksum, and contact support to change your endpoints.
POST /webhooks HTTP/1.1
Content-Type: application/json
svix-id: msg_2yZK3ZV4Tk3E8FQ0YB55X1N0Tq
svix-timestamp: 1783002600
svix-signature: v1,g0hM9SsE+OTPJTGt/tmIKtSyZlE3uFJELVlNIOLJ1OE=
You are on Svix webhooks. Follow Verifying signatures, and manage your endpoints yourself in the partner portal.
If the same URL receives some deliveries with x-fsk-wh-chksm and others with svix-* headers, your endpoint is registered on both delivery methods. Each event is then delivered twice - once by each.
This is expected while you move from legacy to Svix, not a fault. Handle it by deduplicating on event.id (see below), and ask support to remove the legacy registration once your Svix handling is verified. See Moving from legacy to Svix.
Delivery and retries
Deliveries are retried on both delivery methods when your endpoint does not answer with a 2xx. On legacy webhooks, failed deliveries are retried, but there is no published schedule and no portal to inspect or replay them - contact support. On Svix, retries follow an exponential backoff schedule over roughly the following day, endpoints that keep failing may be disabled automatically, and failed deliveries can be inspected and replayed from the portal.
Verify the delivery and save it to a durable queue before returning 2xx, then process asynchronously. If saving fails, return a non-2xx response so delivery can be retried. A handler that does slow work inline risks timing out, which is treated as a failed delivery and retried - so slow processing turns into duplicate processing.
Deduplicate on event ID
Because deliveries are retried, and because an endpoint can be registered on both delivery methods while you move from one to the other, your handler must be idempotent - the same event can arrive more than once.
Every payload, on either delivery method, carries an event envelope with a unique id. This excerpt shows only the envelope:
{
"event": {
"id": "evt_01JS21X856RR8R69GV5F17XK9C",
"type": "sale.completed",
"timestamp": "2025-04-16T14:30:00Z",
"merchantId": "mer_01JQZC2Y6W3F8XKT5H9DPNBMVR"
}
}
Store the event.id of every delivery you have processed, and ignore any delivery whose event.id you have already seen. This one check protects you against:
- a legacy retry, or a replayed legacy delivery - the legacy checksum carries no timestamp, so this check is also its replay protection,
- Svix's automatic retries after a slow or failed acknowledgement, and a manual replay from the portal, and
- the same event arriving on both delivery methods while your endpoint is registered on both.
event.id is the same value on both delivery methods for the same event, because both send the same payload. The Svix svix-id header identifies the Svix message - it is constant across retries of one Svix message, but it is not present on legacy deliveries and does not match event.id. Deduplicate on event.id.
Where ACH depends on this
For ACH bank transfers, acceptance for processing is separate from settlement. The hosted ACH response reports Processing with result code 0; final webhooks report status: Completed with the approval or decline in transactionResponses[].responseCode. Use transaction retrieval to reconcile a missed delivery.
Event categories
| Transaction events | Sales, authorizations, captures, refunds, and voids. Both delivery methods. | Event catalog |
| Token events | Stored payment methods created and removed. Both delivery methods. | Event catalog |
| Merchant lifecycle events | Merchant application progress, approval, and pricing decisions. Svix webhooks only. | Event catalog |
Next steps
Know which delivery method you are on
You are on legacy webhooks unless Svix is enabled for your account. The headers of one delivery confirm it - see Tell from the headers.
Configure an endpoint
Through support on legacy webhooks, self-service in the partner portal on Svix. See Configuring endpoints for legacy, or Configuring endpoints for Svix.
Verify every delivery
Reject any request whose signature does not validate. See Verifying the checksum for legacy, or Verifying signatures for Svix.
Handle the events you subscribed to
See the event catalog for payloads and the full list.