Stripe: webhook signature verification failing [2026 fix]

Webhook signature verification fails when endpoint_secret is missing or mismatched. Copy the correct signing secret from Dashboard and pass it to verifyHeader().

Stripe: webhook signature verification failing [2026 fix]

TL;DR

Cause: Your webhook endpoint is using the wrong or missing endpoint_secret (signing secret from Stripe Dashboard). Fix: Copy the correct signing secret from Stripe Dashboard → Developers → Webhooks → select endpoint → "Signing secret" and pass it to stripe.webhooks.constructEvent().

---

Real Console Error Messages

These are the exact errors you'll see at 2am:

``` Error: No signatures found matching the expected signature for payload. computed signature=<hash>, attempted signature versions=[v1] ```

``` StripeSignatureVerificationError: No signatures found matching the expected signature for payload at Function.constructEvent (/node_modules/stripe/lib/webhooks.js:104:15) ```

``` Webhook Error: error decoding event request body: json: cannot unmarshal string into Go struct field Event.created of type int64 ```

``` stripe.error.SignatureVerificationError: No signatures found matching the expected signature for payload ```

``` Fatal error: HMAC verification failed. Expected signature header 'stripe-signature' not found. ```

---

Broken Code vs. Exact Fix

❌ BROKEN (Most Common)

```javascript // webhook.js - WRONG const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);

app.post('/webhook', express.raw({type: 'application/json'}), (req, res) => { // ❌ Missing endpoint_secret parameter const event = stripe.webhooks.constructEvent( req.body, req.headers['stripe-signature'], // MISSING: endpoint_secret here! ); res.json({received: true}); }); ```

✅ FIXED

```javascript // webhook.js - CORRECT const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);

app.post('/webhook', express.raw({type: 'application/json'}), (req, res) => { // ✅ Pass the signing secret from Stripe Dashboard const event = stripe.webhooks.constructEvent( req.body, req.headers['stripe-signature'], process.env.STRIPE_WEBHOOK_SECRET // ← Copy from Dashboard ); res.json({received: true}); }); ```

❌ BROKEN (Wrong Secret Used)

```javascript // ❌ Using publishable key instead of webhook signing secret const event = stripe.webhooks.constructEvent( req.body, req.headers['stripe-signature'], process.env.STRIPE_PUBLISHABLE_KEY // WRONG! This is not a signing secret ); ```

✅ FIXED

```javascript // ✅ Use ONLY the webhook endpoint's signing secret const event = stripe.webhooks.constructEvent( req.body, req.headers['stripe-signature'], process.env.STRIPE_WEBHOOK_SECRET // From: Dashboard → Webhooks → select endpoint → "Signing secret" ); ```

❌ BROKEN (String Body Instead of Raw)

```javascript // ❌ Using express.json() instead of express.raw() app.post('/webhook', express.json(), (req, res) => { // This converts body to string, breaking HMAC verification const event = stripe.webhooks.constructEvent( req.body, // ❌ Already parsed, signature fails req.headers['stripe-signature'], process.env.STRIPE_WEBHOOK_SECRET ); }); ```

✅ FIXED

```javascript // ✅ MUST use express.raw() to preserve raw bytes for HMAC app.post('/webhook', express.raw({type: 'application/json'}), (req, res) => { const event = stripe.webhooks.constructEvent( req.body, // ✅ Still raw buffer, HMAC verifies req.headers['stripe-signature'], process.env.STRIPE_WEBHOOK_SECRET ); }); ```

---

How to Find Your Signing Secret

1. Go to [Stripe Dashboard](https://dashboard.stripe.com) 2. Navigate: Developers → Webhooks 3. Find your endpoint URL in the list 4. Click on it 5. Scroll to Signing secret section 6. Click Reveal 7. Copy the secret starting with whsec_ 8. Add to .env: ``` STRIPE_WEBHOOK_SECRET=whsec_test_xxxxxxxxxxxx ``` 9. Restart your server 10. Test with stripe trigger payment_intent.succeeded --skip-confirmation

---

Version-Specific Notes

Stripe Node.js SDK (v8.0.0+): The constructEvent() method signature is consistent. However, we cannot guarantee behavior in versions prior to v7.0.0—if you're on an older version, upgrade with npm install stripe@latest.

Express.js: The express.raw() middleware requirement applies to Express 4.16.0+. Older versions may need body-parser middleware instead.

---

Still broken? Check these too

1. Webhook endpoint is offline: Stripe retries for 3 days. Check server logs. If your endpoint crashed, [related guide: debugging Express 500 errors](/?guide=express-errors).

2. Multiple webhook endpoints configured: You have one signing secret *per endpoint*. Verify you're using the secret matching your exact URL, not another endpoint's secret.

3. Body middleware conflict: Ensure no global express.json() middleware processes the webhook route *before* express.raw(). Move webhook route to top of middleware stack or use route-specific middleware: [related: middleware ordering](/?guide=middleware-order).

4. Stripe CLI testing without secret: If testing locally with stripe listen, the CLI auto-generates a signing secret. When you run stripe listen --forward-to localhost:3000/webhook, it prints the secret—use that exact value.

5. Environment variable not loaded: Confirm process.env.STRIPE_WEBHOOK_SECRET is populated by logging it (never log in production). Check .env file format: no quotes, no spaces.

---

Official Documentation

[Stripe Webhook Signing (Official Docs)](https://stripe.com/docs/webhooks/signatures)

---

Found a different variation? Drop it in the comments below—we'll add it to this guide.

🔥 0d
LIVE
↓ PlanetScale rage spiking •⚠ Vercel pricing complaints •↑ Railway gaining fast •↑ Supabase happiness rising •↑ Resend loved by devs •↓ PlanetScale rage spiking •⚠ Vercel pricing complaints •↑ Railway gaining fast •↑ Supabase happiness rising
DEVELOPER PAIN RADAR // Loading...

Developers complain.
Opportunities appear.

We track what developers are struggling with today — and what opportunities that creates.

—
guides today
—
avg happiness
🔥 Pain
📖 Guides
🔭 Explore
👤 Mine
🔥 Pain Radar — rage scores today
↗ share
💡 Opportunity Feed — pain = market gap
📈 Tool Momentum
all scores →
📖 Latest Guide
all guides →
📖 All Guides
📊 Tool Scores
+ Submit
📰 Hacker News
➕ Submit a Tool
← back