C cenaly.ru
Start free

Your PBX API and MCP

Overview: addresses, keys and permissions, connecting ChatGPT and claude.ai with OAuth without a key, limits and security — with links to the REST API, MCP server and webhook articles

7 min read Admin panel demo
On this page 7

Your PBX API and MCP

Your Cenaly phone system is open to your own software and AI assistants:

  • CRM, accounting, your website — the REST API: call log, recordings and transcripts, click-to-call, extensions, forwarding, metrics, call rules, settings export and import;
  • Claude, ChatGPT, Cursor, VS Code, Perplexity — the MCP server: with a key or without a key — you sign in to your account and allow access (OAuth);
  • real-time call events — webhooks to your address with a signature, or the event feed by polling.

Everything acts on behalf of the account owner and only with the permissions the owner granted. Every change shows up in the PBX action log under the name of the key or app.

Three topics#

Article What's inside
Your PBX REST API every method with permissions, parameters and responses, errors, curl examples, ready-made scenarios: call log to CSV, click-to-call from a CRM, night mode on a schedule
Your PBX MCP server connecting Claude Code, Cursor, VS Code, Claude Desktop with a key and cloud assistants with OAuth, the catalogue of 33 tools, example conversations, raw JSON-RPC
Call event webhooks creating a webhook, bodies of every event, signature checks in Node.js, Python, PHP and Go, retries and duplicates, the event feed without your own server, debugging

Addresses#

What Address
REST API https://api.cenaly.ru/pbx-api/v1
MCP server (streamable HTTP) https://api.cenaly.ru/pbx-api/mcp
Method reference api.cenaly.ru/pbx-api/v1/docs
OpenAPI 3.1 description api.cenaly.ru/pbx-api/v1/openapi.json
OAuth metadata https://api.cenaly.ru/.well-known/oauth-authorization-server/pbx-api

Ready-made addresses and snippets are in Telephony → API and MCP → How to connect.

For a location with its own PBX, requests will be able to go straight to the PBX server, bypassing the cloud. The API already reports whether such an address is ready — the direct field in /v1/me and /v1/locations. While this is being rolled out, use the addresses in the table: they also stay available as the fallback path.

Key and permissions#

Only the account owner creates keys: Telephony → API and MCP → Keys → Create key. An employee with the "PBX administrator" role does not see keys — a key acts on behalf of the owner.

  • A key of the form cpx_… is shown once — right after it is created, together with ready-made connection snippets. We only store its fingerprint (SHA-256); a key cannot be recovered, only reissued.
  • A key can be limited to locations (otherwise — all locations, including future ones) and to a term (30, 90, 365 days or no expiry).
  • "Permissions" change the key's permissions and locations on the fly: the integration keeps working, new permissions apply from the next request.
  • "Revoke" — immediately and for good: the next request with this key gets 401.
  • Up to 20 live keys and connections per account.

The key goes in the Authorization: Bearer cpx_… header (or X-Api-Key: cpx_…) — never in the request URL.

Permissions are chosen as a preset or with checkboxes:

Permission What it gives Presets
calls:read call log, call card with its route, event feed CRM, AI assistant, read only, everything
recordings:read link to the call recording (10 minutes) and transcript CRM, AI assistant, read only, everything
calls:dial click-to-call: the employee's phone rings first, after they answer the PBX dials the number CRM, AI assistant, everything
extensions:read extensions, groups, forwarding, do not disturb CRM, AI assistant, read only, everything
extensions:write change personal forwarding and do not disturb AI assistant, everything
presence:read who is free, ringing, talking AI assistant, read only, everything
reports:read call-centre metrics for a period: service level, waiting, abandoned, AHT, FCR, CSAT, where calls are lost, breakdowns by queues, lines, employees read only, everything
routes:read numbers, inbound and outbound rules, rule history, whether the location is open read only, everything
routes:write create, change, delete and reorder call rules, restore from history separate checkbox only
config:export export PBX settings in file format separate checkbox only
config:import load settings from tables: preview, then apply separate checkbox only
webhooks:write create, change, test and delete call event webhooks separate checkbox only
daynight:write close the location until the end of the day or until a date, open it — the same as *28 from a phone separate checkbox only

