Skip to content

API Webhooks

مرجع كامل لإدارة اشتراكات Webhook برمجيًا. استخدم هذه النقاط لتسجيل نقاط نهاية HTTPS تستقبل إشعارات JSON عند وقوع أحداث في مستأجرك.

وارد مقابل صادر

تُعدّ هذه النقاط لضبط Webhooks الصادرة (وقتي → خادمك). إنها ليست عنوان URL الذي تستدعيه مزودو الدفع إلى وقتي.

قائمة اشتراكات Webhook

http
GET /v1/webhooks

يُرجع جميع اشتراكات Webhook للمستأجر المصادق عليه. لا تُدرج الأسرار أبدًا في استجابات القائمة.

مثال الطلب

bash
curl -X GET "https://api.waqti.sa/v1/webhooks" \
  -H "Authorization: Bearer 3|a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0" \
  -H "Accept: application/json"

مثال الاستجابة

json
{
  "data": [
    {
      "id": 7,
      "name": "ERP sync",
      "url": "https://integrations.example.com/waqti/webhook",
      "events": [
        "purchase_order.approved",
        "invoice.paid",
        "vendor.updated"
      ],
      "is_active": true,
      "failure_count": 0,
      "last_triggered_at": "2026-03-28T09:12:33Z",
      "created_at": "2026-01-10T14:20:00Z"
    }
  ]
}

إنشاء Webhook

http
POST /v1/webhooks

يُنشئ اشتراكًا جديدًا. زوّد عنوان URL لاستقبال طلبات POST وقائمة أنواع الأحداث المشترك بها.

جسم الطلب

الحقلالنوعمطلوبالوصف
namestringنعماسم العرض (حد أقصى 100 حرف)
urlstringنعمنقطة نهاية HTTPS تقبل POST من نوع application/json (حد أقصى 500 حرف)
eventsarrayنعمسلسلة واحدة أو أكثر من أنواع الأحداث (انظر الأحداث المتاحة)

سر التوقيع المستخدم للتحقق من HMAC يُولَّد من وقتي ويُرجع فقط في هذه الاستجابة. لا يمكن تعيينه في جسم الطلب ولا يُعرض مجددًا في استجابات GET أو PUT لاحقًا — خزّنه بأمان عند إنشاء الاشتراك.

مثال الطلب

bash
curl -X POST "https://api.waqti.sa/v1/webhooks" \
  -H "Authorization: Bearer 3|a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Procurement automation",
    "url": "https://integrations.example.com/waqti/webhook",
    "events": [
      "purchase_order.created",
      "purchase_order.approved",
      "invoice.created",
      "vendor.created"
    ]
  }'

مثال الاستجابة

json
{
  "data": {
    "id": 8,
    "name": "Procurement automation",
    "url": "https://integrations.example.com/waqti/webhook",
    "events": [
      "purchase_order.created",
      "purchase_order.approved",
      "invoice.created",
      "vendor.created"
    ],
    "secret": "k8mN2pQ9rS4tU7vW1xY5zA6bC0dE3fG8hI2jK5lM9nO1pQ4rS7tU0vW3xY6z",
    "is_active": true,
    "created_at": "2026-04-02T11:05:22Z"
  }
}

تفاصيل Webhook

http
GET /v1/webhooks/{id}

يُرجع اشتراكًا واحدًا بما في ذلك حقول الصحة. لا يُضمَّن سر التوقيع.

مثال الطلب

bash
curl -X GET "https://api.waqti.sa/v1/webhooks/8" \
  -H "Authorization: Bearer 3|a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0" \
  -H "Accept: application/json"

مثال الاستجابة

json
{
  "data": {
    "id": 8,
    "name": "Procurement automation",
    "url": "https://integrations.example.com/waqti/webhook",
    "events": [
      "purchase_order.created",
      "purchase_order.approved",
      "invoice.created",
      "vendor.created"
    ],
    "is_active": true,
    "failure_count": 0,
    "last_triggered_at": "2026-04-02T14:18:00Z",
    "last_failed_at": null,
    "last_failure_reason": null,
    "created_at": "2026-04-02T11:05:22Z",
    "updated_at": "2026-04-02T11:05:22Z"
  }
}

