Each webhook has an auto-generated signing secret. Use it to verify that incoming payloads are authentic and haven't been tampered with.
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.
X-Webhook-Signature header.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);crypto.timingSafeEqual (or equivalent) to prevent timing attacks.