Skip to content

Webhooks

Receive Kustom events by HTTPS POST instead of polling — the event types, the slim payload shape, Standard Webhooks signature verification, secret rotation and why your handler must be idempotent.

A webhook tells you that something happened in Kustom without you having to poll for it. You register an HTTPS endpoint in the Kustom Portal, subscribe it to event types, and Kustom POSTs to it when one occurs. Payloads are deliberately slim — they identify the thing that changed, not its full state — so a handler almost always ends by fetching the object from the relevant API.

{
"id": "kevt_1YcaJdWrmlw9yp1GiiVgad",
"merchant_id": "DM11917000",
"timestamp": "2026-04-10T08:27:07.248645321Z",
"type": "capture.created",
"data": {
"order_id": "25ed76ed-6477-46bb-8444-63945789ccfb",
"capture_id": "070ddfa9-f7a8-4fb0-8291-b5b31a300a23",
"created_at": "2026-04-10T08:27:02.648627Z"
}
}
FieldWhat it is
idUnique ID for the event, stable across retry attempts. Use it for deduplication.
merchant_idYour Kustom Merchant ID.
typeThe event type, from the table below.
timestampISO 8601 time the event was generated.
dataIdentifiers for the affected objects. Contents vary by event type.

Treat data as a pointer, not a snapshot. By the time you handle the event the object may have moved on again, so read the current state through the API using the identifiers given.

Event typeFires when
order.createdA new order has been created.
capture.createdA capture has been made on an order.
refund.createdA refund has been issued on an order.
dispute.createdA new dispute has been opened on an order.
dispute.updatedAn existing dispute changes, for example its status.
ipp.session.createdAn in-person payment session has been created.
ipp.session.activatedAn in-person payment session has been activated.
ipp.payment.failedAn in-person payment attempt has failed.
ipp.session.finalizedAn in-person payment session has been finalized.
ipp.session.cancelledAn in-person payment session has been cancelled.

New event types are added over time. A handler that throws on an unrecognized type will break the first time one appears — ignore what you haven’t subscribed to and log it.

  1. Expose an HTTPS endpoint that accepts POST, returns a 2xx promptly and does its real work asynchronously. Anything other than a 2xx, or a timeout, is a failed delivery and will be retried.
  2. Register it in the Kustom Portal, under Integrations → Webhooks, and choose the event types it should receive.
  3. Verify the signature on every request before you act on the body.

Acknowledge first, process second. A handler that captures, refunds or writes to a slow database before replying is a handler that will be sent duplicates.

Kustom signs every payload following the Standard Webhooks specification, so an off-the-shelf Standard Webhooks library will verify a Kustom delivery unmodified.

HeaderWhat it carries
webhook-idUnique message ID, identical across retry attempts. Use for deduplication.
webhook-timestampUnix timestamp in seconds of when the message was sent.
webhook-signatureOne or more space-delimited HMAC-SHA256 signatures.

Your signing secret is generated when you configure the destination and has the form whsec_<base64-encoded-secret>. Retrieve it from the Portal, store it as a secret and check the webhook-timestamp against your own clock to reject replayed deliveries. Implementation guidance is in the Standard Webhooks specification.

webhook-signature can hold more than one signature. Verify against any accepted secret, not only the first — that’s what makes rotation non-breaking.

Rotate from the Portal at any time. During rotation Kustom signs with both the old and the new secret, space-delimited in webhook-signature, so a verifier that accepts either keeps working throughout. Rotation takes up to 10 minutes to propagate because of caching. Once your code is verifying with the new secret, retire the old one.

If your endpoint doesn’t return 2xx, or times out, Kustom retries with exponential backoff for up to 3 days.

Deliveries are therefore at-least-once, and your handler must be idempotent. Deduplicate on id in the body, or equivalently on the webhook-id header — both are stable across retries of the same event. Record the ID before doing the work and discard anything you’ve already seen.

This page is also available as Markdown — append .md to its URL — and is indexed in llms.txt.