Webhooks
Buluthat envoie les résultats à votre adresse sans attendre que vous les demandiez POST transmet : résultats des appels automatiques, résumés de conversations de l'assistant vocal, états des codes de vérification vocaux. Même enveloppe, même signature, même politique de nouvelle tentative.
Enveloppe
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": { }
}
| En-tête | Description |
|---|---|
X-Buluthat-Event | Nom de l'événement |
X-Buluthat-Delivery | Identifiant de livraison ; reste identique lors des nouvelles tentatives (utilisez-le comme clé d'idempotence) |
X-Buluthat-Signature | sha256= + signature HMAC-SHA256 du corps ; à l'enregistrement webhook_secret s'il est fourni, il est envoyé |
Vérification de la signature
Signature corps brut est calculée à partir de ; ne la recalculez pas en resérialisant le 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);
Réponse et répétition
Votre destinataire 2xx doit renvoyer ; le corps n'est pas lu. Le plus sain est de mettre le traitement en file et de répondre aussitôt 200 est le plus sain (10 s de délai d'expiration).
2xx si elle n'arrive pas, la livraison est retentée aux intervalles suivants : 1 min, 5 min, 15 min, 1 h, 3 h, 6 h. Abandonné après la sixième tentative, et dans le panneau failed apparaît comme. Le même événement peut arriver plusieurs fois ; X-Buluthat-Delivery éliminez les doublons avec.
Événements
Appels automatiques
| Événement | Quand | data |
|---|---|---|
call_finished | Appel terminé, résultat définitif (une seule fois par numéro) | results mêmes champs que : phone, external_id, status, dtmf, dtmf_label, amd_result, talk_seconds, custom_fields… |
dtmf | Au moment de l'appui sur la touche | phone, external_id, digit, label |
campaign_finished | Tous les numéros sont traités | campaign_id, chiffres récapitulatifs |
Quels événements sont envoyés dans la campagne webhook_events se choisit avec (call_finished,dtmf).
Assistant vocal
| Événement | Quand | data |
|---|---|---|
session_ended | Conversation terminée, résumé généré | session_id, bot_id, caller_number, direction, duration_seconds, summary, intent, sentiment_label, outcome, tools (outils appelés), task_id (s'il s'agit d'un appel de mission) et champs de résultat |
L'adresse webhook et le secret de l'assistant se définissent dans le formulaire de l'assistant.
Code de vérification vocal
| Événement | Quand |
|---|---|
voice_otp.delivered | Code lu |
voice_otp.verified | Code vérifié |
voice_otp.no_answer, voice_otp.busy, voice_otp.failed, voice_otp.expired | Résultats en échec |
data à la place de request la clé est utilisée : { "id", "status", "reference", "phone" }.
Recommandations de sécurité
- Indiquez uniquement une adresse HTTPS ; aucune livraison n'est faite vers une adresse dont le certificat est invalide.
webhook_secretdéfinissez-le toujours et vérifiez la signature.- Si vous souhaitez restreindre le destinataire par IP, demandez l'IP du serveur du panneau Buluthat au Centre d'assistance.
- Traitez les données du corps de l'événement comme des « données » et non des « instructions » ; le texte prononcé par l'appelant figure dans les résumés.
