C cenaly.com
Gratis starten

API en MCP van je eigen telefooncentrale

Sleutels en rechten, REST API, MCP-server voor Claude en Cursor, koppeling van ChatGPT en claude.ai via OAuth zonder sleutel, voorbeelden, limieten en fouten

12 min read Demo admin-paneel
On this page 10

API en MCP van uw eigen telefooncentrale

Uw eigen telefooncentrale Cenaly staat open voor uw programma's en AI-assistenten:

  • CRM, boekhoudsysteem, uw eigen website — REST API: oproeplog, opnamen en transcripties, klik-om-te-bellen, toestelnummers, doorschakeling, belregels;
  • Claude Code, Claude Desktop, Cursor — externe MCP-server met een sleutel;
  • ChatGPT, claude.ai, Perplexity, Cursor en VS Code — dezelfde MCP-server zonder sleutel: u logt in op uw account en geeft toegang (OAuth).

Alles werkt namens de eigenaar van het account en alleen met de rechten die hij heeft verleend. Elke wijziging is zichtbaar in het actielog van de telefooncentrale met de naam van de sleutel of de app.

Adressen#

Wat Adres
REST API https://api.cenaly.com/pbx-api/v1
MCP-server (streamable HTTP) https://api.cenaly.com/pbx-api/mcp
Documentatie over de methoden api.cenaly.com/pbx-api/v1/docs
OpenAPI 3.1-beschrijving api.cenaly.com/pbx-api/v1/openapi.json
OAuth-metadata https://api.cenaly.com/.well-known/oauth-authorization-server/pbx-api

Sleutel en rechten#

Een sleutel wordt alleen door de eigenaar van het account aangemaakt: Telefonie → API en MCP → Sleutels → Sleutel aanmaken. Een medewerker met de rol „Beheerder telefooncentrale” ziet geen sleutels — de sleutel werkt namens de eigenaar.

  • Een sleutel van de vorm cpx_… wordt één keer getoond — direct na het aanmaken, samen met kant-en-klare fragmenten om te verbinden. Bij ons wordt alleen de vingerafdruk (SHA-256) bewaard; de sleutel kan niet worden hersteld — u kunt alleen een nieuwe uitgeven.
  • De sleutel kan worden beperkt tot vestigingen (anders alle vestigingen, inclusief toekomstige) en tot een looptijd (30, 90, 365 dagen of onbeperkt).
  • „Rechten” wijzigen de rechten en vestigingen van de sleutel direct: de integratie blijft werken, de nieuwe rechten gelden vanaf het volgende verzoek.
  • „Intrekken” — direct en definitief: het volgende verzoek met deze sleutel krijgt 401.
  • Actieve sleutels en verbindingen — tot 20 per account.

Rechten worden gekozen met een kant-en-klare set of met afzonderlijke vinkjes:

Recht Wat het geeft Sets
calls:read oproeplog en oproepkaart met route CRM, AI-assistent, alleen lezen, alles
recordings:read link naar de opname van het gesprek (10 minuten) en transcriptie CRM, AI-assistent, alleen lezen, alles
calls:dial klik-om-te-bellen: eerst gaat de telefoon van de medewerker, na opname kiest de telefooncentrale het nummer CRM, AI-assistent, alles
extensions:read toestelnummers, groepen, doorschakeling, „niet storen” CRM, AI-assistent, alleen lezen, alles
extensions:write persoonlijke doorschakeling en „niet storen” wijzigen AI-assistent, alles
presence:read wie vrij is, belt, in gesprek is AI-assistent, alleen lezen, alles
reports:read metrics van het callcenter over een periode: servicelevel, wachttijd, gemiste oproepen, AHT, FCR, CSAT, waar we oproepen verliezen, uitsplitsingen naar wachtrijen, lijnen, medewerkers alleen lezen, alles
routes:read nummers, regels voor inkomende en uitgaande oproepen, geschiedenis van regels alleen lezen, alles
routes:write belregels aanmaken, wijzigen, verwijderen en herordenen, terugzetten uit de geschiedenis alleen met een apart vinkje
config:export export van de instellingen van de telefooncentrale als bestand alleen met een apart vinkje
config:import import van instellingen uit tabellen: voorbeeld, daarna toepassen alleen met een apart vinkje
webhooks:write webhooks voor oproepgebeurtenissen aanmaken, wijzigen, testen en verwijderen alleen met een apart vinkje
daynight:write een vestiging sluiten tot het einde van de dag of tot een datum, en weer openen — hetzelfde als *28 vanaf de telefoon alleen met een apart vinkje

Rechten die iets wijzigen of minuten verbruiken, zijn in het venster met amber gemarkeerd. De laatste drie rechten zitten in geen enkele set, zelfs niet in „Alles” — ze kunnen alleen bewust, met een apart vinkje, worden gegeven.

