Skip to content

Verification

Each webhook has an auto-generated signing secret. Use it to verify that incoming payloads are authentic and haven't been tampered with.

Signing Secrets

The signing secret is optional - not all webhook receivers verify signatures. If your receiver does verify, use the secret to validate the X-Webhook-Signature header. You can rotate the secret anytime from Admin > Webhooks.

How Verification Works

  1. When a webhook is delivered, the platform computes an HMAC-SHA256 hash of the raw request body using your webhook's signing secret.
  2. This hash is sent as the X-Webhook-Signature header.
  3. Your endpoint recomputes the hash using the same secret and compares it to the header value.
  4. If they match, the payload is authentic.

Node.js Example

const crypto = require('crypto');

function verifyWebhook(body, signature, secret) {
  const expected = crypto
    .createHmac('sha256', secret)
    .update(body)
    .digest('hex');
  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expected)
  );
}

// In your webhook handler:
const rawBody = req.body; // raw string, not parsed JSON
const sig = req.headers['x-webhook-signature'];
if (!verifyWebhook(rawBody, sig, YOUR_WEBHOOK_SECRET)) {
  return res.status(401).send('Invalid signature');
}
const payload = JSON.parse(rawBody);

Important Notes

Always verify against the raw request body (string), not parsed JSON. Parsing and re-serializing may change whitespace or key ordering.
  • Use crypto.timingSafeEqual (or equivalent) to prevent timing attacks.
  • If you rotate a signing secret, update your endpoint before the next delivery.