> ## Documentation Index
> Fetch the complete documentation index at: https://docs.mithunai.com/llms.txt
> Use this file to discover all available pages before exploring further.

# List the messages in a conversation

> Read the questions and answers in a conversation, oldest first, paged by cursor. An answer is recorded before it is generated, so render only complete ones.

Messages are ordered by `sequence`, oldest first, and paged with a cursor. Loop until `has_more` is `false`; see [Pagination](/api-reference/pagination).

An answer is recorded before it is generated, so while a question is being answered you see its answer message with `status` `pending`. Render only `complete` answers as finished. If a stream was cut off, this is where you find the answer in whatever state it reached.

The same visibility rules apply as for [Get a conversation](/api-reference/conversations/get-conversation): you can read conversations you own, and `owner` or `admin` callers can read any in the organization. Anything else is `404`.

This request also resolves the conversation's assistant. If that assistant can no longer answer (it is `disabled` or `archived`, or has no knowledge attached), this request returns `400` `validation_error`.

<ParamField path="conversation_id" type="string" required>
  The conversation ID.
</ParamField>

<ParamField query="limit" type="integer" default="50">
  The page size, from 1 to 100.
</ParamField>

<ParamField query="cursor" type="string">
  The `next_cursor` value from the previous page. A cursor this server did not issue returns `400`.
</ParamField>

## Response

<ResponseField name="data" type="object[]" required>
  The messages on this page.

  <Expandable title="properties">
    <ResponseField name="id" type="string">
      The message ID.
    </ResponseField>

    <ResponseField name="conversation_id" type="string">
      The conversation the message belongs to.
    </ResponseField>

    <ResponseField name="role" type="string">
      `user` for a question, `assistant` for an answer.
    </ResponseField>

    <ResponseField name="sequence" type="integer">
      Position in the conversation, starting at 1. An answer's sequence is its question's plus one.
    </ResponseField>

    <ResponseField name="status" type="string">
      `complete`, `pending` (still being generated), `interrupted` (stopped early after producing
      some text) or `failed` (produced nothing usable). A question is always `complete`.
    </ResponseField>

    <ResponseField name="text" type="string">
      The message text. Empty for a pending or failed answer.
    </ResponseField>

    <ResponseField name="citations" type="object[]">
      The sources an answer is grounded in. Always empty for a question.

      <Expandable title="properties">
        <ResponseField name="source_id" type="string">
          Identifier of the cited passage. It stays the same while the document's content is
          unchanged and changes when changed content is re-ingested. It is not a knowledge source ID
          or a document ID.
        </ResponseField>

        <ResponseField name="ordinal" type="integer">
          The citation's number, from 1. It matches the `[1]`-style marker in the answer text.
        </ResponseField>

        <ResponseField name="title" type="string">
          Title of the cited document. May be an empty string.
        </ResponseField>

        <ResponseField name="url" type="string | null">
          The source URL, when the document has one.
        </ResponseField>

        <ResponseField name="snippet" type="string | null">
          An excerpt supporting the answer.
        </ResponseField>

        <ResponseField name="anchor" type="string | null">
          A location within the source, such as a heading or page.
        </ResponseField>

        <ResponseField name="score" type="number | null">
          The retrieval relevance score of the cited passage. Higher is more relevant. Use it for
          diagnostics and ranking, not as a probability.
        </ResponseField>
      </Expandable>
    </ResponseField>

    <ResponseField name="abstained" type="boolean">
      `true` when the assistant declined to answer because your knowledge did not support an answer.
      This is a successful outcome, not an error. See [How answers
      work](/concepts/how-answers-work).
    </ResponseField>

    <ResponseField name="created_at" type="string">
      ISO 8601 timestamp with a UTC offset.
    </ResponseField>

    <ResponseField name="model" type="string | null">
      The model that produced an answer, as `provider/name`. `null` for a question.
    </ResponseField>

    <ResponseField name="finish_reason" type="string | null">
      Why generation stopped, as reported. `length` means the answer was cut off at the output
      limit. For a `failed` answer it holds the error code. `null` for a question.
    </ResponseField>

    <ResponseField name="idempotency_key" type="string | null">
      The key you sent with the question, echoed back. `null` on answers.
    </ResponseField>

    <ResponseField name="metadata" type="object">
      The metadata you sent with the question.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="next_cursor" type="string | null" required>
  Pass this back as `cursor` to get the next page. `null` on the last page.
