Guide

واجهة API للويب هوك في Deskgram 2: الطرق وJSON والتوقيع

مرجع REST API المحلي: نقاط الاستقبال والأحداث وربط الحقول والسجل والمحاولات وHMAC والفروق عن MCP.

settings16 دقائق2026-10-24

Key Takeaways

  • أنشئ نقطة استقبال معطلة لمراجعة إعداداتها قبل الإرسال التلقائي:
  • اقرأ endpoint.id من الاستجابة. بافتراض المعرّف التوضيحي 12، أرسل الاختبار:
  • افحص success وdelivery.response status code وdelivery.response body، ثم تحقق من الاستلام الفعلي في نظامك. الاختبار لا يحتوي على عميل محتمل حقيقي، وقد يرفضه تحقق CRM التجاري.
  • فعّل النقطة من الواجهة، أو أرسل إعداداتها كاملة بواسطة PUT مع enabled: true. لا ترسل enabled وحده؛ PUT ليس تحديثًا جزئيًا.

نظرة عامة على وحدة الويب هوك

تمت مراجعة هذا المرجع مقابل الشفرة في 24 أكتوبر 2026. وهو يصف السلوك المنفذ، وليس خطط التطوير. للإعداد من الواجهة، راجع دليل المستخدم.

اتجاهان للطلبات

الاتجاهالجهة المستدعية والوجهةالعنوانالاستخدام
واجهة الإدارة المحليةبرنامجك النصي المحلي يرسل إلى Deskgramhttp://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 قيمة توضيحية، وليس قيمة إلزامية في العقد.

  1. أنشئ نقطة استقبال معطلة لمراجعة إعداداتها قبل الإرسال التلقائي:
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}'
  1. اقرأ endpoint.id من الاستجابة. بافتراض المعرّف التوضيحي 12، أرسل الاختبار:
curl -X POST 'http://127.0.0.1:5000/api/webhooks/endpoints/12/test'
  1. افحص success وdelivery.responsestatuscode وdelivery.response_body، ثم تحقق من الاستلام الفعلي في نظامك. الاختبار لا يحتوي على عميل محتمل حقيقي، وقد يرفضه تحقق CRM التجاري.
  2. فعّل النقطة من الواجهة، أو أرسل إعداداتها كاملة بواسطة PUT مع enabled: true. لا ترسل enabled وحده؛ PUT ليس تحديثًا جزئيًا.
  3. نفّذ إجراءً فعليًا قصيرًا يطابق الحدث المختار، وافحص السجل:
curl 'http://127.0.0.1:5000/api/webhooks/deliveries?endpoint_id=12&limit=20'

كائن endpoint

حقول الإنشاء والتحديث

تستخدم POST وPUT النموذج نفسه.

الحقلالنوعالقيمة الافتراضيةالقواعد
namestringمطلوبمن 1 إلى 120 محرفًا قبل حذف الفراغات الطرفية؛ استخدم اسمًا غير فارغ
urlstringمطلوبمن 8 إلى 2000 محرف، يبدأ بـ http:// أو https://؛ يُنصح بـ HTTPS
methodstringPOSTلا تُدعم إلا POST
secretstring أو nullnull عند الإنشاءتُحذف الفراغات الطرفية؛ حذفه من PUT يحفظ السر، وإرسال null أو قيمة فارغة يمحوه
headersobject بقيم string{}ترويسات إضافية للنظام المستقبل، وليست بيانات دخول Deskgram
eventsمصفوفة string["task.completed"]أحداث الكتالوج الستة أو "*"؛ القائمة الفارغة تتحول إلى task.completed
module_filterمصفوفة string[]الفارغة تعني كل الوحدات؛ مثال ["spam_pm"]
payload_templatestringdeskgramdeskgram أو shortresult أو crmlead أو custom
payload_mappingobject{}إعداد حقول الخرج الموضح لاحقًا
enabledbooleantrueيسمح بالإرسال التلقائي للأحداث المطابقة
timeout_secondsnumber15من 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_idintegerغير محددمعرّف نقطة الاستقبال
event_typestringغير محدداسم الحدث المطابق تمامًا، مثل message.failed
statusstringغير محددpending أو retrying أو success أو error
limitinteger100من 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

الحقلالنوعالوصف
idintegerمعرّف التسليم في قاعدة البيانات المحلية
endpoint_idintegerمعرّف النقطة، حتى لو حُذفت لاحقًا
event_typestringالحدث بصرف النظر عن mapping الخارجي
task_idstring أو nullمعرّف المهمة إن توفر
statusstringpending أو retrying أو success أو error
attemptsintegerعدد المحاولات التلقائية المنفذة
responsestatuscodeinteger أو nullآخر حالة HTTP؛ قد تكون null عند فشل الشبكة
response_bodystring أو nullآخر استجابة بعد اقتطاعها؛ قد تكون null عند فشل الشبكة
errorstring أو nullرسالة تشخيص، وليست حقل خطأ تجاري من CRM
createdat, updatedatstringأوقات UTC بصيغة ISO 8601 تنتهي بـ Z
delivered_atstring أو nullوقت التسليم الناجح
request_payloadobjectJSON بعد mapping؛ في التفاصيل/test/retry فقط
source_payloadobjectالحدث الأصلي قبل 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-Typeapplication/json
User-AgentDeskgram-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. هذه مسارات مستودع للمطورين؛ إعداد الميزة لا يتطلب الوصول إلى الشفرة.

المتابعة

تنزيل Deskgram 2

الخطوة التالية

Helpful Links