Skip to main content

One conversation per external user

A conversation is identified by two things: the API key and the external_user_id you send. You never create a conversation explicitly; the first chat request for a new external_user_id creates it, and every later message from the same external user through the same key continues it. The consequences worth knowing:
  • Isolation per key. The same external_user_id reached through two different keys is two different conversations, even when both keys belong to the same agent. A key never sees dialogs from another key or from another channel (Telegram, the widget, and so on).
  • Rotation keeps history. Rotating a key changes its secret, not its id, so its conversations stay attached.
  • external_user_id is yours. Use a stable identifier from your own system, 1-255 characters. Do not put personal data in it that you would not want stored alongside the dialog.
  • One reply at a time. If a message for an external user arrives while the previous reply is still being produced, the API answers 409 conversation_busy with a Retry-After header. Wait and resend.

List conversations

GET /v1/agents/{agent_id}/conversations returns the key’s conversations, most recently updated first. Both read-only and full keys may call it.
last_message_preview is the latest user or assistant text, truncated to 160 characters, or null for an empty conversation.

Read messages

GET /v1/agents/{agent_id}/conversations/{conversation_id}/messages returns the messages of one conversation, newest first. Only user and assistant messages are returned; tool exchanges, tool-activity rows and the system prompt are never exposed. Each message has id, role (user or assistant), type (text, image, file, …), content (text; non-text payloads are rendered as their text or name) and created_at. A conversation id that belongs to another key or channel, or does not exist, is 404 conversation_not_found. The API does not distinguish the two cases.

Pagination

Every list is {"data": [...], "next_cursor": "..." | null}. Pass next_cursor back as cursor to fetch the next page and stop when it is null. Cursors are opaque; a malformed one is 422 validation_error.

Dates

Dates are ISO-8601. Timezone-aware values are converted to UTC, naive values are read as UTC, and date_to is exclusive. A date_to earlier than date_from is 422 validation_error.