/conversation/connectOpen a session for an agent. Server-side; uses your API key directly.
Connect
Starts a WebRTC session for the given agent. You get back a session_id and an ice_config. Pass the ice_config.iceServers directly into new RTCPeerConnection({ iceServers }) on the browser side.The session_id is the same UUID as the underlying conversation and call records, so you can use it later for GET /conversations/{id}/transcript and GET /recordings/{id}/audio once the call ends.Each call creates persistent records; do not invoke in a tight retry loop. Public agents: if the agent has public_access on, a browser or app can call this endpoint with only the agent_id and no API key. Restrict which sites may embed it with the agent's allowed_origins.WebSocket sessions: with transport: "websocket", the response is a session_id and a ws_url instead, for your client to stream the conversation over (see WS /ws/v1/conversation/:session_id below). Only an API key can open one. By default the agent greets the user first; set direction to outbound when your side placed the call.
Request body
7agent_idstring (UUID)requiredThe agent UUID to start the session with. Must belong to the calling account.
dynamic_variablesobjectoptionalValues for the agent's
{{variable}}placeholders, for this session only — nothing is saved back to the agent. Same shape asPOST /calls/trigger: a flat object of strings, numbers or booleans. Values you send override the agent's stored defaults; a placeholder with neither is never read out as braces: the model sees[name: not provided]in its place, and the spoken opener drops it. Keys may not start withsystem__— those are filled in for you, andsystem__caller_id/system__called_numberare empty on a browser call because there is no phone leg. On a WebSocket session,caller_phonefills the one for its side of the call. UnlikePOST /calls/trigger, an unsupportedsystem__placeholder is treated the same way rather than rejected. Ignored when the session itself is keyless — a public agent reached without an API key, or a call token — because those credentials live in the browser; those sessions use the agent's own defaults. Reaching that same public agent with your API key personalizes normally: what decides is the credential, not the agent.transportstringoptionalwebrtc(the default) for a browser or app peer, orwebsocketto stream the conversation's audio over a WebSocket from your own code. Awebsocketsession needs an API key and returns aws_urlinstead of anice_config.directionstringoptionalWebSocket sessions only.
inbound(the default): the agent greets the user as soon as the socket connects.outbound: your side placed the call, so the agent lets the person who answered speak first, and greets them after their hello or after 3 seconds of silence. Ignored on a WebRTC session.protocolstringoptionalWebSocket sessions only.
aethex(the default): Aethex's JSON events, with what the user and the agent said as text.twilio: the Twilio Media Streams format, for systems that already speak it. Ignored on a WebRTC session.audio_formatstringoptionalWebSocket sessions only. The audio on the wire, both ways:
pcm_16000(16-bit PCM at 16 kHz, the default) orulaw_8000(G.711 µ-law at 8 kHz). Thetwilioprotocol takesulaw_8000only. Ignored on a WebRTC session.caller_phonestring (E.164)optionalWebSocket sessions only. The phone number of the person on the call, in E.164 format (for example
+14155550199), when the call has one. Saved as the call'sfrom_numberon an inbound session and itsto_numberon an outbound one, and fillssystem__caller_idorsystem__called_numberto match. Ignored on a WebRTC session.
Errors
8Missing or invalid API key.
Send a valid X-API-Key header or bearer token.
API key lacks the calls:write scope.
Use a key with the required scope.
transport is websocket, but the request did not use an API key: for example a call token, or a public agent reached without one.
Open WebSocket sessions from your server with an API key.
Account is hard-blocked: subscription canceled past the grace window, or balance is zero with no payment method on file.
Re-subscribe, add a payment method, or top up credits, then retry.
The agent_id does not exist or does not belong to this account.
Verify via GET /api/v1/agents.
agent_id missing or not a valid UUID, or invalid dynamic_variables — not a flat object of strings, numbers and booleans, or a key using the reserved system__ prefix. Also a direction, protocol or audio_format outside its values, audio_format pcm_16000 with protocol twilio, or, on a WebSocket session, a caller_phone that is not in E.164 format.
Send a JSON body with a valid agent_id. If you send dynamic_variables, keep it a flat object of scalar values and drop any system__ key. Send caller_phone in E.164 format, such as +14155550199.
The account or shared backend has no free slot. Response body includes retry_after; response carries a Retry-After header.
Honor the Retry-After header and retry.
No backend slot can be reserved at all.
Retry shortly. If persistent, contact our team at [email protected].
