# كتالوج الأحداث

كل حمولة webhook ملفوفة:

```
{

  "event":       "<event name>",

  "store_id":    13,

  "occurred_at": "2026-04-30T21:18:21+00:00",

  "data":        { /* خاص بالحدث، مُوثَّق أدناه */ },

  "delivery_id": "9f2c41ab77e05d18"

}
```

هذه الصفحة توثّق حقل `data` لكل حدث.

## أحداث الطلبات[​](#أحداث-الطلبات "رابط مباشر إلى أحداث الطلبات")

أحداث الطلبات في API v1 لا تتبع تغييرات لوحة التحكم ولا شركة التوصيل

يُطلق حدث حالة الطلب حين تتغيّر الحالة عبر الـ API، أي `PATCH /v1/orders/{id}` أو `POST /v1/orders/{id}/cancel`، وحين يُضغط زر التأكيد أو الإلغاء في إشعار Telegram بطلب جديد. هذان الزرّان يُطلقان `order.confirmed` و`order.cancelled` لطلبات واجهة المتجر وصفحات الهبوط أيضًا، وهي طلبات لم تُرسل `order.created` قط. أما التأكيد أو الشحن من لوحة تحكم DZBuild، والإرسال الجماعي إلى التوصيل، و`POST /v1/orders/{id}/send-to-delivery`، وتحديثات تتبّع شركة التوصيل التلقائية، فلا تُطلق **شيئًا** هنا.

كما أن هناك 7 حالات للطلب لكن **5** أحداث حالة فقط: الانتقال إلى `pending` والانتقال إلى `processing` لا يُصدران أي شيء إطلاقًا. فقد ينتقل الطلب `pending → processing → shipped` ولا ترى سوى `order.shipped` واحدًا.

