Webhook signature verification failed. No signatures found matching the expected signature for payload
Stripe webhook fails signature check? Usually the wrong whsec_ secret or your framework changed the raw request body. Here's the fix.
Reviewed October 14, 2026
What it means in plain English
Stripe signs every webhook so your app can be sure it's genuine. This error means the check failed: one of the three ingredients (raw body, signature header, signing secret) is wrong.
Likely causes
- Wrong signing secret: Stripe says this is the most common cause. The CLI (
stripe listen) secret differs from the Dashboard endpoint secret. - Using a test-mode secret on a live-mode endpoint (or vice versa).
- Your framework parsed the body as JSON before verification (e.g. Express
express.json()before the webhook route, Next.js Pages Router body parser). - The env var holding the secret is missing in production.
How to fix it, step by step
- Stripe Dashboard → Workbench → Webhooks → open your production endpoint → Reveal secret. It starts
whsec_. - Put it in your host's env vars (e.g.
STRIPE_WEBHOOK_SECRET) for Production, then redeploy. - Make sure the code verifies the raw body:
- Next.js App Router: read
await req.text()and pass that string tostripe.webhooks.constructEvent. - Next.js Pages Router: disable
bodyParserfor that route and use the raw buffer. - Express: register the webhook route with
express.raw({type: 'application/json'})beforeapp.use(express.json()).
- Next.js App Router: read
- Read the signature from the
Stripe-Signatureheader (should look liket=…,v1=…). - Ask your AI tool: "Verify the Stripe webhook using the raw request body and STRIPE_WEBHOOK_SECRET; don't parse JSON first."
How to check it worked
- In Workbench → your endpoint → Event deliveries, resend a recent event; it should show 200.
- Check your server logs for the signature error disappearing.
Sources
Related fixes
Can't fix it? Get help.
If the steps didn't clear the error, send what the screen says. A person can take a look. This is a request for a paid fix, not an instant chat.