Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.ryzeapi.cloud/llms.txt

Use this file to discover all available pages before exploring further.

Webhook and WebSocket share the same envelope and the same catalog of events. The only difference is the delivery channel, data is identical. This page documents the 6 types: message.exchange, message.status, call.update, group.flow, instance.state and label.update.

Envelope

{
  "event": "<event-name>",
  "data": { /* event-specific payload */ },
  "instanceData": {
    "baseUrl": "https://api.example.com",
    "instance": "<name>",
    "token":    "<instance-token>"
  }
}
Filtering is done by the event name in the events field of the config. Empty = all types.

Filtering and routing

{ "events": ["message.exchange", "call.update", "instance.state"] }
When byEvents=true (webhook only), the event name is appended to the URL:
  • Config: url: "https://app/wh", byEvents: true
  • Delivery: POST https://app/wh/message.exchange
Useful for endpoint-based routing without inspecting the payload.

message.exchange

Messages sent and received (text, media, sticker, document, audio, poll, contact, location, etc.), edits and revocations.

Payload

{
  "id": "wamid.msg.123",
  "message": {
    "id": "wamid.msg.123",
    "direction": "incoming | outgoing",
    "timestamp": "2026-04-28T10:30:00Z",
    "chat": {
      "jid": "5511999999999",
      "lid": "100@s.whatsapp.net",
      "name": "João Silva",
      "type": "private | group | newsletter",
      "isCommunity": true
    },
    "sender": {
      "jid": "5511999999999",
      "lid": "100@s.whatsapp.net",
      "name": "João Silva"
    },
    "content": { "text": "Hello" },
    "media": {
      "type": "image | video | audio | document | sticker | ptt | ptv",
      "url": "https://media-...whatsapp.net/...",
      "s3Url": "https://bucket.s3.amazonaws.com/...",
      "base64": "iVBORw0KGgo...",
      "mimetype": "image/jpeg",
      "size": 45678,
      "caption": "Event photo",
      "fileName": "doc.pdf"
    },
    "edit": {
      "original_id": "wamid.original",
      "originalContent": "Old text",
      "text": "New text"
    },
    "forward": { "count": 2 },
    "reply": {
      "message_id": "wamid.replied",
      "sender": { "jid": "...", "name": "..." },
      "text": "...",
      "media": { /* simplified media object */ }
    },
    "poll": {
      "title": "Which flavor?",
      "options": [{ "name": "Chocolate", "count": 0 }]
    },
    "location": {
      "latitude": -23.5505,
      "longitude": -46.6333,
      "address": "Av. Paulista, 1374"
    },
    "contact": {
      "display_name": "Maria",
      "phone_number": "5511987654321",
      "vcard": "BEGIN:VCARD..."
    },
    "list_response": {
      "title": "...",
      "body": "...",
      "list_type": "single_select",
      "single_select_reply": { "option_name": "p1" }
    },
    "button_response": {
      "title": "Buy",
      "body": "...",
      "selected_button_id": "buy_camiseta"
    },
    "interactive": { /* form / native flow / other surfaces */ }
  }
}

Conditional fields

Only the fields relevant to the message type are populated. Edits have edit populated; revocations arrive with type: "message_revoke" in data.message.type.
chat.isCommunity appears only when true, indicating the chat is the announcement channel (parent / announcement channel) of a WhatsApp community. Subgroups linked to a community keep type: "group" and do not include the isCommunity field. In regular groups and DMs the field is also omitted.
media.base64 only appears when mediaBase64=true in the config (webhook or WebSocket). Otherwise, use media.url (whatsapp.net, expires) or media.s3Url (if S3 is configured on the instance).

Example (image received)

{
  "event": "message.exchange",
  "data": {
    "id": "wamid.123",
    "message": {
      "id": "wamid.123",
      "direction": "incoming",
      "timestamp": "2026-04-28T10:30:00Z",
      "chat":   { "jid": "5511999999999", "name": "João", "type": "private" },
      "sender": { "jid": "5511999999999", "name": "João" },
      "media": {
        "type":     "image",
        "url":      "https://media-abc.whatsapp.net/...",
        "mimetype": "image/jpeg",
        "size":     45678,
        "caption":  "Photo"
      }
    }
  },
  "instanceData": { "baseUrl": "https://api...", "instance": "minha", "token": "..." }
}

message.status

Delivery receipts: delivered, read, played, etc.

Payload

{
  "status": "delivered | read | played | sender | read_self | played_self | retry | inactive | server_error",
  "messageIds": ["wamid.123", "wamid.124"],
  "timestamp":  "2026-04-28T10:45:00Z",
  "chat": {
    "jid": "5511999999999",
    "type": "private | group | broadcast",
    "isCommunity": true
  },
  "recipient":     "5511999999999",
  "messageSender": null,
  "isFromMe":      false
}

status enum

ValueMeaning
deliveredMessage reached the recipient’s device.
readRecipient read it (read receipts on).
playedAudio/voice note was played.
senderInternal echo (the source itself reporting delivery).
read_selfThe user themselves marked it as read on another device.
played_selfThe user themselves played it on another device.
retryServer requested redelivery (transient).
inactiveRecipient has been offline too long.
server_errorGeneric WhatsApp server error.
  • messageSender in groups: JID of the original message author (relevant when someone reads a message from another participant).
  • chat.isCommunity follows the same rule as message.exchange: present and true only when the chat is the announcement channel of a community.