</ResponseField>

<ResponseField name="has_more" type="boolean" required>
  Whether another page exists.
</ResponseField>

<RequestExample>
  ```bash cURL theme={"theme":{"light":"github-light","dark":"github-dark"}}
  curl --request GET "$MITHUNAI_URL/arukz/api/v1/conversations/c41f8a2e-6d93-4b0a-b7e5-3f1d2c8a9e60/messages?limit=50" \
    --header "Authorization: Bearer $MITHUNAI_API_KEY"
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"github-dark"}}
  import os, requests

  conversation_id = "c41f8a2e-6d93-4b0a-b7e5-3f1d2c8a9e60"
  response = requests.get(
      f"{os.environ['MITHUNAI_URL']}/arukz/api/v1/conversations/{conversation_id}/messages",
      headers={"Authorization": f"Bearer {os.environ['MITHUNAI_API_KEY']}"},
      params={"limit": 50},
      timeout=60,
  )
  response.raise_for_status()
  print(response.json())
  ```

  ```javascript JavaScript theme={"theme":{"light":"github-light","dark":"github-dark"}}
  const conversationId = 'c41f8a2e-6d93-4b0a-b7e5-3f1d2c8a9e60'
  const response = await fetch(
    `${process.env.MITHUNAI_URL}/arukz/api/v1/conversations/${conversationId}/messages?limit=50`,
    { headers: { Authorization: `Bearer ${process.env.MITHUNAI_API_KEY}` } },
  )
  console.log(await response.json())
  ```
</RequestExample>

<ResponseExample>
  ```json 200 theme={"theme":{"light":"github-light","dark":"github-dark"}}
  {
    "data": [
      {
        "id": "0e6b1d4f-8a27-4c93-b5d0-7f2e9a3c6b18",
        "conversation_id": "c41f8a2e-6d93-4b0a-b7e5-3f1d2c8a9e60",
        "role": "user",
        "sequence": 1,
        "status": "complete",
        "text": "How do I rotate an API key?",
        "citations": [],
        "abstained": false,
        "created_at": "2026-09-24T10:15:05.771204+00:00",
        "model": null,
        "finish_reason": null,
        "idempotency_key": "ticket-4821-q1",
        "metadata": {}
      },
      {
        "id": "7c3a9e52-1b6d-4f08-a4e7-2d9b5f1c8e36",
        "conversation_id": "c41f8a2e-6d93-4b0a-b7e5-3f1d2c8a9e60",
        "role": "assistant",
        "sequence": 2,
        "status": "complete",
        "text": "Mint a new key, move your integration to it, then revoke the old key [1].",
        "citations": [
          {
            "source_id": "3d8f2a61-7e4b-4c19-9a05-b6e1d7c2f480",
            "ordinal": 1,
            "title": "Managing API keys",
            "url": "https://docs.example.com/admin/api-keys#rotation",
            "snippet": "Rotation is mint-then-revoke: create the replacement first, then revoke the old key.",
            "anchor": "rotation",
            "score": 0.82
          }
        ],
        "abstained": false,
        "created_at": "2026-09-24T10:15:05.771204+00:00",
        "model": "anthropic/claude-sonnet-5",
        "finish_reason": "end_turn",
        "idempotency_key": null,
        "metadata": {}
      }
    ],
    "next_cursor": null,
    "has_more": false
  }
  ```

  ```json 404 theme={"theme":{"light":"github-light","dark":"github-dark"}}
  { "code": "not_found", "message": "The requested resource was not found." }
  ```
</ResponseExample>