Permissions that change something or spend minutes are marked amber in the window. The last five permissions are not part of any preset, not even "everything" — they can only be granted deliberately, with a separate checkbox.

ChatGPT, claude.ai, Perplexity, Cursor, VS Code: connecting without a key#

Cloud assistants connect the MCP server https://api.cenaly.ru/pbx-api/mcp with OAuth — no key needed. Where to add the server in each client — in Your PBX MCP server.

The assistant opens the Cenaly sign-in window. After signing in you will see:

  • who is asking for access — the app is named by the address the answer returns to: "Verified connector · chatgpt.com" (likewise claude.ai, perplexity.ai, vscode.dev, Cursor), "A program on this computer" or the warning "Unknown address". The name the app sent itself is shown in small print — anyone can write it;
  • permissions — what the app asks for is ticked (if it asks for "everything", the "AI assistant" preset is ticked); "separate checkbox only" permissions are never pre-ticked;
  • locations — all or selected.

"Allow" takes you back to the assistant, and it immediately sees the PBX tools. The connection appears in Telephony → API and MCP → Keys as a row with the OAuth badge and the app's address — permissions are changed and access is revoked there. Connecting the same app again updates its permissions instead of creating a second connection.

Only the account owner can allow connections.

OAuth for developers of your own connectors#

The authorization server follows the MCP authorization specification — any client that supports it will work:

  1. A request to MCP without a token gets 401 with the header WWW-Authenticate: Bearer resource_metadata="https://api.cenaly.ru/.well-known/oauth-protected-resource/pbx-api/mcp".
  2. The resource metadata (RFC 9728) names the authorization server — https://api.cenaly.ru/pbx-api; its metadata (RFC 8414) is at https://api.cenaly.ru/.well-known/oauth-authorization-server/pbx-api (and …/pbx-api/.well-known/openid-configuration).
  3. Dynamic client registration (RFC 7591): POST /pbx-api/oauth/register. The redirect address may only be localhost / 127.0.0.1 (any port) or the address of a known connector (claude.ai, claude.com, chatgpt.com, chat.openai.com, vscode.dev, www.perplexity.ai, enterprise.perplexity.ai; for Cursor — also exactly cursor://anysphere.cursor-mcp/oauth/callback). Client authentication — none (public client), client_secret_post or client_secret_basic.
  4. Authorization code with PKCE (S256 only): GET /pbx-api/oauth/authorize → the owner's sign-in and consent window → redirect to your address with code, state and iss. The resource parameter is the MCP server address.
  5. Tokens: POST /pbx-api/oauth/token. The code is single-use and lives 2 minutes (a wrong code_verifier burns it); the access token — 1 hour; the refresh token — 90 days, every refresh issues a new one and the previous one stops working.
  6. Revocation: POST /pbx-api/oauth/revoke (RFC 7009) kills the whole connection — like "Revoke" in the "API and MCP" window.

An access token is accepted everywhere a key is: in MCP and in REST, with the permissions and locations the owner allowed.

Limits and errors#

  • Per key or connection: 120 requests per minute and 20,000 per day (REST and MCP together).
  • Click-to-call — separately: 10 per minute and 300 per day.
  • Call log — up to 100 calls per request; the API sees the location's last 400 calls over 90 days.
  • Event feed — up to 2,000 events per location over 7 days, up to 500 per response.
Code Error What to do
401 api_key_missing, api_key_invalid no key, it was revoked or expired; the OAuth token expired — refresh it
403 scope_required the key lacks the permission — add it in "Permissions"
400 location_required the key has several locations — pass location
404 location_not_found no such location or the key is limited to other locations
429 rate_limited the limit is used up, retry after Retry-After seconds

The full error table is in Your PBX REST API.

Security#

  • A key is shown once and stored only as a fingerprint; a leaked key is revoked with one button.
  • Only the owner can allow an OAuth connection, and you see which address gets access; an allowed connection can be limited to permissions and locations and revoked at any time.
  • Phone numbers are your customers' personal data: grant call log and recording permissions only to integrations that really need them.
  • Every change made with a key or connection is in the PBX action log under the key's or app's name.
  • Webhooks are signed with a secret: check the signature of every request rather than the sender's address — how, in Call event webhooks.
Was this article helpful?