Payments Preflight · Check 1 of 15
Verify every webhook signature
Check that your Stripe webhook endpoint verifies the Stripe-Signature header with the raw body and your whsec_ secret before acting on any event.
What it is
Stripe signs each webhook event it sends. The Stripe-Signature header lets your server confirm the event came from Stripe and was not changed.
Why it matters
Your webhook URL is public. If it does not verify signatures, anyone can POST a fake checkout.session.completed and unlock paid features.
How to check
- Find your webhook route and look for
constructEvent(Node) or the equivalent in your Stripe library. - Confirm it reads the raw request body. A body parsed as JSON and re-serialised will not match the signature.
- Send a made-up event with
curl -X POST. It must return 400.
How to fix it
- Copy the endpoint signing secret (
whsec_) from the Dashboard, or fromstripe listenfor local work. - Read the raw body, call
stripe.webhooks.constructEvent(body, sig, secret), return 400 if it throws. - Keep the library's default timestamp tolerance (5 minutes) to limit replayed events.
// app/api/stripe/webhook/route.ts
const body = await req.text(); // raw body
const sig = req.headers.get("stripe-signature")!;
let event: Stripe.Event;
try {
event = stripe.webhooks.constructEvent(body, sig, process.env.STRIPE_WEBHOOK_SECRET!);
} catch {
return new Response("Bad signature", { status: 400 });
}Prompt for your AI coding tool
Paste into Cursor, Claude Code, Lovable or similar. Review the diff before you accept it.
Review my Stripe webhook handler. Make sure it reads the raw request body, verifies the Stripe-Signature header with stripe.webhooks.constructEvent and the STRIPE_WEBHOOK_SECRET env var, and returns 400 before doing anything else if verification fails. Do not parse the body as JSON before verifying. Show me the diff.
Sources
- Receive Stripe events in your webhook endpoint Stripe docs
- Resolve webhook signature verification errors Stripe docs
Related checks
Sponsor this page: get in touch.