← Back to all snippets
JAVASCRIPT

Processing Incoming Webhooks with Node.js and Express

Learn to set up a Node.js Express server to securely receive and process incoming webhooks, including signature verification for data integrity.

const express = require('express');
const bodyParser = require('body-parser');
const crypto = require('crypto'); // For HMAC verification

const app = express();
const port = 3000;

// IMPORTANT: Use raw body for webhook verification if signature uses it.
// body-parser can parse JSON as buffer if needed:
app.use(bodyParser.json({
  verify: (req, res, buf) => {
    req.rawBody = buf; // Store raw body for signature verification
  }
}));

// Secret key provided by the webhook sender (e.g., Stripe, GitHub)
const WEBHOOK_SECRET = 'your_secret_webhook_key'; // Replace with a strong, secret key from your provider environment variable

app.post('/webhook-endpoint', (req, res) => {
  // For providers like Stripe, signature is in headers (e.g., 'stripe-signature')
  // For simplicity, let's assume a generic `x-webhook-signature` header and HMAC-SHA256
  const signature = req.headers['x-webhook-signature'];

  if (!signature || !req.rawBody) {
    console.error('Webhook: Missing signature or raw body.');
    return res.status(400).send('Webhook Error: Missing signature or body.');
  }

  try {
    const hmac = crypto.createHmac('sha256', WEBHOOK_SECRET);
    hmac.update(req.rawBody);
    const expectedSignature = hmac.digest('hex');

    if (expectedSignature !== signature) {
      console.error('Webhook: Signature mismatch!');
      return res.status(403).send('Webhook Error: Invalid signature.');
    }

    // Signature is valid, process the webhook payload
    const event = req.body;
    console.log('Received valid webhook event:', event.type, event.id);

    // Example processing based on event type
    if (event.type === 'order.created') {
      console.log('New order received:', event.data.orderId);
      // Perform actions like updating database, sending notifications, etc.
    } else if (event.type === 'payment.succeeded') {
      console.log('Payment succeeded for:', event.data.customerId);
    }

    res.status(200).send('Webhook received successfully.');
  } catch (error) {
    console.error('Error processing webhook:', error.message);
    res.status(500).send('Webhook Error: Internal server error.');
  }
});

app.listen(port, () => {
  console.log(`Webhook listener running on http://localhost:${port}`);
});

// To test locally, you'll need a tool like ngrok to expose your local server
// to the internet, then configure your webhook provider to send events to
// your ngrok URL + /webhook-endpoint
How it works: This Node.js Express snippet demonstrates how to set up an endpoint to receive and securely process incoming webhooks. It uses `body-parser` to ensure the raw request body is available for signature verification. The core security measure involves calculating an HMAC-SHA256 signature of the raw payload using a shared secret and comparing it against the signature provided in the request header. If signatures match, the webhook is considered authentic and its payload can be safely processed, enabling real-time event-driven communication between services.

Need help integrating this into your project?

Our team of expert developers can help you build your custom application from scratch.

Hire DigitalCodeLabs