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/v1Authentication
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
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
| Parameter | Type | Required | Description |
|---|---|---|---|
to | string | Yes | Recipient phone number, minimum 10 digits (e.g. 919424810211). The platform normalizes the value to E.164 automatically. |
audioName | string | One of | Text to speak as text-to-speech, or an absolute URL to a playable audio file. |
aiAgentId | string | One of | UUID of a Conversational AI agent for a real-time bidirectional conversation. |
xmlId | string | One of | UUID of a saved XML template to render as the call flow. |
voiceRoute | string | No | Routing preference. Defaults to auto. See Routing below. |
fromNumber | string | No | Override the caller ID. Falls back to your default outbound number for the selected route. |
recipientName | string | No | Name to associate with the call in logs and transcripts. |
Routing
voiceRoute value | Behaviour |
|---|---|
auto (default) | Indian destinations are routed through the Indian Route; all other destinations use the US Route. |
indian | Force the Indian Route. |
us | Force the US Route. |
plivo | Force IN2. |
| A phone number you own | Uses 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
| Field | Type | Description |
|---|---|---|
success | boolean | Request success status |
callId | string | Unique call identifier used to correlate the call with its log entry |
route | string | Route that carried the call: vobiz (Indian Route), signalwire (US Route), or plivo (IN2) |
from | string | Caller ID the call was placed from, in E.164 format |
to | string | Recipient number the call was placed to, in E.164 format |
status | string | Initial call status. Always initiated on success — the call is queued with the carrier at this point, not yet answered. |
remainingVoiceMins | integer | Voice minutes remaining after this call was deducted |
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
| Status | Cause |
|---|---|
400 | to is missing or shorter than 10 digits |
400 | None of aiAgentId, xmlId, or audioName was provided |
401 | API key is missing or invalid |
402 | Insufficient voice minutes balance |
403 | The API key does not have the voice:calls scope |
500 | Credentials 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
| Parameter | Type | Description |
|---|---|---|
status | string | Filter by call status: all (default), initiated, in-progress, answered, success, no-answer, failed |
route | string | Filter by route: indian / IN1 (Indian Route), us / US1 (US Route), IN2 / plivo (IN2), vobiz, signalwire. Defaults to all. |
search | string | Search by phone number digits |
from | string | Start of date range, ISO date format (e.g. 2026-07-01) |
to | string | End of date range, ISO date format. Interpreted as end of day. |
page | integer | Page number. Default 1. |
pageSize | integer | Records 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
| Field | Type | Description |
|---|---|---|
data[].id | string | Call log identifier |
data[].phone | string | Recipient number in E.164 format |
data[].type | string | Always API Voice Call for this endpoint |
data[].duration | integer | Call duration in seconds. 0 while the call is still in progress. |
data[].status | string | Dashboard status label (e.g. Started, Success, Failed) |
data[].callStatus | string | Normalized carrier status (e.g. initiated, in-progress, answered, failed) |
data[].route | string | Route that carried the call |
data[].campaignName | string | The recipientName value, or the recipient number when none was supplied |
data[].transcript | string | Call transcript and initiation details. May be empty for calls that did not connect. |
data[].createdAt | string | Timestamp when the call was initiated |
data[].updatedAt | string | Timestamp of the last status update |
pagination.page | integer | Current page number |
pagination.pageSize | integer | Records returned per page |
pagination.total | integer | Total matching records |
pagination.totalPages | integer | Total 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
recipientNameon 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
200response confirms the carrier accepted the request — trackcallStatusafterwards to determine whether the call actually connected - Use the
no-answerandfailedstatus filters to build retry logic for calls that did not connect