開発者
Webhook
通話終了、伝言受付、予約・注文・宿泊予約の変更、キャンペーン終了時に署名付きHTTPS通知を受け取り、それが本当にRinghumからのものかを検証する方法を説明します。
約2分で読めます 24 9月 2026更新
Webhookは、ワークスペースで何かが起きた瞬間に、あなたのサーバーにHTTPSリクエストを送信します。APIをポーリングする代わりにWebhookを使うと、通話が終了した際に要約、結果、収集された詳細情報、文字起こしをすぐに受け取れます。各配信には、あなたとRinghumだけが知る秘密鍵で署名が付けられるため、サーバー側でRinghum以外からのリクエストを拒否できます。
エンドポイントを追加する
エンドポイントの追加・テスト・削除ができるのは、ワークスペースのオーナーと管理者のみです。
- サイドバーの開発者を開きます。
- Webhookカードでエンドポイントを追加をクリックします。
- エンドポイントURLを入力します。
https://で始まる必要があります。 - イベントで、必要なイベントにチェックを入れます。
call.endedはあらかじめチェックされています。 - エンドポイントを追加をクリックします。
- 緑色のボックスに表示された署名シークレット(
whsec_で始まります)をコピーし、サーバーに保存します。完了をクリックします。
重要: 署名シークレットは一度だけ表示されます。紛失した場合は、エンドポイントを削除して再度追加し、新しいシークレットを取得してください。
エンドポイントは必要なだけ追加できます。Webhookはワークスペース内のすべてのアシスタントを対象とします。writeスコープを持つキーを使って、POST /webhooksでAPI経由でエンドポイントを管理することもできます。
イベント
| イベント | 送信タイミング |
|---|---|
call.started |
アシスタントが通話に応答したとき |
call.ended |
通話が終了し要約されたとき(文字起こしと要約を含む) |
call.transferred |
通話が担当者に転送されたとき |
message.taken |
アシスタントが伝言を受け付けたとき |
appointment.booked |
アシスタントが予約を入れたとき |
appointment.rescheduled |
予約の日時が変更されたとき |
appointment.cancelled |
予約がキャンセルされたとき |
order.created |
注文が行われたとき(アシスタント、手動、API経由いずれも) |
order.updated |
注文のステータスが変わったとき |
order.cancelled |
注文がキャンセルされたとき |
reservation.created |
部屋が予約されたとき(アシスタント、手動、API経由いずれも) |
reservation.updated |
予約のステータスが変わったとき(確定、チェックイン、チェックアウト、無断キャンセル) |
reservation.cancelled |
予約がキャンセルされたとき |
campaign.completed |
発信キャンペーンがリストへの発信を終えたとき |
test.ping |
テストを送信をクリックしたとき |
配信内容の例
各配信は、JSON本文と以下のヘッダーを持つPOSTリクエストです。
POST https://example.com/hooks/ringhum
Content-Type: application/json
User-Agent: Ringhum-Webhooks/1.0
X-Ringhum-Event: call.ended
X-Ringhum-Timestamp: 1789250000
X-Ringhum-Signature: v1=5f1a…
{
"id": "evt_8f2k…",
"type": "call.ended",
"created_at": "2026-09-24T14:03:11+00:00",
"data": {
"call_id": 4812,
"direction": "inbound",
"from": "+14155550132",
"to": "+14155550100",
"assistant_id": 3,
"status": "completed",
"outcome": "message_taken",
"sentiment": "neutral",
"duration_seconds": 94,
"summary": "Caller asked for a quote for a kitchen repair…",
"extracted": { "name": "Dana Lee", "reason": "Quote" },
"transcript": [
{ "role": "assistant", "content": "Hello, you've reached…" },
{ "role": "user", "content": "Hi, I'd like a quote…" }
]
}
}
dataオブジェクトの内容はイベントによって異なります。
call.endedとmessage.taken:上記の通話項目。call.startedとcall.transferred:call_id、direction、from、to、assistant_id、status、started_at。appointment.*:appointment_id、title、status、starts_at、ends_at、timezone、customer(名前、電話番号、メール)、contact_id、service、staff、call_id、notes。order.*:order_id、number、status、fulfillment、customer、address、オプションと価格を含むitems、currency、subtotal、fee、total、source、call_id、キャンセルの場合はcancel_reason。reservation.*:reservation_id、number、status、room、check_in、check_out、nights、adults、children、guest、currency、nightly、total、source。campaign.completed:campaign_id、name、キャンペーンの進捗件数。
注: 通話中にアシスタントが予約を取った場合、
appointment.bookedが2回届くことがあります。1回目は予約成立時に予約項目とともに、2回目は通話の要約後に通話項目とともに送信されます。dataにappointment_idかcall_idのどちらが含まれているかを確認し、idフィールドを使って二重処理を避けてください。
署名を検証する
署名は、タイムスタンプ、ドット、リクエスト本文の生データを、エンドポイントの署名シークレットで鍵付けしたHMAC-SHA256です。v1=に続けて16進ダイジェストの形で送信されます。
- JSONとしてパースする前の、受信した通りの生の本文を読み取ります。
{X-Ringhum-Timestamp}.{生の本文}という文字列を組み立てます。- シークレットでHMAC-SHA256を計算し、先頭に
v1=を付けます。 - 定数時間比較を使って
X-Ringhum-Signatureと照合します。 - リプレイ攻撃を防ぐため、タイムスタンプが5分以上前の場合はリクエストを拒否します。
Node.js:
const crypto = require('crypto');
function isValid(req, rawBody, secret) {
const ts = req.header('X-Ringhum-Timestamp');
const sig = req.header('X-Ringhum-Signature') || '';
const expected = 'v1=' + crypto.createHmac('sha256', secret).update(`${ts}.${rawBody}`).digest('hex');
const fresh = Math.abs(Date.now() / 1000 - Number(ts)) < 300;
return fresh && sig.length === expected.length &&
crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected));
}
PHP:
$ts = $_SERVER['HTTP_X_RINGHUM_TIMESTAMP'] ?? '';
$sig = $_SERVER['HTTP_X_RINGHUM_SIGNATURE'] ?? '';
$expected = 'v1=' . hash_hmac('sha256', $ts . '.' . file_get_contents('php://input'), $secret);
if (! hash_equals($expected, $sig) || abs(time() - (int) $ts) > 300) {
http_response_code(400);
exit;
}
レスポンス、タイムアウト、再試行
- 配信を確認するには、
2xxのいずれかのステータスで応答してください。時間のかかる処理は、応答した後に行ってください。 - Ringhumは、応答を最大10秒間待ちます。
- エンドポイントが
2xxで応答しない場合、配信は合計最大3回試行されます:即座に1回、約10秒後にもう1回、約60秒後に最後の1回です。その後は破棄されます。 - 配信は順序どおりに届かないことがあります。
created_atとdata内のIDを使って順序を並べ替えてください。
Webhookの表には、各エンドポイントの最終HTTPステータスと送信日時が表示されます。失敗したエンドポイントもそのまま有効な状態が続きます。Ringhumが自動でオフにすることはありません。
テスト、一時停止、削除
- テストを送信は
test.pingイベントを即座に送信し、エンドポイントから返されたHTTPステータスがメッセージで表示されます。 - 有効スイッチでエンドポイントを一時停止できます。オフの間に発生したイベントは、後から送信されることはありません。
- 削除で、エンドポイントとそのシークレットが削除されます。
よくある質問
連携ページのZapier、Make、n8nとの違いは何ですか? それらの連携は、連携ページとその6種類のイベントを使用します。本文は{"event", "workspace", "sent_at", "data"}の形式で、シークレットを設定した場合の署名ヘッダーはX-Ringhum-Signature: sha256=…という、本文のみのHMAC-SHA256です。ここで説明している開発者向けWebhookは、より多くのイベントをカバーし、タイムスタンプ付きのv1=署名を使用します。詳しくは送信する内容を選ぶをご覧ください。
エンドポイントは2xxを返しているのに、コード側で何も受信できません。 そのエンドポイントでイベントにチェックが入っているか、エンドポイントが有効になっているか、ファイアウォールがインターネットからのリクエストを許可しているかを確認してください。
署名の検証が失敗するのはなぜですか? 多くの場合、ハッシュ計算の前に本文がパースされ、再エンコードされていることが原因です。受信した生のバイト列をそのままハッシュ化してください。
関連記事
APIキーとスコープ
開発者ページでAPIキーを作成・取り消しし、読み取りまたは書き込みのアクセス権を選択する方法と、Ringhum REST APIの基本(ベースURL、認証、ページネーション、エラー、レート制限)について説明します。
RinghumをClaudeなどのAIツールに接続する(MCP)
Model Context Protocolに対応したClaude、ChatGPT、Cursor、VS CodeなどのAIアプリにRinghumをコネクタとして追加し、参照のみか参照と変更のどちらのアクセス権にするかを選び、アプリの接続を解除する方法を説明します。
送信する内容を選ぶ
連携アプリごとに、どの通話、受信トレイの項目、予約、注文を受け取るかを選び、対応が必要な通話のみに通話更新を絞り込む方法を説明します。
アプリを連携する
Slack、CRM、ヘルプデスク、タスク管理ツール、スプレッドシート、ショップ、カレンダーをRinghumに連携する方法、各アプリで使われる連携方式、動作確認の方法を説明します。
解決しませんか?
[email protected]までメールするか、メッセージを送る。TeamプランとScaleプランは優先サポートを受けられます。