Skip to content
VoxaDocs
Navigation
Open console →

Get started

Call flow

Every call in Voxa moves through a small set of statuses, and this page explains each one: how a call starts, what happens while it runs, how it ends, and what Voxa keeps afterwards.

Statuses

StatusMeaningFinal
queuedAn outbound call is waiting for a free call slot, credits or the agent’s calling hours.No
ringingVoxa has asked Plivo to dial the number. The call holds a call slot.No
in-progressThe caller answered (or called in) and the agent is live.No
completedThe conversation ran and ended normally, whoever hung up.Yes
failedSomething went wrong: no credit, the phone provider refused the call, a speech service failed, or the server restarted mid-call.Yes
no-answerThe number rang but nobody picked up.Yes
busyThe number was busy.Yes
canceledThe call was canceled while queued, expired in the queue, its agent was deleted, or Plivo reported it canceled before it connected.Yes
outbound:  queued ──> ringing ──> in-progress ──> completed
             │           │              └───────> failed
             │           ├──> no-answer / busy / failed / canceled
             ├──> canceled  (canceled, expired, agent deleted)
             └──> failed    (out of credits, phone provider refused)

inbound and browser:  in-progress ──> completed / failed

hangup_by and hangup_reason on the call say why it ended. See The call object.

Three ways a call starts

OutboundInboundBrowser
Started byPOST /api/v1/agents/{id}/callSomeone dials a number connected to an agentThe console’s Test in browser, or a WebSocket client
directionoutboundinboundweb
channelphonephoneweb
First statusqueuedin-progressin-progress
Waits in the queueYesNo; refused if no slot is freeNo; refused if no slot is free
Calling hours applyYes, unless ignore_call_windowNoNo
user_dataFrom the requestEmptyFrom the first WebSocket message
Audio8 kHz mu-law over Plivo8 kHz mu-law over Plivo16 kHz 16-bit PCM over a WebSocket

Read more: Outbound calls, Inbound calls, Browser calls.

The queue

Every outbound call is queued, even when a slot is free. A background worker dials queued calls, oldest first, for each workspace. It runs as soon as a call is queued or a call ends, and also every few seconds as a safety net.

For each queued call, the worker checks, in order:

  1. Age. A call queued longer than 24 hours is canceled with the reason expired in queue.
  2. Free slot. If the workspace’s live calls (ringing plus in-progress) already reach its concurrency limit, the call waits. It also waits while the workspace is not active.
  3. Credits. If the balance is ₹0 or less, the call is failed with out of credits.
  4. Agent. If the agent was deleted, the call is canceled.
  5. Calling hours. If the current hour in the agent’s time zone is outside its calling window, the call waits until the window opens.

Then the call moves to ringing (taking the slot before dialling) and Voxa asks Plivo to dial. If Plivo refuses, the call is failed and the slot goes to the next call.

Queued calls survive a server restart. They are stored, and the worker dials them when it comes back.

Limits and billing covers concurrency limits and how to ask for more.

Calling hours

Each agent has a calling window: call.call_start_hour (default 9) to call.call_end_hour (default 21), in call.timezone (default Asia/Kolkata). An outbound call is dialled only when the current hour h satisfies call_start_hour <= h < call_end_hour. With the defaults, the last calls go out at 20:59.

  • Calls queued outside the window wait in the queue. The call.queued event says so: queued at position 1; waits for the calling window (9:00-21:00).
  • Pass "ignore_call_window": true when placing a call to skip the check.
  • The window does not wrap past midnight. If call_start_hour is not less than call_end_hour, the window never opens.
  • A call still waiting after 24 hours expires.

While the call runs

Once a call is in-progress, the agent’s session runs:

  1. Welcome. If the agent has a welcome_message, it is spoken first, with {variables} filled in.
  2. Listen. The transcriber turns the caller’s audio into text and decides when the caller has finished a turn.
  3. Think. The LLM gets the conversation and the agent’s prompt and streams a reply. It can call the agent’s tools, or the built-in end_call.
  4. Speak. Each sentence goes to the voice as soon as it is complete, so the agent starts talking before the full reply is ready.
  5. Interruptions. If the caller talks over the agent (at least interruption_min_words words), the agent stops, drops the audio not yet played, and answers what the caller just said.
  6. Watchdog. Every second, Voxa checks the maximum length, silence, the “are you still there?” check and the credit limit. See the Call tab.

Each step is written to the call’s timeline (GET /api/v1/calls/{id}/events) and sent to your webhooks.

How a call ends

Whohangup_byTypical hangup_reason
The caller hangs upcallercaller hung up
The agent calls end_callagentagent ended the call
The hang-up prompt says the conversation is overagenthang-up prompt: conversation complete
Nobody speaks for hangup_after_silence_secondsagentcaller was silent
The call reaches max_duration_secondsagentmaximum call length reached
The workspace runs out of credit mid-callagentcredits ran out
You end it with POST /api/v1/calls/{id}/hangupapiended from the console
A speech service failserrorspeech services unavailable: ...
Voxa ends it before or outside the sessionsystemexpired in queue, out of credits, server restarted during the call

After the call

When the session ends, Voxa, in this order:

  1. hangs up and closes the speech services;
  2. computes usage (seconds of audio transcribed, characters spoken, LLM tokens);
  3. charges the call per second from your credits;
  4. saves the recording, if call.record is on;
  5. saves the final status and emits call.ended;
  6. runs post-call analytics (summary and extraction), if turned on;
  7. sends call.completed with the full call record to your webhooks.

call.completed is sent only for calls that connected and ran a session. Calls that end as no-answer, busy, canceled, or fail before connecting, get call.ended but no call.completed.

What Voxa records

WhatWhereKept
Call record: status, numbers, timing, usage, cost, summaryGET /api/v1/calls/{id}With the call
Transcript: every caller and agent turn, interrupted replies marked, tool callstranscript on the callWith the call
Timeline: every event with its latencyGET /api/v1/calls/{id}/eventsA set number of days (platform setting)
Recording: stereo WAV, caller on the left, agent on the rightGET /api/v1/calls/{id}/recordingOn the Voxa server
Credit chargeBilling ledger, with the call idWith the workspace
Esc