The envelope
idis the event’s own id. It is the same on every retry and every redelivery, and so is the whole body, byte for byte. Deduplicate onid.created_atis when the event happened, not when this attempt was sent.partner_referenceis always present, though it may be"". It is the checkout’s, refund’s, travel order’s or payout’s reference. A refund made without its own reference carries the checkout’s.datais the event’s own payload, unchanged from v1.
Headers
Verify the signature (Node.js / TypeScript)
Compute the HMAC over the exact bytes you received, before any JSON parsing, and compare it in constant time.Express (TypeScript)
Next.js route handler
whsec_test and exactly the body {"id":"evt_1","type":"payout.succeeded"} (no spaces, no trailing newline), the header is:
Event names
v2 renames the payout events. All other events keep their v1 names. A subscription may list either name, andpayout.* works.
Events a partner usually subscribes to:
Delivery history
GET /v1/partner/webhooks/endpoints/{endpoint_id}/events lists what was sent to an endpoint and how each attempt went.
Filters: status, event_type, start_date, end_date, event_id. Pagination: per_page, cursor.
Redeliver an event
POST /v1/partner/webhooks/events/{event_id}/redeliver sends one event again, whether or not it was delivered. The answer is { "event_id": "…", "status": "queued" }. An unknown event answers 404 event_not_found.
The redelivered body and signature are identical to the first ones, so your id dedupe treats a redelivery as a repeat.
