List messages
Returns the messages in a conversation in chronological order (oldest first). Internal operator notes are never included.
List messages in a conversation (cursor-paginated, oldest first).
Response
{
"results": [
{
"id": "a1000000-0000-4000-8000-000000000001",
"conversation_id": "3f2b1c9a-7d4e-4b21-9c33-0a1b2c3d4e5f",
"thread_id": null,
"sender_type": "CLIENT",
"content": "Where is my order?",
"is_internal_note": false,
"reply_to_id": null,
"created_at": "2026-07-01T10:30:00+00:00",
"attachments": []
},
{
"id": "b2d7e410-3c88-4a15-9f60-7d8e9a0b1c2d",
"conversation_id": "3f2b1c9a-7d4e-4b21-9c33-0a1b2c3d4e5f",
"thread_id": null,
"sender_type": "OPERATOR",
"content": "It shipped this morning \u2014 tracking below.",
"is_internal_note": false,
"reply_to_id": null,
"created_at": "2026-07-01T10:40:00+00:00",
"attachments": []
}
],
"next_cursor": null,
"has_more": false
}The message object
- id, conversation_id, thread_id (usually
null). - sender_type —
CLIENT(the customer),OPERATOR,AI, orSYSTEM. - content — the message text.
- is_internal_note — always
falsehere. - reply_to_id — id of the message this replies to, or
null. - created_at — ISO-8601.
- attachments — array of
{ id, filename, content_type, size }.
Send a message
Delivers a message to the customer through the conversation’s channel. The message is recorded as an OPERATOR message tagged as sent via the API. It appears live in the operator dashboard.
Send a message into an existing conversation.
Request
{
"content": "Your refund of $20.00 has been processed.",
"reply_to_message_id": null,
"sender_user_id": null
}Responses
{
"id": "b2d7e410-3c88-4a15-9f60-7d8e9a0b1c2d",
"conversation_id": "3f2b1c9a-7d4e-4b21-9c33-0a1b2c3d4e5f",
"thread_id": null,
"sender_type": "OPERATOR",
"content": "Your refund of $20.00 has been processed.",
"is_internal_note": false,
"reply_to_id": null,
"created_at": "2026-07-01T10:41:00+00:00",
"attachments": []
}{ "detail": "conversation_closed" }Body fields
- content — required; the message text (max 4096 characters).
- reply_to_message_id — optional; id of a message in the same conversation to reply to.
- sender_user_id — optional; attribute the message to a teammate instead of the key itself. See Who the message is from below.
Who the message is from
A message sent through the API is recorded as an OPERATOR message with no human behind it, so you decide whose name and picture the customer sees. There are two options, and you choose per message.
From the key itself (default)
Each API key has a sender name and an optional picture, set on the Developer page. Send without naming anyone and the customer sees those — for example a key called Order Bot appears as “Order Bot”. If you leave the sender name blank, the key’s own name is used, so a message is never anonymous.
From one of your teammates
Pass sender_user_id and the message is attributed to that person instead — their name and avatar, exactly as if they had typed it in the dashboard. This is what you want when you are relaying replies your agents wrote somewhere else.
{
"content": "Your refund has been processed.",
"sender_user_id": "7c1e5a02-9b43-4f18-8a77-2d6e0f4b9c81"
}Get the ids from GET /api/v1/operators/. The person must be a member of the same project; anyone else returns 400 sender_user_not_a_project_member. Either way the acting key is recorded, so you keep an audit trail.
You cannot pass a free-form name or picture on a message. Attribution is an id so that it can be checked — otherwise any key could impersonate a named operator to your customers.
Names in other languages
The sender name can have a per-language version, like your AI assistant’s name and your operators’ nicknames. Customers see the name for their conversation’s language; a language you have not filled in falls back to the base name. Add them on the Developer page, under the key’s identity.
Notes & limits
- Sending to a
CLOSEDconversation returns400 conversation_closed. - Group (Telegram group) conversations are not supported in v1 (
400 group_conversations_not_supported). - An empty
contentreturns400 content_required. - Rate limit: 60 requests/minute per API key.