Webhooks

Event delivery from wa-server to your backend. This page separates Device vs Messaging webhooks and explains delivery semantics in detail.

Quick Summary

  • Two families of events: Device and Messaging.
  • All deliveries use an envelope: { event, device_id, app_id, payload, timestamp, request_id }.
  • Messaging webhooks include direction for inbound vs outbound.
  • Receipts report delivered, read, or played when available.
  • Identifiers are JIDs; phone numbers are not guaranteed.

Setup Flow

  1. Set webhook_path on the App (example: /webhooks/wa).
  2. Optionally set domain_url on the App or configure WEBHOOK_BASE_URL.
  3. Store the generated webhook_secret and verify signatures.
  4. Deduplicate using request_id to handle retries.

If no webhook is set for an App, events are skipped for its devices.

Delivery & Ordering

  • Webhooks are asynchronous; events may arrive delayed or out of order.
  • Retry behavior depends on your HTTP responses; use request_id to deduplicate.
  • Do not assume every WhatsApp event will be delivered; network/privacy can omit fields.

Envelope

Field Type Description
event string Event name.
device_id string Device UUID.
app_id string Owning App UUID.
payload object Event-specific payload.
timestamp string ISO8601 event time.
request_id string Trace ID for idempotency.

Device Webhooks

Device events describe lifecycle changes. Use these for UI state, reconnect flows, and monitoring.

Event When Key fields What to do
device_qr_generated QR created/regenerated status, qr_expires_at Show QR to user; re-scan if expired.
device_connected Link complete status, wa_number, wa_device_jid, linked_at Mark device ready; allow sending.
device_disconnected Disconnected (no destroy) status Trigger reconnect or prompt rescan.
device_destroyed Device removed status Cleanup downstream state/media.

Device Webhook Examples

device_qr_generated

{
  "event": "device_qr_generated",
  "device_id": "dev_example123",
  "app_id": "app_example123",
  "timestamp": "2026-01-03T12:39:00Z",
  "request_id": "...",
  "payload": {
    "status": "qr_generated",
    "qr_expires_at": "2026-01-03T12:41:00Z"
  }
}

device_connected

{
  "event": "device_connected",
  "device_id": "dev_example123",
  "app_id": "app_example123",
  "timestamp": "2026-01-10T02:10:52Z",
  "request_id": "...",
  "payload": {
    "status": "connected",
    "wa_number": "6285211112222",
    "wa_lid": "9876543210987654321@lid",
    "wa_device_jid": "6285211112222:1@s.whatsapp.net",
    "linked_at": "2026-01-10T02:10:52Z"
  }
}

device_disconnected

{
  "event": "device_disconnected",
  "device_id": "dev_example123",
  "app_id": "app_example123",
  "timestamp": "2026-01-03T12:45:00Z",
  "request_id": "...",
  "payload": { "status": "disconnected" }
}

device_destroyed

{
  "event": "device_destroyed",
  "device_id": "dev_example123",
  "app_id": "app_example123",
  "timestamp": "2026-01-03T12:50:00Z",
  "request_id": "...",
  "payload": { "status": "destroyed" }
}

Messaging Webhooks

Messaging events include inbound/outbound messages, receipts, presence, chat presence, message revokes, and session warnings.

Event When Key fields Notes
message Message received/sent chat, from, wa_number, message_id, direction, text, message_type, is_group, media_path, media_mime_type, caption, media_size, media_filename, contact_name, contact_vcard, latitude, longitude, location_name, location_address Complete information: message_type (text/image/video/audio/document/sticker/location/contact), is_group (true for group messages). For media: media_mime_type (e.g., image/jpeg), caption (if present), media_size (bytes), media_filename (for documents). For contact: contact_name, contact_vcard. For location: latitude, longitude, location_name, location_address. text contains message text or caption. media_path is set when media download succeeds. Use GET /media?path={media_path} to download. For groups: chat is group JID (@g.us), from is sender JID (inbound) or device JID (outbound).
receipt Delivery/read update wa_number, chat, from, message_ids, receipt, timestamp Use chat/from to map to the peer; message_sender appears for group receipts.
presence Availability changes (1:1) from, last_seen, unavailable Use for online/last-seen signals.
chat_presence Typing/recording states chat, state, media state is composing/paused; media indicates audio/text.
message_revoked Message revoked wa_number, chat, from, message_id Remove or mark deleted in UI.
warning / logout Session issues reason, code/expires Alert ops and reconnect.

Media Information in Message Webhooks

For media messages (image, video, audio, document, sticker), the webhook payload includes comprehensive media metadata:

Field Type Description Example
message_type string Type of message: text, image, video, audio, document, sticker, location, contact "image"
media_mime_type string MIME type of the media file (only for media messages) "image/jpeg", "video/mp4", "application/pdf"
caption string Caption text for image/video/document messages (if present) "Check out this photo"
media_size number Size of media file in bytes (only for media messages) 245678
media_filename string Original filename for document messages (if available) "report.pdf"
media_path string Path to downloaded media file (if download succeeded). Use GET /media?path={media_path} to download. "media/app-id/device-id-message-id.bin"
text string Message text or caption (for media with caption, this contains the caption) "Hello" or "Image caption"

Note: All media fields are optional and only present when applicable. For text messages, only message_type and text are set. For media messages, all relevant fields are included.

Video Messages (message_type: "video")

Video messages include all standard media fields plus video-specific information:

  • message_type: Always "video"
  • media_mime_type: Typically "video/mp4" or "video/quicktime"
  • media_size: File size in bytes
  • caption: Optional caption text (if video has caption)
  • text: Contains caption text if present, otherwise empty
  • media_path: Path to downloaded video file (if download succeeded)
  • is_view_once: true if video is view-once, false otherwise

Video download: Use GET /media?path={media_path} to download the video file. The video is automatically downloaded when received.

Audio Messages (message_type: "audio")

Audio messages include all standard media fields plus audio-specific information:

  • message_type: Always "audio"
  • media_mime_type: Typically "audio/mpeg", "audio/ogg", "audio/aac", or "audio/opus"
  • media_size: File size in bytes
  • media_path: Path to downloaded audio file (if download succeeded)
  • ptt: true if audio is a voice note (push-to-talk), false if regular audio file
  • is_view_once: true if audio is view-once (rare), false otherwise

Audio types: Audio messages can be either regular audio files or voice notes (PTT/push-to-talk). Voice notes are typically shorter recordings sent in real-time, while regular audio files are longer-form audio content. Use GET /media?path={media_path} to download the audio file.

Document Messages (message_type: "document")

Document messages include all standard media fields plus document-specific information:

  • message_type: Always "document"
  • media_mime_type: MIME type of the document (e.g., application/pdf, application/vnd.openxmlformats-officedocument.wordprocessingml.document for .docx, application/vnd.ms-excel for .xls, etc.)
  • media_size: File size in bytes
  • media_filename: Original filename of the document (e.g., report.pdf, invoice.xlsx)
  • caption: Optional caption text (if document has caption)
  • text: Contains caption text if present, otherwise empty
  • media_path: Path to downloaded document file (if download succeeded)
  • is_view_once: true if document is view-once (rare), false otherwise

Supported document types: PDF, Word (.doc, .docx), Excel (.xls, .xlsx), PowerPoint (.ppt, .pptx), text files, ZIP archives, and other document formats. Use GET /media?path={media_path} to download the document file.

Sticker Messages (message_type: "sticker")

Sticker messages include all standard media fields plus sticker-specific information:

  • message_type: Always "sticker"
  • media_mime_type: Typically "image/webp" for WhatsApp stickers (sticker format is WebP)
  • media_size: File size in bytes (stickers are typically small, under 100KB)
  • media_path: Path to downloaded sticker file (if download succeeded)
  • is_view_once: false for stickers (stickers cannot be view-once)

Sticker format: WhatsApp stickers use WebP format and are typically animated or static images. Stickers don't support captions. Use GET /media?path={media_path} to download the sticker file.

Location Messages (message_type: "location")

Location messages include geographical coordinate information:

  • message_type: Always "location"
  • latitude: Latitude coordinate (decimal degrees, -90 to 90)
  • longitude: Longitude coordinate (decimal degrees, -180 to 180)
  • location_name: Optional name of the location (e.g., "National Monument", "Restaurant ABC")
  • location_address: Optional address of the location (e.g., "Jakarta, Indonesia", "123 Main St, City")
  • text: Contains location name if available, otherwise displays "📍 Location"

