Skip to main content
Partner endpoints receive webhooks in the v2 envelope. Platnova switches an endpoint to v2. Endpoints that are not switched keep the v1 body and v1 event names.

The envelope

  • id is 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 on id.
  • created_at is when the event happened, not when this attempt was sent.
  • partner_reference is 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.
  • data is 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
Never verify a body you have re-serialised, such as JSON.stringify(req.body) after a JSON body parser has run. Key order and whitespace change, and the signature will not match.
To test your code: with the secret whsec_test and exactly the body {"id":"evt_1","type":"payout.succeeded"} (no spaces, no trailing newline), the header is:
Rotating secrets and the key id headers are covered in Webhook signatures.

Event names

v2 renames the payout events. All other events keep their v1 names. A subscription may list either name, and payout.* 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.