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

# Get Conversation by ID

> Fetch a previously stored question/answer turn by its `conversation_id`.

Use `GET /chat/conversation/{conversation_id}/` to retrieve a single question/answer turn that was created by an earlier `POST /chat/query/` call. The response uses the **same shape** as the non-streaming `/chat/query/` response, so the same client code that consumes a fresh agent answer can also display a stored one.

Send your API key in the `X-API-KEY` header. The only input is the `conversation_id` path parameter.

## When to use

* **Re-fetch after a stream disconnect.** If an SSE client lost the connection mid-stream, the agent pipeline still finishes and persists the result. Call this endpoint with the `conversation_id` from the `start` event to retrieve the final answer.
* **Re-display a prior turn** without re-running the agent.
* **Async workflows** that hand the `conversation_id` between systems.

## Where to get a `conversation_id`

Every `POST /chat/query/` response includes a `conversation_id`:

* In the JSON response body (`conversation_id` field).
* In both the SSE `start` and `done` events when streaming.

A new `conversation_id` is assigned for every `/chat/query/` call, including follow-ups inside the same `chat_id`.

## Response Notes

* The response body matches `POST /chat/query/` (JSON path) field-for-field: `final_answer`, `thinking`, `chat_id`, `chat_url`, `conversation_id`, `sources`, `mode`, `tools`, `content`.
* `final_answer` is recovered from the persisted answer text and cleaned the same way the live path cleans it (`<answer>`, `<ref>`, `<abbr>`, and citation markup are stripped).
* `tools` and `content` reproduce the agent's reasoning trail: every tool call the agent made (with its arguments, output, and status) plus the ordered text/tool transcript. These are populated from the stored conversation state.
* `sources` includes the same per-entry `id`, `type`, `display_name`, and (for paginated docs) `page` fields as the live `/chat/query/` response.
* `thinking` is populated from the legacy agent-logs side panel when the turn was answered by the legacy orchestrator; for turns produced by the current agent pipeline it is always `""` (inspect `tools` / `content` instead).
* `mode` reflects the value echoed back when the conversation was answered.
* The endpoint is read-only. It does not run the agent, does not consume floating-session capacity, and is not subject to the per-`(API key, user_id)` concurrency limit.
* Returns **404** if no conversation with this ID exists in the API key's organization (including conversations whose chat has been deleted).

## Example Response

```json theme={null}
{
  "final_answer": "EMEM is embedded memory integrated into the device for storing code and data.",
  "thinking": "",
  "chat_id": "2d8a39d8-29d6-4f0f-bc5f-4c5f0f9c9d54",
  "chat_url": "https://voltai.ai/ExampleOrg/chat/2d8a39d8-29d6-4f0f-bc5f-4c5f0f9c9d54",
  "conversation_id": 184217,
  "sources": [
    {
      "id": "0351-E1",
      "source_name": "example-datasheet.pdf",
      "page": 12,
      "type": "text",
      "url": "https://voltai.ai/ExampleOrg/library?source_name=example-datasheet.pdf&source_type=text&source_page=12",
      "display_name": "Library Search"
    }
  ],
  "mode": "AUTO",
  "tools": [
    {
      "id": "call_8c2f",
      "name": "search_library",
      "display_name": "Library Search",
      "title": "Searching \"EMEM\" in Datasheets",
      "input": { "query": "EMEM", "topic_id": 17 },
      "output": "Found 3 matching chunks…",
      "status": "success",
      "subagent_instance_id": null
    }
  ],
  "content": [
    {
      "type": "tool",
      "id": "call_8c2f",
      "name": "search_library",
      "display_name": "Library Search",
      "title": "Searching \"EMEM\" in Datasheets",
      "input": { "query": "EMEM", "topic_id": 17 },
      "output": "Found 3 matching chunks…",
      "status": "success",
      "subagent_instance_id": null
    },
    {
      "type": "text",
      "text": "EMEM is embedded memory integrated into the device for storing code and data.",
      "subagent_instance_id": null
    }
  ]
}
```


## OpenAPI