Location coordinates: Location messages always include latitude and longitude. The location_name and location_address fields are optional and only present when provided in the original message. Use these coordinates to display the location on a map.

Live Location: When someone shares live location, each location update will be received as a separate location message through the webhook. You can track live location sharing by monitoring consecutive location messages from the same sender arriving at regular intervals (typically every few seconds). The updates continue until the sharing duration expires (15 minutes, 1 hour, or 8 hours) or is manually stopped. Note: Currently, sending live location programmatically is not supported - users must share live location manually through the WhatsApp app. See Live Location Documentation for more details.

Contact and Location Information in Message Webhooks

For contact and location messages, the webhook payload includes specific fields:

Contact Messages (message_type: "contact")

Field Type Description Example
contact_name string Display name of the contact "John Doe"
contact_vcard string vCard data in standard vCard format (contains phone numbers, email, etc.). Can contain multiple phone numbers (multiple TEL fields). "BEGIN:VCARD\nVERSION:3.0\nFN:John Doe\nTEL;TYPE=CELL:+6281234567890\nTEL;TYPE=WORK:+6289876543210\nEND:VCARD"

Auto-farming: When a contact message is received, the system automatically extracts all phone numbers from the vCard and fetches their profile data (push name, business name, LID, phone JID) in the background. This data is stored in the identities table for future JID/LID mapping.

Location Messages (message_type: "location")

Field Type Description Example
latitude number Latitude coordinate of the location -6.175392
longitude number Longitude coordinate of the location 106.827153
location_name string Name of the location (if provided) "National Monument"
location_address string Address of the location (if provided) "Jakarta, Indonesia"

Note: All contact and location fields are optional and only present when available in the message.

Direction (Inbound vs Outbound)

  • direction = inbound means peer → device.
  • direction = outbound means device → peer.
  • Outbound can come from API sends or from the device's WhatsApp app.

Mapping guidance:

  • Inbound: chat is the peer (or group), from is the sender.
  • Outbound: chat is the peer (or group), from is the device JID.
  • Groups: chat is the group JID and from is the participant JID.

Group Messages vs Individual Messages

All message webhooks include the is_group field to distinguish between group and individual (1-on-1) messages.

Individual Messages (is_group: false)

  • chat field: Contains the peer's phone JID (format: 6281234567890@s.whatsapp.net)
  • from field: For inbound: sender's JID (same as chat). For outbound: device JID
  • is_group field: Always false
  • Media information: Complete media metadata is included (same as group messages)

Group Messages (is_group: true)

  • chat field: Contains the group JID (format: 1203630...@g.us)
  • from field: For inbound: sender's JID within the group. For outbound: device JID
  • is_group field: Always true
  • LID support: Both chat_lid and from_lid may be present for privacy
  • Media information: Complete media metadata is included (same as individual messages)

Important: All message types (text, image, video, audio, document, sticker, location, contact) work identically for both individual and group messages. The only difference is the is_group flag and the JID format in chat and from fields.

Read/Delivered/Played (Appearance)

Receipt webhooks report delivery state for outbound messages.

  • receipt = server: WhatsApp accepted the message (sent).
  • receipt = delivered: message delivered to recipient device.
  • receipt = read: recipient opened/read message.
  • receipt = played: voice note/video viewed (when applicable).

Use message_ids in the payload to update your local status. Fields chat and from are JIDs and can be LIDs; treat them as opaque IDs.

Receipt availability depends on WhatsApp settings and network; absence of a receipt does not imply failure.

JID and LID (Must Read)

  • Phone JID: 15551234567@s.whatsapp.net
  • LID (privacy ID): lid_example@lid
  • Groups: 1203630...-...@g.us

Webhook fields chat and from are JIDs and may be LIDs. Treat them as opaque strings. Do not parse to numeric or assume a phone number is available.

When WhatsApp hides phone numbers, you will only receive LID. This is normal and expected.

Best practice: store the raw JID/LID and map it to a contact record later when a phone JID appears.

When Messages Come From the WhatsApp App (Not API)

  • Messages sent from the device’s own WhatsApp app still trigger the message webhook.
  • They arrive with direction = outbound and chat pointing to the peer.
  • from typically contains the device JID (e.g., 15550000001:1@s.whatsapp.net).
  • LIDs are common here too; do not assume phone numbers exist.

If an outbound message arrives with a LID, keep it and update your mapping later when a phone JID is observed in future messages or receipts.

Message Webhook Examples

Message webhooks are organized by message type. Each type includes examples for individual (1-on-1) and group conversations, with both inbound (received) and outbound (sent) directions.

Text Messages

Individual - Inbound

{
  "event": "message",
  "device_id": "dev_example123",
  "app_id": "app_example123",
  "timestamp": "2026-01-10T02:15:00Z",
  "request_id": "...",
  "payload": {
    "wa_number": "6285211112222",
    "from": "6281234567890@s.whatsapp.net",
    "from_lid": "1234567890987654321@lid",
    "chat": "6281234567890@s.whatsapp.net",
    "chat_lid": "1234567890987654321@lid",
    "message_id": "ABCD123456789",
    "direction": "inbound",
    "message_type": "text",
    "text": "Hello John",
    "is_group": false,
    "is_view_once": false
  }
}

Individual - Outbound

{
  "event": "message",
  "device_id": "dev_example123",
  "app_id": "app_example123",
  "timestamp": "2026-01-10T02:15:05Z",
  "request_id": "...",
  "payload": {
    "wa_number": "6285211112222",
    "from": "6285211112222:1@s.whatsapp.net",
    "chat": "6281234567890@s.whatsapp.net",
    "message_id": "msg_xyz789",
    "direction": "outbound",
    "message_type": "text",
    "text": "Hi Jane",
    "is_group": false,
    "is_view_once": false
  }
}

Group - Inbound

{
  "event": "message",
  "device_id": "dev_example123",
  "app_id": "app_example123",
  "timestamp": "2026-01-12T11:00:00Z",
  "request_id": "...",
  "payload": {
    "wa_number": "6285211112222",
    "from": "6281234567890@s.whatsapp.net",
    "from_lid": "1234567890987654321@lid",
    "chat": "120363012345678901@g.us",
    "chat_lid": "9876543210987654321@lid",
    "message_id": "GROUP_MSG_123",
    "direction": "inbound",
    "message_type": "text",
    "text": "Hello everyone in the group!",
    "is_group": true,
    "is_view_once": false
  }
}

Group - Outbound

{
  "event": "message",
  "device_id": "dev_example123",
  "app_id": "app_example123",
  "timestamp": "2026-01-12T11:10:00Z",
  "request_id": "...",
  "payload": {
    "wa_number": "6285211112222",
    "from": "6285211112222:1@s.whatsapp.net",
    "chat": "120363012345678901@g.us",
    "message_id": "GROUP_OUT_789",
    "direction": "outbound",
    "message_type": "text",
    "text": "Announcement: Meeting at 3 PM",
    "is_group": true,
    "is_view_once": false
  }
}

Image Messages

Individual - Inbound (with caption)

{
  "event": "message",
  "device_id": "dev_example123",
  "app_id": "app_example123",
  "timestamp": "2026-01-12T09:17:13Z",
  "request_id": "...",
  "payload": {
    "wa_number": "6285211112222",
    "from": "6281234567890@s.whatsapp.net",
    "from_lid": "1234567890987654321@lid",
    "chat": "6281234567890@s.whatsapp.net",
    "chat_lid": "1234567890987654321@lid",
    "message_id": "IMG_IND_123",
    "direction": "inbound",
    "message_type": "image",
    "text": "Check out this photo",
    "caption": "Check out this photo",
    "media_mime_type": "image/jpeg",
    "media_size": 245678,
    "media_path": "media/app-id/device-id-IMG_IND_123.bin",
    "is_group": false,
    "is_view_once": false
  }
}

Individual - Outbound (with caption)

{
  "event": "message",
  "device_id": "dev_example123",
  "app_id": "app_example123",
  "timestamp": "2026-01-12T10:30:00Z",
  "request_id": "...",
  "payload": {
    "wa_number": "6285211112222",
    "from": "6285211112222:1@s.whatsapp.net",
    "chat": "6281234567890@s.whatsapp.net",
    "message_id": "IMG_OUT_456",
    "direction": "outbound",
    "message_type": "image",
    "text": "Check out this image",
    "caption": "Check out this image",
    "media_mime_type": "image/jpeg",
    "media_size": 156789,
    "is_group": false,
    "is_view_once": false
  }
}

