voice. A call joins one agent and, for phone calls, one number in the same account. Every call opens with the agent’s greeting, which must say it is an AI.
Place a call
201 with a call (status: ringing for a live project, in_progress for a sandbox one). The call is refused when:
Recording is off unless you send
record: true.
Read and control calls
GET /v1/calls(filtersaccount_id,agent_id,status; cursor pagination) andGET /v1/calls/{id}.POST /v1/calls/{id}/end: a call not answered yet iscanceledat once. A live call in progress answers202; the call closes when the phone line hangs up, andcall.endedfollows.POST /v1/calls/{id}/transferwith{ "to"?, "mode"?: "warm" | "cold" }: only to one of the agent’stransfer_targets(the first whentois left out), never to a number that sent STOP. Warm is the default. Only phone calls in progress can be transferred.GET /v1/calls/{id}/transcript:{ lines: [{ speaker: caller | agent | human, text, created_at }], complete }.GET /v1/calls/{id}/recording: a 10-minute link to the audio, only when the call was recorded (404 recording_not_foundotherwise).
queued, ringing, in_progress, completed, failed, no_answer (also a dialed call nobody picked up within 2 minutes), canceled.
Inbound calls
Bind an agent to a number and it answers that number’s calls:POST /v1/numbers with agent_id, or PATCH /v1/numbers/{id} with { "agent_id": "agent_…" } (null unbinds). The number’s voice_state turns active once voice is set up for it; if setup fails, the same PATCH retries it. Someone who called the number may be called back from it.
Realtime sessions (browser and mobile)
client_secret.value (a LiveKit token), url and room. The token is bound to that one room and participant and must be used within 60 seconds. Your API key never goes to the client. The session is a call with direction: realtime and shows up in /v1/calls.
Sandbox
Sandbox projects never reach a carrier or LiveKit, and simulated calls aren’t metered. The same consent, STOP, hours and concurrency rules apply.- A call placed from a simulated number is
in_progressat once. POST /v1/calls/{id}/simulate_turnwith{ "text": "…" }plays what the caller says. The agent answers through its hosted runtime, and both lines are added to the transcript.POST /v1/numbers/{id}/simulate_callwith{ "from": "+1…" }plays an inbound call to the number’s agent.- A realtime session comes back with
simulated: trueand no token. Drive it withsimulate_turn.
Webhooks and usage
call.started, call.ended (data.call) and call.transcript.ready (data.transcript) are sent through webhooks. A finished live call records voice_min_allternit, or voice_min_byok for an agent on your own model key, billed per second (usage).
Not available yet
The agent can’t start a transfer by itself during a call. Thetransfer tool still answers tool_not_available. Transfer through POST /v1/calls/{id}/transfer instead.