API și MCP ale propriei centrale telefonice
Propria centrală telefonică Cenaly este deschisă pentru programele și asistenții dumneavoastră AI:
- CRM, sistem de evidență, propriul site — REST API: jurnal de apeluri, înregistrări și transcrieri, apel la un clic, posturi suplimentare, redirecționare, reguli de apelare;
- Claude Code, Claude Desktop, Cursor — server MCP la distanță prin cheie;
- ChatGPT, claude.ai, Perplexity, Cursor și VS Code — același server MCP fără cheie: vă autentificați în contul dumneavoastră și autorizați accesul (OAuth).
Totul funcționează în numele proprietarului contului și doar cu drepturile pe care acesta le-a acordat. Fiecare modificare este vizibilă în jurnalul de acțiuni al centralei telefonice, cu numele cheii sau al aplicației.
Adrese#
| Ce | Adresă |
|---|---|
| REST API | https://api.cenaly.com/pbx-api/v1 |
| Server MCP (streamable HTTP) | https://api.cenaly.com/pbx-api/mcp |
| Documentația metodelor | api.cenaly.com/pbx-api/v1/docs |
| Descrierea OpenAPI 3.1 | api.cenaly.com/pbx-api/v1/openapi.json |
| Metadate OAuth | https://api.cenaly.com/.well-known/oauth-authorization-server/pbx-api |
Cheia și drepturile#
Cheia este creată doar de proprietarul contului: Telefonie → API și MCP → Chei → Creează cheie. Un angajat cu rolul „Administrator al centralei telefonice” nu vede cheile — cheia acționează în numele proprietarului.
- Cheia de forma
cpx_…este afișată o singură dată — imediat după creare, împreună cu fragmente gata de inserat pentru conectare. La noi se păstrează doar amprenta ei (SHA-256); cheia nu poate fi recuperată — doar emisă una nouă. - Cheia poate fi limitată la puncte de lucru (altfel — toate punctele de lucru, inclusiv cele viitoare) și la un termen (30, 90, 365 de zile sau nelimitat).
- „Drepturi” modifică în timp real drepturile și punctele de lucru ale cheii: integrarea continuă să funcționeze, iar noile drepturi se aplică de la următoarea cerere.
- „Revocă” — imediat și definitiv: următoarea cerere cu această cheie va primi 401.
- Chei și conexiuni active — până la 20 per cont.
Drepturile se aleg printr-un set gata pregătit sau prin bife:
| Drept | Ce oferă | Seturi |
|---|---|---|
calls:read |
jurnalul de apeluri și fișa apelului cu traseul | CRM, Asistent AI, doar citire, tot |
recordings:read |
link către înregistrarea conversației (10 minute) și transcrierea | CRM, Asistent AI, doar citire, tot |
calls:dial |
apel la un clic: mai întâi sună telefonul angajatului, după răspuns centrala formează numărul | CRM, Asistent AI, tot |
extensions:read |
posturi suplimentare, grupuri, redirecționare, „nu deranjați” | CRM, Asistent AI, doar citire, tot |
extensions:write |
modificarea redirecționării personale și a „nu deranjați” | Asistent AI, tot |
presence:read |
cine este liber, sună, vorbește | Asistent AI, doar citire, tot |
reports:read |
metricile call center-ului pentru o perioadă: nivelul de servire, așteptarea, apelurile abandonate, AHT, FCR, CSAT, unde pierdem apeluri, defalcări pe cozi, linii, angajați | doar citire, tot |
routes:read |
numere, reguli de intrare și de ieșire, istoricul regulilor | doar citire, tot |
routes:write |
crearea, modificarea, ștergerea și reordonarea regulilor de apelare, revenirea din istoric | doar cu bifă separată |
config:export |
exportul setărilor centralei telefonice într-un fișier | doar cu bifă separată |
config:import |
importul setărilor din tabele: previzualizare, apoi aplicare | doar cu bifă separată |
webhooks:write |
crearea, modificarea, verificarea și ștergerea webhook-urilor pentru evenimentele apelurilor | doar cu bifă separată |
daynight:write |
închiderea unui punct de lucru până la sfârșitul zilei sau până la o dată, deschiderea — la fel ca *28 de la telefon |
doar cu bifă separată |
Drepturile care modifică ceva sau consumă minute sunt marcate cu chihlimbar în fereastră. Ultimele trei drepturi nu fac parte din niciun set, nici măcar din „Tot” — ele pot fi acordate doar în cunoștință de cauză, cu o bifă separată.
ChatGPT, claude.ai, Perplexity, Cursor, VS Code: conectare fără cheie#
Asistenții cloud nu pot insera o cheie în antet — ei conectează serverul MCP prin OAuth. Nu este nevoie să creați o cheie.
claude.ai: Setări → Conectori → Adaugă propriul conector → inserați https://api.cenaly.com/pbx-api/mcp → Conectare.
ChatGPT: Setări → Aplicații și conectori → Avansat → activați modul dezvoltator → Creează → inserați https://api.cenaly.com/pbx-api/mcp, autentificare — OAuth.
Perplexity: Setările contului → Conectori → „+ Conector propriu” → La distanță → inserați https://api.cenaly.com/pbx-api/mcp, autentificare — OAuth.
Cursor și VS Code: adăugați un server MCP la distanță (HTTP) cu adresa https://api.cenaly.com/pbx-api/mcp fără antet cu cheie — fereastra de autentificare se va deschide în browser. În Cursor: .cursor/mcp.json → {"mcpServers": {"cenaly-pbx": {"url": "https://api.cenaly.com/pbx-api/mcp"}}}; în VS Code: comanda „MCP: Add Server” → HTTP.
Apoi asistentul va deschide fereastra de autentificare Cenaly. După autentificare veți vedea:
- cine solicită accesul — aplicația este denumită după adresa către care va reveni răspunsul: „Conector verificat · chatgpt.com” (la fel — claude.ai, perplexity.ai, vscode.dev, Cursor), „Program de pe acest computer” sau avertismentul „Adresă necunoscută”. Numele trimis de aplicație este afișat cu caractere mici — oricine îl poate scrie;
- drepturile — sunt bifate cele solicitate de aplicație (dacă aceasta solicită „tot ce se poate”, este bifat setul „Asistent AI”); drepturile „doar cu bifă separată” nu sunt niciodată bifate în prealabil;
- punctele de lucru — toate sau cele selectate.
„Permite” vă readuce în asistent, iar acesta vede imediat instrumentele centralei telefonice. Conexiunea apare în Telefonie → API și MCP → Chei ca un rând cu eticheta OAuth și adresa aplicației — tot acolo se modifică drepturile și se revocă accesul. Reconectarea aceleiași aplicații îi actualizează drepturile, nu creează o a doua conexiune.
Doar proprietarul contului poate autoriza conexiuni.
Claude Code, Claude Desktop, Cursor: conectare prin cheie#
Claude Code — cu o singură comandă:
claude mcp add --transport http telephony https://api.cenaly.com/pbx-api/mcp --header "Authorization: Bearer cpx_…"
Claude Desktop, Cursor (.cursor/mcp.json) și alți clienți cu fișier de configurare:
{
"mcpServers": {
"telephony": {
"type": "http",
"url": "https://api.cenaly.com/pbx-api/mcp",
"headers": { "Authorization": "Bearer cpx_…" }
}
}
}
Blocurile gata de inserat cu cheia dumneavoastră sunt afișate imediat după crearea cheii. Asistentul AI vede doar instrumentele permise de cheie și poate răspunde la „cine a sunat astăzi și nu a reușit să ajungă”, „sună-l înapoi pe acest client de pe telefonul Annei”, „activează-mi redirecționarea către mobil”.
REST API#
Cheia — în antetul Authorization: Bearer <cheie> (sau X-Api-Key). Dacă cheia are un singur punct de lucru, parametrul location poate fi omis; dacă are mai multe — răspunsul 400 location_required le va enumera.
| Metodă | Cale | Drept | Ce face |
|---|---|---|---|
| GET | /v1/me |
— | drepturile, punctele de lucru și limitele cheii |
| GET | /v1/locations |
— | punctele de lucru ale cheii și PBX-urile lor |
| GET | /v1/calls |
calls:read |
jurnalul apelurilor: since, until, direction, status (answered, missed, ai), number, extension, limit până la 100, cursor |
| GET | /v1/calls/{id} |
calls:read |
apelul cu traseul: ce regulă s-a declanșat, al cui telefon a sunat, cine a răspuns |
| GET | /v1/calls/{id}/recording |
recordings:read |
link către înregistrare valabil 10 minute |
| GET | /v1/calls/{id}/transcript |
recordings:read |
transcrierea și rezumatul conversației |
| POST | /v1/dial |
calls:dial |
apel cu un clic: { "extension": "101", "number": "+995555123456" } |
| GET | /v1/dial/{commandId} |
calls:dial |
cum decurge apelul cu un clic |
| GET | /v1/extensions |
extensions:read |
posturi suplimentare, grupuri, redirecționare, „nu deranjați” |
| PUT | /v1/extensions/{ext}/forwarding |
extensions:write |
redirecționarea personală a postului suplimentar |
| PUT | /v1/extensions/{ext}/dnd |
extensions:write |
„nu deranjați”: { "on": true } |
| GET | /v1/presence |
presence:read |
cine este liber chiar acum |
| GET | /v1/metrics |
reports:read |
metricile call center-ului pentru o perioadă: from, to (datele locale ale punctului de lucru YYYY-MM-DD, implicit — ultimele 7 zile), compare (prev, year, prev,year sau gol), sections (metrics,loss,queues,lines,operators,directions,heatmap,daily), callbacks=true — și viteza de reapelare |
| GET | /v1/routes |
routes:read |
numerele, regulile pentru apeluri primite și efectuate |
| GET | /v1/routes/history |
routes:read |
istoricul modificărilor regulilor |
| POST, PUT, DELETE | /v1/routes/inbound…, /v1/routes/outbound… |
routes:write |
regulile de apelare una câte una: creare, modificare a câmpurilor transmise, ștergere, reordonare, revenire |
| GET, POST | /v1/config/export, /v1/config/import |
config:export, config:import |
setările în format de fișier; încărcarea — previzualizare, apoi aplicare |
| GET | /v1/events |
calls:read |
evenimentele apelurilor punctului de lucru pentru 7 zile (până la 2000): since (id-ul evenimentului sau timpul), types, limit (până la 500 per răspuns) |
| GET, POST, PATCH, DELETE | /v1/webhooks… |
webhooks:write |
webhook-uri: listare, creare, modificare, ștergere; …/rotate-secret, …/test, …/deliveries |
| GET, PUT | /v1/open-closed |
routes:read, daynight:write |
dacă este închis și până când; închidere până la sfârșitul zilei { "closed": true }, până la o dată { "closed": true, "until": "2026-10-05T09:00" } sau deschidere |
Descrierea completă a câmpurilor — pe pagina documentației și în OpenAPI.
Cine a sunat astăzi și nu a reușit să ajungă:
curl -H "Authorization: Bearer cpx_…" \
"https://api.cenaly.com/pbx-api/v1/calls?status=missed&since=$(date -u +%Y-%m-%dT00:00:00Z)"
Reapelarea unui client de pe telefonul postului suplimentar 101:
curl -X POST -H "Authorization: Bearer cpx_…" -H "Content-Type: application/json" \
-d '{"extension":"101","number":"+995555123456"}' "https://api.cenaly.com/pbx-api/v1/dial"
Metricile pentru septembrie cu comparație față de august și septembrie anul trecut — pentru propria panou BI:
curl -H "Authorization: Bearer cpx_…" \
"https://api.cenaly.com/pbx-api/v1/metrics?from=2026-09-01&to=2026-09-30&compare=prev,year"
În răspuns, metrics — aceleași cifre ca pe ecranul Telefonie → Jurnal apeluri → Analitică: apeluri primite, preluate și pierdute, nivelul de servire (pragul și ținta — din setările cozii), așteptarea medie și maximă, ponderea abandonate fără scurte, AHT, FCR, ponderea transferurilor și a botului, CSAT. compare.prev și compare.year — aceleași câmpuri pentru perioada anterioară și pentru aceeași perioadă de acum un an. Comparația cu anul trecut se calculează pentru perioade de până la 400 de zile.
Activarea redirecționării către mobil, dacă angajatul nu a răspuns în 15 secunde:
curl -X PUT -H "Authorization: Bearer cpx_…" -H "Content-Type: application/json" \
-d '{"forward":{"noAnswer":{"kind":"number","number":"+995599000111"},"noAnswerSec":15}}' \
"https://api.cenaly.com/pbx-api/v1/extensions/101/forwarding"
Instrumente MCP#
Aceleași operațiuni ca la REST. Clientul vede doar instrumentele permise de cheie sau de conexiune:
| Instrumente | Drept |
|---|---|
list_locations |
— |
list_calls, get_call |
calls:read |
get_call_recording, get_call_transcript |
recordings:read |
call_number, get_dial_status |
calls:dial |
list_extensions |
extensions:read |
set_forwarding, set_do_not_disturb |
extensions:write |
get_presence |
presence:read |
get_call_metrics |
reports:read |
list_routes, list_route_history |
routes:read |
save_inbound_rule, delete_inbound_rule, move_inbound_rule, save_outbound_rule, delete_outbound_rule, move_outbound_rule, set_outbound_calls, restore_route_version |
routes:write |
export_config |
config:export |
import_config |
config:import |
get_call_events |
calls:read |
list_webhooks, save_webhook, delete_webhook, rotate_webhook_secret, test_webhook, list_webhook_deliveries |
webhooks:write |
get_open_closed |
routes:read |
set_open_closed |
daynight:write |
Serverul funcționează fără sesiuni (streamable HTTP, JSON-RPC 2.0): initialize, tools/list, tools/call.
OAuth pentru dezvoltatorii propriilor conectori#
Serverul de autorizare respectă specificația de autorizare MCP — este potrivit orice client care o acceptă:
- O cerere către MCP fără token primește 401 cu antetul
WWW-Authenticate: Bearer resource_metadata="https://api.cenaly.com/.well-known/oauth-protected-resource/pbx-api/mcp". - Metadatele resursei (RFC 9728) indică serverul de autorizare —
https://api.cenaly.com/pbx-api; metadatele acestuia (RFC 8414) sunt la adresahttps://api.cenaly.com/.well-known/oauth-authorization-server/pbx-api(și…/pbx-api/.well-known/openid-configuration). - Înregistrare dinamică a clientului (RFC 7591):
POST /pbx-api/oauth/register. Adresa de returnare — doarlocalhost/127.0.0.1(orice port) sau adresa unui conector cunoscut (claude.ai, claude.com, chatgpt.com, chat.openai.com, vscode.dev, www.perplexity.ai, enterprise.perplexity.ai; la Cursor — în plus exactcursor://anysphere.cursor-mcp/oauth/callback). Metoda de autentificare a clientului —none(client public),client_secret_postsauclient_secret_basic. - Cod de autorizare cu PKCE (doar
S256):GET /pbx-api/oauth/authorize→ fereastra de autentificare și de consimțământ a proprietarului → revenire la adresa dumneavoastră cucode,stateșiiss. Parametrulresource— adresa serverului MCP. - Tokenuri:
POST /pbx-api/oauth/token. Codul este de unică folosință și este valabil 2 minute (uncode_verifierincorect îl anulează); tokenul de acces — 1 oră; tokenul de reînnoire — 90 de zile, la fiecare reînnoire se emite unul nou, iar cel vechi încetează să funcționeze. - Revocare:
POST /pbx-api/oauth/revoke(RFC 7009) anulează conexiunea în întregime — ca „Revocare” în fereastra „API și MCP”.
Tokenul de acces este acceptat oriunde cheia: atât în MCP, cât și în REST, cu drepturile și punctele de lucru permise de proprietar.
Limite și erori#
- Per cheie sau conexiune: 120 de cereri pe minut și 20 000 pe zi (REST și MCP împreună).
- Apel în clic — separat: 10 pe minut și 300 pe zi.
- Jurnalul — până la 100 de apeluri per cerere; în jurnalul PBX al punctului de lucru — ultimele 400 de apeluri din 90 de zile.
| Cod | Eroare | Ce să faceți |
|---|---|---|
| 401 | api_key_missing, api_key_invalid |
cheia lipsește, a fost revocată sau a expirat; tokenul OAuth a expirat — reînnoiți-l |
| 403 | scope_required |
cheia nu are dreptul — adăugați-l la „Drepturi” |
| 400 | location_required |
cheia are mai multe puncte de lucru — transmiteți location |
| 404 | location_not_found |
punctul de lucru nu există sau cheia este limitată la alte puncte de lucru |
| 429 | rate_limited |
limita a fost atinsă, repetați după Retry-After secunde |
Evenimente apel#
În timp real — webhook-uri ale centralei telefonice: Telefonie → API și MCP → Webhook-uri sau POST /v1/webhooks cu o cheie cu dreptul webhooks:write. La adresa dumneavoastră https ajunge în câteva secunde un POST pentru fiecare eveniment: call.started (a început: direcție, cine, către cine, linie), call.ringing (la cine sună — câte unul pentru fiecare telefon), call.answered (cine a răspuns), call.transferred (cine și către cine a transferat), call.ended (rezultat, durată, conversație, cine a răspuns). Webhook-ul poate fi limitat la puncte de lucru și tipuri de evenimente.
{ "id": "1727771234.56:2", "type": "call.answered", "createdAt": "2026-10-01T10:00:05Z",
"locationId": "…", "webhookId": "wh_…", "attempt": 1,
"data": { "callId": "1727771234.56", "seq": 2, "direction": "inbound",
"from": { "number": "+995555123456" }, "party": { "extension": "101", "name": "Анна" } } }
Semnătura — antetul X-Cenaly-Signature: t=<timp unix>,v1=<HMAC-SHA256 din "t.corp" cu secretul webhook-ului>. Recalculați, comparați în timp constant și respingeți t mai vechi de 5 minute. Secretul whsec_… este afișat o singură dată; „Secret nou” îl anulează imediat pe cel anterior.
Livrarea — răspundeți 2xx în 10 secunde. Altfel reluăm cu pauze de 10 s, 30 s, 2, 5, 10, 15 și 15 minute (8 încercări, circa o oră); reluarea poartă același id — după el eliminați duplicatele. Jurnalul livrărilor (codul răspunsului, ora, încercarea) — în fereastra webhook-ului și GET /v1/webhooks/{id}/deliveries; „Verifică” trimite un webhook.ping de serviciu. Adresa timp de 3 zile consecutive nu a acceptat nicio livrare — webhook-ul se dezactivează singur: proprietarul primește un e-mail, în fereastra „Webhook-uri” apare mențiunea „Dezactivat automat” și butonul „Activează” (sau PATCH /v1/webhooks/{id} cu { "enabled": true }).
Fără server propriu — aceeași listă prin interogare: GET /v1/events?since=<id-ul ultimului eveniment> sau instrumentul MCP get_call_events (evenimentele punctului de lucru din ultimele 7 zile, până la 2000; per răspuns — până la 500, more: true — continuați cu același since).
După procesarea înregistrării — apelul cu transcriere și analiză ajunge prin webhook-ul sursei „Webhook” în secțiunea „Apeluri”.
„Deschis / închis” — PUT /v1/open-closed cu { "closed": true } închide punctul de lucru până la sfârșitul zilei (ca *28 de la telefon: apelurile merg după regulile „în afara orelor”), false — îl deschide; GET arată dacă este închis și de către cine. Cu "until" — închis până la acel moment (nu mai mult de 30 de zile), apoi se deschide singur: ora fără decalaj (2026-10-05T09:00) este citită în fusul punctului de lucru; false îl anulează și pe acesta. Este nevoie de bifa activată „Închidere cu codul *28” în rutare (altfel 409).
Securitate#
- Cheia este afișată o singură dată și este păstrată la noi doar ca amprentă; o cheie compromisă se revocă printr-un singur buton.
- Conexiunea OAuth este permisă doar de proprietar și se vede către ce adresă pleacă accesul; o conexiune permisă poate fi limitată la drepturi și puncte de lucru și revocată în orice moment.
- Numerele de telefon sunt date personale ale clienților dumneavoastră: acordați drepturi asupra jurnalului și înregistrărilor doar acelor integrări care le necesită cu adevărat.
- Toate modificările prin cheie sau conexiune — în jurnalul de acțiuni al centralei telefonice, cu numele cheii sau al aplicației.