> 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

## Übersicht

Bestimmte Ereignisse in ElevenLabs können so konfiguriert werden, dass sie Webhooks auslösen. Dadurch können externe Anwendungen und Systeme diese Ereignisse beim Auftreten empfangen und verarbeiten. Derzeit werden folgende Ereignistypen unterstützt:

| Ereignistyp                      | Beschreibung                                                                                                                                    |
| -------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
| `post_call_transcription`        | Ein Anruf über die Agents Platform ist beendet und die Analyse abgeschlossen                                                                    |
| `voice_removal_notice`           | Eine freigegebene Stimme soll entfernt werden                                                                                                   |
| `voice_removal_notice_withdrawn` | Die Entfernung einer freigegebenen Stimme ist nicht mehr geplant                                                                                |
| `voice_removed`                  | Eine freigegebene Stimme wurde entfernt und ist nicht mehr nutzbar                                                                              |
| `flows_generation`               | Eine [Image-&-Video-Generierung](/docs/de/eleven-api/guides/how-to/image-and-video/webhooks) wurde abgeschlossen oder ist fehlgeschlagen        |
| `flows_template_run`             | Ein [Template-Durchlauf](/docs/de/eleven-api/guides/how-to/templates/run-a-template#get-the-result) wurde abgeschlossen oder ist fehlgeschlagen |

## Konfiguration

Webhooks können auf der Seite mit den allgemeinen Einstellungen erstellt, deaktiviert und gelöscht werden. Für Nutzer in [Workspaces](/docs/de/overview/administration/workspaces/overview) können nur Workspace-Administratoren die Webhooks für den Workspace konfigurieren.

![HMAC-Webhook-Konfiguration](/docs/_fern-img/9ea298daac1c64eb43c802a12f7824e83accca44ba2edd1d01a39bcd62c0b9d6.webp)

Nach der Erstellung kann der Webhook ausgewählt werden, um in Produkteinstellungen wie [Agents Platform](/docs/de/eleven-agents/workflows/post-call-webhooks) auf Ereignisse zu warten.

Die Ereignisse `flows_generation` und `flows_template_run` werden beide über ein Abonnement aktiviert: Aktivieren Sie unter **Select events to listen to** die Option **Image & Video API generation or template run completed**, oder übergeben Sie das Ereignis `flows` an [Workspace-Webhook aktualisieren](/docs/de/api-reference/webhooks/update). Eine Generierung oder ein Durchlauf sendet sein Ereignis nur, wenn die Erstellungsanfrage ein Feld `webhook` enthält.

Webhooks können jederzeit auf der Seite mit den allgemeinen Einstellungen deaktiviert werden. Webhooks, die wiederholt fehlschlagen, werden automatisch deaktiviert, wenn es 10 oder mehr aufeinanderfolgende Fehler gibt und die letzte erfolgreiche Zustellung mehr als 7 Tage zurückliegt oder nie eine erfolgreiche Zustellung erfolgte. Automatisch deaktivierte Webhooks müssen auf der Einstellungsseite wieder aktiviert werden. Webhooks können gelöscht werden, wenn sie von keinem Produkt verwendet werden.

## Wiederholungen

Webhook-Wiederholungen können für jeden Webhook aktiviert werden, um die Zustellung bei fehlgeschlagenen Anfragen automatisch erneut zu versuchen. Wiederholungen sind standardmäßig deaktiviert. Aktivieren Sie Wiederholungen beim Erstellen oder Aktualisieren eines Webhooks über die [API](/docs/de/api-reference/webhooks/create) oder in den Webhook-Einstellungen.

> **Note**
>
> Wiederholungen werden für ElevenAgents-[Webhooks nach dem Anruf](/docs/de/eleven-agents/workflows/post-call-webhooks) unterstützt, einschließlich Ereignissen für Transkription
> (`post_call_transcription`), Audio (`post_call_audio`) und fehlgeschlagene Anrufinitiierung
> (`call_initiation_failure`).

### Wiederholungsplan

Wenn ein Zustellversuch mit einem wiederholbaren Fehler fehlschlägt, versucht das System die Zustellung bis zu fünfmal erneut, mit zunehmenden Verzögerungen zwischen den Versuchen:

| Versuch | Verzögerung |
| ------- | ----------- |
| 1       | Sofort      |
| 2       | 30 Sekunden |
| 3       | 2 Minuten   |
| 4       | 8 Minuten   |
| 5       | 30 Minuten  |

Zu jeder Wiederholung wird eine kleine zufällige Abweichung von bis zu 10 % der Verzögerung hinzugefügt, um die Last zu verteilen und Thundering-Herd-Probleme zu vermeiden.

### Wiederholbare Fehler

Nicht jeder Fehler löst eine Wiederholung aus. Nur folgende Fehler gelten als wiederholbar:

* Statuscodes `5xx` (Serverfehler wie 500, 502, 503, 504).
* `429` (Too Many Requests).
* `408` (Request Timeout).
* Verbindungsfehler und Anfrage-Timeouts.

Anfragefehler im Bereich `4xx` (etwa 400, 401, 403, 404) werden **nicht** wiederholt, da sie in der Regel auf ein Konfigurationsproblem hinweisen, das manuell behoben werden muss.

### Warteschlangenlimits pro Webhook

Jeder Webhook ist auf 100 ausstehende Wiederholungsjobs begrenzt. Wenn ein Webhook mehr als 100 Wiederholungen in der Warteschlange ansammelt, werden weitere Jobs verworfen, bis bestehende Wiederholungen verarbeitet wurden. Das verhindert, dass ein einzelner falsch konfigurierter Webhook übermäßig viele Ressourcen verbraucht.

Audio-Webhooks haben zwei zusätzliche Limits. Eine Audio-Nutzlast von mehr als 50 MiB wird einmal zugestellt und nicht wiederholt. Außerdem dürfen die in der Warteschlange befindlichen Audio-Wiederholungen für einen einzelnen Webhook insgesamt 400 MiB nicht überschreiten.

### Verhalten bei automatischer Deaktivierung

Das System verfolgt aufeinanderfolgende Zustellfehler für jeden Webhook. Ein Webhook wird automatisch deaktiviert, wenn beide folgenden Bedingungen erfüllt sind:

* Es sind 10 oder mehr aufeinanderfolgende Zustellfehler aufgetreten.
* Der Webhook wurde nie erfolgreich zugestellt oder die letzte erfolgreiche Zustellung liegt mehr als 7 Tage zurück.

Wenn ein Webhook automatisch deaktiviert wird, erhalten Workspace-Administratoren eine E-Mail-Benachrichtigung. Der Webhook muss auf der Einstellungsseite manuell wieder aktiviert werden, bevor er Zustellungen fortsetzt.

## Integration

Um Webhooks zu integrieren, erstellen Sie einen Endpoint-Handler, der Webhook-Ereignisdaten als POST-Anfragen empfängt. Nach der Validierung der Signatur sollte der Handler umgehend HTTP 200 zurückgeben, um den erfolgreichen Empfang zu bestätigen. Wenn wiederholt keine erfolgreiche Antwort zurückgegeben wird, kann der Webhook automatisch deaktiviert werden.

Die Nutzlast bei einer Wiederholung ist identisch mit dem ursprünglichen Zustellversuch. Webhook-Empfänger können anhand der Nutzlast allein nicht zwischen einer ersten Zustellung und einer Wiederholung unterscheiden. Gestalten Sie Ihren Handler daher **idempotent** – die mehrfache Verarbeitung desselben Ereignisses sollte dasselbe Ergebnis erzeugen. Verwenden Sie bei Bedarf `event_timestamp` und ereignisspezifische Kennungen wie `conversation_id`, um Ereignisse zu deduplizieren.

### Felder der obersten Ebene

| Feld              | Typ    | Beschreibung              |
| ----------------- | ------ | ------------------------- |
| `type`            | string | Typ des Ereignisses       |
| `data`            | object | Daten für das Ereignis    |
| `event_timestamp` | string | Zeitpunkt des Ereignisses |

## Beispiel für eine Webhook-Nutzlast

```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"
      }
    }
  }
}
```

## Authentifizierung

Der Listener muss alle eingehenden Webhooks validieren. Webhooks unterstützen derzeit die Authentifizierung über HMAC-Signaturen. So richten Sie die HMAC-Authentifizierung ein:

* Speichern Sie das beim Erstellen des Webhooks generierte gemeinsame Geheimnis sicher.
* Verifizieren Sie den Header ElevenLabs-Signature in Ihrem Endpunkt mithilfe des SDK.

Das JavaScript-SDK stellt `constructEvent` bereit, das Python-SDK `construct_event` mit **`rawBody`**, **`sig_header`** und **`secret`** (diese heißen in Python nicht `payload` / `signature`). Beide verifizieren die Signatur, validieren den Zeitstempel und parsen die JSON-Nutzlast.

#### Python

Beispiel für einen Webhook-Handler mit FastAPI:

```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

Beispiel für einen Webhook-Handler mit Express:

```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

Beispiel für einen Webhook-Handler mit einer Next.js-API-Route:

**`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 });
}
```