Skip to content
VoxaDocs
Navigation
Open console →

Calls

The call object

Every call in Voxa, outbound, inbound or in the browser, is stored as one call record, and this page describes each of its fields, how to read them, and what they look like for common outcomes.

Read a call

curl https://voxa.abhinavyadav.in/api/v1/calls/$CALL_ID -H "X-API-Key: $VOXA_API_KEY"

The same record, plus a transcript_text field, is sent in the call.completed webhook as data.call. See Webhook events.

A complete example

An outbound call where the caller confirmed an appointment and the agent ended the call:

{
  "id": "00b1d622a8f04f4f8f3a3c2d9e5b7a11",
  "agent_id": "1b81a241c0e44f5c9d1f0e2a7c3b9d10",
  "agent_name": "Appointment reminder",
  "channel": "phone",
  "direction": "outbound",
  "from_number": "+918035001234",
  "to_number": "+919812345678",
  "status": "completed",
  "provider": "plivo",
  "provider_call_id": "b7a5f8de-1c2b-4c55-9d1e-7f3a2b6c9e10",
  "provider_request_id": "0f6a1c4e-58b2-11f1-9a3e-0242ac110002",
  "user_data": {"customer_name": "Rohan", "slot": "11 am"},
  "transcript": [
    {"role": "assistant", "text": "Hello Rohan, this is City Clinic calling about your appointment tomorrow.", "at": "2026-10-01T14:44:02.410000+05:30", "interrupted": false},
    {"role": "user", "text": "Yes, I'll be there at eleven.", "at": "2026-10-01T14:44:07.950000+05:30", "interrupted": false},
    {"role": "assistant", "text": "Great, we'll see you tomorrow at 11 am. Goodbye!", "at": "2026-10-01T14:44:09.120000+05:30", "interrupted": false}
  ],
  "usage": {"stt_seconds": 14.0, "tts_characters": 121, "llm_input_tokens": 1840, "llm_output_tokens": 41, "llm_calls": 1},
  "recording_path": "/data/recordings/00b1d622a8f04f4f8f3a3c2d9e5b7a11.wav",
  "recording_seconds": 14.1,
  "hangup_by": "agent",
  "hangup_reason": "agent ended the call",
  "error": "",
  "created_at": "2026-10-01T14:43:51.002000+05:30",
  "queued_at": "2026-10-01T14:43:51.001000+05:30",
  "dequeued_at": "2026-10-01T14:43:52.318000+05:30",
  "answered_at": "2026-10-01T14:44:01.870000+05:30",
  "ended_at": "2026-10-01T14:44:16.090000+05:30",
  "duration_seconds": 14.2,
  "first_audio_ms": 1050,
  "cost_paise": 95,
  "providers": {"llm": "gemini", "llm_model": "gemini-3.5-flash-lite", "stt": "cartesia", "tts": "cartesia", "telephony": "plivo"},
  "provider_cost_usd": 0.0061,
  "ignore_call_window": false,
  "instance": "blue",
  "summary": "City Clinic called Rohan to confirm tomorrow's 11 am appointment. Rohan confirmed he will come. The agent said goodbye and ended the call.",
  "extracted": {"confirmed": true, "new_day": null}
}

Fields

Identity

FieldTypeNotes
idstringThe call id. 32 hex characters.
agent_idstringThe agent that ran the call.
agent_namestringThe agent’s name when the call was created. Kept even if the agent is renamed or deleted.
channelphone or webPhone (Plivo) or browser.
directionoutbound, inbound or webHow the call started. See Call flow.
from_numberstringE.164. Outbound: your caller ID. Inbound: the caller. Browser: empty.
to_numberstringE.164. Outbound: the number called. Inbound: your number. Browser: empty.
user_dataobjectWhat you passed when placing the call. Empty for inbound calls.
ignore_call_windowbooleanWhether the call was allowed to skip calling hours.

Status

FieldTypeNotes
statusstringqueued, ringing, in-progress, completed, failed, no-answer, busy or canceled. The last five are final. See Call flow.
errorstringWhy a call failed. Empty otherwise. A voice-service failure during a call is also written here, even if the call goes on.