Group - Inbound (with caption)

{
  "event": "message",
  "device_id": "dev_example123",
  "app_id": "app_example123",
  "timestamp": "2026-01-12T11:05:00Z",
  "request_id": "...",
  "payload": {
    "wa_number": "6285211112222",
    "from": "6281234567890@s.whatsapp.net",
    "from_lid": "1234567890987654321@lid",
    "chat": "120363012345678901@g.us",
    "chat_lid": "9876543210987654321@lid",
    "message_id": "IMG_GROUP_IN_789",
    "direction": "inbound",
    "message_type": "image",
    "text": "Check out this photo from our trip",
    "caption": "Check out this photo from our trip",
    "media_mime_type": "image/jpeg",
    "media_size": 345678,
    "media_path": "media/app-id/device-id-IMG_GROUP_IN_789.bin",
    "is_group": true,
    "is_view_once": false
  }
}

Group - Outbound (with caption)

{
  "event": "message",
  "device_id": "dev_example123",
  "app_id": "app_example123",
  "timestamp": "2026-01-12T11:15:00Z",
  "request_id": "...",
  "payload": {
    "wa_number": "6285211112222",
    "from": "6285211112222:1@s.whatsapp.net",
    "chat": "120363012345678901@g.us",
    "message_id": "IMG_GROUP_OUT_999",
    "direction": "outbound",
    "message_type": "image",
    "text": "Team photo",
    "caption": "Team photo",
    "media_mime_type": "image/jpeg",
    "media_size": 456789,
    "is_group": true,
    "is_view_once": false
  }
}

Video Messages

Individual - Inbound (with caption)

{
  "event": "message",
  "device_id": "dev_example123",
  "app_id": "app_example123",
  "timestamp": "2026-01-12T11:20:00Z",
  "request_id": "...",
  "payload": {
    "wa_number": "6285211112222",
    "from": "6281234567890@s.whatsapp.net",
    "from_lid": "1234567890987654321@lid",
    "chat": "6281234567890@s.whatsapp.net",
    "chat_lid": "1234567890987654321@lid",
    "message_id": "VIDEO_IND_123",
    "direction": "inbound",
    "message_type": "video",
    "text": "Check out this video",
    "caption": "Check out this video",
    "media_mime_type": "video/mp4",
    "media_size": 2456789,
    "media_path": "media/app-id/device-id-VIDEO_IND_123.bin",
    "is_group": false,
    "is_view_once": false
  }
}

Individual - Outbound (with caption)

{
  "event": "message",
  "device_id": "dev_example123",
  "app_id": "app_example123",
  "timestamp": "2026-01-12T11:30:00Z",
  "request_id": "...",
  "payload": {
    "wa_number": "6285211112222",
    "from": "6285211112222:1@s.whatsapp.net",
    "chat": "6281234567890@s.whatsapp.net",
    "message_id": "VIDEO_OUT_456",
    "direction": "outbound",
    "message_type": "video",
    "text": "Here's the video I promised",
    "caption": "Here's the video I promised",
    "media_mime_type": "video/mp4",
    "media_size": 4567890,
    "is_group": false,
    "is_view_once": false
  }
}

Group - Inbound (with caption)

{
  "event": "message",
  "device_id": "dev_example123",
  "app_id": "app_example123",
  "timestamp": "2026-01-12T11:25:00Z",
  "request_id": "...",
  "payload": {
    "wa_number": "6285211112222",
    "from": "6281234567890@s.whatsapp.net",
    "from_lid": "1234567890987654321@lid",
    "chat": "120363012345678901@g.us",
    "chat_lid": "9876543210987654321@lid",
    "message_id": "VIDEO_GROUP_IN_789",
    "direction": "inbound",
    "message_type": "video",
    "text": "Watch this video everyone",
    "caption": "Watch this video everyone",
    "media_mime_type": "video/mp4",
    "media_size": 3456789,
    "media_path": "media/app-id/device-id-VIDEO_GROUP_IN_789.bin",
    "is_group": true,
    "is_view_once": false
  }
}

Group - Outbound (with caption)

{
  "event": "message",
  "device_id": "dev_example123",
  "app_id": "app_example123",
  "timestamp": "2026-01-12T11:35:00Z",
  "request_id": "...",
  "payload": {
    "wa_number": "6285211112222",
    "from": "6285211112222:1@s.whatsapp.net",
    "chat": "120363012345678901@g.us",
    "message_id": "VIDEO_GROUP_OUT_999",
    "direction": "outbound",
    "message_type": "video",
    "text": "Video for the team",
    "caption": "Video for the team",
    "media_mime_type": "video/mp4",
    "media_size": 5678901,
    "is_group": true,
    "is_view_once": false
  }
}

Audio Messages

Audio messages can be voice notes (PTT/push-to-talk) or regular audio files. Voice notes use ptt: true and are typically shorter recordings.

Individual - Inbound (Voice Note)

{
  "event": "message",
  "device_id": "dev_example123",
  "app_id": "app_example123",
  "timestamp": "2026-01-12T11:40:00Z",
  "request_id": "...",
  "payload": {
    "wa_number": "6285211112222",
    "from": "6281234567890@s.whatsapp.net",
    "from_lid": "1234567890987654321@lid",
    "chat": "6281234567890@s.whatsapp.net",
    "chat_lid": "1234567890987654321@lid",
    "message_id": "AUDIO_VOICE_123",
    "direction": "inbound",
    "message_type": "audio",
    "media_mime_type": "audio/ogg; codecs=opus",
    "media_size": 45678,
    "media_path": "media/app-id/device-id-AUDIO_VOICE_123.bin",
    "ptt": true,
    "is_group": false,
    "is_view_once": false
  }
}

Individual - Inbound (Regular Audio)

{
  "event": "message",
  "device_id": "dev_example123",
  "app_id": "app_example123",
  "timestamp": "2026-01-12T11:42:00Z",
  "request_id": "...",
  "payload": {
    "wa_number": "6285211112222",
    "from": "6281234567890@s.whatsapp.net",
    "from_lid": "1234567890987654321@lid",
    "chat": "6281234567890@s.whatsapp.net",
    "chat_lid": "1234567890987654321@lid",
    "message_id": "AUDIO_REGULAR_456",
    "direction": "inbound",
    "message_type": "audio",
    "media_mime_type": "audio/mpeg",
    "media_size": 1234567,
    "media_path": "media/app-id/device-id-AUDIO_REGULAR_456.bin",
    "ptt": false,
    "is_group": false,
    "is_view_once": false
  }
}

Group - Inbound (Voice Note)

{
  "event": "message",
  "device_id": "dev_example123",
  "app_id": "app_example123",
  "timestamp": "2026-01-12T11:45:00Z",
  "request_id": "...",
  "payload": {
    "wa_number": "6285211112222",
    "from": "6281234567890@s.whatsapp.net",
    "from_lid": "1234567890987654321@lid",
    "chat": "120363012345678901@g.us",
    "chat_lid": "9876543210987654321@lid",
    "message_id": "AUDIO_GROUP_789",
    "direction": "inbound",
    "message_type": "audio",
    "media_mime_type": "audio/ogg; codecs=opus",
    "media_size": 67890,
    "media_path": "media/app-id/device-id-AUDIO_GROUP_789.bin",
    "ptt": true,
    "is_group": true,
    "is_view_once": false
  }
}

Individual - Outbound (Voice Note)

{
  "event": "message",
  "device_id": "dev_example123",
  "app_id": "app_example123",
  "timestamp": "2026-01-12T11:50:00Z",
  "request_id": "...",
  "payload": {
    "wa_number": "6285211112222",
    "from": "6285211112222:1@s.whatsapp.net",
    "chat": "6281234567890@s.whatsapp.net",
    "message_id": "AUDIO_OUT_999",
    "direction": "outbound",
    "message_type": "audio",
    "media_mime_type": "audio/ogg; codecs=opus",
    "media_size": 34567,
    "ptt": true,
    "is_group": false,
    "is_view_once": false
  }
}

Group - Outbound (Regular Audio)

