레퍼런스HTTP APIMessages & turns

Committed result of one turn

GET
/v1/sessions/{id}/turns/{turn_id}

Reads one turn: its status, terminal reason, the engine's committed result and usage, and the worker attempts that ran it. This is the durable answer to whether a turn finished: completed, failed, interrupted, cancelled and outcome_unknown are terminal. completed means the engine ended the turn normally, not that the requested work is done. result and usage are null until the turn ends, and their shape is the runtime's. It changes nothing.

Scope: sessions:read (API key or cookie session).

Authorization

headerAuthorizationBearer <token>

For servers and scripts: an API key sent as an HTTP bearer token, Bearer <key>. It holds exactly the scopes it was issued with; a key issued before scopes existed holds none. It never needs the CSRF header, and it cannot manage agents, members, teams or API keys. Issue one in the web console under Settings → API keys; each operation names the scope it needs.

Scope: sessions:read

Path Parameters

id*string

The session's id.

Match^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$
Formatuuid
turn_id*string

The turn's id.

Length1 <= length

Response Body

The turn as it stands now.

application/json
  1. response
turn_id*string
Length1 <= length
session_id*string
Match^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$
Formatuuid
status*string

needs_input is derived when read, as for the session: a running turn with a pending request a client can still answer.

Value in"queued""running""needs_input""completed""failed""interrupted""cancelled""outcome_unknown"
message*string
channel*|

Where the instruction came from: slack (a mention, DM or thread reply), web (the console) or api (an API key). Null for a turn from before it was recorded, or one the platform queued itself, such as an approval answered after its worker was gone, or the follow-up to a turn whose push request came before the session had a checkpoint.

Defaultnull
created_by*|

Who sent the instruction: the signed-in person, the Slack user's linked account, or for an API key the person who created the key. Null when no person is recorded: an API key no person created, or a turn the platform queued itself.

Defaultnull
slack_permalink*|

The Slack message the instruction came from, as the link Slack gave for it (chat.getPermalink); it opens only for someone who can read that message in Slack. Null for an instruction not from Slack, one from before links were kept, or when Slack did not give a link.

Defaultnull
terminal_reason*|null
checkpoint_revision*|

The newest checkpoint this turn committed that a restore can still reach. A revision garbage collection removed, or one a start_fresh recovery decision retired, is not reported; null when none is left.

created_at*string
Match^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d(?:\.\d+)?(?:Z))$
Formatdate-time
started_at*|null
ended_at*|null
result*unknown|null
usage*unknown|null
attempts*array<>
Example Request
curl -X GET 'https://example.com/v1/sessions/497f6eca-6276-4993-bfeb-53cbbbba6f08/turns/string'
Example Response
{  "turn_id": "1",  "session_id": "0f8b6a52-3d1e-4c7a-9b2f-5e6d7c8a9b01",  "status": "completed",  "message": "Add a health check endpoint and a test for it.",  "channel": "web",  "created_by": {    "user_id": "3e7f1a90-5c2d-4b8e-8f61-2a9d0c4b7e35",    "display_name": "Mina Park"  },  "slack_permalink": null,  "terminal_reason": null,  "checkpoint_revision": 2,  "created_at": "2026-10-11T08:00:00Z",  "started_at": "2026-10-11T08:00:05Z",  "ended_at": "2026-10-11T08:03:12Z",  "result": {    "type": "result",    "subtype": "success",    "result": "Added GET /health and a test for it."  },  "usage": {    "input_tokens": 48210,    "output_tokens": 3120  },  "attempts": [    {      "attempt_id": "att_01",      "state": "exited",      "lease_epoch": 1,      "execution_generation": 1,      "started_at": "2026-10-11T08:00:05Z",      "ended_at": "2026-10-11T08:03:12Z",      "profile_id": "claude-coding-real"    }  ]}