> ## Documentation Index
> Fetch the complete documentation index at: https://docs.thunderphone.com/llms.txt
> Use this file to discover all available pages before exploring further.

# نظرة عامة على Webhooks

> كيفية إرسال ThunderPhone للأحداث في الوقت الفعلي، وكيفية التحقق من التوقيعات، ومقارنة نماذج التسليم القديمة والمعتمدة على نقاط النهاية.

يرسل ThunderPhone طلبات HTTP `POST` إلى خادمك عند حدوث أمور
أثناء مكالمة — بدء مكالمة واردة أو انتهاء مكالمة أو اكتمال
تشغيل تقييم أو إطلاق تنبيه، وغير ذلك. هناك **نموذجا تسليم**:

<CardGroup cols={2}>
  <Card title="نقاط نهاية الويب هوك (موصى بها)" icon="bolt" href="/ar/webhooks/endpoints">
    عناوين URL متعددة، وأسرار لكل نقطة نهاية، وفلاتر أحداث لكل نقطة نهاية،
    وإعادات محاولة تلقائية.
    أدرها عبر `GET/POST/PATCH/DELETE /v1/developer/webhook-endpoints`.
  </Card>

  <Card title="ويب هوك قديم بعنوان URL واحد" icon="link" href="/api-reference/organizations#legacy-single-url-webhook">
    عنوان URL واحد لكل مؤسسة. يحمل أحداث دورة حياة المكالمة، بما في ذلك
    عمليات تبادل الإعدادات **الحاجبة**. يُدار عبر `GET/PUT /v1/webhook`.
  </Card>
</CardGroup>

تُسلَّم أنواع الأحداث العشرة جميعها في [كتالوج الأحداث](/ar/webhooks/events)
عبر نقاط نهاية الويب هوك. تُرسل أحداث دورة حياة المكالمة الستة
(`telephony.incoming`, `telephony.complete`, `telephony.tool`,
`web.incoming`, `web.complete`, `web.tool`) **أيضًا** إلى
الويب هوك القديم ذي عنوان URL الواحد — إذا كان لديك عنوان URL قديم ونقطة
نهاية مطابقة، فستتلقى الحدث عبر **كلا** المسارين. يوجد السلوك الحاجب
(تبادل إعدادات [`telephony.incoming` / `web.incoming`
](/ar/webhooks/call-incoming) و[توجيه الأدوات](/ar/tools/overview)
في وضع الويب هوك) حصريًا في المسار القديم؛ وكل تسليم إلى نقطة نهاية هو
إشعار يُرسل دون انتظار.

## تنسيق الحمولة

تكون عمليات التسليم إلى نقاط النهاية كائن JSON يحتوي على `data` و`event_id` و
`type`:

```json theme={null}
{
  "data": {
    "call_id": 987654321,
    "from_number": "+14155550199",
    "to_number": "+15551234567"
  },
  "event_id": "3f6b2ad0-1c9e-4a57-9f2b-8f6f0f9d2f11",
  "type": "telephony.incoming"
}
```

يكون `event_id` فريدًا لكل حدث يتم إصداره. ويكون متطابقًا عبر إعادات المحاولة
**وكذلك** عبر كل نقطة نهاية تتلقى الحدث — أزل التكرار باستخدامه.

يرسل الويب هوك القديم ذي عنوان URL الواحد `type` و`data` نفسيهما ولكن
**من دون** `event_id`:

```json theme={null}
{
  "type": "telephony.incoming",
  "data": { "call_id": 987654321, "from_number": "+14155550199", "to_number": "+15551234567" }
}
```

عند الإرسال، تُسلسَل كل حمولة بشكل معياري — تكون المفاتيح مرتبة
أبجديًا، ومن دون مسافات بيضاء، وبترميز UTF-8. أمثلة التنسيق الجميلة في
هذه الوثائق مخصصة لسهولة القراءة فقط.

راجع [كتالوج الأحداث](/ar/webhooks/events) للاطلاع على القائمة الكاملة لأنواع
الأحداث وحقول الحمولة.

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

يحمل كل طلب توقيع HMAC-SHA256 محسوبًا على **نص الطلب الخام** في ترويسة `X-ThunderPhone-Signature`. مفتاح التوقيع هو `secret` الخاص بنقطة النهاية (أو `secret` الخاص بخطاف الويب على مستوى مؤسستك لعمليات التسليم القديمة).

