Skip to main content
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.