Numere de telefon
10 endpoint-uri. Fiecare cale de mai jos este relativă la URL-ul de bază al API-ului și include deja prefixul /api/v1 — vezi convențiile pentru autentificare, paginare, erori și idempotență.
| Endpoint | ||
|---|---|---|
| GET | /telephony/phone-numbers | List the tenant's phone numbers, filterable by provider, status, country or number substring, paginated |
| POST | /telephony/phone-numbers | Register a number the tenant already controls (BYO/SIP) without any carrier purchase, returning the new row |
| GET | /telephony/phone-numbers/{id} | Fetch one phone number row with its routing, hook, recording and capability configuration |
| PATCH | /telephony/phone-numbers/{id} | Update a number's routing destination, hooks, caller id, recording and status, returning the refreshed row |
| DELETE | /telephony/phone-numbers/{id} | Soft-delete the phone number row; releasing it at the carrier is a separate explicit action |
| POST | /telephony/phone-numbers/{id}/configure | Push CallAgent's webhook URLs for this number to the carrier and report whether the config is now in sync |
| POST | /telephony/phone-numbers/{id}/release | Release the number at the carrier first, then mark the row released and disable inbound and outbound |
| POST | /telephony/phone-numbers/import | Import every number a carrier account already owns, updating existing rows and marking vanished ones released |
| POST | /telephony/phone-numbers/purchase | Buy a number at the carrier, persist it only after the carrier confirms, then push webhook config best-effort |
| POST | /telephony/phone-numbers/search | Search a carrier's inventory for available numbers by country, type, area code or pattern before buying |
Endpoint-uri
List the tenant's phone numbers, filterable by provider, status, country or number substring, paginated
- Handler-ul nu impune niciun scope — orice cheie validă îl poate apela.
Parametri de interogare
| Nume | Tip | Obligatoriu | Note |
|---|---|---|---|
provider | string | — | |
status | string | — | |
country | string | — | |
number | string | — |
curl -X GET "$CALLAGENT_API_URL/telephony/phone-numbers?provider=string&status=string" \
-H "Authorization: Bearer $CALLAGENT_API_KEY" \
-H "Accept: application/json"const response = await fetch(`${process.env.CALLAGENT_API_URL}/telephony/phone-numbers?provider=string&status=string`, {
method: 'GET',
headers: {
Authorization: `Bearer ${process.env.CALLAGENT_API_KEY}`,
Accept: 'application/json',
},
});
if (!response.ok) {
const { error } = await response.json();
throw new Error(`${error.type}: ${error.message}`);
}
const { data } = await response.json();<?php
$handle = curl_init(getenv('CALLAGENT_API_URL') . '/telephony/phone-numbers?provider=string&status=string');
curl_setopt_array($handle, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('CALLAGENT_API_KEY'),
'Accept: application/json',
],
]);
$body = json_decode(curl_exec($handle), true);
$status = curl_getinfo($handle, CURLINFO_HTTP_CODE);
curl_close($handle);
if ($status >= 400) {
throw new RuntimeException("{$body['error']['type']}: {$body['error']['message']}");
}
$data = $body['data'];import os, requests
response = requests.get(
f"{os.environ['CALLAGENT_API_URL']}/telephony/phone-numbers?provider=string&status=string",
headers={"Authorization": f"Bearer {os.environ['CALLAGENT_API_KEY']}"},
timeout=30,
)
response.raise_for_status()
data = response.json()["data"]Răspunsuri
| Status | Corp |
|---|---|
200 | data-wrapped array |
Exemplu de răspuns, generat din schemă:
{
"data": [
"string"
],
"meta": {
"page": 1,
"limit": 25,
"total": 1,
"pages": 1
}
}Register a number the tenant already controls (BYO/SIP) without any carrier purchase, returning the new row
- Handler-ul nu impune niciun scope — orice cheie validă îl poate apela.
- Request body keys are camelCase (e.g. friendlyName, sipTrunkId, assistantId), not the snake_case the rest of the wire format uses
Corpul cererii
| Câmp | Tip | Obligatoriu | Note |
|---|---|---|---|
number | string | da | max 32 chars |
friendlyName | string | null | — | max 255 chars |
sipTrunkId | string | null | — | |
assistantId | string | null | — | |
squadId | string | null | — | |
capabilities | voice · sms · mms · fax[] | null | — |
curl -X POST "$CALLAGENT_API_URL/telephony/phone-numbers" \
-H "Authorization: Bearer $CALLAGENT_API_KEY" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{
"number": "+40712345678",
"friendlyName": "Support Line",
"capabilities": [
"voice"
]
}'const response = await fetch(`${process.env.CALLAGENT_API_URL}/telephony/phone-numbers`, {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.CALLAGENT_API_KEY}`,
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
"number": "+40712345678",
"friendlyName": "Support Line",
"capabilities": [
"voice"
]
}),
});
if (!response.ok) {
const { error } = await response.json();
throw new Error(`${error.type}: ${error.message}`);
}
const { data } = await response.json();<?php
$handle = curl_init(getenv('CALLAGENT_API_URL') . '/telephony/phone-numbers');
curl_setopt_array($handle, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('CALLAGENT_API_KEY'),
'Accept: application/json',
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode([
'number' => '+40712345678',
'friendlyName' => 'Support Line',
'capabilities' => [
'voice',
],
]),
]);
$body = json_decode(curl_exec($handle), true);
$status = curl_getinfo($handle, CURLINFO_HTTP_CODE);
curl_close($handle);
if ($status >= 400) {
throw new RuntimeException("{$body['error']['type']}: {$body['error']['message']}");
}
$data = $body['data'];import os, requests
response = requests.post(
f"{os.environ['CALLAGENT_API_URL']}/telephony/phone-numbers",
headers={"Authorization": f"Bearer {os.environ['CALLAGENT_API_KEY']}"},
json={
"number": "+40712345678",
"friendlyName": "Support Line",
"capabilities": [
"voice"
]
},
timeout=30,
)
response.raise_for_status()
data = response.json()["data"]Răspunsuri
| Status | Corp |
|---|---|
200 | JSON object |
201 | data-wrapped PhoneNumber |
Erori
| Status | Când apare |
|---|---|
409 | A non-released row for this E.164 number already exists in the organization |
422 | Validation failed, or the number is not valid E.164 |
Exemplu de răspuns, generat din schemă:
"string"Fetch one phone number row with its routing, hook, recording and capability configuration
- Handler-ul nu impune niciun scope — orice cheie validă îl poate apela.
Parametri de cale
| Nume | Tip | Obligatoriu | Note |
|---|---|---|---|
id | string | da |
curl -X GET "$CALLAGENT_API_URL/telephony/phone-numbers/01JQ0000000000000000000000" \
-H "Authorization: Bearer $CALLAGENT_API_KEY" \
-H "Accept: application/json"const response = await fetch(`${process.env.CALLAGENT_API_URL}/telephony/phone-numbers/01JQ0000000000000000000000`, {
method: 'GET',
headers: {
Authorization: `Bearer ${process.env.CALLAGENT_API_KEY}`,
Accept: 'application/json',
},
});
if (!response.ok) {
const { error } = await response.json();
throw new Error(`${error.type}: ${error.message}`);
}
const { data } = await response.json();<?php
$handle = curl_init(getenv('CALLAGENT_API_URL') . '/telephony/phone-numbers/01JQ0000000000000000000000');
curl_setopt_array($handle, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('CALLAGENT_API_KEY'),
'Accept: application/json',
],
]);
$body = json_decode(curl_exec($handle), true);
$status = curl_getinfo($handle, CURLINFO_HTTP_CODE);
curl_close($handle);
if ($status >= 400) {
throw new RuntimeException("{$body['error']['type']}: {$body['error']['message']}");
}
$data = $body['data'];import os, requests
response = requests.get(
f"{os.environ['CALLAGENT_API_URL']}/telephony/phone-numbers/01JQ0000000000000000000000",
headers={"Authorization": f"Bearer {os.environ['CALLAGENT_API_KEY']}"},
timeout=30,
)
response.raise_for_status()
data = response.json()["data"]Răspunsuri
| Status | Corp |
|---|---|
200 | data-wrapped PhoneNumber |
Erori
| Status | Când apare |
|---|---|
404 | No such number for this tenant |
Exemplu de răspuns, generat din schemă:
{
"data": {
"id": "01JQ0000000000000000000000",
"organization_id": "01JQ0000000000000000000000",
"number": "+40712345678",
"friendly_name": "Support Line",
"provider": "twilio",
"telephony_account_id": "01JQ0000000000000000000000",
"provider_credential_id": "01JQ0000000000000000000000",
"provider_number_sid": "string",
"provider_account_sid": "string",
"provider_metadata": {},
"capabilities": {},
"country": "string",
"region": "string",
"locality": "string",
"number_type": "string",
"address_requirement": "string",
"destination_type": "assistant",
"destination_id": "01JQ0000000000000000000000",
"destination_value": "string",
"fallback_destination_id": "01JQ0000000000000000000000",
"fallback_destination_type": "assistant",
"assistant_id": "01JQ0000000000000000000000",
"squad_id": "01JQ0000000000000000000000",
"hook_enabled": true,
"hook_url": "https://example.com/hook",
"hook_timeout_ms": 30,
"hook_headers": {},
"hook_fallback": "string",
"hook_last_success_at": "2026-01-01T12:00:00+00:00",
"hook_last_failure_at": "2026-01-01T12:00:00+00:00",
"hook_last_error": "string",
"outbound_enabled": true,
"outbound_caller_id_number": "+40712345678",
"outbound_caller_id_name": "Support Line",
"sip_trunk_id": "01JQ0000000000000000000000",
"caller_id_policy_id": "01JQ0000000000000000000000",
"sms_enabled": true,
"sms_assistant_id": "01JQ0000000000000000000000",
"sms_webhook_url": "https://example.com/hook",
"messaging_service_sid": "string",
"recording_mode": "disabled",
"recording_consent_required": true,
"voice_webhook_url": "https://example.com/hook",
"status_webhook_url": "https://example.com/hook",
"webhooks_configured_at": "2026-01-01T12:00:00+00:00",
"webhooks_in_sync": true,
"max_concurrent_calls": 1,
"status": "pending",
"inbound_enabled": true,
"imported_at": "2026-01-01T12:00:00+00:00",
"purchased_at": "2026-01-01T12:00:00+00:00",
"released_at": "2026-01-01T12:00:00+00:00",
"last_inbound_at": "2026-01-01T12:00:00+00:00",
"last_outbound_at": "2026-01-01T12:00:00+00:00",
"monthly_cost": "string",
"setup_cost": "string",
"currency": "string",
"notes": "string",
"settings": {},
"metadata": {},
"created_at": "2026-01-01T12:00:00+00:00",
"updated_at": "2026-01-01T12:00:00+00:00",
"deleted_at": "2026-01-01T12:00:00+00:00",
"phone_number_hook_id": "01JQ0000000000000000000000"
}
}Update a number's routing destination, hooks, caller id, recording and status, returning the refreshed row
- Handler-ul nu impune niciun scope — orice cheie validă îl poate apela.
- camelCase body keys (friendlyName, hookUrl, ...); hookSecret is encrypted on write and never readable back
Parametri de cale
| Nume | Tip | Obligatoriu | Note |
|---|---|---|---|
id | string | da |
Corpul cererii
| Câmp | Tip | Obligatoriu | Note |
|---|---|---|---|
friendlyName | string | null | — | max 255 chars |
destinationType | assistant · squad · queue · ivr · ring_group · extension … | null | — | |
destinationId | string | null | — | max 32 chars |
destinationValue | string | null | — | max 255 chars |
assistantId | string | null | — | max 32 chars |
squadId | string | null | — | max 32 chars |
sipTrunkId | string | null | — | |
callerIdPolicyId | string | null | — | |
phoneNumberHookId | string | null | — | |
hookEnabled | boolean | null | — | |
hookUrl | string | null | — | uri. max 1024 chars |
hookSecret | string | null | — | max 255 chars |
hookTimeoutMs | integer | null | — | min 200. max 3000 |
hookFallback | static · reject · voicemail · null | null | — | |
inboundEnabled | boolean | null | — | |
outboundEnabled | boolean | null | — | |
outboundCallerIdNumber | string | null | — | max 32 chars |
outboundCallerIdName | string | null | — | max 255 chars |
smsEnabled | boolean | null | — | |
smsAssistantId | string | null | — | max 32 chars |
recordingMode | disabled · mono · dual_channel · inherit | null | — | |
recordingConsentRequired | boolean | null | — | |
maxConcurrentCalls | integer | null | — | min 1 |
status | pending · active · suspended · released · error | null | — | |
metadata | string[] | null | — |
curl -X PATCH "$CALLAGENT_API_URL/telephony/phone-numbers/01JQ0000000000000000000000" \
-H "Authorization: Bearer $CALLAGENT_API_KEY" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{
"friendlyName": "Support Line",
"destinationType": "assistant",
"phoneNumberHookId": "+40712345678",
"hookEnabled": true,
"hookUrl": "https://example.com/hook",
"hookTimeoutMs": 30,
"hookFallback": "static"
}'const response = await fetch(`${process.env.CALLAGENT_API_URL}/telephony/phone-numbers/01JQ0000000000000000000000`, {
method: 'PATCH',
headers: {
Authorization: `Bearer ${process.env.CALLAGENT_API_KEY}`,
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
"friendlyName": "Support Line",
"destinationType": "assistant",
"phoneNumberHookId": "+40712345678",
"hookEnabled": true,
"hookUrl": "https://example.com/hook",
"hookTimeoutMs": 30,
"hookFallback": "static"
}),
});
if (!response.ok) {
const { error } = await response.json();
throw new Error(`${error.type}: ${error.message}`);
}
const { data } = await response.json();<?php
$handle = curl_init(getenv('CALLAGENT_API_URL') . '/telephony/phone-numbers/01JQ0000000000000000000000');
curl_setopt_array($handle, [
CURLOPT_CUSTOMREQUEST => 'PATCH',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('CALLAGENT_API_KEY'),
'Accept: application/json',
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode([
'friendlyName' => 'Support Line',
'destinationType' => 'assistant',
'phoneNumberHookId' => '+40712345678',
'hookEnabled' => true,
'hookUrl' => 'https://example.com/hook',
'hookTimeoutMs' => 30,
'hookFallback' => 'static',
]),
]);
$body = json_decode(curl_exec($handle), true);
$status = curl_getinfo($handle, CURLINFO_HTTP_CODE);
curl_close($handle);
if ($status >= 400) {
throw new RuntimeException("{$body['error']['type']}: {$body['error']['message']}");
}
$data = $body['data'];import os, requests
response = requests.patch(
f"{os.environ['CALLAGENT_API_URL']}/telephony/phone-numbers/01JQ0000000000000000000000",
headers={"Authorization": f"Bearer {os.environ['CALLAGENT_API_KEY']}"},
json={
"friendlyName": "Support Line",
"destinationType": "assistant",
"phoneNumberHookId": "+40712345678",
"hookEnabled": True,
"hookUrl": "https://example.com/hook",
"hookTimeoutMs": 30,
"hookFallback": "static"
},
timeout=30,
)
response.raise_for_status()
data = response.json()["data"]Răspunsuri
| Status | Corp |
|---|---|
200 | data-wrapped object |
Erori
| Status | Când apare |
|---|---|
404 | No such number for this tenant |
422 | Validation failed, or a referenced trunk/policy/hook id does not exist |
Exemplu de răspuns, generat din schemă:
{
"data": {
"id": "01JQ0000000000000000000000",
"organization_id": "01JQ0000000000000000000000",
"number": "+40712345678",
"friendly_name": "Support Line",
"provider": "twilio",
"telephony_account_id": "01JQ0000000000000000000000",
"provider_credential_id": "01JQ0000000000000000000000",
"provider_number_sid": "string",
"provider_account_sid": "string",
"provider_metadata": {},
"capabilities": {},
"country": "string",
"region": "string",
"locality": "string",
"number_type": "string",
"address_requirement": "string",
"destination_type": "assistant",
"destination_id": "01JQ0000000000000000000000",
"destination_value": "string",
"fallback_destination_id": "01JQ0000000000000000000000",
"fallback_destination_type": "assistant",
"assistant_id": "01JQ0000000000000000000000",
"squad_id": "01JQ0000000000000000000000",
"hook_enabled": true,
"hook_url": "https://example.com/hook",
"hook_timeout_ms": 30,
"hook_headers": {},
"hook_fallback": "string",
"hook_last_success_at": "2026-01-01T12:00:00+00:00",
"hook_last_failure_at": "2026-01-01T12:00:00+00:00",
"hook_last_error": "string",
"outbound_enabled": true,
"outbound_caller_id_number": "+40712345678",
"outbound_caller_id_name": "Support Line",
"sip_trunk_id": "01JQ0000000000000000000000",
"caller_id_policy_id": "01JQ0000000000000000000000",
"sms_enabled": true,
"sms_assistant_id": "01JQ0000000000000000000000",
"sms_webhook_url": "https://example.com/hook",
"messaging_service_sid": "string",
"recording_mode": "disabled",
"recording_consent_required": true,
"voice_webhook_url": "https://example.com/hook",
"status_webhook_url": "https://example.com/hook",
"webhooks_configured_at": "2026-01-01T12:00:00+00:00",
"webhooks_in_sync": true,
"max_concurrent_calls": 1,
"status": "pending",
"inbound_enabled": true,
"imported_at": "2026-01-01T12:00:00+00:00",
"purchased_at": "2026-01-01T12:00:00+00:00",
"released_at": "2026-01-01T12:00:00+00:00",
"last_inbound_at": "2026-01-01T12:00:00+00:00",
"last_outbound_at": "2026-01-01T12:00:00+00:00",
"monthly_cost": "string",
"setup_cost": "string",
"currency": "string",
"notes": "string",
"settings": {},
"metadata": {},
"created_at": "2026-01-01T12:00:00+00:00",
"updated_at": "2026-01-01T12:00:00+00:00",
"deleted_at": "2026-01-01T12:00:00+00:00",
"phone_number_hook_id": "01JQ0000000000000000000000"
}
}Soft-delete the phone number row; releasing it at the carrier is a separate explicit action
- Handler-ul nu impune niciun scope — orice cheie validă îl poate apela.
- Acest răspuns nu este împachetat în
data.
Parametri de cale
| Nume | Tip | Obligatoriu | Note |
|---|---|---|---|
id | string | da |
curl -X DELETE "$CALLAGENT_API_URL/telephony/phone-numbers/01JQ0000000000000000000000" \
-H "Authorization: Bearer $CALLAGENT_API_KEY" \
-H "Accept: application/json"const response = await fetch(`${process.env.CALLAGENT_API_URL}/telephony/phone-numbers/01JQ0000000000000000000000`, {
method: 'DELETE',
headers: {
Authorization: `Bearer ${process.env.CALLAGENT_API_KEY}`,
Accept: 'application/json',
},
});
if (!response.ok) {
const { error } = await response.json();
throw new Error(`${error.type}: ${error.message}`);
}
const { data } = await response.json();<?php
$handle = curl_init(getenv('CALLAGENT_API_URL') . '/telephony/phone-numbers/01JQ0000000000000000000000');
curl_setopt_array($handle, [
CURLOPT_CUSTOMREQUEST => 'DELETE',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('CALLAGENT_API_KEY'),
'Accept: application/json',
],
]);
$body = json_decode(curl_exec($handle), true);
$status = curl_getinfo($handle, CURLINFO_HTTP_CODE);
curl_close($handle);
if ($status >= 400) {
throw new RuntimeException("{$body['error']['type']}: {$body['error']['message']}");
}
$data = $body['data'];import os, requests
response = requests.delete(
f"{os.environ['CALLAGENT_API_URL']}/telephony/phone-numbers/01JQ0000000000000000000000",
headers={"Authorization": f"Bearer {os.environ['CALLAGENT_API_KEY']}"},
timeout=30,
)
response.raise_for_status()
data = response.json()["data"]Răspunsuri
| Status | Corp |
|---|---|
204 | No content |
Erori
| Status | Când apare |
|---|---|
404 | No such number for this tenant |
Push CallAgent's webhook URLs for this number to the carrier and report whether the config is now in sync
- Handler-ul nu impune niciun scope — orice cheie validă îl poate apela.
- On failure it still returns a {"data": {configured: false}} body with status 502, not the usual error envelope
Parametri de cale
| Nume | Tip | Obligatoriu | Note |
|---|---|---|---|
id | string | da |
curl -X POST "$CALLAGENT_API_URL/telephony/phone-numbers/01JQ0000000000000000000000/configure" \
-H "Authorization: Bearer $CALLAGENT_API_KEY" \
-H "Accept: application/json"const response = await fetch(`${process.env.CALLAGENT_API_URL}/telephony/phone-numbers/01JQ0000000000000000000000/configure`, {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.CALLAGENT_API_KEY}`,
Accept: 'application/json',
},
});
if (!response.ok) {
const { error } = await response.json();
throw new Error(`${error.type}: ${error.message}`);
}
const { data } = await response.json();<?php
$handle = curl_init(getenv('CALLAGENT_API_URL') . '/telephony/phone-numbers/01JQ0000000000000000000000/configure');
curl_setopt_array($handle, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('CALLAGENT_API_KEY'),
'Accept: application/json',
],
]);
$body = json_decode(curl_exec($handle), true);
$status = curl_getinfo($handle, CURLINFO_HTTP_CODE);
curl_close($handle);
if ($status >= 400) {
throw new RuntimeException("{$body['error']['type']}: {$body['error']['message']}");
}
$data = $body['data'];import os, requests
response = requests.post(
f"{os.environ['CALLAGENT_API_URL']}/telephony/phone-numbers/01JQ0000000000000000000000/configure",
headers={"Authorization": f"Bearer {os.environ['CALLAGENT_API_KEY']}"},
timeout=30,
)
response.raise_for_status()
data = response.json()["data"]Răspunsuri
| Status | Corp |
|---|---|
200 | JSON object |
Erori
| Status | Când apare |
|---|---|
404 | No such number for this tenant |
502 | Carrier configuration failed |
Exemplu de răspuns, generat din schemă:
"string"Release the number at the carrier first, then mark the row released and disable inbound and outbound
- Handler-ul nu impune niciun scope — orice cheie validă îl poate apela.
Parametri de cale
| Nume | Tip | Obligatoriu | Note |
|---|---|---|---|
id | string | da |
curl -X POST "$CALLAGENT_API_URL/telephony/phone-numbers/01JQ0000000000000000000000/release" \
-H "Authorization: Bearer $CALLAGENT_API_KEY" \
-H "Accept: application/json"const response = await fetch(`${process.env.CALLAGENT_API_URL}/telephony/phone-numbers/01JQ0000000000000000000000/release`, {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.CALLAGENT_API_KEY}`,
Accept: 'application/json',
},
});
if (!response.ok) {
const { error } = await response.json();
throw new Error(`${error.type}: ${error.message}`);
}
const { data } = await response.json();<?php
$handle = curl_init(getenv('CALLAGENT_API_URL') . '/telephony/phone-numbers/01JQ0000000000000000000000/release');
curl_setopt_array($handle, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('CALLAGENT_API_KEY'),
'Accept: application/json',
],
]);
$body = json_decode(curl_exec($handle), true);
$status = curl_getinfo($handle, CURLINFO_HTTP_CODE);
curl_close($handle);
if ($status >= 400) {
throw new RuntimeException("{$body['error']['type']}: {$body['error']['message']}");
}
$data = $body['data'];import os, requests
response = requests.post(
f"{os.environ['CALLAGENT_API_URL']}/telephony/phone-numbers/01JQ0000000000000000000000/release",
headers={"Authorization": f"Bearer {os.environ['CALLAGENT_API_KEY']}"},
timeout=30,
)
response.raise_for_status()
data = response.json()["data"]Răspunsuri
| Status | Corp |
|---|---|
200 | JSON object |
Erori
| Status | Când apare |
|---|---|
404 | No such number for this tenant |
422 | No active credential, unknown provider, or the row has no carrier id |
501 | The provider has no adapter or no release API |
502 | The carrier rejected the release |
504 | The carrier could not be reached |
Exemplu de răspuns, generat din schemă:
{
"data": {
"id": "01JQ0000000000000000000000",
"organization_id": "01JQ0000000000000000000000",
"number": "+40712345678",
"friendly_name": "Support Line",
"provider": "twilio",
"telephony_account_id": "01JQ0000000000000000000000",
"provider_credential_id": "01JQ0000000000000000000000",
"provider_number_sid": "string",
"provider_account_sid": "string",
"provider_metadata": {},
"capabilities": {},
"country": "string",
"region": "string",
"locality": "string",
"number_type": "string",
"address_requirement": "string",
"destination_type": "assistant",
"destination_id": "01JQ0000000000000000000000",
"destination_value": "string",
"fallback_destination_id": "01JQ0000000000000000000000",
"fallback_destination_type": "assistant",
"assistant_id": "01JQ0000000000000000000000",
"squad_id": "01JQ0000000000000000000000",
"hook_enabled": true,
"hook_url": "https://example.com/hook",
"hook_timeout_ms": 30,
"hook_headers": {},
"hook_fallback": "string",
"hook_last_success_at": "2026-01-01T12:00:00+00:00",
"hook_last_failure_at": "2026-01-01T12:00:00+00:00",
"hook_last_error": "string",
"outbound_enabled": true,
"outbound_caller_id_number": "+40712345678",
"outbound_caller_id_name": "Support Line",
"sip_trunk_id": "01JQ0000000000000000000000",
"caller_id_policy_id": "01JQ0000000000000000000000",
"sms_enabled": true,
"sms_assistant_id": "01JQ0000000000000000000000",
"sms_webhook_url": "https://example.com/hook",
"messaging_service_sid": "string",
"recording_mode": "disabled",
"recording_consent_required": true,
"voice_webhook_url": "https://example.com/hook",
"status_webhook_url": "https://example.com/hook",
"webhooks_configured_at": "2026-01-01T12:00:00+00:00",
"webhooks_in_sync": true,
"max_concurrent_calls": 1,
"status": "pending",
"inbound_enabled": true,
"imported_at": "2026-01-01T12:00:00+00:00",
"purchased_at": "2026-01-01T12:00:00+00:00",
"released_at": "2026-01-01T12:00:00+00:00",
"last_inbound_at": "2026-01-01T12:00:00+00:00",
"last_outbound_at": "2026-01-01T12:00:00+00:00",
"monthly_cost": "string",
"setup_cost": "string",
"currency": "string",
"notes": "string",
"settings": {},
"metadata": {},
"created_at": "2026-01-01T12:00:00+00:00",
"updated_at": "2026-01-01T12:00:00+00:00",
"deleted_at": "2026-01-01T12:00:00+00:00",
"phone_number_hook_id": "01JQ0000000000000000000000"
}
}Import every number a carrier account already owns, updating existing rows and marking vanished ones released
- Handler-ul nu impune niciun scope — orice cheie validă îl poate apela.
- Request body keys are camelCase (e.g. telephonyAccountId), not the snake_case the rest of the wire format uses
Corpul cererii
| Câmp | Tip | Obligatoriu | Note |
|---|---|---|---|
provider | twilio · telnyx · didww · plivo · zadarma · didlogic … | da | §8.1. The telephony providers CallAgent can terminate or originate through. The value is what is stored in phone_numbers.provider, sip_trunks.provider and provider_credentials.provider — keep them stable, they are persisted. |
telephonyAccountId | string | null | — |
curl -X POST "$CALLAGENT_API_URL/telephony/phone-numbers/import" \
-H "Authorization: Bearer $CALLAGENT_API_KEY" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{
"provider": "twilio"
}'const response = await fetch(`${process.env.CALLAGENT_API_URL}/telephony/phone-numbers/import`, {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.CALLAGENT_API_KEY}`,
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
"provider": "twilio"
}),
});
if (!response.ok) {
const { error } = await response.json();
throw new Error(`${error.type}: ${error.message}`);
}
const { data } = await response.json();<?php
$handle = curl_init(getenv('CALLAGENT_API_URL') . '/telephony/phone-numbers/import');
curl_setopt_array($handle, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('CALLAGENT_API_KEY'),
'Accept: application/json',
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode([
'provider' => 'twilio',
]),
]);
$body = json_decode(curl_exec($handle), true);
$status = curl_getinfo($handle, CURLINFO_HTTP_CODE);
curl_close($handle);
if ($status >= 400) {
throw new RuntimeException("{$body['error']['type']}: {$body['error']['message']}");
}
$data = $body['data'];import os, requests
response = requests.post(
f"{os.environ['CALLAGENT_API_URL']}/telephony/phone-numbers/import",
headers={"Authorization": f"Bearer {os.environ['CALLAGENT_API_KEY']}"},
json={
"provider": "twilio"
},
timeout=30,
)
response.raise_for_status()
data = response.json()["data"]Răspunsuri
| Status | Corp |
|---|---|
200 | JSON object |
Erori
| Status | Când apare |
|---|---|
422 | Validation failed, unknown provider, or no active credential for the provider |
501 | The provider has no adapter or no inventory API wired up |
502 | The carrier rejected the inventory call |
504 | The carrier could not be reached |
Exemplu de răspuns, generat din schemă:
{
"data": {
"imported": 1,
"updated": 1,
"missing": 1,
"numbers": [
"string"
]
}
}Buy a number at the carrier, persist it only after the carrier confirms, then push webhook config best-effort
- Handler-ul nu impune niciun scope — orice cheie validă îl poate apela.
- Request body keys are camelCase (e.g. telephonyAccountId, friendlyName), not the snake_case the rest of the wire format uses
Corpul cererii
| Câmp | Tip | Obligatoriu | Note |
|---|---|---|---|
provider | twilio · telnyx · didww · plivo · zadarma · didlogic … | da | §8.1. The telephony providers CallAgent can terminate or originate through. The value is what is stored in phone_numbers.provider, sip_trunks.provider and provider_credentials.provider — keep them stable, they are persisted. |
number | string | da | max 32 chars |
telephonyAccountId | string | null | — | |
friendlyName | string | null | — | max 255 chars |
curl -X POST "$CALLAGENT_API_URL/telephony/phone-numbers/purchase" \
-H "Authorization: Bearer $CALLAGENT_API_KEY" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{
"provider": "twilio",
"number": "+40712345678",
"friendlyName": "Support Line"
}'const response = await fetch(`${process.env.CALLAGENT_API_URL}/telephony/phone-numbers/purchase`, {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.CALLAGENT_API_KEY}`,
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
"provider": "twilio",
"number": "+40712345678",
"friendlyName": "Support Line"
}),
});
if (!response.ok) {
const { error } = await response.json();
throw new Error(`${error.type}: ${error.message}`);
}
const { data } = await response.json();<?php
$handle = curl_init(getenv('CALLAGENT_API_URL') . '/telephony/phone-numbers/purchase');
curl_setopt_array($handle, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('CALLAGENT_API_KEY'),
'Accept: application/json',
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode([
'provider' => 'twilio',
'number' => '+40712345678',
'friendlyName' => 'Support Line',
]),
]);
$body = json_decode(curl_exec($handle), true);
$status = curl_getinfo($handle, CURLINFO_HTTP_CODE);
curl_close($handle);
if ($status >= 400) {
throw new RuntimeException("{$body['error']['type']}: {$body['error']['message']}");
}
$data = $body['data'];import os, requests
response = requests.post(
f"{os.environ['CALLAGENT_API_URL']}/telephony/phone-numbers/purchase",
headers={"Authorization": f"Bearer {os.environ['CALLAGENT_API_KEY']}"},
json={
"provider": "twilio",
"number": "+40712345678",
"friendlyName": "Support Line"
},
timeout=30,
)
response.raise_for_status()
data = response.json()["data"]Răspunsuri
| Status | Corp |
|---|---|
200 | JSON object |
201 | data-wrapped PhoneNumber |
Erori
| Status | Când apare |
|---|---|
422 | Validation failed, unknown provider, or no active credential for the provider |
501 | The provider has no adapter or no programmatic purchase API |
502 | The carrier rejected the purchase |
504 | The carrier could not be reached |
Exemplu de răspuns, generat din schemă:
"string"Search a carrier's inventory for available numbers by country, type, area code or pattern before buying
- Handler-ul nu impune niciun scope — orice cheie validă îl poate apela.
- Request body keys are camelCase (e.g. areaCode), not the snake_case the rest of the wire format uses
Corpul cererii
| Câmp | Tip | Obligatoriu | Note |
|---|---|---|---|
provider | twilio · telnyx · didww · plivo · zadarma · didlogic … | da | §8.1. The telephony providers CallAgent can terminate or originate through. The value is what is stored in phone_numbers.provider, sip_trunks.provider and provider_credentials.provider — keep them stable, they are persisted. |
country | string | da | max 2 chars. min 2 chars |
type | local · mobile · toll_free · national · null | null | — | |
areaCode | string | null | — | max 8 chars |
contains | string | null | — | max 32 chars |
region | string | null | — | max 64 chars |
locality | string | null | — | max 64 chars |
capabilities | string[] | null | — | |
limit | integer | null | — | min 1. max 100 |
curl -X POST "$CALLAGENT_API_URL/telephony/phone-numbers/search" \
-H "Authorization: Bearer $CALLAGENT_API_KEY" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{
"provider": "twilio",
"country": "string",
"type": "local",
"limit": 25
}'const response = await fetch(`${process.env.CALLAGENT_API_URL}/telephony/phone-numbers/search`, {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.CALLAGENT_API_KEY}`,
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
"provider": "twilio",
"country": "string",
"type": "local",
"limit": 25
}),
});
if (!response.ok) {
const { error } = await response.json();
throw new Error(`${error.type}: ${error.message}`);
}
const { data } = await response.json();<?php
$handle = curl_init(getenv('CALLAGENT_API_URL') . '/telephony/phone-numbers/search');
curl_setopt_array($handle, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('CALLAGENT_API_KEY'),
'Accept: application/json',
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode([
'provider' => 'twilio',
'country' => 'string',
'type' => 'local',
'limit' => 25,
]),
]);
$body = json_decode(curl_exec($handle), true);
$status = curl_getinfo($handle, CURLINFO_HTTP_CODE);
curl_close($handle);
if ($status >= 400) {
throw new RuntimeException("{$body['error']['type']}: {$body['error']['message']}");
}
$data = $body['data'];import os, requests
response = requests.post(
f"{os.environ['CALLAGENT_API_URL']}/telephony/phone-numbers/search",
headers={"Authorization": f"Bearer {os.environ['CALLAGENT_API_KEY']}"},
json={
"provider": "twilio",
"country": "string",
"type": "local",
"limit": 25
},
timeout=30,
)
response.raise_for_status()
data = response.json()["data"]Răspunsuri
| Status | Corp |
|---|---|
200 | JSON object |
Erori
| Status | Când apare |
|---|---|
422 | Validation failed, unknown provider, or no active credential for the provider |
501 | The provider has no adapter or no number-search API |
502 | The carrier rejected the search |
504 | The carrier could not be reached |
Exemplu de răspuns, generat din schemă:
{
"data": {}
}