Calls API
Use the Slovio Calls API to place an outbound AI voice call, pass call variables to your agent, and read the call's status, outcome, duration and cost.
5 min readUpdated
To place an AI voice call from your own system, send POST /v1/comms/calls with your voice agent's ID, the number to call and any variables the agent should use. Then read the call with GET /v1/comms/calls/{callId}, or receive events through calling webhooks. Your plan must include both API access and AI Calling.
Place a call
POST https://api.slovio.ai/v1/comms/callscurl -X POST https://api.slovio.ai/v1/comms/calls \
-H "x-access-key: $SLOVIO_ACCESS_KEY" \
-H "Authorization: Bearer $SLOVIO_SECRET_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: appt-20261004-8812" \
-d '{
"agentId": "66f2a9c4e1b7d30012ab45cd",
"to": "+919876543210",
"variables": {
"customer_name": "Priya Sharma",
"appointment_time": "4 October, 11:30 AM",
"fee": 500
}
}'| Field | Rules |
|---|---|
agentId |
Required. The voice agent that makes the call: its ID in Calling, or the agent's uuid. 1 to 64 characters. |
to |
Required. E.164 format: +, country code, number (+919876543210). |
from |
Optional. One of your active numbers. Leave it out to use your default caller ID. |
variables |
Optional. Values the agent can use in its prompts. See the rules below. |
idempotencyKey |
Optional. 8 to 128 characters of A-Z a-z 0-9 . _ -. You can send it as the Idempotency-Key header instead. |
Any other field in the body is rejected with a validation error.
Find your agent ID
- Open Calling → API.
- In Place a call, pick your agent in Agent in the example.
- The example request below it now contains that agent's
agentId. Select Copy.
The ID is also in the address bar when you open an agent with Edit flow: it is the last part of /dashboard/calling-workflow/<id>.
Variables: how to pass them
Each variable fills a {{name}} token in the agent's prompts. If the prompt says Confirm the appointment on {{appointment_time}}, send "appointment_time": "4 October, 11:30 AM".
| Rule | Limit |
|---|---|
| How many | Up to 50 per call. |
| Names | Start with a letter or _, then letters, digits or _. Up to 64 characters ([A-Za-z_][A-Za-z0-9_]{0,63}). |
| Values | A string (up to 1000 characters), a number, or true/false. No objects or lists. |
| Reserved names | nodes_visited and extracted_variables are used by the call itself and are refused. |
A token with no value becomes empty, and the agent is told not to invent it. Names are case-sensitive: {{customer_name}} and {{Customer_Name}} are different.
Idempotency
Use one key per intended call, such as your appointment ID plus the attempt. If a network error leaves you unsure whether the call was placed, send the same request with the same key:
- Same key, same
agentIdandto: you get the original call back with"message": "Call already placed"and"replayed": true. Nothing is dialled or charged again. - Same key, different agent or number: HTTP 400,
This idempotency key was already used for a different call. - Header and body key both sent but different: HTTP 400,
Idempotency-Key header and idempotencyKey differ.
The response
A placed call returns HTTP 200:
{
"statusCode": "10000",
"status": 200,
"message": "Call initiated",
"data": {
"callId": "api-3f9c0b1e7d2a4c58b6e1f0a9d8c7b6a5e4d3c2b1",
"status": "initiated",
"direction": "outbound",
"agentId": "66f2a9c4e1b7d30012ab45cd",
"to": "+919876543210",
"outcome": null,
"durationSeconds": 0,
"cost": null,
"authorizedAmount": 12.5,
"recordingAvailable": false,
"createdAt": "2026-10-03T05:30:12.000Z",
"updatedAt": "2026-10-03T05:30:12.000Z",
"replayed": false
}
}Save callId. authorizedAmount is the amount held from your wallet for this call. The actual cost is settled after the call ends.
Get a call
GET https://api.slovio.ai/v1/comms/calls/{callId}{
"statusCode": "10000",
"status": 200,
"message": "Call fetched",
"data": {
"callId": "api-3f9c0b1e7d2a4c58b6e1f0a9d8c7b6a5e4d3c2b1",
"status": "completed",
"direction": "outbound",
"agentId": "66f2a9c4e1b7d30012ab45cd",
"to": "+919876543210",
"outcome": "completed",
"durationSeconds": 74,
"cost": 4.2,
"authorizedAmount": 12.5,
"recordingAvailable": true,
"createdAt": "2026-10-03T05:30:12.000Z",
"updatedAt": "2026-10-03T05:31:40.000Z"
}
}| Field | Meaning |
|---|---|
status |
initiated, completed, no_answer, busy or failed. |
outcome |
How the call ended, once it has ended. null before that. |
durationSeconds |
Connected time. |
cost |
The settled cost from your wallet. null until the call is settled. |
recordingAvailable |
true if a recording exists. |
An unknown callId, or one from another account, returns 404 Call not found.
Errors when placing a call
| HTTP | Message | What to do |
|---|---|---|
| 400 | to must be E.164 format (e.g. +12025550100) |
Add + and the country code. |
| 404 | Agent not found |
Check agentId. It must be an agent in this account. |
| 404 | From number not found |
from must be one of your active numbers. |
| 400 | Insufficient balance to start the call |
Recharge your wallet. |
| 400 | Calling is not priced for your account yet |
Ask Slovio support to set up calling rates. |
| 400 | This number is on your do-not-call list |
The person can't be called. |
| 403 | Business verification is overdue (or a more specific reason) |
Complete business verification. |
| 400 | Your calling line is busy — try again in N second(s) |
Wait that many seconds and retry with the same key. |
| 403 | Feature not available in your plan. Please upgrade to access this feature. |
Your plan needs API access and AI Calling. |
Validation errors use the shape in Errors and rate limits.
Limits and billing
- You can place 60 calls per minute and read calls 600 times per minute per API key.
- Each call holds an estimated amount from your wallet when it is placed. After the call, only the connected minutes are charged and the rest is released.
- API calls go through the same checks as calls started in the app: your do-not-call list, business verification, your line's pacing and your wallet balance.
Common questions
Where do I find the agentId?
In Calling → API, pick the agent in Agent in the example and copy the request. The ID is also the last part of the address when you open the agent with Edit flow.
Can I send a variable with a space in its name?
No. Names can only use letters, digits and _, and must not start with a digit. Use customer_name, not customer name.
Why is cost null?
The cost is settled after the call ends. Read the call again a little later, or wait for the call.ended webhook.
Can I download the recording or transcript through the API?
Not at the moment. The API tells you whether a recording exists. Open the call in Calling → Call Logs to play or download it.
What happens if I retry with the same Idempotency-Key?
You get the same call back with "message": "Call already placed". The person is not called twice and you are not charged twice.
Stuck, or is something here out of date? Tell the team — we reply within a working day.