C cenaly.com
Започни бесплатно

API и MCP за сопствена телефонска централа

Клучеви и овластувања, REST API, MCP-сервер за Claude и Cursor, поврзување на ChatGPT и claude.ai преку OAuth без клуч, примери, лимити и грешки

On this page 10

API и MCP на сопствената АТС

Сопствената АТС Cenaly е отворена за вашите програми и AI асистенти:

  • CRM, сметководен систем, сопствена веб-страница — REST API: дневник на повици, снимки и транскрипти, повик со еден клик, екстензии, пренасочување, правила за повици;
  • Claude Code, Claude Desktop, Cursor — оддалечен MCP-сервер со клуч;
  • ChatGPT, claude.ai, Perplexity, Cursor и VS Code — истиот MCP-сервер без клуч: се најавувате на својата сметка и дозволувате пристап (OAuth).

Сѐ работи во име на сопственикот на сметката и само со правата што тој ги дал. Секоја промена е видлива во дневникот на дејства на АТС со името на клучот или апликацијата.

Адреси#

Што Адреса
REST API https://api.cenaly.com/pbx-api/v1
MCP-сервер (streamable HTTP) https://api.cenaly.com/pbx-api/mcp
Документација за методите api.cenaly.com/pbx-api/v1/docs
Опис OpenAPI 3.1 api.cenaly.com/pbx-api/v1/openapi.json
Метаподатоци за OAuth https://api.cenaly.com/.well-known/oauth-authorization-server/pbx-api

Клуч и права#

Клуч создава само сопственикот на сметката: Телефонија → API и MCP → Клучеви → Создај клуч. Вработен со улога „Администратор на АТС“ не гледа клучеви — клучот дејствува во име на сопственикот.

  • Клуч од вид cpx_… се прикажува еднаш — веднаш по создавањето, заедно со готовите вметнувања за поврзување. Кај нас се чува само неговиот отпечаток (SHA-256), клучот не може да се врати — само да се издаде нов.
  • Клучот може да се ограничи со локации (инаку — сите локации, вклучително и идните) и со рок (30, 90, 365 дена или без рок).
  • „Права“ ги менуваат правата и локациите на клучот во лет: интеграцијата продолжува да работи, новите права важат од следното барање.
  • „Отповикај“ — веднаш и засекогаш: следното барање со овој клуч ќе добие 401.
  • Активни клучеви и поврзувања — до 20 на сметка.

Правата се избираат со готов сет или со штиклирање:

Право Што дава Сетови
calls:read дневник на повици и картичка на повик со рута CRM, AI асистент, само читање, сѐ
recordings:read врска до снимката од разговорот (10 минути) и транскрипт CRM, AI асистент, само читање, сѐ
calls:dial повик со еден клик: прво ѕвони телефонот на вработениот, по одговорот АТС го бира бројот CRM, AI асистент, сѐ
extensions:read екстензии, групи, пренасочување, „не вознемирувај“ CRM, AI асистент, само читање, сѐ
extensions:write менување на личното пренасочување и „не вознемирувај“ AI асистент, сѐ
presence:read кој е слободен, ѕвони, разговара AI асистент, само читање, сѐ
reports:read метрики на кол-центарот за период: ниво на услуга, чекање, напуштени, AHT, FCR, CSAT, каде ги губиме повиците, пресеци по редици, линии, вработени само читање, сѐ
routes:read броеви, правила за влезни и излезни повици, историја на правила само читање, сѐ
routes:write создавање, менување, бришење и преместување на правила за повици, враќање од историјата само со посебно штиклирање
config:export извоз на поставките на АТС во формат на датотека само со посебно штиклирање
config:import вчитување на поставки од табели: преглед, потоа примена само со посебно штиклирање
webhooks:write создавање, менување, проверка и бришење на вебхукови за настани од повици само со посебно штиклирање
daynight:write затворање на локација до крајот на денот или до датум, отворање — исто како *28 од телефон само со посебно штиклирање

Правата што нешто менуваат или трошат минути се означени со килибарна боја во прозорецот. Последните три права не влегуваат во ниту еден сет, дури ни во „Сѐ“ — може да се дадат само свесно, со посебно штиклирање.

ChatGPT, claude.ai, Perplexity, Cursor, VS Code: поврзување без клуч#

