If your webhook endpoint doesn't verify the signature, yes. Anyone who learns the URL can send a hand-written checkout.session.completed and your app will believe it.
Webhook paths are predictable (/api/webhooks/stripe), appear in tutorials and AI-generated code, and leak in public repos and front-end bundles. Treat the URL as public.
Stripe signs every event with the endpoint's secret in the Stripe-Signature header. Verify it with the official library and reject anything that fails (Stripe docs; Stripe docs: signatures). The signature includes a timestamp, and Stripe's libraries reject events older than 5 minutes by default, which limits replays (source).
payment_status, as Stripe's fulfillment guide does (Stripe docs: Fulfill orders). A forged event can't fake the API response.livemode doesn't match your environment.Send an unsigned POST to your own endpoint: curl -i -X POST -H 'content-type: application/json' -d '{}' https://yourdomain.com/api/webhooks/stripe. A correct endpoint answers 400. A 200 means it accepts unsigned events. WebhookProof's free check does this with a harmless synthetic event.
Paste your webhook URL. WebhookProof sends 3 harmless test requests and tells you whether Stripe can reach it and whether it rejects unsigned events.
Run the free checkOnly if your endpoint skips signature verification. Verify the Stripe-Signature header with the endpoint secret and reject anything that fails.
No. Webhook paths are predictable and often leak. Signature verification is what protects you.
Send an unsigned POST with an empty JSON body to your own endpoint. It should return 400. A 200 means it accepts unverified events.
Stripe webhook not working? Check these 7 things in order · A customer paid but didn't get access. What went wrong? · Stripe webhook signature verification failed · Stripe webhook getting a 307 or 308 redirect
Last reviewed 2026-10-18. WebhookProof is an independent tool, not affiliated with Stripe, Inc. Quotes are from the linked documentation.