> ## 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.

# Event catalog

> Schemas, enums and examples for the 6 event types delivered via webhook and WebSocket

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

```json theme={null}
{
  "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

```json theme={null}
{ "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

```json theme={null}
{
  "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`.

<Note>
  `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.
</Note>

<Tip>
  `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).
</Tip>

### Example (image received)

```json theme={null}
{
  "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

```json theme={null}
{
  "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

| Value          | Meaning                                                      |
| -------------- | ------------------------------------------------------------ |
| `delivered`    | Message reached the recipient's device.                      |
| `read`         | Recipient read it (read receipts on).                        |
| `played`       | Audio/voice note was played.                                 |
| `sender`       | Internal echo (the source itself reporting delivery).        |
| `read_self`    | The **user themselves** marked it as read on another device. |
| `played_self`  | The user themselves played it on another device.             |
| `retry`        | Server requested redelivery (transient).                     |
| `inactive`     | Recipient has been offline too long.                         |
| `server_error` | Generic WhatsApp server error.                               |

<Note>
  * `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.
</Note>

***

## `call.update`

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

### Payload

```json theme={null}
{
  "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

| Value          | When it fires                                                      |
| -------------- | ------------------------------------------------------------------ |
| `offer`        | Call received/sent (initial ring).                                 |
| `accepted`     | Remote side answered.                                              |
| `rejected`     | Remote side rejected.                                              |
| `terminated`   | Call ended, `duration` in seconds is populated.                    |
| `notification` | Contextual call notification (e.g., missed group call).            |
| `latency`      | Latency metric during the call (`latency` in ms, `latencyStatus`). |

<Tip>
  To auto-reject calls, set `autoRejectCalls=true` in the [instance settings block](/en/api/instance/settings-update), you still receive the `offer` + `rejected` events on the webhook.
</Tip>

***

## `group.flow`

Group changes: members, metadata, settings.

### Payload, participant change

```json theme={null}
{
  "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

| `type`                        | Meaning                                 |
| ----------------------------- | --------------------------------------- |
| `name`                        | Group name changed                      |
| `topic`                       | Description changed                     |
| `locked` / `unlocked`         | Members can/cannot edit info            |
| `announce` / `not_announce`   | Members can/cannot send messages        |
| `ephemeral` / `not_ephemeral` | Ephemeral messages on/off               |
| `invite`                      | Invite link generated                   |
| `link` / `unlink`             | Subgroup linked/unlinked from community |
| `delete`                      | Group deleted                           |
| `membership_approval`         | Approval mode for new members changed   |
| `suspended` / `unsuspended`   | Group suspended/reactivated by WhatsApp |

***

## `instance.state`

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

### Payload

```json theme={null}
{
  "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

| State                       | Meaning                                                        | Extra fields populated                  |
| --------------------------- | -------------------------------------------------------------- | --------------------------------------- |
| `connected`                 | Active session, ready to send/receive.                         | ,                                       |
| `disconnected`              | Disconnected (transient, usually reconnects on its own).       | ,                                       |
| `logged_out`                | Session invalidated (requires new `connect`).                  | `reason`                                |
| `stream_replaced`           | Another session took over (multi-device conflict).             | ,                                       |
| `temp_banned`               | Temporary ban applied by WhatsApp.                             | `expireAt`, `expireInSeconds`, `reason` |
| `client_outdated`           | The WhatsApp Web version in use is outdated, contact support.  | `message`                               |
| `connect_failure`           | Failure during connection.                                     | `reason`, `reasonCode`                  |
| `stream_error`              | WhatsApp stream error.                                         | `errorMsg`                              |
| `cat_refresh_error`         | Failed to refresh credentials (`cat`).                         | `errorMsg`                              |
| `qr_ready`                  | New QR available for pairing.                                  | `codes[]`, `onConnect`                  |
| `pair_success`              | Pairing completed.                                             | `jid`, `platform`                       |
| `pair_error`                | Error during pairing.                                          | `errorMsg`                              |
| `qr_scanned_no_multidevice` | QR scanned but the target device does not support multidevice. | ,                                       |
| `keepalive_timeout`         | Unstable connection, keepalive not answered.                   | ,                                       |
| `keepalive_restored`        | Connection stabilized after `keepalive_timeout`.               | ,                                       |
| `manual_reconnect`          | Reconnection triggered manually via REST.                      | ,                                       |

<Tip>
  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]`.
</Tip>

***

## `label.update`

Label edits/associations (WhatsApp Business labels).

### Payload

```json theme={null}
{
  "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

| `type`    | valid `action`       | Extra fields                                                                     |
| --------- | -------------------- | -------------------------------------------------------------------------------- |
| `edit`    | `updated`, `deleted` | `name`, `color`, `labelType`, `isActive`, `isImmutable`, `orderIndex`, `deleted` |
| `chat`    | `add`, `remove`      | `chatJid`, `labeled`                                                             |
| `message` | `add`, `remove`      | `chatJid`, `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

<CardGroup cols={2}>
  <Card title="Configure webhook" icon="webhook" href="/en/api/events/webhook-configure">
    Filter events via `events[]` in the config.
  </Card>

  <Card title="Configure WebSocket" icon="plug" href="/en/api/events/websocket-configure">
    Same filter syntax as the webhook.
  </Card>

  <Card title="Connect via WebSocket" icon="bolt" href="/en/api/websocket">
    Receive events in real time.
  </Card>

  <Card title="Events overview" icon="bell" href="/en/api/events/overview">
    Webhook vs WebSocket comparison.
  </Card>
</CardGroup>
