Apeluri
Istoricul apelurilor primite și date: cine, cu cine, cât, și ce s-a întâmplat.
Un „apel” aici e o convorbire cu cineva din afară: un pacient care a sunat la cabinet, o comandă confirmată prin telefon, un apel pierdut la ora prânzului. Apelurile interne, dintre două interioare, nu apar. Fiecare apel are un id care nu se schimbă, aceleași câmpuri oriunde l-ai vedea, și rămâne în istoric cât ține retenția contului tău.
Lista apelurilor
Apelurile, cele mai noi întâi, pe pagini. Fără niciun parametru primești ultimele 30 de zile, câte 50 pe pagină.
| Parametru | Tip | Ce face |
|---|---|---|
from | moment | De la acest moment, inclusiv. ISO 8601 (2026-10-01T00:00:00+03:00) sau secunde Unix. Fără el, ultimele 30 de zile. |
to | moment | Până la acest moment. |
direction | inbound · outbound | Doar primite, sau doar date. |
result | answered · missed · busy · no_answer · cancelled · failed | Doar apelurile cu acest rezultat. missed e o scurtătură: primite la care nu a vorbit nimeni, oricare ar fi cauza. |
number | cifre | Numărul celui din afară, sau o parte din el. Scrii cifrele cum le ai; +, spațiile și punctele se ignoră. |
line | cifre | Numărul tău pe care a intrat sau de pe care a ieșit apelul. Util când ai mai multe numere și vrei doar unul. |
agent | interior | Interiorul colegului care a vorbit: a răspuns, la un apel primit, sau a format, la unul dat. |
limit | 1–200 | Câte apeluri pe pagină. Implicit 50. |
cursor | string | next_cursor din pagina anterioară, trimis neschimbat. |
Un parametru scris greșit nu e ignorat: primești 400 cu invalid_parameter și explicația. Așa, un filtru greșit nu îți umple sistemul cu apeluri pe care nu le-ai cerut.
Exemplu
Apelurile primite și nepreluate din 17 octombrie:
curl "https://api.criox.ro/v1/calls?direction=inbound&result=missed&from=2026-10-17T00:00:00%2B03:00&to=2026-10-18T00:00:00%2B03:00" \
-H "Authorization: Bearer cxk_…"
Răspunsul, cu un singur apel ca să încapă aici:
{
"data": [
{
"id": "c0ffee00-1b2c-4d3e-8f4a-5b6c7d8e9f01",
"direction": "inbound",
"started_at": "2026-10-17T08:12:41.000Z",
"ended_at": "2026-10-17T08:15:27.000Z",
"contact_number": "+40743755549",
"contact_number_national": "0743755549",
"contact_name": "Ion Popescu",
"line_number": "+40215708509",
"line_number_national": "0215708509",
"agent_extension": "101",
"agent_name": "Maria Ionescu",
"queue_number": null,
"queue_name": null,
"result": "answered",
"missed_reason": null,
"after_hours": false,
"wait_seconds": 12,
"talk_seconds": 154,
"duration_seconds": 166,
"recorded": true,
"crm_provider": "kommo",
"crm_contact_id": "991",
"crm_contact_url": "https://exemplu.kommo.com/contacts/detail/991",
"destination_type": "extension",
"destination_number": "101",
"destination_name": "Maria Ionescu",
"path": [
{ "type": "extension", "number": "101", "name": "Maria Ionescu", "key": null, "at": "2026-10-17T08:12:41.000Z", "seconds": 12, "result": "answered" }
]
}
],
"has_more": true,
"next_cursor": "MTc2MDY4Mjc2MS5jMGZmZWUwMC0xYjJjLTRkM2UtOGY0YS01YjZjN2Q4ZTlmMDE"
}
Paginarea
Cât timp has_more e true, ceri pagina următoare cu cursor=next_cursor, cu aceleași filtre. Cursorul ține minte unde ai rămas, deci un apel care intră în istoric între două pagini nu te face să sari peste altul. Când nu mai e nimic, has_more e false și next_cursor e null.
O pagină poate avea mai puține rânduri decât limit și totuși has_more: true: apelurile interne se scot după ce pagina a fost tăiată. Oprește-te după has_more, nu după numărul de rânduri.
// Node.js: toate apelurile din octombrie, pagină cu pagină
let cursor = null;
do {
const url = new URL("https://api.criox.ro/v1/calls");
url.searchParams.set("from", "2026-10-01T00:00:00+03:00");
if (cursor) url.searchParams.set("cursor", cursor);
const res = await fetch(url, { headers: { Authorization: `Bearer ${process.env.CRIOX_KEY}` } });
if (!res.ok) throw new Error(`CrioX a răspuns ${res.status}`);
const page = await res.json();
for (const call of page.data) await save(call);
cursor = page.has_more ? page.next_cursor : null;
} while (cursor);
Un apel
Un singur apel, după id. Cazul obișnuit: ai primit evenimentul call.completed, ai păstrat call_id, și vrei să-l recitești mai târziu, de exemplu după ce colegul a adăugat numele în agendă. Îl găsești cât timp îl ține retenția contului, nu doar 30 de zile.
curl https://api.criox.ro/v1/calls/c0ffee00-1b2c-4d3e-8f4a-5b6c7d8e9f01 \
-H "Authorization: Bearer cxk_…"
Răspunsul e obiectul „apel” de mai jos, fără înveliș. Un id care nu există în contul tău primește 404 cu call_not_found; un id care nu e UUID primește 400.
Obiectul „apel”
Aceleași chei, în aceeași ordine, pe orice apel; null acolo unde nu se aplică sau nu se știe. E același obiect ca în evenimente, unde id se numește call_id. Modelul e simetric: contact_* e mereu cel din afară, agent_* e mereu colegul tău, line_* e mereu numărul tău, oricare ar fi sensul apelului.
| Câmp | Tip | Ce înseamnă |
|---|---|---|
id | uuid | Id-ul apelului. Stabil; în evenimente e call_id. |
direction | inbound · outbound | inbound = primit, outbound = dat. |
started_at | moment | Când a început apelul: când a sunat telefonul, la un primit, sau când s-a format numărul, la un dat. UTC. |
ended_at | moment | Când s-a închis. UTC. |
contact_number | string · null | Numărul celui din afară, în forma internațională (+40…). null când a sunat cu numărul ascuns. |
contact_number_national | string · null | Același număr, în forma națională (07…). Pentru un număr străin, la fel ca cel de mai sus. |
contact_name | string · null | Numele lui, dacă îl știm: din CRM-ul legat sau din agenda CrioX. |
line_number | string · null | Numărul tău: cel pe care a intrat apelul (primit) sau cel afișat celuilalt (dat). Internațional. |
line_number_national | string · null | Același, național. |
agent_extension | string · null | Interiorul colegului care a răspuns (primit) sau a format (dat). null pe un apel la care nu a vorbit nimeni, și tot null când a răspuns asistentul AI sau mesageria vocală, nu un coleg. La un apel primit pe un grup, e cel care a ridicat, nu un membru oarecare. |
agent_name | string · null | Numele colegului, cum e în CrioX. |
queue_number | string · null | Coada de call-center prin care a trecut apelul, dacă a trecut printr-una. Grupurile de sonerie nu apar aici. |
queue_name | string · null | Numele cozii. |
result | string | Ce s-a întâmplat. Valorile, mai jos. |
missed_reason | string · null | De ce nu a vorbit nimeni. Doar pe un apel primit nepreluat; altfel null. Valorile, mai jos. |
after_hours | boolean · null | Apelul a intrat în afara programului numărului. null pe un apel dat, sau când programul nu s-a putut citi. |
wait_seconds | integer · null | Cât a așteptat apelantul până a vorbit cu cineva. Pe un apel nepreluat, cât a sunat. |
talk_seconds | integer · null | Cât s-a vorbit. 0 când nu a vorbit nimeni. |
duration_seconds | integer · null | De la început la sfârșit, cu tot cu așteptare. |
recorded | boolean · null | Există o înregistrare a convorbirii. Înregistrarea în sine nu se ia încă prin API; o asculți din CrioX. |
crm_provider | string · null | CRM-ul în care e cunoscut contactul (kommo, istoma, medsoft), dacă ai unul legat și l-a găsit. |
crm_contact_id | string · null | Id-ul fișei lui în acel CRM. |
crm_contact_url | string · null | Legătura spre fișă, de pus pe un buton. |
destination_type | string · null | Unde a trimis numărul apelul la intrare: extension, group, queue, ivr, assistant, voicemail sau external. Pe un apel dat, external. null când apelul s-a încheiat pe număr fără să fie trimis nicăieri. Detalii mai jos. |
destination_number | string · null | Numărul destinației: interiorul, grupul (8001), coada (7001), meniul (500), asistentul (6001), căsuța vocală sau numărul din afară. null când centrala nu l-a consemnat. |
destination_name | string · null | Numele ei, când se știe: al cozii, al meniului, al colegului. |
path | pas[] · null | Traseul apelului, pas cu pas, în ordinea în care s-a întâmplat. Forma unui pas e mai jos. null doar pe evenimentul call.answered, unde traseul nu se știe încă; listă goală când nu s-a consemnat niciun pas. |
Valorile lui result
answered | A vorbit cineva. |
busy | Ocupat. |
no_answer | A sunat și nu a răspuns nimeni. |
cancelled | Apelantul a închis înainte să răspundă cineva. |
failed | Apelul nu s-a putut face: număr greșit, rețea, refuz. |
Valorile lui missed_reason
after_hours | A sunat în afara programului: ore, zi liberă sau o închidere pusă de tine. |
limit | Refuzat de o limită a contului, de exemplu toate liniile ocupate. |
no_agent | Coada nu avea pe nimeni disponibil. |
busy | Ocupat. |
abandoned | A închis cât aștepta. |
unanswered | Restul: a sunat fără răspuns, a ajuns în mesageria vocală sau s-a oprit într-un meniu. |
Nu există un câmp „a lăsat mesaj vocal”. Centrala nu leagă mesajul de apel, iar un câmp ghicit ar fi o minciună pe care ai automatiza. Când se va putea spune sigur, îl adăugăm.
Destinația și traseul
Un apel primit intră pe un număr, iar numărul îl trimite undeva: la un interior, la un grup de sonerie, într-o coadă, într-un meniu vocal, la asistentul AI, în mesageria vocală sau la un număr din afară. Acel „undeva” e destinația, cu tipul, numărul și numele ei. Rămâne destinația chiar dacă apelul l-a preluat până la urmă un coleg: pentru „cine a vorbit” sunt câmpurile agent_*. Pe un apel dat, destinația e numărul sunat.
| Tip | Ce e | Număr |
|---|---|---|
extension | Un interior, telefonul unui coleg. | 100–499 |
group | Un grup de sonerie: mai multe interioare sună deodată sau pe rând. | 8001–8099 |
queue | O coadă de call-center, cu agenți și așteptare. | 7001–7099 |
ivr | Un meniu vocal: „apăsați 1 pentru…”. | 500–599 |
assistant | Asistentul AI. | 6001–6099 |
voicemail | Mesageria vocală; numărul e al căsuței. | căsuța |
external | Un număr din afară: un mobil sunat de centrală în locul biroului, sau numărul sunat pe un apel dat. | +40… |
Traseul (path)
Tot ce s-a întâmplat cu apelul, în ordine: a intrat în meniu, a apăsat o tastă, a intrat în coadă, au sunat două interioare, a răspuns unul, a fost trecut la asistent. Fiecare pas are aceleași șapte chei, null unde nu se aplică:
| Cheie | Tip | Ce înseamnă |
|---|---|---|
type | string | Același vocabular ca destination_type. |
number | string · null | Numărul pasului: interiorul care a sunat, coada, grupul, numărul din afară. |
name | string · null | Numele: al colegului, al cozii, al meniului. Pe o tastă, ce înseamnă tasta, dacă meniul o spune. |
key | string · null | Tasta apăsată, doar pe un pas ivr cu result: "key". |
at | moment | Când a început pasul. UTC. |
seconds | integer · null | Cât a ținut: cât a sunat interiorul, cât a stat în coadă, cât a ținut apelul după transfer. |
result | string · null | Ce s-a întâmplat cu pasul; valorile, mai jos. |
Valorile lui result, pe tip de pas:
ivr | enter a intrat în meniu · key a apăsat o tastă · exit a ieșit fără să aleagă |
queue | answered l-a preluat un agent · abandoned a închis cât aștepta · moved a fost scos din coadă și dus mai departe · timeout s-a terminat timpul · no_agent coada nu avea pe nimeni · exit_key a ieșit cu o tastă · other |
extension, external | answered · answered_elsewhere a răspuns alt telefon · no_answer · busy · offline telefonul nu era conectat · cancelled apelantul a închis · rejected · failed · null când nu se știe |
group, assistant, voicemail | null: centrala nu consemnează un deznodământ al lor; ce a urmat se vede din pașii de după. |
Un apel care a intrat într-un meniu, a ales „Programări”, a așteptat în coadă și l-a preluat al doilea coleg sunat:
{
"destination_type": "ivr",
"destination_number": null,
"destination_name": "Meniu principal",
"path": [
{ "type": "ivr", "number": null, "name": "Meniu principal", "key": null, "at": "2026-10-17T08:12:42.000Z", "seconds": null, "result": "enter" },
{ "type": "ivr", "number": null, "name": "Programări", "key": "1", "at": "2026-10-17T08:12:46.000Z", "seconds": null, "result": "key" },
{ "type": "queue", "number": "7001", "name": "Programări", "key": null, "at": "2026-10-17T08:12:46.000Z", "seconds": 7, "result": "answered" },
{ "type": "extension", "number": "102", "name": "Ion Popa", "key": null, "at": "2026-10-17T08:12:47.000Z", "seconds": 4, "result": "no_answer" },
{ "type": "extension", "number": "101", "name": "Maria Ionescu", "key": null, "at": "2026-10-17T08:12:51.000Z", "seconds": 2, "result": "answered" }
]
}
Ce centrala nu a consemnat iese null, nu ghicit. Numărul unui grup se știe doar când apelul a fost trimis explicit la el; altfel grupul se vede ca mai multe interioare sunând deodată, cu destination_number: null. Numele grupurilor, ale asistenților și ale căsuțelor vocale nu sunt pe rândul apelului. Un meniu are nume, dar nu număr, decât dacă apelul s-a încheiat în el.
Întrebări frecvente
De ce lipsește un apel pe care îl văd în CrioX?
Trei cauze obișnuite: e un apel intern, între două interioare, și acelea nu intră în API; e mai vechi de 30 de zile și nu ai trimis from; sau pagina ta de istoric are un filtru pe care cererea nu îl are. Dacă nu e niciuna, scrie-ne cu id-ul apelului.
Cum iau toate apelurile de ieri?
Cu from și to pe ziua de ieri, în fusul tău orar, și paginare până la has_more: false. Exemplul de la paginare face exact asta pentru o lună.
Cum sincronizez continuu, fără să ratez nimic?
Primești evenimentele: ele vin în câteva secunde după fiecare apel, cu același obiect. Dacă totuși preferi să întrebi tu, întreabă o dată la câteva minute, cu from = momentul ultimului apel pe care îl ai, minus o oră, ca să prinzi și apelurile lungi care s-au închis mai târziu. Apelurile pe care le ai deja le recunoști după id.
Pot lua înregistrarea convorbirii?
Încă nu prin API. recorded îți spune dacă există; o asculți din CrioX. Accesul la înregistrări prin API e pe listă, cu reguli proprii, pentru că e altceva decât a ști că apelul a avut loc.
CrioX · suport@criox.ro · live.criox.ro