{
  "event": "message",
  "device_id": "dev_example123",
  "app_id": "app_example123",
  "timestamp": "2026-01-12T11:55:00Z",
  "request_id": "...",
  "payload": {
    "wa_number": "6285211112222",
    "from": "6285211112222:1@s.whatsapp.net",
    "chat": "120363012345678901@g.us",
    "message_id": "AUDIO_GROUP_OUT_111",
    "direction": "outbound",
    "message_type": "audio",
    "media_mime_type": "audio/mpeg",
    "media_size": 2345678,
    "ptt": false,
    "is_group": true,
    "is_view_once": false
  }
}

Document Messages

Individual - Inbound (with caption)

{
  "event": "message",
  "device_id": "dev_example123",
  "app_id": "app_example123",
  "timestamp": "2026-01-12T12:00:00Z",
  "request_id": "...",
  "payload": {
    "wa_number": "6285211112222",
    "from": "6281234567890@s.whatsapp.net",
    "from_lid": "1234567890987654321@lid",
    "chat": "6281234567890@s.whatsapp.net",
    "chat_lid": "1234567890987654321@lid",
    "message_id": "DOC_IND_123",
    "direction": "inbound",
    "message_type": "document",
    "text": "Please review this document",
    "caption": "Please review this document",
    "media_mime_type": "application/pdf",
    "media_size": 1024000,
    "media_filename": "report.pdf",
    "media_path": "media/app-id/device-id-DOC_IND_123.bin",
    "is_group": false,
    "is_view_once": false
  }
}

Group - Inbound (without caption)

{
  "event": "message",
  "device_id": "dev_example123",
  "app_id": "app_example123",
  "timestamp": "2026-01-12T12:05:00Z",
  "request_id": "...",
  "payload": {
    "wa_number": "6285211112222",
    "from": "6281234567890@s.whatsapp.net",
    "from_lid": "1234567890987654321@lid",
    "chat": "120363012345678901@g.us",
    "chat_lid": "9876543210987654321@lid",
    "message_id": "DOC_GROUP_456",
    "direction": "inbound",
    "message_type": "document",
    "media_mime_type": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
    "media_size": 2048000,
    "media_filename": "budget_2026.xlsx",
    "media_path": "media/app-id/device-id-DOC_GROUP_456.bin",
    "is_group": true,
    "is_view_once": false
  }
}

Individual - Outbound (with caption)

{
  "event": "message",
  "device_id": "dev_example123",
  "app_id": "app_example123",
  "timestamp": "2026-01-12T12:10:00Z",
  "request_id": "...",
  "payload": {
    "wa_number": "6285211112222",
    "from": "6285211112222:1@s.whatsapp.net",
    "chat": "6281234567890@s.whatsapp.net",
    "message_id": "DOC_OUT_789",
    "direction": "outbound",
    "message_type": "document",
    "text": "Here's the invoice",
    "caption": "Here's the invoice",
    "media_mime_type": "application/pdf",
    "media_size": 512000,
    "media_filename": "invoice_2026_01.pdf",
    "is_group": false,
    "is_view_once": false
  }
}

Sticker Messages

Individual - Inbound

{
  "event": "message",
  "device_id": "dev_example123",
  "app_id": "app_example123",
  "timestamp": "2026-01-12T12:15:00Z",
  "request_id": "...",
  "payload": {
    "wa_number": "6285211112222",
    "from": "6281234567890@s.whatsapp.net",
    "from_lid": "1234567890987654321@lid",
    "chat": "6281234567890@s.whatsapp.net",
    "chat_lid": "1234567890987654321@lid",
    "message_id": "STICKER_IND_123",
    "direction": "inbound",
    "message_type": "sticker",
    "media_mime_type": "image/webp",
    "media_size": 45678,
    "media_path": "media/app-id/device-id-STICKER_IND_123.bin",
    "is_group": false,
    "is_view_once": false
  }
}

Group - Inbound

{
  "event": "message",
  "device_id": "dev_example123",
  "app_id": "app_example123",
  "timestamp": "2026-01-12T12:20:00Z",
  "request_id": "...",
  "payload": {
    "wa_number": "6285211112222",
    "from": "6281234567890@s.whatsapp.net",
    "from_lid": "1234567890987654321@lid",
    "chat": "120363012345678901@g.us",
    "chat_lid": "9876543210987654321@lid",
    "message_id": "STICKER_GROUP_456",
    "direction": "inbound",
    "message_type": "sticker",
    "media_mime_type": "image/webp",
    "media_size": 34567,
    "media_path": "media/app-id/device-id-STICKER_GROUP_456.bin",
    "is_group": true,
    "is_view_once": false
  }
}

Individual - Outbound

{
  "event": "message",
  "device_id": "dev_example123",
  "app_id": "app_example123",
  "timestamp": "2026-01-12T12:25:00Z",
  "request_id": "...",
  "payload": {
    "wa_number": "6285211112222",
    "from": "6285211112222:1@s.whatsapp.net",
    "chat": "6281234567890@s.whatsapp.net",
    "message_id": "STICKER_OUT_789",
    "direction": "outbound",
    "message_type": "sticker",
    "media_mime_type": "image/webp",
    "media_size": 23456,
    "is_group": false,
    "is_view_once": false
  }
}

Group - Outbound

{
  "event": "message",
  "device_id": "dev_example123",
  "app_id": "app_example123",
  "timestamp": "2026-01-12T12:30:00Z",
  "request_id": "...",
  "payload": {
    "wa_number": "6285211112222",
    "from": "6285211112222:1@s.whatsapp.net",
    "chat": "120363012345678901@g.us",
    "message_id": "STICKER_GROUP_OUT_999",
    "direction": "outbound",
    "message_type": "sticker",
    "media_mime_type": "image/webp",
    "media_size": 38901,
    "is_group": true,
    "is_view_once": false
  }
}

Location Messages

Individual - Inbound (with name & address)

{
  "event": "message",
  "device_id": "dev_example123",
  "app_id": "app_example123",
  "timestamp": "2026-01-12T11:25:00Z",
  "request_id": "...",
  "payload": {
    "wa_number": "6285211112222",
    "from": "6281234567890@s.whatsapp.net",
    "from_lid": "1234567890987654321@lid",
    "chat": "6281234567890@s.whatsapp.net",
    "chat_lid": "1234567890987654321@lid",
    "message_id": "LOC_IND_123",
    "direction": "inbound",
    "message_type": "location",
    "latitude": -6.175392,
    "longitude": 106.827153,
    "location_name": "National Monument",
    "location_address": "Jakarta, Indonesia",
    "is_group": false,
    "is_view_once": false
  }
}

Individual - Inbound (coordinates only)

{
  "event": "message",
  "device_id": "dev_example123",
  "app_id": "app_example123",
  "timestamp": "2026-01-12T11:35:00Z",
  "request_id": "...",
  "payload": {
    "wa_number": "6285211112222",
    "from": "6281234567890@s.whatsapp.net",
    "from_lid": "1234567890987654321@lid",
    "chat": "6281234567890@s.whatsapp.net",
    "chat_lid": "1234567890987654321@lid",
    "message_id": "LOC_COORDS_789",
    "direction": "inbound",
    "message_type": "location",
    "latitude": -6.175392,
    "longitude": 106.827153,
    "is_group": false,
    "is_view_once": false
  }
}

Group - Inbound

{
  "event": "message",
  "device_id": "dev_example123",
  "app_id": "app_example123",
  "timestamp": "2026-01-12T11:30:00Z",
  "request_id": "...",
  "payload": {
    "wa_number": "6285211112222",
    "from": "6281234567890@s.whatsapp.net",
    "from_lid": "1234567890987654321@lid",
    "chat": "120363012345678901@g.us",
    "chat_lid": "9876543210987654321@lid",
    "message_id": "LOC_GROUP_456",
    "direction": "inbound",
    "message_type": "location",
    "latitude": -6.2088,
    "longitude": 106.8456,
    "location_name": "Restaurant ABC",
    "location_address": "Jl. Sudirman No. 123, Jakarta",
    "is_group": true,
    "is_view_once": false
  }
}

Individual - Outbound