تحديث Webhook

http
PUT /v1/webhooks/{id}

يُحدّث اشتراكًا قائمًا. جميع حقول الجسم اختيارية؛ الحقول المُهملة تحتفظ بقيمها الحالية.

جسم الطلب

الحقلالنوعالوصف
namestringاسم العرض (حد أقصى 100 حرف)
urlstringعنوان التسليم (حد أقصى 500 حرف)
eventsarrayقائمة بديلة لأنواع الأحداث (حد أدنى 1 إذا وُفِّر الحقل)
is_activebooleanتفعيل أو إيقاف التسليم مؤقتًا

مثال الطلب

bash
curl -X PUT "https://api.waqti.sa/v1/webhooks/8" \
  -H "Authorization: Bearer 3|a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{
    "events": [
      "purchase_order.approved",
      "purchase_order.rejected",
      "purchase_order.cancelled",
      "invoice.approved",
      "invoice.paid",
      "budget.threshold_reached"
    ],
    "is_active": true
  }'

مثال الاستجابة

json
{
  "data": {
    "id": 8,
    "name": "Procurement automation",
    "url": "https://integrations.example.com/waqti/webhook",
    "events": [
      "purchase_order.approved",
      "purchase_order.rejected",
      "purchase_order.cancelled",
      "invoice.approved",
      "invoice.paid",
      "budget.threshold_reached"
    ],
    "is_active": true,
    "updated_at": "2026-04-02T15:40:10Z"
  }
}

حذف Webhook

http
DELETE /v1/webhooks/{id}

يُزيل الاشتراك نهائيًا. لا يُرسل تسليم بعد ذلك.

مثال الطلب

bash
curl -X DELETE "https://api.waqti.sa/v1/webhooks/8" \
  -H "Authorization: Bearer 3|a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0" \
  -H "Accept: application/json"

مثال الاستجابة

json
{
  "data": null
}

إرسال حدث اختبار

http
POST /v1/webhooks/{id}/test

يضع في قائمة الانتظار تسليم اختبار فوريًا إلى عنوان URL المُعدّ بنفس الترويسات وقواعد التوقيع كالأحداث الحقيقية. يستخدم الحمولة نوع الحدث الاصطناعي webhook.test.

مثال الطلب

bash
curl -X POST "https://api.waqti.sa/v1/webhooks/8/test" \
  -H "Authorization: Bearer 3|a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0" \
  -H "Accept: application/json"

مثال الاستجابة (نجاح)

json
{
  "data": {
    "status_code": 200,
    "response": "{\"received\":true}"
  }
}

إذا لم تُرجع نقطة النهاية حالة HTTP ناجحة، تُرجع API الاستجابة 422 مع رسالة خطأ تصف الفشل.

الأحداث المتاحة

اشترك باستخدام سلاسل حدث API في طلبات POST / PUT. عمود الاختصار يطابق التسميات الشائعة (po.*، إلخ.)؛ الخادم يقبل فقط القيمة الخاصة بـ API.

حدث APIاختصارالوصف
purchase_order.createdpo.createdأُنشئ أمر شراء جديد
purchase_order.approvedpo.approvedوُافق على أمر الشراء
purchase_order.rejectedpo.rejectedرُفض أمر الشراء
purchase_order.cancelledpo.cancelledأُلغي أمر الشراء
invoice.createdinvoice.createdأُنشئت فاتورة جديدة
invoice.approvedinvoice.approvedوُافقت على الفاتورة
invoice.paidinvoice.paidوُسِمَت الفاتورة كمدفوعة
vendor.createdvendor.createdأُنشئ مورد جديد
vendor.updatedvendor.updatedحُدّثت تفاصيل المورد
budget.threshold_reachedbudget.threshold_reachedتجاوزت الميزانية عتبة التنبيه

