Webhooks
Webhooks allow you to receive real-time notifications when events happen in ezylegal. Instead of polling the API, you can subscribe to events and receive HTTP callbacks when something changes.
How Webhooks Work
- You provide a webhook URL when creating a session (or configure a default in your Partner Dashboard)
- When an event occurs, ezylegal sends an HTTP POST request to your URL
- Your server processes the event and returns a 2xx response
- If delivery fails, ezylegal retries with exponential backoff
Quick Start
1. Create a Webhook Endpoint
Set up an endpoint on your server to receive webhooks:
// Express.js example
app.post('/webhooks/ezyfamily', express.json(), (req, res) => {
const event = req.body;
switch (event.event) {
case 'session.completed':
handleSessionCompleted(event.data);
break;
case 'session.pdf_ready':
handlePdfReady(event.data);
break;
default:
console.log('Unhandled event:', event.event);
}
res.status(200).send('OK');
});
2. Specify the URL When Creating Sessions
curl -X POST https://api.ezy-forms.com.au/v1/sessions \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"form_type": "financial_statement",
"customer_email": "[email protected]",
"webhook_url": "https://yourapp.com/webhooks/ezyfamily"
}'
3. Verify Webhook Signatures
Always verify that webhooks came from ezylegal:
const crypto = require('crypto');
function verifySignature(payload, signature, secret) {
const expectedSignature = crypto
.createHmac('sha256', secret)
.update(payload, 'utf8')
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expectedSignature)
);
}
See Webhook Security for complete verification examples.
Event Types
| Event | Description |
|-------|-------------|
| session.accessed | Customer opened the form for the first time |
| session.section_completed | A form section was completed |
| session.completed | Form fully submitted |
| session.pdf_ready | PDF document generated |
| session.expired | Session expired without completion |
See Webhook Events for detailed payload examples.
Webhook Payload Format
All webhook payloads follow this structure:
{
"event": "session.completed",
"session_id": "sess_abc123xyz",
"timestamp": "2024-01-16T14:22:00Z",
"data": {
// Event-specific data
}
}
Headers
| Header | Description |
|--------|-------------|
| Content-Type | Always application/json |
| X-Webhook-Signature | HMAC-SHA256 signature |
| X-Webhook-ID | Unique delivery ID |
| X-Webhook-Timestamp | Unix timestamp of delivery |
Retry Behavior
If your endpoint doesn't return a 2xx status code, ezylegal will retry:
| Attempt | Delay | |---------|-------| | 1 | Immediate | | 2 | 1 minute | | 3 | 5 minutes | | 4 | 30 minutes | | 5 | 2 hours | | 6 | 8 hours | | 7 | 24 hours |
After 7 failed attempts, the webhook is marked as failed and no more retries occur.
Retry Headers
On retry attempts, these headers are included:
| Header | Description |
|--------|-------------|
| X-Webhook-Retry-Count | Current attempt number (0-6) |
| X-Webhook-Original-Timestamp | Timestamp of first attempt |
Best Practices
1. Respond Quickly
Return a 200 response as fast as possible. Process webhooks asynchronously:
app.post('/webhooks/ezyfamily', async (req, res) => {
// Acknowledge immediately
res.status(200).send('OK');
// Process asynchronously
await processWebhookAsync(req.body);
});
2. Handle Duplicates
Webhooks may be delivered more than once. Use the X-Webhook-ID header to deduplicate:
const processedWebhooks = new Set();
app.post('/webhooks/ezyfamily', async (req, res) => {
const webhookId = req.headers['x-webhook-id'];
if (processedWebhooks.has(webhookId)) {
return res.status(200).send('Already processed');
}
processedWebhooks.add(webhookId);
// Process webhook...
});
3. Verify Signatures
Always verify webhook signatures to ensure authenticity. See Security.
4. Use HTTPS
Webhook URLs must use HTTPS in production. HTTP is only allowed for localhost during development.
Testing Webhooks
Local Development
Use a tunneling service to test webhooks locally:
# Using ngrok
ngrok http 3000
# Your webhook URL becomes:
# https://abc123.ngrok.io/webhooks/ezyfamily
Manual Testing
You can trigger test webhooks from the Partner Dashboard:
- Go to Settings → Webhooks
- Click Send Test Webhook
- Select an event type
- View the delivery result
Troubleshooting
Webhook Not Received
- Check your endpoint is accessible from the internet
- Verify HTTPS is configured correctly
- Check firewall rules allow incoming requests
- Review webhook delivery logs in Partner Dashboard
Signature Verification Failing
- Ensure you're using the raw request body (not parsed JSON)
- Check your webhook secret is correct
- Verify you're using HMAC-SHA256
Processing Errors
- Check your server logs for exceptions
- Ensure your database can handle the incoming data
- Verify your async job queue is processing
Related Guides
- Webhook Events - All event types and payloads
- Webhook Security - Signature verification
- Integration Guide - Complete integration patterns