Облачните асистенти не умеат да вметнат клуч во заглавие — тие го поврзуваат MCP-серверот преку OAuth. Не треба да се создава клуч.

claude.ai: Поставки → Конектори → Додај свој конектор → вметнете https://api.cenaly.com/pbx-api/mcp → Поврзи.

ChatGPT: Поставки → Апликации и конектори → Дополнително → вклучете режим на развивач → Создај → вметнете https://api.cenaly.com/pbx-api/mcp, автентикација — OAuth.

Perplexity: Поставки на сметката → Конектори → „+ Свој конектор“ → Оддалечен → вметнете https://api.cenaly.com/pbx-api/mcp, автентикација — OAuth.

Cursor и VS Code: додајте оддалечен (HTTP) MCP-сервер со адреса https://api.cenaly.com/pbx-api/mcp без заглавие со клуч — прозорецот за најава ќе се отвори во прелистувачот. Во Cursor: .cursor/mcp.json → {"mcpServers": {"cenaly-pbx": {"url": "https://api.cenaly.com/pbx-api/mcp"}}}; во VS Code: командата „MCP: Add Server“ → HTTP.

Понатаму асистентот ќе отвори прозорец за најава во Cenaly. По најавата ќе видите:

  • кој бара пристап — апликацијата се именува според адресата на која ќе се врати одговорот: „Проверен конектор · chatgpt.com“ (исто така — claude.ai, perplexity.ai, vscode.dev, Cursor), „Програма на овој компјутер“ или предупредување „Непозната адреса“. Името што го пратила апликацијата е прикажано ситно — може да го напише било кој;
  • права — означено е тоа што го бара апликацијата (ако бара „сѐ по ред“, означен е сетот „AI асистент“); правата „само со посебно штиклирање“ никогаш не се означуваат однапред;
  • локации — сите или избраните.

„Дозволи“ ве враќа во асистентот и тој веднаш ги гледа алатките на АТС. Поврзувањето се појавува во Телефонија → API и MCP → Клучеви како ред со ознака OAuth и адресата на апликацијата — таму исто така се менуваат правата и се отповикува пристапот. Повторното поврзување на истата апликација ги обновува нејзините права, а не создава второ поврзување.

Поврзувања може да дозволува само сопственикот на сметката.

Claude Code, Claude Desktop, Cursor: поврзување со клуч#

Claude Code — со една команда:

claude mcp add --transport http telephony https://api.cenaly.com/pbx-api/mcp --header "Authorization: Bearer cpx_…"

Claude Desktop, Cursor (.cursor/mcp.json) и други клиенти со датотека за поставки:

{
  "mcpServers": {
    "telephony": {
      "type": "http",
      "url": "https://api.cenaly.com/pbx-api/mcp",
      "headers": { "Authorization": "Bearer cpx_…" }
    }
  }
}

Готовите вметнувања со вашиот клуч се прикажуваат веднаш по создавањето на клучот. AI асистентот ги гледа само алатките дозволени со клучот и може да одговори на „кој ѕвонеше денес и не се јави“, „јави се на овој гостин од телефонот на Ана“, „вклучи ми пренасочување на мобилен“.

REST API#

Клучот — во заглавието Authorization: Bearer <ключ> (или X-Api-Key). Ако клучот има една Локација, параметарот location може да не се пренесува; ако има неколку — одговорот 400 location_required ќе ги наброи.

