Error library

Stripe webhook signature verification failed: fix

Stripe raises this when one of the three inputs to constructEvent() is wrong: the raw request body, the Stripe-Signature header, or the endpoint secret. Pass the unmodified raw body (not parsed JSON) and the whsec_ secret for that exact endpoint.

Cause: Wrong endpoint secret (often CLI vs Dashboard secret mixed up) or a framework parsed/re-serialized the body before verification.

How to fix it

  1. Confirm the whsec_ secret matches the endpoint receiving events (Dashboard endpoint secret vs stripe listen secret are different).
  2. Pass the raw body: express.raw({type: 'application/json'}) in Express, or await req.text() in Next.js route handlers.
  3. Read the Stripe-Signature header; it should look like t=...,v1=....
  4. Use separate secrets for test and live mode endpoints, and redeploy after changing env vars.

Example

Illustrative example, not from a customer project.

- app.post('/webhook', express.json(), (req, res) => {
+ app.post('/webhook', express.raw({ type: 'application/json' }), (req, res) => {
    const sig = req.headers['stripe-signature'];
    const event = stripe.webhooks.constructEvent(req.body, sig, process.env.STRIPE_WEBHOOK_SECRET);

FAQ

It works with the Stripe CLI but fails in production. Why?

The CLI prints its own whsec_ secret. Production needs the secret of the Dashboard endpoint.

Can I just skip verification?

You shouldn't. Verification is how you know the event came from Stripe.

Get a $149 diagnosis See pricing Stripe still not live? We take it live at a fixed price.

$149Get a $149 diagnosis