Skip to Content
API ReferenceVoice API

Voice API

Place outbound voice calls and query your call history programmatically. Use this API to trigger automated calls from your own application, CRM, or alerting system.

Base URL

https://voxvaani.com/api/v1

Authentication

All requests require an API key in the header: x-api-key: YOUR_API_KEY or Authorization: Bearer YOUR_API_KEY

Required scope: voice:calls

ℹ️ Voice Minutes Are Consumed Per Call

Each call placed through this API deducts 1 voice minute from your account balance at the moment the call is initiated, not when it ends. If the remaining balance is insufficient, the request is rejected with a 402 response and no call is placed.

Check your remaining balance with the Balance API before placing calls in a batch.


Place an Outbound Call

Initiate an outbound call that plays a text-to-speech or audio message, runs a conversational AI agent, or renders a saved XML template.

Endpoint: POST /voice/call

At least one of audioName, aiAgentId, or xmlId is required. The call is routed automatically based on the destination number and your voiceRoute setting.

Parameters

ParameterTypeRequiredDescription
tostringYesRecipient phone number, minimum 10 digits (e.g. 919424810211). The platform normalizes the value to E.164 automatically.
audioNamestringOne ofText to speak as text-to-speech, or an absolute URL to a playable audio file.
aiAgentIdstringOne ofUUID of a Conversational AI agent for a real-time bidirectional conversation.
xmlIdstringOne ofUUID of a saved XML template to render as the call flow.
voiceRoutestringNoRouting preference. Defaults to auto. See Routing below.
fromNumberstringNoOverride the caller ID. Falls back to your default outbound number for the selected route.
recipientNamestringNoName to associate with the call in logs and transcripts.

Routing

voiceRoute valueBehaviour
auto (default)Indian destinations are routed through the Indian Route; all other destinations use the US Route.
indianForce the Indian Route.
usForce the US Route.
plivoForce IN2.
A phone number you ownUses that number as the caller ID. If the number is an IN2 number, the call is placed through IN2.

Response