ChatGPT, claude.ai, Perplexity, Cursor, VS Code: verbinden zonder sleutel#

Cloudassistenten kunnen geen sleutel in een header plaatsen — zij verbinden de MCP-server via OAuth. Een sleutel aanmaken is niet nodig.

claude.ai: Instellingen → Connectors → Eigen connector toevoegen → plak https://api.cenaly.com/pbx-api/mcp → Verbinden.

ChatGPT: Instellingen → Apps en connectors → Geavanceerd → schakel de ontwikkelaarsmodus in → Aanmaken → plak https://api.cenaly.com/pbx-api/mcp, authenticatie — OAuth.

Perplexity: Accountinstellingen → Connectors → „+ Eigen connector” → Extern → plak https://api.cenaly.com/pbx-api/mcp, authenticatie — OAuth.

Cursor en VS Code: voeg een externe (HTTP) MCP-server toe met het adres https://api.cenaly.com/pbx-api/mcp zonder header met een sleutel — het inlogvenster opent in de browser. In Cursor: .cursor/mcp.json → {"mcpServers": {"cenaly-pbx": {"url": "https://api.cenaly.com/pbx-api/mcp"}}}; in VS Code: de opdracht „MCP: Add Server” → HTTP.

Daarna opent de assistent het inlogvenster van Cenaly. Na het inloggen ziet u:

  • wie toegang vraagt — de app wordt genoemd naar het adres waarnaar het antwoord teruggaat: „Geverifieerde connector · chatgpt.com” (net zo — claude.ai, perplexity.ai, vscode.dev, Cursor), „Programma op deze computer” of de waarschuwing „Onbekend adres”. De naam die de app heeft meegestuurd, staat klein weergegeven — die kan door iedereen zijn ingevuld;
  • rechten — aangevinkt staat wat de app vraagt (vraagt die „alles maar dan ook alles”, dan is de set „AI-assistent” aangevinkt); rechten „alleen met een apart vinkje” worden nooit vooraf aangevinkt;
  • vestigingen — alle of geselecteerde.

„Toestaan” brengt u terug naar de assistent, en die ziet direct de tools van de telefooncentrale. De verbinding verschijnt in Telefonie → API en MCP → Sleutels als een regel met het label OAuth en het adres van de app — daar wijzigt u ook de rechten en trekt u de toegang in. Opnieuw verbinden met dezelfde app werkt de rechten bij in plaats van een tweede verbinding aan te maken.

Alleen de eigenaar van het account mag verbindingen toestaan.

Claude Code, Claude Desktop, Cursor: verbinding met sleutel#

Claude Code — met één opdracht:

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

Claude Desktop, Cursor (.cursor/mcp.json) en andere clients met een instellingenbestand:

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

Kant-en-klare fragmenten met uw sleutel worden direct na het aanmaken van de sleutel getoond. De AI-assistent ziet alleen de tools die de sleutel toestaat, en kan antwoorden op „wie belde er vandaag en kreeg geen gehoor”, „bel deze gast terug vanaf de telefoon van Anna”, „zet voor mij doorschakeling naar mobiel aan”.

REST API#

De sleutel staat in de header Authorization: Bearer <ключ> (of X-Api-Key). Als de sleutel één vestiging heeft, hoeft u de parameter location niet mee te sturen; bij meerdere somt de respons 400 location_required ze op.

Methode Pad Recht Wat het doet
GET /v1/me — rechten, vestigingen en limieten van de sleutel
GET /v1/locations — vestigingen van de sleutel en hun telefooncentrale
GET /v1/calls calls:read oproeplog: since, until, direction, status (answered, missed, ai), number, extension, limit tot 100, cursor
GET /v1/calls/{id} calls:read oproep met route: welke regel is uitgevoerd, wiens telefoon overging, wie opnam
GET /v1/calls/{id}/recording recordings:read link naar de opname, 10 minuten geldig
GET /v1/calls/{id}/transcript recordings:read transcriptie en samenvatting van het gesprek
POST /v1/dial calls:dial klik-en-bel: { "extension": "101", "number": "+995555123456" }
GET /v1/dial/{commandId} calls:dial voortgang van klik-en-bel
GET /v1/extensions extensions:read toestelnummers, groepen, doorschakeling, „niet storen”
PUT /v1/extensions/{ext}/forwarding extensions:write persoonlijke doorschakeling van een toestelnummer
PUT /v1/extensions/{ext}/dnd extensions:write „niet storen”: { "on": true }
GET /v1/presence presence:read wie is nu beschikbaar
GET /v1/metrics reports:read callcentermetrics over een periode: from, to (lokale datums van de vestiging YYYY-MM-DD, standaard de laatste 7 dagen), compare (prev, year, prev,year of leeg), sections (metrics,loss,queues,lines,operators,directions,heatmap,daily), callbacks=true — ook de terugbelsnelheid
GET /v1/routes routes:read nummers, regels voor inkomende en uitgaande oproepen
GET /v1/routes/history routes:read wijzigingsgeschiedenis van regels
POST, PUT, DELETE /v1/routes/inbound…, /v1/routes/outbound… routes:write oproepregels één voor één: aanmaken, doorgegeven velden wijzigen, verwijderen, herordenen, terugdraaien
GET, POST /v1/config/export, /v1/config/import config:export, config:import instellingen als bestand; bij uploaden eerst een voorbeeld, daarna toepassen
GET /v1/events calls:read oproepgebeurtenissen van de vestiging over 7 dagen (tot 2000): since (gebeurtenis-id of tijd), types, limit (tot 500 per respons)
GET, POST, PATCH, DELETE /v1/webhooks… webhooks:write webhooks: opvragen, aanmaken, wijzigen, verwijderen; …/rotate-secret, …/test, …/deliveries
GET, PUT /v1/open-closed routes:read, daynight:write of het gesloten is en tot wanneer; sluiten tot het einde van de dag { "closed": true }, tot een datum { "closed": true, "until": "2026-10-05T09:00" } of openen

