Skip to main content

Conversations and messages

Three endpoints cover the whole flow: start or resume a conversation, send a message and get the reply, and read messages.

Start or resume a conversation​

POST /api/v1/conversations
{
"user": { "id": "b7f3c2d1", "name": "Matthew", "metadata": { "role": "admin" } },
"conversation_id": "optional: resume this one"
}

Without conversation_id, the user's newest open conversation in the inbox is resumed. If there is none, a new one is created and the response status is 201. With conversation_id, that conversation is returned if it belongs to this user; otherwise not_found.

{
"conversation": { "id": "8c1e…", "status": "open", "mode": "assistant", "created": false },
"user": { "id": "b7f3c2d1", "customer_id": "d41a…" },
"messages": [
{ "id": "…", "role": "user", "content": "How do payouts work?", "created_at": "2026-09-14T18:02:11Z" },
{ "id": "…", "role": "assistant", "content": "Payouts are sent…", "created_at": "2026-09-14T18:02:15Z" }
]
}
  • messages holds the last 50, oldest first, so you can render history on open.
  • role is user (your user), assistant (the AI), or agent (a person on the TrolleyChat side).
  • mode is assistant while the AI is answering and human once a person has taken over.

Send a message and get the reply​

POST /api/v1/conversations/{id}/messages
{ "content": "How do payouts work?", "message_id": "optional UUID v4 for safe retries" }

The response arrives when the reply is ready, typically in three to eight seconds:

{
"message": { "id": "…", "created_at": "…" },
"reply": { "id": "…", "role": "assistant", "content": "Payouts are sent…", "created_at": "…" },
"mode": "assistant"
}
  • content is at most 4,000 characters.
  • If the assistant hands the conversation to a person, reply.actions contains { "type": "escalated" }. The team is alerted; the assistant keeps answering until a person takes the conversation over, at which point mode becomes human. After an escalation, poll the read endpoint so the person's reply reaches your user.
  • When mode is human, your message is stored for the person and reply is null.
  • Retrying with the same message_id returns the original reply with "deduped": true rather than answering twice. Always set one when you retry.

Read messages​

GET /api/v1/conversations/{id}/messages?since=2026-09-14T18:02:15Z

Returns everything visible in the conversation, oldest first, up to 100. With since, only messages created after that timestamp. Use it to pick up a person's replies after a handoff; polling every five to ten seconds while mode is human is fine.

{
"conversation": { "id": "8c1e…", "status": "open", "mode": "human" },
"messages": [ { "id": "…", "role": "agent", "content": "Hi Matthew, I can help with that.", "created_at": "…" } ]
}

What your team sees​

Conversations started through the API appear in the inbox with an API badge. Your team can watch them, take over, and reply from the dashboard exactly as they do for the widget. Their replies reach your application through the read endpoint.