Stripe webhook: "No signatures found matching the expected signature for payload"

Exact error
No signatures found matching the expected signature for payload. Are you passing the raw request body you received from Stripe?
Also appears as (1)
  • Webhook payload must be provided as a string or a Buffer ... Payload was provided as a parsed JavaScript object instead.
Manually verified CI: pending

We reproduced the error and confirmed the fix on our own test machine on the date shown. Nightly CI re-runs are not running yet. How we verify.

Last verified
Re-test due
Published
Repro
7 files, hashes public
Fix ID
APP-19
Environment and versions
osDebian 13 (container)
node20.19.2
express5.3.0
stripe23.0.1 (stripe-node)

In brief

Stripe signs the raw request bytes, and your server changes them before verification. The full fix gives the exact Express route order and body handling, the secret checks, and our 4-case test table.

Get the full fix ↓

Symptom

You added Stripe Checkout to an app built with Cursor, Bolt or Lovable, with a Node/Express or Next.js backend. Payments go through, but your webhook endpoint returns 400, and your logs show one of these:

No signatures found matching the expected signature for payload. Are you passing the raw request body you received from Stripe?
Webhook payload must be provided as a string or a Buffer ... Payload was provided as a parsed JavaScript object instead.

So orders never get marked as paid.

Why it happens

  • Stripe signs the exact bytes it sends. stripe.webhooks.constructEvent() needs those same, untouched bytes, plus the signing secret (whsec_...) for that endpoint.
  • AI-generated servers usually add app.use(express.json()) at the top. That turns the body into an object before your webhook code sees it:
    • Passing that object gives the "must be provided as a string or a Buffer" error.
    • "Fixing" it with JSON.stringify(req.body) creates different bytes, which gives "No signatures found".
  • A wrong secret gives the same "No signatures found" error (e.g. the Stripe CLI's secret instead of the dashboard endpoint's, or test vs live).

What we could not test

  • Real Stripe deliveries, the Stripe CLI (stripe listen), and test vs live secrets in a real account.
  • Next.js App Router and Pages Router, Vercel serverless body handling, and other frameworks.
  • Proxies that rewrite the body.

The full fix

$4

The free part of this page tells you what's wrong. The full fix tells you exactly what to do. It includes:

  • Step-by-step fix, safest option first (the full page is 495 words)
  • 2 copy-paste blocks of commands, config or code
  • How to check it worked
  • Our test record from Oct 26, 2026: what we ran and what happened

Launching soon. Checkout isn't open yet; prices may change at launch. Join the waitlist. You can check what you'll get: SHA-256 of the full fix 98c0a7ca9438f66c… (how to check).

Sources

  1. Stripe docs: resolve webhook signature verification errors
  2. Stack Overflow: No signatures found matching the expected signature for payload
  3. Stack Overflow: Webhook payload must be provided as a string or a Buffer
  4. Stack Overflow: webhook with Stripe and Next.js 13
  5. Stack Overflow: Stripe webhook error on Next.js / Vercel
  6. vercel/next.js#49739

How this page was made

Drafted by an AI agent and reproduced on our test machine on Oct 26, 2026. The scripts and logs are in the repro bundle; their file hashes are public on the repro page. Human review: not yet. No warranty: try fixes on a copy or staging environment first. Machine-readable versions: Markdown · JSON.

Found a mistake or a newer version where this breaks? Tell us.