{
  "event": "message",
  "device_id": "dev_example123",
  "app_id": "app_example123",
  "timestamp": "2026-01-12T11:40:00Z",
  "request_id": "...",
  "payload": {
    "wa_number": "6285211112222",
    "from": "6285211112222:1@s.whatsapp.net",
    "chat": "6281234567890@s.whatsapp.net",
    "message_id": "LOC_OUT_123",
    "direction": "outbound",
    "message_type": "location",
    "latitude": -6.175392,
    "longitude": 106.827153,
    "location_name": "National Monument",
    "location_address": "Jakarta, Indonesia",
    "is_group": false,
    "is_view_once": false
  }
}

Group - Outbound

{
  "event": "message",
  "device_id": "dev_example123",
  "app_id": "app_example123",
  "timestamp": "2026-01-12T11:45:00Z",
  "request_id": "...",
  "payload": {
    "wa_number": "6285211112222",
    "from": "6285211112222:1@s.whatsapp.net",
    "chat": "120363012345678901@g.us",
    "message_id": "LOC_GROUP_OUT_456",
    "direction": "outbound",
    "message_type": "location",
    "latitude": -6.2088,
    "longitude": 106.8456,
    "location_name": "Restaurant ABC",
    "location_address": "Jl. Sudirman No. 123, Jakarta",
    "is_group": true,
    "is_view_once": false
  }
}

Live Location Updates

Live location sharing sends multiple location updates over time. Each update is a separate location message webhook.

Individual - Update #1

{
  "event": "message",
  "device_id": "dev_example123",
  "app_id": "app_example123",
  "timestamp": "2026-01-12T12:00:00Z",
  "request_id": "...",
  "payload": {
    "wa_number": "6285211112222",
    "from": "6281234567890@s.whatsapp.net",
    "from_lid": "1234567890987654321@lid",
    "chat": "6281234567890@s.whatsapp.net",
    "chat_lid": "1234567890987654321@lid",
    "message_id": "LIVE_LOC_001",
    "direction": "inbound",
    "message_type": "location",
    "latitude": -6.175392,
    "longitude": 106.827153,
    "location_name": "Current Location",
    "location_address": "Jakarta, Indonesia",
    "is_group": false,
    "is_view_once": false
  }
}

Individual - Update #2 (15s later)

{
  "event": "message",
  "device_id": "dev_example123",
  "app_id": "app_example123",
  "timestamp": "2026-01-12T12:00:15Z",
  "request_id": "...",
  "payload": {
    "wa_number": "6285211112222",
    "from": "6281234567890@s.whatsapp.net",
    "from_lid": "1234567890987654321@lid",
    "chat": "6281234567890@s.whatsapp.net",
    "chat_lid": "1234567890987654321@lid",
    "message_id": "LIVE_LOC_002",
    "direction": "inbound",
    "message_type": "location",
    "latitude": -6.175405,
    "longitude": 106.827168,
    "location_name": "Current Location",
    "location_address": "Jakarta, Indonesia",
    "is_group": false,
    "is_view_once": false
  }
}

Group - Update

{
  "event": "message",
  "device_id": "dev_example123",
  "app_id": "app_example123",
  "timestamp": "2026-01-12T12:00:30Z",
  "request_id": "...",
  "payload": {
    "wa_number": "6285211112222",
    "from": "6281234567890@s.whatsapp.net",
    "from_lid": "1234567890987654321@lid",
    "chat": "120363012345678901@g.us",
    "chat_lid": "9876543210987654321@lid",
    "message_id": "LIVE_LOC_GROUP_003",
    "direction": "inbound",
    "message_type": "location",
    "latitude": -6.175420,
    "longitude": 106.827180,
    "location_name": "Moving Location",
    "location_address": "Jakarta, Indonesia",
    "is_group": true,
    "is_view_once": false
  }
}

Contact Messages

Individual - Inbound (single phone)

{
  "event": "message",
  "device_id": "dev_example123",
  "app_id": "app_example123",
  "timestamp": "2026-01-12T11:20:00Z",
  "request_id": "...",
  "payload": {
    "wa_number": "6285211112222",
    "from": "6281234567890@s.whatsapp.net",
    "from_lid": "1234567890987654321@lid",
    "chat": "6281234567890@s.whatsapp.net",
    "chat_lid": "1234567890987654321@lid",
    "message_id": "CONTACT_MSG_123",
    "direction": "inbound",
    "message_type": "contact",
    "contact_name": "John Doe",
    "contact_vcard": "BEGIN:VCARD\nVERSION:3.0\nFN:John Doe\nTEL;TYPE=CELL:+6281234567890\nEMAIL:john@example.com\nEND:VCARD",
    "is_group": false,
    "is_view_once": false
  }
}

Individual - Inbound (multiple phones)

{
  "event": "message",
  "device_id": "dev_example123",
  "app_id": "app_example123",
  "timestamp": "2026-01-12T11:22:00Z",
  "request_id": "...",
  "payload": {
    "wa_number": "6285211112222",
    "from": "6281234567890@s.whatsapp.net",
    "from_lid": "1234567890987654321@lid",
    "chat": "6281234567890@s.whatsapp.net",
    "chat_lid": "1234567890987654321@lid",
    "message_id": "CONTACT_MULTI_456",
    "direction": "inbound",
    "message_type": "contact",
    "contact_name": "Jane Smith",
    "contact_vcard": "BEGIN:VCARD\nVERSION:3.0\nFN:Jane Smith\nTEL;TYPE=CELL:+6281234567890\nTEL;TYPE=WORK:+6289876543210\nTEL;TYPE=HOME:+6281111111111\nEMAIL:jane@example.com\nEND:VCARD",
    "is_group": false,
    "is_view_once": false
  }
}

Auto-farming: The system automatically extracts all phone numbers from the vCard and fetches their profile data in the background.

Other Webhook Examples

receipt (read)

{
  "event": "receipt",
  "device_id": "dev_example123",
  "app_id": "app_example123",
  "timestamp": "2026-01-12T11:25:00Z",
  "request_id": "...",
  "payload": {
    "wa_number": "6285211112222",
    "from": "6281234567890@s.whatsapp.net",
    "from_lid": "1234567890987654321@lid",
    "chat": "120363012345678901@g.us",
    "chat_lid": "9876543210987654321@lid",
    "message_id": "GROUP_VIDEO_456",
    "direction": "inbound",
    "message_type": "video",
    "text": "Watch this video everyone",
    "caption": "Watch this video everyone",
    "media_mime_type": "video/mp4",
    "media_size": 3456789,
    "media_path": "media/app-id/device-id-GROUP_VIDEO_456.bin",
    "is_group": true,
    "is_view_once": false
  }
}

Group video: Same video metadata as individual, but is_group is true and chat is the group JID. from is the sender's JID within the group.

message (inbound from group - text)

{
  "event": "message",
  "device_id": "dev_example123",
  "app_id": "app_example123",
  "timestamp": "2026-01-12T11:00:00Z",
  "request_id": "...",
  "payload": {
    "wa_number": "6285211112222",
    "from": "6281234567890@s.whatsapp.net",
    "from_lid": "1234567890987654321@lid",
    "chat": "120363012345678901@g.us",
    "chat_lid": "9876543210987654321@lid",
    "message_id": "GROUP_MSG_123",
    "direction": "inbound",
    "message_type": "text",
    "text": "Hello everyone in the group!",
    "is_group": true,
    "is_view_once": false
  }
}

Group text: is_group is true, chat contains group JID (@g.us), and from is the sender's JID within the group. message_type is always included.

message (inbound from group - image with caption)

{
  "event": "message",
  "device_id": "dev_example123",
  "app_id": "app_example123",
  "timestamp": "2026-01-12T11:05:00Z",
  "request_id": "...",
  "payload": {
    "wa_number": "6285211112222",
    "from": "6281234567890@s.whatsapp.net",
    "from_lid": "1234567890987654321@lid",
    "chat": "120363012345678901@g.us",
    "chat_lid": "9876543210987654321@lid",
    "message_id": "GROUP_IMG_456",
    "direction": "inbound",
    "message_type": "image",
    "text": "Check out this photo from our trip",
    "caption": "Check out this photo from our trip",
    "media_mime_type": "image/jpeg",
    "media_size": 345678,
    "media_path": "media/b1580b43-f254-4a5e-bad3-6b16f49517d9/367ec376-2c93-45bc-ad97-bbbb42507021-GROUP_IMG_456.bin",
    "is_group": true,
    "is_view_once": false
  }
}

Group media: All media information is included (same as individual messages). from identifies who sent the media in the group, while chat is the group JID (@g.us). is_group is true.

message (outbound to group - text)

