> 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

## Overzicht

Je kunt bepaalde gebeurtenissen binnen ElevenLabs configureren om webhooks te activeren, zodat externe applicaties en systemen deze gebeurtenissen kunnen ontvangen en verwerken zodra ze plaatsvinden. De momenteel ondersteunde gebeurtenistypen zijn:

| Gebeurtenistype                  | Beschrijving                                                         |
| -------------------------------- | -------------------------------------------------------------------- |
| `post_call_transcription`        | Een gesprek in Agents Platform is afgerond en de analyse is voltooid |
| `voice_removal_notice`           | Een gedeelde stem is gepland om te worden verwijderd                 |
| `voice_removal_notice_withdrawn` | Een gedeelde stem staat niet langer gepland voor verwijdering        |
| `voice_removed`                  | Een gedeelde stem is verwijderd en kan niet langer worden gebruikt   |

## Configuratie

Je kunt webhooks maken, uitschakelen en verwijderen via de pagina met algemene instellingen. Voor gebruikers binnen [Workspaces](/docs/nl/overview/administration/workspaces/overview) kunnen alleen workspacebeheerders de webhooks voor de workspace configureren.

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

Na het maken kun je de webhook selecteren om te luisteren naar gebeurtenissen in productinstellingen, zoals [Agents Platform](/docs/nl/eleven-agents/workflows/post-call-webhooks).

Je kunt webhooks op elk moment uitschakelen via de pagina met algemene instellingen. Webhooks die herhaaldelijk mislukken, worden automatisch uitgeschakeld als er 10 of meer opeenvolgende fouten zijn en de laatste succesvolle levering meer dan 7 dagen geleden was of nog nooit succesvol is afgeleverd. Automatisch uitgeschakelde webhooks moet je opnieuw inschakelen via de instellingenpagina. Je kunt webhooks verwijderen als ze niet door producten worden gebruikt.

## Nieuwe pogingen

Je kunt per webhook nieuwe pogingen inschakelen om de aflevering automatisch opnieuw te proberen wanneer een request mislukt. Nieuwe pogingen zijn standaard uitgeschakeld. Schakel nieuwe pogingen in wanneer je een webhook maakt of bijwerkt via de [API](/docs/nl/api-reference/webhooks/create) of in de webhookinstellingen.

> **Note**
>
> Nieuwe pogingen worden ondersteund voor ElevenAgents-[webhooks na een gesprek](/docs/nl/eleven-agents/workflows/post-call-webhooks), waaronder gebeurtenissen voor transcriptie
> (`post_call_transcription`), audio (`post_call_audio`) en een mislukte gespreksstart
> (`call_initiation_failure`).

### Schema voor nieuwe pogingen

Wanneer een afleveringspoging mislukt met een fout waarvoor een nieuwe poging mogelijk is, probeert het systeem maximaal 5 keer opnieuw met steeds langere vertragingen tussen de pogingen:

| Poging | Vertraging   |
| ------ | ------------ |
| 1      | Onmiddellijk |
| 2      | 30 seconden  |
| 3      | 2 minuten    |
| 4      | 8 minuten    |
| 5      | 30 minuten   |

Aan elke nieuwe poging wordt een kleine willekeurige afwijking toegevoegd (maximaal 10% van de vertraging) om de belasting te verdelen en problemen door gelijktijdige pieken te voorkomen.

### Fouten waarvoor opnieuw wordt geprobeerd

Niet alle fouten leiden tot een nieuwe poging. Alleen de volgende fouten worden beschouwd als fouten waarvoor opnieuw wordt geprobeerd:

* `5xx`-statuscodes (serverfouten zoals 500, 502, 503, 504).
* `429` (Te veel requests).
* `408` (Request-time-out).
* Verbindingsfouten en request-time-outs.

Requestfouten in het `4xx`-bereik (zoals 400, 401, 403, 404) worden **niet** opnieuw geprobeerd, omdat deze doorgaans wijzen op een configuratieprobleem dat handmatig moet worden opgelost.

### Wachtrijlimieten per webhook

Elke webhook is beperkt tot 100 wachtende nieuwe pogingstaken. Als een webhook meer dan 100 nieuwe pogingen in de wachtrij verzamelt, worden aanvullende taken verwijderd totdat bestaande nieuwe pogingen zijn verwerkt. Dit voorkomt dat één verkeerd geconfigureerde webhook buitensporig veel resources verbruikt.

Audio-webhooks hebben twee extra limieten. Een audiopayload groter dan 50 MiB wordt één keer afgeleverd en niet opnieuw geprobeerd, en de nieuwe audiopogingen in de wachtrij voor één webhook mogen in totaal niet groter zijn dan 400 MiB.

### Gedrag bij automatisch uitschakelen

Het systeem houdt opeenvolgende afleveringsfouten bij voor elke webhook. Een webhook wordt automatisch uitgeschakeld wanneer aan beide volgende voorwaarden is voldaan:

* Er zijn 10 of meer opeenvolgende afleveringsfouten opgetreden.
* De webhook is nog nooit succesvol afgeleverd, of de laatste succesvolle aflevering was meer dan 7 dagen geleden.

Wanneer een webhook automatisch wordt uitgeschakeld, ontvangen workspacebeheerders een e-mailmelding. De webhook moet handmatig opnieuw worden ingeschakeld via de instellingenpagina voordat deze weer afleveringen uitvoert.

## Integratie

Maak voor integratie met webhooks een endpointhandler die webhookgebeurtenisgegevens als POST-requests ontvangt. Na validatie van de handtekening moet de handler snel HTTP 200 retourneren om succesvolle ontvangst aan te geven. Als je herhaaldelijk geen succesvolle respons retourneert, kan de webhook automatisch worden uitgeschakeld.

De payload bij een nieuwe poging is identiek aan de oorspronkelijke afleveringspoging. Webhookgebruikers kunnen niet alleen aan de payload zien of het om een eerste aflevering of een nieuwe poging gaat, dus ontwerp je handler **idempotent** — het meerdere keren verwerken van dezelfde gebeurtenis moet hetzelfde resultaat opleveren. Gebruik indien nodig `event_timestamp` en gebeurtenisspecifieke identificatiegegevens (zoals `conversation_id`) om gebeurtenissen te ontdubbelen.

### Velden op het hoogste niveau

| Veld              | Type   | Beschrijving                        |
| ----------------- | ------ | ----------------------------------- |
| `type`            | string | Type gebeurtenis                    |
| `data`            | object | Gegevens voor de gebeurtenis        |
| `event_timestamp` | string | Wanneer deze gebeurtenis plaatsvond |

## Voorbeeld van webhookpayload

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

## Authenticatie

Het is belangrijk dat de listener alle binnenkomende webhooks valideert. Webhooks ondersteunen momenteel authenticatie via HMAC-handtekeningen. Stel HMAC-authenticatie als volgt in:

* Sla het gedeelde geheim dat is gegenereerd bij het maken van de webhook veilig op
* Verifieer de header ElevenLabs-Signature in je endpoint met de SDK

De JavaScript SDK biedt `constructEvent`; de Python SDK biedt `construct_event` met **`rawBody`**, **`sig_header`** en **`secret`** (in Python heten deze niet `payload` / `signature`). Beide verifiëren de handtekening, valideren de timestamp en parsen de JSON-payload.

#### Python

Voorbeeld van een webhookhandler met 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

Voorbeeld van een webhookhandler met 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

Voorbeeld van een webhookhandler met een 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 });
}
```