Skip to main content
Webhooks are the intended way to track funding. Polling works, but every state transition emits an event and failures are pushed, not polled.

Payload

Events

funding_intent.created, .quoted, .awaiting_payment, .payment_received, .in_review, .settling, .settled, .partially_settled, .undeliverable, .failed, .expired, .canceled, .refund_pending, .refunded, .refund_failed
funding_address.created, funding_address.funded
customer.requirements_updated, customer.balance_updated
The three you must handle are funding_intent.settled, funding_intent.failed, and funding_intent.refund_failed. The last one is the only event that always requires a human.

Verifying

The signature is HMAC-SHA256 over timestamp + "." + raw_body.
Verify with a constant-time comparison, and reject timestamps older than five minutes. verifyWebhook does both and throws rather than returning false, so an unchecked call cannot silently pass.

Delivery

At-least-once, so your handler must be idempotent. Use the event id as your dedup key. Retries on failure: immediate, 1m, 5m, 15m, 1h, 6h, 24h, then marked permanently failed and surfaced in the dashboard. Respond 2xx within 5 seconds.

Live status in a browser

For a checkout UI, subscribe rather than poll:
Server-sent events, authenticated with a checkout session token.