{
  "event": "message",
  "device_id": "dev_example123",
  "app_id": "app_example123",
  "timestamp": "2026-01-12T11:10:00Z",
  "request_id": "...",
  "payload": {
    "wa_number": "6285211112222",
    "from": "6285211112222:1@s.whatsapp.net",
    "from_lid": "9876543210987654321@lid",
    "chat": "120363012345678901@g.us",
    "chat_lid": "9876543210987654321@lid",
    "message_id": "GROUP_OUT_789",
    "direction": "outbound",
    "message_type": "text",
    "text": "Announcement: Meeting at 3 PM",
    "is_group": true,
    "is_view_once": false
  }
}

Outbound to group: When your device sends to a group, is_group is true and chat is the group JID (@g.us). from is your device JID.

message (outbound video - individual)

{
  "event": "message",
  "device_id": "dev_example123",
  "app_id": "app_example123",
  "timestamp": "2026-01-12T11:30:00Z",
  "request_id": "...",
  "payload": {
    "wa_number": "6285211112222",
    "from": "6285211112222:1@s.whatsapp.net",
    "chat": "6281234567890@s.whatsapp.net",
    "message_id": "VIDEO_OUT_789",
    "direction": "outbound",
    "message_type": "video",
    "text": "Here's the video I promised",
    "caption": "Here's the video I promised",
    "media_mime_type": "video/mp4",
    "media_size": 4567890,
    "is_group": false,
    "is_view_once": false
  }
}

Outbound individual video: Complete video metadata. is_group is false. from is the device JID.

message (outbound video - group)

{
  "event": "message",
  "device_id": "dev_example123",
  "app_id": "app_example123",
  "timestamp": "2026-01-12T11:35:00Z",
  "request_id": "...",
  "payload": {
    "wa_number": "6285211112222",
    "from": "6285211112222:1@s.whatsapp.net",
    "chat": "120363012345678901@g.us",
    "message_id": "GROUP_VIDEO_OUT_999",
    "direction": "outbound",
    "message_type": "video",
    "text": "Video for the team",
    "caption": "Video for the team",
    "media_mime_type": "video/mp4",
    "media_size": 5678901,
    "is_group": true,
    "is_view_once": false
  }
}

Outbound group video: Same video metadata as individual, but is_group is true and chat is the group JID.

message (inbound audio - individual, voice note)

{
  "event": "message",
  "device_id": "dev_example123",
  "app_id": "app_example123",
  "timestamp": "2026-01-12T11:40:00Z",
  "request_id": "...",
  "payload": {
    "wa_number": "6285211112222",
    "from": "6281234567890@s.whatsapp.net",
    "from_lid": "1234567890987654321@lid",
    "chat": "6281234567890@s.whatsapp.net",
    "chat_lid": "1234567890987654321@lid",
    "message_id": "AUDIO_VOICE_123",
    "direction": "inbound",
    "message_type": "audio",
    "media_mime_type": "audio/ogg; codecs=opus",
    "media_size": 45678,
    "media_path": "media/app-id/device-id-AUDIO_VOICE_123.bin",
    "ptt": true,
    "is_group": false,
    "is_view_once": false
  }
}

Voice note (PTT): ptt is true for voice notes (push-to-talk). These are typically shorter audio messages recorded in real-time. media_mime_type is often audio/ogg or audio/opus for voice notes.

message (inbound audio - individual, regular audio)

{
  "event": "message",
  "device_id": "dev_example123",
  "app_id": "app_example123",
  "timestamp": "2026-01-12T11:42:00Z",
  "request_id": "...",
  "payload": {
    "wa_number": "6285211112222",
    "from": "6281234567890@s.whatsapp.net",
    "from_lid": "1234567890987654321@lid",
    "chat": "6281234567890@s.whatsapp.net",
    "chat_lid": "1234567890987654321@lid",
    "message_id": "AUDIO_REGULAR_456",
    "direction": "inbound",
    "message_type": "audio",
    "media_mime_type": "audio/mpeg",
    "media_size": 1234567,
    "media_path": "media/app-id/device-id-AUDIO_REGULAR_456.bin",
    "ptt": false,
    "is_group": false,
    "is_view_once": false
  }
}

Regular audio file: ptt is false for regular audio files (music, podcasts, etc.). These can be longer-form audio content. media_mime_type is typically audio/mpeg or audio/aac for regular audio.

message (inbound audio - group, voice note)

{
  "event": "message",
  "device_id": "dev_example123",
  "app_id": "app_example123",
  "timestamp": "2026-01-12T11:45:00Z",
  "request_id": "...",
  "payload": {
    "wa_number": "6285211112222",
    "from": "6281234567890@s.whatsapp.net",
    "from_lid": "1234567890987654321@lid",
    "chat": "120363012345678901@g.us",
    "chat_lid": "9876543210987654321@lid",
    "message_id": "GROUP_AUDIO_789",
    "direction": "inbound",
    "message_type": "audio",
    "media_mime_type": "audio/ogg; codecs=opus",
    "media_size": 67890,
    "media_path": "media/app-id/device-id-GROUP_AUDIO_789.bin",
    "ptt": true,
    "is_group": true,
    "is_view_once": false
  }
}

Group voice note: Same audio metadata as individual, but is_group is true and chat is the group JID. from identifies who sent the voice note in the group.

message (outbound audio - individual, voice note)

{
  "event": "message",
  "device_id": "dev_example123",
  "app_id": "app_example123",
  "timestamp": "2026-01-12T11:50:00Z",
  "request_id": "...",
  "payload": {
    "wa_number": "6285211112222",
    "from": "6285211112222:1@s.whatsapp.net",
    "chat": "6281234567890@s.whatsapp.net",
    "message_id": "AUDIO_OUT_999",
    "direction": "outbound",
    "message_type": "audio",
    "media_mime_type": "audio/ogg; codecs=opus",
    "media_size": 34567,
    "ptt": true,
    "is_group": false,
    "is_view_once": false
  }
}

Outbound voice note: ptt is true for voice notes sent from your device. is_group is false for individual messages.

message (outbound audio - group, regular audio)

{
  "event": "message",
  "device_id": "dev_example123",
  "app_id": "app_example123",
  "timestamp": "2026-01-12T11:55:00Z",
  "request_id": "...",
  "payload": {
    "wa_number": "6285211112222",
    "from": "6285211112222:1@s.whatsapp.net",
    "chat": "120363012345678901@g.us",
    "message_id": "GROUP_AUDIO_OUT_111",
    "direction": "outbound",
    "message_type": "audio",
    "media_mime_type": "audio/mpeg",
    "media_size": 2345678,
    "ptt": false,
    "is_group": true,
    "is_view_once": false
  }
}

Outbound group audio: ptt is false for regular audio files. is_group is true and chat is the group JID.

message (inbound document - individual, with caption)

{
  "event": "message",
  "device_id": "dev_example123",
  "app_id": "app_example123",
  "timestamp": "2026-01-12T12:00:00Z",
  "request_id": "...",
  "payload": {
    "wa_number": "6285211112222",
    "from": "6281234567890@s.whatsapp.net",
    "from_lid": "1234567890987654321@lid",
    "chat": "6281234567890@s.whatsapp.net",
    "chat_lid": "1234567890987654321@lid",
    "message_id": "DOC_INDIVIDUAL_123",
    "direction": "inbound",
    "message_type": "document",
    "text": "Please review this document",
    "caption": "Please review this document",
    "media_mime_type": "application/pdf",
    "media_size": 1024000,
    "media_filename": "report.pdf",
    "media_path": "media/app-id/device-id-DOC_INDIVIDUAL_123.bin",
    "is_group": false,
    "is_view_once": false
  }
}

Individual document: Includes media_filename in addition to other media fields. Documents can have optional captions. is_group is false.

message (inbound document - group, without caption)

{
  "event": "message",
  "device_id": "dev_example123",
  "app_id": "app_example123",
  "timestamp": "2026-01-12T12:05:00Z",
  "request_id": "...",
  "payload": {
    "wa_number": "6285211112222",
    "from": "6281234567890@s.whatsapp.net",
    "from_lid": "1234567890987654321@lid",
    "chat": "120363012345678901@g.us",
    "chat_lid": "9876543210987654321@lid",
    "message_id": "DOC_GROUP_456",
    "direction": "inbound",
    "message_type": "document",
    "media_mime_type": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
    "media_size": 2048000,
    "media_filename": "budget_2026.xlsx",
    "media_path": "media/app-id/device-id-DOC_GROUP_456.bin",
    "is_group": true,
    "is_view_once": false
  }
}

