تمت مراجعة هذا المرجع مقابل الشفرة في 24 أكتوبر 2026. وهو يصف السلوك المنفذ، وليس خطط التطوير. للإعداد من الواجهة، راجع دليل المستخدم.
اتجاهان للطلبات
| الاتجاه | الجهة المستدعية والوجهة | العنوان | الاستخدام |
|---|---|---|---|
| واجهة الإدارة المحلية | برنامجك النصي المحلي يرسل إلى Deskgram | http://127.0.0.1:5000/api/webhooks | إدارة نقاط الاستقبال وقراءة سجل التسليم |
| الويب هوك الصادر | Deskgram يرسل إلى نظامك المستقبل | عنوان URL المحفوظ في نقطة الاستقبال | إرسال الأحداث بطلب POST يحتوي على JSON |
العنوان والمنفذ مثال لخادم backend محلي؛ استخدم عنوان تثبيتك الفعلي. هذه ليست واجهة خادم التراخيص أو خادم MCP، كما أنها ليست طريقتي setWebhook أو getUpdates في Telegram Bot API.
المسارات المحلية الموضحة هنا لا تتضمن تحققًا منفصلًا من Bearer token. استخدمها ضمن بيئة محلية موثوقة، ولا تفتح منفذ backend للإنترنت من أجل إرسال الويب هوك. التسليم الصادر لا يحتاج إلى اتصال وارد إلى حاسوب Deskgram. إذا أضفت بوابة مصادقة خاصة، فتُضبط قواعدها على حدة.
تُعاد الاستجابات المحلية بصيغة JSON. عند إرسال إعدادات بواسطة POST أو PUT، استخدم Content-Type: application/json.
بداية سريعة للواجهة
تستخدم أوامر curl التالية صدفة تدعم علامات الاقتباس المفردة. في PowerShell استخدم curl.exe والتزم بقواعد إصدارك لتمرير JSON. النطاقات والمعرّفات والأسرار في الأمثلة وهمية. النص الروسي داخل JSON قيمة توضيحية، وليس قيمة إلزامية في العقد.
- أنشئ نقطة استقبال معطلة لمراجعة إعداداتها قبل الإرسال التلقائي:
curl -X POST 'http://127.0.0.1:5000/api/webhooks/endpoints' \ -H 'Content-Type: application/json' \ --data '{"name":"CRM: рассылка","url":"https://receiver.example.com/deskgram","secret":"YOUR_SHARED_SECRET","events":["message.sent","message.failed","lead.reply_received"],"module_filter":["spam_pm"],"payload_template":"deskgram","enabled":false}'- اقرأ endpoint.id من الاستجابة. بافتراض المعرّف التوضيحي 12، أرسل الاختبار:
curl -X POST 'http://127.0.0.1:5000/api/webhooks/endpoints/12/test'- افحص success وdelivery.responsestatuscode وdelivery.response_body، ثم تحقق من الاستلام الفعلي في نظامك. الاختبار لا يحتوي على عميل محتمل حقيقي، وقد يرفضه تحقق CRM التجاري.
- فعّل النقطة من الواجهة، أو أرسل إعداداتها كاملة بواسطة PUT مع enabled: true. لا ترسل enabled وحده؛ PUT ليس تحديثًا جزئيًا.
- نفّذ إجراءً فعليًا قصيرًا يطابق الحدث المختار، وافحص السجل:
curl 'http://127.0.0.1:5000/api/webhooks/deliveries?endpoint_id=12&limit=20'كائن endpoint
حقول الإنشاء والتحديث
تستخدم POST وPUT النموذج نفسه.
| الحقل | النوع | القيمة الافتراضية | القواعد |
|---|---|---|---|
name | string | مطلوب | من 1 إلى 120 محرفًا قبل حذف الفراغات الطرفية؛ استخدم اسمًا غير فارغ |
url | string | مطلوب | من 8 إلى 2000 محرف، يبدأ بـ http:// أو https://؛ يُنصح بـ HTTPS |
method | string | POST | لا تُدعم إلا POST |
secret | string أو null | null عند الإنشاء | تُحذف الفراغات الطرفية؛ حذفه من PUT يحفظ السر، وإرسال null أو قيمة فارغة يمحوه |
headers | object بقيم string | {} | ترويسات إضافية للنظام المستقبل، وليست بيانات دخول Deskgram |
events | مصفوفة string | ["task.completed"] | أحداث الكتالوج الستة أو "*"؛ القائمة الفارغة تتحول إلى task.completed |
module_filter | مصفوفة string | [] | الفارغة تعني كل الوحدات؛ مثال ["spam_pm"] |
payload_template | string | deskgram | deskgram أو shortresult أو crmlead أو custom |
payload_mapping | object | {} | إعداد حقول الخرج الموضح لاحقًا |
enabled | boolean | true | يسمح بالإرسال التلقائي للأحداث المطابقة |
timeout_seconds | number | 15 | من 3 إلى 60 ثانية |
في نقاط الاستقبال العادية، تُطبق المهلة على عمليات الشبكة الخاصة بعميل HTTP، وليست حدًا صارمًا لمدة استدعاء API المحلي بالكامل. تنتظر test وretry انتهاء التسليم، بما في ذلك المحاولات التلقائية والفواصل بينها.
تُحوّل أسماء الوحدات إلى أحرف صغيرة ويُستبدل - بـ _. تُزال التكرارات في الأحداث والوحدات. تعني "*" كل الأحداث التي تصل فعلًا إلى هذه الآلية، ولا تضيف تكاملات غير موجودة للوحدات الأخرى.
حقول الاستجابة
يحتوي endpoint على الإعدادات المذكورة، بالإضافة إلى id من نوع integer وhassecret من نوع boolean وcreatedat وupdated_at بتوقيت UTC. يُعاد secret دائمًا بقيمة null، حتى عند وجود سر محفوظ.
تُعيد REST API المحلية قيم headers دون إخفاء. قد تحتوي على رموز وصول للنظام المستقبل؛ تجنب نشر الاستجابة الكاملة في السجلات العامة أو رسائل الدعم.
مثال استجابة الإنشاء:
{ "success": true, "endpoint": { "id": 12, "name": "CRM: рассылка", "url": "https://receiver.example.com/deskgram", "method": "POST", "secret": null, "has_secret": true, "headers": {}, "events": ["message.sent", "message.failed", "lead.reply_received"], "module_filter": ["spam_pm"], "payload_template": "deskgram", "payload_mapping": {}, "enabled": false, "timeout_seconds": 15.0, "created_at": "2026-10-15T10:00:00Z", "updated_at": "2026-10-15T10:00:00Z" }}طرق API
تتضمن المسارات التالية /api. تستخدم العملية المكتملة HTTP 200، بما في ذلك الإنشاء والحذف. endpointid وdeliveryid معرّفان صحيحان للسجلات المقابلة.
GET /api/webhooks/endpoints
قائمة نقاط الاستقبال من الأحدث إلى الأقدم بحسب وقت الإنشاء، دون معاملات ترقيم صفحات. الاستجابة {"endpoints": [...]} وكل عنصر كائن endpoint. القائمة الفارغة {"endpoints": []}.
POST /api/webhooks/endpoints
إنشاء نقطة استقبال وفق النموذج أعلاه. الاستجابة {"success": true, "endpoint": {...}}.
إذا لم ترسل enabled، تصبح النقطة مفعلة فورًا. أرسل false صراحةً أثناء الإعداد الأولي.
PUT /api/webhooks/endpoints/{endpoint_id}
تحديث نقطة الاستقبال. يتطلب name وurl وجميع الإعدادات الحالية التي تريد الاحتفاظ بها. تعود الحقول غير المرسلة إلى قيمها الافتراضية، باستثناء secret.
لا تعِد إرسال كائن الاستجابة كما هو: القيمة secret: null ستزيل السر المحفوظ. احذف المفتاح secret من الطلب للاحتفاظ بالسر. أما إرساله صراحةً بقيمة null أو سلسلة فارغة فيمحو السر.
مثال التفعيل مع الاحتفاظ بالسر:
{ "name": "CRM: рассылка", "url": "https://receiver.example.com/deskgram", "method": "POST", "headers": {}, "events": ["message.sent", "message.failed", "lead.reply_received"], "module_filter": ["spam_pm"], "payload_template": "deskgram", "payload_mapping": {}, "enabled": true, "timeout_seconds": 15}الاستجابة {"success": true, "endpoint": {...}}. عند غياب نقطة الاستقبال تُعاد HTTP 404.
DELETE /api/webhooks/endpoints/{endpoint_id}
حذف نقطة الاستقبال دون جسم طلب. الاستجابة {"success": true, "endpoint_id": 12}. عدم وجودها يعطي HTTP 404.
يبقى سجل التسليم. الحذف لا يلغي إرسالًا بدأ بالفعل، ولا يمكن إعادة محاولة سجل بعد حذف نقطة الاستقبال الخاصة به.
POST /api/webhooks/endpoints/{endpoint_id}/test
إرسال اختبار إلى النقطة المحددة فقط. لا يحتاج جسم طلب ولا يقبل payload اختباريًا اعتباطيًا.
يعمل الاختبار الصريح حتى مع نقطة معطلة، بصرف النظر عن الاشتراك في الأحداث ومرشح الوحدات. يُطبق mapping الحالي، وتعود الاستجابة بعد انتهاء الإرسال والمحاولات التلقائية.
مثال رفض النظام المستقبل للتنسيق القياسي بواسطة HTTP 403:
{ "success": false, "delivered": 0, "delivery_id": 45, "status": "error", "delivery": { "id": 45, "endpoint_id": 12, "event_type": "webhook.test", "task_id": null, "status": "error", "attempts": 3, "response_status_code": 403, "response_body": "Forbidden", "error": "HTTP 403", "created_at": "2026-10-15T10:01:00Z", "updated_at": "2026-10-15T10:01:07Z", "delivered_at": null, "request_payload": { "schema_version": "1.0", "event": "webhook.test", "occurred_at": "2026-10-15T10:01:00Z", "source": "deskgram", "test": true, "endpoint": {"id": 12, "name": "CRM: рассылка"} }, "source_payload": { "schema_version": "1.0", "event": "webhook.test", "occurred_at": "2026-10-15T10:01:00Z", "source": "deskgram", "test": true, "endpoint": {"id": 12, "name": "CRM: рассылка"} } }}تبقى حالة API المحلية هي HTTP 200. الرمز 403 خاص بالنظام المستقبل ويظهر داخل delivery. عند النجاح تُعاد success: true وdelivered: 1 وstatus: "success".
إذا لم تُنشأ عملية تسليم، فقد تكون delivery_id وdelivery بقيمة null مع success: false. نقطة استقبال غير موجودة تعطي HTTP 404 محلية.
GET /api/webhooks/deliveries
قائمة التسليم من الأحدث إلى الأقدم بحسب الإنشاء.
| معامل query | النوع | الافتراضي | المعنى |
|---|---|---|---|
endpoint_id | integer | غير محدد | معرّف نقطة الاستقبال |
event_type | string | غير محدد | اسم الحدث المطابق تمامًا، مثل message.failed |
status | string | غير محدد | pending أو retrying أو success أو error |
limit | integer | 100 | من 1 إلى 500 سجل |
الاستجابة {"deliveries": [...]}. كل عنصر كائن تسليم دون requestpayload أو sourcepayload. لا توجد offset أو cursor أو قيمة للعدد الإجمالي.
GET /api/webhooks/deliveries/{delivery_id}
تفاصيل تسليم تتضمن requestpayload وsourcepayload. الاستجابة {"delivery": {...}}. عند غياب السجل تُعاد HTTP 404.
POST /api/webhooks/deliveries/{delivery_id}/retry
إعادة محاولة يدوية لسجل حالته error. لا يحتاج جسم طلب. ينشئ سجلًا جديدًا وينتظر انتهاء محاولاته. مسموح أيضًا عندما تكون نقطة الاستقبال معطلة.
تحتوي الاستجابة على success من نوع boolean وoriginaldeliveryid من نوع integer وstatus من نوع string وكائن delivery الجديد كاملًا. تختلف id وX-Deskgram-Delivery-Id عن الأصل، ولا يُستبدل السجل القديم. فشل المستقبل يعود محليًا بـ HTTP 200 مع success: false.
HTTP 400 تعني أن الأصل ليس error أو أن إعادة محاولته اليدوية جارية في العملية الحالية. HTTP 404 تعني غياب سجل التسليم أو نقطة الاستقبال.
GET /api/webhooks/events
كتالوج الأحداث الستة مع تسميات الواجهة. يحتفظ المثال بالتسميات الروسية التي تعيدها API فعلًا؛ ترجمة الوثيقة لا تغير قيمها.
{ "events": [ {"event": "task.completed", "label": "Задача завершена"}, {"event": "task.failed", "label": "Задача завершилась ошибкой"}, {"event": "task.cancelled", "label": "Задача остановлена"}, {"event": "lead.reply_received", "label": "Получен ответ лида"}, {"event": "message.sent", "label": "Сообщение отправлено"}, {"event": "message.failed", "label": "Ошибка отправки сообщения"} ]}يُرسل webhook.test بطريقة الاختبار المنفصلة ولا يدخل كتالوج الاشتراكات. تقبل الإعدادات "*"، لكنه أيضًا لا يظهر في الكتالوج.
كائن delivery
| الحقل | النوع | الوصف |
|---|---|---|
id | integer | معرّف التسليم في قاعدة البيانات المحلية |
endpoint_id | integer | معرّف النقطة، حتى لو حُذفت لاحقًا |
event_type | string | الحدث بصرف النظر عن mapping الخارجي |
task_id | string أو null | معرّف المهمة إن توفر |
status | string | pending أو retrying أو success أو error |
attempts | integer | عدد المحاولات التلقائية المنفذة |
responsestatuscode | integer أو null | آخر حالة HTTP؛ قد تكون null عند فشل الشبكة |
response_body | string أو null | آخر استجابة بعد اقتطاعها؛ قد تكون null عند فشل الشبكة |
error | string أو null | رسالة تشخيص، وليست حقل خطأ تجاري من CRM |
createdat, updatedat | string | أوقات UTC بصيغة ISO 8601 تنتهي بـ Z |
delivered_at | string أو null | وقت التسليم الناجح |
request_payload | object | JSON بعد mapping؛ في التفاصيل/test/retry فقط |
source_payload | object | الحدث الأصلي قبل mapping؛ قد يكون {} في السجلات القديمة؛ في التفاصيل/test/retry فقط |
في النقل العادي، يُحتفظ بما لا يزيد على 2000 محرف من الاستجابة. يحد النقل المحمي الخاص بـ MCP أيضًا عدد البايتات المقروءة. السجل ليس تتبع HTTP كاملًا؛ لا يحفظ ترويسات الطلب ولا كل استجابة وسيطة لكل محاولة.
الأحداث وJSON الصادر
الأمثلة تستخدم payload_template: "deskgram". يغير mapping البنية الخارجية، لكن X-Deskgram-Event يبقى اسم الحدث.
أحداث انتهاء المهام
| الحدث | المعنى |
|---|---|
task.completed | انتهى تنفيذ المهمة؛ لا يضمن نجاح كل إجراء داخلها |
task.failed | حالة خطأ نهائية |
task.cancelled | توقفت المهمة أو أُلغيت |
{ "schema_version": "1.0", "event": "task.completed", "occurred_at": "2026-10-15T10:05:00Z", "source": "deskgram", "task": { "task_id": "12345", "task_name": "Тестовая рассылка", "module_name": "spam_pm", "status": "completed", "created_at": "2026-10-15T10:04:00Z", "completed_at": "2026-10-15T10:05:00Z", "accounts_count": 1, "params": {}, "statistics": {}, "result": {} }}تعتمد params وstatistics وresult على الوحدة، ولا توجد بنية موحدة للعدادات في كل المهام. قد تكون taskname وmodulename وcreated_at بقيمة null. تحافظ failed/cancelled على عائلة البنية، مع تغيير الحدث والحالة والنتائج المتاحة.
أحداث الرسائل المباشرة
حاليًا ترتبط message.sent وmessage.failed وlead.replyreceived بوحدة spampm. اختيار مرشح لوحدة أخرى لا ينشئ مصدر أحداث جديدًا.
مثال رسالة مرسلة:
{ "schema_version": "1.0", "event": "message.sent", "occurred_at": "2026-10-15T10:04:20Z", "source": "deskgram", "module": "spam_pm", "task": { "task_id": "12345", "campaign_id": "spam_pm:12345", "module_name": "spam_pm" }, "account": {"id": "987654321"}, "lead": { "telegram_user_id": "123456789", "username": "example_client", "raw_identifier": "@example_client" }, "message": { "message_id": 1001, "message_text": "Здравствуйте!", "raw_identifier": "@example_client", "text": "Здравствуйте!", "status": "sent" }}يتوقف محتوى lead وmessage على البيانات المتاحة. قد يغيب الهاتف أو username أو الاسم أو المعرّف أو النص. لربط النص استخدم message.text. الحقل message_text إضافي لمسار إرسال محدد، وليس حقلًا عامًا لكل الأحداث.
في message.failed يحتوي message على error والحالة المتاحين، وقد لا يوجد معرّف لرسالة مرسلة بنجاح. تخطي المستلم أو فشل التعرف عليه لا ينتج هذا الحدث دائمًا.
قد يحتوي message في lead.replyreceived على messageid وtext وmedia_type وdatetime وtimestamp وstatus: "received". يظهر الحدث فقط عندما يستقبل معالج نشط الرد فعلًا. إنشاء webhook لا يشغل مراقبة دائمة للحسابات ولا يضمن تلقي الردود بعد انتهاء المهمة.
message.sent لا يؤكد قراءة المستلم. تعامل مع المعرّفات كقيم غير شفافة: معرّفات المهمة والحساب ومستخدم Telegram سلاسل نصية؛ message_id معين قد يكون رقمًا.
حدث الاختبار
يتضمن schemaversion وevent: "webhook.test" وoccurredat وsource وtest: true وendpoint: {id, name}. المثال الكامل موجود في استجابة طريقة test.
لا يحتوي على task أو lead أو account أو message. mapping الذي يعتمد فقط على مصادر lead ينتج {}.
ربط الحقول
يرسل deskgram الحدث الأصلي كاملًا ويتجاهل payload_mapping. اختر تنسيقًا آخر لتقليل البيانات المرسلة.
للتنسيقات shortresult وcrmlead وcustom، يوصى بالشكل الصريح التالي:
{ "fields": [ {"target": "event", "source": "event", "enabled": true}, {"target": "contact.telegram_id", "source": "lead.telegram_user_id", "enabled": true}, {"target": "contact.username", "source": "lead.username", "enabled": true}, {"target": "comment", "source": "message.text", "enabled": true}, {"target": "status", "source": ["message.status", "task.status"], "enabled": true} ]}ضع الكائن كله في payload_mapping. target هو مسار الحقل عند المستقبل، وsource مساره في حدث Deskgram الأصلي. ليست هذه قيمًا ثابتة ولا تعبيرات قابلة للتنفيذ.
نتيجة مثال message.sent:
{ "event": "message.sent", "contact": {"telegram_id": "123456789", "username": "example_client"}, "comment": "Здравствуйте!", "status": "sent"}القواعد:
- النقطة في target تنشئ كائنات متداخلة. تجنب مسارات متعارضة مثل contact وcontact.username معًا.
- يقرأ source مفاتيح الكائنات بالفواصل النقطية. لا يدعم فهارس المصفوفات أو قوالب
{{...}}. - القيمة الغائبة أو null لا تُضاف. المصدر المفرد يحفظ 0 وfalse والسلسلة الفارغة بنوع JSON الأصلي.
- قائمة المصادر تختار أول قيمة ليست null أو سلسلة أو قائمة أو كائنًا فارغًا. تُدعم أيضًا السلسلة
"message.status|task.status". - enabled: false يستبعد الحقل؛ غياب enabled يعني تضمينه.
{"fields": []}أو تعطيل جميع الحقول ينتج{}دون الرجوع للحدث الكامل.- payloadmapping: {} يستخدم الحقول المدمجة في shortresult/crm_lead، بينما custom ينتج {}. fields الصريحة تثبت العقد المطلوب.
shortresult المدمج يستخدم المتاح من event وoccurredat وtaskid وmodule وstatus وlead وmessage وerror. crmlead المدمج يستخدم event وoccurredat وtaskid وaccountid وtelegramuserid وusername وphone وfirstname وlastname وrawidentifier وmessageid وmessagetext وmessagestatus وmessageerror.
قد تحفظ الواجهة قائمة fields خاصة قابلة للتعديل لأحد القوالب. الإعدادات المحفوظة للنقطة هي التي تحدد المحتوى الفعلي، لا اسم القالب وحده.
ترويسات الطلب الصادر
| الترويسة | القيمة |
|---|---|
Content-Type | application/json |
User-Agent | Deskgram-Webhooks/1.0 |
X-Deskgram-Delivery-Id | معرّف سجل التسليم كسلسلة |
X-Deskgram-Event | اسم الحدث |
x-secret | السر المشترك إن ضُبط |
X-Deskgram-Webhook-Secret | السر المشترك نفسه |
X-Deskgram-Signature | توقيع sha256= عند وجود سر |
السر ليس مفتاح HMAC فقط؛ يُرسل أيضًا في ترويستين. استخدم HTTPS ولا تكتب هذه القيم في سجلات عامة.
لا يمكن لـ headers استبدال Content-Type أو User-Agent أو Delivery-Id أو Event، ولا الترويسات الثلاث المرتبطة بالسر عند ضبطه، بغض النظر عن حالة الأحرف. يمكن إضافة ترويسات أخرى، مثل Authorization الخاص بالمستقبل.
التحقق من التوقيع
الخوارزمية HMAC-SHA256(secretutf8, rawrequest_body). تحتوي الترويسة على sha256= ثم digest بالنظام الست عشري بأحرف صغيرة.
يشمل التوقيع البايتات نفسها التي أُرسلت. يُرمّز JSON بـ UTF-8 دون تحويل النص غير ASCII إلى escape، مع ترتيب المفاتيح وفواصل بلا فراغات. استخدم جسم HTTP الخام، لا JSON جرى تحليله وإعادة تسلسله.
مثال Python بالمكتبة القياسية فقط:
import hashlibimport hmacdef verify_deskgram_signature(raw_body: bytes, signature: str, secret: str) -> bool: if not secret or not signature: return False expected = "sha256=" + hmac.new( secret.encode("utf-8"), raw_body, hashlib.sha256 ).hexdigest() try: return hmac.compare_digest(expected, signature) except TypeError: return Falseمرر البايتات الخام وترويسة X-Deskgram-Signature والسر المحفوظ عند المستقبل. عند فشل التحقق لا تنفذ الإجراء التجاري. حمّل السر من إعدادات محمية، ولا تثق مباشرةً بقيمة x-secret الواردة.
لا يمنع التوقيع وحده إعادة إرسال جسم صحيح التوقيع. يلزم منطق لدى المستقبل لفحص العمر وإزالة التكرار. Delivery-Id ليس ضمن الجسم الموقع. تُحذف الفراغات الطرفية للسر؛ استخدم سرًا ASCII غير فارغ بلا فراغات طرفية وبطول لا يتجاوز 1000 محرف.
المحاولات وحدود الضمان
- النجاح فقط HTTP 200–299. لا تُتبع 3xx. يظل HTTP 200 مع خطأ تجاري في JSON نجاحًا للنقل.
- حتى ثلاث محاولات تلقائية، بفاصل يقارب ثانيتين ثم أربع ثوانٍ قبل الثانية والثالثة. تُعاد أخطاء الشبكة وHTTP بما فيها 4xx، ولا تُعالج Retry-After بصورة منفصلة.
- تستخدم المحاولات التلقائية الجسم وDelivery-Id نفسيهما. يجب أن يتحمل المستقبل الطلب المكرر دون تكرار إجراء أُنجز.
- تستخدم retry اليدوية URL والسر وheaders الحالية. عند وجود sourcepayload يُطبق mapping الحالي على الأصل؛ السجلات القديمة دونه تعيد requestpayload المحفوظ دون mapping ثانٍ.
- retry اليدوية تنشئ Delivery-Id جديدًا. للحد من تكرار العمل، استخدم أيضًا معرّفات المهمة/الحساب/الرسالة ونوع الحدث بما يناسب السيناريو.
- Delivery-Id فريد ضمن قاعدة بيانات محلية واحدة، لا كل تثبيتات Deskgram. ميّز المرسلين إذا كان لديك أكثر من مصدر.
- لا يوجد ضمان exactly-once أو ترتيب بين أحداث مختلفة أو استعادة تلقائية للطابور بعد توقف العملية. سجل pending/retrying المقطوع لا يعني أنه سيُستأنف عند التشغيل.
- تعطيل النقطة يمنع اختيارها لأحداث تلقائية جديدة، لكنه لا يلغي إرسالًا بدأ. test/retry الصريحتان تستطيعان الإرسال لنقطة معطلة.
تسلسل استقبال مناسب: تحقق من التوقيع، احفظ الحدث بشكل موثوق أو ضعه بطابورك، أعد 2xx، ثم نفذ المعالجة الطويلة على حدة.
أخطاء API
| HTTP المحلي | الحالة |
|---|---|
| 200 | العملية مكتملة؛ في test/retry افحص success وdelivery أيضًا |
| 400 | طريقة/تنسيق/حدث غير مدعوم، URL دون http(s)، retry غير صالحة |
| 404 | غياب النقطة أو السجل، أو حذف نقطة التسليم الأصلي |
| 422 | فشل تحقق الجسم أو الأنواع أو نطاق limit/timeout |
مثال خطأ؛ قد يبقى نص الخادم بالروسية:
{"detail": "Webhook endpoint не найден"}في أخطاء التحقق قد تكون detail مصفوفة تشخيص FastAPI بدل سلسلة. فشل قاعدة البيانات أو backend قد يسبب خطأ خادم أيضًا؛ وهذا منفصل عن استجابة CRM الخارجية.
الفروق عن MCP
MCP واجهة إدارة منفصلة لوكيل ذكاء اصطناعي، وليست اسمًا آخر لـ REST API هذه. راجع اتصال MCP.
| الخاصية | REST المحلي | أدوات MCP |
|---|---|---|
| نقطة جديدة | enabled=true افتراضيًا | معطلة افتراضيًا |
| المعاينة | الطلب ينفذ فعلًا | الإنشاء والتعديل dry-run افتراضيًا بحسب إعدادات MCP |
| التحديث | PUT كامل باستثناء قاعدة secret | تحديث جزئي |
| عنوان المستقبل | http(s)، لا تنشر API المحلية | HTTPS عام فقط مع حماية شبكة |
| المهلة | 3–60 ثانية | 3–30 ثانية |
| القراءة | URL وقيم headers وتفاصيل payload كاملة | دون أسرار أو قيم headers أو أجسام تسليم كاملة |
النقطة المنشأة أو المأخوذة للإدارة بفعل MCP حقيقي ينطبق عليها تحتفظ بقواعد الشبكة المحمية في الإرسال اللاحق، بما فيه الإرسال من الواجهة. PUT عادي لا يزيل هذا الوضع. القراءة أو dry-run أو التعطيل أو الحذف لا تنقل نقطة قديمة بذاتها إلى السياسة الجديدة.
مصادر العقد
لصيانة الوثيقة: نموذج REST والمسارات web/routes/api/webhooks.py؛ الأحداث والتوقيع والمحاولات web/webhookdispatcher.py؛ البيانات الحية functions/functions/spampm/crmintegration.py؛ النقل المحمي web/webhooknetwork.py؛ MCP web/mcp/webhooks.py. هذه مسارات مستودع للمطورين؛ إعداد الميزة لا يتطلب الوصول إلى الشفرة.