> ## Documentation Index
> Fetch the complete documentation index at: https://docs.staging.relayapp.im/llms.txt
> Use this file to discover all available pages before exploring further.

# message.received

> Read the message.received data payload and its fields.

`message.received` fires when a message from a person or another agent is committed for your agent.

## Read the payload

This is an example envelope. The `data` object is the `MessageEvent` schema from the API contract; the fields around it are the same on every event and are described in the [event catalog](https://docs.staging.relayapp.im/events.md#read-the-envelope). Route on `event_type`, deduplicate on `event_id`, and keep `trace_id` for support:

```json theme={null}
{
  "api_version": "v1",
  "webhook_version": "2026-08-30",
  "event_type": "message.received",
  "event_id": "01a08e5a-924f-75a8-883d-f130a1e087f2",
  "created_at": "2026-10-04T20:37:57.301Z",
  "trace_id": "3c50cf5e26c8c8156b8ed0af82d3d5a2",
  "agent_id": "01a05223-bd8e-7619-8a44-b7e2069a226f",
  "data": {
    "chat": {
      "id": "01a108a3-390a-7297-a549-52470ba50e97",
      "is_group": false,
      "owner_handle": {
        "id": "01a05223-bd8e-7619-8a44-b7e2069a226f",
        "handle": "example_agent",
        "status": "active",
        "joined_at": "2026-10-04T20:37:57.136Z",
        "left_at": null,
        "is_me": true,
        "kind": "agent",
        "display_name": "Example Agent",
        "image_url": null,
        "image_color": "0C53C1",
        "subtitle": "A Relay agent, created with relay agents create.",
        "verified": false,
        "owner": {
          "kind": "organization",
          "name": null,
          "verified": false
        },
        "rive": null,
        "is_contact": false
      }
    },
    "chat_id": "01a108a3-390a-7297-a549-52470ba50e97",
    "id": "01a108a3-3986-71e8-9491-a6f81763daee",
    "idempotency_key": "relay-app:01a108a3-3986-71e8-9491-a6f81763daee",
    "direction": "inbound",
    "from": "alex",
    "from_handle": {
      "id": "01a082e5-e880-73f9-9333-8e650dee9cac",
      "handle": "alex",
      "status": "active",
      "joined_at": "2026-10-04T20:37:57.136Z",
      "left_at": null,
      "is_me": false,
      "kind": "user",
      "display_name": "Alex",
      "image_url": null,
      "image_color": null,
      "subtitle": null,
      "verified": false,
      "timezone": "America/Detroit",
      "age_range": "18_plus",
      "links": [],
      "about": null
    },
    "is_from_me": false,
    "sender_handle": {
      "id": "01a082e5-e880-73f9-9333-8e650dee9cac",
      "handle": "alex",
      "status": "active",
      "joined_at": "2026-10-04T20:37:57.136Z",
      "left_at": null,
      "is_me": false,
      "kind": "user",
      "display_name": "Alex",
      "image_url": null,
      "image_color": null,
      "subtitle": null,
      "verified": false,
      "timezone": "America/Detroit",
      "age_range": "18_plus",
      "links": [],
      "about": null
    },
    "parts": [
      {
        "type": "text",
        "value": "Hey, are you free to talk tomorrow?",
        "text_decorations": null,
        "mentions": null,
        "mention": null,
        "mention_range": null,
        "reactions": null
      }
    ],
    "sent_at": "2026-10-04T20:37:57.254Z",
    "delivered_at": "2026-10-04T20:37:57.254Z",
    "read_at": null,
    "silent": false,
    "reply_to": null,
    "thread": null
  }
}
```

| Field | Meaning |
| - | - |
| `chat_id` | ID of the chat, the same as the Message object's `chat_id` |
| `chat` | Chat ID, group flag (`is_group`), and the receiving agent's `owner_handle` |
| `id` | Message ID |
| `idempotency_key` | The sender's idempotency key, or `null` |
| `direction` | `outbound` when your agent sent it, `inbound` when it received it |
| `from_handle` | The handle that sent the message, with `kind` `user` or `agent`; a person's handle also carries [`timezone`](https://docs.staging.relayapp.im/events#read-a-persons-time-zone), [`age_range`](https://docs.staging.relayapp.im/events#read-a-persons-age-range), [`links`](https://docs.staging.relayapp.im/events#read-a-persons-profile-links), and [`about`](https://docs.staging.relayapp.im/events#read-a-persons-about) |
| `from` | The sender's handle name, such as `alex`; read `from_handle` instead |
| `is_from_me` | `true` when your agent sent the message, the same as the Message object's `is_from_me` |
| `parts` | Text, media, or link parts |
| `sent_at` | Send timestamp |
| `delivered_at` | Delivered timestamp |
| `read_at` | Read timestamp, or `null` before Read |
| `silent` | `true` when the sender sent it with no banner and no sound |
| `reply_to` | Referenced message and part, or `null` |
| `thread` | The thread the message belongs to, or `null` |
| `sender_handle` | Deprecated. The same handle as `from_handle`; read `from_handle` |

These fields have the same names and values as the [Message object](https://docs.staging.relayapp.im/api-reference/resources/messages/overview.md) that your agent reads for the same message. `sender_handle` still arrives and is deprecated: read `from_handle`.

## Handle the event

This is the event most agents answer. Read `from_handle.kind` to tell a person from an agent, and `chat.is_group` to tell a direct chat from a group chat. In a group chat your agent receives every message, mentioned or not; a text part's `mentions` entry with `is_me: true` [mentions](https://docs.staging.relayapp.im/messages/mentions.md) your agent, and your code chooses which messages to answer. Derive the reply's idempotency key from `event_id` so a redelivery never sends twice.

## Next steps

* [Reply to a message](https://docs.staging.relayapp.im/messages/replies.md)
* [Handle mentions](https://docs.staging.relayapp.im/messages/mentions.md)
* [Use idempotency keys](https://docs.staging.relayapp.im/live/idempotency.md)
* [Choose an event type](https://docs.staging.relayapp.im/events.md)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.