Send and receive a call's audio from your own program, for example your own phone system or app. Start the call:
curl https://evasay.com/api/v1/voice/calls/websocket \
-X POST \
-H "Authorization: Bearer sk-your-key" \
-H "Content-Type: application/json" \
-d '{ "agent_id": "AGENT_ID", "encoding": "pcm_s16le", "sample_rate": 16000 }'
The websocket_url in the answer carries a one-time token and can be opened within 15 minutes. encoding is pcm_s16le (16-bit little-endian PCM at a sample_rate of 8000, 16000 or 24000) or mulaw (8 kHz μ-law). Audio goes both ways as binary frames in that format, ideally 20 ms each. Text frames are JSON:
| Direction | Messages |
|---|---|
| You → EvaSay | {"type":"dtmf","digits":"12#"} key presses; {"type":"end"} hangs up; {"type":"text","text":"…"} words the caller typed ("input":"button" for a tapped reply); {"type":"context","text":"…","key":"cart"} what your app reports (the agent does not answer it); {"type":"typing"} the caller is typing (send it about once a second while they do; the agent holds off speaking for 2 s); {"type":"tool_result","id":"…","result":{…}} (or "error") a page function's answer |
| EvaSay → you | start (with callId); clear (the caller interrupted: drop agent audio not played yet); transcript (role, text, final, and input for typed words); user_started_speaking, user_stopped_speaking, agent_started_speaking, agent_stopped_speaking; cards (cards, quick_replies); tool (id, name, arguments: run one of your page functions); notice (code: too_fast or limit for typed words); ended (with reason, then the socket closes) |
The agent greets as soon as you connect. user_id and page_tools (the page functions your app answers, see below) may be added to the request. Calls are billed per minute like any other, with the same call records, analysis and webhooks.