curl --request POST \
--url https://api.lehar.ai/ca/api/v0/calls \
--header 'Content-Type: application/json' \
--header 'X-API-KEY: <api-key>' \
--data '
{
"agent_id": "agent_sales_hi",
"to_number": "+919876543210",
"callee_name": "Jane",
"custom_variables": {
"company": "Acme"
},
"idempotency_key": "crm-lead-8821",
"call_config": {
"max_call_length": 600,
"call_retry_config": {
"retry_count": 2,
"retry_not_picked": 30
},
"call_time": {
"call_start_time": "10:00",
"call_end_time": "19:00",
"timezone": "Asia/Kolkata"
}
}
}
'import requests
url = "https://api.lehar.ai/ca/api/v0/calls"
payload = {
"agent_id": "agent_sales_hi",
"to_number": "+919876543210",
"callee_name": "Jane",
"custom_variables": { "company": "Acme" },
"idempotency_key": "crm-lead-8821",
"call_config": {
"max_call_length": 600,
"call_retry_config": {
"retry_count": 2,
"retry_not_picked": 30
},
"call_time": {
"call_start_time": "10:00",
"call_end_time": "19:00",
"timezone": "Asia/Kolkata"
}
}
}
headers = {
"X-API-KEY": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'X-API-KEY': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
agent_id: 'agent_sales_hi',
to_number: '+919876543210',
callee_name: 'Jane',
custom_variables: {company: 'Acme'},
idempotency_key: 'crm-lead-8821',
call_config: {
max_call_length: 600,
call_retry_config: {retry_count: 2, retry_not_picked: 30},
call_time: {call_start_time: '10:00', call_end_time: '19:00', timezone: 'Asia/Kolkata'}
}
})
};
fetch('https://api.lehar.ai/ca/api/v0/calls', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.lehar.ai/ca/api/v0/calls",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'agent_id' => 'agent_sales_hi',
'to_number' => '+919876543210',
'callee_name' => 'Jane',
'custom_variables' => [
'company' => 'Acme'
],
'idempotency_key' => 'crm-lead-8821',
'call_config' => [
'max_call_length' => 600,
'call_retry_config' => [
'retry_count' => 2,
'retry_not_picked' => 30
],
'call_time' => [
'call_start_time' => '10:00',
'call_end_time' => '19:00',
'timezone' => 'Asia/Kolkata'
]
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-API-KEY: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.lehar.ai/ca/api/v0/calls"
payload := strings.NewReader("{\n \"agent_id\": \"agent_sales_hi\",\n \"to_number\": \"+919876543210\",\n \"callee_name\": \"Jane\",\n \"custom_variables\": {\n \"company\": \"Acme\"\n },\n \"idempotency_key\": \"crm-lead-8821\",\n \"call_config\": {\n \"max_call_length\": 600,\n \"call_retry_config\": {\n \"retry_count\": 2,\n \"retry_not_picked\": 30\n },\n \"call_time\": {\n \"call_start_time\": \"10:00\",\n \"call_end_time\": \"19:00\",\n \"timezone\": \"Asia/Kolkata\"\n }\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-API-KEY", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.lehar.ai/ca/api/v0/calls")
.header("X-API-KEY", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"agent_id\": \"agent_sales_hi\",\n \"to_number\": \"+919876543210\",\n \"callee_name\": \"Jane\",\n \"custom_variables\": {\n \"company\": \"Acme\"\n },\n \"idempotency_key\": \"crm-lead-8821\",\n \"call_config\": {\n \"max_call_length\": 600,\n \"call_retry_config\": {\n \"retry_count\": 2,\n \"retry_not_picked\": 30\n },\n \"call_time\": {\n \"call_start_time\": \"10:00\",\n \"call_end_time\": \"19:00\",\n \"timezone\": \"Asia/Kolkata\"\n }\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.lehar.ai/ca/api/v0/calls")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["X-API-KEY"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"agent_id\": \"agent_sales_hi\",\n \"to_number\": \"+919876543210\",\n \"callee_name\": \"Jane\",\n \"custom_variables\": {\n \"company\": \"Acme\"\n },\n \"idempotency_key\": \"crm-lead-8821\",\n \"call_config\": {\n \"max_call_length\": 600,\n \"call_retry_config\": {\n \"retry_count\": 2,\n \"retry_not_picked\": 30\n },\n \"call_time\": {\n \"call_start_time\": \"10:00\",\n \"call_end_time\": \"19:00\",\n \"timezone\": \"Asia/Kolkata\"\n }\n }\n}"
response = http.request(request)
puts response.read_body{
"call_id": "call_01EXAMPLE",
"customer_id": "customer_01EXAMPLE",
"agent_id": "agent_sales_hi",
"status": "queued",
"outcome": null,
"sub_status": null,
"error": null,
"to_number_masked": "+***3210",
"callee_name": "Jane",
"from_number": "+911140000000",
"from_phone_number_id": "pn_01EXAMPLE",
"custom_variables": {
"company": "Acme"
},
"call_config": {
"max_call_length": 600
},
"smart_formatter": {},
"scheduled_for": null,
"attempt_count": 0,
"session_id": null,
"created_at": "2026-08-11T09:00:00Z",
"updated_at": "2026-08-11T09:00:00Z",
"completed_at": null
}Place an outbound call
Fires one outbound phone call, server-to-server. Requires an X-API-KEY credential — bearer logins and agent-session tokens are rejected even though they can carry sessions:write. Answers 200 with the call record; the call may not have dialled yet. The agent must be a published, voice-channel agent (enforced asynchronously at dial time, not by a synchronous check on this request). Scope sessions:write.
curl --request POST \
--url https://api.lehar.ai/ca/api/v0/calls \
--header 'Content-Type: application/json' \
--header 'X-API-KEY: <api-key>' \
--data '
{
"agent_id": "agent_sales_hi",
"to_number": "+919876543210",
"callee_name": "Jane",
"custom_variables": {
"company": "Acme"
},
"idempotency_key": "crm-lead-8821",
"call_config": {
"max_call_length": 600,
"call_retry_config": {
"retry_count": 2,
"retry_not_picked": 30
},
"call_time": {
"call_start_time": "10:00",
"call_end_time": "19:00",
"timezone": "Asia/Kolkata"
}
}
}
'import requests
url = "https://api.lehar.ai/ca/api/v0/calls"
payload = {
"agent_id": "agent_sales_hi",
"to_number": "+919876543210",
"callee_name": "Jane",
"custom_variables": { "company": "Acme" },
"idempotency_key": "crm-lead-8821",
"call_config": {
"max_call_length": 600,
"call_retry_config": {
"retry_count": 2,
"retry_not_picked": 30
},
"call_time": {
"call_start_time": "10:00",
"call_end_time": "19:00",
"timezone": "Asia/Kolkata"
}
}
}
headers = {
"X-API-KEY": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'X-API-KEY': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
agent_id: 'agent_sales_hi',
to_number: '+919876543210',
callee_name: 'Jane',
custom_variables: {company: 'Acme'},
idempotency_key: 'crm-lead-8821',
call_config: {
max_call_length: 600,
call_retry_config: {retry_count: 2, retry_not_picked: 30},
call_time: {call_start_time: '10:00', call_end_time: '19:00', timezone: 'Asia/Kolkata'}
}
})
};
fetch('https://api.lehar.ai/ca/api/v0/calls', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.lehar.ai/ca/api/v0/calls",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'agent_id' => 'agent_sales_hi',
'to_number' => '+919876543210',
'callee_name' => 'Jane',
'custom_variables' => [
'company' => 'Acme'
],
'idempotency_key' => 'crm-lead-8821',
'call_config' => [
'max_call_length' => 600,
'call_retry_config' => [
'retry_count' => 2,
'retry_not_picked' => 30
],
'call_time' => [
'call_start_time' => '10:00',
'call_end_time' => '19:00',
'timezone' => 'Asia/Kolkata'
]
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-API-KEY: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.lehar.ai/ca/api/v0/calls"
payload := strings.NewReader("{\n \"agent_id\": \"agent_sales_hi\",\n \"to_number\": \"+919876543210\",\n \"callee_name\": \"Jane\",\n \"custom_variables\": {\n \"company\": \"Acme\"\n },\n \"idempotency_key\": \"crm-lead-8821\",\n \"call_config\": {\n \"max_call_length\": 600,\n \"call_retry_config\": {\n \"retry_count\": 2,\n \"retry_not_picked\": 30\n },\n \"call_time\": {\n \"call_start_time\": \"10:00\",\n \"call_end_time\": \"19:00\",\n \"timezone\": \"Asia/Kolkata\"\n }\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-API-KEY", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.lehar.ai/ca/api/v0/calls")
.header("X-API-KEY", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"agent_id\": \"agent_sales_hi\",\n \"to_number\": \"+919876543210\",\n \"callee_name\": \"Jane\",\n \"custom_variables\": {\n \"company\": \"Acme\"\n },\n \"idempotency_key\": \"crm-lead-8821\",\n \"call_config\": {\n \"max_call_length\": 600,\n \"call_retry_config\": {\n \"retry_count\": 2,\n \"retry_not_picked\": 30\n },\n \"call_time\": {\n \"call_start_time\": \"10:00\",\n \"call_end_time\": \"19:00\",\n \"timezone\": \"Asia/Kolkata\"\n }\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.lehar.ai/ca/api/v0/calls")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["X-API-KEY"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"agent_id\": \"agent_sales_hi\",\n \"to_number\": \"+919876543210\",\n \"callee_name\": \"Jane\",\n \"custom_variables\": {\n \"company\": \"Acme\"\n },\n \"idempotency_key\": \"crm-lead-8821\",\n \"call_config\": {\n \"max_call_length\": 600,\n \"call_retry_config\": {\n \"retry_count\": 2,\n \"retry_not_picked\": 30\n },\n \"call_time\": {\n \"call_start_time\": \"10:00\",\n \"call_end_time\": \"19:00\",\n \"timezone\": \"Asia/Kolkata\"\n }\n }\n}"
response = http.request(request)
puts response.read_body{
"call_id": "call_01EXAMPLE",
"customer_id": "customer_01EXAMPLE",
"agent_id": "agent_sales_hi",
"status": "queued",
"outcome": null,
"sub_status": null,
"error": null,
"to_number_masked": "+***3210",
"callee_name": "Jane",
"from_number": "+911140000000",
"from_phone_number_id": "pn_01EXAMPLE",
"custom_variables": {
"company": "Acme"
},
"call_config": {
"max_call_length": 600
},
"smart_formatter": {},
"scheduled_for": null,
"attempt_count": 0,
"session_id": null,
"created_at": "2026-08-11T09:00:00Z",
"updated_at": "2026-08-11T09:00:00Z",
"completed_at": null
}Authorizations
Body
A published voice agent.
Destination in E.164, e.g. +919876543210.
128Caller ID to dial from.
Scalar values substituted into the agent's prompt. Max 64 keys, 30 KB total.
Show child attributes
Show child attributes
Opaque JSON echoed back on the call record, and echoed verbatim as the metadata field on every webhook event for this call (call_started, call_completed, recording_completed) — use it to correlate events against your own records. Max 16 KiB.
A repeat of the same key returns 409 instead of dialling twice.
^[A-Za-z0-9_.:-]{1,128}$Show child attributes
Show child attributes
Accepted and echoed back for contract compatibility, but NOT applied to the call.
Response
The call record. to_number is never echoed — only to_number_masked.

