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

# Get Durable Turn

> Poll durable turn status and partial content

Returns the authoritative lifecycle state for a durable turn. Poll this endpoint after [Create Durable Turn](/api-reference/chats/create-turn), or use it to inspect a WebSocket-created turn.

```http theme={"theme":{"light":"github-light","dark":"github-dark"}}
GET /v1/agents/{agent_id}/chats/{chat_id}/turns/{turn_id}
```

Status polling is not rate-limited by the chat submission throttle. Use client backoff rather than a tight loop.

<ParamField header="Authorization" type="string" required>
  Bearer token obtained from [Authenticate](/api-reference/authentication/authenticate).
</ParamField>

<ParamField path="agent_id" type="string" required>
  Published agent UUID used to run the chat.
</ParamField>

<ParamField path="chat_id" type="string" required>
  Member-owned chat UUID.
</ParamField>

<ParamField path="turn_id" type="string" required>
  Durable turn UUID returned at acceptance.
</ParamField>

## Response

<ResponseField name="turn_id" type="string" required>
  Durable turn UUID.
</ResponseField>

<ResponseField name="chat_id" type="string" required>
  Owning chat UUID.
</ResponseField>

<ResponseField name="status" type="string" required>
  Public lifecycle status: `in_progress`, `completed`, `failed`, or `cancelled`.
</ResponseField>

<ResponseField name="created_at" type="string" required>
  ISO 8601 acceptance timestamp.
</ResponseField>

<ResponseField name="completed_at" type="string | null" required>
  Terminal timestamp, or null while in progress.
</ResponseField>

<ResponseField name="last_seq" type="integer" required>
  Highest durable event sequence represented by the status snapshot.
</ResponseField>

<ResponseField name="partial_content" type="string | null" required>
  Authoritative accumulated assistant text through `last_seq`. It can be present while in progress and after cancellation/failure.
</ResponseField>

<ResponseField name="result_message_id" type="string | null" required>
  UUID of the persisted terminal assistant message, when one was written. It is present for completed and failed turns, can be present for a cancelled turn with persisted partial output, and is `null` while running or when cancellation produced no message.
</ResponseField>

<ResponseField name="replay_available" type="boolean" required>
  Whether exact event replay is currently available. A terminal turn reports true only when the journal includes its terminal event.
</ResponseField>

<ResponseField name="replay_degraded" type="boolean" required>
  Whether the turn permanently lost exact replay guarantees.
</ResponseField>

<ResponseField name="error" type="object | null" required>
  Safe public error when `status` is `failed`, otherwise null.

  <Expandable title="Turn error">
    <ResponseField name="code" type="string" required>
      Stable error code.
    </ResponseField>

    <ResponseField name="message" type="string" required>
      Safe public message. For failed status responses, the service currently returns `The response could not be completed.`
    </ResponseField>

    <ResponseField name="debug_id" type="string | null" required>
      Correlation ID for support, when available.
    </ResponseField>
  </Expandable>
</ResponseField>

## Polling behavior

* While `status` is `in_progress`, update the displayed partial answer from `partial_content` and remember `last_seq`.
* On `completed`, fetch `result_message_id` with [Get Message](/api-reference/chats/get-message) or refresh [Get Chat](/api-reference/chats/get-chat).
* On `failed`, surface `error.code`; `result_message_id` identifies the persisted error message, and `error.debug_id` is available for support correlation.
* On `cancelled`, keep any non-empty `partial_content` as the persisted partial answer. A non-null `result_message_id` identifies that persisted partial assistant message.

The status endpoint and Get Chat use public status values. A WebSocket `resume` control frame instead exposes raw status values (`running`, `done`, `error`, `cancelled`).

<RequestExample>
  ```bash cURL theme={"theme":{"light":"github-light","dark":"github-dark"}}
  curl \
    "https://api.trellis.sh/v1/agents/AGENT_ID/chats/9f0ac8f2-7a22-4ec8-a778-b0b1b83a86bb/turns/26e53cf2-b12d-4a2a-a3b7-5382a87f8f5b" \
    -H "Authorization: Bearer YOUR_TOKEN"
  ```

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

  response = requests.get(
      "https://api.trellis.sh/v1/agents/AGENT_ID/chats/9f0ac8f2-7a22-4ec8-a778-b0b1b83a86bb/turns/26e53cf2-b12d-4a2a-a3b7-5382a87f8f5b",
      headers={"Authorization": "Bearer YOUR_TOKEN"},
  )
  response.raise_for_status()
  turn = response.json()
  ```

  ```javascript JavaScript theme={"theme":{"light":"github-light","dark":"github-dark"}}
  const response = await fetch(
    "https://api.trellis.sh/v1/agents/AGENT_ID/chats/9f0ac8f2-7a22-4ec8-a778-b0b1b83a86bb/turns/26e53cf2-b12d-4a2a-a3b7-5382a87f8f5b",
    { headers: { Authorization: "Bearer YOUR_TOKEN" } },
  );
  const turn = await response.json();
  ```
</RequestExample>

<ResponseExample>
  ```json 200 In progress theme={"theme":{"light":"github-light","dark":"github-dark"}}
  {
    "turn_id": "26e53cf2-b12d-4a2a-a3b7-5382a87f8f5b",
    "chat_id": "9f0ac8f2-7a22-4ec8-a778-b0b1b83a86bb",
    "status": "in_progress",
    "created_at": "2026-08-08T18:00:01.234567+00:00",
    "completed_at": null,
    "last_seq": 7,
    "partial_content": "The portfolio contains",
    "result_message_id": null,
    "replay_available": true,
    "replay_degraded": false,
    "error": null
  }
  ```

  ```json 200 Completed theme={"theme":{"light":"github-light","dark":"github-dark"}}
  {
    "turn_id": "26e53cf2-b12d-4a2a-a3b7-5382a87f8f5b",
    "chat_id": "9f0ac8f2-7a22-4ec8-a778-b0b1b83a86bb",
    "status": "completed",
    "created_at": "2026-08-08T18:00:01.234567+00:00",
    "completed_at": "2026-08-08T18:00:09.876543+00:00",
    "last_seq": 14,
    "partial_content": "The portfolio contains 42 active projects.",
    "result_message_id": "69fd9d75-7141-4584-b8be-7dd6a3073459",
    "replay_available": true,
    "replay_degraded": false,
    "error": null
  }
  ```

  ```json 200 Failed theme={"theme":{"light":"github-light","dark":"github-dark"}}
  {
    "turn_id": "26e53cf2-b12d-4a2a-a3b7-5382a87f8f5b",
    "chat_id": "9f0ac8f2-7a22-4ec8-a778-b0b1b83a86bb",
    "status": "failed",
    "created_at": "2026-08-08T18:00:01.234567+00:00",
    "completed_at": "2026-08-08T18:00:05.876543+00:00",
    "last_seq": 8,
    "partial_content": null,
    "result_message_id": "0f5f77ba-90d2-4df3-b640-9f943cc2db84",
    "replay_available": true,
    "replay_degraded": false,
    "error": {
      "code": "DATABASE_CONNECTION_FAILED",
      "message": "The response could not be completed.",
      "debug_id": "4a8c0ae6"
    }
  }
  ```

  ```json 404 Unknown chat/agent binding theme={"theme":{"light":"github-light","dark":"github-dark"}}
  {"detail":"Chat not found"}
  ```

  ```json 404 Unknown turn theme={"theme":{"light":"github-light","dark":"github-dark"}}
  {"detail":"Turn not found"}
  ```
</ResponseExample>