### الخطوات

1. اقرأ نص الطلب الخام **قبل** أي تحليل.
2. احسب `hmac_sha256(secret, body).hexdigest()`.
3. قارنه بزمن ثابت مع ترويسة `X-ThunderPhone-Signature`.

نوقّع البايتات التي نرسلها كما هي تمامًا، وهذه البايتات هي تسلسل JSON القياسي (مفاتيح مرتبة وفواصل مضغوطة). لذلك ينجح التحقق دائمًا باستخدام النص الخام — وإذا كان إطار العمل لديك يزوّدك بـ JSON محلل فقط، فإن إعادة تسلسله بمفاتيح مرتبة وفواصل مضغوطة تنتج بايتات مطابقة. تُغطّى كلتا الطريقتين في [دليل التحقق](/ar/guides/verify-webhook-signatures).

<CodeGroup>
  ```python Python theme={null}
  import hmac
  import hashlib

  def verify_signature(body: bytes, signature: str, secret: str) -> bool:
      expected = hmac.new(
          secret.encode("utf-8"),
          body,
          hashlib.sha256,
      ).hexdigest()
      return hmac.compare_digest(expected, signature or "")

  # Example Flask handler
  from flask import Flask, request, abort
  app = Flask(__name__)

  @app.post("/thunderphone-webhook")
  def handle():
      body = request.get_data()
      sig = request.headers.get("X-ThunderPhone-Signature", "")
      if not verify_signature(body, sig, WEBHOOK_SECRET):
          abort(401)
      event = request.get_json()
      # dispatch on event["type"] …
      return "", 204
  ```

  ```javascript Node.js (Express) theme={null}
  import crypto from "node:crypto";
  import express from "express";

  function verifySignature(body, signature, secret) {
    const expected = crypto
      .createHmac("sha256", secret)
      .update(body)
      .digest("hex");
    if (!signature || expected.length !== signature.length) return false;
    return crypto.timingSafeEqual(
      Buffer.from(expected),
      Buffer.from(signature),
    );
  }

  const app = express();
  app.post(
    "/thunderphone-webhook",
    express.raw({ type: "application/json" }),
    (req, res) => {
      const sig = req.header("X-ThunderPhone-Signature") || "";
      if (!verifySignature(req.body, sig, process.env.WEBHOOK_SECRET)) {
        return res.sendStatus(401);
      }
      const event = JSON.parse(req.body.toString("utf8"));
      // dispatch on event.type …
      res.sendStatus(204);
    },
  );
  ```
</CodeGroup>

## دلالات التسليم

تنطبق هذه الدلالات على عمليات تسليم **نقطة النهاية**. أما خطاف الويب القديم ذو عنوان URL الواحد
فهو محاولة متزامنة واحدة دون إعادة محاولات.

<AccordionGroup>
  <Accordion title="إعادة المحاولات">
    تتم محاولة كل حدث مرة واحدة فورًا. تُقرّ أي استجابة `2xx`
    بالتسليم. عند أي نتيجة أخرى (غير 2xx،
    أو خطأ في الاتصال، أو انتهاء المهلة)، نعيد المحاولة بعد **1 دقيقة، و5 دقائق، و30 دقيقة، وساعتين، و6 ساعات،
    و12 ساعة، و24 ساعة من المحاولة الأولى** — أي 8 محاولات خلال
    24 ساعة. إذا فشلت كل محاولة، يتوقف التسليم وتُعلَّم نقطة النهاية بالحالة
    `status="failing"` في
    [نقاط نهاية خطاف الويب](/ar/webhooks/endpoints). أعد `2xx` بمجرد
    قبول الحمولة بشكل دائم؛ ونفّذ المعالجة بصورة غير متزامنة.
  </Accordion>

  <Accordion title="الترتيب">
    ترتيب التسليم هو بأفضل جهد ممكن. عمليًا، نسلّم الأحداث بالترتيب الذي
    تُصدَر به، لكن إعادة المحاولات قد تعيد ترتيبها عند الفشل.
    أزل التكرار دائمًا وطابق البيانات باستخدام `call_id` / معرّف الكائن.
  </Accordion>

  <Accordion title="التكرارات">
    التسليم هو **مرة واحدة على الأقل**: قد تؤدي إعادة المحاولة بعد استجابة لم
    نتلقَّها إلى تكرار حدث. تحمل كل إعادة محاولة المعرّف نفسه
    `event_id`، لذا خزّن المعرّفات التي تمت معالجتها وتجاوز التكرارات. يكون `event_id`
    مشتركًا أيضًا بين نقاط النهاية — فنقطتا النهاية المشتركتان في
    الحدث نفسه تتلقيان `event_id` نفسه.
  </Accordion>

  <Accordion title="انتهاء المهلات">
    تبلغ مهلة عمليات تسليم نقطة النهاية **30 ثانية** لكل محاولة. في
    المسار القديم، تنتهي مهلة الطلبات الحاجبة التي تتحكم في سلوك المكالمات المباشرة — أي
    تبادل إعدادات [`telephony.incoming` / `web.incoming`](/ar/webhooks/call-incoming) —
    بعد **10 ثوانٍ**، لكن الاستجابة البطيئة تؤخر الرد على المكالمة، لذا احرص على
    الرد خلال بضع ثوانٍ. يتيح [إرسال الأدوات](/ar/tools/overview) في وضع خطاف الويب 20 ثانية.
  </Accordion>

  <Accordion title="عناوين IP المصدر">
    تنشأ خطافات الويب الصادرة من نطاق عناوين IP السحابية الخاص بـ ThunderPhone.
    إذا كان جدار الحماية لديك يتطلب قائمة سماح، فتواصل مع الدعم وسنشارك
    النطاقات الحالية.
  </Accordion>
