Fix Stripe Webhook in Express

In Express, middleware order is everything. If express.json() runs before your webhook route, it consumes the raw body and Stripe's signature check fails.

The fix — middleware order in app.js

// app.js — register webhook routes BEFORE express.json()
import webhookRouter from './routes/webhooks.js';

// ✓ Webhook routes first — with raw body parser
app.use('/api/webhooks', express.raw({ type: 'application/json' }), webhookRouter);

// ✓ JSON parser after — for all other routes
app.use(express.json());
app.use('/api', otherRoutes);

The complete webhook handler

// routes/webhooks.js
import express from 'express';
import Stripe from 'stripe';

const router = express.Router();
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY);
const secret = process.env.STRIPE_WEBHOOK_SECRET;

router.post('/stripe', express.raw({ type: 'application/json' }), (req, res) => {
  const sig = req.headers['stripe-signature'];

  if (!sig) {
    return res.status(400).json({ error: 'Missing stripe-signature header' });
  }

  let event;
  try {
    // req.body is a Buffer when using express.raw()
    event = stripe.webhooks.constructEvent(req.body, sig, secret);
  } catch (err) {
    return res.status(400).json({ error: \`Webhook Error: \${err.message}\` });
  }

  switch (event.type) {
    case 'checkout.session.completed':
      // fulfill order
      break;
    case 'customer.subscription.deleted':
      // cancel subscription
      break;
  }

  res.json({ received: true });
});

export default router;
Using bodyParser separately? The old pattern was bodyParser.raw() from the body-parser package. Since Express 4.16+, express.raw() is built in — no separate package needed.

Verify middleware order

# Quick check — log which middleware runs on the webhook route
app.use('/api/webhooks', (req, res, next) => {
  console.log('Content-Type:', req.headers['content-type']);
  console.log('Body type:', typeof req.body, Buffer.isBuffer(req.body) ? '(Buffer)' : '');
  next();
});

If body type shows object instead of Buffer, express.json() ran first. Fix the route registration order.

Generate the complete Express handler with correct middleware order.

Open WebhookFix →
For informational purposes only. Always test in staging before production. MetricLogic accepts no responsibility for issues arising from use of these tools. © 2026 MetricLogic.
HttpFixer by MetricLogic · Blog · All Tools · Generators MIT · GitHub →