Group document: Same document metadata as individual, but is_group is true and chat is the group JID. from identifies who sent the document in the group.

message (outbound document - individual, with caption)

{
  "event": "message",
  "device_id": "dev_example123",
  "app_id": "app_example123",
  "timestamp": "2026-01-12T12:10:00Z",
  "request_id": "...",
  "payload": {
    "wa_number": "6285211112222",
    "from": "6285211112222:1@s.whatsapp.net",
    "chat": "6281234567890@s.whatsapp.net",
    "message_id": "DOC_OUT_789",
    "direction": "outbound",
    "message_type": "document",
    "text": "Here's the invoice",
    "caption": "Here's the invoice",
    "media_mime_type": "application/pdf",
    "media_size": 512000,
    "media_filename": "invoice_2026_01.pdf",
    "is_group": false,
    "is_view_once": false
  }
}

Outbound individual document: Complete document metadata including media_filename. is_group is false.

message (inbound sticker - individual)

{
  "event": "message",
  "device_id": "dev_example123",
  "app_id": "app_example123",
  "timestamp": "2026-01-12T12:15:00Z",
  "request_id": "...",
  "payload": {
    "wa_number": "6285211112222",
    "from": "6281234567890@s.whatsapp.net",
    "from_lid": "1234567890987654321@lid",
    "chat": "6281234567890@s.whatsapp.net",
    "chat_lid": "1234567890987654321@lid",
    "message_id": "STICKER_INDIVIDUAL_123",
    "direction": "inbound",
    "message_type": "sticker",
    "media_mime_type": "image/webp",
    "media_size": 45678,
    "media_path": "media/app-id/device-id-STICKER_INDIVIDUAL_123.bin",
    "is_group": false,
    "is_view_once": false
  }
}

Individual sticker: Stickers use WebP format. They don't support captions. is_group is false.

message (inbound sticker - group)

{
  "event": "message",
  "device_id": "dev_example123",
  "app_id": "app_example123",
  "timestamp": "2026-01-12T12:20:00Z",
  "request_id": "...",
  "payload": {
    "wa_number": "6285211112222",
    "from": "6281234567890@s.whatsapp.net",
    "from_lid": "1234567890987654321@lid",
    "chat": "120363012345678901@g.us",
    "chat_lid": "9876543210987654321@lid",
    "message_id": "STICKER_GROUP_456",
    "direction": "inbound",
    "message_type": "sticker",
    "media_mime_type": "image/webp",
    "media_size": 34567,
    "media_path": "media/app-id/device-id-STICKER_GROUP_456.bin",
    "is_group": true,
    "is_view_once": false
  }
}

Group sticker: Same sticker metadata as individual, but is_group is true and chat is the group JID. from identifies who sent the sticker in the group.

message (outbound sticker - individual)

{
  "event": "message",
  "device_id": "dev_example123",
  "app_id": "app_example123",
  "timestamp": "2026-01-12T12:25:00Z",
  "request_id": "...",
  "payload": {
    "wa_number": "6285211112222",
    "from": "6285211112222:1@s.whatsapp.net",
    "chat": "6281234567890@s.whatsapp.net",
    "message_id": "STICKER_OUT_789",
    "direction": "outbound",
    "message_type": "sticker",
    "media_mime_type": "image/webp",
    "media_size": 23456,
    "is_group": false,
    "is_view_once": false
  }
}

Outbound individual sticker: Complete sticker metadata. is_group is false.

message (outbound sticker - group)

{
  "event": "message",
  "device_id": "dev_example123",
  "app_id": "app_example123",
  "timestamp": "2026-01-12T12:30:00Z",
  "request_id": "...",
  "payload": {
    "wa_number": "6285211112222",
    "from": "6285211112222:1@s.whatsapp.net",
    "chat": "120363012345678901@g.us",
    "message_id": "STICKER_GROUP_OUT_999",
    "direction": "outbound",
    "message_type": "sticker",
    "media_mime_type": "image/webp",
    "media_size": 38901,
    "is_group": true,
    "is_view_once": false
  }
}

Outbound group sticker: Same sticker metadata as individual, but is_group is true and chat is the group JID.

message (inbound location - individual)

{
  "event": "message",
  "device_id": "dev_example123",
  "app_id": "app_example123",
  "timestamp": "2026-01-12T11:25:00Z",
  "request_id": "...",
  "payload": {
    "wa_number": "6285211112222",
    "from": "6281234567890@s.whatsapp.net",
    "from_lid": "1234567890987654321@lid",
    "chat": "6281234567890@s.whatsapp.net",
    "chat_lid": "1234567890987654321@lid",
    "message_id": "LOCATION_INDIVIDUAL_123",
    "direction": "inbound",
    "message_type": "location",
    "latitude": -6.175392,
    "longitude": 106.827153,
    "location_name": "National Monument",
    "location_address": "Jakarta, Indonesia",
    "is_group": false,
    "is_view_once": false
  }
}

Individual location: Complete location data including coordinates, name, and address. is_group is false.

message (inbound location - group)

{
  "event": "message",
  "device_id": "dev_example123",
  "app_id": "app_example123",
  "timestamp": "2026-01-12T11:30:00Z",
  "request_id": "...",
  "payload": {
    "wa_number": "6285211112222",
    "from": "6281234567890@s.whatsapp.net",
    "from_lid": "1234567890987654321@lid",
    "chat": "120363012345678901@g.us",
    "chat_lid": "9876543210987654321@lid",
    "message_id": "LOCATION_GROUP_456",
    "direction": "inbound",
    "message_type": "location",
    "latitude": -6.2088,
    "longitude": 106.8456,
    "location_name": "Restaurant ABC",
    "location_address": "Jl. Sudirman No. 123, Jakarta",
    "is_group": true,
    "is_view_once": false
  }
}

Group location: Same location metadata as individual, but is_group is true and chat is the group JID. from identifies who sent the location in the group.

message (inbound location - coordinates only)

{
  "event": "message",
  "device_id": "dev_example123",
  "app_id": "app_example123",
  "timestamp": "2026-01-12T11:35:00Z",
  "request_id": "...",
  "payload": {
    "wa_number": "6285211112222",
    "from": "6281234567890@s.whatsapp.net",
    "from_lid": "1234567890987654321@lid",
    "chat": "6281234567890@s.whatsapp.net",
    "chat_lid": "1234567890987654321@lid",
    "message_id": "LOCATION_COORDS_ONLY_789",
    "direction": "inbound",
    "message_type": "location",
    "latitude": -6.175392,
    "longitude": 106.827153,
    "is_group": false,
    "is_view_once": false
  }
}

Coordinates only: Location messages can have only coordinates without location_name or location_address. These fields are optional.

message (outbound location - individual)

{
  "event": "message",
  "device_id": "dev_example123",
  "app_id": "app_example123",
  "timestamp": "2026-01-12T11:40:00Z",
  "request_id": "...",
  "payload": {
    "wa_number": "6285211112222",
    "from": "6285211112222:1@s.whatsapp.net",
    "chat": "6281234567890@s.whatsapp.net",
    "message_id": "LOCATION_OUT_123",
    "direction": "outbound",
    "message_type": "location",
    "latitude": -6.175392,
    "longitude": 106.827153,
    "location_name": "National Monument",
    "location_address": "Jakarta, Indonesia",
    "is_group": false,
    "is_view_once": false
  }
}

Outbound individual location: Complete location data for outbound message. is_group is false.

message (outbound location - group)

{
  "event": "message",
  "device_id": "dev_example123",
  "app_id": "app_example123",
  "timestamp": "2026-01-12T11:45:00Z",
  "request_id": "...",
  "payload": {
    "wa_number": "6285211112222",
    "from": "6285211112222:1@s.whatsapp.net",
    "chat": "120363012345678901@g.us",
    "message_id": "LOCATION_GROUP_OUT_456",
    "direction": "outbound",
    "message_type": "location",
    "latitude": -6.2088,
    "longitude": 106.8456,
    "location_name": "Restaurant ABC",
    "location_address": "Jl. Sudirman No. 123, Jakarta",
    "is_group": true,
    "is_view_once": false
  }
}

