Kendi santralinizin API'si ve MCP'si
Kendi santraliniz Cenaly, programlarınıza ve yapay zeka asistanlarınıza açıktır:
- CRM, muhasebe sistemi, kendi siteniz — REST API: çağrı günlüğü, kayıtlar ve deşifreler, tek tıkla arama, dahili numaralar, yönlendirme, arama kuralları;
- Claude Code, Claude Desktop, Cursor — anahtarla uzak MCP sunucusu;
- ChatGPT, claude.ai, Perplexity, Cursor ve VS Code — aynı MCP sunucusu anahtarsız: kendi hesabınıza giriş yapar ve erişim izni verirsiniz (OAuth).
Her şey hesap sahibi adına ve yalnızca onun verdiği yetkilerle çalışır. Her değişiklik, santralin işlem günlüğünde anahtarın veya uygulamanın adıyla görünür.
Adresler#
| Ne | Adres |
|---|---|
| REST API | https://api.cenaly.com/pbx-api/v1 |
| MCP sunucusu (streamable HTTP) | https://api.cenaly.com/pbx-api/mcp |
| Yöntem belgeleri | api.cenaly.com/pbx-api/v1/docs |
| OpenAPI 3.1 tanımı | api.cenaly.com/pbx-api/v1/openapi.json |
| OAuth meta verileri | https://api.cenaly.com/.well-known/oauth-authorization-server/pbx-api |
Anahtar ve yetkiler#
Anahtarı yalnızca hesap sahibi oluşturur: Telefon → API ve MCP → Anahtarlar → Anahtar oluştur. «Santral yöneticisi» rolündeki çalışan anahtarları görmez — anahtar hesap sahibi adına geçerlidir.
cpx_…biçimindeki anahtar yalnızca bir kez gösterilir — oluşturulduktan hemen sonra, bağlantı için hazır eklemelerle birlikte. Bizde yalnızca parmak izi (SHA-256) saklanır, anahtar geri getirilemez — yalnızca yeni bir tane çıkarılabilir.- Anahtar şubelerle (aksi halde gelecektekiler dahil tüm şubeler) ve süreyle (30, 90, 365 gün veya süresiz) sınırlandırılabilir.
- «Yetkiler» anahtarın yetkilerini ve şubelerini anında değiştirir: entegrasyon çalışmaya devam eder, yeni yetkiler bir sonraki istekten itibaren geçerli olur.
- «İptal et» — hemen ve kalıcı olarak: bu anahtarla yapılan bir sonraki istek 401 alır.
- Hesap başına etkin anahtar ve bağlantı sayısı 20'ye kadardır.
Yetkiler hazır bir setle veya onay kutularıyla seçilir:
| Yetki | Ne sağlar | Setler |
|---|---|---|
calls:read |
çağrı günlüğü ve rotasıyla birlikte çağrı kartı | CRM, yapay zeka asistanı, yalnızca okuma, tümü |
recordings:read |
görüşme kaydı bağlantısı (10 dakika) ve deşifre | CRM, yapay zeka asistanı, yalnızca okuma, tümü |
calls:dial |
tek tıkla arama: önce çalışanın telefonu çalar, yanıtlandıktan sonra santral numarayı çevirir | CRM, yapay zeka asistanı, tümü |
extensions:read |
dahili numaralar, gruplar, yönlendirme, «rahatsız etmeyin» | CRM, yapay zeka asistanı, yalnızca okuma, tümü |
extensions:write |
kişisel yönlendirmeyi ve «rahatsız etmeyin» durumunu değiştirme | yapay zeka asistanı, tümü |
presence:read |
kim müsait, kim çalıyor, kim görüşüyor | yapay zeka asistanı, yalnızca okuma, tümü |
reports:read |
dönem için çağrı merkezi metrikleri: hizmet düzeyi, bekleme, yanıtsız, AHT, FCR, CSAT, çağrıları nerede kaybediyoruz, kuyruk, hat ve çalışan bazında kırılımlar | yalnızca okuma, tümü |
routes:read |
numaralar, gelen ve giden kuralları, kural geçmişi | yalnızca okuma, tümü |
routes:write |
arama kuralları oluşturma, değiştirme, silme ve yeniden sıralama, geçmişten geri alma | yalnızca ayrı onay kutusuyla |
config:export |
santral ayarlarını dosya biçiminde dışa aktarma | yalnızca ayrı onay kutusuyla |
config:import |
ayarları tablolardan içe aktarma: önizleme, ardından uygulama | yalnızca ayrı onay kutusuyla |
webhooks:write |
çağrı olayı webhook'ları oluşturma, değiştirme, test etme ve silme | yalnızca ayrı onay kutusuyla |
daynight:write |
şubeyi gün sonuna veya belirli bir tarihe kadar kapatma, açma — telefondan *28 ile aynı |
yalnızca ayrı onay kutusuyla |
Bir şeyi değiştiren veya dakika harcayan yetkiler pencerede amber renkle işaretlenir. Son üç yetki hiçbir sete, «Tümü» dahil, girmez — bunlar yalnızca bilinçli olarak, ayrı onay kutusuyla verilebilir.
ChatGPT, claude.ai, Perplexity, Cursor, VS Code: anahtarsız bağlantı#
Bulut asistanları anahtarı başlığa ekleyemez — MCP sunucusuna OAuth ile bağlanırlar. Anahtar oluşturmak gerekmez.
claude.ai: Ayarlar → Bağlayıcılar → Kendi bağlayıcınızı ekleyin → https://api.cenaly.com/pbx-api/mcp adresini yapıştırın → Bağlan.
ChatGPT: Ayarlar → Uygulamalar ve bağlayıcılar → Gelişmiş → geliştirici modunu açın → Oluştur → https://api.cenaly.com/pbx-api/mcp adresini yapıştırın, kimlik doğrulama — OAuth.
Perplexity: Hesap ayarları → Bağlayıcılar → «+ Kendi bağlayıcınız» → Uzak → https://api.cenaly.com/pbx-api/mcp adresini yapıştırın, kimlik doğrulama — OAuth.
Cursor ve VS Code: https://api.cenaly.com/pbx-api/mcp adresiyle, anahtar başlığı olmadan uzak (HTTP) MCP sunucusu ekleyin — giriş penceresi tarayıcıda açılır. Cursor'da: .cursor/mcp.json → {"mcpServers": {"cenaly-pbx": {"url": "https://api.cenaly.com/pbx-api/mcp"}}}; VS Code'da: «MCP: Add Server» komutu → HTTP.
Ardından asistan Cenaly giriş penceresini açar. Girişten sonra şunları görürsünüz:
- erişimi kim istiyor — uygulama, yanıtın döneceği adresle adlandırılır: «Doğrulanmış bağlayıcı · chatgpt.com» (aynı şekilde — claude.ai, perplexity.ai, vscode.dev, Cursor), «Bu bilgisayardaki program» veya «Bilinmeyen adres» uyarısı. Uygulamanın gönderdiği ad küçük yazıyla gösterilir — onu herkes yazabilir;
- yetkiler — uygulamanın istedikleri işaretlenir (eğer «her şeyi» istiyorsa, «Yapay zeka asistanı» seti işaretlenir); «yalnızca ayrı onay kutusuyla» verilen yetkiler hiçbir zaman önceden işaretlenmez;
- şubeler — tümü veya seçilenler.
«İzin ver» sizi asistana geri döndürür ve asistan santralin araçlarını hemen görür. Bağlantı Telefon → API ve MCP → Anahtarlar bölümünde OAuth etiketi ve uygulama adresiyle bir satır olarak görünür — yetkiler de orada değiştirilir ve erişim orada iptal edilir. Aynı uygulamanın yeniden bağlanması, ikinci bir bağlantı oluşturmak yerine yetkilerini günceller.
Bağlantılara yalnızca hesap sahibi izin verebilir.
Claude Code, Claude Desktop, Cursor: anahtarla bağlantı#
Claude Code — tek komutla:
claude mcp add --transport http telephony https://api.cenaly.com/pbx-api/mcp --header "Authorization: Bearer cpx_…"
Claude Desktop, Cursor (.cursor/mcp.json) ve ayar dosyası olan diğer istemciler:
{
"mcpServers": {
"telephony": {
"type": "http",
"url": "https://api.cenaly.com/pbx-api/mcp",
"headers": { "Authorization": "Bearer cpx_…" }
}
}
}
Anahtarınızla hazır ekleme blokları, anahtar oluşturulduktan hemen sonra gösterilir. Asistan yalnızca anahtarın izin verdiği araçları görür ve "bugün kim aradı ve ulaşamadı", "bu misafiri Anna'nın telefonundan geri arayın", "bana cep telefonuna yönlendirmeyi aç" sorularını yanıtlayabilir.
REST API#
Anahtar Authorization: Bearer <ключ> başlığında (veya X-Api-Key). Anahtarın tek şubesi varsa location parametresini göndermeniz gerekmez; birden fazlaysa 400 location_required yanıtı bunları listeler.
| Yöntem | Yol | Yetki | Ne yapar |
|---|---|---|---|
| GET | /v1/me |
— | anahtarın yetkileri, şubeleri ve limitleri |
| GET | /v1/locations |
— | anahtarın şubeleri ve bunların santralleri |
| GET | /v1/calls |
calls:read |
çağrı günlüğü: since, until, direction, status (answered, missed, ai), number, extension, limit 100'e kadar, cursor |
| GET | /v1/calls/{id} |
calls:read |
rotasıyla birlikte çağrı: hangi kural devreye girdi, kimin telefonu çaldı, kim yanıtladı |
| GET | /v1/calls/{id}/recording |
recordings:read |
10 dakika geçerli kayıt bağlantısı |
| GET | /v1/calls/{id}/transcript |
recordings:read |
görüşmenin dökümü ve özeti |
| POST | /v1/dial |
calls:dial |
tek tıkla arama: { "extension": "101", "number": "+995555123456" } |
| GET | /v1/dial/{commandId} |
calls:dial |
tek tıkla aramanın durumu |
| GET | /v1/extensions |
extensions:read |
dahili numaralar, gruplar, yönlendirme, "rahatsız etmeyin" |
| PUT | /v1/extensions/{ext}/forwarding |
extensions:write |
dahili numaranın kişisel yönlendirmesi |
| PUT | /v1/extensions/{ext}/dnd |
extensions:write |
"rahatsız etmeyin": { "on": true } |
| GET | /v1/presence |
presence:read |
şu anda kim müsait |
| GET | /v1/metrics |
reports:read |
dönem için çağrı merkezi metrikleri: from, to (şubenin yerel tarihleri YYYY-MM-DD, varsayılan — son 7 gün), compare (prev, year, prev,year veya boş), sections (metrics,loss,queues,lines,operators,directions,heatmap,daily), callbacks=true — geri arama hızı da eklenir |
| GET | /v1/routes |
routes:read |
numaralar, gelen ve giden kuralları |
| GET | /v1/routes/history |
routes:read |
kural değişikliklerinin geçmişi |
| POST, PUT, DELETE | /v1/routes/inbound…, /v1/routes/outbound… |
routes:write |
çağrı kurallarını tek tek: oluştur, gönderilen alanları değiştir, sil, sırasını değiştir, geri al |
| GET, POST | /v1/config/export, /v1/config/import |
config:export, config:import |
ayarlar dosya biçiminde; yükleme — önce önizleme, sonra uygulama |
| GET | /v1/events |
calls:read |
şubenin 7 günlük çağrı olayları (2000'e kadar): since (olay id'si veya zaman), types, limit (yanıt başına 500'e kadar) |
| GET, POST, PATCH, DELETE | /v1/webhooks… |
webhooks:write |
webhook'lar: listele, oluştur, değiştir, sil; …/rotate-secret, …/test, …/deliveries |
| GET, PUT | /v1/open-closed |
routes:read, daynight:write |
kapalı mı ve ne zamana kadar; gün sonuna kadar kapat { "closed": true }, belirli bir tarihe kadar { "closed": true, "until": "2026-10-05T09:00" } veya aç |
Alanların tam açıklaması dokümantasyon sayfasında ve OpenAPI içinde.
Bugün kim aradı ve ulaşamadı:
curl -H "Authorization: Bearer cpx_…" \
"https://api.cenaly.com/pbx-api/v1/calls?status=missed&since=$(date -u +%Y-%m-%dT00:00:00Z)"
Müşteriyi 101 numaralı dahiliden geri arayın:
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"
Eylül metrikleri, Ağustos ve geçen yılın Eylül ayıyla karşılaştırmalı — kendi BI paneliniz için:
curl -H "Authorization: Bearer cpx_…" \
"https://api.cenaly.com/pbx-api/v1/metrics?from=2026-09-01&to=2026-09-30&compare=prev,year"
Yanıtta metrics — Telefon → Çağrı Günlüğü → Analitik ekranındakiyle aynı rakamlar: gelen, yanıtlanan ve kaçırılan, hizmet düzeyi (eşik ve hedef — kuyruk ayarlarından), ortalama ve en uzun bekleme, kısa görüşmeler hariç terk edilme oranı, AHT, FCR, transfer ve bot oranı, CSAT. compare.prev ve compare.year — önceki dönem ve geçen yılın aynı dönemi için aynı alanlar. Geçen yılla karşılaştırma 400 güne kadar olan dönemler için hesaplanır.
Bir çalışan 15 saniye içinde yanıtlamazsa cep telefonuna yönlendirmeyi açın:
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 araçları#
REST ile aynı işlemler. İstemci yalnızca anahtarın veya bağlantının izin verdiği araçları görür:
| Araçlar | Yetki |
|---|---|
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 |
Sunucu oturum olmadan çalışır (streamable HTTP, JSON-RPC 2.0): initialize, tools/list, tools/call.
Kendi bağlayıcılarınız için OAuth#
Yetkilendirme sunucusu MCP yetkilendirme spesifikasyonuna uyar — bunu destekleyen her istemci uygundur:
- Tokensiz bir MCP isteği,
WWW-Authenticate: Bearer resource_metadata="https://api.cenaly.com/.well-known/oauth-protected-resource/pbx-api/mcp"başlığıyla 401 alır. - Kaynak meta verileri (RFC 9728) yetkilendirme sunucusunu belirtir —
https://api.cenaly.com/pbx-api; bunun meta verileri (RFC 8414) isehttps://api.cenaly.com/.well-known/oauth-authorization-server/pbx-apiadresindedir (ve…/pbx-api/.well-known/openid-configuration). - İstemcinin dinamik kaydı (RFC 7591):
POST /pbx-api/oauth/register. Dönüş adresi yalnızcalocalhost/127.0.0.1(herhangi bir port) veya bilinen bir bağlayıcının adresi olabilir (claude.ai, claude.com, chatgpt.com, chat.openai.com, vscode.dev, www.perplexity.ai, enterprise.perplexity.ai; Cursor için ayrıca tam olarakcursor://anysphere.cursor-mcp/oauth/callback). İstemcinin giriş yöntemi —none(genel istemci),client_secret_postveyaclient_secret_basic. - PKCE ile yetkilendirme kodu (yalnızca
S256):GET /pbx-api/oauth/authorize→ sahibinin giriş ve onay penceresi → adresinizecode,stateveissile dönüş.resourceparametresi — MCP sunucusunun adresidir. - Tokenlar:
POST /pbx-api/oauth/token. Kod tek kullanımlıktır ve 2 dakika geçerlidir (hatalıcode_verifierkodu geçersiz kılar); erişim tokenı — 1 saat; yenileme tokenı — 90 gün, her yenilemede yeni bir tane verilir, önceki çalışmayı durdurur. - İptal:
POST /pbx-api/oauth/revoke(RFC 7009) bağlantıyı tümüyle geçersiz kılar — «API ve MCP» penceresindeki «İptal et» gibi.
Erişim tokenı, anahtarın kabul edildiği her yerde kabul edilir: hem MCP'de hem REST'te, sahibin izin verdiği yetkiler ve şubelerle.
Limitler ve hatalar#
- Anahtar veya bağlantı başına: dakikada 120 istek ve günde 20 000 (REST ve MCP birlikte).
- Tek tıkla arama — ayrıca: dakikada 10 ve günde 300.
- Günlük — istek başına 100 aramaya kadar; santralin şube günlüğünde — son 90 gündeki son 400 arama.
| Kod | Hata | Ne yapmalı |
|---|---|---|
| 401 | api_key_missing, api_key_invalid |
anahtar yok, iptal edilmiş veya süresi dolmuş; OAuth tokenının süresi dolmuş — yenileyin |
| 403 | scope_required |
anahtarın yetkisi yok — «Yetkiler» bölümüne ekleyin |
| 400 | location_required |
anahtarın birden fazla şubesi var — location gönderin |
| 404 | location_not_found |
şube yok veya anahtar başka şubelerle sınırlı |
| 429 | rate_limited |
limit doldu, Retry-After saniye sonra tekrar deneyin |
Çağrı olayları#
Gerçek zamanlı — santral webhook'ları: Telefon → API ve MCP → Webhook'lar veya webhooks:write yetkisine sahip bir anahtarla POST /v1/webhooks. https adresinize her olay için saniyeler içinde bir POST gelir: call.started (başladı: yön, kim, kime, hat), call.ringing (kimde çalıyor — her telefon için bir tane), call.answered (kim yanıtladı), call.transferred (kim kime aktardı), call.ended (sonuç, süre, görüşme, kim yanıtladı). Webhook şubeler ve olay türleriyle sınırlandırılabilir.
{ "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": "Анна" } } }
İmza — X-Cenaly-Signature: t=<unix zamanı>,v1=<"t.gövde" üzerinden webhook gizli anahtarıyla HMAC-SHA256> başlığı. Yeniden hesaplayın, sabit sürede karşılaştırın ve t değeri 5 dakikadan eskiyse reddedin. whsec_… gizli anahtarı bir kez gösterilir; "Yeni gizli anahtar" öncekini hemen geçersiz kılar.
Teslimat — 10 saniye içinde 2xx yanıtı verin. Aksi halde 10 sn, 30 sn, 2, 5, 10, 15 ve 15 dakika aralıklarla yeniden deneriz (8 deneme, yaklaşık bir saat); yeniden deneme aynı id değerini taşır — buna göre kopyaları eleyin. Teslimat günlüğü (yanıt kodu, zaman, deneme) webhook penceresinde ve GET /v1/webhooks/{id}/deliveries ile görülebilir; "Kontrol et" hizmet amaçlı bir webhook.ping gönderir. Adres 3 gün üst üste hiçbir teslimatı kabul etmezse webhook kendiliğinden kapanır: sahibine e-posta gelir, "Webhook'lar" penceresinde "Otomatik olarak kapatıldı" işareti ve "Aç" düğmesi görünür (veya { "enabled": true } ile PATCH /v1/webhooks/{id}).
Kendi sunucunuz olmadan — aynı akış sorgulama ile: GET /v1/events?since=<son olayın id değeri> veya MCP aracı get_call_events (şubenin son 7 gündeki olayları, en fazla 2000; yanıt başına en fazla 500, more: true ise aynı since ile ilerleyin).
Kayıt işlendikten sonra — dökümü ve analizi olan çağrı, «Çağrılar» bölümünde "Webhook" kaynağından webhook ile gelir.
"Açık / kapalı" — { "closed": true } ile PUT /v1/open-closed şubeyi gün sonuna kadar kapatır (telefondan *28 gibi: çağrılar "mesai dışı" kurallarıyla ilerler), false ise açar; GET kapatılıp kapatılmadığını ve kimin kapattığını gösterir. "until" ile — o ana kadar kapalıdır (en fazla 30 gün), sonra kendiliğinden açılır: saat dilimi belirtilmeyen zaman (2026-10-05T09:00) şubenin saat diliminde okunur; false bunu da kaldırır. Yönlendirmede "Kod *28 ile kapat" onay kutusunun işaretli olması gerekir (aksi halde 409).
Güvenlik#
- Anahtar bir kez gösterilir ve bizde yalnızca parmak izi olarak saklanır; sızan bir anahtar tek düğmeyle iptal edilir.
- OAuth bağlantısına yalnızca sahip izin verir ve erişimin hangi adrese gittiği görülür; izin verilen bağlantı yetkiler ve şubelerle sınırlandırılabilir ve her an iptal edilebilir.
- Telefon numaraları müşterilerinizin kişisel verileridir: günlük ve kayıtlar için yetkileri yalnızca gerçekten ihtiyaç duyan entegrasyonlara verin.
- Anahtar veya bağlantı üzerinden yapılan tüm değişiklikler, anahtarın veya uygulamanın adıyla santral işlem günlüğünde yer alır.