Conversations
A conversation is one stable iMessage thread owned by an agent identity. Shared and dedicated inbound conversations are 1:1 and start when a human messages the agent. A dedicated outbound number can also start 1:1 conversations and group chats. Conversations persist as history after a 1:1 connection is released or a dedicated number is detached.
For 1:1 conversations, assignment_status reflects the current connection: "active" means the recipient is connected right now, and "released" means they disconnected. Group conversations instead return null assignment_id, assignment_status, and remote_number, plus is_group: true, a best-known participants list, and group_creation_status.
List conversations GET
GET /conversationsList 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, which always see their own identity |
include_groups | boolean | false | Include group conversations. Groups are excluded before pagination when false |
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 |
start_datetime | string | - | Only conversations created on or after this date/time |
end_datetime | string | - | Only conversations created on or before this date/time; a bare date includes the whole day |
tz | string | UTC | IANA zone for interpreting zone-less start_datetime/end_datetime values. Defaults to UTC |
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.
start_datetime, end_datetime, and tz filter on the conversation's created_at — when the conversation was created, not its latest-message time. This list is ordered by most recent message, but the date filter is on creation time. Previews, unread counts, totals, and ordering still describe the full conversation — they are not sliced to the window. Both bounds are optional and non-breaking — omit them for unchanged behavior. See Filtering by date.
Response (200)
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 /conversations/{conversation_id}Get a single 1:1 or group conversation by ID. Known group UUIDs work directly even though group list results are opt-in. To read the messages in it, use GET /messages?conversation_id=....
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)
For a group, group_creation_status is "creating" while the first send is establishing the group, "not_created" before creation or after a definitive creation failure, and "ready" after the group is established. A failed creation attempt remains in the same conversation's message history; send another message using its conversation_id to retry. See Group creation lifecycle.
Error responses
| Status | Description |
|---|---|
| 404 | Conversation not found, belongs to another organization, or belongs to a different identity than asserted |
Conversation projections GET
The bounded projection list follows the same compatibility rule: GET /conversation-projections defaults to include_groups=false, and GET /conversation-projections?include_groups=true opts groups in before pagination. GET /conversation-projections/{conversation_id} reads a known group directly.
Projection conversation objects add the same participants and is_group fields and return null assignment/recipient fields for groups. They do not include group_creation_status. MCP conversation reads use this projection surface; MCP can read opted-in groups but cannot send or perform group actions in V1.
List connections GET
GET /assignmentsList active iMessage connections, newest first — one row per recipient currently connected to an agent identity through the 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, which always see their own identity |
limit | integer | 50 | Number of results (1-200) |
offset | integer | 0 | Pagination offset |
Response (200)
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
POST /mark-readSend 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
Response (200)
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, or the conversation is a group and read receipts are not supported for groups |
| 502 | Upstream delivery failure — safe to retry |
Send typing indicator POST
POST /typingShow the typing bubble to a 1:1 conversation's recipient — useful while your agent prepares a longer reply. The indicator clears on its own or when the next message arrives. Group conversations do not support typing indicators.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
conversation_id | UUID | Yes | The conversation whose recipient should see the typing bubble |
Response (200)
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, or the conversation is a group and typing indicators are not supported for groups |
| 502 | Upstream delivery failure — safe to retry |
Conversation object
| Field | Type | Description |
|---|---|---|
id | string (UUID) | Stable conversation key for reads, replies, and supported actions |
assignment_id | string (UUID) | null | The 1:1 connection carrying the conversation; null for groups |
assignment_status | string | null | "active" or "released" for 1:1 conversations; null for groups |
remote_number | string | null | Human's E.164 phone number for a 1:1 conversation; null for groups |
participants | string[] | One E.164 phone number for a 1:1 conversation, or the append-only best-known participant history for a group |
is_group | boolean | Whether this is an iMessage group chat |
group_creation_status | string | null | Group creation lifecycle: "creating", "not_created", or "ready"; null for 1:1 conversations |
created_at | string (ISO 8601) | Creation timestamp |
updated_at | string (ISO 8601) | Last update timestamp |
Conversation summary object
Returned by 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 |
Group summaries use the same nullable assignment/remote fields and participants, is_group, and group_creation_status fields as the conversation object. Groups appear only when include_groups=true.
Connection object
Returned by 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 |