00 / free tool
Stripe webhook event checklist
Pick what your app does with Stripe. Get the events to subscribe to, what each one means, the mistakes people make, and a checklist you can copy.
01 / build your checklist
Must handle (2)
checkout.session.completedThe customer finished Checkout.
> Fulfill the order, but only if the session's payment_status isn't unpaid. With bank debits the money may still be on its way. Stripe docs
checkout.session.async_payment_succeededA delayed payment (for example ACH Direct Debit) went through after Checkout finished.
> Fulfill now. Must-have if you accept any payment method that isn't instant. Stripe docs
Should handle (3)
checkout.session.async_payment_failedA delayed payment failed after Checkout finished.
> Don't fulfill. Tell the customer, for example by email. Stripe docs
charge.refundedA charge was fully or partly refunded.
> Take back access or cancel the order if your refund policy says so. Stripe docs
charge.dispute.createdA customer disputed a charge with their bank.
> Decide whether to send evidence or limit the account. Without this event you only learn about disputes in the Dashboard. Stripe docs
If it applies (1)
checkout.session.expiredA Checkout Session expired without being completed.
> Only if you hold something while the customer pays, such as stock or a draft order. Release it here. Stripe docs
Common mistakes
- > Unlocking only on the success page. Run the same fulfill step from the webhook too. The customer can close the tab first.
- > Fulfilling on checkout.session.completed without checking payment_status. A delayed payment shows as unpaid until checkout.session.async_payment_succeeded arrives.
- > Fulfilling twice. Stripe may call your fulfill step more than once, even at the same time, for the same session. Record that you fulfilled it and skip repeats.
- > A slow handler. When you set a success_url, Checkout waits up to 10 seconds for your webhook reply before it redirects. Answer 2xx first, then do the slow work.
Every endpoint
- > Verify the Stripe-Signature header with the raw request body and the endpoint's own whsec_ secret.
- > Return a 2xx status quickly, before slow work.
- > Log event IDs you've processed and skip repeats. The same event can arrive more than once.
- > Don't rely on event order.
- > Subscribe only to the events you handle.
- > Each endpoint has its own whsec_ secret, and test and live mode secrets differ. Set up the live endpoint on its own before launch.
Copy the checklist
Paste it into a ticket, your README, or the prompt you give your AI builder.
02 / where this comes from
a
Event names
Every event name on this page is in Stripe's list of event types. Nothing is made up. Stripe: types of events
b
What to do with each
From Stripe's own guides: fulfill Checkout orders webhooks with subscriptions Connect webhooks invoice status changes webhook best practices
c
Set it up
Add the events in Workbench, Webhooks, on your endpoint. Then test with the Stripe CLI and check each one arrives. The webhook testing guide walks through it, and the error decoder explains failed deliveries.
03 / questions
- Which Stripe webhook events do I need for Checkout?
- For one-time payments: checkout.session.completed, plus checkout.session.async_payment_succeeded and checkout.session.async_payment_failed if you accept delayed payment methods such as ACH Direct Debit. Check payment_status before you fulfill.
- Which events do I need for subscriptions?
- At least invoice.paid, invoice.payment_failed, customer.subscription.updated and customer.subscription.deleted. If you start subscriptions with Checkout, also checkout.session.completed to link the customer to your user.
- invoice.paid or invoice.payment_succeeded?
- Stripe sends invoice.paid when an invoice payment succeeds or when an invoice is marked paid outside Stripe. invoice.payment_succeeded only covers the first case.
- Should I subscribe to all events?
- No. Stripe's advice is to subscribe only to the events your integration needs.
- Does this tool send anything?
- No. The list is built into the page and runs in your browser. Copy uses your own clipboard.
04 / catch it next time
Picking the right events is step one. Step two is knowing when they stop arriving. CheckoutAlarm reads your Stripe account with a read-only key and emails you when events are still undelivered after about 15 minutes, when an endpoint gets disabled, or when sales stop.
Free: 1 site, checked once a day. Pro: $19 a month for up to 3 sites, checked hourly. We only check sites you prove you own, and for Stripe we only take a read-only restricted key. Compare plans
Watch my app freeFree for one app. Checked every day. No card needed.
05 / more free tools
- Stripe webhook signature checkerPaste the raw body, the Stripe-Signature header and your whsec_ secret. See if they match and why not. Runs in your browser.
- Stripe webhook error decoderPaste a webhook error or an Event deliveries status (400, 401, 307, timed out). Get what it means and the fix.
- Webhook outage cost calculatorHow much money passed through while your webhook was broken, what Stripe will still retry, and whether a quiet spell in sales is normal.
- Stripe test vs live key checkerPaste the first 8 characters of a Stripe key. See if it's test or live, publishable, secret or restricted, and whether it's in the wrong place (like a secret in a NEXT_PUBLIC_ variable).