Calls Live
Calls are conversations with channel = "call". Each call carries an event timeline (ringing, answered, ended, voicemail_left) plus the standard conversation fields. AI features (Smart Hold, AI Receptionist) layer on top.
Real-time call control happens over Socket.io call events. The REST endpoints here exist for backend automation, audit, and history.
List calls
Cursor-paginated list. Filters: status, assigneeId, departmentId, phoneNumberId, visitorId.
Code samples
curl 'https://app.message.com/api/v1/calls?status=open' \
-H 'Authorization: Bearer YOUR_WORKSPACE_JWT'const res = await fetch('https://app.message.com/api/v1/calls?status=open', {
headers: { Authorization: 'Bearer ' + token }
});
const { calls } = await res.json();import requests
r = requests.get(
"https://app.message.com/api/v1/calls",
headers={"Authorization": f"Bearer {token}"},
params={"status": "open"},
)
calls = r.json()["calls"]require "net/http"
require "json"
uri = URI("https://app.message.com/api/v1/calls?status=open")
res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
req = Net::HTTP::Get.new(uri)
req["Authorization"] = "Bearer #{token}"
http.request(req)
end
calls = JSON.parse(res.body)["calls"]<?php
$ctx = stream_context_create([
"http" => ["method" => "GET", "header" => "Authorization: Bearer $token"]
]);
$calls = json_decode(file_get_contents("https://app.message.com/api/v1/calls?status=open", false, $ctx), true)["calls"];Get one call
Returns the call record plus the full event timeline.
{
"id": "uuid",
"version": 4,
"channel": "call",
"status": "open",
"fromE164": "+14155550100",
"toE164": "+14155550199",
"assignedAgentId": "uuid",
"phoneNumberId": "uuid",
"voicemailId": null,
"events": [
{ "eventType": "ringing", "createdAt": "2026-05-13T15:00:00Z", "fromE164": "+14155550100" },
{ "eventType": "answered", "agentId": "uuid", "createdAt": "2026-05-13T15:00:08Z" },
{ "eventType": "ended", "createdAt": "2026-05-13T15:01:32Z", "duration_ms": 84000, "recordingUrl": "https://..." }
],
"createdAt": "2026-05-13T15:00:00Z"
}Event types
| Type | Meaning |
|---|---|
ringing | Carrier delivered the inbound call; queue is being notified. |
answered | An agent picked up. Carries agentId. |
on_hold | Agent put the caller on hold. |
resumed | Hold released. |
transferred | Call moved to another agent or department. |
ended | Call ended. Carries duration_ms and recordingUrl (if recording enabled). |
voicemail_left | Caller left a voicemail; voicemailId links to the voicemail record. |
ai_engaged | Smart Hold or AI Receptionist took the call. Planned |
Answer a call
Marks the call as answered by the calling agent. The carrier-side answer happens over WebRTC in the dashboard; this endpoint records the metadata. Returns 200.
Hang up
Ends the call cleanly. The conversation status moves to solved. ended event is appended.
Hold and resume
Toggle hold. Holding triggers the configured hold music or, above the Smart Hold threshold, the AI hold experience.
Transfer
Move the call to another agent or department. Same handshake semantics as conversation transfer.
{
"agentId": "uuid",
"expectedVersion": 4
}Recording
Mid-call recording control. Whether recording starts automatically is a per-phone-number setting. Recordings are stored in DigitalOcean Spaces; the URL appears on the ended event.
Call recording is regulated. Two-party consent jurisdictions require notice. We provide a configurable spoken disclosure on the inbound greeting; ensure it is enabled before recording in those regions.
Errors
| Code | When |
|---|---|
400 invalid_body | Payload validation failed. |
403 forbidden | Agent lacks the call channel. |
404 not_found | Call does not exist. |
409 stale_version | Optimistic-lock mismatch on transfer. |
422 illegal_state | Cannot perform this action in the current call state (e.g., hold on an unanswered call). |
Common pitfalls
- Polling for incoming calls. Subscribe to
call:ringingon the agent namespace. The REST list endpoint is for backfill only. - Assuming recording is always on. Recording is per-phone-number. Check the
recordingPolicyfield on the phone-number record before relying on a recording URL. - Confusing call status with event type. Status is the conversation state (
open,solved). Event type is a specific transition in the call timeline.