---
title: "List calls"
method: GET
path: "/v1/calls"
---

# List calls

`GET /v1/calls`

## Request

- Base URL: `https://volai.cz`
- URL: `https://volai.cz/v1/calls`
- Auth: HTTP bearer

The call history, newest first. `direction` (`in` or `out`) limits the list to one direction. Filters `from`/`to` (Unix ms, `startedAt` in range, `from <= to`), `agentId`, `flagged` (`true`/`false`), `goal` (`success`/`failure`/`unclear`/`no_conversation`/`not_evaluated`, or the backward-compatible `unknown` - records with no clear result: `goal.result` is missing or `unknown` (always true for unclear and not_evaluated, and for no_conversation only when its result is `unknown`) - see the call's `goal` field), `outcome` (`agent`/`transferred`/`no_answer`/`other`, see the Billing column of the `kind` table below; a gate ring, `kind: "ring"`, is always `other`, even when its status is `no_answer`). Unknown parameters are ignored. **Calls vs. conversations**: `GET /v1/calls` returns individual call RECORDS - each phone leg is its own row. The portal's `/en/calls` table groups related legs (an inbound agent leg plus an outbound transfer leg) into one CONVERSATION - a successfully transferred call therefore shows as one row in the portal, but as up to two records via the API/MCP (the leg that performed the transfer has `outcome: "transferred"`; the receiving leg keeps its own `outcome`). Sum call counts from the API with that in mind.

## Query parameters

- `limit` integer
- `before` integer
- `direction` 'in' | 'out'
- `from` integer
- `to` integer
- `agentId` string
- `flagged` 'true' | 'false'
- `goal` 'success' | 'failure' | 'unclear' | 'no_conversation' | 'not_evaluated' | 'unknown'
- `outcome` 'agent' | 'transferred' | 'no_answer' | 'other'

## Response `200`

Calls

- object
  - `calls` object[], required
    - `id` string, required
    - `direction` 'in' | 'out', required
    - `from` string, required
    - `to` string, required
    - `status` 'initiated' | 'ringing' | 'in_progress' | 'completed' | 'failed' | 'missed' | 'no_answer', required
    - `startedAt` number, required
    - `durationSecs` number
    - `priceHal` number
    - `agentId` string
    - `callbackOf` object
      - `callId` string, required
      - `taskId` string
      - `taskItemId` string
    - `source` 'api' | 'mcp' | 'portal' | 'inbound', required
    - `kind` 'agent' | 'bridge' | 'relay' | 'inbound' | 'transfer' | 'sip' | 'ring'
    - `ring` object: Present only on a ring attempt (`kind` is `ring`): how long ringing was requested, how the attempt ended and how long the target rang. `outcome` and `rangSecs` are absent while the attempt is still running.
      - `requestedSecs` integer, required: Seconds of ringing that were requested for this attempt: the ringSecs of the request, or 10 when it was omitted.
      - `outcome` 'rang' | 'ended_early' | 'answered' | 'unknown': How a ring attempt ended. `rang`: the target rang and volai hung up when the requested time ran out. `ended_early`: the call ended on its own before volai hung up (the target declined it, was busy or unreachable). `answered`: the target picked up and volai hung up at once; the connected seconds are billed on top at the outbound call rate. `unknown`: the result could not be determined (for example the call never showed up as ringing) and is settled later from the carrier's call record. A gate that opens when it sees the call usually ends as `rang` or `ended_early`; `answered` is the exception.
      - `rangSecs` number: How long the target rang, in seconds. First volai's own measurement, replaced by the carrier's figure once its call record has been processed. The carrier counts the ringing from the moment the order is placed, so its figure is usually 1 to 3 seconds longer than the requested `ringSecs`.
    - `answeredBy` 'human' | 'voicemail' | 'ivr' | 'unknown': Outbound calls only: `human`, `voicemail`, `ivr` (an automated voice menu answered; the engine hangs up), or `unknown` when the engine reached no decision or the transcript is missing. Inbound calls omit the field, because a brief caller reply is not a voicemail.
    - `voicemailReason` 'phrase' | 'long_monologue' | 'beep' | 'human_reply' | 'ivr_phrase' | 'digits'
    - `voicemailMessageLeft` boolean
    - `optOutRequested` true: Calls on the built-in engine, in either direction: the remote participant explicitly asked not to be called again (for example "už mi nevolejte" / "do not call me"), even in the last seconds after the farewell. Present only as `true`; this triggers protection of the remote participant's number in the account's do-not-call list (outbound to, inbound from).
    - `voicemailDetectedAtSecs` number
    - `endReason` 'completed' | 'no_answer' | 'busy' | 'rejected' | 'capacity' | 'blocked' | 'loop_guard' | 'credit_blocked' | 'suspended' | 'failed' | 'engine_error' | 'caller_loop'
    - `workflowPath` object[]: Path of the call through the agent's workflow nodes, if any. Written only by volai's own voice engine's post-call (provider: "engine"); a call on an agent hosted on ElevenLabs never carries this field, even when the agent has phases and the call went through them. Also absent when the agent has no workflow configured.
      - `node` string, required
      - `label` string, required
      - `viaEdge` string, nullable, required: Id of the edge this step entered through; null for the entry step.
      - `turnIndex` number, required
      - `at` number, required: Unix ms timestamp of this step.
      - `enterPhraseSpoken` boolean, required
    - `data` object
    - `hasRecording` boolean
    - `note` string, nullable, required
    - `flag` object, nullable, required
      - `reason` string, required
      - `flaggedAt` number, required
    - `handledAt` number, nullable, required
    - `goal` object, nullable, required
      - `result` 'success' | 'failure' | 'unknown', required
      - `rationale` string, nullable, required
      - `reason` 'no_caller_speech' | 'evaluation_error', nullable, required: Why the result is `unknown` - `no_caller_speech` (the caller never spoke) or `evaluation_error` (the evaluation itself failed); `null` for a genuinely unclear result or an older record without this field.
    - `hasConversation` boolean, nullable, required: Whether the call had an actual conversation with the caller. `false` means reliably no conversation (not connected, voicemail, a voice menu answered, or the engine explicitly reported the caller never spoke). `null` means it cannot be determined (an older record with neither a transcript nor the signal).
    - `rating` object, nullable, required: One-click call rating from the portal, the post-call e-mail, PATCH /v1/calls/{id} or MCP annotate_call. null means not rated yet.
      - `value` 'good' | 'bad', required
      - `reason` 'misunderstood' | 'wrong_answer' | 'silence' | 'hung_up_early' | 'other'
      - `note` string
      - `at` number, required
      - `source` 'portal' | 'email' | 'api' | 'mcp', required
    - `missedSms` object: Present once the missed-call SMS was actually sent (or queued and later sent during quiet hours) for this call.
      - `sentAt` number, required
      - `messageId` string, required
  - `hasMore` boolean, required
  - `nextBefore` number, nullable, required

## Other responses

- `400`: Error codes: validation (request).
- `401`: Error codes: unauthorized (request).
- `403`: Error codes: account_suspended (account).
- `429`: Error codes: rate_limited (busy).
- `500`: Error codes: internal_error (service).

---

[API](https://skmtc.dev/volai/apis/volai-rest-api.md) · [All operations](https://skmtc.dev/volai/apis/volai-rest-api/llms.txt) · [OpenAPI document](https://skmtc.dev/volai/apis/volai-rest-api/revisions/12029b05e2fa?raw)
