Skip to main content
Every production session your agents handle — from the API, the console, public agents, or phone calls — is queryable over REST: a lightweight list for browsing, a merged timeline of messages and tool activity per session, and per-speaker recordings when the agent records audio. You can query a session while the call is still in progress. This is a server-side API — authenticate with your API key. The client SDKs deliberately expose no history interface; fetch history from your backend and pass it to your frontend as needed.

What gets stored

The session record — status, timing, caller attribution, name, and metadata — and the conversation transcript are always kept for production sessions. Audio recording is a per-agent choice, on by default: set conversation.record_audio in the console under your agent’s Settings or in the conversation section of the config API, with a per-session override on the session request. Recording off means there is no audio to download. The setting doesn’t affect the live call: transcript events still stream to connected clients in real time.
Recording defaults to on. Call-recording laws vary by jurisdiction — make sure callers are informed and consent where required before going live.

List sessions

GET /v1/agent/sessions returns session facts, newest first. The list is intentionally thin — no transcripts or tool details — so it stays fast at any volume.
Each row carries the session facts:
caller_number and dialed_number are set for phone sessions only (E.164) and are null for web sessions. name is the display name you passed when creating the session (null when omitted), and metadata echoes back whatever you attached when creating the session.

Filters

pending sessions — a session was created but no participant ever connected — are excluded by default. Pass status=pending explicitly to see them. Preview calls made from the Builder never appear in this API.

Pagination

Two modes, mutually exclusive (combining them returns 400): page_size defaults to 30, maximum 100; values out of range are rejected. In cursor mode total is null unless you pass include_total=true. Page mode is capped at an offset of 100,000 rows — requests beyond it return 400 — and every page response still includes next_cursor, so you can switch to cursor crawling from any page for deep scans.

Get a session

GET /v1/agent/sessions/{session_id} returns the session facts plus a single items timeline: messages and tool activity merged in the order they actually happened.
API (curl)

Item types

Details worth knowing:
  • Role vocabulary — the history API’s assistant is the same speaker the SDK’s live events call agent.
  • Order — items are sorted by created_at ascending; a tool_result’s timestamp is its completion time, so long-running tools appear where they actually finished, with messages in between. Items sharing a timestamp order message, then tool_call, then tool_result.
  • tool_source — where the tool ran: client, webhook, builtin (platform tools such as call transfer and hang-up), mcp (tools from a connected MCP server), background (work the agent delegated to a background task), or unknown (calls recorded before source attribution). Treat it as an open set. See Tools.
  • Payloadsinput and output are JSON strings, symmetric with the live SDK events, so one parser covers both. output and error are stored up to 256 KB; beyond that the text is cut and output_truncated is true.
  • Mid-call queries — you can fetch an active session; you get the items persisted so far, and analysis is null until post-call analysis completes.
  • A tool_call without a matching tool_result means the execution never resolved.
items is a discriminated union on type, and it evolves additively. Ignore item types and fields you don’t recognize — new modalities and item kinds will appear without a version bump.

Correlate with live events

call_id is the same identifier your client receives in the SDK’s toolCallStarted / toolCallCompleted / toolCallFailed events. Log it live, and you can align in-call UI with the post-call record — jump from a tool chip in your interface straight to the matching tool_call / tool_result pair in history. See the Web SDK.

Download recordings

GET /v1/agent/sessions/{session_id}/recording returns the recording status and signed download URLs — one audio track per speaker, so you can play or process the agent and the user separately. Recordings exist only when the session was recorded: for sessions that never recorded — recording turned off, or no audio produced — the endpoint returns 404.
API (curl)
Signed URLs are short-lived. Don’t store them — store the session_id and request fresh URLs when you need the audio. For the same reason, recordings are not embedded in the session detail response.

Access semantics

  • Your API key sees every production session across your team’s workspaces, from all sources.
  • A session that doesn’t exist — or belongs to another team — always returns 404, never 403. The recording endpoint additionally returns 404 for a session that exists but was never recorded.

Going further

Post-call analysis

What the embedded analysis object contains and how to configure it.

Webhooks

Push instead of poll — get notified when sessions end.

Web SDK

The live toolCall* events that share call_id with history.

Inbound calls

Where caller_number and dialed_number come from.