CallEvent is how the gateway tells you what happened to a call after you
hand it off. Events are pushed on the same uni-stream pipe as audio.
CallEvent schema
| Field | Type | When populated |
|---|---|---|
call_sid | string | Always. |
event_type | EventType | Always (see table below). |
status | string | Coarse string for human reading: INITIATED, RINGING, ANSWERED, COMPLETED, FAILED, BUSY, NO_ANSWER. |
start_timestamp_ms | int64 | CHANNEL_CREATE and later events. |
q850_cause | int32 | CHANNEL_HANGUP_COMPLETE. ITU-T Q.850 cause. |
recording_url | string | CHANNEL_HANGUP_COMPLETE if recording on. |
duration_seconds | int32 | CHANNEL_HANGUP_COMPLETE. |
answer_timestamp_ms | int64 | CHANNEL_ANSWER and later. |
end_timestamp_ms | int64 | CHANNEL_HANGUP_COMPLETE. |
packets_sent | uint32 | CHANNEL_HANGUP_COMPLETE. |
packets_received | uint32 | CHANNEL_HANGUP_COMPLETE. |
packets_lost | uint32 | CHANNEL_HANGUP_COMPLETE. |
bytes_sent | uint64 | CHANNEL_HANGUP_COMPLETE. |
jitter_ms | double | CHANNEL_HANGUP_COMPLETE. |
estimated_mos | double | CHANNEL_HANGUP_COMPLETE. R-factor → MOS estimate. |
trunk_id | string | Always. |
tenant_id | string | Always. |
codec | string | Negotiated egress codec. |
timestamp_ms | int64 | When the gateway emitted this event. |
client_id | string | Echo of EventStreamRequest.client_id. |
Event types
event_type value | Name | Fired |
|---|---|---|
0 UNKNOWN | reserved | Should never appear. If it does, log and drop. |
1 CHANNEL_CREATE | b-leg (callee) was created. Do not assume audio yet. | |
2 CHANNEL_ANSWER | Far end picked up; audio is flowing. | |
3 CHANNEL_HANGUP_COMPLETE | Final accounting event. Includes Q.850 cause and stats. | |
4 CHANNEL_HOLD | Caller pressed hold (or ExecuteDialplan(MUSIC_ON_HOLD)). | |
5 CHANNEL_RESUME | Hold lifted. |
Subscribing
Send oneEventStreamRequest immediately after connect. The SDKs do this
for you in connect() / connect_async(). The client_id should be a
stable per-process UUID — the gateway uses it to demux events when the
same tenant has multiple SDK instances connected.
Ordering
For a singlecall_sid, events are emitted strictly in this order:
call_sids, events are not ordered — they’re just pushed as fast
as the gateway can serialize them.
Reconnect behaviour
- Within a session: If a uni-stream resets mid-frame, the gateway will
open a new one and replay the latest
CHANNEL_HANGUP_COMPLETEfor any call that completed during the gap. Mid-call events are not replayed — there’s no point, you’ve already missed the audio. - Across sessions: A fresh QUIC connection with the same
client_idresumes the subscription. The gateway holds an event buffer of 120 seconds perclient_id; anything older is dropped.
Recommended consumer pattern
Track in-flightcall_sids in a set; remove them on CHANNEL_HANGUP_COMPLETE.
Don’t try to drive UI off status strings alone — they’re for humans.
Branch on event_type and use q850_cause to disambiguate hang-up reasons.