Outbound group location: Same location metadata as individual, but is_group is true and chat is the group JID.

message (inbound live location - individual, update #1)

{
  "event": "message",
  "device_id": "dev_example123",
  "app_id": "app_example123",
  "timestamp": "2026-01-12T12:00:00Z",
  "request_id": "...",
  "payload": {
    "wa_number": "6285211112222",
    "from": "6281234567890@s.whatsapp.net",
    "from_lid": "1234567890987654321@lid",
    "chat": "6281234567890@s.whatsapp.net",
    "chat_lid": "1234567890987654321@lid",
    "message_id": "LIVE_LOC_UPDATE_001",
    "direction": "inbound",
    "message_type": "location",
    "latitude": -6.175392,
    "longitude": 106.827153,
    "location_name": "Current Location",
    "location_address": "Jakarta, Indonesia",
    "is_group": false,
    "is_view_once": false
  }
}

Live location update: First update when someone starts sharing live location. message_id will be different for each update. Monitor consecutive location messages to detect live location.

message (inbound live location - individual, update #2)

{
  "event": "message",
  "device_id": "dev_example123",
  "app_id": "app_example123",
  "timestamp": "2026-01-12T12:00:15Z",
  "request_id": "...",
  "payload": {
    "wa_number": "6285211112222",
    "from": "6281234567890@s.whatsapp.net",
    "from_lid": "1234567890987654321@lid",
    "chat": "6281234567890@s.whatsapp.net",
    "chat_lid": "1234567890987654321@lid",
    "message_id": "LIVE_LOC_UPDATE_002",
    "direction": "inbound",
    "message_type": "location",
    "latitude": -6.175405,
    "longitude": 106.827168,
    "location_name": "Current Location",
    "location_address": "Jakarta, Indonesia",
    "is_group": false,
    "is_view_once": false
  }
}

Live location update: Second update (15 seconds later). Coordinates have changed slightly. Notice the timestamp difference is ~15 seconds and coordinates are updated. This pattern continues until sharing stops.

message (inbound live location - group, update #3)

{
  "event": "message",
  "device_id": "dev_example123",
  "app_id": "app_example123",
  "timestamp": "2026-01-12T12:00:30Z",
  "request_id": "...",
  "payload": {
    "wa_number": "6285211112222",
    "from": "6281234567890@s.whatsapp.net",
    "from_lid": "1234567890987654321@lid",
    "chat": "120363012345678901@g.us",
    "chat_lid": "9876543210987654321@lid",
    "message_id": "LIVE_LOC_GROUP_003",
    "direction": "inbound",
    "message_type": "location",
    "latitude": -6.175420,
    "longitude": 106.827180,
    "location_name": "Moving Location",
    "location_address": "Jakarta, Indonesia",
    "is_group": true,
    "is_view_once": false
  }
}

Live location in group: Same pattern as individual, but is_group is true and chat is the group JID. from identifies who is sharing live location in the group.

message (outbound to group - image with caption)

{
  "event": "message",
  "device_id": "dev_example123",
  "app_id": "app_example123",
  "timestamp": "2026-01-12T11:15:00Z",
  "request_id": "...",
  "payload": {
    "wa_number": "6285211112222",
    "from": "6285211112222:1@s.whatsapp.net",
    "chat": "120363012345678901@g.us",
    "message_id": "GROUP_IMG_OUT_999",
    "direction": "outbound",
    "message_type": "image",
    "text": "Team photo",
    "caption": "Team photo",
    "media_mime_type": "image/jpeg",
    "media_size": 456789,
    "is_group": true,
    "is_view_once": false
  }
}

Outbound media to group: Complete media information is included. is_group is true, chat is the group JID.

message (inbound contact)

{
  "event": "message",
  "device_id": "dev_example123",
  "app_id": "app_example123",
  "timestamp": "2026-01-12T11:20:00Z",
  "request_id": "...",
  "payload": {
    "wa_number": "6285211112222",
    "from": "6281234567890@s.whatsapp.net",
    "from_lid": "1234567890987654321@lid",
    "chat": "6281234567890@s.whatsapp.net",
    "chat_lid": "1234567890987654321@lid",
    "message_id": "CONTACT_MSG_123",
    "direction": "inbound",
    "message_type": "contact",
    "contact_name": "John Doe",
    "contact_vcard": "BEGIN:VCARD\nVERSION:3.0\nFN:John Doe\nTEL;TYPE=CELL:+6281234567890\nEMAIL:john@example.com\nEND:VCARD",
    "is_group": false,
    "is_view_once": false
  }
}

Contact message: Includes contact_name and contact_vcard fields. The vCard contains all contact information in standard format. Auto-farming: The system automatically extracts all phone numbers from the vCard and fetches their profile data (push name, business name, LID, phone JID) in the background.

message (inbound contact - multiple phones)

{
  "event": "message",
  "device_id": "dev_example123",
  "app_id": "app_example123",
  "timestamp": "2026-01-12T11:22:00Z",
  "request_id": "...",
  "payload": {
    "wa_number": "6285211112222",
    "from": "6281234567890@s.whatsapp.net",
    "from_lid": "1234567890987654321@lid",
    "chat": "6281234567890@s.whatsapp.net",
    "chat_lid": "1234567890987654321@lid",
    "message_id": "CONTACT_MULTI_456",
    "direction": "inbound",
    "message_type": "contact",
    "contact_name": "Jane Smith",
    "contact_vcard": "BEGIN:VCARD\nVERSION:3.0\nFN:Jane Smith\nTEL;TYPE=CELL:+6281234567890\nTEL;TYPE=WORK:+6289876543210\nTEL;TYPE=HOME:+6281111111111\nEMAIL:jane@example.com\nEND:VCARD",
    "is_group": false,
    "is_view_once": false
  }
}

Multiple phones: When vCard contains multiple phone numbers, the system will extract and farm profile data for all of them automatically (6281234567890, 6289876543210, 6281111111111 in this example).

receipt (read)

{
  "event": "receipt",
  "device_id": "dev_example123",
  "app_id": "app_example123",
  "timestamp": "2026-01-10T02:16:01Z",
  "request_id": "...",
  "payload": {
    "wa_number": "6285211112222",
    "chat": "6281234567890@s.whatsapp.net",
    "chat_lid": "1234567890987654321@lid",
    "from": "6285211112222:1@s.whatsapp.net",
    "is_group": false,
    "message_ids": ["msg_xyz789"],
    "receipt": "read",
    "timestamp": "2026-01-10T02:16:01Z"
  }
}

presence

{
  "event": "presence",
  "device_id": "dev_example123",
  "app_id": "app_example123",
  "timestamp": "2026-01-03T12:37:15Z",
  "request_id": "...",
  "payload": {
    "from": "15551234567@s.whatsapp.net",
    "last_seen": null,
    "unavailable": false
  }
}

chat_presence

{
  "event": "chat_presence",
  "device_id": "dev_example123",
  "app_id": "app_example123",
  "timestamp": "2026-01-03T12:37:20Z",
  "request_id": "...",
  "payload": {
    "chat": "15551234567@s.whatsapp.net",
    "state": "composing",
    "media": ""
  }
}

message_revoked

{
  "event": "message_revoked",
  "device_id": "dev_example123",
  "app_id": "app_example123",
  "timestamp": "2026-01-03T12:38:00Z",
  "request_id": "...",
  "payload": {
    "wa_number": "15550000001",
    "chat": "15551234567@s.whatsapp.net",
    "from": "15551234567@s.whatsapp.net",
    "message_id": "ABCD1234",
    "timestamp": "2026-01-03T12:38:00Z"
  }
}

warning

{
  "event": "warning",
  "device_id": "dev_example123",
  "app_id": "app_example123",
  "timestamp": "2026-01-03T12:40:00Z",
  "request_id": "...",
  "payload": {
    "reason": "client_outdated",
    "code": ""
  }
}

logout

{
  "event": "logout",
  "device_id": "dev_example123",
  "app_id": "app_example123",
  "timestamp": "2026-01-03T12:41:00Z",
  "request_id": "...",
  "payload": {
    "reason": "logged_out",
    "code": "401"
  }
}

Signature & Retry

  • Headers: X-WA-Signature, X-WA-Signature-Alg, X-WA-Timestamp.
  • Signature base: X-WA-Timestamp + "." + raw_body.
  • Reject stale timestamps and deduplicate by request_id.