Skip to content

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 two headers:

HeaderValue
X-SendAPI-EventThe event type, e.g. message.received.
X-SendAPI-SignatureThe HMAC-SHA256 hex digest of the raw request body, signed with your webhook secret. No sha256= prefix.
javascript
const crypto = require('crypto');

function verifyWebhook(rawBody, signature, secret) {
  const expected = crypto
    .createHmac('sha256', secret)
    .update(rawBody)
    .digest('hex');
  return crypto.timingSafeEqual(
    Buffer.from(signature, 'hex'),
    Buffer.from(expected, 'hex')
  );
}

Event Payload Structure

All webhook events share a common envelope:

json
{
  "event": "message.received",
  "timestamp": "2026-03-09T14:30:00Z",
  "data": { ... }
}

Message Events

message.received

Fired when an inbound WhatsApp message arrives at your session.

json
{
  "event": "message.received",
  "timestamp": "2026-03-09T14:30:00Z",
  "data": {
    "message_id": 14,
    "session_id": 8,
    "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.

json
{
  "event": "message.sent",
  "timestamp": "2026-03-09T14:30:01Z",
  "data": {
    "message_id": 14,
    "session_id": 8,
    "to": "+14155552671",
    "type": "text",
    "status": "sent"
  }
}

message.delivered

Fired when the message is delivered to the recipient's device (double grey checkmark).

json
{
  "event": "message.delivered",
  "timestamp": "2026-03-09T14:30:22Z",
  "data": {
    "message_id": 14,
    "session_id": 8,
    "delivered_at": "2026-03-09T14:30:22Z"
  }
}

message.read

Fired when the recipient opens and reads the message (blue checkmarks).

json
{
  "event": "message.read",
  "timestamp": "2026-03-09T14:31:05Z",
  "data": {
    "message_id": 14,
    "session_id": 8,
    "read_at": "2026-03-09T14:31:05Z"
  }
}

message.failed

Fired when a message delivery fails permanently.

json
{
  "event": "message.failed",
  "timestamp": "2026-03-09T14:30:05Z",
  "data": {
    "message_id": 14,
    "session_id": 8,
    "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.

json
{
  "event": "session.connected",
  "timestamp": "2026-03-09T14:30:00Z",
  "data": {
    "session_id": 8,
    "phone_number": "+447700900000"
  }
}

session.disconnected

Fired when a session loses connection. reconnecting: true means the SDK will attempt to recover automatically.

json
{
  "event": "session.disconnected",
  "timestamp": "2026-03-09T15:00:00Z",
  "data": {
    "session_id": 8,
    "reason": "connection_lost",
    "reconnecting": true
  }
}

session.qr_updated

Fired when a new QR code is generated for a session (e.g., previous one expired).

json
{
  "event": "session.qr_updated",
  "timestamp": "2026-03-09T14:32:00Z",
  "data": {
    "session_id": 8,
    "qr_code": "data:image/png;base64,iVBORw0KGgoAAAA..."
  }
}

Group Events

group.participant_added

json
{
  "event": "group.participant_added",
  "data": {
    "session_id": 8,
    "group_id": 3,
    "participant": "+250788000000",
    "added_by": "+447700900000"
  }
}

group.participant_removed

json
{
  "event": "group.participant_removed",
  "data": {
    "session_id": 8,
    "group_id": 3,
    "participant": "+14155552671",
    "removed_by": "+447700900000"
  }
}

Retry Policy

Webhook deliveries are retried with exponential backoff if your endpoint returns a non-2xx status or doesn't respond within 10 seconds. 4 attempts total:

AttemptDelay since previous attempt
1 (initial)Immediate
25 seconds
330 seconds
42 minutes

If all 4 fail, the delivery is recorded as failed in your dashboard. View GET /v1/webhooks/{id}/deliveries to inspect failed attempts.

Released under the MIT License.