````yaml chat-query.json GET /chat/conversation/{conversation_id}/
openapi: 3.1.0
info:
  title: Voltai API Docs
  description: .
  license:
    name: MIT
    url: https://opensource.org/licenses/MIT
  version: 1.0.0
servers:
  - url: https://api-prod.voltai.ai
security:
  - ApiKeyAuth: []
paths:
  /chat/conversation/{conversation_id}/:
    get:
      description: >-
        Fetch a previously stored conversation (a single question/answer turn)
        by its `conversation_id`. Returns the same JSON shape as the
        non-streaming `POST /chat/query/` response, populated from the persisted
        `Conversation` row.


        Use this to retrieve the result of an earlier `/chat/query/` call (for
        example, after polling, after a stream disconnect, or to re-display a
        previously asked question without re-running the agent). The endpoint is
        read-only and does not consume floating-session capacity.
      parameters:
        - in: path
          name: conversation_id
          required: true
          description: >-
            The integer identifier returned in `conversation_id` from a prior
            `/chat/query/` response (or the `start` / `done` SSE events).
          schema:
            type: integer
      responses:
        '200':
          description: >-
            Stored conversation, in the same shape as the JSON response from
            `POST /chat/query/`.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ChatResponse'
        '403':
          description: Invalid or missing API key
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '404':
          description: >-
            No conversation with this `conversation_id` exists in the API key's
            organization.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