How the call ended

FieldTypeNotes
hangup_bystringcaller, agent, api, error, system, or empty when the call never connected (no-answer, busy, and Plivo failures).
hangup_reasonstringA short reason in plain English.

Common pairs:

hangup_byhangup_reasonStatus
callercaller hung upcompleted
agentagent ended the callcompleted
agenthang-up prompt: conversation completecompleted
agentcaller was silentcompleted
agentmaximum call length reachedcompleted
agentcredits ran outcompleted
apicanceled from the consolecanceled
apiended from the consolecompleted
errorspeech services unavailable: ..., speech recognition stoppedfailed
systemexpired in queue, agent was deletedcanceled
systemout of credits, the phone provider refused the call: ..., server restarted during the callfailed
(empty)Plivo’s hang-up cause, for example NO_ANSWERno-answer, busy, failed or canceled

Timing

All times are ISO 8601. In /api/v1 responses they use your time zone (India time by default); in webhooks they are UTC.

FieldTypeNotes
created_atdatetimeWhen the record was created.
queued_atdatetime or nullOutbound only: when the call joined the queue.
dequeued_atdatetime or nullOutbound only: when a slot was taken and dialling started.
answered_atdatetime or nullWhen the agent went live.
ended_atdatetime or nullWhen the call ended.
duration_secondsnumberSeconds from answered_at to the end, to one decimal. This is what you are billed for. 0 if the call never connected.
first_audio_msinteger or nullThe average time, over the agent’s replies, from the caller finishing a turn to the agent’s first audio. The welcome message is not counted. null if the agent never replied.

Conversation

FieldTypeNotes
transcriptarrayEvery turn, in order. Not included in GET /api/v1/calls lists.
transcript[].roleassistant, user or toolAgent, caller, or a tool call.
transcript[].textstringWhat was said. For an interrupted reply, only what the caller heard. For a tool, name({args}).
transcript[].atdatetimeWhen the turn was saved.
transcript[].interruptedbooleantrue if the caller cut the agent off.

The webhook copy of the record adds transcript_text: the transcript as plain text, one role: text line per turn, without tool turns.

Analytics

FieldTypeNotes
summarystringThe post-call summary, if analytics.summarize is on. Filled a few seconds after the call ends.
extractedobjectFields from analytics.extraction_prompt. {} if off or failed.

See Analytics tab.

Usage and cost

FieldTypeNotes
cost_paiseintegerWhat the call cost your workspace, in paise. Per-second billing, rounded up to the paisa. See Limits and billing.
usage.stt_secondsnumberSeconds of caller audio sent to the transcriber.
usage.tts_charactersintegerCharacters sent to the voice.
usage.llm_input_tokensintegerLLM input tokens, including the hang-up check.
usage.llm_output_tokensintegerLLM output tokens, including thinking tokens and the hang-up check.
usage.llm_callsintegerLLM requests made during the call.
providersobjectWhich services ran the call: llm, llm_model, stt, tts, telephony (plivo or web).
provider_cost_usdnumberVoxa’s estimate of what the providers charged for this call, in US dollars. For information; you are billed cost_paise.

Recording

FieldTypeNotes
recording_secondsnumberLength of the recording. 0 if there is none.
recording_pathstringWhere the file is on the Voxa server. Use GET /api/v1/calls/{id}/recording to download it.

See Recording.

Telephony and internals

FieldTypeNotes
providerstringplivo or web.
provider_call_idstringPlivo’s call UUID, once the call is answered.
provider_request_idstringPlivo’s request id for an outbound dial.
instancestringThe Voxa server process that ran the call’s audio. Useful when reporting a problem.

What a record looks like for other outcomes

No answer. status: "no-answer", hangup_by: "", hangup_reason is Plivo’s cause, duration_seconds: 0, cost_paise: 0, empty transcript. Webhooks get call.ended but no call.completed.

