انتقل إلى المحتوى
WbizTool

API v2 (تجريبي)

Webhooks

نقطة استقبال webhook هي عنوان URL على خادمك يستدعيه WbizTool عندما يحدث شيء لرسالة: أُرسلت، أو فشلت، أو أُلغيت، أو انتهت صلاحيتها. تصلك الأخبار فورًا بدلًا من الاستطلاع المتكرر، وكل طلب موقّع لتتمكن من التحقق من أنه جاء من WbizTool.

العمليةنقطة النهايةالنطاق
إضافة نقطة استقبالPOST /api/v2/webhooksmessages:read
عرض نقاط الاستقبالGET /api/v2/webhooksmessages:read
جلب نقطة استقبالGET /api/v2/webhooks/{id}messages:read
إزالة نقطة استقبالDELETE /api/v2/webhooks/{id}messages:read
استبدال سرّ التوقيعPOST /api/v2/webhooks/{id}/rotate-secretmessages:read
إرسال حدث تجريبيPOST /api/v2/webhooks/{id}/testmessages:read

تخص نقاط الاستقبال مساحة العمل، وتتلقى أحداث كل رسائلها أيًّا كان مُرسِلها: API، أو لوحة التحكم، أو الحملات، أو التذكيرات، أو التكاملات. لهذا لا يستطيع مفتاح مقيّد ببعض الأرقام إدارتها: كل استدعاء يُجاب بـ 403 number_not_allowed.

الأحداث#

النوعمتى
message.sentخرجت رسالة من رقمك.
message.failedتعذّر إرسال رسالة؛ ويذكر error.message السبب.
message.cancelledأُلغيت رسالة منتظرة: عبر API، أو من لوحة التحكم، أو لأن رقمها أو حملتها أُزيل.
message.expiredلم تُرسَل رسالة قبل expires_at الخاص بها.
pingحدث تجريبي طلبته.

تأتي لاحقًا أحداث الأرقام (الاتصال، وتسجيل الخروج) وأحداث الرسائل الواردة. لا ترسل علامتا التسليم والقراءة أحداثًا؛ اجلب الرسالة لرؤيتهما.

إضافة نقطة استقبال#

POSThttps://wbiztool.com/api/v2/webhooks

النص (Body): JSON (application/json)

الجسم

urlstringمطلوب

نقطة الاستقبال الخاصة بك: عنوان https:// عام، حتى 500 حرف. تُرفض عناوين http:// والعناوين الخاصة والمحلية (مثل localhost أو 192.168.x.x).

eventsarray of stringsاختياري

أنواع الأحداث التي تتلقاها: أيٌّ من message.sent وmessage.failed وmessage.cancelled وmessage.expired. القيمة الافتراضية: الأربعة كلها. ويصل ping دائمًا عندما تطلبه.

descriptionstringاختياري

ملاحظة لنفسك، حتى 100 حرف، مثل Order system.

يمكن أن يكون لمساحة العمل حتى 5 نقاط استقبال. الاستجابة هي 201 مع نقطة الاستقبال و**secret الخاص بالتوقيع، ويُعرض هذه المرة فقط**. احفظه حيث يستطيع مستقبِلك قراءته، مثل متغير بيئة. لا تعرض الاستجابات اللاحقة إلا secret_last4؛ وإذا فقدت السرّ، فاستبدله.

curl -X POST https://wbiztool.com/api/v2/webhooks \
  -H "Authorization: Bearer $WBIZTOOL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com/wbiztool/events",
    "events": ["message.sent", "message.failed"],
    "description": "Order system"
  }'

الاستجابة (201):

{
  "id": 41,
  "url": "https://example.com/wbiztool/events",
  "description": "Order system",
  "events": ["message.sent", "message.failed"],
  "secret_last4": "9c1e",
  "active": true,
  "disabled_reason": null,
  "created_at": "2026-10-18T11:20:05.733Z",
  "last_delivery": null,
  "secret": "3f0b…9c1e"
}

قيمة secret الحقيقية 64 حرفًا ست عشريًا. إعادة محاولة هذا الطلب مع Idempotency-Key نفسه لا تضيف نقطة استقبال ثانية، ولا تتضمن استجابتها السرّ.

أخطاء إضافة نقطة استقبال#

HTTPالرمزمتى
400validation_failed‏url مفقود أو طويل جدًا، أو events فارغ أو يحتوي على نوع غير معروف، أو أن حقلًا غير معروف
403webhook_limit_reachedلدى مساحة العمل بالفعل 5 نقاط استقبال
403number_not_allowedالمفتاح مقيّد ببعض الأرقام
422invalid_webhook_url‏url ليس عنوان https:// عامًا

عرض نقاط الاستقبال#

GEThttps://wbiztool.com/api/v2/webhooks

نقاط استقبال مساحة العمل التي تتلقى الأحداث، من الأقدم إلى الأحدث، في قائمة data واحدة.

curl https://wbiztool.com/api/v2/webhooks \
  -H "Authorization: Bearer $WBIZTOOL_API_KEY"

