Make a Call — Agent to Customer
Initiate an outbound call connecting an agent (user) to a customer. The agent is called first on their configured device (phone/SIP), then the customer is dialed.
info
This is a Voice v2 (CCM) API. Agents must be added as co-workers in the Exotel dashboard and their device must be ON. For calls without user context, see Voice v1.
Endpoint​
POST /v2/accounts/<account_sid>/calls
Regional URLs​
| Region | URL |
|---|---|
| Singapore | https://<api_key>:<api_token>@ccm-api.exotel.com/v2/accounts/<account_sid>/calls |
| Mumbai | https://<api_key>:<api_token>@ccm-api.in.exotel.com/v2/accounts/<account_sid>/calls |
Request Body (JSON)​
{
"from": {
"user_contact_uri": "sip:agent@exotel.com"
},
"to": {
"number": "+919876543210"
},
"virtual_number": "+911234567890",
"recording": true,
"recording_channels": "dual",
"custom_field": "ticket_12345",
"status_callback": [
{
"event": "terminal",
"url": "https://your-server.com/webhook/call-status"
},
{
"event": "answered",
"url": "https://your-server.com/webhook/call-answered"
}
]
}
Request Parameters​
| Parameter | Required | Type | Description |
|---|---|---|---|
from | Yes | Object | Agent identifier. Use user_contact_uri (SIP URI) or user_id (UUID from dashboard). |
to | Yes | Object | Customer phone number in E.164 format: {"number": "+91XXXXXXXXXX"} |
virtual_number | Yes | String | ExoPhone in E.164 format. |
recording | No | Boolean | Enable call recording. Default: false. |
recording_channels | No | String | single (mixed) or dual (separate agent/customer). |
wait_audio_url | No | String | Audio URL (WAV) played to agent while customer is being dialed. Recommended: under 2MB. |
max_time_limit | No | Integer | Maximum call duration in seconds. |
attempt_time_out | No | Integer | Ring timeout in seconds. |
custom_field | No | String | Application-specific metadata. |
status_callback | No | Array | Webhook event configurations (see above). |
From Object Options​
// Option 1: By SIP URI
{ "user_contact_uri": "sip:agent@exotel.com" }
// Option 2: By user ID
{ "user_id": "agent-uuid-from-dashboard" }
// Option 3: By phone number
{ "user_contact_uri": "+919999999999" }
Code Examples​
- cURL
- Python
- Node.js
curl -X POST 'https://<api_key>:<api_token>@ccm-api.exotel.com/v2/accounts/<account_sid>/calls' \
-H 'Content-Type: application/json' \
-d '{
"from": {"user_contact_uri": "sip:agent@exotel.com"},
"to": {"number": "+919876543210"},
"virtual_number": "+911234567890",
"recording": true,
"status_callback": [{"event": "terminal", "url": "https://your-server.com/webhook"}]
}'
import requests
import json
url = "https://ccm-api.exotel.com/v2/accounts/<account_sid>/calls"
payload = {
"from": {"user_contact_uri": "sip:agent@exotel.com"},
"to": {"number": "+919876543210"},
"virtual_number": "+911234567890",
"recording": True,
"status_callback": [
{"event": "terminal", "url": "https://your-server.com/webhook"}
]
}
response = requests.post(
url,
auth=("<api_key>", "<api_token>"),
headers={"Content-Type": "application/json"},
data=json.dumps(payload)
)
print(response.json())
const axios = require('axios');
const response = await axios.post(
'https://ccm-api.exotel.com/v2/accounts/<account_sid>/calls',
{
from: { user_contact_uri: 'sip:agent@exotel.com' },
to: { number: '+919876543210' },
virtual_number: '+911234567890',
recording: true,
status_callback: [
{ event: 'terminal', url: 'https://your-server.com/webhook' }
]
},
{
auth: { username: '<api_key>', password: '<api_token>' },
headers: { 'Content-Type': 'application/json' }
}
);
console.log(response.data);
Response​
{
"request_id": "req_abc123",
"method": "POST",
"http_code": 200,
"response": {
"call_sid": "unique_call_identifier",
"call_state": "active",
"call_status": null,
"assigned_agent_details": {
"user_id": "agent-uuid",
"contact_uri": "sip:agent@exotel.com"
},
"customer_details": {
"number": "+919876543210"
},
"virtual_number": "+911234567890",
"recording": true,
"created_time": "2024-06-15T10:30:00.000Z"
}
}
note
HTTP 200 is not a confirmation of successful call placement. Use the StatusCallback webhook or the Call Details API to check actual call status.
Error Responses​
| HTTP Code | Error Code | Description |
|---|---|---|
401 | 1010 | Authentication failed — check API key/token |
404 | 10731 | User not found — agent must be added in dashboard |
409 | 1012 | User device unavailable — device is OFF |
409 | 10705 | User device unverified |
409 | 10706 | User device busy — agent is on another call |
404 | 10716 | Virtual number not found — check ExoPhone |
500 | 1100 | Internal Server Error |