Every webhook request includes an X-Webhook-Signature header containing an HMAC-SHA256 signature. You should always verify this signature before processing the payload to ensure the request came from SendKit.
How it works
SendKit signs the JSON payload using your webhook’s signing secret:
HMAC-SHA256(JSON payload, signing_secret)
The resulting hex digest is sent in the X-Webhook-Signature header.
Verification examples
import crypto from 'crypto';
import express from 'express';
const app = express();
// Important: use raw body for signature verification
app.use(express.json({
verify: (req, res, buf) => { req.rawBody = buf.toString(); }
}));
const verify = (rawBody, signature, secret) => {
const expected = crypto
.createHmac('sha256', secret)
.update(rawBody)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expected)
);
};
app.post('/webhooks/sendkit', (req, res) => {
const signature = req.headers['x-webhook-signature'];
const secret = process.env.SENDKIT_WEBHOOK_SECRET;
if (!verify(req.rawBody, signature, secret)) {
return res.status(401).send('Invalid signature');
}
// Process the event
console.log(req.body.type);
res.status(200).send('OK');
});
Rotating secrets
You can rotate your webhook’s signing secret at any time from the dashboard. After rotation, use the new secret to verify future deliveries. Previous deliveries will still show the old signature in logs.
After rotating a secret, update your application immediately. Requests signed with the old secret will fail verification.