Verify Checkout Docs

Receive signed events

Webhooks are recommended automation, not a requirement. Polling remains a supported fallback and recovery path.

A webhook is a change signal

Save the deposit ID when you create the checkout. When a signed webhook arrives, verify and deduplicate it, then retrieve GET /v1/deposits/{depositId} whenever you need the authoritative current state. Fulfill exactly once only when that state is succeeded; never fulfill from the browser return or delivery order alone.

Create and activate an endpoint

  1. Open Webhook endpoints and add an HTTPS URL.
  2. Select events. Outcome events and webhook.test are selected by default; lifecycle events are opt-in.
  3. Copy the one-time whsec_… signing secret.
  4. Send a test delivery. The first successful 2xx response activates the endpoint.

Verify every delivery

Read the raw request bytes before JSON parsing. The signature is HMAC-SHA256 over <timestamp>.<raw-body> and uses the current signature version v1.

import { createHmac, timingSafeEqual } from "node:crypto";

function verifyWebhook(rawBody: Buffer, timestamp: string, signature: string, secret: string) {
  const ageSeconds = Math.abs(Date.now() / 1000 - Number(timestamp));
  if (!Number.isFinite(ageSeconds) || ageSeconds > 300) return false;

  const expected = createHmac("sha256", secret)
    .update(`${timestamp}.`)
    .update(rawBody)
    .digest("hex");
  const received = signature.startsWith("v1=") ? signature.slice(3) : "";
  if (received.length !== expected.length) return false;
  return timingSafeEqual(Buffer.from(received, "hex"), Buffer.from(expected, "hex"));
}

Required headers:

HeaderPurpose
VerifyCheckout-EventEvent type
VerifyCheckout-Event-IdStable event ID for deduplication
VerifyCheckout-Delivery-IdThis delivery attempt
VerifyCheckout-TimestampUnix timestamp included in the signature
VerifyCheckout-Signaturev1=<hex-hmac-sha256> signature
VerifyCheckout-Api-VersionWebhook payload contract version
VerifyCheckout-TestPresent on test deliveries

The current webhook payload API version is 2026-06-01.

Reject stale timestamps before processing, compare signatures in constant time, and return 2xx only after the event is durably accepted.

Events and delivery semantics

Outcome events cover completed, failed, expired, and review results. Optional lifecycle events describe earlier progress; webhook.test verifies connectivity. The dashboard event selector is the authoritative catalog for your account.

Deliveries are at least once. They can be duplicated, retried after non-2xx responses, and arrive out of order. Deduplicate by event ID and make wallet crediting idempotent by deposit ID. Do not assume the next event is newer—retrieve the current deposit when ordering matters.

The recommended end-to-end sequence is: create checkout → save deposit ID → send the customer to checkout → accept the signed webhook → retrieve the deposit when confirmation is needed → fulfill only when its current status is succeeded. See Create a Deposit for the complete flow.

Webhook payloads include environment: "live" as a compatibility field. The current platform has one active flow; do not branch business logic on this value.

Rotate a signing secret

Create or rotate the endpoint secret in the dashboard, deploy the new whsec_… value to your receiver, send a test delivery, and remove the old value after the transition window. Never use an API key as a webhook secret.

On this page

No Headings