?key=YOUR_KEY on the URL, or the X-Auth header when your client can set one. The upgrade is refused with 401 when the key is missing or wrong, and with 503 when live_filter is false in GET /api/voice/capabilities or this node is at its session limit. On 503, retry on a new connection.session.ended is still sent.{
"type": "start",
"call_id": "your-call-id",
"from": "+15559990000",
"to": "+15551234567",
"sample_rate": 8000,
"encoding": "pcm16",
"params": { "webhook": "https://example.com/hook", "language": "en", "report": "false" }
}| Field | Required | Notes |
|---|---|---|
type | yes | Always start. |
call_id | no | Your identifier. Echoed in every event. |
from | for report | Caller number in E.164 with a leading +. |
to | no | Called number in E.164. |
sample_rate | no | 8000 to 48000. Default 8000. |
encoding | no | pcm16 (16-bit little-endian, default) or mulaw. |
params | no | Same keys as the URL parameters. Values are strings. A value here wins over the URL. |
| Message | Meaning |
|---|---|
{"type":"transcript","text":"...","track":"inbound"} | Words you transcribed yourself. track is inbound (caller, default) or outbound (callee). Each message is one final utterance. |
{"type":"dtmf","digit":"1"} | A key press. Collected into intel.dtmf. |
{"type":"stop"} | The call ended. Closing the socket has the same effect. |
type field. The filter never sends binary frames.type | When | Extra fields |
|---|---|---|
session.started | The start message was accepted. | |
transcript.line | One utterance is final. | speaker, text |
verdict | The score or category changed enough to matter. | verdict |
session.ended | The call ended and the final analysis is done. | verdict, intel, transcript, duration_seconds, reported, reported_numbers |
session_id, kind (filter), call_id, from, to, at. A verdict object carries score (0 to 1), level (clean, suspicious, likely_scam, scam), category (one exact CallerAPI complaint subject, or none), tactics, signals, summary, source.verdict event is sent when the first score reaches 0.3, when the level or category changes, or when the score moves by 0.15 or more. Expect zero events on a clean call and two to five on a scam call.webhook, every event except transcript.line is also posted to that HTTPS URL, signed with X-Voice-Signature: sha256=<hex> (HMAC-SHA256 of the raw body, key is your API key). No retry. Read GET /api/voice/sessions/{id} when a post is missing.{"type":"stop"} or close the socket. The server flushes transcription, runs the final analysis (up to 20 seconds), files the caller when report=true and the final level is scam, sends session.ended, then closes. A session ends by itself after 60 minutes.connected and start frames replace the plain start message. Use POST /api/voice/filter/twiml or /texml to get the vendor XML that does this for you.