Метод Пат Право Што прави
GET /v1/me — права, Локации и лимити на клучот
GET /v1/locations — Локации на клучот и нивните АТС
GET /v1/calls calls:read дневник на повици: since, until, direction, status (answered, missed, ai), number, extension, limit до 100, cursor
GET /v1/calls/{id} calls:read повик со маршрута: кое правило се активираше, чиј телефон ѕвонеше, кој одговори
GET /v1/calls/{id}/recording recordings:read врска до Снимањето за 10 минути
GET /v1/calls/{id}/transcript recordings:read транскрипт и резиме на разговорот
POST /v1/dial calls:dial повик со еден клик: { "extension": "101", "number": "+995555123456" }
GET /v1/dial/{commandId} calls:dial како оди повикот со еден клик
GET /v1/extensions extensions:read добавочни, групи, пренасочување, „не вознемирувај“
PUT /v1/extensions/{ext}/forwarding extensions:write лично пренасочување на добавочен
PUT /v1/extensions/{ext}/dnd extensions:write „не вознемирувај“: { "on": true }
GET /v1/presence presence:read кој е слободен во моментов
GET /v1/metrics reports:read метрики на кол-центарот за период: from, to (локални датуми на Локацијата YYYY-MM-DD, по правило — последните 7 дена), compare (prev, year, prev,year или празно), sections (metrics,loss,queues,lines,operators,directions,heatmap,daily), callbacks=true — и брзина на повторно јавување
GET /v1/routes routes:read Броеви, правила за влезни и излезни
GET /v1/routes/history routes:read историја на промени на правилата
POST, PUT, DELETE /v1/routes/inbound…, /v1/routes/outbound… routes:write правила за повици едно по едно: создај, измени ги пренесените полиња, избриши, премести, врати
GET, POST /v1/config/export, /v1/config/import config:export, config:import поставки во формат на датотека; вчитувањето — преглед, потоа примена
GET /v1/events calls:read настани од повици на Локацијата за 7 дена (до 2000): since (id на настан или време), types, limit (до 500 за одговор)
GET, POST, PATCH, DELETE /v1/webhooks… webhooks:write вебхукови: список, создај, измени, избриши; …/rotate-secret, …/test, …/deliveries
GET, PUT /v1/open-closed routes:read, daynight:write дали е затворено и до кога; затвори до крајот на денот { "closed": true }, до датум { "closed": true, "until": "2026-10-05T09:00" } или отвори

Целосен опис на полињата — на страницата документација и во OpenAPI.

Кој ѕвонеше денес и не се јави:

curl -H "Authorization: Bearer cpx_…" \
  "https://api.cenaly.com/pbx-api/v1/calls?status=missed&since=$(date -u +%Y-%m-%dT00:00:00Z)"

Да се јавиш повторно на клиентот од телефонот на добавочен 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"

Метрики за септември со споредба со август и септември минатата година — за своја 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"

Во одговорот metrics — истите бројки како на екранот Телефонија → Дневник на повици → Аналитика: влезни, примени и пропуштени, ниво на услуга (праг и цел — од поставките на редот), просечно и максимално чекање, удел на напуштени без кратки, AHT, FCR, удел на пренасочувања и бот, CSAT. compare.prev и compare.year — истите полиња за претходниот период и за истиот период пред една година. Споредбата со минатата година се пресметува за периоди до 400 дена.

Вклучи пренасочување на мобилен, ако вработениот не одговорил за 15 секунди:

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"

Инструменти MCP#

Истите операции како кај REST. Клиентот ги гледа само инструментите дозволени со клучот или поврзувањето:

Инструменти Право
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

Серверот работи без сесии (streamable HTTP, JSON-RPC 2.0): initialize, tools/list, tools/call.

OAuth за развивачи на свои конектори#