Canceled while queued. status: "canceled", hangup_by: "api", hangup_reason: "canceled from the console", dequeued_at: null, cost_paise: 0.

Expired in the queue. status: "canceled", hangup_by: "system", hangup_reason: "expired in queue".

Caller went silent. status: "completed", hangup_by: "agent", hangup_reason: "caller was silent", usually a transcript with the welcome message and no user turns.

Other call endpoints

RequestReturns
GET /api/v1/callsA page of calls, newest first, without transcripts.
GET /api/v1/calls/{id}One call with its transcript.
GET /api/v1/calls/{id}/eventsThe call’s timeline.
GET /api/v1/calls/{id}/recordingThe WAV recording (?download=true adds a file name).
POST /api/v1/calls/{id}/hangupCancel or end the call. See Outbound calls.

All need calls.view, except hang-up, which needs calls.place.

List calls

curl "https://voxa.abhinavyadav.in/api/v1/calls?agent_id=$AGENT_ID&status=completed,failed&limit=20" \
  -H "X-API-Key: $VOXA_API_KEY"
{"items": [{"id": "00b1d622a8f04f4f8f3a3c2d9e5b7a11", "status": "completed", "duration_seconds": 14.2, "cost_paise": 95, "...": "..."}], "total": 37}
Query parameterDefaultNotes
agent_idOnly these agents’ calls: one id, or several separated by commas.
statusOne status, or several separated by commas.
directionoutbound, inbound or web, or several separated by commas.
since, untilCalls created at or after since and before until (ISO 8601, e.g. 2026-10-01T00:00:00+05:30).
call_idA call id, or its beginning.
phone_numberYour side of the call: the caller ID of an outbound call, the dialled number of an inbound one. Several separated by commas.
customer_numberThe other side of the call, or any part of it (98123 finds +919812345678).
batch_idOnly the calls of this campaign.
qText to find in the call id, either number, or the agent name. Case-insensitive.
sort-created_atcreated_at, duration_seconds or cost_paise; a leading - sorts in descending order.
limit501 to 200.
skip0For paging: skip this many calls.

total is the number of calls that match, for paging.

Timeline

curl https://voxa.abhinavyadav.in/api/v1/calls/$CALL_ID/events -H "X-API-Key: $VOXA_API_KEY"
[
  {"at": "2026-10-01T14:43:51.004000+05:30", "type": "call.queued", "level": "info", "message": "queued at position 1", "data": {"position": 1, "by": "key:backend"}, "latency_ms": null},
  {"at": "2026-10-01T14:44:01.880000+05:30", "type": "call.started", "level": "info", "message": "outbound call with Appointment reminder", "data": {"channel": "phone", "stt": "cartesia/ink-2", "llm": "gemini-3.5-flash-lite", "...": "..."}, "latency_ms": null},
  {"at": "2026-10-01T14:44:09.010000+05:30", "type": "tts.first_audio", "level": "info", "message": "agent started speaking", "data": {}, "latency_ms": 1050}
]

Each entry is one event, oldest first. Timelines are kept for a limited number of days; the call record itself is kept.

Exporting calls

Download calls as CSV, newest first, one row per call. In the console: Dashboard → Download → Calls (CSV), for the period on screen, or Logs → Calls → Export with the filters on screen. Over the API:

curl -o calls.csv "https://voxa.abhinavyadav.in/api/v1/calls/export?days=30&timezone=Asia/Kolkata" \
  -H "X-API-Key: $VOXA_API_KEY"
ParameterDefaultWhat it does
days30Calls from the last 1 to 365 days (ignored when since is given).
agent_id, status, direction, since, until, call_id, phone_number, customer_number, batch_id, qThe same filters as List calls.
timezoneAsia/KolkataThe zone created_at is written in.

Columns: call_id, created_at, agent, direction, status, from_number, to_number, duration_seconds, cost_inr, first_audio_ms, hangup_by, hangup_reason, summary, then one extracted.<key> column per extracted field found in the period (lists are joined with ; ). At most 50,000 rows per export. Each export is recorded in the audit log.

Esc