Webhooki

Buluthat wysyła wyniki na Twój adres, nie czekając, aż o nie zapytasz POST obsługuje: wyniki automatycznych połączeń, podsumowania rozmów asystenta głosowego, statusy głosowych kodów weryfikacyjnych. Ta sama koperta, ten sam podpis, ta sama polityka ponawiania.

Koperta

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": { }
}
NagłówekOpis
X-Buluthat-EventNazwa zdarzenia
X-Buluthat-DeliveryIdentyfikator dostarczenia; przy ponowieniach pozostaje ten sam (użyj jako klucza idempotencji)
X-Buluthat-Signaturesha256= + podpis HMAC-SHA256 treści; w rekordzie webhook_secret jest wysyłane, jeśli podano

Weryfikacja podpisu

Podpis surowa treść obliczane na podstawie; nie obliczaj, serializując JSON ponownie.

$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);

Odpowiedź i powtórzenie

Twój odbiorca 2xx powinien zwrócić; treść nie jest odczytywana. Najlepiej wrzucić przetwarzanie do kolejki i od razu 200 najlepiej wrócić (limit czasu 10 s).

2xx jeśli nie dotrze, dostarczenie jest ponawiane w odstępach: 1 min, 5 min, 15 min, 1 godz., 3 godz., 6 godz.. Po szóstej próbie zostaje porzucone i w panelu failed widoczne jako. To samo zdarzenie może dotrzeć wielokrotnie; X-Buluthat-Delivery odfiltruj duplikaty przez.

Zdarzenia

Automatyczne połączenia

ZdarzenieKiedydata
call_finishedPołączenie zakończone, wynik ostateczny (jednorazowo na numer)results te same pola co: phone, external_id, status, dtmf, dtmf_label, amd_result, talk_seconds, custom_fields…
dtmfW chwili naciśnięcia klawiszaphone, external_id, digit, label
campaign_finishedWszystkie numery zostały zakończonecampaign_id, liczby zbiorcze

Które zdarzenia mają być wysyłane w kampanii webhook_events wybierane przez (call_finished,dtmf).

Asystent głosowy

ZdarzenieKiedydata
session_endedRozmowa zakończona, podsumowanie wygenerowanesession_id, bot_id, caller_number, direction, duration_seconds, summary, intent, sentiment_label, outcome, tools (wywołane narzędzia), task_id (jeśli jest to zadanie dzwoniące) oraz pola wyniku

Adres webhooka asystenta i sekret definiuje się w formularzu asystenta.

Głosowy kod weryfikacyjny

ZdarzenieKiedy
voice_otp.deliveredKod odczytany
voice_otp.verifiedKod zweryfikowany
voice_otp.no_answer, voice_otp.busy, voice_otp.failed, voice_otp.expiredWyniki negatywne

data zamiast request używany jest klucz: { "id", "status", "reference", "phone" }.

Zalecenia dotyczące bezpieczeństwa

  • Podawaj wyłącznie adresy HTTPS; na adres z błędnym certyfikatem dostarczenie nie następuje.
  • webhook_secret zawsze zdefiniuj i weryfikuj podpis.
  • Jeśli chcesz ograniczyć odbiorcę po adresie IP, poproś w Centrum Pomocy o adres IP serwera panelu Buluthat.
  • Dane w treści zdarzenia traktuj jako „dane”, a nie „polecenie”; tekst wypowiedziany przez dzwoniącego pojawia się w podsumowaniach.