zoxaAI
Homepage
API ReferenceCalls

Create a WebSocket call

POST /api/v1/call (no type) with transport=websocket — create a call backed by a raw-PCM WebSocket. Two-step flow — create the call, then connect /ws/audio/{callId}.

POST /api/v1/call

Create a call backed by a raw-PCM WebSocket stream. Returned audioUrl is the relative path to the WS endpoint — open it from your client and audio flows immediately, no SDP/ICE.

This is the right choice for server-side audio pipelines (BYO-SIP bridges, IVR integrations, audio file playback bots). Browsers should use the WebRTC mode instead because it handles echo cancellation, NAT traversal, and jitter buffering for you.

Authentication

X-API-Key: zsk_...

Request body

type is omitted for the WebSocket path — that's what tells the dispatcher to use the WebSocket transport handler.

FieldTypeRequiredDefaultDescription
transport"websocket"—"websocket"Selects raw-PCM WS transport. Default — omit to get this mode.
agentIdstringone of two—A saved agent's UUID. Validated as a string only (not strict UUID, unlike the v2 type=outbound path).
agentobjectone of two—Inline transient agent — a full Agent Config; at minimum name + llm: { provider, model }. Provide exactly one of agentId / agent.
contextVariables{string: string}——Substituted into {{key}} placeholders before the call starts.

Lifecycle webhook lives inside the agent config's webhook field (saved or inline). See Webhooks for the shape.

Audio format (fixed)

The wire format is fixed — there is nothing to declare on the request:

DirectionFormat
You → agent (microphone)Raw 16-bit signed little-endian PCM, mono, 16 000 Hz
Agent → you (speech)Raw 16-bit signed little-endian PCM, mono, 24 000 Hz

The agent's voice is synthesized at 24 kHz and delivered to you untouched, so you receive full generation quality. If you're bridging to a narrowband system (e.g. a SIP trunk at 8 kHz), resample on your side.

Response

Returns HTTP 201 Created.

{
  "callId":   "call_4e4e571f8c9b3cf8e99d",
  "audioUrl": "/api/v1/ws/audio/call_4e4e571f8c9b3cf8e99d",
  "transport": "websocket",
  "status": "pending"
}
FieldTypeDescription
callIdstringzoxaAI's internal id. Stable across the lifetime of the call.
audioUrlstringRelative path to the WS endpoint. Prepend wss://dashboard.zoxa.ai to connect.
transport"websocket"Echo.
status"pending"Call row created but not yet active. Becomes "active" when you connect the WS.

Examples

1. Create the call

curl -X POST https://dashboard.zoxa.ai/api/v1/call \
  -H "X-API-Key: zsk_..." \
  -H "Content-Type: application/json" \
  -d '{
    "transport": "websocket",
    "agentId": "550e8400-e29b-41d4-a716-446655440000"
  }'
const res = await fetch("https://dashboard.zoxa.ai/api/v1/call", {
  method: "POST",
  headers: {
    "X-API-Key": "zsk_...",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    transport: "websocket",
    agentId: "550e8400-e29b-41d4-a716-446655440000",
  }),
});
const { callId, audioUrl } = await res.json();
import httpx

resp = httpx.post(
    "https://dashboard.zoxa.ai/api/v1/call",
    headers={"X-API-Key": "zsk_..."},
    json={
        "transport": "websocket",
        "agentId": "550e8400-e29b-41d4-a716-446655440000",
    },
)
data = resp.json()
call_id, audio_url = data["callId"], data["audioUrl"]

2. Connect the WebSocket

wss://dashboard.zoxa.ai/api/v1/ws/audio/{callId}?api_key=zsk_...

Full wire protocol on the WebSocket Protocol page.

What zoxaAI does after the 201

  1. Resolves the agent config (persistent or transient), substitutes contextVariables, and writes it into config_snapshot on the calls row.
  2. Validates inline tools against your tool catalog. Invalid tools fail the request with 400 and leave a transport=web row tagged with the validation error for audit.
  3. Returns audioUrl — no pipeline runs until you connect the WS.

Errors

StatusdetailWhen
400"No organization selected"Auth missing org context.
400Pydantic messageMode constraints failed (agentId + agent both set, etc.).
400{ "error": "Tool validation failed", "details": [...] }Inline tool references something invalid (missing function, bad schema).
400{ "error": "Reference validation failed", "details": [...] }Inline tool references a file/agent/etc. that doesn't exist in your org.
404"Agent not found"agentId doesn't resolve in your org.
400validation object ({ error, details })Schema or cross-field validation failed — a missing required field (name, llm), an unknown field (extra="forbid"), or a mode rule (agentId + agent both set, or neither). Same object shape as the tool-validation rows above.

On this page