{ "success": true, "callId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "route": "vobiz", "from": "+918065480950", "to": "+919424810211", "status": "initiated", "remainingVoiceMins": 19 }

Response Fields

FieldTypeDescription
successbooleanRequest success status
callIdstringUnique call identifier used to correlate the call with its log entry
routestringRoute that carried the call: vobiz (Indian Route), signalwire (US Route), or plivo (IN2)
fromstringCaller ID the call was placed from, in E.164 format
tostringRecipient number the call was placed to, in E.164 format
statusstringInitial call status. Always initiated on success — the call is queued with the carrier at this point, not yet answered.
remainingVoiceMinsintegerVoice minutes remaining after this call was deducted
⚠️ A Successful Response Is Not a Connected Call

A 200 response means the carrier accepted the call request. It does not mean the recipient answered. Poll Voice Call Logs or review the Call Logs page in the dashboard for the final call outcome.

Errors

StatusCause
400to is missing or shorter than 10 digits
400None of aiAgentId, xmlId, or audioName was provided
401API key is missing or invalid
402Insufficient voice minutes balance
403The API key does not have the voice:calls scope
500Credentials for the selected route are not configured on your account

Example

curl:

curl -X POST "https://voxvaani.com/api/v1/voice/call" \ -H "x-api-key: YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "to": "919424810211", "audioName": "Hello from Voxvaani! This is a test call from our API.", "recipientName": "John Doe" }'

Python:

import requests response = requests.post( "https://voxvaani.com/api/v1/voice/call", headers={"x-api-key": "YOUR_API_KEY"}, json={ "to": "919424810211", "audioName": "Hello from Voxvaani! This is a test call from our API.", "recipientName": "John Doe", }, ) data = response.json() print(f"Call {data['callId']} via {data['route']}: {data['status']}")

JavaScript:

const response = await fetch("https://voxvaani.com/api/v1/voice/call", { method: "POST", headers: { "x-api-key": "YOUR_API_KEY", "Content-Type": "application/json" }, body: JSON.stringify({ to: "919424810211", audioName: "Hello from Voxvaani! This is a test call from our API.", recipientName: "John Doe" }) }); const data = await response.json(); console.log(`Call ${data.callId} via ${data.route}: ${data.status}`);

Fetch Voice Call Logs

Query the history of calls placed through this API. Supports filtering by status, route, phone number, and date range.

Endpoint: GET /voice/call-logs

Only calls placed via the API (type: "API Voice Call") are returned. Calls launched from dashboard campaigns are excluded — see Call Logs for the full call history view.

Query Parameters

ParameterTypeDescription
statusstringFilter by call status: all (default), initiated, in-progress, answered, success, no-answer, failed
routestringFilter by route: indian / IN1 (Indian Route), us / US1 (US Route), IN2 / plivo (IN2), vobiz, signalwire. Defaults to all.
searchstringSearch by phone number digits
fromstringStart of date range, ISO date format (e.g. 2026-07-01)
tostringEnd of date range, ISO date format. Interpreted as end of day.
pageintegerPage number. Default 1.
pageSizeintegerRecords per page. Default 10, maximum 100.

Response

{ "success": true, "data": [ { "id": "clog_abc123", "phone": "+919424810211", "type": "API Voice Call", "duration": 45, "cost": 0, "status": "Success", "callStatus": "answered", "route": "vobiz", "campaignName": "John Doe", "transcript": "API Voice Call initiated via vobiz.\nFrom: +918065480950\nTo: +919424810211", "createdAt": "2026-07-14T10:00:00.000Z", "updatedAt": "2026-07-14T10:00:52.000Z" } ], "pagination": { "page": 1, "pageSize": 10, "total": 1, "totalPages": 1 } }

Response Fields

FieldTypeDescription
data[].idstringCall log identifier
data[].phonestringRecipient number in E.164 format
data[].typestringAlways API Voice Call for this endpoint
data[].durationintegerCall duration in seconds. 0 while the call is still in progress.
data[].statusstringDashboard status label (e.g. Started, Success, Failed)
data[].callStatusstringNormalized carrier status (e.g. initiated, in-progress, answered, failed)
data[].routestringRoute that carried the call
data[].campaignNamestringThe recipientName value, or the recipient number when none was supplied
data[].transcriptstringCall transcript and initiation details. May be empty for calls that did not connect.
data[].createdAtstringTimestamp when the call was initiated
data[].updatedAtstringTimestamp of the last status update
pagination.pageintegerCurrent page number
pagination.pageSizeintegerRecords returned per page
pagination.totalintegerTotal matching records
pagination.totalPagesintegerTotal number of pages

Example

curl:

curl -X GET "https://voxvaani.com/api/v1/voice/call-logs?status=answered&page=1&pageSize=10" \ -H "x-api-key: YOUR_API_KEY"

Python:

import requests response = requests.get( "https://voxvaani.com/api/v1/voice/call-logs", headers={"x-api-key": "YOUR_API_KEY"}, params={"status": "answered", "page": 1, "pageSize": 10}, ) data = response.json() for call in data["data"]: print(f"{call['phone']}{call['callStatus']} ({call['duration']}s)")

JavaScript:

const params = new URLSearchParams({ status: "answered", page: "1", pageSize: "10" }); const response = await fetch(`https://voxvaani.com/api/v1/voice/call-logs?${params}`, { headers: { "x-api-key": "YOUR_API_KEY" } }); const { data, pagination } = await response.json(); console.log(`${pagination.total} answered calls`);

Tips

  • Set recipientName on every call — it is the only human-readable label available when reviewing call logs later
  • Prefer voiceRoute: "auto" unless you have a specific reason to pin a route; automatic routing selects the most cost-effective carrier for the destination
  • Deduct balances are taken at initiation, so validate your remaining voice minutes before looping over a large recipient list
  • A 200 response confirms the carrier accepted the request — track callStatus afterwards to determine whether the call actually connected
  • Use the no-answer and failed status filters to build retry logic for calls that did not connect