What is a webhook?#
A webhook lets your server receive an HTTP POST notification every time a lead is claimed or a direct message arrives on Lawzana. Instead of checking your dashboard manually, you can automate follow-ups, update your CRM, or trigger any workflow instantly.
Webhooks are available on Pro plans and above.
Setting up your webhook#
- Go to Settings > Integrations in your Lawzana dashboard
- Paste your webhook URL (e.g.
https://your-server.com/webhook) - Click Connect
- Save the signing secret shown on screen - it will only be displayed once
- Click Send test lead to verify everything works
Supported events#
| Event | When it fires |
|---|---|
lead.claimed |
When your firm claims a lead |
message.received |
When a direct message arrives from a potential client |
Payload format#
lead.claimed#
{
"event": "lead.claimed",
"timestamp": "2026-04-06T12:00:00.000Z",
"lead": {
"id": "abc123def",
"name": "John Smith",
"email": "[email protected]",
"phone": "+44 7700 900000",
"message": "I need help with a property dispute...",
"service": "Property Law",
"location": "London, United Kingdom",
"claimed_at": "2026-04-06T12:00:00.000Z"
}
}
message.received#
{
"event": "message.received",
"timestamp": "2026-04-06T12:00:00.000Z",
"message": {
"id": "456",
"name": "Jane Doe",
"email": "[email protected]",
"phone": "+44 7700 900001",
"message": "I would like to discuss my case...",
"service": "Family Law",
"location": "Manchester, United Kingdom",
"received_at": "2026-04-06T12:00:00.000Z"
}
}
Using with Zapier#
No code required - connect Lawzana webhooks to 5,000+ apps:
- Go to zapier.com and create a new Zap
- Choose Webhooks by Zapier as the trigger
- Select Catch Hook and copy the webhook URL Zapier gives you
- Paste the URL in Settings > Integrations in your Lawzana dashboard
- Click Send test lead to trigger Zapier's test
- Add your action (Google Sheets, Slack, email, HubSpot, etc.)
Retry policy#
If your server returns a non-2xx response, Lawzana retries up to 3 times with increasing delays:
- 1st retry: after 1 minute
- 2nd retry: after 5 minutes
- 3rd retry: after 15 minutes
If all retries fail, the delivery is marked as permanently failed. Check Delivery History in the Integrations tab to debug issues.
Delivery history#
Every webhook delivery is logged under Settings > Integrations with:
- Status code (e.g. 200, 500, timeout)
- Response time in milliseconds
- Timestamp of the attempt
- Response body for failed deliveries (to help you debug)
Use the event filter (Leads / Messages / Tests) and status filter (Success / Failed) to narrow down specific deliveries.
Troubleshooting#
403 errors with Cloudflare or bot protection#
If your webhook URL is behind Cloudflare, Sucuri, or another bot protection service, deliveries may fail with a 403 status. These services block automated HTTP requests that can't solve JavaScript challenges.
To fix this, add a firewall exception for your webhook endpoint:
Cloudflare:
- Go to Security > WAF in your Cloudflare dashboard
- Create a custom rule: When URI Path equals
/your-webhook-path, set action to Skip (skip all remaining rules) - Save and deploy the rule
Other providers: Look for a "whitelist" or "allow" option for specific URL paths, and exclude your webhook endpoint from bot protection.
Timeout errors#
If deliveries show "timeout", your server is taking longer than 10 seconds to respond. Webhook endpoints should return a 200 response immediately and process the data asynchronously (e.g. via a queue).
Advanced: Verifying the signature#
Every webhook delivery includes an X-Lawzana-Signature header containing an HMAC-SHA256 signature of the request body. You can use this to verify that the request genuinely came from Lawzana.
PHP example#
$payload = file_get_contents('php://input');
$signature = $_SERVER['HTTP_X_LAWZANA_SIGNATURE'] ?? '';
$expected = 'sha256=' . hash_hmac('sha256', $payload, $yourSecret);
if (!hash_equals($expected, $signature)) {
http_response_code(401);
exit('Invalid signature');
}
Node.js example#
const crypto = require('crypto');
function verifySignature(payload, signature, secret) {
const expected = 'sha256=' + crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(expected),
Buffer.from(signature)
);
}