Why it happens
Fulfilment runs off the webhook — checkout.session.completed, or payment_intent.succeeded — and the app either does not listen for that event, listens on a route that is not deployed, or handles it and throws before writing anything.
How to tell
- Deliveries answered 200 but nothing written; or answered 500 at the time of each payment.
- The endpoint's event list does not include the completed event.
- An error in the handler for every payment, grouped under one fingerprint.
The fix
- Subscribe the endpoint to checkout.session.completed, and to payment_intent.succeeded if you use intents directly.
- Make the handler idempotent: record the Stripe event id, do the work, answer 200; answer 200 again for a duplicate.
- Replay the missed events from Stripe for the window.
The prompt for your builder
Paste this into Lovable, Bolt, Cursor, Claude Code or whatever built the app. Replace anything in capitals. It never asks you to paste a secret into a chat; keys go into your host’s environment, by you.
Make my Stripe webhook handler fulfil orders on checkout.session.completed: find the order by the session's client_reference_id or metadata, mark it paid, send the confirmation, and store the Stripe event id so a replayed event is ignored. Return 200 only after the database write succeeds, and 500 with a logged reason if it fails so Stripe retries.
How Keelnest catches it
When the handler fails, Stripe keeps retrying, and Revenue Guard opens an incident once deliveries are still failing after an hour; error capture groups the handler's error under one fingerprint. Revenue Guard also reads the endpoint's event list every hour and opens an incident when it does not listen for completed payments or cancellations your account is sending. A handler that answers 200 and writes nothing still looks healthy from Stripe's side.
Know the moment this happens.
Keelnest watches your production app every five minutes and tells you in plain English what broke — with the fix. Free for your first app.
Related
- Stripe disabled your webhook endpointPayments succeed in Stripe, but your app never marks them paid. The endpoint in Stripe's dashboard says Disabled.The fix
- Payments stop after a deployCheckout reaches the pay step and stalls, or orders never show as paid — and it started right after a publish.The fix