Серверот за авторизација ја следи спецификацијата за авторизација на MCP — одговара секој клиент што ја поддржува:

  1. Барање до MCP без токен добива 401 со заглавје WWW-Authenticate: Bearer resource_metadata="https://api.cenaly.com/.well-known/oauth-protected-resource/pbx-api/mcp".
  2. Метаподатоците за ресурсот (RFC 9728) го наведуваат серверот за авторизација — https://api.cenaly.com/pbx-api; неговите метаподатоци (RFC 8414) — на адресата https://api.cenaly.com/.well-known/oauth-authorization-server/pbx-api (и …/pbx-api/.well-known/openid-configuration).
  3. Динамична регистрација на клиент (RFC 7591): POST /pbx-api/oauth/register. Адресата за враќање — само localhost / 127.0.0.1 (било кој порт) или адреса на познат конектор (claude.ai, claude.com, chatgpt.com, chat.openai.com, vscode.dev, www.perplexity.ai, enterprise.perplexity.ai; кај Cursor — уште точно cursor://anysphere.cursor-mcp/oauth/callback). Начинот на најава на клиентот — none (јавен клиент), client_secret_post или client_secret_basic.
  4. Код за авторизација со PKCE (само S256): GET /pbx-api/oauth/authorize → прозорец за најава и согласност на сопственикот → враќање на вашата адреса со code, state и iss. Параметарот resource — адресата на MCP-серверот.
  5. Токени: POST /pbx-api/oauth/token. Кодот е еднократен и живее 2 минути (погрешен code_verifier го гаси); токенот за пристап — 1 час; токенот за обновување — 90 дена, при секое обновување се издава нов, претходниот престанува да работи.
  6. Отповикување: POST /pbx-api/oauth/revoke (RFC 7009) го гаси поврзувањето целосно — како „Отповикај“ во прозорецот „API и MCP“.

Токенот за пристап се прифаќа насекаде каде што се прифаќа клучот: и во MCP, и во REST, со правата и локациите што ги дозволил сопственикот.

Лимити и грешки#

  • На клуч или поврзување: 120 барања во минута и 20 000 во деноноќие (REST и MCP заедно).
  • Звонок во клик — одделно: 10 во минута и 300 во деноноќие.
  • Дневникот — до 100 звонови за барање; во дневникот на АТС локацијата — последните 400 звонови за 90 дена.
Код Грешка Што да направите
401 api_key_missing, api_key_invalid клучот го нема, отповикан е или истекол; токенот OAuth истекол — обновете го
403 scope_required клучот нема право — додајте го во „Права“
400 location_required клучот има повеќе локации — предајте location
404 location_not_found локацијата ја нема или клучот е ограничен на други локации
429 rate_limited лимитот е исцрпен, повторете по Retry-After секунди

Настани од повици#

Во реално време — вебхукови на АТС: Телефонија → API и MCP → Вебхукови или POST /v1/webhooks со клуч со право webhooks:write. На вашата https-адреса за секунди пристигнува POST за секој настан: call.started (започнат: насока, кој, каде, линија), call.ringing (кај кого ѕвони — по еден за секој телефон), call.answered (кој одговорил), call.transferred (кој и на кого префрлил), call.ended (резултат, времетраење, разговор, кој одговорил). Вебхукот може да се ограничи по локации и типови на настани.

{ "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": "Анна" } } }

Потпис — заглавје X-Cenaly-Signature: t=<време unix>,v1=<HMAC-SHA256 од "t.тело" со тајната на вебхукот>. Пресметајте повторно, споредете во постојано време и отфрлете t постаро од 5 минути. Тајната whsec_… се прикажува еднаш; „Нова тајна“ веднаш ја гаси претходната.

Достава — одговорете 2xx за 10 секунди. Инаку повторуваме со паузи од 10 с, 30 с, 2, 5, 10, 15 и 15 минути (8 обиди, околу еден час); повторувањето носи истиот id — по него отфрлајте дупликати. Дневникот на достави (код на одговор, време, обид) — во прозорецот на вебхукот и GET /v1/webhooks/{id}/deliveries; „Провери“ праќа службен webhook.ping. Адресата 3 дена по ред не примила ниту една достава — вебхукот се исклучува сам: на сопственикот му доаѓа е-пошта, во прозорецот „Вебхукови“ — ознака „Исклучен автоматски“ и копче „Вклучи“ (или PATCH /v1/webhooks/{id} со { "enabled": true }).

Без свој сервер — истата лента преку анкетирање: GET /v1/events?since=<id на последниот настан> или алатката MCP get_call_events (настани на локацијата за последните 7 дена, до 2000; за одговор — до 500, more: true — листајте понатаму со истиот since).

По обработка на снимката — повикот со транскрипт и анализа пристигнува преку вебхук на изворот „Вебхук“ во делот „Повици“.

„Отворено / затворено“ — PUT /v1/open-closed со { "closed": true } ја затвора локацијата до крајот на денот (како *28 од телефон: повиците одат по правилата „надвор од работно време“), false — ја отвора; GET покажува дали е затворена и од кого. Со "until" — затворена до тој момент (не повеќе од 30 дена), потоа се отвора сама: времето без поместување (2026-10-05T09:00) се чита во часовниот појас на локацијата; false го отстранува и тоа. Потребна е вклучена опција „Затвори со код *28“ во рутирањето (инаку 409).

Безбедност#

  • Клучот се прикажува еднаш и кај нас се чува само како отпечаток; истечен клуч се отповикува со едно копче.
  • OAuth-поврзување дозволува само сопственикот, и се гледа на која адреса оди пристапот; дозволеното поврзување може да се ограничи по права и локации и да се отповика во секој момент.
  • Телефонските броеви се лични податоци на вашите клиенти: давајте права за дневникот и снимките само на интеграциите на кои навистина им се потребни.
  • Сите промени преку клуч или поврзување — во дневникот на дејства на АТС со името на клучот или апликацијата.
Was this article helpful?