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
- When a webhook is delivered, the platform computes an HMAC-SHA256 hash of the raw request body using your webhook's signing secret.
- This hash is sent as the
X-Webhook-Signatureheader. - Your endpoint recomputes the hash using the same secret and compares it to the header value.
- 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.