</AccordionGroup>

## الاختيار بين خطافات الويب القديمة والقائمة على نقاط النهاية

| الميزة                 | القديم (`/v1/webhook`)                                                    | نقاط النهاية (`/v1/developer/webhook-endpoints`) |
| ---------------------- | ------------------------------------------------------------------------- | ------------------------------------------------ |
| عدد عناوين URL         | 1 لكل مؤسسة                                                               | عدة عناوين لكل مؤسسة                             |
| تغطية الأحداث          | `telephony.*` / `web.*` فقط                                               | جميع أنواع الأحداث العشرة                        |
| عامل تصفية الأحداث     | —                                                                         | لكل نقطة نهاية                                   |
| إعادة المحاولات        | لا يوجد                                                                   | 8 محاولات خلال 24 ساعة                           |
| الغلاف                 | `type` + `data`                                                           | `type` + `data` + `event_id`                     |
| تدوير السر             | يستبدل السر الوحيد                                                        | سر لكل نقطة نهاية                                |
| التعطيل دون حذف        | —                                                                         | `status=disabled`                                |
| ظهور الحالة            | —                                                                         | `active` / `disabled` / `failing`                |
| تبادل الإعدادات الحاجب | نعم ([`telephony.incoming` / `web.incoming`](/ar/webhooks/call-incoming)) | أبدًا — إشعارات فقط                              |
| الأنسب لـ              | إعدادات المكالمات الديناميكية                                             | استهلاك الأحداث في بيئة الإنتاج                  |

يجب أن تستهلك عمليات التكامل الجديدة الأحداث عبر خطافات الويب القائمة على
نقاط النهاية. احتفظ بعنوان URL قديم (أو أضف واحدًا) فقط إذا كنت تضبط المكالمات
ديناميكيًا عند وقت الرد أو تستخدم إرسال الأدوات في وضع خطاف الويب — إذ إن
عمليات تبادل الطلبات/الاستجابات هذه تعمل فقط عبر المسار القديم.

***

## ذو صلة

<CardGroup cols={2}>
  <Card title="كتالوج الأحداث" icon="list" href="/ar/webhooks/events">
    جميع أنواع الأحداث وحمولاتها.
  </Card>

  <Card title="نقاط نهاية خطاف الويب" icon="bolt" href="/ar/webhooks/endpoints">
    أدر نقاط نهاية متعددة وعوامل تصفية الأحداث والأسرار.
  </Card>

  <Card title="telephony.incoming / web.incoming" icon="phone" href="/ar/webhooks/call-incoming">
    الطلب الحاجب الذي يجب أن يجيب عنه خادمك لإعداد المكالمات.
  </Card>

  <Card title="telephony.complete / web.complete" icon="phone" href="/ar/webhooks/call-complete">
    حمولة ما بعد المكالمة تتضمن النص المفرغ والتسجيل والمقاييس.
  </Card>
</CardGroup>
