> This is a page from the ElevenLabs documentation. For a complete page index, fetch https://elevenlabs.io/docs/llms.txt. For the full documentation in a single file, fetch https://elevenlabs.io/docs/llms-full.txt.

# Webhooks

## 概要

ElevenLabs内の特定のイベントはwebhookをトリガーするよう設定でき、外部アプリケーションやシステムで発生時にイベントを受信・処理できます。現在サポートされているイベントタイプは次のとおりです。

| イベントタイプ                          | 説明                                                                                              |
| -------------------------------- | ----------------------------------------------------------------------------------------------- |
| `post_call_transcription`        | Agents Platformの通話が終了し、分析が完了した                                                                  |
| `voice_removal_notice`           | 共有音声の削除が予定されている                                                                                 |
| `voice_removal_notice_withdrawn` | 共有音声の削除予定が取り消された                                                                                |
| `voice_removed`                  | 共有音声が削除され、使用できなくなった                                                                             |
| `flows_generation`               | [画像＆ビデオの生成](/docs/ja/eleven-api/guides/how-to/image-and-video/webhooks)が完了または失敗した               |
| `flows_template_run`             | [テンプレート実行](/docs/ja/eleven-api/guides/how-to/templates/run-a-template#get-the-result)が完了または失敗した |

## 設定

webhookは、一般設定ページから作成、無効化、削除できます。[ワークスペース](/docs/ja/overview/administration/workspaces/overview)内のユーザーについては、ワークスペース管理者のみがワークスペースのwebhookを設定できます。

![HMAC webhookの設定](/docs/_fern-img/9ea298daac1c64eb43c802a12f7824e83accca44ba2edd1d01a39bcd62c0b9d6.webp)

作成後、[Agents Platform](/docs/ja/eleven-agents/workflows/post-call-webhooks)などのプロダクト設定で、イベントをリッスンするwebhookを選択できます。

`flows_generation`イベントと`flows_template_run`イベントは、どちらも1つのサブスクリプションで有効になります。**リッスンするイベントを選択**で**画像＆ビデオAPIの生成またはテンプレート実行の完了**にチェックを入れるか、[ワークスペースwebhookを更新](/docs/ja/api-reference/webhooks/update)に`flows`イベントを渡します。生成または実行は、作成リクエストに`webhook`フィールドが含まれる場合にのみイベントを送信します。

webhookはいつでも一般設定ページから無効化できます。10回以上連続して失敗し、最後の配信成功から7日以上経過しているか、一度も配信に成功していない場合、繰り返し失敗するwebhookは自動的に無効化されます。自動的に無効化されたwebhookは、設定ページから再度有効にする必要があります。どのプロダクトでも使用されていないwebhookは削除できます。

## リトライ

webhookごとにリトライを有効にすると、リクエストが失敗した際に配信を自動で再試行できます。リトライはデフォルトで無効です。[API](/docs/ja/api-reference/webhooks/create)経由でwebhookを作成または更新する際、またはwebhook設定で有効にしてください。

> **Note**
>
> リトライは、文字起こし（`post_call_transcription`）、オーディオ（`post_call_audio`）、通話開始失敗（`call_initiation_failure`）イベントを含む、ElevenAgentsの[通話後webhook](/docs/ja/eleven-agents/workflows/post-call-webhooks)でサポートされています。

### リトライスケジュール

再試行可能なエラーで配信試行が失敗した場合、試行間の遅延を増やしながら最大5回再試行します。

| 試行 | 遅延  |
| -- | --- |
| 1  | 即時  |
| 2  | 30秒 |
| 3  | 2分  |
| 4  | 8分  |
| 5  | 30分 |

負荷を分散し、サンダリングハード問題を回避するため、各リトライには小さなランダムジッター（遅延の最大10%）が追加されます。

### 再試行可能なエラー

すべての失敗でリトライがトリガーされるわけではありません。再試行可能と見なされる失敗は以下のみです。

* `5xx`ステータスコード（500、502、503、504などのサーバーエラー）。
* `429`（リクエスト過多）。
* `408`（リクエストタイムアウト）。
* 接続エラーおよびリクエストタイムアウト。

`4xx`の範囲にあるリクエストエラー（400、401、403、404など）は、通常は手動での修正が必要な設定上の問題を示すため、**リトライされません**。

### webhookごとのキュー上限

各webhookは、保留中のリトライジョブが100件までに制限されます。webhookに100件を超えるリトライがキューに蓄積された場合、既存のリトライが処理されるまで追加ジョブは破棄されます。これにより、設定ミスのある1つのwebhookが過剰なリソースを消費することを防ぎます。

オーディオwebhookには追加で2つの制限があります。50MiBを超えるオーディオペイロードは1回のみ配信され、リトライされません。また、1つのwebhookでキューに入れられるオーディオのリトライは、合計400MiBを超えることはできません。

### 自動無効化の動作

システムはwebhookごとに連続した配信失敗を追跡します。以下の両方の条件を満たすと、webhookは自動的に無効化されます。

* 10回以上連続して配信に失敗した。
* webhookの配信が一度も成功していない、または最後の配信成功から7日以上経過している。

webhookが自動的に無効化されると、ワークスペース管理者にメール通知が送信されます。配信を再開するには、設定ページから手動でwebhookを再度有効にする必要があります。

## インテグレーション

webhookとインテグレーションするには、POSTリクエストとしてwebhookイベントデータを受信するエンドポイントハンドラーを作成します。署名を検証した後、正常に受信したことを示すため、ハンドラーは速やかにHTTP 200を返す必要があります。成功レスポンスを繰り返し返せない場合、webhookが自動的に無効化されることがあります。

リトライのペイロードは元の配信試行と同一です。webhookコンシューマーはペイロードだけでは初回配信とリトライを区別できないため、ハンドラーは**冪等**に設計してください。同じイベントを複数回処理しても、同じ結果になる必要があります。必要に応じて、`event_timestamp`とイベント固有の識別子（`conversation_id`など）を使用してイベントを重複排除してください。

### トップレベルフィールド

| フィールド             | 型      | 説明          |
| ----------------- | ------ | ----------- |
| `type`            | string | イベントの種類     |
| `data`            | object | イベントのデータ    |
| `event_timestamp` | string | このイベントの発生日時 |

## webhookペイロードの例

```json
{
  "type": "post_call_transcription",
  "event_timestamp": 1739537297,
  "data": {
    "agent_id": "xyz",
    "conversation_id": "abc",
    "status": "done",
    "transcript": [
      {
        "role": "agent",
        "message": "Hey there angelo. How are you?",
        "tool_calls": null,
        "tool_results": null,
        "feedback": null,
        "time_in_call_secs": 0,
        "conversation_turn_metrics": null
      },
      {
        "role": "user",
        "message": "Hey, can you tell me, like, a fun fact about 11 Labs?",
        "tool_calls": null,
        "tool_results": null,
        "feedback": null,
        "time_in_call_secs": 2,
        "conversation_turn_metrics": null
      },
      {
        "role": "agent",
        "message": "I do not have access to fun facts about Eleven Labs. However, I can share some general information about the company. Eleven Labs is an AI voice technology platform that specializes in voice cloning and text-to-speech...",
        "tool_calls": null,
        "tool_results": null,
        "feedback": null,
        "time_in_call_secs": 9,
        "conversation_turn_metrics": {
          "convai_llm_service_ttfb": {
            "elapsed_time": 0.3704247010173276
          },
          "convai_llm_service_ttf_sentence": {
            "elapsed_time": 0.5551181449554861
          }
        }
      }
    ],
    "metadata": {
      "start_time_unix_secs": 1739537297,
      "call_duration_secs": 22,
      "cost": 296,
      "deletion_settings": {
        "deletion_time_unix_secs": 1802609320,
        "deleted_logs_at_time_unix_secs": null,
        "deleted_audio_at_time_unix_secs": null,
        "deleted_transcript_at_time_unix_secs": null,
        "delete_transcript_and_pii": true,
        "delete_audio": true
      },
      "feedback": {
        "overall_score": null,
        "likes": 0,
        "dislikes": 0
      },
      "authorization_method": "authorization_header",
      "charging": {
        "dev_discount": true
      },
      "termination_reason": ""
    },
    "analysis": {
      "evaluation_criteria_results": {},
      "data_collection_results": {},
      "call_successful": "success",
      "transcript_summary": "The conversation begins with the agent asking how Angelo is, but Angelo redirects the conversation by requesting a fun fact about 11 Labs. The agent acknowledges they don't have specific fun facts about Eleven Labs but offers to provide general information about the company. They briefly describe Eleven Labs as an AI voice technology platform specializing in voice cloning and text-to-speech technology. The conversation is brief and informational, with the agent adapting to the user's request despite not having the exact information asked for."
    },
    "conversation_initiation_client_data": {
      "conversation_config_override": {
        "agent": {
          "prompt": null,
          "first_message": null,
          "language": "en"
        },
        "tts": {
          "voice_id": null
        }
      },
      "custom_llm_extra_body": {},
      "dynamic_variables": {
        "user_name": "angelo"
      }
    }
  }
}
```

## 認証

受信側は、すべての受信Webhookを検証することが重要です。Webhookは現在、HMAC署名による認証に対応しています。HMAC認証は次の手順で設定します。

* Webhookの作成時に生成された共有シークレットを安全に保存する
* SDKを使用してエンドポイントでElevenLabs-Signatureヘッダーを検証する

JavaScript SDKでは`constructEvent`を、Python SDKでは\*\*`rawBody`**、**`sig_header`**、**`secret`\*\*を指定する`construct_event`を利用できます（Pythonでは`payload`／`signature`という名前ではありません）。どちらも署名の検証、タイムスタンプの検証、JSONペイロードの解析を行います。

#### Python

FastAPIを使用したWebhookハンドラーの例：

```python
from dotenv import load_dotenv
from fastapi import FastAPI, Request
from fastapi.responses import JSONResponse
from elevenlabs.client import ElevenLabs
from elevenlabs.errors import BadRequestError
import os

load_dotenv()

app = FastAPI()
elevenlabs = ElevenLabs(
    api_key=os.getenv("ELEVENLABS_API_KEY"),
)

WEBHOOK_SECRET = os.getenv("WEBHOOK_SECRET")

@app.post("/webhook")
async def receive_message(request: Request):
    payload = await request.body()
    signature = request.headers.get("elevenlabs-signature")

    try:
        event = elevenlabs.webhooks.construct_event(
            rawBody=payload.decode("utf-8"),
            sig_header=signature,
            secret=WEBHOOK_SECRET,
        )
    except BadRequestError as e:
        return JSONResponse(content={"error": "Invalid signature"}, status_code=401)

    # construct_event returns a dict (parsed JSON), not an object with attributes
    if event.get("type") == "post_call_transcription":
        print(f"Received transcription: {event.get('data')}")

    return {"status": "received"}
```

#### JavaScript

#### Express

Expressを使用したWebhookハンドラーの例：

```javascript
import { ElevenLabsClient } from '@elevenlabs/elevenlabs-js';
import express from 'express';

const app = express();

const elevenlabs = new ElevenLabsClient();
const WEBHOOK_SECRET = process.env.WEBHOOK_SECRET;

// Use express.text() to preserve raw body for signature verification
app.post('/webhook', express.text({ type: 'application/json' }), async (req, res) => {
  const signature = req.headers['elevenlabs-signature'];
  const payload = req.body; // Raw string body

  let event;
  try {
    event = await elevenlabs.webhooks.constructEvent(payload, signature, WEBHOOK_SECRET);
  } catch (error) {
    return res.status(401).json({ error: 'Invalid signature' });
  }

  // Process the webhook event
  if (event.type === 'post_call_transcription') {
    console.log('Received transcription:', event.data);
  }

  res.status(200).json({ received: true });
});
```

#### Next.js

Next.js APIルートを使用したWebhookハンドラーの例：

**`app/api/webhook/route.ts`**

```typescript app/api/webhook/route.ts
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
import { ElevenLabsClient } from '@elevenlabs/elevenlabs-js';

const elevenlabs = new ElevenLabsClient();
const WEBHOOK_SECRET = process.env.WEBHOOK_SECRET;

export async function POST(req: NextRequest) {
  const body = await req.text();
  const signature = req.headers.get('elevenlabs-signature');

  let event;
  try {
    event = await elevenlabs.webhooks.constructEvent(body, signature, WEBHOOK_SECRET);
  } catch (error) {
    return NextResponse.json({ error: 'Invalid signature' }, { status: 401 });
  }

  // Process the webhook event
  if (event.type === 'post_call_transcription') {
    console.log('Received transcription:', event.data);
  }

  return NextResponse.json({ received: true }, { status: 200 });
}
```