Conversations
Every call needs Authorization: Bearer <key>. 8 calls:
- List conversations:
GET /v1/conversations - Get a conversation with its recent messages and notes:
GET /v1/conversations/:id - Assign, snooze, close, reopen or label a conversation:
PATCH /v1/conversations/:id - Reply in a conversation:
POST /v1/conversations/:id/messages - Add an internal note:
POST /v1/conversations/:id/notes - List saved replies:
GET /v1/saved-replies - Create a saved reply:
POST /v1/saved-replies - Update a saved reply:
PATCH /v1/saved-replies/:id
List conversations
GET /v1/conversations
Most recent activity first. Agents see conversations assigned to them or unassigned.
Query parameters
| Name | Type | Required | Description |
|---|---|---|---|
limit | integer | No | From 1 to 100. Default 50. |
cursor | string | No | Opaque cursor from next_cursor. Up to 512 characters. |
status | enum | No | One of: open, snoozed, closed. |
assignee | string (uuid) or enum | No | A user id, me or unassigned. One of: me, unassigned. |
team_id | string (uuid) | No | |
label | string | No | Up to 64 characters. |
line_id | string | No | Line id (ln_...). |
contact_id | string | No | Contact id (ctc_...). |
q | string | No | Up to 100 characters. |
Headers
| Name | Type | Required | Description |
|---|---|---|---|
x-workspace-id | string | No | Workspace for session (JWT) callers. API keys carry their own workspace. |
Response 200
| Field | Type | Description |
|---|---|---|
data | object[] | |
data[].assignee_user_id | string (uuid) or null | |
data[].contact | object | |
data[].contact.company | string or null | |
data[].contact.first_name | string or null | |
data[].contact.id | string | Contact id (ctc_...). |
data[].contact.last_name | string or null | |
data[].contact.phone | string | Phone number in E.164 format. |
data[].created_at | string (date-time) | ISO 8601 timestamp. |
data[].handled_by | string | |
data[].id | string | Conversation id (cnv_...). |
data[].labels | string[] | |
data[].last_message | object or null | |
data[].last_message.direction | enum | One of: outbound, inbound. |
data[].last_message.id | string | Message id (msg_...). |
data[].last_message.preview | string | Up to 200 characters. |
data[].last_message_at | string (date-time) or null | ISO 8601 timestamp. |
data[].line_id | string or null | Line id (ln_...). |
data[].snoozed_until | string (date-time) or null | ISO 8601 timestamp. |
data[].status | enum | One of: open, snoozed, closed. |
data[].team_id | string (uuid) or null | |
data[].unread_count | integer | From 0 to 9007199254740991. |
data[].updated_at | string (date-time) | ISO 8601 timestamp. |
next_cursor | string or null | Pass as cursor to get the next page; null at the end. |
Errors: 400, 401, 403, 404, 409, 413, 415, 429, 500. See errors for the shape and codes.
Get a conversation with its recent messages and notes
GET /v1/conversations/:id
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Conversation id (cnv_...). |
Query parameters
| Name | Type | Required | Description |
|---|---|---|---|
messages_limit | integer | No | From 1 to 100. Default 50. |
messages_cursor | string | No | Opaque cursor from messages_next_cursor, for older messages. Up to 512 characters. |
Headers
| Name | Type | Required | Description |
|---|---|---|---|
x-workspace-id | string | No | Workspace for session (JWT) callers. API keys carry their own workspace. |
Response 200
| Field | Type | Description |
|---|---|---|
assignee_user_id | string (uuid) or null | |
contact | object | |
contact.company | string or null | |
contact.first_name | string or null | |
contact.id | string | Contact id (ctc_...). |
contact.last_name | string or null | |
contact.phone | string | Phone number in E.164 format. |
created_at | string (date-time) | ISO 8601 timestamp. |
handled_by | string | |
id | string | Conversation id (cnv_...). |
labels | string[] | |
last_message | object or null | |
last_message.direction | enum | One of: outbound, inbound. |
last_message.id | string | Message id (msg_...). |
last_message.preview | string | Up to 200 characters. |
last_message_at | string (date-time) or null | ISO 8601 timestamp. |
line_id | string or null | Line id (ln_...). |
messages | object[] | |
messages[].body | string | |
messages[].channel | enum | One of: imessage, sms. |
messages[].contact_id | string | Contact id (ctc_...). |
messages[].conversation_id | string | Conversation id (cnv_...). |
messages[].created_at | string (date-time) | ISO 8601 timestamp. |
messages[].delivered_at | string (date-time) or null | ISO 8601 timestamp. |
messages[].direction | enum | One of: outbound, inbound. |
messages[].error_code | string or null | |
messages[].error_details | object or null | |
messages[].external_id | string or null | |
messages[].from | string or null | Phone number in E.164 format. |
messages[].id | string | Message id (msg_...). |
messages[].is_test | boolean | |
messages[].line_id | string or null | Line id (ln_...). |
messages[].media | object[] | |
messages[].media[].filename | string or null | |
messages[].media[].mime | string or null | |
messages[].media[].size | integer or null | From 0 to 9007199254740991. |
messages[].media[].url | string | |
messages[].metadata | object | |
messages[].read_at | string (date-time) or null | ISO 8601 timestamp. |
messages[].scheduled_for | string (date-time) or null | ISO 8601 timestamp. |
messages[].sent_at | string (date-time) or null | ISO 8601 timestamp. |
messages[].sent_by_staff | boolean | |
messages[].source | enum or null | One of: api, dashboard, workflow, agent, outreach, mcp. |
messages[].status | enum | One of: queued, scheduled, sending, sent, delivered, read, failed, received. |
messages[].to | string or null | Phone number in E.164 format. |
messages[].updated_at | string (date-time) | ISO 8601 timestamp. |
messages_next_cursor | string or null | Pass as messages_cursor for older messages; null when there are none. |
notes | object[] | The most recent internal notes, newest first. |
notes[].author_user_id | string (uuid) or null | |
notes[].body | string | |
notes[].conversation_id | string | Conversation id (cnv_...). |
notes[].created_at | string (date-time) | ISO 8601 timestamp. |
notes[].id | string (uuid) | |
snoozed_until | string (date-time) or null | ISO 8601 timestamp. |
status | enum | One of: open, snoozed, closed. |
team_id | string (uuid) or null | |
unread_count | integer | From 0 to 9007199254740991. |
updated_at | string (date-time) | ISO 8601 timestamp. |
Errors: 400, 401, 403, 404, 409, 413, 415, 429, 500. See errors for the shape and codes.
Assign, snooze, close, reopen or label a conversation
PATCH /v1/conversations/:id
Agents can update conversations they can see and assign them only to themselves or nobody. Team, labels and handled_by need full inbox access; labels also need contacts access and change the contact's labels. handled_by: agent:<id> needs a live agent, and is refused for test-mode API keys, because the agent then sends live messages.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Conversation id (cnv_...). |
Headers
| Name | Type | Required | Description |
|---|---|---|---|
x-workspace-id | string | No | Workspace for session (JWT) callers. API keys carry their own workspace. |
idempotency-key | string | No | Makes the write safe to retry for 24 hours. 1 to 255 printable characters. Keys starting with outreach:, workflow: or agent: are reserved for messages bubbl3 sends itself and are refused with 400. Up to 255 characters. |
Request body
| Field | Type | Required | Description |
|---|---|---|---|
assignee_user_id | string (uuid) or null | No | |
handled_by | string | No | |
labels | string[] | No | Up to 50 items. |
mark_read | boolean | No | |
snoozed_until | string (date-time) or null | No | ISO 8601 timestamp. |
status | enum | No | One of: open, snoozed, closed. |
team_id | string (uuid) or null | No |
Response 200
| Field | Type | Description |
|---|---|---|
assignee_user_id | string (uuid) or null | |
contact | object | |
contact.company | string or null | |
contact.first_name | string or null | |
contact.id | string | Contact id (ctc_...). |
contact.last_name | string or null | |
contact.phone | string | Phone number in E.164 format. |
created_at | string (date-time) | ISO 8601 timestamp. |
handled_by | string | |
id | string | Conversation id (cnv_...). |
labels | string[] | |
last_message | object or null | |
last_message.direction | enum | One of: outbound, inbound. |
last_message.id | string | Message id (msg_...). |
last_message.preview | string | Up to 200 characters. |
last_message_at | string (date-time) or null | ISO 8601 timestamp. |
line_id | string or null | Line id (ln_...). |
snoozed_until | string (date-time) or null | ISO 8601 timestamp. |
status | enum | One of: open, snoozed, closed. |
team_id | string (uuid) or null | |
unread_count | integer | From 0 to 9007199254740991. |
updated_at | string (date-time) | ISO 8601 timestamp. |
Errors: 400, 401, 403, 404, 409, 413, 415, 429, 500. See errors for the shape and codes.
Reply in a conversation
POST /v1/conversations/:id/messages
Queues a reply to the conversation’s contact, through the same send pipeline as POST /v1/messages. Agents can reply in conversations assigned to them or unassigned.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Conversation id (cnv_...). |
Headers
| Name | Type | Required | Description |
|---|---|---|---|
x-workspace-id | string | No | Workspace for session (JWT) callers. API keys carry their own workspace. |
idempotency-key | string | No | Makes the write safe to retry for 24 hours. 1 to 255 printable characters. Keys starting with outreach:, workflow: or agent: are reserved for messages bubbl3 sends itself and are refused with 400. Up to 255 characters. |
Request body
| Field | Type | Required | Description |
|---|---|---|---|
body | string | No | Up to 2000 characters. |
media | object[] | No | Up to 10 items. |
media[].filename | string | No | Up to 255 characters. |
media[].mime | string | No | Up to 100 characters. |
media[].url | string (uri) | Yes | Publicly fetchable URL of the file. Up to 2048 characters. |
Response 201
| Field | Type | Description |
|---|---|---|
body | string | |
channel | enum | One of: imessage, sms. |
contact_id | string | Contact id (ctc_...). |
conversation_id | string | Conversation id (cnv_...). |
created_at | string (date-time) | ISO 8601 timestamp. |
delivered_at | string (date-time) or null | ISO 8601 timestamp. |
direction | enum | One of: outbound, inbound. |
error_code | string or null | |
error_details | object or null | |
external_id | string or null | |
from | string or null | Phone number in E.164 format. |
id | string | Message id (msg_...). |
is_test | boolean | |
line_id | string or null | Line id (ln_...). |
media | object[] | |
media[].filename | string or null | |
media[].mime | string or null | |
media[].size | integer or null | From 0 to 9007199254740991. |
media[].url | string | |
metadata | object | |
read_at | string (date-time) or null | ISO 8601 timestamp. |
scheduled_for | string (date-time) or null | ISO 8601 timestamp. |
sent_at | string (date-time) or null | ISO 8601 timestamp. |
sent_by_staff | boolean | |
source | enum or null | One of: api, dashboard, workflow, agent, outreach, mcp. |
status | enum | One of: queued, scheduled, sending, sent, delivered, read, failed, received. |
to | string or null | Phone number in E.164 format. |
updated_at | string (date-time) | ISO 8601 timestamp. |
Errors: 400, 401, 403, 404, 409, 413, 415, 429, 500. See errors for the shape and codes.
Add an internal note
POST /v1/conversations/:id/notes
Notes are visible to the team only and are never sent to the contact.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Conversation id (cnv_...). |
Headers
| Name | Type | Required | Description |
|---|---|---|---|
x-workspace-id | string | No | Workspace for session (JWT) callers. API keys carry their own workspace. |
idempotency-key | string | No | Makes the write safe to retry for 24 hours. 1 to 255 printable characters. Keys starting with outreach:, workflow: or agent: are reserved for messages bubbl3 sends itself and are refused with 400. Up to 255 characters. |
Request body
| Field | Type | Required | Description |
|---|---|---|---|
body | string | Yes | Up to 5000 characters. |
Response 201
| Field | Type | Description |
|---|---|---|
author_user_id | string (uuid) or null | |
body | string | |
conversation_id | string | Conversation id (cnv_...). |
created_at | string (date-time) | ISO 8601 timestamp. |
id | string (uuid) |
Errors: 400, 401, 403, 404, 409, 413, 415, 429, 500. See errors for the shape and codes.
List saved replies
GET /v1/saved-replies
Agents see replies for everyone and for their own team.
Headers
| Name | Type | Required | Description |
|---|---|---|---|
x-workspace-id | string | No | Workspace for session (JWT) callers. API keys carry their own workspace. |
Response 200
| Field | Type | Description |
|---|---|---|
data | object[] | |
data[].body | string | |
data[].created_at | string (date-time) | ISO 8601 timestamp. |
data[].id | string (uuid) | |
data[].team_id | string (uuid) or null | |
data[].title | string | |
data[].updated_at | string (date-time) | ISO 8601 timestamp. |
Errors: 400, 401, 403, 404, 409, 413, 415, 429, 500. See errors for the shape and codes.
Create a saved reply
POST /v1/saved-replies
Headers
| Name | Type | Required | Description |
|---|---|---|---|
x-workspace-id | string | No | Workspace for session (JWT) callers. API keys carry their own workspace. |
idempotency-key | string | No | Makes the write safe to retry for 24 hours. 1 to 255 printable characters. Keys starting with outreach:, workflow: or agent: are reserved for messages bubbl3 sends itself and are refused with 400. Up to 255 characters. |
Request body
| Field | Type | Required | Description |
|---|---|---|---|
body | string | Yes | Up to 2000 characters. |
team_id | string (uuid) or null | No | |
title | string | Yes | Up to 120 characters. |
Response 201
| Field | Type | Description |
|---|---|---|
body | string | |
created_at | string (date-time) | ISO 8601 timestamp. |
id | string (uuid) | |
team_id | string (uuid) or null | |
title | string | |
updated_at | string (date-time) | ISO 8601 timestamp. |
Errors: 400, 401, 403, 404, 409, 413, 415, 429, 500. See errors for the shape and codes.
Update a saved reply
PATCH /v1/saved-replies/:id
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
id | string (uuid) | Yes |
Headers
| Name | Type | Required | Description |
|---|---|---|---|
x-workspace-id | string | No | Workspace for session (JWT) callers. API keys carry their own workspace. |
idempotency-key | string | No | Makes the write safe to retry for 24 hours. 1 to 255 printable characters. Keys starting with outreach:, workflow: or agent: are reserved for messages bubbl3 sends itself and are refused with 400. Up to 255 characters. |
Request body
| Field | Type | Required | Description |
|---|---|---|---|
body | string | No | Up to 2000 characters. |
team_id | string (uuid) or null | No | |
title | string | No | Up to 120 characters. |
Response 200
| Field | Type | Description |
|---|---|---|
body | string | |
created_at | string (date-time) | ISO 8601 timestamp. |
id | string (uuid) | |
team_id | string (uuid) or null | |
title | string | |
updated_at | string (date-time) | ISO 8601 timestamp. |
Errors: 400, 401, 403, 404, 409, 413, 415, 429, 500. See errors for the shape and codes.