Call endpoints
ReachCell supports call signalling — not live voice streaming. Call state events are delivered to your registered webhook endpoint. See Same-country-code rule for destination restrictions.
POST /v1/calls/dial
Initiate an outbound call from one of your provisioned numbers.
Request body
| Field | Type | Required | Notes |
|---|---|---|---|
from | string | Yes | Your provisioned number in E.164 format. |
to | string | Yes | Destination number in E.164 format. Must be in the same country as from. |
Response (202 Accepted)
{
"success": true,
"data": {
"call_id": "b4e2f7a1-83fe-4aed-b7ef-471f2efc95a9",
"from": "+14155552671",
"to": "+14155553000",
"status": "initiating",
"created_at": "2026-06-08T13:30:06Z"
}
}
import requests
r = requests.post(
"https://api.reachcell.com/v1/calls/dial",
headers={
"Authorization": "Bearer ak_your_api_key",
"Content-Type": "application/json",
},
json={
"from": "+91XXXXXXXXXX", # provisioned number
"to": "+91YYYYYYYYYY", # same-country destination
},
)
call = r.json()["data"]
print(call["call_id"], call["status"]) # status: initiating<?php
$ch = curl_init('https://api.reachcell.com/v1/calls/dial');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ak_your_api_key',
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode([
'from' => '+91XXXXXXXXXX',
'to' => '+91YYYYYYYYYY',
]),
]);
$body = json_decode(curl_exec($ch), true);
curl_close($ch);
$callId = $body['data']['call_id'];
// Monitor via GET /v1/calls/{callId} or call.* webhooksconst res = await fetch('https://api.reachcell.com/v1/calls/dial', {
method: 'POST',
headers: {
Authorization: 'Bearer ak_your_api_key',
'Content-Type': 'application/json',
},
body: JSON.stringify({
from: '+91XXXXXXXXXX',
to: '+91YYYYYYYYYY',
}),
});
const { data } = await res.json();
const callId = data.call_id; // status: initiatingPOST /v1/calls/{call_id}/hangup
End an active or ringing call. Valid when status is initiating, ringing, or connected.
import requests
call_id = "b4e2f7a1-83fe-4aed-b7ef-471f2efc95a9"
r = requests.post(
f"https://api.reachcell.com/v1/calls/{call_id}/hangup",
headers={"Authorization": "Bearer ak_your_api_key"},
)
print(r.json()["data"]["status"]) # ended<?php
$callId = 'b4e2f7a1-83fe-4aed-b7ef-471f2efc95a9';
$ch = curl_init("https://api.reachcell.com/v1/calls/{$callId}/hangup");
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ak_your_api_key'],
]);
$body = json_decode(curl_exec($ch), true);
curl_close($ch);
echo $body['data']['status']; // endedconst callId = 'b4e2f7a1-83fe-4aed-b7ef-471f2efc95a9';
const res = await fetch(
`https://api.reachcell.com/v1/calls/${callId}/hangup`,
{ method: 'POST', headers: { Authorization: 'Bearer ak_your_api_key' } },
);
const { data } = await res.json();
console.log(data.status); // endedPOST /v1/calls/{call_id}/answer
Answer an inbound call that is in the ringing state. For missed-call verification workflows you typically do not answer — just let the call.missed webhook confirm the number.
import requests
call_id = "b4e2f7a1-..."
r = requests.post(
f"https://api.reachcell.com/v1/calls/{call_id}/answer",
headers={"Authorization": "Bearer ak_your_api_key"},
)
print(r.json()["data"]["status"]) # answering<?php
$callId = 'b4e2f7a1-...';
$ch = curl_init("https://api.reachcell.com/v1/calls/{$callId}/answer");
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ak_your_api_key'],
]);
$body = json_decode(curl_exec($ch), true);
curl_close($ch);
echo $body['data']['status']; // answeringconst callId = 'b4e2f7a1-...';
const res = await fetch(
`https://api.reachcell.com/v1/calls/${callId}/answer`,
{ method: 'POST', headers: { Authorization: 'Bearer ak_your_api_key' } },
);
const { data } = await res.json();
console.log(data.status); // answeringGET /v1/calls/{call_id}
Retrieve call details and current status.
Response fields
| Field | Description |
|---|---|
call_id | UUID of the call session. |
from | Originating number (E.164). |
to | Destination number (E.164). |
direction | outbound or inbound. |
status | initiating, ringing, connected, ended, missed, rejected, or failed. |
initiated_at | When the call was initiated. |
ringing_at | When the device began ringing, or null. |
connected_at | When the call was answered, or null. |
ended_at | When the call ended/missed/rejected, or null. |
duration_seconds | Connected duration in seconds, or null if never answered. |
cost_usd | Per-call charge in USD, or null if within plan allowance. |
created_at | Timestamp the record was created. |
import requests
call_id = "b4e2f7a1-83fe-4aed-b7ef-471f2efc95a9"
r = requests.get(
f"https://api.reachcell.com/v1/calls/{call_id}",
headers={"Authorization": "Bearer ak_your_api_key"},
)
call = r.json()["data"]
print(call["status"], call["duration_seconds"])<?php
$callId = 'b4e2f7a1-83fe-4aed-b7ef-471f2efc95a9';
$ch = curl_init("https://api.reachcell.com/v1/calls/{$callId}");
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ak_your_api_key'],
]);
$body = json_decode(curl_exec($ch), true);
curl_close($ch);
echo $body['data']['status']; // missed, ended, connected, etc.
echo $body['data']['duration_seconds']; // null if never answeredconst callId = 'b4e2f7a1-83fe-4aed-b7ef-471f2efc95a9';
const res = await fetch(
`https://api.reachcell.com/v1/calls/${callId}`,
{ headers: { Authorization: 'Bearer ak_your_api_key' } },
);
const { data } = await res.json();
console.log(data.status, data.duration_seconds);GET /v1/calls
List all calls for your account, newest first. Paginated.
Query parameters
| Parameter | Description |
|---|---|
number | Filter by E.164 number (matches from or to). |
direction | inbound or outbound. |
status | One of: initiating, ringing, connected, ended, missed, rejected, failed. |
from_date | Start date (YYYY-MM-DD, inclusive). |
to_date | End date (YYYY-MM-DD, inclusive). |
page | Page number, default 1. |
per_page | Results per page, default 20. |
import requests
r = requests.get(
"https://api.reachcell.com/v1/calls",
headers={"Authorization": "Bearer ak_your_api_key"},
params={"direction": "outbound", "status": "missed"},
)
calls = r.json()["data"]
for c in calls:
print(c["to"], c["status"], c["ended_at"])<?php
$ch = curl_init(
'https://api.reachcell.com/v1/calls?direction=outbound&status=missed'
);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ak_your_api_key'],
]);
$body = json_decode(curl_exec($ch), true);
curl_close($ch);
foreach ($body['data'] as $call) {
echo $call['to'] . ' — ' . $call['status'] . "\n";
}const params = new URLSearchParams({ direction: 'outbound', status: 'missed' });
const res = await fetch(
`https://api.reachcell.com/v1/calls?${params}`,
{ headers: { Authorization: 'Bearer ak_your_api_key' } },
);
const { data, meta } = await res.json();
console.log(`${meta.total} calls`);
data.forEach(c => console.log(c.to, c.status));