Skip to main content
Realtime voice is in beta and access is gated per workspace. The realtime clients are in the SDK source but not in the published packages (3.0.0, Rust 0.2.0); they ship with the next release of every SDK except C++.
Connect to create the session (POST /v1/audio/realtime/sessions), open the relay WebSocket and wait for relay.connected. Then stream PCM16 audio in, read provider events out, and end the call to get its final bill. The relay protocol, warnings and reason codes are described in Realtime voice sessions.

Install what your language needs

client.realtime.connect() sends your API key, so call it on your server only. Node.js 22 or later has a global WebSocket; on older runtimes, install the ws package or pass your own constructor as webSocket.For a call that runs in the browser, create the session on your server and open the socket in the browser with connectRealtimeSession(). It takes the session your server created, including its client_secret, which works only for that one session, and never needs the API key. Browser calls shows both halves.

Make a call

Read every event

Iterate the session instead of subscribing per event type. Iteration stops when the socket closes. In Python, the first iterator also gets the events received since connect() returned, starting with relay.connected.
Python: async with session: ends the call with end() when the block exits, if it hasn’t ended already.

Browser calls

TypeScript only. Never put a Phaseo API key in browser code. On your server, create the session with client.realtime.createSession(), which takes the same model, voice, instructions, provider and metadata options as connect(), and return the response to your page:
TypeScript
In the browser, join the session with connectRealtimeSession(). It opens the relay with the session’s client_secret and returns the same session object as connect():
TypeScript
connectRealtimeSession(info, options) accepts webSocket and connectTimeoutMs like connect(), plus baseUrl (default https://api.phaseo.app/v1) if you use a regional endpoint.

Connect options

Every SDK sends model (required, for example openai/gpt-realtime-2) and the optional voice, instructions, provider and metadata to the create-session request, and waits 30 seconds for relay.connected by default.

Session

TypeScript and Python: The other SDKs have the same operations. Audio is PCM16 bytes, base64-encoded for you; provider events pass through unchanged as each language’s JSON type; end defaults to a 60-second timeout.

Errors

If the socket closes, or end() times out, without session.ended, ending the call fails with a closed-session error. The call is still billed. The error carries the final bill path, GET /v1/generations?id=realtime%3A<session_id>, which returns the final cost once it is settled. connect() fails if the relay ends the session before it connects, or if relay.connected doesn’t arrive in time (Python raises TimeoutError; Rust returns RealtimeError::EndedBeforeConnecting or RealtimeError::ConnectTimeout).
Last modified on November 5, 2026