setup-webhook について
通話イベントを受信し、通話に影響するデータを返せるサーバー URL を設定する Vapi webhook スキルです。URL の設定階層、イベント処理、認証、ローカル開発を扱います。
主な機能
- 01アシスタント、番号、組織の URL 設定
- 02通話イベントとツールイベントの処理
- 03認証情報を使った認証設定
- 04パブリックトンネル経由のローカルイベント転送
- 05通話終了レポート項目の確認
活用シーン
- 01文字起こしと通話状態の変化を受信
- 02アシスタントのツール呼び出しに結果を返す
- 03ローカル開発中の webhook 処理のテスト
- 04認証情報による Vapi サーバー URL の保護
MCP 対応
README では、互換性のある AI エージェントがドキュメントを検索できる Vapi ドキュメント MCP サーバーに触れています。
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ vapiai/ skills --skill setup-webhookインストール後、Claude Code で/setup-webhookを入力して読み込まれたか確認します。
同梱ファイルreferences/webhook-events.md
詳細
Vapi Webhook/サーバー URL の設定
通話中に Vapi からリアルタイムイベント(文字起こし、ツール呼び出し、ステータス変更、通話終了レポート)を受信するためのサーバー URL を設定します。
セットアップ:
VAPI_API_KEYが設定されていることを確認してください。必要に応じてsetup-api-keyスキルを参照してください。
概要
Vapi は「サーバー URL」(Webhook)を使ってアプリケーションと通信します。一方向の従来型 Webhook とは異なり、Vapi のサーバー URL は双方向通信に対応しているため、サーバーから通話に影響するデータを返すことができます。
サーバー URL の設定場所
アシスタントに設定する場合
curl -X PATCH https://api.vapi.ai/assistant/{id} \
-H "Authorization: Bearer $VAPI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"server": {
"url": "https://your-server.com/vapi/webhook",
"credentialId": "cred_abc123"
}
}'
Dashboard > Custom Credentials で省略可能な credentialId を作成します。意図的に公開しているエンドポイントの場合に限り、省略してください。
電話番号に設定する場合
電話番号の更新にも、url と省略可能な credentialId を含む server オブジェクトを使用します。API 経由で更新する場合は、まず電話番号を取得し、PATCH 本文で既存の provider 識別子を保持してください。プロバイダーが不明な場合は、ダッシュボードを使うのが最も安全です。
組織レベルで設定する場合
Vapi ダッシュボードの Settings > Server URL でデフォルトのサーバー URL を設定します。
優先順位:ツールのサーバー URL > アシスタントのサーバー URL > 電話番号のサーバー URL > 組織のサーバー URL。
イベントの種類
| イベント | 説明 | 応答が必要ですか? |
|---|---|---|
assistant-request | 動的なアシスタント設定のリクエスト | はい — アシスタント設定を返します |
tool-calls | アシスタントがツールを呼び出しています | はい — ツールの結果を返します |
status-update | 通話ステータスが変更されました | いいえ |
transcript | リアルタイムの文字起こしが更新されました | いいえ |
end-of-call-report | 通話が要約とともに完了しました | いいえ |
hang | アシスタントが応答できませんでした | いいえ |
speech-update | 音声アクティビティが検出されました | いいえ |
Webhook サーバーの例(Express.js)
import express from "express";
const app = express();
app.use(express.json());
app.post("/vapi/webhook", (req, res) => {
const { message } = req.body;
switch (message.type) {
case "assistant-request":
// Dynamically configure the assistant based on the caller
res.json({
assistant: {
name: "Dynamic Assistant",
firstMessage: `Hello ${message.call.customer?.name || "there"}!`,
model: {
provider: "openai",
model: "gpt-4.1",
messages: [
{ role: "system", content: "You are a helpful assistant." },
],
},
voice: { provider: "vapi", voiceId: "Elliot", version: 2 },
transcriber: { provider: "deepgram", model: "nova-3", language: "en" },
},
});
break;
case "tool-calls":
// Handle tool calls from the assistant
const results = (message.toolCallList || []).map((toolCall: any) => ({
toolCallId: toolCall.id,
result: handleToolCall(
toolCall.name,
toolCall.parameters || toolCall.arguments
),
}));
res.json({ results });
break;
case "end-of-call-report":
// Process the call report
console.log("Call ended:", {
callId: message.call.id,
endedReason: message.endedReason,
cost: message.cost,
analysis: message.analysis,
artifact: message.artifact,
});
res.json({});
break;
case "status-update":
console.log("Call status:", message.status);
res.json({});
break;
case "transcript":
console.log(`[${message.role}]: ${message.transcript}`);
res.json({});
break;
default:
res.json({});
}
});
function handleToolCall(name: string, args: any): string {
// Implement your tool logic here
return `Result for ${name}`;
}
app.listen(3000, () => console.log("Webhook server running on port 3000"));
Webhook サーバーの例(Python/Flask)
from flask import Flask, request, jsonify
app = Flask(__name__)
@app.route("/vapi/webhook", methods=["POST"])
def vapi_webhook():
data = request.json
message = data.get("message", {})
msg_type = message.get("type")
if msg_type == "assistant-request":
return jsonify({
"assistant": {
"name": "Dynamic Assistant",
"firstMessage": "Hello! How can I help?",
"model": {
"provider": "openai",
"model": "gpt-4.1",
"messages": [
{"role": "system", "content": "You are a helpful assistant."}
],
},
"voice": {"provider": "vapi", "voiceId": "Elliot", "version": 2},
"transcriber": {"provider": "deepgram", "model": "nova-3", "language": "en"},
}
})
elif msg_type == "tool-calls":
results = []
for tool_call in message.get("toolCallList", []):
results.append({
"toolCallId": tool_call["id"],
"result": f"Handled {tool_call['name']}",
})
return jsonify({"results": results})
elif msg_type == "end-of-call-report":
print(f"Call ended: {message['call']['id']}")
print(f"Summary: {message.get('analysis', {}).get('summary')}")
return jsonify({})
if __name__ == "__main__":
app.run(port=3000)
Webhook 認証
Vapi の Custom Credential を使用し、その ID を server.credentialId に指定します。Vapi は Bearer Token、OAuth 2.0 クライアントクレデンシャル、HMAC クレデンシャルに対応しています。設定したクレデンシャルに応じてリクエストを検証してください。HMAC のヘッダー名、アルゴリズム、タイムスタンプ、ペイロード形式は設定可能なため、固定の x-vapi-signature 形式を前提にしないでください。
Bearer クレデンシャルの場合は、受信した Authorization: Bearer <token> の値を、サーバーで安全に保管しているトークンと照合します。シークレット自体をアシスタントまたは電話番号のペイロードに含めないでください。
ローカル開発
Vapi CLI と公開トンネルを使用します。CLI はポート 4242 からアプリへの転送を行いますが、公開 URL 自体は作成しません。
# Install the CLI
curl -sSL https://vapi.ai/install.sh | bash
# Terminal 1: expose the CLI listener
ngrok http 4242
# Terminal 2: forward events from the CLI to your app
vapi listen --forward-to localhost:3000/vapi/webhook
Vapi のサーバー URL に公開 ngrok URL を設定します。CLI を使わず、Express または Flask サーバーに直接トンネルを接続するには、次のようにします。
ngrok http 3000
# Copy the ngrok URL and set it as your server URL
通話終了レポートのフィールド
end-of-call-report イベントには次の内容が含まれます。
| フィールド | 説明 |
|---|---|
call | メタデータを含む通話オブジェクト全体 |
endedReason | 通話が終了した理由 |
artifact | 録音、文字起こし、メッセージ、その他有効化された成果物 |
analysis | 設定された要約、構造化データ、成功評価 |
cost | 通話の合計コスト |
startedAt / endedAt | 含まれる場合の通話時刻 |
参考資料
- 一般的なサーバー URL イベント — 一般的なイベントのペイロードと応答
- サーバー URL の設定 — 設定場所と優先順位
- サーバー認証 — Custom Credentials
- ローカル開発 — Webhook のローカルテスト
その他のリソース
Vapi は、互換性のある AI エージェントが Vapi のナレッジベースにアクセスできるドキュメント MCP サーバーを提供しています。このスキルの範囲を超える高度な設定、トラブルシューティング、SDK の詳細などについては、ドキュメント検索をご利用ください。
Claude Code に Vapi ドキュメント MCP サーバーを手動で追加するには、次のコマンドを実行します。
claude mcp add vapi-docs -- npx -y mcp-remote https://docs.vapi.ai/_mcp/server
対応しているエージェントへのセットアップ手順については、Vapi MCP 統合ガイドをご覧ください。