Developer Docs Logo
API RequestsAPI SchemaChats

Send Conversation Message

POST/v1/conversations/{conversation_id}/messages

Sends a message to a conversation. The message is enqueued for asynchronous delivery. Supports plain text messages and forms. Requires chat:write scope.

Closing the conversation in the same call

Set transition_status_to to close the conversation right after this message is delivered — for a goodbye note, or a "this chat has ended" notice. Use this rather than sending the message and then calling PUT /v1/conversations/{id}/status yourself: as two separate requests they can overtake each other.

ValueMeaning
RESOLVEDClosed, but the contact reopens it by sending another message.
FINALIZEDPermanently closed. You will need a new conversation next time.
OPENNot accepted. Sending any message into a resolved conversation reopens it already.
RuleBehavior
OrderingThe message always lands first — the conversation is only closed once the message is persisted, so the customer never sees a closed chat missing your last message.
ResponseStill 202, immediately. The close happens moments later in the background; the response acknowledges the message, not the close.
End stateThe one you asked for, whatever the conversation was doing beforehand. If it was already closed, the message reopens it and it closes again — agents may see a brief reopen in the history. If it was already in the requested state, nothing changes.
FINALIZED from OPENResolved first, then finalized — matching PUT /v1/conversations/{id}/status.
EnablementRequires the capability to be switched on for your workspace. Until it is, the field is silently ignored: the message is sent normally and returns 202, but the conversation stays open.
Already FINALIZEDA finalized conversation rejects new messages, so this cannot add a farewell to a chat that is already permanently closed. Create a new conversation instead.
Invalid value400, and no message is sent. (While the capability is off nothing is validated, so the same request returns 202 instead.)

Best-effort, and a failure is silent. The message is never affected — it is sent, stored and delivered regardless. But if the close itself fails (transient backend problem, or someone changed the status in the meantime) the conversation keeps its previous status and nothing tells you: the 202 was only ever about the message, and there is no webhook for a close that did not happen. If the final status matters, read it back with GET /v1/conversations/{id} and fall back to PUT /v1/conversations/{id}/status.

Authorization

BearerAuth
AuthorizationBearer <token>

In: header

Path Parameters

conversation_id*string

The unique identifier (UUID) of the conversation that will receive the message.

Formatuuid

Request Body

application/json

The message content, type, and sender information.

TypeScript Definitions

Use the request body type in TypeScript.

Request body for sending a conversation message. Supports plain text messages, forms, and attachments.

Response Body

application/json

application/json

application/json

application/json

application/json

application/json

curl -X POST "https://example.com/v1/conversations/8b86b34d-3d4e-4f20-9d55-9d4c93d0b8a2/messages" \  -H "Content-Type: application/json" \  -d '{    "content": "Hello, how can I help you today?",    "message_type": "MESSAGE",    "send_as": {      "agent_id": "9e9097a8-5c9a-4e1e-8218-3b833d8b0039"    },    "transition_status_to": "RESOLVED"  }'
{  "request_id": "ca9b5a07-1d77-46f3-9fa6-6c827db6ac3d"}