لا تتضمن القائمة نقاط الاستقبال التي توقفت. ويرى المالكون نقاط الاستقبال أيضًا، ويمكنهم إزالتها، في الإعدادات ← مفاتيح API تحت نقاط استقبال webhook.

جلب نقطة استقبال#

GEThttps://wbiztool.com/api/v2/webhooks/{id}

نقطة استقبال واحدة. يُظهر last_delivery كيف جرى آخر تسليم لها. نقطة الاستقبال غير الموجودة أو التي أُزيلت تُجاب بـ 404 webhook_not_found؛ أما النقطة المتوقفة فتُعرض مع active: false.

إزالة نقطة استقبال#

DELETEhttps://wbiztool.com/api/v2/webhooks/{id}

لا يُرسَل إليها شيء بعد ذلك، بما في ذلك إعادات المحاولة التي لا تزال منتظرة. الاستجابة هي {"id": 41, "deleted": true}.

استبدال سرّ التوقيع#

POSThttps://wbiztool.com/api/v2/webhooks/{id}/rotate-secret

يُنشئ سرًّا جديدًا لنقطة الاستقبال. الاستجابة هي 200 مع نقطة الاستقبال وsecret الجديد الخاص بها، ويُعرض هذه المرة فقط. يتوقف السرّ القديم فورًا: الأحداث المرسلة بعد ذلك تُوقَّع بالسرّ الجديد، بما فيها إعادات محاولة الأحداث السابقة. حدّث مستقبِلك فورًا.

curl -X POST https://wbiztool.com/api/v2/webhooks/41/rotate-secret \
  -H "Authorization: Bearer $WBIZTOOL_API_KEY"

إرسال حدث تجريبي#

POSThttps://wbiztool.com/api/v2/webhooks/{id}/test

يضع حدث ping في قائمة الانتظار لنقطة الاستقبال هذه، موقّعًا مثل كل حدث، لتتمكن من اختبار مستقبِلك. الاستجابة هي 202:

{ "event_id": "evt_8a2f4c1d9b7e6a5f4c3b2a19", "type": "ping", "queued": true }

تتلقى نقطة الاستقبال لديك:

{
  "id": "evt_8a2f4c1d9b7e6a5f4c3b2a19",
  "type": "ping",
  "created_at": "2026-10-18T11:21:40.002Z",
  "data": { "webhook_id": 41 }
}

حمولة الحدث#

كل حدث هو طلب POST بجسم JSON:

{
  "id": "evt_c41d7e2a9f3b8c6d5e4f3a21",
  "type": "message.sent",
  "created_at": "2026-10-18T10:15:09.912Z",
  "data": {
    "message": {
      "id": 9817263,
      "status": "sent",
      "from": { "id": 101, "phone": "919800000000", "platform": "whatsapp" },
      "to": { "phone": "+919876543210", "contact_id": 991 },
      "text": "Hi Asha, your order #1042 is ready.",
      "media": null,
      "send_at": null,
      "expires_at": null,
      "created_at": "2026-10-18T10:15:02.311Z",
      "sent_at": "2026-10-18T10:15:09.870Z",
      "error": null
    }
  }
}
الحقلالوصف
idمعرّف الحدث، evt_ متبوعًا بـ 24 حرفًا. يحتفظ الحدث نفسه بمعرّفه في كل إعادة محاولة.
typeأحد أنواع الأحداث.
created_atوقت وقوع الحدث.
data.messageلأحداث message.*: الرسالة كما كانت حينها. يعمل media.url فيها لمدة 26 ساعة على الأقل.
data.webhook_idلحدث ping: معرّف نقطة الاستقبال.

الترويسات:

الترويسةالقيمة
Content-Typeapplication/json
User-AgentWbizTool-Webhooks/2
WbizTool-Event-Id‏id الخاص بالحدث، وهو نفسه في كل إعادة محاولة
WbizTool-Timestampوقت إرسال هذه المحاولة، بثواني Unix، مثل 1792310409
WbizTool-Signature‏v1=‎ متبوعًا بقيمة HMAC-SHA256 الست عشرية لـ <timestamp>.<raw body>، محسوبةً بسرّ نقطة الاستقبال

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

تحقّق من كل طلب قبل أن تثق به: احسب التوقيع من الجسم الخام (قبل أن يحلّل إطار العمل لديك JSON)، وقارنه بالترويسة بمقارنة ثابتة الزمن، وارفض الطوابع الزمنية التي تبعد أكثر من 5 دقائق، حتى لا يمكن إعادة تشغيل طلب قديم. إنه المخطط نفسه المستخدم في توقيعات webhook في API v1، مع سرّ نقطة الاستقبال الخاص بها.

ثم استخدم WbizTool-Event-Id لتجاهل التكرارات: قد يصل الحدث نفسه أكثر من مرة، مثلًا عندما تضيع استجابتك فنعيد المحاولة.

import hashlib, hmac, json, os, time

SECRET = os.environ["WBIZTOOL_WEBHOOK_SECRET"]

