Skip to content

Signing & Verification

Every webhook delivery includes a signature so your server can verify that the request came from Tolinku and was not modified in transit.

  1. Tolinku serializes the JSON payload body.
  2. It computes an HMAC-SHA256 hash using your webhook’s signing secret.
  3. The hex-encoded hash is sent in the X-Webhook-Signature header.
  4. The event type is sent in the X-Webhook-Event header.

Your server should compute the same HMAC and compare it to the header value.

import crypto from 'crypto';
function verifyWebhook(payload, signature, secret) {
const expected = crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expected)
);
}
// In your Express handler:
app.post('/webhooks/tolinku', express.raw({ type: 'application/json' }), (req, res) => {
const signature = req.headers['x-webhook-signature'];
const event = req.headers['x-webhook-event'];
if (!verifyWebhook(req.body, signature, process.env.TOLINKU_WEBHOOK_SECRET)) {
return res.status(401).send('Invalid signature');
}
const payload = JSON.parse(req.body);
console.log(`Received ${event}:`, payload.data);
res.status(200).send('OK');
});
  • The signature is computed on the raw request body (the exact bytes sent), not on a parsed and re-serialized JSON object. Use the raw body for HMAC computation.
  • If your web framework automatically parses JSON, you need to configure it to also preserve the raw body (as shown in the Express example above with express.raw()).
  • The signing secret starts with whsec_. Store it as an environment variable, not in your source code.