Web call protocol
The WebSocket protocol behind web call sessions, for iOS, Android, Flutter, kiosks, and any platform without an official SDK.
Web call sessions stream audio over a plain WebSocket with JSON frames.
In the browser, the @omnidim-ai/client SDK (see the SDKs tab) handles all
of this for you. Use this page when you are integrating from a platform
without an official SDK: mobile apps, desktop apps, kiosks, or embedded
devices.
Get a connection URL
Create a session server-side with your API key using
create session. The
response contains a ws_url:
{
"session_id": 4521,
"token": "sess_51gF2qw8LxNz0vY4mT7Ka3RjD9pBcE6HuWiQnZsX0oM",
"expires_at": "2026-07-17T12:15:00Z",
"ws_url": "wss://live.omnidim.io/chat/start_voice_chat?request_token=sess_..."
}Connect your client to ws_url exactly as returned. Never construct or
cache WebSocket URLs; the URL format is not a contract and can change
at any time.
Token semantics:
- The token is valid to connect for 15 minutes after create.
- It covers a single conversation and expires when that conversation ends.
- If the connection drops mid-call, reconnecting to the same
ws_urlre-attaches to the same conversation, so a brief network blip does not lose the call.
Send: microphone audio
Send one JSON frame per audio chunk:
{ "type": "audio", "data": "<base64 of 16 kHz mono PCM16>" }- Audio is 16 kHz, mono, 16-bit little-endian PCM, base64-encoded.
- Chunks of roughly 100 to 200 ms work well.
- Hang up by closing the socket. No other frame types are needed.
Receive: agent events
Every server frame is a JSON object with an event field. Ignore any
event you do not recognize; new events may be added at any time.
| Event | Payload | What to do |
|---|---|---|
media | media.payload: base64 16 kHz mono PCM16 | Queue it for playback. |
clear | none | Stop playback and drop everything queued. The visitor interrupted the agent, so latency here is very visible. |
end_call | media.payload.reason: why the call ended (for example hangup) | Stop audio and close your UI. The server closes the socket. |
user | media.payload: text | Final transcript of the visitor's speech so far this turn. |
partial_text | media.payload: text | Interim (still changing) visitor transcript. |
system | media.payload: text | The agent's reply text as it starts speaking. |
last_system_message | media.payload: text | The agent's full reply so far this turn. Each one supersedes the previous, so render the latest. |
error | message text | Surface or log the error. The call may still continue. |
Close codes
| Code | Meaning |
|---|---|
| 1000 | Normal close: the conversation ended. |
| 1011 | Internal error. |
| 1013 | Try again later: the platform is at capacity. Retry with backoff. |
An invalid, expired, or already-used token closes the connection during
setup. Create a new session and connect with the fresh ws_url.
Create session
Create a voice Session: a short-lived, single-conversation reservation that lets a client hold a live voice chat with your agent. This is step 1 of 2. Creating the Session does not start any audio on its own; it returns a ws_url that a client then connects to over WebSocket to actually talk.
Real-time and streaming
How real-time data flows in OmniDimension. Streaming voice on live calls, webhook event delivery for call results, and live status polling for bulk campaigns.