De volledige beschrijving van de velden staat op de pagina documentatie en in OpenAPI.

Wie belde er vandaag en kreeg geen gehoor:

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

Een klant terugbellen vanaf de telefoon van toestelnummer 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"

Metrics over september met vergelijking met augustus en september van vorig jaar — voor uw eigen BI-paneel:

curl -H "Authorization: Bearer cpx_…" \
  "https://api.cenaly.com/pbx-api/v1/metrics?from=2026-09-01&to=2026-09-30&compare=prev,year"

In de respons bevat metrics dezelfde cijfers als op het scherm Telefonie → Oproeplog → Analyse: inkomend, aangenomen en gemist, servicelevel (drempel en doel — uit de wachtrijinstellingen), gemiddelde en maximale wachttijd, aandeel opgehangen zonder kort gesprek, AHT, FCR, aandeel doorverbindingen en bot, CSAT. compare.prev en compare.year — dezelfde velden over de vorige periode en over dezelfde periode een jaar geleden. De vergelijking met vorig jaar wordt berekend voor periodes tot 400 dagen.

Doorschakeling naar mobiel aanzetten als een medewerker niet binnen 15 seconden opneemt:

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-gereedschappen#

Dezelfde bewerkingen als bij REST. De client ziet alleen gereedschappen die door de sleutel of verbinding zijn toegestaan:

Gereedschappen Recht
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

De server werkt zonder sessies (streamable HTTP, JSON-RPC 2.0): initialize, tools/list, tools/call.

OAuth voor ontwikkelaars van eigen connectors#

