Skip to main content
This page covers the exact payload for each WhatsApp event. Register your endpoint and verify signatures as described in the general Webhooks guide first. Every event is wrapped the same way:
{
  "event": "message.received",
  "data": { ... }
}

message.received

Fired when a customer sends you a WhatsApp message.
{
  "event": "message.received",
  "data": {
    "message_id": "5a9e6f1c-9e2f-4b1c-8a5c-7e8f9a0b1c2d",
    "wamid": "wamid.HBgMOTE5ODc2NTQzMjEwFQIAEhg...",
    "from": "+919876543210",
    "type": "text",
    "text": "What are your store hours?",
    "timestamp": "2026-07-14T18:22:04Z"
  }
}
message_id is Tanvik’s internal ID (same one GET /v1/messages/{id} uses); wamid is WhatsApp’s own message ID.

message.status

Fired on each status transition of a message you sent via the API.
{
  "event": "message.status",
  "data": {
    "message_id": "5a9e6f1c-9e2f-4b1c-8a5c-7e8f9a0b1c2d",
    "status": "delivered",
    "timestamp": "2026-07-14T18:22:41Z"
  }
}
status is one of sent, delivered, read, failed. On failed, an additional error string is included with the reason.

otp.verified

Fired when a customer successfully verifies an OTP.
{
  "event": "otp.verified",
  "data": {
    "otp_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "to": "+919876543210",
    "verified_at": "2026-07-14T18:24:10Z"
  }
}
This only fires on success. A wrong or expired code doesn’t trigger a webhook — check the Verify OTP response directly for that.

template.status

Fired when a submitted template transitions to approved or rejected. It does not fire on every sync check — only on the actual status change.
{
  "event": "template.status",
  "data": {
    "template_id": "9c858901-8a57-4791-81fe-4c455b099bc9",
    "name": "order_shipped",
    "status": "approved"
  }
}
On rejected, a rejection_reason string is included with Meta’s explanation.