Payload 仕様
配信形式
HTTPS POST で JSON ボディが送信されます。Content-Type は application/json。
サンプル Payload (Custom エンドポイント)
{
"projectId": "3c9acfb1-c6b7-4bbc-b6c3-628af54d56c1",
"webhookEndpoint": {
"id": "ep-001",
"name": "本番通知",
"endpointType": "CUSTOM",
"target": "https://example.com/webhook",
"contentKey": null
},
"eventType": "OUTBOUND_CALL_ERROR",
"body": {
"subject": "[Recho] 発信通話エラー",
"text": "[Recho] 発信通話エラー\n━━━━━━━━━━━━━━\ncallId: abc-123\ncallStatus: CALLING\ncallSid: CA94b51...\nclientId: client-1\n━━━━━━━━━━━━━━\nエラー一覧:\n - [NETWORK_ERROR] Connection timed out (phase: CONNECTING)\n━━━━━━━━━━━━━━\n時刻: 2026-05-12 10:24:00",
"data": {
"callId": "abc-123",
"callStatus": "CALLING",
"callSid": "CA94b51...",
"clientId": "client-1"
},
"errors": [
{
"code": "NETWORK_ERROR",
"message": "Connection timed out",
"timestamp": "2026-05-12T10:23:45.000Z",
"where": "OutboundCallAdapter.connect",
"phase": "CONNECTING",
"stacktrace": ""
}
]
},
"authConfig": { "authType": "NONE" }
}
注記
Slack / Teams / Email の場合は内部で適切な形式に変換されます(Custom のみがこの構造を直接受け取ります)。
トップレベルフィールド
| フィールド | 型 | 用途 |
|---|---|---|
projectId | string | 発火元の project ID (UUID)。マルチプロジェクト運用時のルーティングや権限チェックに使う想定 |
webhookEndpoint | WebhookEndpoint | 配信先エンドポイントの設定スナップショット。マルチエンドポイント運用時に「どの設定経由で届いた通知か」を識別する用途 |
eventType | EventType | イベント種別。受信側 switch のキーとして使うのが基本。値の一覧は Events を参照 |
body | WebhookBody | 通知本文(後述) |
authConfig | AuthConfig | このリクエストの認証方式の参照情報。実際の認証検証はリクエストヘッダ側で行う(認証方式 参照)。payload 側はあくまで「何方式で署名されたか」を示すメタ |
webhookEndpoint フィールド
| フィールド | 型 | 用途 |
|---|---|---|
id | string | エンドポイントの ID(Recho 内部の主キー)。ログ突合や問い合わせ時に使用 |
name | string | エンドポイント名(ダッシュボードでの表示名) |
endpointType | 'SLACK' | 'TEAMS' | 'EMAIL' | 'CUSTOM' | エンドポイント種別。Custom のときのみこの payload 構造をそのまま受け取る |
target | string | 設定された宛先(Custom: URL / Slack/Teams: Incoming Webhook URL / Email: メールアドレス)。情報用 |
contentKey | string | null | テンプレート種別キー。null の場合は標準フォーマット |
body フィールド
| フィールド | 型 | 用途 |
|---|---|---|
subject | string | 表示用の件名。メール送信時の Subject、UI 上の見出しなどに使う想定 |
text | string | 表示用の整形済み本文(人間可読)。改行 (\n) と区切り線入り。Slack / Teams 投稿、ログ表示、メール本文などに流すのが想定用途。機械的にパースしないこと |
data | Record<string, string> | 機械可読な識別情報。callId / callStatus / callSid / clientId 等を持つフラットな string→string マップ。プログラム側はここを参照する |
errors | Array<CallError> | undefined | エラー時のみ含まれる配列。受信側は body.errors?.length でエラー判定 → 詳細ログや通知に流用 |
body.data フィールド(通話識別情報)
| フィールド | 型 | 用途 |
|---|---|---|
callId | string | 通話 ID(一意)。外部システムで通話を識別する主キー。同じ callId のイベントは FIFO で配信される(設定ガイド 参照) |
callStatus | string | 通知時点の通話ステータス。値の一覧は callStatus 一覧 参照。エラー判定には使えない(errors 配列の有無で行うこと) |
callSid | string | 電話回線プロバイダ側の通話 ID(無い場合は空文字)。プロバイダ側ログとの突合に使う想定 |
clientId | string | クライアント識別子(任意・無い場合は空文字)。発信時に指定したアプリケーション側 ID をそのまま透過させるためのフィールド |
eventType(イベント種別)
payload の eventType は、Webhook 設定ページの 「通知トリガー」セクションに並ぶ項目と 1 対 1 対応します。つまり通知トリガーで ON にした項目の値が、そのまま payload の eventType として届きます。
全 18 種類の eventType および payload 例は Events ページの一覧表を参照してください。
TypeScript 型定義
type EventType =
// 発信通話 (OUTBOUND)
| 'OUTBOUND_CALL_PENDING'
| 'OUTBOUND_CALL_REQUESTED'
| 'OUTBOUND_CALL_CALLING'
| 'OUTBOUND_CALL_CLOSING'
| 'OUTBOUND_CALL_COMPLETED'
| 'OUTBOUND_CALL_EXPIRED'
| 'OUTBOUND_CALL_NO_RESPONSE'
| 'OUTBOUND_CALL_CANCELED'
| 'OUTBOUND_CALL_BUSY'
| 'OUTBOUND_CALL_UNREACHABLE'
| 'OUTBOUND_CALL_MAX_ATTEMPTS_REACHED'
| 'OUTBOUND_CALL_ERROR'
// 着信通話 (INBOUND)
| 'INBOUND_CALL_CONNECTING'
| 'INBOUND_CALL_CALLING'
| 'INBOUND_CALL_CLOSING'
| 'INBOUND_CALL_COMPLETED'
| 'INBOUND_CALL_CONCURRENCY_LIMIT_EXCEEDED'
| 'INBOUND_CALL_ERROR';
備考
受信したいイベントは、Webhook 設定ページ上部の「通知トリガー」セクションで個別に ON/OFF を切り替えてください。OFF のものは配信されません。
body.errors[] フィールド(エラー詳細)
エラー発生時のみ含まれる配列。1 件以上のエラーオブジェクトが入ります。
| フィールド | 型 | 必須 | 例 | 用途 |
|---|---|---|---|---|
code | string | 必須 | "NETWORK_ERROR" | 機械可読のエラーコード(^[A-Z0-9_]+$)。受信側 switch のキーとして使う。一覧は 主なエラーコード一覧 |
message | string | 必須 | "Connection timed out" | 人間可読のエラーメッセージ(日本語または英語)。表示・ログ用 |
timestamp | string (ISO8601) | 必須 | "2026-05-12T10:23:45.000Z" | エラー発生時刻(UTC・ミリ秒精度)。時系列ソートに使う |
where | string | 必須 | "OutboundCallAdapter.connect" | 発生箇所(クラス名 / 関数名 / モジュール名)。Recho 側調査時の参照情報 |
phase | string | 必須 | "CONNECTING" | 通話のどのフェーズで発生したか。原因切り分けや集計に使う |
stacktrace | string | 必須 | "Error: Connection timed out\n at ..." | スタックトレース。空文字列の場合あり(外部由来エラーなど)。一次調査用 |
重要
エラー判定は body.errors 配列が空でないかで行ってください。body.data.callStatus にはエラー発生時点の遷移中ステータス(CALLING など)が入る場合があり、ERROR 固定ではありません。
TypeScript 型定義
type CallError = {
code: string; // ^[A-Z0-9_]+$ にマッチ
message: string;
timestamp: string; // ISO 8601 (UTC)
where: string;
phase: string;
stacktrace: string;
};
type WebhookBody = {
subject: string;
text: string;
data: Record<string, string>;
errors?: CallError[]; // エラー時のみ
};
主なエラーコード一覧
実際に発生するコードはこれら以外にも存在しえます。受信側は未知の code 値が来ても落ちないよう実装してください(例: switch の default 節でログのみ出力)。
| code | カテゴリ | 説明 |
|---|---|---|
WEBSOCKET_CONNECTION_FAILED | WebSocket 接続 | 音声 AI WebSocket への接続に失敗 |
INVALID_REQUEST_ID | リクエスト検証 | リクエスト ID または電話番号が無効 |
INTERNATIONAL_PERMISSION_ERROR | リクエスト検証 | 国際電話の発信権限なし |
STATUS_UPDATE_TO_CALLING_FAILED | ステータス更新 | CALLING への遷移に失敗 |
STATUS_UPDATE_TO_CLOSING_FAILED | ステータス更新 | CLOSING への遷移に失敗 |
STATUS_UPDATE_TO_FINAL_STATUS_FAILED | ステータス更新 | 最終ステータス(COMPLETED など)への遷移に失敗 |
STATUS_UPDATE_TO_ERROR_FAILED | ステータス更新 | (旧仕様)ERROR への遷移に失敗 |
STATUS_UPDATE_TO_CONCURRENCY_LIMIT_EXCEEDED_FAILED | ステータス更新 | CONCURRENCY_LIMIT_EXCEEDED への遷移に失敗 |
VOICEAI_PROCESSING_ERROR | VoiceAI 処理 | 通話中の VoiceAI 内部処理エラー |
PRE_VOICEAI_RUNNING_FAILED | VoiceAI 処理 | VoiceAI 実行前処理に失敗(設定取得、フック等) |
POST_VOICEAI_RUNNING_FAILED | VoiceAI 処理 | VoiceAI 実行後処理に失敗 |
ANALYZER_FAILED | 分析 | 通話結果分析処理に失敗 |
GEMINI_ANALYZER_FAILED | 分析 | Gemini ベースの分析処理に失敗 |
HISTORY_FORMAT_FAILED | 分析 | 会話履歴のフォーマット処理に失敗 |
CALL_LOG_SAVE_FAILED | CallLog 保存 | 通話ログの永続化に失敗 |
GEMINI_API_UNAVAILABLE | 外部 API | Gemini API が利用不可 |
STATUS_UPDATE_IN_CALLBACK_FAILED | コールバック | 通話切断後のコールバック処理内でのステータス更新失敗 |
CALLBACK_PROCESSING_FAILED | コールバック | 通話切断後のコールバック処理全般での失敗 |
STALE_CALL_STATUS_DETECTED | 内部監視 | ステータスが一定時間遷移しないことを内部監視 Lambda が検知 |
CALL_INITIATION_FAILED | 通話開始 | 電話回線プロバイダ側で通話の開始に失敗 |
NETWORK_ERROR | ネットワーク | ネットワーク I/O 失敗の汎用コード |
TIMEOUT | ネットワーク | 外部リクエストや内部処理のタイムアウト |