Api / Conversations

GET/v1/conversations/:id/messages

Auth: tenant — Status: stable

List messages in a conversation, oldest first (chat order, ready to render).

Request

Path paramTypeDescription
idintConversation id.

Query parameters

NameTypeDefaultDescription
after_idint0Return messages with id > after_id. Useful for incremental polling.
limitint200Page size. Max 500.
curl -H "Authorization: Bearer atr_…" \
  "http://arbiter.example.com/v1/conversations/1/messages?after_id=10"

Response

200 OK

{
  "conversation_id": 1,
  "count": 4,
  "messages": [
    {
      "id": 1,
      "conversation_id": 1,
      "role": "user",
      "content": "what's a fanout in DSLs?",
      "input_tokens": 0,
      "output_tokens": 0,
      "created_at": 1777088746,
      "request_id": "a889e53a7211eefa"
    },
    {
      "id": 2,
      "conversation_id": 1,
      "role": "assistant",
      "content": "A fanout is …",
      "input_tokens": 1234,
      "output_tokens": 567,
      "created_at": 1777088752,
      "request_id": "a889e53a7211eefa"
    }
  ]
}

User messages have zero tokens (they're the input, not a measured turn). Assistant messages carry the full request totals (cumulative across the master + every delegated / parallel sub-agent for that turn). request_id correlates with the SSE stream and the matching billing-service usage record.

The assistant content field is the cumulative master output across every tool-call re-entry iteration, joined with newlines. This is what the next message replays into the agent's history. Field schemas: Data model → ConversationMessage.

Failure modes

StatusWhenBody
401Missing / invalid bearer.{"error": "..."}
404Conversation doesn't exist or belongs to another tenant.{"error": "conversation not found"}

See also