Call events Live
Phone calls are conversations where channel = 'call'. The dashboard renders the call view in real time by subscribing to these events on the /agent namespace. Our carrier-grade SIP infrastructure posts call events to our backend, we normalise them, and we fan them out.
For the inbound webhook side (carrier to us) see Calls inbound. For REST control of an active call see Calls API.
Call lifecycle
call:ringing, carrier received the call, we created a conversation, agents in the routing set hear it ring.call:answered, one agent picked up. Other agents see the call disappear from their queue.call:on_hold, agent placed the caller on hold. Smart Hold may engage if configured (Planned).call:resumed, agent took the caller off hold.call:transferred, agent transferred to another agent or department.call:ended, hangup from either side. Recording finalised.call:voicemail, no agent picked up before voicemail timeout; recording captured.
call:ringing
Fired when an inbound call arrives at one of your DIDs. Routing rules decide which agents see the event; default is all agents who are available and whose channel set includes calls.
{
"type": "call:ringing",
"conversationId": "uuid",
"callId": "uuid",
"fromE164": "+14155550100",
"toE164": "+18005550100",
"phoneNumberId": "uuid", // your DID
"callerName": "Alice Johnson", // CNAM lookup or visitor record
"visitorId": "uuid", // null if first contact
"createdAt": "2026-05-13T15:30:00Z"
}Answering
Emit call:answer to claim the call. First emit wins; the rest receive an already_taken ack.
socket.emit("call:answer", {
callId: "uuid"
}, (err, callState) => {
if (err === "already_taken") return; // another agent picked up
if (err) throw new Error(err);
});call:answered
Fired to all subscribers when one agent picks up. Other dashboards remove the call from their ringing UI.
{
"type": "call:answered",
"conversationId": "uuid",
"callId": "uuid",
"agentId": "uuid",
"createdAt": "2026-05-13T15:30:08Z"
}call:on_hold and call:resumed
Holds and resumes flip the call between an active media stream and a held state. While held, the caller hears the configured hold music or Smart Hold AI (when shipped).
- Emit
call:holdto place the caller on hold. - Emit
call:resumeto bring the caller back.
call:transferred
Fired when the agent transfers the call. Pass either targetAgentId or targetDepartmentId. Agent transfers run through the same 30-second handshake as chat transfers; department transfers are instant and route to the next available agent in the department.
socket.emit("call:transfer", {
callId: "uuid",
targetAgentId: "uuid", // OR
targetDepartmentId: "uuid"
}, (err) => { /* ... */ });call:ended
Fired when either party hangs up or the carrier drops the leg. endedBy reports which side initiated the hangup. recordingUrl points to the final mixed-down recording (available within ~10s of hangup).
{
"type": "call:ended",
"conversationId": "uuid",
"callId": "uuid",
"endedBy": "agent" | "caller" | "carrier",
"duration_ms": 84000,
"recordingUrl": "https://...",
"createdAt": "2026-05-13T15:31:32Z"
}call:voicemail
Fired when the call rolled to voicemail before any agent answered. The recording URL is available immediately; the transcript follows within ~5s once our speech-to-text pass returns.
{
"type": "call:voicemail",
"conversationId": "uuid",
"callId": "uuid",
"recordingUrl": "https://...",
"duration_ms": 32000,
"transcript": "Hi, this is Alice calling about my order.",
"createdAt": "2026-05-13T15:31:32Z"
}Voicemails are also surfaced via Voicemails API for later retrieval.
Emit reference
| Emit | Effect |
|---|---|
call:answer | Claim a ringing call. |
call:hangup | End the active call from the agent side. |
call:hold | Put the caller on hold. |
call:resume | Resume from hold. |
call:transfer | Transfer to agent or department. |
Smart Hold integration
When Smart Hold ships, it engages automatically once a caller has been on hold past the configured threshold (default five minutes). The AI introduces itself honestly as AI, gathers context, and surfaces a structured summary to the agent on resume. See Smart hold (Planned).
Common pitfalls
- Listening for
call:answeredto claim. The claim happens on the emit ack ofcall:answer, not on the broadcast event. By the timecall:answeredfires, the call is already taken. - Recording URL not ready immediately. The
recordingUrloncall:endedmay be a placeholder until the mix completes (~10s). PollGET /api/v1/calls/:idif you need the final URL right away. - Treating calls as separate from conversations. Every call has a conversation. Use the same conversation primitive for tags, notes, and AI engagement.
- Voicemail without DNC compliance. If you build outbound calling on top, respect the visitor's suppression list. See Suppressions API.