De autorisatieserver volgt de MCP-autorisatiespecificatie — elke client die deze ondersteunt, is geschikt:

  1. Een verzoek aan MCP zonder token krijgt 401 met de header WWW-Authenticate: Bearer resource_metadata="https://api.cenaly.com/.well-known/oauth-protected-resource/pbx-api/mcp".
  2. De metadata van de resource (RFC 9728) noemen de autorisatieserver — https://api.cenaly.com/pbx-api; de metadata daarvan (RFC 8414) staan op https://api.cenaly.com/.well-known/oauth-authorization-server/pbx-api (en …/pbx-api/.well-known/openid-configuration).
  3. Dynamische registratie van de client (RFC 7591): POST /pbx-api/oauth/register. Het retouradres is alleen localhost / 127.0.0.1 (elke poort) of het adres van een bekende connector (claude.ai, claude.com, chatgpt.com, chat.openai.com, vscode.dev, www.perplexity.ai, enterprise.perplexity.ai; bij Cursor ook precies cursor://anysphere.cursor-mcp/oauth/callback). De inlogmethode van de client is none (publieke client), client_secret_post of client_secret_basic.
  4. Autorisatiecode met PKCE (alleen S256): GET /pbx-api/oauth/authorize → inlog- en toestemmingsvenster van de eigenaar → terugkeer naar uw adres met code, state en iss. De parameter resource is het adres van de MCP-server.
  5. Tokens: POST /pbx-api/oauth/token. De code is eenmalig en leeft 2 minuten (een onjuiste code_verifier dooft hem); het toegangstoken — 1 uur; het vernieuwingstoken — 90 dagen, bij elke vernieuwing wordt een nieuw token uitgegeven en werkt het vorige niet meer.
  6. Intrekken: POST /pbx-api/oauth/revoke (RFC 7009) dooft de verbinding in zijn geheel — net als „Intrekken” in het venster „API en MCP”.

Het toegangstoken wordt overal geaccepteerd waar de sleutel geldt: zowel in MCP als in REST, met de rechten en vestigingen die de eigenaar heeft toegestaan.

Limieten en fouten#

  • Per sleutel of verbinding: 120 verzoeken per minuut en 20 000 per dag (REST en MCP samen).
  • Bellen in één klik — apart: 10 per minuut en 300 per dag.
  • Logboek — tot 100 gesprekken per verzoek; in het logboek van de ATS-vestiging de laatste 400 gesprekken van 90 dagen.
Code Fout Wat te doen
401 api_key_missing, api_key_invalid de sleutel ontbreekt, is ingetrokken of verlopen; het OAuth-token is verlopen — vernieuw het
403 scope_required de sleutel mist een recht — voeg het toe bij „Rechten”
400 location_required de sleutel heeft meerdere vestigingen — geef location mee
404 location_not_found de vestiging bestaat niet of de sleutel is beperkt tot andere vestigingen
429 rate_limited de limiet is bereikt, probeer het opnieuw na Retry-After seconden

Gespreksgebeurtenissen#

Realtime — webhooks van de telefooncentrale: Telefonie → API en MCP → Webhooks of POST /v1/webhooks met een sleutel met het recht webhooks:write. Op uw https-adres komt binnen enkele seconden een POST binnen voor elke gebeurtenis: call.started (begonnen: richting, wie, waarnaartoe, lijn), call.ringing (bij wie het overgaat — één per telefoon), call.answered (wie heeft opgenomen), call.transferred (wie heeft naar wie doorverbonden), call.ended (resultaat, duur, gesprek, wie heeft opgenomen). De webhook kan worden beperkt tot vestigingen en gebeurtenistypen.

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

Handtekening — de header X-Cenaly-Signature: t=<unixtijd>,v1=<HMAC-SHA256 van "t.body" met het webhookgeheim>. Herbereken, vergelijk in constante tijd en weiger een t ouder dan 5 minuten. Het geheim whsec_… wordt één keer getoond; „Nieuw geheim” dooft het vorige onmiddellijk.

Bezorging — antwoord met 2xx binnen 10 seconden. Anders herhalen we met pauzes van 10 s, 30 s, 2, 5, 10, 15 en 15 minuten (8 pogingen, ongeveer een uur); de herhaling draagt dezelfde id — gooi daarmee duplicaten weg. Het bezorglogboek (antwoordcode, tijd, poging) staat in het webhookvenster en via GET /v1/webhooks/{id}/deliveries; „Controleren” stuurt een servicebericht webhook.ping. Als het adres 3 etmalen op rij geen enkele bezorging heeft aangenomen, wordt de webhook automatisch uitgeschakeld: de eigenaar ontvangt een e-mail, in het venster „Webhooks” staat de markering „Automatisch uitgeschakeld” en de knop „Inschakelen” (of PATCH /v1/webhooks/{id} met { "enabled": true }).

Zonder eigen server — dezelfde feed via polling: GET /v1/events?since=<id van de laatste gebeurtenis> of de MCP-tool get_call_events (gebeurtenissen van de vestiging van de laatste 7 dagen, tot 2000; per antwoord tot 500, more: true — blader verder met dezelfde since).

Na verwerking van de opname — een gesprek met transcriptie en analyse komt binnen via een webhook van de bron „Webhook” in het gedeelte „Gesprekken”.

„Open / gesloten” — PUT /v1/open-closed met { "closed": true } sluit de vestiging tot het einde van de dag (zoals *28 vanaf de telefoon: gesprekken verlopen volgens de regels „buiten openingstijden”), false opent deze; GET toont of deze gesloten is en door wie. Met "until" — gesloten tot dat moment (niet verder dan 30 dagen), daarna gaat deze vanzelf weer open: een tijd zonder offset (2026-10-05T09:00) wordt gelezen in de tijdzone van de vestiging; false heft dat ook op. Hiervoor is het aangevinkte vakje „Sluiten met code *28” in de routering nodig (anders 409).

Beveiliging#

  • De sleutel wordt één keer getoond en bij ons alleen als vingerafdruk bewaard; een gelekt sleutel wordt met één knop ingetrokken.
  • Een OAuth-verbinding mag alleen de eigenaar toestaan, en er is zichtbaar naar welk adres de toegang gaat; een toegestane verbinding kan worden beperkt in rechten en vestigingen en op elk moment worden ingetrokken.
  • Telefoonnummers zijn persoonsgegevens van uw klanten: geef alleen die integraties rechten op het logboek en de opnamen die ze echt nodig hebben.
  • Alle wijzigingen via een sleutel of verbinding staan in het actielogboek van de telefooncentrale met de naam van de sleutel of app.
Was this article helpful?