API وMCP لمقسمك الهاتفي
مقسمك الهاتفي Cenaly مفتوح لبرامجك ومساعدي الذكاء الاصطناعي:
- CRM، نظام محاسبي، موقعك الخاص — REST API: سجل المكالمات، التسجيلات والنصوص، اتصال بنقرة، التحويلات الداخلية، إعادة التوجيه، قواعد المكالمات؛
- Claude Code، Claude Desktop، Cursor — خادم MCP عن بُعد عبر مفتاح؛
- ChatGPT، claude.ai، Perplexity، Cursor وVS Code — الخادم نفسه بدون مفتاح: تسجّل الدخول إلى حسابك وتسمح بالوصول (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، مساعد الذكاء الاصطناعي، قراءة فقط، الكل |
recordings:read |
رابط تسجيل المحادثة (10 دقائق) والنص | CRM، مساعد الذكاء الاصطناعي، قراءة فقط، الكل |
calls:dial |
اتصال بنقرة: يرن هاتف الموظف أولًا، وبعد الرد يطلب المقسم الرقم | CRM، مساعد الذكاء الاصطناعي، الكل |
extensions:read |
التحويلات الداخلية، المجموعات، إعادة التوجيه، «عدم الإزعاج» | CRM، مساعد الذكاء الاصطناعي، قراءة فقط، الكل |
extensions:write |
تغيير إعادة التوجيه الشخصية و«عدم الإزعاج» | مساعد الذكاء الاصطناعي، الكل |
presence:read |
من متفرغ، ومن يرن، ومن يتحدث | مساعد الذكاء الاصطناعي، قراءة فقط، الكل |
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: أضف خادم MCP عن بُعد (HTTP) بالعنوان 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)، أو «برنامج على هذا الحاسوب» أو تحذير «عنوان غير مألوف». الاسم الذي أرسله التطبيق معروض بخط صغير — يمكن لأي أحد كتابته؛
- الصلاحيات — المؤشَّر عليها ما يطلبه التطبيق (وإذا طلب «كل شيء» يُؤشَّر على مجموعة «مساعد الذكاء الاصطناعي»)؛ والصلاحيات «بمربع اختيار منفصل فقط» لا تُؤشَّر مسبقًا أبدًا؛
- الفروع — الكل أو المختارة.
«السماح» يعيدك إلى المساعد، فيرى فورًا أدوات المقسم. يظهر الاتصال في الاتصالات الهاتفية → 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_…" }
}
}
}
تظهر الإدراجات الجاهزة مع مفتاحك مباشرة بعد إنشاء المفتاح. لا يرى مساعد الذكاء الاصطناعي إلا الأدوات التي يسمح بها المفتاح، ويمكنه الإجابة عن «من اتصل اليوم ولم يصل»، و«أعد الاتصال بهذا الضيف من هاتف آنا»، و«فعّل لي التحويل إلى الجوال».
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 (معرّف الحدث أو الوقت)، 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 — يصلح أي عميل يدعمها:
- الطلب إلى MCP دون رمز مميز يعيد 401 مع الترويسة
WWW-Authenticate: Bearer resource_metadata="https://api.cenaly.com/.well-known/oauth-protected-resource/pbx-api/mcp". - تشير بيانات الموارد الوصفية (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). - التسجيل الديناميكي للعميل (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. - رمز التفويض مع PKCE (
S256فقط):GET /pbx-api/oauth/authorize→ نافذة دخول المالك وموافقته → الإرجاع إلى عنوانك معcodeوstateوiss. المعاملresource— عنوان خادم MCP. - الرموز المميزة:
POST /pbx-api/oauth/token. الرمز يُستخدم مرة واحدة ويعيش دقيقتين (يُبطلهcode_verifierغير الصحيح)؛ رمز الوصول — ساعة واحدة؛ رمز التحديث — 90 يومًا، ويُصدر عند كل تحديث رمز جديد ويتوقف عمل السابق. - الإبطال:
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 إلا المالك، ويظهر إلى أي عنوان يُمنح الوصول؛ ويمكن تقييد الاتصال المصرَّح به بالصلاحيات والفروع وإلغاؤه في أي لحظة.
- أرقام الهواتف بيانات شخصية لعملائك: امنح صلاحيات السجل والتسجيلات فقط للتكاملات التي تحتاجها فعلًا.
- كل التغييرات عبر المفتاح أو الاتصال — في سجل إجراءات المقسم مع اسم المفتاح أو التطبيق.