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配信ID。再試行しても同じ値が保たれます(冪等キーとしてご利用ください)
X-Buluthat-Signaturesha256= + 本文の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時間。6回目の試行後は中止され、パネルに failed と表示されます。同じイベントが複数回届くことがあります。 X-Buluthat-Delivery で重複を除外してください。

イベント

自動発信

イベントいつdata
call_finished通話が終了し、結果が確定(番号ごとに1回)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のURLとシークレットは、アシスタントのフォームで設定します。

音声確認コード

イベントいつ
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で制限する場合は、BuluthatのパネルサーバーのIPをサポートセンターにご請求ください。
  • イベント本文のデータは「指示」ではなく「データ」として処理してください。発信者の発言内容は要約に含まれます。