تصفّح الأقسام

الـ Webhooks

يصل طلب HTTP إلى خادمك لحظة تغيّر محادثة أو رسالة أو جهة اتصال، وتتحقّق أنه منّا.

في هذا المقال

الـ Webhook يرسل طلب POST إلى رابط على خادمك كلما وقع حدث اخترته في مساحة عملك، مثل رسالة جديدة. بهذا لا تحتاج أن تسأل الـ API كل قليل عن الجديد.

أضف Webhook

تحتاج دور المدير.

  1. افتح الإعدادات ثم خيارات الربط.
  2. في بطاقة Webhook (1) اضغط تهيئة (2).
بطاقة Webhook في صفحة خيارات الربط، مع تحديد البطاقة وزر «تهيئة»
  1. اضغط إضافة webhook جديد.
  2. اكتب رابط Webhook (1)، ويجب أن يكون عنوان https عاماً على خادمك.
  3. اكتب إن شئت اسم الويب هوك (2) لتميّز كل Webhook عن غيره.
  4. تحت الأحداث (3) اختر الأحداث التي تريدها.
  5. اضغط إنشاء webhook (4).
  6. يظهر المفتاح السري الخاص به. انسخه إلى إعدادات خادمك ثم اضغط تم. تجده لاحقاً في نموذج تعديل الـ Webhook.
نموذج «إضافة webhook جديد» وعليه أرقام: رابط Webhook، واسم الويب هوك، وقائمة الأحداث، وزر «إنشاء webhook»

الأحداث

الاسم الذي يصل في الحقل event، واسمه في النموذج:

  • conversation_created: تم إنشاء المحادثة
  • conversation_status_changed: تم تغيير حالة المحادثة (مفتوحة، محلولة، معلّقة، مؤجّلة)
  • conversation_updated: تم تحديث المحادثة (مثل الوسوم أو الموظف المسؤول أو السمات)
  • message_created: تم إنشاء رسالة (الرسائل الواردة والصادرة، والملاحظات الخاصة ومعها "private": true؛ سطور النشاط لا تُرسل)
  • message_updated: تم تحديث الرسالة (مثل تغيّر حالة التسليم)
  • webwidget_triggered: أداة الدردشة المباشرة مفتوحة من قبل المستخدم
  • contact_created: إنشاء جهة اتصال
  • contact_updated: تحديث جهة اتصال
  • conversation_typing_on وconversation_typing_off: بدء الكتابة في محادثة، وإيقاف الكتابة في محادثة

ماذا يصلك؟

المحتوى JSON، ويُرسل مع Content-Type: application/json. فيه دائماً event وكائن account، والباقي حسب الحدث. مثال مختصر لـ message_created:

{
  "event": "message_created",
  "id": 9876,
  "content": "وين طلبي؟",
  "message_type": "incoming",
  "private": false,
  "created_at": "2026-10-29T08:15:02Z",
  "account": { "id": 12, "name": "My Store" },
  "inbox": { "id": 29, "name": "Store WhatsApp" },
  "sender": { "id": 42, "name": "Sara", "phone_number": "+966500000000" },
  "conversation": { "id": 123, "status": "open", "labels": [], "meta": { "assignee": null } }
}
  • conversation.id هو الرقم الذي يظهر في صندوق الوارد، نفسه الذي يستخدمه الـ API.
  • account.id هنا هو الرقم التسلسلي لمساحة العمل، لا معرّف acc_ الذي في الرابط.
  • أحداث …_updated وconversation_status_changed تضيف changed_attributes، وفيها القيمة السابقة والحالية لكل حقل تغيّر.

تحقّق من التوقيع

كل طلب يحمل ثلاث ترويسات:

  • X-Hadir-Delivery: معرّف فريد لهذا الإرسال.
  • X-Hadir-Timestamp: وقت الإرسال بثواني يونكس.
  • X-Hadir-Signature: sha256= ثم قيمة HMAC SHA256 بالصيغة الست عشرية لـ: الوقت، ثم نقطة، ثم المحتوى الخام كما هو، بمفتاح الـ Webhook السري.

احسب القيمة نفسها على خادمك من المحتوى الخام قبل تحليله، وقارن. في Node.js:

const crypto = require('crypto');

function isFromHadir(rawBody, headers, secret) {
  const ts = headers['x-hadir-timestamp'];
  const expected = 'sha256=' + crypto.createHmac('sha256', secret)
    .update(`${ts}.${rawBody}`).digest('hex');
  const given = String(headers['x-hadir-signature'] || '');
  const fresh = Math.abs(Date.now() / 1000 - Number(ts)) < 300;
  return fresh && given.length === expected.length &&
    crypto.timingSafeEqual(Buffer.from(given), Buffer.from(expected));
}

في PHP: hash_equals('sha256=' . hash_hmac('sha256', $ts . '.' . $rawBody, $secret), $signature). رفض الأوقات القديمة، كما في المثال، يمنع أحداً من إعادة إرسال طلب التقطه.

المهلة وإعادة المحاولة

  • أمام خادمك 5 ثوانٍ للرد. ردّ بأي رمز 2xx بسرعة، وأكمل العمل الطويل بعدها.
  • الإرسال الذي تنتهي مهلته أو يأتيه رد غير 2xx لا يُعاد، ولوحة التحكم لا تعرض الإرسالات الفاشلة. إن كان فوات أي حدث مشكلة عندك، راجع الـ API بين حين وآخر أيضاً.
  • قد تصل الأحداث بغير ترتيبها. اعتمد على created_at والمعرّفات، لا على ترتيب الوصول.
ملاحظة: تبقى الـ Webhooks تعمل حتى لو صارت باقتك لاحقاً لا تشمل الـ API؛ المرفوض فقط هو إضافتها أو تعديلها. احذف ما لا تحتاجه من الصفحة نفسها.

هل أفادك المقال؟

شكراً لملاحظتك ✓

لا تكتب بيانات شخصية

وصلتنا ملاحظتك، وسنراجع المقال على ضوئها.

لمعرفة كيف يستخدم هذا الموقع ملفات تعريف الارتباط، راجع سياسة الخصوصية