Launch offer Get 50% off every monthly plan for a limited time. View plans →

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

FieldTypeRequiredNotes
fromstringYesYour provisioned number in E.164 format.
tostringYesDestination 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.* webhooks
const 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: initiating

POST /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'];  // ended
const 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);  // ended

POST /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'];  // answering
const 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);  // answering

GET /v1/calls/{call_id}

Retrieve call details and current status.

Response fields

FieldDescription
call_idUUID of the call session.
fromOriginating number (E.164).
toDestination number (E.164).
directionoutbound or inbound.
statusinitiating, ringing, connected, ended, missed, rejected, or failed.
initiated_atWhen the call was initiated.
ringing_atWhen the device began ringing, or null.
connected_atWhen the call was answered, or null.
ended_atWhen the call ended/missed/rejected, or null.
duration_secondsConnected duration in seconds, or null if never answered.
cost_usdPer-call charge in USD, or null if within plan allowance.
created_atTimestamp 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 answered
const 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

ParameterDescription
numberFilter by E.164 number (matches from or to).
directioninbound or outbound.
statusOne of: initiating, ringing, connected, ended, missed, rejected, failed.
from_dateStart date (YYYY-MM-DD, inclusive).
to_dateEnd date (YYYY-MM-DD, inclusive).
pagePage number, default 1.
per_pageResults 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));
© 2026 ReachCell · Terms · Privacy · AUP · API v1 · support@reachcell.com