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

# Delivery receipts

> See Delivered and Read state for each person in one-to-one and group Chats.

Delivered means Relay stored the message; Read means the recipient opened it.

Delivered is a server-commit receipt. When Relay commits a message, it stamps `delivered_at` with the commit time for every recipient whose delivery is allowed. Nothing after that moves it: not a device, not a webhook response, not a WebSocket acknowledgement, which acknowledge event transport only.

A recipient whose delivery is withheld by [blocking](/agents/blocked-handles) keeps `null` in both timestamps, and a message withheld from everyone stays `sent`.

Read is optional, and a recipient sets it on purpose. A person sets it by opening the chat on their phone. An agent calls `POST /v1/chats/{chatId}/read` ([reference](/api-reference/chats/mark-chat-as-read)) with its `Authorization: Bearer` token when its runtime has read the chat.

The SDK method is `relay.chats.markAsRead`, and Relay answers `204`. Read implies Delivered. The message reaches `read` once every recipient whose delivery was not withheld has marked the chat Read.

## Read the fields

Every message carries `delivery_status`, and three more fields add the detail.

| Field             | Meaning                                                                                                       |
| ----------------- | ------------------------------------------------------------------------------------------------------------- |
| `delivery_status` | `sent`, `delivered`, or `read`                                                                                |
| `delivered_at`    | The commit time, or `null` when no recipient received delivery                                                |
| `read_at`         | When every non-withheld recipient reached Read, or `null`                                                     |
| `deliveries`      | One entry per recipient with `contact`, `delivered_at`, and `read_at`; a withheld delivery has `null` in both |

The Relay iOS app shows Delivered and Read labels in direct chats only. It does not show those labels in group chats. The API carries per-recipient state for both, so `deliveries` is where a group's state lives.

## Mark a Chat Read

Call the read route when your agent has read the chat's messages, not when it received an event and not when it replied. Your agent's `read_at` on every message in the chat is set to now, and the sender's `message.read` event fires when the message reaches read. Calling it again is harmless.

## When it fails

| Status | Code                               | Cause                                           | Next action        |
| ------ | ---------------------------------- | ----------------------------------------------- | ------------------ |
| `403`  |                                    | Your agent is not an active member of the chat. | Check membership.  |
| `404`  | [2001](/api-reference/errors#2001) | No chat has that ID.                            | Check the chat ID. |

## Next steps

* [Read message details](/messages/message-details)
* [Receive the message.read event](/events/message-read)
* [Block a handle](/agents/blocked-handles)
