Calls
The Calls API lets you list call history, view call details with transcripts, download recordings, initiate outbound calls, and run batch call campaigns.
Every endpoint in this section accepts both authentication methods -- Bearer JWT and API key (X-API-Key). This means an automated integration (for example, a handler receiving the post-call webhook) can list calls and download recordings with an API key alone.
List Calls
GET /calls
Returns a paginated list of call logs, ordered by start time (newest first).
Query Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
page | integer | 1 | Page number |
page_size | integer | 20 | Items per page (max 100) |
direction | string | -- | Filter by inbound or outbound |
status | string | -- | Filter by call status (e.g. completed, failed) or outcome (e.g. voicemail, caller_hangup) |
search | string | -- | Search by phone number (from or to) |
Response
{
"items": [
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"call_sid": "CA1234567890abcdef",
"direction": "inbound",
"from_number": "+15551234567",
"to_number": "+15559876543",
"start_time": "2026-03-01T14:30:00Z",
"end_time": "2026-03-01T14:32:45Z",
"duration": 165.0,
"status": "completed",
"outcome": "completed",
"error_reason": null,
"created_at": "2026-03-01T14:30:00Z",
"agent_name": "Support Agent"
}
],
"total": 142,
"page": 1,
"page_size": 20
}
Call Log Fields
| Field | Type | Description |
|---|---|---|
id | uuid | Internal call log ID |
call_sid | string | Twilio Call SID |
direction | string | inbound or outbound |
from_number | string | Caller phone number |
to_number | string | Called phone number |
start_time | datetime | Call start timestamp |
end_time | datetime | null | Call end timestamp |
duration | float | null | Call duration in seconds |
status | string | Call status (completed, failed, in-progress, queued) |
outcome | string | null | Call outcome (completed, caller_hangup, no_answer, timeout, transferred, voicemail, invalid_number, failed). timeout means the call was ended by a silence or maximum-duration limit; caller_hangup is a genuine caller disconnect. |
error_reason | string | null | Error description if the call failed |
created_at | datetime | Record creation timestamp |
agent_name | string | null | Name of the agent that handled the call |
Get Call Detail
GET /calls/{call_id}
Returns a single call with full details including the conversation transcript and provider usage metrics.
Response
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"call_sid": "CA1234567890abcdef",
"direction": "inbound",
"from_number": "+15551234567",
"to_number": "+15559876543",
"start_time": "2026-03-01T14:30:00Z",
"end_time": "2026-03-01T14:32:45Z",
"duration": 165.0,
"status": "completed",
"outcome": "completed",
"error_reason": null,
"created_at": "2026-03-01T14:30:00Z",
"agent_name": "Support Agent",
"transcript": [
{ "role": "user", "content": "Hi, I need help with my order." },
{ "role": "assistant", "content": "Of course! Could you share your order number?" }
],
"provider_usage": {
"deepgram": { "type": "stt", "model": "nova-2" },
"openai": { "type": "llm", "model": "gpt-4o" },
"elevenlabs": { "type": "tts", "model": "eleven_turbo_v2" }
},
"recording_url": "call-CA1234567890abcdef.wav"
}
Additional Detail Fields
| Field | Type | Description |
|---|---|---|
transcript | array | null | Conversation turns with role and content |
provider_usage | object | null | Provider names and models used during the call |
recording_url | string | null | Filename of the WAV recording (if recording was enabled) |
Download Recording
GET /calls/{call_id}/recording
Downloads the WAV recording file for a call. Returns 404 if no recording is available.
The call.completed webhook includes a recording_download_url pointing at this endpoint. Fetch it with your API key in the X-API-Key header to retrieve the audio.
Response
200 OK with Content-Type: audio/wav and the binary file content.
Initiate Outbound Call
POST /calls
Queues a single outbound call. The call is processed asynchronously at 1 call per second by a background worker. The response returns immediately with a call_id and a placeholder call_sid that is updated once Twilio assigns the real SID.
This endpoint accepts both Bearer JWT and API key authentication.
Request Body
{
"to_number": "+15551234567",
"from_number": "+15559876543",
"agent_id": "550e8400-e29b-41d4-a716-446655440000",
"variables": {
"customer_name": "Jane Doe",
"company_name": "Globex"
}
}
Request Fields
| Field | Type | Required | Description |
|---|---|---|---|
to_number | string | Yes | Destination phone number in E.164 format |
from_number | string | No | Caller ID number. If omitted, resolved from the agent's assigned number or the SIP config default. |
agent_id | string | No | Agent UUID to handle the call. If omitted, the agent assigned to from_number is used. |
variables | object | No | Per-call overrides for the target agent's custom variables, as a map of variable name to string value. Applies to this call only and never changes the agent's saved defaults. Every key must be a custom variable defined on the target agent; a built-in variable name or an unknown key returns 422 listing the offending keys. |
Unlike the dashboard editor, which only warns about unrecognised placeholders and still lets you save, this endpoint validates variables strictly. A key that matches a built-in variable name (built-ins are never overridable) or that is not a custom variable defined on the target agent is rejected with 422, and the response lists the offending keys. This surfaces integration mistakes loudly instead of silently dropping data. See Dynamic Variables for the variable model.
Response
202 Accepted
{
"call_id": "550e8400-e29b-41d4-a716-446655440000",
"call_sid": "queued-550e8400e29b",
"status": "queued"
}
The call_sid will be a placeholder prefixed with queued- until the background worker initiates the call with Twilio.
Batch Outbound Calls
POST /calls/batch
Queues multiple outbound calls at once. All calls share the same from_number and agent_id, and are processed at 1 call per second.
Request Body
{
"to_numbers": ["+15551111111", "+15552222222", "+15553333333"],
"from_number": "+15559876543",
"agent_id": "550e8400-e29b-41d4-a716-446655440000"
}
Request Fields
| Field | Type | Required | Description |
|---|---|---|---|
to_numbers | array[string] | Yes | List of destination phone numbers |
from_number | string | No | Shared caller ID for all calls |
agent_id | string | No | Agent to handle all calls in the batch |
Response
202 Accepted
{
"batch_id": "batch-abc123",
"total": 3,
"status": "queued"
}
Get Batch Status
GET /calls/batch/{batch_id}
Check the progress of a batch call job.
Response
{
"batch_id": "batch-abc123",
"total": 3,
"queued": 1,
"initiated": 1,
"failed": 1,
"calls": [
{ "to_number": "+15551111111", "status": "initiated", "call_sid": "CA..." },
{ "to_number": "+15552222222", "status": "queued", "call_sid": null },
{ "to_number": "+15553333333", "status": "failed", "call_sid": null, "error": "Invalid number" }
]
}