Skip to main content

Calls

Verified against backend/internal/publicapi/dto.go, calls_handler.go, and routes.go.

MethodPathScope
GET/callscalls:read
GET/calls/:idcalls:read
POST/callscalls:write
POST/calls/:id/hangupcalls:control — see Call Control

List calls

bash
curl "https://api.voicematrix.ai/api/v1/ext/calls?status=completed&limit=20" \
  -H "X-API-Key: vm_live_..."

Query parameters

ParamTypeNotes
limitint1–100
offsetint≥ 0
statusstringcompleted, missed, failed
directionstringinbound, outbound
agent_iduuid
from_date / to_dateISO 8601

Response — every list endpoint on this API uses the same envelope:

json
{
  "data": [
    {
      "id": "550e8400-...",
      "status": "completed",
      "direction": "inbound",
      "caller": "+972501234567",
      "callee": "+97233822555",
      "agent": { "id": "...", "name": "Support Agent" },
      "started_at": "2026-08-20T10:00:00Z",
      "ended_at": "2026-08-20T10:02:00Z",
      "duration": 120,
      "summary": "Customer asked about pricing",
      "recording_url": "https://...",
      "cost": 0.15,
      "metadata": {}
    }
  ],
  "pagination": { "total": 214, "limit": 20, "offset": 0, "has_more": true }
}

recording_url, when present, is re-signed at request time. Stored URLs use a 24-hour SAS token — if this endpoint returned the value exactly as stored, the majority of recordings older than a day would 403 with no explanation. If Azure Storage isn't configured, it falls back to the raw stored URL rather than omitting the field.

Get one call

text
GET /calls/:id

Same shape as a list item, plus transcript: an array of {role, text, timestamp} (role is assistant or user).

Place an outbound call

bash
curl -X POST https://api.voicematrix.ai/api/v1/ext/calls \
  -H "X-API-Key: vm_live_..." \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: place-call-8f21" \
  -d '{
    "to": "+972501234567",
    "agent_id": "550e8400-e29b-41d4-a716-446655440000",
    "metadata": { "campaign": "q3-outreach" }
  }'

to and agent_id (a UUID) are required. metadata is an arbitrary JSON object echoed back on the call record.

Send an Idempotency-Key — this is the endpoint most worth protecting against a retry-triggered double-dial, since a duplicate here means a real second phone call. See Idempotency for the exact scope-check ordering.

Response (201):

json
{ "id": "...", "status": "queued", "to": "+972501234567", "agent_id": "550e8400-..." }

This call is subject to the organization's daily/monthly outbound budget and concurrency cap, and the key's own 50/day limit — see Authentication → Rate limits.

Next

  • Call Control — hanging up mid-call, and what's deliberately not exposed
  • Webhookscall.started / call.ended fire from this resource
All pages