Webhook API
The Webhook API allows you to receive real-time notifications when events occur in your Zaits account.
Base URL
https://api.zaits.net/v1/webhooksAuthentication
All requests require your API key in the Authorization header:
Authorization: Bearer YOUR_API_KEYHow Webhooks Work
Register an endpoint - Provide a URL on your server to receive events
Select events - Choose which events you want to be notified about
Receive notifications - We'll send POST requests to your endpoint when events occur
Verify & process - Verify the webhook signature and process the event
Create Webhook Endpoint
Register a new webhook endpoint to receive notifications.
Endpoint
POST /v1/webhooks/endpointsParameters
url
string
✅
Your webhook endpoint URL (must be HTTPS)
events
array
✅
Array of event types to subscribe to
description
string
❌
Description of the endpoint
active
boolean
❌
Whether endpoint is active (default: true)
Request Example
curl -X POST https://api.zaits.net/v1/webhooks/endpoints \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://your-app.com/webhooks/zaits",
"events": ["document.signed", "face.verified", "ocr.completed"],
"description": "Main production webhook",
"active": true
}'const response = await fetch('https://api.zaits.net/v1/webhooks/endpoints', {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({
url: 'https://your-app.com/webhooks/zaits',
events: ['document.signed', 'face.verified', 'ocr.completed'],
description: 'Main production webhook',
active: true
})
});
const result = await response.json();import requests
response = requests.post(
'https://api.zaits.net/v1/webhooks/endpoints',
headers={
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json'
},
json={
'url': 'https://your-app.com/webhooks/zaits',
'events': ['document.signed', 'face.verified', 'ocr.completed'],
'description': 'Main production webhook',
'active': True
}
)
result = response.json()Response
{
"success": true,
"data": {
"id": "we_abc123xyz",
"url": "https://your-app.com/webhooks/zaits",
"events": ["document.signed", "face.verified", "ocr.completed"],
"description": "Main production webhook",
"secret": "whsec_1234567890abcdef",
"active": true,
"created_at": "2024-01-15T10:00:00Z"
}
}Important: Save the secret value! You'll need it to verify webhook signatures. It's only shown once when creating the endpoint.
List Webhook Endpoints
Get all your configured webhook endpoints.
Endpoint
GET /v1/webhooks/endpointsQuery Parameters
active
boolean
Filter by active status
page
number
Page number (default: 1)
per_page
number
Items per page (default: 25)
Request Example
curl -X GET "https://api.zaits.net/v1/webhooks/endpoints?active=true" \
-H "Authorization: Bearer YOUR_API_KEY"Response
{
"success": true,
"data": [
{
"id": "we_abc123xyz",
"url": "https://your-app.com/webhooks/zaits",
"events": ["document.signed", "face.verified"],
"description": "Main production webhook",
"active": true,
"created_at": "2024-01-15T10:00:00Z",
"last_delivery": "2024-01-15T14:30:00Z",
"success_rate": 0.98
}
],
"pagination": {
"page": 1,
"per_page": 25,
"total": 3
}
}Update Webhook Endpoint
Update an existing webhook endpoint configuration.
Endpoint
PUT /v1/webhooks/endpoints/{endpoint_id}Parameters
url
string
❌
New webhook URL
events
array
❌
Updated event subscriptions
description
string
❌
Updated description
active
boolean
❌
Enable/disable endpoint
Request Example
curl -X PUT https://api.zaits.net/v1/webhooks/endpoints/we_abc123xyz \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"events": ["document.signed", "document.expired", "face.verified"],
"active": true
}'Response
{
"success": true,
"data": {
"id": "we_abc123xyz",
"url": "https://your-app.com/webhooks/zaits",
"events": ["document.signed", "document.expired", "face.verified"],
"active": true,
"updated_at": "2024-01-15T15:00:00Z"
}
}Delete Webhook Endpoint
Remove a webhook endpoint.
Endpoint
DELETE /v1/webhooks/endpoints/{endpoint_id}Request Example
curl -X DELETE https://api.zaits.net/v1/webhooks/endpoints/we_abc123xyz \
-H "Authorization: Bearer YOUR_API_KEY"Response
{
"success": true,
"data": {
"message": "Webhook endpoint deleted successfully",
"endpoint_id": "we_abc123xyz"
}
}Test Webhook Endpoint
Send a test event to verify your endpoint is working.
Endpoint
POST /v1/webhooks/endpoints/{endpoint_id}/testParameters
event_type
string
❌
Event type to test (default: "test")
Request Example
curl -X POST https://api.zaits.net/v1/webhooks/endpoints/we_abc123xyz/test \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"event_type": "document.signed"
}'Response
{
"success": true,
"data": {
"test_sent": true,
"response_status": 200,
"response_time": 145,
"response_body": "OK"
}
}Get Webhook Deliveries
View the delivery history for a webhook endpoint.
Endpoint
GET /v1/webhooks/endpoints/{endpoint_id}/deliveriesQuery Parameters
status
string
Filter by status: success, failed
event_type
string
Filter by event type
page
number
Page number
per_page
number
Items per page
Request Example
curl -X GET "https://api.zaits.net/v1/webhooks/endpoints/we_abc123xyz/deliveries?status=failed" \
-H "Authorization: Bearer YOUR_API_KEY"Response
{
"success": true,
"data": [
{
"id": "del_xyz789",
"event_id": "evt_abc123",
"event_type": "document.signed",
"status": "failed",
"attempts": 3,
"response_status": 500,
"response_time": 2045,
"error_message": "Internal server error",
"created_at": "2024-01-15T14:30:00Z",
"last_attempt": "2024-01-15T14:35:00Z"
}
],
"pagination": {
"page": 1,
"per_page": 25,
"total": 12
}
}Available Events
Get a list of all webhook event types you can subscribe to.
Endpoint
GET /v1/webhooks/eventsRequest Example
curl -X GET https://api.zaits.net/v1/webhooks/events \
-H "Authorization: Bearer YOUR_API_KEY"Response
{
"success": true,
"data": {
"events": [
{
"name": "document.signed",
"description": "Document has been signed by a signer",
"category": "signing"
},
{
"name": "document.completed",
"description": "All signers have signed the document",
"category": "signing"
},
{
"name": "document.expired",
"description": "Document signing period has expired",
"category": "signing"
},
{
"name": "face.verified",
"description": "Face verification completed",
"category": "face"
},
{
"name": "face.liveness.detected",
"description": "Liveness detection completed",
"category": "face"
},
{
"name": "ocr.completed",
"description": "OCR processing completed",
"category": "ocr"
},
{
"name": "ocr.id.extracted",
"description": "ID card data extracted",
"category": "ocr"
},
{
"name": "user.credits.low",
"description": "User credits below threshold",
"category": "account"
},
{
"name": "api.rate.limited",
"description": "API rate limit exceeded",
"category": "system"
}
]
}
}Webhook Payload Format
All webhook events are sent as POST requests with this format:
Headers
Content-Type: application/json
X-Zaits-Signature: sha256=1234567890abcdef...
X-Zaits-Event: document.signed
X-Zaits-Delivery: del_xyz789Body
{
"id": "evt_abc123xyz",
"type": "document.signed",
"created": 1642251600,
"data": {
"document_id": "doc_abc123",
"signer": {
"email": "[email protected]",
"name": "John Doe"
},
"signed_at": "2024-01-15T14:30:00Z",
"ip_address": "192.168.1.1"
}
}Webhook Security
Verifying Webhook Signatures
To ensure webhooks are from Zaits, verify the signature:
const crypto = require('crypto');
function verifyWebhookSignature(payload, signature, secret) {
const expectedSignature = crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex');
return `sha256=${expectedSignature}` === signature;
}
// Express.js example
app.post('/webhooks/zaits', express.raw({type: 'application/json'}), (req, res) => {
const signature = req.headers['x-zaits-signature'];
const secret = 'whsec_1234567890abcdef'; // Your webhook secret
if (!verifyWebhookSignature(req.body, signature, secret)) {
return res.status(401).send('Invalid signature');
}
const event = JSON.parse(req.body);
// Process the event
switch(event.type) {
case 'document.signed':
handleDocumentSigned(event.data);
break;
// ... handle other events
}
res.status(200).send('OK');
});import hmac
import hashlib
from flask import Flask, request, abort
app = Flask(__name__)
def verify_webhook_signature(payload, signature, secret):
expected_signature = hmac.new(
secret.encode('utf-8'),
payload,
hashlib.sha256
).hexdigest()
return f'sha256={expected_signature}' == signature
@app.route('/webhooks/zaits', methods=['POST'])
def webhook():
signature = request.headers.get('X-Zaits-Signature')
secret = 'whsec_1234567890abcdef' # Your webhook secret
if not verify_webhook_signature(request.data, signature, secret):
abort(401)
event = request.json
# Process the event
if event['type'] == 'document.signed':
handle_document_signed(event['data'])
# ... handle other events
return 'OK', 200<?php
function verifyWebhookSignature($payload, $signature, $secret) {
$expectedSignature = 'sha256=' . hash_hmac('sha256', $payload, $secret);
return hash_equals($expectedSignature, $signature);
}
// Get the raw POST body
$payload = file_get_contents('php://input');
$signature = $_SERVER['HTTP_X_ZAITS_SIGNATURE'];
$secret = 'whsec_1234567890abcdef'; // Your webhook secret
if (!verifyWebhookSignature($payload, $signature, $secret)) {
http_response_code(401);
die('Invalid signature');
}
$event = json_decode($payload, true);
// Process the event
switch($event['type']) {
case 'document.signed':
handleDocumentSigned($event['data']);
break;
// ... handle other events
}
http_response_code(200);
echo 'OK';
?>Webhook Retry Policy
If your endpoint fails to respond successfully:
Initial attempt - Sent immediately when event occurs
First retry - After 1 minute
Second retry - After 5 minutes
Third retry - After 30 minutes
Final retry - After 2 hours
After 5 failed attempts, the webhook delivery is marked as failed.
Successful Response
Your endpoint should return a 2xx status code (200-299) within 10 seconds.
Failed Response
Any of these constitute a failed delivery:
Non-2xx status code
Timeout (>10 seconds)
Connection error
Invalid SSL certificate
Best Practices
Endpoint Implementation
Return quickly - Process webhooks asynchronously
Idempotency - Handle duplicate events gracefully
Order - Don't assume events arrive in order
Verification - Always verify webhook signatures
HTTPS only - Use SSL/TLS for security
Error Handling
Return 200 OK immediately, process async
Log all webhook events for debugging
Implement retry logic for your own processing
Monitor webhook delivery success rate
Security
Keep webhook secrets secure
Rotate secrets periodically
Whitelist Zaits IP addresses if possible
Validate event data before processing
Next: Usage & Analytics API
Last updated