قد تتوفر أنواع أحداث إضافية مع تطور المنتج؛ يجب أن تتجاهل تكاملك قيم event غير المعروفة التي لا تتعامل معها.

حمولة Webhook والتحقق من التوقيع

كل تسليم هو HTTP POST مع Content-Type: application/json. لهذا الشكل جسم JSON:

مثال جسم التسليم

json
{
  "id": "9f2d5c1e-6b4a-4e8d-9c3f-1a7e2d5b8c60",
  "event": "purchase_order.approved",
  "created_at": "2026-04-02T16:22:11+00:00",
  "tenant_id": "acme-corp",
  "data": {
    "purchase_order_id": 442,
    "po_number": "PO-2026-0442",
    "status": "approved",
    "total_amount": 128750.5,
    "currency": "SAR",
    "approved_at": "2026-04-02T16:22:00+00:00"
  }
}

الترويسات

الترويسةالوصف
X-Waqti-Eventنفس السلسلة كحقل event في الجسم
X-Waqti-SignatureHMAC-SHA256 للجسم الخام للطلب بترميز hex باستخدام سر الاشتراك
X-Waqti-Deliveryمعرف التسليم الداخلي (مفيد للدعم وسجل idempotency)
User-AgentWaqti-Webhook/1.0

التحقق من HMAC SHA-256

  1. اقرأ جسم HTTP الخام كنص (قبل تحليل JSON).
  2. احسب HMAC_SHA256(raw_body, secret) وترمّزه كسلسلة hexadecimal بحروف صغيرة.
  3. قارن النتيجة مع X-Waqti-Signature بمقارنة زمن ثابت (مثل hash_equals في PHP).

إذا لم يطابق التوقيع، ارفض الطلب ولا تثق بـ JSON.

WARNING

المسافات البيضاء وترتيب المفاتيح وتطبيع Unicode يؤثر على الجسم الخام. تحقق من البايتات التي أرسلها وقتي فعليًا، وليس نسخة JSON أُعيد تسلسلها، ما لم يضمن إطار عملك مخرجات متطابقة.

سياسة إعادة المحاولة

تُعاد محاولة التسليمات الفاشلة (حالة HTTP غير 2xx، انتهاء المهلة، أو أخطاء شبكة) تلقائيًا. توقّع حتى نحو ثلاث إعادات بعد المحاولة الأولى، مع تراجع أسي بين كل محاولة. بعد استنفاد الحد الأقصى، يُعلَّم التسليم كفاشل.

إذا استمرت الإخفاقات، قد تزيد وقتي عدّاد الفشل على الاشتراك وتُعطّل Webhook تلقائيًا بعد فشل متتالي كثير — أصلح نقطة النهاية وأعد التفعيل عبر PUT أو واجهة الإدارة.

أفضل ممارسات أمنية

  • استخدم HTTPS فقط لعناوين Webhook حتى تُشفَّر الحمولات والبيانات الوصفية أثناء النقل.
  • تحقق من كل طلب بـ X-Waqti-Signature قبل التصرف؛ اعتبر التوقيع المفقود أو غير الصالح هجومًا أو خطأ إعدادًا.
  • خزّن السر من استجابة الإنشاء في مدير أسرار أو متغير بيئة، وليس في نظام التحكم بالإصدارات.
  • استجب بسرعة بـ 2xx بعد التحقق ووضع العمل في طابور؛ نفّذ المعالجة الثقيلة بشكل غير متزامن حتى لا تنتهي مهلة وقتي وتُعاد المحاولة دون داعٍ.
  • صمّم لازدواجية التسليم: التسليم ممكن أن يكون at-least-once؛ استخدم id (UUID في الحمولة) أو مفاتيح idempotency خاصة بك لإزالة التكرار.

Built by M & L Technologies