Webhooks allow your application to receive real-time notifications when events occur, such as incoming messages, delivery status changes, or partner invitation updates.
Zavu supports two types of webhooks:
Sender Webhooks : Receive events for a specific sender (messages, conversations)
Project Webhooks : Receive project-level events (partner invitations)
Project Webhooks
Project webhooks are ideal for receiving notifications about project-level events, such as when a partner invitation is completed. This is particularly useful if you’re using the Partner Invitations API to onboard clients.
Via Dashboard
Go to Dashboard and select your project
Navigate to Webhooks in the sidebar
In the “Project Webhook” section, click Configure
Enter your webhook URL and select the events you want to receive
Save - you’ll receive a signing secret
Via API
Configure a project webhook using the invitations API:
curl -X POST https://api.zavu.dev/v1/invitations/webhook \
-H "Authorization: Bearer zv_live_xxx" \
-H "Content-Type: application/json" \
-d '{
"url": "https://your-app.com/webhooks/zavu",
"events": ["invitation.status_changed"]
}'
Response:
{
"webhook" : {
"url" : "https://your-app.com/webhooks/zavu" ,
"events" : [ "invitation.status_changed" ],
"secret" : "whsec_abc123def456..." ,
"active" : true
}
}
Managing Project Webhooks
Get current configuration:
curl https://api.zavu.dev/v1/invitations/webhook \
-H "Authorization: Bearer zv_live_xxx"
Update webhook:
curl -X PATCH https://api.zavu.dev/v1/invitations/webhook \
-H "Authorization: Bearer zv_live_xxx" \
-H "Content-Type: application/json" \
-d '{
"url": "https://new-url.com/webhooks",
"active": true
}'
Remove webhook:
curl -X DELETE https://api.zavu.dev/v1/invitations/webhook \
-H "Authorization: Bearer zv_live_xxx"
Project Webhook Events
Event Description invitation.status_changedA partner invitation status changed (pending, in_progress, completed, cancelled)
Project Webhook Payload
{
"id" : "evt_1234567890_abc123" ,
"type" : "invitation.status_changed" ,
"timestamp" : 1705312200000 ,
"projectId" : "prj_xyz789" ,
"data" : {
"invitationId" : "inv_abc123" ,
"clientName" : "John Doe" ,
"clientEmail" : "john@example.com" ,
"currentStatus" : "completed" ,
"newSenderId" : "snd_new123" ,
"wabaAccountId" : "waba_123456"
}
}
Project webhooks are independent of sender webhooks. You can have both configured simultaneously.
Sender Webhooks
Each sender can have one webhook configured. Webhooks are managed as part of the sender resource.
Via Dashboard
Go to Dashboard and select your project
Navigate to your Sender’s settings
Click Add Webhook
Enter your webhook URL and select the events you want to receive
Save - you’ll receive a signing secret
Via API
Configure a webhook when creating a new sender:
curl -X POST https://api.zavu.dev/v1/senders \
-H "Authorization: Bearer zv_live_xxx" \
-H "Content-Type: application/json" \
-d '{
"name": "My Sender",
"phoneNumber": "+15551234567",
"webhookUrl": "https://your-app.com/webhooks/zavu",
"webhookEvents": ["message.inbound", "message.delivered", "message.failed"]
}'
Response:
{
"id" : "snd_abc123" ,
"name" : "My Sender" ,
"phoneNumber" : "+15551234567" ,
"isDefault" : false ,
"webhook" : {
"url" : "https://your-app.com/webhooks/zavu" ,
"events" : [ "message.inbound" , "message.delivered" , "message.failed" ],
"secret" : "whsec_abc123def456..." ,
"active" : true
},
"createdAt" : "2024-01-15T10:30:00.000Z"
}
Store your webhook secret securely. It’s only shown once when you create the sender with a webhook. You’ll need it to verify webhook signatures.
Available Events
Inbound (Receiving Messages)
Event Description conversation.newFirst message from a new contact (new conversation started) message.inboundA customer sent you a message
Outbound (Delivery Tracking)
Event Description message.queuedYour message was queued for delivery message.sentYour message was sent to the carrier message.deliveredYour message was delivered to the recipient message.failedMessage delivery failed
Templates
Event Description template.status_changedA WhatsApp template status changed (draft, pending, approved, rejected)
Partner Invitations (Project Webhook)
Event Description invitation.status_changedA partner invitation status changed (pending, in_progress, completed, cancelled)
The invitation.status_changed event is delivered via Project Webhooks , not Sender Webhooks. See the Project Webhooks section above for configuration.
Subscribe to message.inbound to receive all customer messages. Add conversation.new to get notified when a new contact messages you for the first time (useful for lead tracking). The outbound events are optional and used for tracking delivery status.
Webhook Payload
All webhook payloads follow the same structure:
{
"id" : "evt_1234567890_abc123" ,
"type" : "message.inbound" ,
"timestamp" : 1705312200000 ,
"senderId" : "snd_abc123" ,
"projectId" : "prj_xyz789" ,
"data" : {
// Event-specific data
}
}
Field Description idUnique event identifier typeEvent type (e.g., message.inbound) timestampUnix timestamp in milliseconds senderIdThe Sender that received this event projectIdYour project ID dataEvent-specific payload
Handling Webhooks
Your webhook endpoint must:
Respond with 2xx status within 30 seconds
Verify the signature to ensure the request is from Zavu
Process asynchronously for long-running tasks
TypeScript (Express)
Python (Flask)
import express from "express" ;
const app = express ();
app . post ( "/webhooks/zavu" , express . json (), ( req , res ) => {
// 1. Verify signature (see Security guide)
const signature = req . headers [ "x-zavu-signature" ];
if ( ! verifySignature ( signature , req . body , process . env . WEBHOOK_SECRET )) {
return res . status ( 401 ). send ( "Invalid signature" );
}
// 2. Acknowledge receipt immediately
res . status ( 200 ). send ( "OK" );
// 3. Process the event asynchronously
const event = req . body ;
processEvent ( event ). catch ( console . error );
});
async function processEvent ( event ) {
switch ( event . type ) {
case "message.inbound" :
await handleInboundMessage ( event . data );
break ;
case "message.delivered" :
await handleDeliveryConfirmation ( event . data );
break ;
case "message.failed" :
await handleDeliveryFailure ( event . data );
break ;
}
}
Retry Policy
If your endpoint returns an error or doesn’t respond within 30 seconds, Zavu will retry the delivery:
Attempt Delay 1st retry 1 minute 2nd retry 5 minutes 3rd retry 15 minutes 4th retry 1 hour 5th retry 4 hours
After 5 failed attempts, the webhook delivery is marked as failed. You can view failed deliveries in the Dashboard.
Managing Webhooks
Update Webhook Configuration
Update your sender’s webhook settings:
curl -X PATCH https://api.zavu.dev/v1/senders/snd_abc123 \
-H "Authorization: Bearer zv_live_xxx" \
-H "Content-Type: application/json" \
-d '{
"webhookUrl": "https://new-url.com/webhooks",
"webhookEvents": ["message.inbound"],
"webhookActive": true
}'
Disable Webhook
curl -X PATCH https://api.zavu.dev/v1/senders/snd_abc123 \
-H "Authorization: Bearer zv_live_xxx" \
-H "Content-Type: application/json" \
-d '{
"webhookActive": false
}'
Remove Webhook
Set webhookUrl to null to remove the webhook:
curl -X PATCH https://api.zavu.dev/v1/senders/snd_abc123 \
-H "Authorization: Bearer zv_live_xxx" \
-H "Content-Type: application/json" \
-d '{
"webhookUrl": null
}'
Regenerate Secret
If your webhook secret is compromised:
curl -X POST https://api.zavu.dev/v1/senders/snd_abc123/webhook/secret \
-H "Authorization: Bearer zv_live_xxx"
Response:
{
"secret" : "whsec_new_secret_here..."
}
Next Steps