إن احتجت أحداثًا تغطي كل مصادر الطلبات وكل تغييرات الحالة، استخدم إضافة Webhooks للتاجر على `/dashboard/webhooks` بدلًا من ذلك — انظر المقارنة في [نظرة عامة على Webhooks](https://dzbuild.com/ar/ar/api-docs/webhooks/overview.md).

### `order.created`[​](#ordercreated "رابط مباشر إلى ordercreated")

يُطلق **فقط** للطلبات المُنشأة عبر `POST /v1/orders`. طلبات واجهة المتجر وصفحات الهبوط والطلبات اليدوية من لوحة التحكم لا تُطلق هذا الحدث — فإن ربطت التنفيذ به ستفوّت الغالبية الساحقة من طلبات التاجر.

```
{

  "data": {

    "order_id":       6894,

    "order_number":   "ORD-13-20260317-1A2B3C4D",

    "customer_phone": "0555000000",

    "total":          1000

  }

}
```

هذه المفاتيح الأربعة هي كامل الحمولة. اجلب `GET /v1/orders/{id}` إن احتجت أي شيء آخر.

### `order.confirmed`[​](#orderconfirmed "رابط مباشر إلى orderconfirmed")

يُطلق عند الانتقال إلى `confirmed`. مع الإعداد الافتراضي لـ **خصم المخزون** (عند التأكيد)، يُخصم المخزون في هذه اللحظة. أما في متجر ضُبط على **فور وصول الطلب**، فالطلب الذي وصل بعد هذا الاختيار خُصم مخزونه عند إنشائه، وتأكيده لا يخصم شيئًا إضافيًا.

```
{

  "data": {

    "order_id":   6894,

    "old_status": "pending",

    "new_status": "confirmed"

  }

}
```

### `order.shipped`[​](#ordershipped "رابط مباشر إلى ordershipped")

```
{ "data": { "order_id": 6894, "old_status": "processing", "new_status": "shipped" } }
```

قد تكون `old_status` حالة لم تُخطَر بها قط — فالانتقال إلى `processing` في هذا المثال لم يُطلق حدثًا خاصًا به.

### `order.delivered`[​](#orderdelivered "رابط مباشر إلى orderdelivered")

```
{ "data": { "order_id": 6894, "old_status": "shipped", "new_status": "delivered" } }
```

### `order.cancelled`[​](#ordercancelled "رابط مباشر إلى ordercancelled")

يُطلق حين ينتقل الطلب إلى `cancelled` من `pending` أو `confirmed` أو `processing` — وهذه هي الحالات الوحيدة التي يُسمح بالإلغاء منها. أما `POST /v1/orders/{id}/cancel` على طلب في حالة `shipped` أو `delivered` فيُرجع `400 bad_request` ولا يُطلق أي حدث. وإن كان الطلب في حالة مخزون مُلتزَم، يُسترَد المخزون قبل إطلاق هذا الحدث.

```
{ "data": { "order_id": 6894, "old_status": "confirmed", "new_status": "cancelled" } }
```

### `order.returned`[​](#orderreturned "رابط مباشر إلى orderreturned")

```
{ "data": { "order_id": 6894, "old_status": "delivered", "new_status": "returned" } }
```

## أحداث الدفع[​](#أحداث-الدفع "رابط مباشر إلى أحداث الدفع")

### `payment.received`[​](#paymentreceived "رابط مباشر إلى paymentreceived")

**محجوز — لا يُصدَر حاليًا.** الاسم مقبول في مصفوفة `events` عند التسجيل ويظهر في `allowed_events`، لكن لا شيء يُطلقه. تغييرات حالة الدفع لن تصل إلى نقطتك؛ اقرأ `GET /v1/orders/{id}` إن احتجتها.

## تتبّع الاشتراكات والأحداث[​](#تتبّع-الاشتراكات-والأحداث "رابط مباشر إلى تتبّع الاشتراكات والأحداث")

### `signup.counted`[​](#signupcounted "رابط مباشر إلى signupcounted")

يُطلق عند ورود نداء `/v1/signups` تم احتسابه فعلًا (وليس مكررًا).

```
{

  "data": {

    "key_id":  "dzpub_live_0123456789abc",

    "source":  "landing-page-1",

    "country": "DZ"

  }

}
```

لأسباب خصوصية لا نعيد إرسال `email` ولا `phone` ولا `external_user_id` في الـ webhook — أنظمتك تملك هذه القيم أصلًا. الـ webhook إشارة "هذا الاشتراك احتُسب، انقله إلى CRM لديك".

### `event.recorded`[​](#eventrecorded "رابط مباشر إلى eventrecorded")

**محجوز — لا يُصدَر حاليًا.** `POST /v1/events` يسجّل الحدث ويزيد الاستهلاك، لكنه لا يُطلق أي webhook.

## أحداث المنتجات[​](#أحداث-المنتجات "رابط مباشر إلى أحداث المنتجات")

### `product.stock_low`[​](#productstock_low "رابط مباشر إلى productstock_low")

**محجوز — لا يُصدَر حاليًا.** لا يوجد دفع لتنبيه انخفاض المخزون اليوم.

لكن الحقل الأساسي حقيقي: `GET /v1/products/{id}` يُرجع `low_stock_alert` إلى جانب `stock_quantity` تحت `inventory`، فيمكنك استعلام الشرط بنفسك.

## داخلي / اختبار[​](#داخلي--اختبار "رابط مباشر إلى داخلي / اختبار")

### `webhook.test`[​](#webhooktest "رابط مباشر إلى webhooktest")

يُطلق بـ `POST /v1/webhooks/{id}/test`. يتيح لك التأكد من أن نقطتك قابلة للوصول دون انتظار حدث حقيقي.

```
{ "data": { "ts": 1717112657 } }
```

لا يمكن الاشتراك فيه — فتضمين `webhook.test` في مصفوفة `events` عند التسجيل يُرجع `400 bad_request` `"unknown event: webhook.test. Allowed: …"`. ويُسلَّم الاختبار إلى الـ webhook الذي تناديه عليه بغض النظر عن قائمة اشتراكاته.

## الرؤوس (لكل حدث)[​](#الرؤوس-لكل-حدث "رابط مباشر إلى الرؤوس (لكل حدث)")

```
Content-Type:    application/json

User-Agent:      dzbuild-webhook/1

X-DZ-Timestamp:  <unix seconds>

X-DZ-Signature:  t=<unix seconds>,v1=<hex hmac-sha256>

X-DZ-Delivery-Id: <numeric delivery id>
```

`X-DZ-Delivery-Id` هو معرّف تسليم رقمي (مثلًا `4127`). وهو ثابت عبر كل إعادة محاولة لذلك التسليم، وهو **ليس** نفس القيمة `delivery_id` ذات الـ 16 خانة ست عشرية الموجودة في جسم JSON. ولا يشمل التوقيع هذه الترويسة، لذا أزل التكرار بـ `delivery_id` الموجود في الجسم.

## الإصدار[​](#الإصدار "رابط مباشر إلى الإصدار")

نُضيف أحداثًا جديدة ضمن v1 بحرية (إضافي). عندما نغيّر **شكل `data` لحدث قائم**، يكون ذلك تغييرًا يستوجب v2 ويحصل على بادئة مسار جديدة. فيمكن لشيفرتك الاعتماد على:

* `event` ثابت.
* قد تظهر حقول جديدة على المستوى الأعلى في `data`.
* الأنواع والمعاني الموجودة لن تتغير بدون v2.
* ترتيب مفاتيح `data` **غير** مضمون.
