Keep the original body intact.
Read the raw body once, before JSON middleware transforms it. Object key order, spaces and line endings matter to a signature, even when two JSON documents mean the same thing.
const rawBody = await request.text();
const signature = request.headers.get("stripe-signature");
if (!signature) return new Response(null, { status: 400 });
let event;
try {
event = stripe.webhooks.constructEvent(
rawBody, signature, process.env.STRIPE_WEBHOOK_SECRET
);
} catch {
return new Response(null, { status: 400 });
}
// Only now accept the verified event for durable processing.This assumes the official Stripe server SDK and server-only secret are already configured. Do not log the body or secret while debugging.
Check which endpoint created the signature.
An API key is not a webhook signing secret. Match the destination, environment and signing secret rather than copying whichever secret is nearest. A CLI forwarding listener and a registered dashboard endpoint can use different signing secrets.
Try the local signature debugger with a development delivery. It reports the signature match separately from timestamp freshness, so an old sample does not look like a new valid delivery.
Check time without disabling the check.
A correctly signed old payload should not pass a live freshness check. Use a fresh development delivery and check the receiving server’s clock. Do not remove replay protection to make a captured payload pass.
Our debugger uses a five-minute absolute window to expose both stale and future-dated samples. Production verification belongs in the official SDK with your reviewed tolerance and clock configuration.
Test one changed byte.
Verify a known development delivery, then add a space to the raw body. The changed payload must fail. Check a wrong secret too. Finally confirm that verification success still leads to durable processing; a matching signature does not grant access by itself.
Reference: Stripe’s signature error guide. For failures after acknowledgement, read Webhook returns 200, but nothing happens.