Inkbox

> # Documentation index
> Fetch the complete documentation index at: https://inkbox.ai/sitemap.xml
> Use this file to discover all available pages before exploring further.

---

# Conversations
description: List and read iMessage conversations, check connection state, send read receipts, and show typing indicators

---


# Conversations

A conversation is one thread between a connected human and an agent identity. Conversations are created automatically when a human connects through the [router](/docs/api/imessage/router) and messages the agent, and they persist as history even if the human later disconnects.

Every conversation read carries an `assignment_status` field reflecting the *current* connection: `"active"` means the recipient is connected right now, `"released"` means they disconnected. Sends, tapbacks, read receipts, and typing indicators into a released conversation return `409` until the recipient reconnects through the router.

---

## List conversations `GET`


List conversation summaries ordered by most recent message, with latest-message preview and unread count.

### Query parameters

| Parameter | Type | Default | Description |
| :--- | :--- | :--- | :--- |
| `agent_identity_id` | UUID | - | Narrow to one identity. Ignored for [identity-scoped API keys](/docs/api-keys), which always see their own identity |
| `limit` | integer | 50 | Number of results (1-200) |
| `offset` | integer | 0 | Pagination offset |
| `is_blocked` | boolean | - | Filter by blocked state of the underlying messages. `true` summarizes blocked rows only, `false` non-blocked rows only, and omitting it applies the caller's default visibility |

Identity-scoped API keys never see blocked rows in conversation summaries. With `is_blocked=false`, previews, ordering, unread counts, and totals are computed from non-blocked rows only.

### Response (200)

```json
[
    {
      "id": "82cf24f6-78fe-48da-a673-6a75b4f4a819",
      "assignment_id": "9b2e4a68-8cb1-4f18-b97d-a2324c8b4d1f",
      "assignment_status": "active",
      "remote_number": "+15555550123",
      "latest_text": "Can you move my 3pm?",
      "latest_message_at": "2026-06-09T14:30:00Z",
      "latest_direction": "inbound",
      "latest_has_media": false,
      "unread_count": 2,
      "total_count": 15
    }
]
```

### Error responses

| Status | Description |
| :--- | :--- |
| 400 | `agent_identity_id` names an identity that is not enabled for iMessage |
| 403 | Identity-scoped key passed an `agent_identity_id` other than its own |
| 404 | `agent_identity_id` not found, or not visible to the caller |

---

## Get conversation `GET`


