Security

Learn how to secure your webhook endpoints and validate webhook signatures.

Signature Verification

Every webhook request includes an X-Zellify-Signature header containing an HMAC SHA-256 hash of the raw request body computed using your webhook secret.

Always validate webhook signatures before processing any webhook data.

JavaScript / TypeScript (Node.js)

import crypto from 'crypto';
import express from 'express';

function verifyWebhookSignature(rawBody: Buffer, signature: string, secret: string): boolean {
  const computed = crypto.createHmac('sha256', secret).update(rawBody).digest('hex');
  const a = Buffer.from(computed, 'hex');
  const b = Buffer.from(signature || '', 'hex');
  return a.length === b.length && crypto.timingSafeEqual(a, b);
}

const app = express();

// Capture raw body for signature verification
app.use(express.json({
  verify: (req: any, _res, buf) => { req.rawBody = buf; }
}));

app.post('/webhooks', (req: any, res) => {
  const signature = req.header('X-Zellify-Signature') || '';
  const isValid = verifyWebhookSignature(req.rawBody, signature, process.env.ZELLIFY_WEBHOOK_SECRET || '');
  if (!isValid) return res.status(401).json({ error: 'Invalid signature' });
  // Process the webhook...
  res.status(200).json({ received: true });
});

Python (Flask)

PHP

Best practices:

  • Validate the signature using the raw request body (not parsed JSON)

  • Use timing-safe comparison (timingSafeEqual, compare_digest, hash_equals)

  • Keep your secret in environment variables and rotate periodically

Last updated