Webhooks

Webhooks

الوجهات، الأحداث، التوقيع، وإعادة المحاولة.

Webhook — إدارة الوجهات

GET    /instances/{instance_id}/webhooks
POST   /instances/{instance_id}/webhooks
PATCH  /instances/{instance_id}/webhooks/{webhook_id}
POST   /instances/{instance_id}/webhooks/{webhook_id}/enabled   { "enabled": true }
DELETE /instances/{instance_id}/webhooks/{webhook_id}

POST /instances/{instance_id}/webhooks
{
  "destination_url": "https://your-site.com/webhook",
  "events": ["message", "message.ack", "session.status", "message.unknown"],
  "client_sign_secret": "your-secret",
  "ignore_status": true
}
→ 201 { "success": true, "webhook_id": "whk_…" }

يُنشأ الويب هوك معطلاً — فعّله بمسار enabled. PATCH يستبدل الإعداد كاملاً فأرسل destination_url و events دائماً؛ client_sign_secret الفارغ يُبقي السر الحالي و clear_client_sign = true يزيله. يمكن إدارة كل ذلك أيضاً من صفحة الجلسة.

Webhook — الأحداث

session.statusتغيّر حالة الجلسة (WORKING، SCAN_QR_CODE، FAILED…) مع رقم الجوال المرتبط.
messageرسالة واردة من الآخرين.
message.anyكل رسالة في الجلسة، الواردة والصادرة (fromMe).
message.ackتحديث تسليم/قراءة رسالة أرسلتها (حقل ack).
message.reactionتفاعل (إيموجي) على رسالة.
message.editedتعديل رسالة.
message.revokedحذف رسالة لدى الجميع.
message.unknownحدث من المنصة: رسالة أرسلتها عبر API صارت unknown وتحتاج قرارك.

أحداث أخرى متاحة (المجموعات، المكالمات، التصنيفات، الاستطلاعات، التواجد) — القائمة الكاملة في نموذج الويب هوك بصفحة الجلسة.

ignore_status (افتراضي true): حالات واتساب/القصص (status@broadcast) لا تُرسل إليك. اجعله false لاستقبالها ضمن أحداث الرسائل.

Webhook — شكل الطلب الواصل لوجهتك

POST https://your-site.com/webhook
Content-Type: application/json
X-TProTool-Event-Id: evt_…
X-TProTool-Timestamp: 1760209200
X-TProTool-Signature: v1=…

{
  "event_id": "evt_…",
  "event": "message",
  "instance_id": "ins_…",
  "timestamp": 1760209200000,
  "payload": {
    "id": "…",
    "from": "[email protected]",
    "from_phone": "9665xxxxxxxx",
    "fromMe": false,
    "body": "Hello",
    "hasMedia": true,
    "media": {
      "status": "ready",
      "mimetype": "image/jpeg",
      "media_id": "med_…",
      "url": "https://…/m/…",
      "expires_at": "…"
    }
  }
}

// message.unknown
{
  "event_id": "evt_…",
  "event": "message.unknown",
  "instance_id": "ins_…",
  "payload": { "message_id": "msg_…", "client_reference": "order-123", "to": "9665xxxxxxxx", "type": "text", "error_code": "TIMEOUT" }
}
// error_code: TIMEOUT | WORKER_DIED
media.status = readyالملف محفوظ — نزّله من url قبل expires_at.
media.status = too_largeالملف أكبر من الحد المسموح فلم يُحفظ.
media.status = failedتعذّر تنزيل الملف من واتساب.
media.status = outgoingوسيط في رسالة أرسلتها الجلسة — لا يُحفظ منه نسخة.
media.status = unavailableالوسيط غير متاح للتنزيل.

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

عند ضبط client_sign_secret يصل الرأس X-TProTool-Signature بالقيمة v1= ثم HMAC-SHA256 للنص (timestamp + "." + جسم الطلب الخام) بالسر. X-TProTool-Event-Id و X-TProTool-Timestamp يصلان دائماً. ارفض الطلب إن لم يطابق التوقيع أو كان الوقت أقدم من 5 دقائق.

<?php
$secret = 'your-secret';
$raw = file_get_contents('php://input');
$ts  = $_SERVER['HTTP_X_TPROTOOL_TIMESTAMP'] ?? '';
$sig = $_SERVER['HTTP_X_TPROTOOL_SIGNATURE'] ?? '';

$expected = 'v1=' . hash_hmac('sha256', $ts . '.' . $raw, $secret);
if (!hash_equals($expected, $sig) || abs(time() - (int) $ts) > 300) {
    http_response_code(401);
    exit;
}

$event = json_decode($raw, true);
// ignore if $event['event_id'] was already processed
http_response_code(200);

Webhook — الرد وإعادة المحاولة

ردّ بأي رمز 2xx خلال 8 ثوانٍ ليُعتبر التسليم ناجحاً. غير ذلك يُعاد الإرسال بفواصل متزايدة (5، 10، 20، 40، 80 ثانية) حتى 6 محاولات ثم يصبح فشلاً نهائياً، ويمكنك إعادة تسليمه يدوياً من سجل التسليم في صفحة الجلسة.

410 Gone: يُعطَّل الويب هوك ويتوقف الإرسال إليه حتى تفعّله من جديد. 429 مع Retry-After: تُؤجَّل المحاولة للوقت المطلوب (حتى ساعة).

event_id ثابت للحدث في كل المحاولات — احفظه وتجاهل أي حدث وصلك سابقاً. عالج الحدث بعد الرد بسرعة إن كانت معالجته طويلة.