Choosing a transport
When to use phone (outbound / inbound) vs WebSocket vs WebRTC. Trade-offs, latency, and what your client actually needs.
The same agent works across four transports. Picking the right one is a question of where the audio comes from and where it goes.
The four options
| Transport | The audio source/sink | When to use |
|---|---|---|
| Phone outbound | A real phone number — dialled from your Twilio/Vobiz number to a customer's number. | You're calling customers (sales, reminders, surveys). |
| Phone inbound | A real phone number — customers dial your registered DID. | You're running a hotline / IVR / receptionist. |
| WebSocket | Your own server. You send and receive raw PCM frames over a WS. | Server-to-server pipelines, SIP-bridge integrations, audio-file replay bots, custom mobile apps with their own audio engine. |
| WebRTC | A browser (or any WebRTC-capable client) over zoxaAI's built-in SmallWebRTC transport. | Browser-embedded voice agents — chatbots in your dashboard, embedded support, anything where the end-user is on a web page. |
Decision tree
Is the audio on a phone call (PSTN / SIP)?
├── Yes — outbound (you dial) → POST /call type=outbound (Phone outbound)
├── Yes — inbound (customer dials you) → POST /call type=inbound (Phone inbound)
└── No, the audio is on the web side
Is the end-user in a browser?
├── Yes → POST /call transport=webrtc (WebRTC)
└── No, my server controls the audio → POST /call transport=websocket (WebSocket)
+ connect to /ws/audio/{callId}Trade-offs in detail
Phone — outbound / inbound
| Pro | Con |
|---|---|
| Works with the world's most-used audio device — a phone. | Telephony costs (your provider bills you). |
| No SDK required on the user's side. | Provider sandbox / number provisioning needed up-front. |
| Built-in call status events (busy, no-answer, etc.). | Sample rate is fixed at 8 kHz mulaw — narrowband only. |
Use this for: outbound campaigns, customer-facing hotlines, anything where the end-user has only a phone.
WebRTC
| Pro | Con |
|---|---|
Standard RTCPeerConnection — no third-party client SDK required. | You complete the SDP offer/answer handshake yourself (POST/PATCH to offerUrl). |
| Sub-second connect, high audio quality; codec negotiated via SDP. | Hard 610-second default cap (configurable via maxCallDurationS). |
| Works on every modern browser without extra setup. | The audio stays on the WebRTC peer connection — your server doesn't directly see raw frames. |
Use this for: dashboards, in-app voice agents, marketing widgets, anywhere the user is already on a web page.
WebSocket
| Pro | Con |
|---|---|
| You see and send raw PCM frames — full control over the audio pipeline. | You do everything: capture, encode, jitter buffer, echo cancellation. |
Negotiable sample rate (16000 for HD or 8000 for telephony bridges). | No built-in browser-friendly client — you'd need to build one. |
| Easy to bridge to a SIP trunk, audio file, or custom hardware. | If your client buffers audio, you'll feel the latency tax. |
Use this for: server-side bots, SIP trunks, automated audio testing, custom voice surfaces that aren't phones or browsers.
Common combinations
| Scenario | Combo |
|---|---|
| Voice agent embedded in your customer dashboard | WebRTC (browser-flow) |
| Sales bot calling a list of prospects | Phone outbound + a campaign |
| Support hotline | Phone inbound binding (inbound-flow) |
| Voice IVR replacing your existing Asterisk PBX | WebSocket (websocket-flow) with mulaw 8 kHz to bridge SIP audio |
| Twilio inbound passed to a zoxaAI agent | Phone inbound — register the Twilio number once, all future calls bridge to your agent |
Same agent, any transport
The agent config is transport-agnostic. The same saved agent can be invoked over phone, WebSocket, or WebRTC — only the POST /call body changes.
What stays the same across transports
- The
agentId/agentselection rules contextVariablessubstitutionagent.webhooklifecycle events- The
GET /calls/{callId}response shape - Transcript, recordings, and cost accounting
What changes between transports
| Thing | Phone | WebRTC | WebSocket |
|---|---|---|---|
| Body field that selects this transport | type: "outbound" / "inbound" | transport: "webrtc" | transport: "websocket" (or omit) |
| Returns | callId | callId, offerUrl | callId, audioUrl |
| Audio is via | Provider (Twilio/Vobiz) | SmallWebRTC peer connection (SDP offer/answer at offerUrl) | Your WS |
| Sample rate / codec | 8 kHz mulaw (provider-fixed) | Negotiated via SDP | Fixed: 16 kHz PCM in, 24 kHz PCM out |
| Default max duration | Provider's account default | 610 sec (maxCallDurationS) | Unlimited until WS closes (maxCallDurationS still caps the agent) |
Related
- Calls overview — the dispatcher
- WebSocket protocol — full wire spec
Full-configuration reference
Fully-populated agent and POST /call bodies showing every field with realistic values. Use as a reference to see what's available.
Calls Overview
How POST /api/v1/call dispatches between outbound phone, inbound phone, WebSocket, and WebRTC modes — plus the full list of call-related endpoints.