WhatsApp Webhook Events
SendAPI fires HTTP POST requests to your webhook URL whenever something happens on your WhatsApp sessions. All payloads are signed with HMAC-SHA256 for verification.
Webhook Security
Every webhook request includes an X-SendAPI-Signature header containing the HMAC-SHA256 signature of the raw request body, signed with your webhook secret.
const crypto = require('crypto');
function verifyWebhook(rawBody, signature, secret) {
const expected = crypto
.createHmac('sha256', secret)
.update(rawBody)
.digest('hex');
return `sha256=${expected}` === signature;
}Event Payload Structure
All webhook events share a common envelope:
{
"event": "message.received",
"timestamp": "2026-03-09T14:30:00Z",
"data": { ... }
}Message Events
message.received
Fired when an inbound WhatsApp message arrives at your session.
{
"event": "message.received",
"timestamp": "2026-03-09T14:30:00Z",
"data": {
"message_id": "msg_01H8...QP",
"session_id": "sess_01H8BKF...Z2T",
"from": "+447700900000",
"type": "text",
"content": { "body": "Hi, I need help with my order." },
"received_at": "2026-03-09T14:30:00Z"
}
}message.sent
Fired when an outbound message is confirmed sent to WhatsApp servers.
{
"event": "message.sent",
"timestamp": "2026-03-09T14:30:01Z",
"data": {
"message_id": "msg_01H8...QP",
"session_id": "sess_01H8BKF...Z2T",
"to": "+14155552671",
"type": "text",
"status": "sent"
}
}message.delivered
Fired when the message is delivered to the recipient's device (double grey checkmark).
{
"event": "message.delivered",
"timestamp": "2026-03-09T14:30:22Z",
"data": {
"message_id": "msg_01H8...QP",
"session_id": "sess_01H8BKF...Z2T",
"delivered_at": "2026-03-09T14:30:22Z"
}
}message.read
Fired when the recipient opens and reads the message (blue checkmarks).
{
"event": "message.read",
"timestamp": "2026-03-09T14:31:05Z",
"data": {
"message_id": "msg_01H8...QP",
"session_id": "sess_01H8BKF...Z2T",
"read_at": "2026-03-09T14:31:05Z"
}
}message.failed
Fired when a message delivery fails permanently.
{
"event": "message.failed",
"timestamp": "2026-03-09T14:30:05Z",
"data": {
"message_id": "msg_01H8...QP",
"session_id": "sess_01H8BKF...Z2T",
"error_code": "131026",
"error_message": "Message undeliverable: recipient is not a WhatsApp user."
}
}Session Events
session.connected
Fired when a device scans the QR code and the session becomes active.
{
"event": "session.connected",
"timestamp": "2026-03-09T14:30:00Z",
"data": {
"session_id": "sess_01H8BKF...Z2T",
"phone_number": "+447700900000"
}
}session.disconnected
Fired when a session loses connection. reconnecting: true means the SDK will attempt to recover automatically.
{
"event": "session.disconnected",
"timestamp": "2026-03-09T15:00:00Z",
"data": {
"session_id": "sess_01H8BKF...Z2T",
"reason": "connection_lost",
"reconnecting": true
}
}session.qr_updated
Fired when a new QR code is generated for a session (e.g., previous one expired).
{
"event": "session.qr_updated",
"timestamp": "2026-03-09T14:32:00Z",
"data": {
"session_id": "sess_01H8BKF...Z2T",
"qr_code": "data:image/png;base64,iVBORw0KGgoAAAA..."
}
}Group Events
group.participant_added
{
"event": "group.participant_added",
"data": {
"session_id": "sess_01H8BKF...Z2T",
"group_id": "grp_01H9...XT",
"participant": "+250788000000",
"added_by": "+447700900000"
}
}group.participant_removed
{
"event": "group.participant_removed",
"data": {
"session_id": "sess_01H8BKF...Z2T",
"group_id": "grp_01H9...XT",
"participant": "+14155552671",
"removed_by": "+447700900000"
}
}Retry Policy
Webhook deliveries are retried up to 4 times with exponential backoff if your endpoint returns a non-2xx status:
| Attempt | Delay |
|---|---|
| 1 (initial) | Immediate |
| 2 | 5 seconds |
| 3 | 30 seconds |
| 4 | 2 minutes |
| 5 | 10 minutes |
After 5 failed attempts, the delivery is marked as failed and no further retries are made. Check the Webhook logs in your dashboard to review failed deliveries and retry them manually.