# Get a case transcript (/docs/api/voice-agents/agent-tests/getAgentTestTranscript)

> For the complete documentation index, see [llms.txt](https://docs.tandemcx.ai/llms.txt). Any page on this site can be fetched as Markdown by appending `.md` to its URL.

`GET /v1/agent-media/agents/{agentId}/test-runs/{runId}/results/{testId}/{attempt}/transcript`

Get a case transcript

The conversation one case produced, oldest first, including tool calls. An `invalid` case has no transcript.

## Request

**Base URL:** `https://api.tandemcx.ai`

**Authentication:** `Authorization: Bearer <token>` — A Tandem bearer token. Requests are scoped to the organization the token belongs to; no organization header is required.

### Path parameters

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `agentId` | string | Yes | The agent's unique ID. |
| `runId` | string | Yes | The test run's unique ID. |
| `testId` | string | Yes | The test's unique ID. |
| `attempt` | integer | Yes | The attempt number, from 1. |

## Responses

### 200 — The transcript.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `turns` | array of object | No | — |
| `turns[].role` | enum: `user` \| `assistant` \| `tool` | Yes | `user` is the test caller. `tool` is a tool call, with `text` empty. |
| `turns[].text` | string | Yes | — |
| `turns[].tool` | object | No | Present exactly when `role` is `tool`. |
| `turns[].tool.toolUseId` | string | No | — |
| `turns[].tool.name` | string | No | — |
| `turns[].tool.status` | enum: `ok` \| `error` \| `running` \| `unknown` | No | — |
| `turns[].tool.args` | unknown | No | — |
| `turns[].tool.errorText` | string | No | The failure reason, only when the call failed. |
| `turns[].tool.httpStatus` | integer | No | The HTTP status an integration tool answered with, when the tool ran for real. |
| `turns[].tool.detail` | object | No | What the integration was sent, what it answered, and what the agent got back. Present only for a caller who passes the organization-admin check; it is removed server-side for anyone else, not hidden by the client. It can hold your endpoint's customer data. It is kept for 90 days, and on a call or chat it is deleted with the transcript. A tool that is not an integration has no `request` or `response`, only `agentSaw`. Calls recorded before this was captured have no `request` or `response` either. |
| `turns[].tool.detail.request` | object | No | The request as the platform built it. Credentials stored on the integration are added afterward and are not shown. |
| `turns[].tool.detail.response` | object | No | The response as the integrations service returned it, with the integration's secret values removed. Not the bytes on the wire. |
| `turns[].tool.detail.agentSaw` | unknown | No | The value the tool returned to the agent, after any response extraction. |
| `turns[].stubbed` | boolean | No | True when this tool call answered from the test's stub instead of running. |
| `lineTurns` | array of integer | No | For each line of the transcript the judge read, the index of the turn it came from. A criterion's `turnIndex` indexes this list. |

### 400 — The request was malformed. `error` names the reason, such as `invalid_agentId`, `invalid_version`, `invalid_slot`, or `invalid_prompt`.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `error` | string | No | A stable machine-readable code. |
| `message` | string | No | A human-readable explanation, safe to show to an end user. Present on errors an operator can act on; browser clients display this field in preference to a generic fallback. |
| `limit` | integer | No | Present on some errors (e.g. `prompt_too_long`) that reject a value against a fixed bound: the bound itself. |
| `length` | integer | No | Present on some errors (e.g. `prompt_too_long`) that reject a value against a fixed bound: the measured size of the rejected value. |
| `reason` | string | No | Present on some errors (e.g. `invalid_avatar_image`) that have more than one cause: which one applied. |

### 401 — Missing, malformed, or expired bearer token.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `error` | string | No | A stable machine-readable code. |
| `message` | string | No | A human-readable explanation, safe to show to an end user. Present on errors an operator can act on; browser clients display this field in preference to a generic fallback. |
| `limit` | integer | No | Present on some errors (e.g. `prompt_too_long`) that reject a value against a fixed bound: the bound itself. |
| `length` | integer | No | Present on some errors (e.g. `prompt_too_long`) that reject a value against a fixed bound: the measured size of the rejected value. |
| `reason` | string | No | Present on some errors (e.g. `invalid_avatar_image`) that have more than one cause: which one applied. |

### 404 — `error` is `not_found`: no such run for this agent, no result for this test and attempt, or the result has no transcript.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `error` | string | No | A stable machine-readable code. |
| `message` | string | No | A human-readable explanation, safe to show to an end user. Present on errors an operator can act on; browser clients display this field in preference to a generic fallback. |
| `limit` | integer | No | Present on some errors (e.g. `prompt_too_long`) that reject a value against a fixed bound: the bound itself. |
| `length` | integer | No | Present on some errors (e.g. `prompt_too_long`) that reject a value against a fixed bound: the measured size of the rejected value. |
| `reason` | string | No | Present on some errors (e.g. `invalid_avatar_image`) that have more than one cause: which one applied. |