def verify(secret: str, body: bytes, headers) -> bool:
    ts, sig = headers.get("WbizTool-Timestamp", ""), headers.get("WbizTool-Signature", "")
    if not ts.isdigit() or abs(time.time() - int(ts)) > 300:
        return False
    mac = "v1=" + hmac.new(secret.encode(), ts.encode() + b"." + body, hashlib.sha256).hexdigest()
    return hmac.compare_digest(mac, sig)

# Flask
from flask import Flask, request

app = Flask(__name__)
seen = set()  # use your database in production

@app.post("/wbiztool/events")
def events():
    body = request.get_data()  # the raw bytes
    if not verify(SECRET, body, request.headers):
        return "", 401
    event_id = request.headers["WbizTool-Event-Id"]
    if event_id in seen:
        return "", 200  # a repeat: already handled
    seen.add(event_id)
    event = json.loads(body)
    if event["type"] == "message.failed":
        message = event["data"]["message"]
        print("Failed:", message["id"], message["error"]["message"])
    return "", 200

في Django، مرّر request.body وrequest.headers.

أجب بـ 2xx بسرعة، ثم أنجز العمل البطيء بعد ذلك (في قائمة انتظار مثلًا).

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

  • أجب بأي 2xx خلال 10 ثوانٍ. وأي شيء آخر يُعدّ فشلًا: رمز حالة آخر (بما في ذلك 4xx)، أو عدم الإجابة خلال 10 ثوانٍ، أو عدم الاتصال خلال 3 ثوانٍ. تُتبَع عمليات إعادة التوجيه، 3 على الأكثر، ويجب أن تؤدي كل منها إلى عنوان عام.
  • يُعاد إرسال التسليم الفاشل بعد 1 و5 و15 دقيقة، ثم بعد 1 و2 و4 و8 و8 ساعات: 9 محاولات على مدى 23 ساعة تقريبًا. وبعد آخرها، يُتجاهل ذلك الحدث.
  • تحمل إعادة المحاولة الجسم نفسه وWbizTool-Event-Id نفسه، مع WbizTool-Timestamp وتوقيع جديدين.
  • الترتيب غير مضمون. قد يصل message.sent المُعاد إرساله بعد حدث لاحق. استخدم status الخاص بالرسالة، أو اجلب الرسالة، عندما يهمّك الترتيب.

يُظهر last_delivery في نقطة الاستقبال كيف جرى آخر تسليم: state (pending أو delivered أو failed)، وstatus_code الذي أجاب به خادمك، ووقت إنشاء الحدث.

متى تتوقف نقاط الاستقبال#

تتوقف نقطة الاستقبال عن تلقي الأحداث عند حدوث أحد ما يلي. وتبقى في GET /webhooks مع active: false وdisabled_reason، لتعرف السبب؛ ولا يزال من الممكن قراءتها وإزالتها، لكن لا يمكن اختبارها ولا منحها سرًّا جديدًا (404).

  • فشلت لمدة 24 ساعة. إذا لم يُسلَّم إليها شيء طوال 24 ساعة بينما استمرت عمليات التسليم في الفشل، فإنها تُوقَف وتُتجاهل إعادات المحاولة المنتظرة. وتظهر حينها في الإعدادات ← مفاتيح API بالحالة متوقفة. أصلح خادمك، ثم أضف نقطة الاستقبال مرة أخرى.
  • أُبطل المفتاح الذي أنشأها أو انتهت صلاحيته. إبطال مفتاح يوقف كل ما أعدّه. أضف نقطة الاستقبال مرة أخرى بمفتاح آخر.
  • أُزيلت، عبر إزالة نقطة استقبال أو في الإعدادات ← مفاتيح API.

نقاط الاستقبال المتوقفة لا تُحتسب ضمن الحد البالغ 5.

كائن نقطة استقبال webhook#

الحقلالنوعالوصف
idintegerمعرّف نقطة الاستقبال.
urlstringالمكان الذي تُرسَل إليه الأحداث.
descriptionstringملاحظتك؛ "" عندما لا توجد ملاحظة.
eventsarrayأنواع الأحداث التي تتلقاها.
secretstringسرّ التوقيع: يظهر فقط في استجابتي إضافة نقطة استقبال واستبدال سرّ التوقيع.
secret_last4stringآخر 4 أحرف من السرّ، لتعرف أيّ سرّ لديك.
activeboolean‏false عندما لم تعد تتلقى أحداثًا – راجع متى تتوقف نقاط الاستقبال.
disabled_reasonstring or nullسبب توقفها (الفشل لمدة 24 ساعة، أو أن المفتاح الذي أنشأها أُبطل أو انتهت صلاحيته)؛ وnull ما دامت نشطة.
created_atstringوقت إضافتها.
last_deliveryobject or nullآخر تسليم جرت محاولته: state، وstatus_code (أو null عندما لم يُجب خادمك)، وcreated_at. وتكون null قبل التسليم الأول.

صفحات ذات صلة#