components:
  schemas:
    ChatResponse:
      description: Agent response.
      type: object
      required:
        - final_answer
        - thinking
        - chat_id
        - chat_url
        - conversation_id
        - sources
        - mode
        - tools
        - content
      properties:
        final_answer:
          type: string
          description: >-
            Cleaned answer text returned by the agent. Internal markup
            (`<answer>`, `<ref>`, `<abbr>`, citation tokens) is stripped.
        thinking:
          type: string
          description: >-
            Aggregated reasoning string from the legacy multi-agent
            orchestrator: per-agent entries are concatenated in execution order,
            each prefixed by a header line and separated by a blank line. Empty
            under the current agent pipeline — use `tools` and `content` to
            inspect the reasoning trail instead.
        chat_id:
          type: string
          format: uuid
          description: >-
            Thread identifier: the `Chat` UUID for this conversation. Reuse this
            value in subsequent requests to continue the same thread.
        chat_url:
          type: string
          format: uri
          description: >-
            Web UI link to this thread:
            `https://voltai.ai/{organization_name}/chat/{chat_id}` using the
            resolved organization's `name`.
        conversation_id:
          type: integer
          description: >-
            Identifier of the specific question/answer turn within the thread. A
            new `conversation_id` is generated for every `/chat/query/` request.
            Use it with `GET /chat/conversation/{conversation_id}/` to fetch
            this exact turn later.
        sources:
          type: array
          description: >-
            Evidence cited by the agent. Each entry is annotated with the tool
            that surfaced it (`display_name`) and a stable `id` for joining back
            to citation tokens in `final_answer`.
          items:
            $ref: '#/components/schemas/Source'
        mode:
          type:
            - string
            - 'null'
          description: >-
            Echo of the request `mode`. Retained for backwards compatibility;
            current agent behavior does not depend on it.
        tools:
          type: array
          description: >-
            Every tool call the agent made while answering this turn, in
            execution order. Lets non-streaming clients see the same reasoning
            trail that SSE clients receive as live `tool_call` / `tool_output`
            frames.
          items:
            $ref: '#/components/schemas/ToolInvocation'
        content:
          type: array
          description: >-
            Raw agent transcript for the turn: an ordered list of `text` and
            `tool` items as the agent produced them. `text` items concatenate to
            `final_answer`; `tool` items mirror the entries in `tools`.
          items:
            $ref: '#/components/schemas/ContentItem'
    Error:
      type: object
      properties:
        detail:
          type: string
          description: Human-readable error description.
    Source:
      type: object
      description: >-
        A single piece of evidence cited by the agent. Two shapes are returned
        interchangeably depending on the producing tool:


        - Library / PDF chunks: `source_name` is the source filename, `page` is
        the page number, and `url` is either the document's external link (when
        configured on the source) or a Voltai library deep-link.

        - Web pages, fetched URLs, and connector items (Slack, Jira, Confluence,
        Salesforce, SharePoint, Assembla): `source_name` is the page or item
        title, `page` is `null`, and `url` is the original link.

        - Part-detail / part-comparison / part-replacement sources:
        `source_name` is the display label and `url` may be `null` when the
        source has no canonical link.
      required:
        - source_name
        - page
        - url
      properties:
        id:
          type:
            - string
            - 'null'
          description: >-
            Stable identifier for the source within this response. Use it to
            join citation tokens that appear in `final_answer` (e.g.
            `[0351-E1]`) back to a specific source entry.
        source_name:
          type: string
          description: >-
            Display label for the source. Filename for library chunks; page or
            item title for web / connector / fetched URL sources; display name
            for part sources.
        page:
          type:
            - integer
            - 'null'
          description: >-
            1-indexed page number for paginated sources (library PDFs). `null`
            for web pages, connector items, and part sources.
        type:
          type:
            - string
            - 'null'
          description: >-
            Source type tag from the producing tool (`text`, `web`, `part`,
            ...). Defaults to `text` when the tool did not stamp one.
        url:
          type:
            - string
            - 'null'
          description: >-
            Link to view the source. For library chunks this is either the
            source's configured external URL or a Voltai library deep-link with
            `source_name` / `source_page` parameters. For web and connector
            sources it is the original link. May be `null` when no canonical
            link exists.
        display_name:
          type: string
          description: >-
            Human-readable label for the tool that surfaced the source (e.g.
            `"Web Search"`, `"Library Search"`, `"Part Detail"`). Present
            whenever the agent successfully attributed the source to a tool
            call.
    ToolInvocation:
      type: object
      description: >-
        One tool call the agent performed while producing its answer. The full
        list is returned in execution order on `ChatResponse.tools` and `done`
        SSE events.
      required:
        - id
        - name
        - status
      properties:
        id:
          type: string
          description: >-
            Tool-call identifier. Stable for the lifetime of the conversation
            and used to correlate `tool_call` and `tool_output` SSE frames.
        name:
          type: string
          description: >-
            Internal tool name (e.g. `search_library`, `search_web`,
            `fetch_url`, `part_detail`, `task`).
        display_name:
          type: string
          description: >-
            Human-readable label for the tool (e.g. `"Library Search"`). Falls
            back to a title-cased version of `name` when no friendly label is
            registered.
        title:
          type: string
          description: >-
            One-line, argument-aware summary suitable for showing in a UI (e.g.
            `'Searching "EMEM" in Datasheets'`).
        input:
          type:
            - object
            - 'null'
          description: >-
            Arguments the agent passed to the tool. `null` for private tools
            whose inputs are not surfaced to the API.
        output:
          type:
            - string
            - 'null'
          description: >-
            Raw text output the tool returned to the agent. `""` for private
            tools whose results are hidden from the API surface.
        status:
          type: string
          enum:
            - running
            - success
            - error
          description: Final status of the tool call.
        subagent_instance_id:
          type:
            - string
            - 'null'
          description: >-
            If this tool was invoked by a subagent (delegated via a parent
            `task` call), the parent task's `id`. Top-level tools have `null`.
    ContentItem:
      oneOf:
        - type: object
          description: >-
            Text fragment emitted by the agent (main agent or a subagent).
            Concatenate all main-agent text items in order to reconstruct the
            agent's prose.
          required:
            - type
            - text
          properties:
            type:
              type: string
              enum:
                - text
            text:
              type: string
              description: Text content of this fragment.
            subagent_instance_id:
              type:
                - string
                - 'null'
              description: >-
                When non-null, this text was produced by a subagent and is read
                by the main agent as a tool result rather than shown directly to
                the user.
        - type: object
          description: >-
            Tool call interleaved into the agent's output stream. The same
            fields as `ToolInvocation` (with `sources` stripped — they are
            surfaced on top-level `sources`).
          required:
            - type
            - id
            - name
            - status
          allOf:
            - $ref: '#/components/schemas/ToolInvocation'
            - properties:
                type:
                  type: string
                  enum:
                    - tool
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: x-api-key

````