Get a single conversation by ID. To read the messages in it, use [`GET /messages?conversation_id=...`](/docs/api/imessage/messages#list-messages).

### Path parameters

| Parameter | Type | Description |
| :--- | :--- | :--- |
| `conversation_id` | UUID | Unique identifier of the conversation |

### Query parameters

| Parameter | Type | Description |
| :--- | :--- | :--- |
| `agent_identity_id` | UUID | Optional identity assertion — returns 404 if the conversation belongs to a different identity |

### Response (200)

```json
{
    "id": "82cf24f6-78fe-48da-a673-6a75b4f4a819",
    "assignment_id": "9b2e4a68-8cb1-4f18-b97d-a2324c8b4d1f",
    "assignment_status": "active",
    "remote_number": "+15555550123",
    "created_at": "2026-06-08T09:12:00Z",
    "updated_at": "2026-06-09T14:30:00Z"
}
```

### Error responses

| Status | Description |
| :--- | :--- |
| 404 | Conversation not found, belongs to another organization, or belongs to a different identity than asserted |

---

## List connections `GET`


List active iMessage connections, newest first — one row per recipient currently connected to an agent identity through the [router](/docs/api/imessage/router). Released connections are not returned; use `assignment_status` on conversation reads to detect a disconnect after the fact.

### Query parameters

| Parameter | Type | Default | Description |
| :--- | :--- | :--- | :--- |
| `agent_identity_id` | UUID | - | Narrow to one identity. Ignored for [identity-scoped API keys](/docs/api-keys), which always see their own identity |
| `limit` | integer | 50 | Number of results (1-200) |
| `offset` | integer | 0 | Pagination offset |

### Response (200)

```json
[
    {
      "id": "9b2e4a68-8cb1-4f18-b97d-a2324c8b4d1f",
      "remote_number": "+15555550123",
      "agent_identity_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
      "organization_id": "org_2abc123def456",
      "status": "active",
      "released_at": null,
      "created_at": "2026-06-08T09:11:00Z",
      "updated_at": "2026-06-08T09:11:00Z"
    }
]
```

### Error responses

| Status | Description |
| :--- | :--- |
| 403 | Identity-scoped key passed an `agent_identity_id` other than its own |
| 404 | `agent_identity_id` not found, or not visible to the caller |

---

## Mark conversation read `POST`


Send a read receipt to the human — they see "Read" under their latest message — and mark the conversation's inbound messages as read.

### Request body

| Field | Type | Required | Description |
| :--- | :--- | :--- | :--- |
| `conversation_id` | UUID | Yes | The conversation to mark read |

### Request example

```json
{
    "conversation_id": "82cf24f6-78fe-48da-a673-6a75b4f4a819"
}
```

### Response (200)

```json
{
    "conversation_id": "82cf24f6-78fe-48da-a673-6a75b4f4a819",
    "updated_count": 2
}
```

`updated_count: 0` means no inbound messages needed updating; the read receipt is still sent.

### Error responses

| Status | Description |
| :--- | :--- |
| 400 | The conversation's identity is not enabled for iMessage |
| 403 | The conversation's recipient is blocked by a contact rule |
| 404 | Conversation not found, or not visible to the caller |
| 409 | The recipient has disconnected from this agent and must reconnect through the router |
| 502 | Upstream delivery failure — safe to retry |

---

## Send typing indicator `POST`


Show the typing bubble to the conversation's recipient — useful while your agent prepares a longer reply. The indicator clears on its own or when the next message arrives.

### Request body

| Field | Type | Required | Description |
| :--- | :--- | :--- | :--- |
| `conversation_id` | UUID | Yes | The conversation whose recipient should see the typing bubble |

### Response (200)

```json
{
    "status": "sent"
}
```

### Error responses

| Status | Description |
| :--- | :--- |
| 400 | The conversation's identity is not enabled for iMessage |
| 403 | The conversation's recipient is blocked by a contact rule |
| 404 | Conversation not found, or not visible to the caller |
| 409 | The recipient has disconnected from this agent and must reconnect through the router |
| 502 | Upstream delivery failure — safe to retry |

---

## Conversation object

| Field | Type | Description |
| :--- | :--- | :--- |
| `id` | string (UUID) | Conversation ID — the stable key for reads, replies, mark-read, and typing |
| `assignment_id` | string (UUID) | The connection (one human ↔ one agent) carrying this conversation |
| `assignment_status` | string | `"active"` while the recipient is connected, `"released"` after they disconnect |
| `remote_number` | string | The human's phone number (E.164) |
| `created_at` | string (ISO 8601) | Creation timestamp |
| `updated_at` | string (ISO 8601) | Last update timestamp |

## Conversation summary object

Returned by [List conversations](#list-conversations); adds latest-message preview fields:

| Field | Type | Description |
| :--- | :--- | :--- |
| `latest_text` | string \| null | Latest message body preview |
| `latest_message_at` | string (ISO 8601) \| null | Latest message timestamp |
| `latest_direction` | string \| null | Direction of the latest message |
| `latest_has_media` | boolean | Whether the latest message carries media |
| `unread_count` | integer | Unread inbound message count in the summarized view |
| `total_count` | integer | Total message count in the summarized view |

## Connection object

Returned by [List connections](#list-connections). The pool line carrying the connection is managed by Inkbox and never appears in API responses.

| Field | Type | Description |
| :--- | :--- | :--- |
| `id` | string (UUID) | Connection ID — matches `assignment_id` on conversations |
| `remote_number` | string | The connected human's phone number (E.164) |
| `agent_identity_id` | string (UUID) | The agent identity the human is connected to |
| `organization_id` | string | Owning organization |
| `status` | string | Always `"active"` on returned rows — released connections are not listed |
| `released_at` | string (ISO 8601) \| null | When the connection was released; `null` while active |
| `created_at` | string (ISO 8601) | When the human connected |
| `updated_at` | string (ISO 8601) | Last update timestamp |
