Guides · Free check · $9 fix pack

Guides

How to test a Stripe webhook fix without waiting for a new payment

You found the bug (a redirect, a parsed body, the wrong signing secret), pushed a fix, and now you're waiting for the next real payment to see if it worked. You don't have to. Stripe gives you three ways to send an event to your endpoint on demand.

1. Resend the exact event that failed

This is the best test, because it's the real event your handler choked on, sent to the real endpoint. Stripe's docs list two ways (Stripe docs: Receive Stripe events in your webhook endpoint):

Get the event ID (evt_...) from the endpoint's event deliveries in the Dashboard, and the endpoint ID (we_...) from the endpoint's page. The CLI reference adds that "You must pass --webhook-endpoint=we_123456 to resend the event to a specific webhook endpoint", and that requests "run in a sandbox by default", so add --live for a live-mode event (Stripe CLI reference: events resend).

stripe events resend evt_123 --webhook-endpoint=we_123 --live

Then open the endpoint's deliveries and look for a 2xx. If it's still failing, the status code tells you what's left (7-step checklist).

Two things to know first. A manual resend "doesn't cancel Stripe's automatic retry behavior, even if it results in a 2xx status code" (source), so the same event can arrive again later; make the handler skip event IDs it has already processed (duplicate events). And if the customer already got access some other way, a resend may grant it twice unless the grant is idempotent.

2. Replay events on your own machine

To step through the handler locally, forward events with the Stripe CLI: stripe listen --forward-to localhost:4242/webhook (Stripe docs: Test webhooks with the Stripe CLI). The stripe listen command "outputs the" signing secret to use in your handler (source), and "The webhook signing secret provided will not change between restarts to the listen command" (Stripe CLI reference: listen).

That secret only works for events forwarded by the CLI. Your deployed endpoint has its own whsec_; mixing them up is a classic cause of signature failures (test vs live webhook secret). With stripe listen running, stripe events resend <event_id> without the endpoint flag sends the event "to the CLI's local webhook endpoint" (source).

3. Trigger a fresh test event

If you don't have a failed event to reuse, create one in a sandbox. stripe trigger checkout.session.completed is on the CLI's supported list, and the reference warns that "triggering events causes side effects: all necessary API objects will be created in the process" (Stripe CLI reference: trigger). Do it in a sandbox, not live.

A triggered session won't carry your app's client_reference_id or metadata, so your handler may not find a user to unlock. You can pass your own values with --add or --override, for example --add checkout_session:metadata.user_id=test_user (source). Or run one checkout in your app in a sandbox with a Stripe test card, which exercises the real flow from button to unlock.

Which one to use

What these tests don't tell you

All three send properly signed events, so they show that Stripe can reach you and your handler accepts real events. They don't show that your endpoint rejects unsigned or forged ones (can someone fake a Stripe payment?). That's one of the things the free check below tests.

Check yours in 10 seconds (free).

Paste your webhook URL. WebhookProof sends 3 harmless test requests and tells you whether Stripe can reach it and whether it rejects unsigned events. If it finds a problem, the $9 fix pack gives you the exact copy-paste fix for your stack (refundable for 14 days).

Run the free check

FAQ

How do I resend a Stripe webhook event?

In the Dashboard, open the event and click Resend (up to 15 days after the event was created), or run stripe events resend <event_id> --webhook-endpoint=<endpoint_id> with the Stripe CLI (up to 30 days). Add --live for a live-mode event.

Does resending a Stripe event stop the automatic retries?

No. Stripe says a manual resend does not cancel its automatic retry behavior, even if the resend gets a 2xx, so make your handler skip event IDs it has already processed.

Can I trigger checkout.session.completed with the Stripe CLI?

Yes, stripe trigger checkout.session.completed is supported. It creates the API objects it needs, so run it in a sandbox, and use --add or --override to set metadata your handler expects.

Why does my webhook pass with stripe listen but fail in production?

stripe listen prints its own signing secret, which only matches events the CLI forwards. Your deployed endpoint needs the whsec_ secret from that endpoint in the Dashboard.

Sources

More guides

Stripe webhook not working? Check these 7 things in order · A customer paid but didn't get access. What went wrong? · No signatures found matching the expected signature for payload · Stripe webhook failing with a 307 or 308 redirect

Last reviewed 2026-10-28. WebhookProof is an independent tool, not affiliated with Stripe, Inc.. Quotes are from the linked documentation.