Documentation Menu

Stripe webhook signature verification

Stripe signs each webhook delivery in the Stripe-Signature header. Verification must use the exact raw request body and the endpoint signing secret for the destination that received the event.

Most Stripe signature failures are caused by body parsing, an incorrect whsec_ secret, or a timestamp outside the allowed tolerance.

Requirements

  • Read the Stripe-Signature header from the incoming request.
  • Preserve the request body exactly as received before JSON parsing or re-serialization.
  • Use the endpoint signing secret, which begins with whsec_, rather than a Stripe API key.
  • Use the official Stripe SDK verification helper where one is available for your language.

Node.js example

javascript
import express from 'express';
import Stripe from 'stripe';

const app = express();
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY);

app.post('/webhooks/stripe', express.raw({ type: 'application/json' }), (req, res) => {
  try {
    const event = stripe.webhooks.constructEvent(
      req.body,
      req.headers['stripe-signature'],
      process.env.STRIPE_WEBHOOK_SECRET
    );
    res.status(200).json({ received: true, type: event.type });
  } catch (error) {
    res.status(400).send('Invalid Stripe signature');
  }
});

Why verification fails

Error patternWhat to check
No matching signatureConfirm the raw body, endpoint secret, and Stripe-Signature header.
Timestamp outside toleranceCheck server time and use a newly delivered event.
Missing headerConfirm the request came from Stripe and that proxies preserve the header.
Works locally but not in productionCompare middleware order, body decoding, and environment-specific secrets.

Diagnose with captured evidence

  1. Open the captured request and confirm the Stripe-Signature header is present.
  2. Compare the endpoint environment in Stripe with the whsec_ secret loaded by the application.
  3. Check whether the framework exposed bytes, a string, or an already parsed object to the verifier.
  4. Use the reconstruction result to identify whether extraction, digest comparison, or timestamp validation diverged.
  5. Send a new Stripe test event after changing middleware or secrets.

Verify the fix

Verification is fixed when a new Stripe delivery passes signature validation using the raw body, the handler returns 2xx, and the same event ID is not processed twice.

Was this page helpful?

Your feedback helps us improve the docs.