Webhooks can be used to receive notifications about events occurring in DocuSeal. They allow you to automatically synchronize data between DocuSeal and your application or receive real-time event notifications.
For example, you can use webhooks to get notified when templates are created or updated, or when documents are signed. Services like Zapier, Make.com and n8n also work seamlessly with DocuSeal Webhooks.
Every webhook request is signed with an HMAC-SHA256 signature, sent as the X-Docuseal-Signature header. This proves the request came from DocuSeal and hasn’t been tampered with in transit.
To get your signing secret, click the Security button in the top right corner of the webhook page and open the HMAC tab. Click the masked input to reveal the full whsec_... value, then copy it.
The signature header has the format [timestamp].[signature]. The signed content is [timestamp].[raw_body]. To verify, recompute the HMAC and compare it with the received signature using a constant-time comparison.
const crypto = require('crypto');
function verifyWebhook(req, secret) {
const header = req.headers['x-docuseal-signature'];
if (!header) return false;
const [timestamp, signature] = header.split('.', 2);
// Reject stale requests (5 minute tolerance)
if (Math.abs(Date.now() / 1000 - Number(timestamp)) > 300) return false;
// Recompute the signature over `${timestamp}.${rawBody}`
const expected = crypto
.createHmac('sha256', secret)
.update(`${timestamp}.${req.rawBody}`)
.digest('hex');
return (
expected.length === signature.length &&
crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(signature))
);
}
You need the raw request body — the exact bytes DocuSeal sent — not a re-serialized JSON object. If your framework parses and re-serializes the body before you can read it, the signature will not match even when the JSON content is semantically identical. Always verify against the exact bytes received on the wire.