sk_v1_test_… key.
1. Stand up a receiver
A webhook endpoint is an HTTPS URL that accepts aPOST. Start with a handler
that captures the raw body (the signature covers the exact bytes, so a body
that’s been parsed and re-serialized by framework middleware will not verify)
and acknowledges quickly.
On Node, webhooks.unwrap() from the server SDK checks the signature and
replay window, then returns a typed event:
Express
{id}.{timestamp}.{body} — Verify signatures has the
full manual implementation in Node, Python, and Go.
2. Register the endpoint
Tell Ionic where to deliver and which events you want. For this walkthrough, subscribe topayment_intent.created.
secret that starts with whsec_. This is the only time it’s shown. Save it where your server can read it:
3. Verify every delivery
Your handler already does:unwrap recomputes the signature over the raw body
with constant-time comparison, rejects deliveries older than the replay
window, and throws on anything that doesn’t match. Don’t skip verification:
an unverified endpoint will accept forged events from anyone who learns your
URL. If you’re implementing it yourself, Verify
signatures walks through the same checks step by step.
4. Trigger an event
Create a payment intent. This needs only an amount and currency — no card — and emitspayment_intent.created.
5. You’re receiving webhooks
That’s the whole loop: register, verify, receive. Becauseunwrap returns a
typed event, handling a specific type narrows the payload for you:
Event catalog
Subscribe to the events you actually handle —
payment_intent.succeeded, refund.succeeded, and the rest.Idempotency & retries
Make your handler safe against duplicate and out-of-order deliveries before you ship.
Developing locally
Ionic can’t deliver webhooks tolocalhost. Two ways to work while local:
- Read the current status. Fetch the resource directly when you need an
answer — for example
GET /v1/checkout/sessions/{id}returnspayment_statuson demand. This works for most local testing. - Tunnel your receiver. Expose your local port (for example
ngrok http 3000), register the tunnel URL as a webhook endpoint, and update the endpoint’surlwhenever the tunnel address changes.

