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

# Concepts

> Relay contacts, conversations, messages, parts, and delivery semantics.

## Contacts and users

A **user** is a person using Relay. An **agent** appears to that person as a **contact**. The Agent Token authenticates external code as that contact; it does not create a user session or run the agent inside Relay.

## Conversations and participants

A conversation has a stable `conversation_id` and participants. A direct conversation normally contains one user and one contact. An agent can send only to a conversation in which its contact is an active participant and installed for the user.

Use the `conversation_id` supplied in `message.received`. Agents can read a conversation's history with `GET /v1/conversations/{id}/messages`.

## Messages and ordered parts

A message carries an ordered `parts[]` array. Relay assigns each stored part a zero-based `part_index`. Keep the array order: it is presentation order and provides a stable target for replies and future interactions.

| Type    | v0 shape                                            | Meaning                                      |
| ------- | --------------------------------------------------- | -------------------------------------------- |
| `text`  | `{ "type": "text", "text": "Hello" }`               | Text content.                                |
| `link`  | `{ "type": "link", "text": "https://example.com" }` | An HTTP or HTTPS URL.                        |
| `data`  | `{ "type": "data", "payload": { ... } }`            | Structured JSON content.                     |
| `media` | `{ "type": "media", "attachment_id": "att_..." }`   | An existing media attachment reference.      |
| `voice` | `{ "type": "voice", "attachment_id": "att_..." }`   | An existing voice-note attachment reference. |

The v0 send route accepts 1–32 parts. Text is limited to 8 KB per part and data payloads to 16 KB. Public attachment upload is **coming soon**, so a new developer integration can send text, links, and data today but cannot create a new `attachment_id` through the developer API yet.

Stored messages include:

```json theme={null}
{
  "id": "msg_01JZM3T8AH",
  "conversation_id": "cnv_01JZC7K4RQ",
  "sequence": 7,
  "sender": { "kind": "contact", "id": "agt_01JZRELAY" },
  "parts": [
    { "part_index": 0, "type": "text", "text": "Here is the link:" },
    { "part_index": 1, "type": "link", "text": "https://example.com" }
  ],
  "reply_to": null,
  "fallback_text": "Here is the link:",
  "status": "sent",
  "created_at": "2026-07-12T01:21:08.000Z"
}
```

`fallback_text` is the plain-language representation used by notifications, search, and clients that cannot render a part. In v0 Relay derives it from the first text part, then the first link, or finally `[attachment]`. The developer send route does not accept a `fallback_text` override.

## Sequence and cursor

`message.sequence` is the message's order inside one conversation. It is not the polling cursor.

`next_cursor` is an opaque position in an agent's event log. Persist it exactly and return it as `cursor`; do not decode it or calculate a replacement. Passing it acknowledges the earlier events.

## At-least-once delivery

Polling and webhooks are at-least-once transports. The same envelope may arrive again, and webhook attempts may arrive out of order. Process each `event_id` once:

1. Verify the webhook signature when applicable.
2. Atomically record `event_id` if it is new.
3. Return success or advance the polling cursor promptly.
4. Process the event asynchronously.

Use the incoming `event_id` to derive the reply's `Idempotency-Key`. Reusing the same key with the same request returns the original message. Reusing it with a different request returns `idempotency_conflict`.

<Warning>
  Attachments and uploads, typing and read state, edits, unsends, socket mode, store distribution, and calls are specified for Relay but are not implemented in the v0 developer API.
</Warning>
