Skip to main content

Signature Verification

Every webhook request is signed. Always verify the X-Notifo-Signature header before processing the payload.

How the signature is computed

secretHash = SHA-256( rawSecret )
signature = "sha256=" + HMAC-SHA256( key=secretHash, data=requestBody )

rawSecret is the value shown once when you create the webhook.

Verification examples

const crypto = require('crypto');

// Use express.raw() so req.body is a Buffer (raw bytes — required for correct HMAC)
app.post('/webhooks/notifo', express.raw({ type: 'application/json' }), (req, res) => {
const sig = req.headers['x-notifo-signature'];
const rawBody = req.body; // Buffer

const secretHash = crypto.createHash('sha256').update(YOUR_SIGNING_SECRET).digest('hex');
const expected = 'sha256=' + crypto.createHmac('sha256', secretHash).update(rawBody).digest('hex');

if (!crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected))) {
return res.status(401).send('Invalid signature');
}

const event = JSON.parse(rawBody);
console.log(event.event, event.messageId, event.status);
res.sendStatus(200);
});
Important

Always use the raw request body bytes for HMAC computation. Parsing JSON first and re-serializing will change byte order and invalidate the signature.