call.update

Call events: offer, accepted, rejected, terminated, latency.

Payload

{
  "type": "offer | accepted | rejected | terminated | notification | latency",
  "direction": "incoming | outgoing",
  "callId": "call-abc123",
  "from": "5511999999999",
  "to":   "5511888888888",
  "timestamp": "2026-04-28T10:35:00Z",
  "groupJid": null,
  "callMedia": "audio | video | null",
  "remotePlatform": "Android | iPhone | null",
  "remoteVersion": "2.23.15.74",
  "noticeType": "group | null",
  "reason": null,
  "duration": 123,
  "latency":  45.6,
  "latencyStatus": "Excellent | Good | Average | Poor"
}

type enum

ValueWhen it fires
offerCall received/sent (initial ring).
acceptedRemote side answered.
rejectedRemote side rejected.
terminatedCall ended, duration in seconds is populated.
notificationContextual call notification (e.g., missed group call).
latencyLatency metric during the call (latency in ms, latencyStatus).
To auto-reject calls, set autoRejectCalls=true in the instance settings block, you still receive the offer + rejected events on the webhook.

group.flow

Group changes: members, metadata, settings.

Payload, participant change

{
  "type": "joined | left | promoted | demoted",
  "groupJid": "120363406289005073@g.us",
  "groupName": "Dev Team",
  "timestamp": "2026-04-28T11:00:00Z",
  "participants": [
    { "jid": "5511999999999", "action": "joined" }
  ]
}

Metadata subtypes

typeMeaning
nameGroup name changed
topicDescription changed
locked / unlockedMembers can/cannot edit info
announce / not_announceMembers can/cannot send messages
ephemeral / not_ephemeralEphemeral messages on/off
inviteInvite link generated
link / unlinkSubgroup linked/unlinked from community
deleteGroup deleted
membership_approvalApproval mode for new members changed
suspended / unsuspendedGroup suspended/reactivated by WhatsApp

instance.state

Changes in the instance’s own state (connection, QR, ban, pairing).

Payload

{
  "instance": "minha",
  "state": "connected | disconnected | logged_out | stream_replaced | temp_banned | client_outdated | connect_failure | stream_error | cat_refresh_error | qr_ready | pair_success | pair_error | qr_scanned_no_multidevice | keepalive_timeout | keepalive_restored | manual_reconnect",
  "timestamp": "2026-04-28T10:50:00Z",
  "reason": "...",
  "reasonCode": 123,
  "message": "...",
  "expireAt": "2026-04-28T11:50:00Z",
  "expireInSeconds": 3600,
  "onConnect": true,
  "codes": ["1@abc...,xyz==,base64string"],
  "jid": "5511999999999@s.whatsapp.net",
  "platform": "iPhone | Android | Desktop",
  "errorMsg": "..."
}

state enum

StateMeaningExtra fields populated
connectedActive session, ready to send/receive.
disconnectedDisconnected (transient, usually reconnects on its own).
logged_outSession invalidated (requires new connect).reason
stream_replacedAnother session took over (multi-device conflict).
temp_bannedTemporary ban applied by WhatsApp.expireAt, expireInSeconds, reason
client_outdatedThe WhatsApp Web version in use is outdated, contact support.message
connect_failureFailure during connection.reason, reasonCode
stream_errorWhatsApp stream error.errorMsg
cat_refresh_errorFailed to refresh credentials (cat).errorMsg
qr_readyNew QR available for pairing.codes[], onConnect
pair_successPairing completed.jid, platform
pair_errorError during pairing.errorMsg
qr_scanned_no_multideviceQR scanned but the target device does not support multidevice.
keepalive_timeoutUnstable connection, keepalive not answered.
keepalive_restoredConnection stabilized after keepalive_timeout.
manual_reconnectReconnection triggered manually via REST.
So your client knows when to refresh the QR in the UI, listen for instance.state with state=qr_ready and render data.codes[0].

label.update

Label edits/associations (WhatsApp Business labels).

Payload

{
  "type":   "edit | chat | message",
  "labelId": "1",
  "timestamp": "2026-04-28T10:00:00Z",
  "action": "updated | deleted | add | remove",

  // type=edit:
  "name": "Important",
  "color": 0,
  "labelType": "CUSTOM",
  "isActive": true,
  "isImmutable": false,
  "orderIndex": 1,
  "deleted": false,

  // type=chat:
  "chatJid": "5511999999999@s.whatsapp.net",
  "labeled": true,

  // type=message:
  "messageId": "wamid.abc"
}

type × action combinations

typevalid actionExtra fields
editupdated, deletedname, color, labelType, isActive, isImmutable, orderIndex, deleted
chatadd, removechatJid, labeled
messageadd, removechatJid, messageId

Events not emitted (internal)

Captured by the whatsmeow handler but not propagated via webhook/WS:
  • *events.Picture, profile picture change (logged only).
  • *events.FBMessage, Facebook Business (logged only).
  • *events.HistorySync, history sync (processed and stored in DB).
If you need to consume any of these changes, poll the corresponding REST endpoints (profile, history).

References

Configure webhook

Filter events via events[] in the config.

Configure WebSocket

Same filter syntax as the webhook.

Connect via WebSocket

Receive events in real time.

Events overview

Webhook vs WebSocket comparison.