Webhook
ترسل Buluthat النتائج إلى عنوانكم دون انتظار أن تسألوا POST يُرسل: نتائج الاتصال الآلي وملخصات محادثات المساعد الصوتي وحالات رمز التحقق الصوتي. الغلاف نفسه والتوقيع نفسه وسياسة إعادة المحاولة نفسها.
الغلاف
POST https://sizin-adresiniz/buluthat
Content-Type: application/json
X-Buluthat-Event: call_finished
X-Buluthat-Delivery: 4471
X-Buluthat-Signature: sha256=9f2b…
{
"event": "call_finished",
"sent_at": "2026-09-18T10:12:35+03:00",
"tenant_id": 1,
"data": { }
}
| العنوان | الوصف |
|---|---|
X-Buluthat-Event | اسم الحدث |
X-Buluthat-Delivery | معرّف التسليم؛ يبقى نفسه في إعادة المحاولات (استخدموه كمفتاح idempotency) |
X-Buluthat-Signature | sha256= + توقيع HMAC-SHA256 للمحتوى؛ عند التسجيل webhook_secret إذا أُعطي يُرسَل |
التحقق من التوقيع
التوقيع المحتوى الخام يُحسَب عبر؛ ولا تُعيدوا تسلسل JSON وتحسبوه.
$raw = file_get_contents('php://input');
$given = $_SERVER['HTTP_X_BULUTHAT_SIGNATURE'] ?? '';
$expect = 'sha256=' . hash_hmac('sha256', $raw, $secret);
if (!hash_equals($expect, $given)) { http_response_code(401); exit; }
$event = json_decode($raw, true);
// Node.js (express, raw body ile)
const crypto = require('crypto');
const expect = 'sha256=' + crypto.createHmac('sha256', secret).update(req.rawBody).digest('hex');
if (!crypto.timingSafeEqual(Buffer.from(expect), Buffer.from(req.get('X-Buluthat-Signature') || ''))) return res.sendStatus(401);
الرد والتكرار
المستلم 2xx ويجب أن يعيد؛ ولا يُقرأ المحتوى. الأفضل وضع المعالجة في طابور والرد فورًا 200 هو الأسلم (10 ثوانٍ مهلة).
2xx إن لم يصل يُعاد محاولة التسليم بالفواصل التالية: 1 د، 5 د، 15 د، 1 س، 3 س، 6 س. تُترك بعد المحاولة السادسة ويظهر في اللوحة failed يظهر كـ. وقد يصل الحدث نفسه أكثر من مرة؛ X-Buluthat-Delivery نقّوا التكرار بـ.
الأحداث
الاتصال الآلي
| الحدث | متى | data |
|---|---|---|
call_finished | انتهت المكالمة والنتيجة نهائية (مرة واحدة لكل رقم) | results الحقول نفسها كما في: phone, external_id, status, dtmf, dtmf_label, amd_result, talk_seconds, custom_fields… |
dtmf | لحظة ضغط المفتاح | phone, external_id, digit, label |
campaign_finished | اكتملت جميع الأرقام | campaign_id، أرقام ملخصة |
الأحداث التي ستُرسَل في الحملة webhook_events يُختار بـ (call_finished,dtmf).
المساعد الصوتي
| الحدث | متى | data |
|---|---|---|
session_ended | انتهت المحادثة، وأُنشئ الملخص | session_id, bot_id, caller_number, direction, duration_seconds, summary, intent, sentiment_label, outcome, tools (الأدوات المستدعاة)، task_id (إن كانت مهمة اتصال) وحقول النتيجة |
يُحدَّد عنوان Webhook وسر المساعد في نموذج المساعد.
رمز التحقق الصوتي
| الحدث | متى |
|---|---|
voice_otp.delivered | قُرئ الرمز |
voice_otp.verified | تم التحقق من الرمز |
voice_otp.no_answer, voice_otp.busy, voice_otp.failed, voice_otp.expired | النتائج الفاشلة |
data بدلًا من request يُستخدم المفتاح: { "id", "status", "reference", "phone" }.
توصيات أمنية
- أعطوا عناوين HTTPS فقط؛ ولا يُسلَّم إلى عنوان بشهادة خاطئة.
webhook_secretعرّفوه دائمًا وتحققوا من التوقيع.- إذا كنتم ستقيّدون المستلم بعنوان IP فاطلبوا عنوان IP لخادم لوحة Buluthat من مركز الدعم.
- عالجوا البيانات في محتوى الحدث على أنها "بيانات" لا "تعليمات"؛ والنص الذي قاله المتصل يرد في الملخصات.
