Calls
Verified against backend/internal/publicapi/dto.go, calls_handler.go, and routes.go.
| Method | Path | Scope |
|---|---|---|
| GET | /calls | calls:read |
| GET | /calls/:id | calls:read |
| POST | /calls | calls:write |
| POST | /calls/:id/hangup | calls:control — see Call Control |
List calls
curl "https://api.voicematrix.ai/api/v1/ext/calls?status=completed&limit=20" \
-H "X-API-Key: vm_live_..."Query parameters
| Param | Type | Notes |
|---|---|---|
limit | int | 1–100 |
offset | int | ≥ 0 |
status | string | completed, missed, failed |
direction | string | inbound, outbound |
agent_id | uuid | |
from_date / to_date | ISO 8601 |
Response — every list endpoint on this API uses the same envelope:
{
"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
GET /calls/:idSame shape as a list item, plus transcript: an array of {role, text, timestamp} (role is assistant or user).
Place an outbound call
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):
{ "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
- Webhooks —
call.started/call.endedfire from this resource