Webhooks Setup & Events
Webhooks Setup & Events
Webhooks notify your application in real time when document events occur.
Setting up a webhook
- Go to Dashboard → Settings → Webhooks
- Click Add endpoint
- Enter your HTTPS endpoint URL
- Select which events to subscribe to (or select "All events")
- Copy the signing secret — you'll use it to verify payloads
Available events
Event | Fired when |
|---|---|
| A new document is created |
| Any status transition |
| A signer or payer opens their link |
| A signer completes signing |
| Payment is confirmed |
| Document reaches |
Webhook payload
{
"event": "document.signed",
"timestamp": "2026-04-15T15:00:00Z",
"data": {
"id": "doc_abc123",
"type": "signable",
"status": "all_signed",
"title": "NDA — Acme Corp",
"docUrl": "https://zipzign.com/sign/doc_abc123",
"pdfUrl": "https://zipzign.com/pdf/doc_abc123",
"amount": null,
"currency": null,
"payerEmail": null,
"payerName": null,
"signers": [
{
"id": "sgn_1",
"name": "Alice",
"email": "alice@example.com",
"status": "signed",
"signedAt": "2026-04-15T15:00:00Z"
}
],
"metadata": { "clientId": "client_789" },
"sandbox": false,
"createdAt": "2026-04-15T12:00:00Z",
"updatedAt": "2026-04-15T15:00:00Z"
}
}
Verifying webhook signatures
Each webhook request includes an X-ZipZign-Signature header. Verify it to ensure the payload is genuine:
const crypto = require('crypto');
function verifyWebhook(payload, signature, secret) {
const expected = crypto
.createHmac('sha256', secret)
.update(payload, 'utf8')
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(expected),
Buffer.from(signature)
);
}
// Express example
app.post('/webhooks/zipzign', express.raw({ type: 'application/json' }), (req, res) => {
const sig = req.headers['x-zipzign-signature'];
const isValid = verifyWebhook(req.body, sig, process.env.ZIPZIGN_WEBHOOK_SECRET);
if (!isValid) {
return res.status(401).send('Invalid signature');
}
const event = JSON.parse(req.body);
if (event.event === 'document.completed') {
// Handle completion
}
res.status(200).send('OK');
});
Retry behavior
- ZipZign retries failed webhook deliveries (non-2xx response) up to 5 times with exponential backoff
- Retries occur at: 30s, 2m, 10m, 1h, 4h after initial failure
- After 5 failed attempts, the delivery is marked failed
Best practices
- Respond with
200immediately, then process asynchronously - Use the
idfield to deduplicate events (retries send the same payload) - Always verify the HMAC signature before processing
Updated on: 16/04/2026
Thank you!