Skip to main content
WSAPI emits real-time events whenever something happens on your WhatsApp instance — new messages, status changes, group updates, calls, and more.

Delivery modes

There are two ways to receive events:
WSAPI sends an HTTP POST request to a public endpoint you configure. Best for server-based applications that already expose HTTP endpoints.
  1. Configure your instance with Webhook delivery mode and specify a Webhook URL
  2. When an event occurs, WSAPI sends a POST request with the event payload
  3. Your server processes the event and responds with a 200 status code
See Configuring Event Delivery for setup instructions.

Event payload

All events follow this structure regardless of delivery mode:
{
  "eventId": "evt_a1b2c3d4e5f67890",
  "instanceId": "ins_ABCdefGHIjk",
  "receivedAt": "2025-05-19T00:51:44.816Z",
  "eventType": "message",
  "eventData": {
    // Event-specific data
  }
}
FieldTypeDescription
eventIdstringUnique event identifier
instanceIdstringThe instance that generated the event
receivedAtstringISO 8601 timestamp when the event was received
eventTypestringThe event type (e.g., message, logged_in)
eventDataobjectEvent-specific payload

Event types

EventCategoryDescription
logged_inSessionInstance connected to WhatsApp
logged_outSessionInstance disconnected (includes reason)
login_errorSessionPairing error occurred
initial_sync_finishedSessionInitial history sync completed
messageMessagesNew message received (text, media, reaction, contact, etc.)
message_readMessagesMessage read/delivery receipt
message_deleteMessagesMessage was deleted
message_starMessagesMessage was starred/unstarred
message_history_syncMessagesOn-demand history sync messages
chat_settingChatsChat settings changed (mute, pin, read, archive, ephemeral)
chat_presenceChatsContact is typing, recording, or paused
chat_push_nameChatsContact’s push name changed
chat_statusChatsChat about/status text updated
chat_pictureChatsChat picture changed
contactContactsContact information updated
groupGroupsGroup/community settings or membership changed
newsletterNewslettersNewsletter/channel subscription or mute change
user_presenceUsersUser online/offline status changed
call_offerCallsIncoming call received
call_acceptCallsCall was accepted
call_terminateCallsCall ended
Four events are system events: logged_in, logged_out, login_error, and initial_sync_finished. System events are always delivered regardless of event filter configuration and cannot be opted out of.

Webhook delivery headers

Every webhook POST request includes the following HTTP headers:
HeaderDescription
Content-TypeAlways application/json
X-Instance-IdThe ID of the instance that generated the event
X-Webhook-SignatureHMAC-SHA256 signature of the request body. Only present when a signingSecret is configured.

Verifying event signatures

When a Signing Secret is configured for your instance, WSAPI signs every event payload using HMAC-SHA256. The signature is included in the X-Webhook-Signature header with the format:
sha256=<hex-encoded HMAC-SHA256>
Always configure a signing secret to verify the authenticity of incoming events and prevent unauthorized parties from sending fake events to your endpoint.
To verify an event:
  1. Compute the HMAC-SHA256 of the raw request body using your signing secret as the key
  2. Hex-encode the result and prepend sha256=
  3. Compare the computed value with the X-Webhook-Signature header using a constant-time comparison to prevent timing attacks
const crypto = require("crypto");

function verifySignature(body, secret, headerValue) {
  const expected =
    "sha256=" + crypto.createHmac("sha256", secret).update(body).digest("hex");
  return crypto.timingSafeEqual(
    Buffer.from(expected),
    Buffer.from(headerValue)
  );
}

Delivery and retries

  • WSAPI expects a 2xx response for webhook deliveries
  • If no valid response is received, WSAPI retries delivery up to 2 times
  • After that, the event is discarded
  • Implement idempotent processing to handle potential duplicate deliveries

Best practices

  • Respond quickly — return 200 immediately and process events asynchronously
  • Verify signatures — always validate the X-Webhook-Signature on incoming events
  • Handle duplicates — design your handler to be idempotent in case of retries
  • Filter events — use event filtering to only receive events you need
  • Use HTTPS — always use an HTTPS endpoint for your webhook URL
  • Log events — log incoming events for debugging and audit purposes