Skip to main content
POST
A browser call (also called a web call) runs one of your agents with the user’s microphone and speakers. It is the same endpoint as Place a call, with two differences in the body: "channel": "web", and no to. Sending to with channel: "web" returns 400 invalid_request, because nothing is dialled. Call it from your server, where your key lives. The 202 gives you two links for this one call. Hand them to the page, and the page never sees your key:

The audio socket

The page opens ws_url with new WebSocket(ws_url). Audio is binary in both directions: raw PCM, 16-bit signed little-endian, mono, 48,000 Hz, with no header. Send 20 ms frames (1,920 bytes) continuously, and send zeros to mute rather than stopping. When the user interrupts, the server sends the text message {"event":"clear"}: drop any agent audio you have queued but not yet played. Closing the socket ends the call. The call stays queued until the page connects, then moves to in_progress. If no audio connects before ws_url expires, the call ends failed with ended_reason: "no-media" and costs nothing.

The live event stream

Events are agent.state (listening, processing, speaking, ended), transcript.turn (one per finished turn, for both speakers) and call.ended, which is always last. Your server can read the same stream with its key at Stream live events.

While it runs and after

  • Steer or end it from your server with Send a live control: an instruction the agent follows from its next reply, or a close with a goodbye line.
  • Results arrive as webhooks to webhook_url, the same as a phone call. With final_results: true you also get one call.processed carrying the finished transcript. See Webhooks.
  • Billing starts when audio goes live and follows the same per-minute rate as a phone call.
The browser calls guide has a complete page and backend, timing options for timed sessions, and every event payload.

Authorizations

Authorization
string
header
required

Your workspace secret key, sk_live_ followed by 32 hex characters. Create one in the console under Developers.

Headers

Idempotency-Key
string

Up to 255 characters. The same key within 24 hours replays the first answer and creates nothing new. Build it from your own record, such as order-8842-reminder-1.

Maximum string length: 255

Body

application/json
agent_id
string

The agent that runs the call. Required for channel phone and web. Optional for channel realtime: without it the session starts with an empty prompt, no tools, no greeting, the default voice and automatic language, and the Realtime client's session.update configures it. A realtime session never plays the agent's first_message; the client's first response.create starts the conversation.

Minimum string length: 1
agent_revision
integer
Required range: x >= 1
caller_name
string
channel
enum<string>
default:phone

phone dials to. web is a browser session: no to, no route; the answer adds ws_url and events_url. realtime is an OpenAI Realtime-compatible session with the same rules, answer and per-minute price as web, except that it is refused (429 concurrency_limit) rather than queued when no voice slot is free; first_message, system_prompt, timing, test and flow agents are not accepted on it.

Available options:
phone,
web,
realtime
final_results
boolean
default:false

Send one consolidated call.processed after the call ends, once its transcript, any analysis or post-call tools and a flow agent's outcome settle, carrying data.transcript (and data.call.flow for a flow agent). Requires webhook_url.

first_message
string

Replaces the agent's opening line for this call only. {{var}} placeholders are substituted and validated like the agent's first_message. Not accepted for channel realtime.

Required string length: 1 - 500
from
string
max_duration_secs
integer
metadata
object

Your own correlation ids (for example session_id, user_id). Frozen with the call and echoed unchanged in the call object and every webhook's data.call. Never given to the agent. Serialized size at most 4096 bytes. Do not put secrets here.

phone_number_id
string
pool_id
string
recording_enabled
boolean

Store the call's audio. Default true; a workspace whose policy disables recording defaults to false and answers true with 403 recording_disabled.

route
string
system_prompt
string

Replaces the agent's system prompt for this call only; the agent, its revision and every other setting stay the agent's. {{var}} placeholders are filled from this call's variables and validated like the agent's system_prompt (with an input_schema, each must be a declared input, a system variable or a pre-call tool output). Stored with the call but never returned on the call object or in webhooks. Not accepted for channel realtime (400 invalid_request) or for a flow agent (409 flow_system_prompt_unsupported).

Required string length: 1 - 12000
test
boolean
tier
string
timing
object

Web and phone calls only (not realtime). Seconds count from live media start; max_duration_secs stays the hard cap. The *_before_end values must be at most the call's effective max_duration_secs minus 10, and close_secs_before_end less than wrap_up_secs_before_end when both are set.

to
string
variables
object
voice
object
webhook_url
string

Response

Accepted, not dialled yet

202 response of POST /v2/calls. Web calls and realtime sessions add the session credentials: paths the public edge makes absolute. transport names the channel.

id
string
required
status
enum<string>
required
Available options:
queued
events_url
string

Live events (Server-Sent Events) path with a reusable read-only token, valid for the call's maximum duration plus one hour.

transport
enum<string>
Available options:
web,
realtime
ws_url
string

Browser audio socket path with a single-use token. Expires at ws_url_expires_at (300 seconds). An idempotent replay repeats it only while the token is unused.

ws_url_expires_at
string<date-time>