---
title: "Gebeurteniscatalogus"
description: "Alle webhookgebeurtenistypen die ThunderPhone verstuurt."
---

Elke webhookbody heeft een veld `type` waarvan de waarde een van de
gebeurtenistypen op deze pagina is. Wanneer je je abonneert op een
[endpoint](/nl/webhooks/endpoints), moet de array `events` de
gebeurtenistypen bevatten die je wilt (of leeg zijn om je op alles te abonneren —
behalve de gebeurtenissen per beurt [`telephony.turn`](#telephony-turn) /
[`web.turn`](#web-turn), die alleen worden afgeleverd bij endpoints die
ze expliciet vermelden).

Deze gebeurtenissen worden op twee manieren afgeleverd:

* **Endpointleveringen** zijn altijd **niet-blokkerende** meldingen
  met [opnieuw proberen](/nl/webhooks/overview): reageer met
  een willekeurige 2xx; de envelop bevat een `event_id` voor deduplicatie.
* **Blokkerende** uitwisselingen vinden alleen plaats via de
  [verouderde webhook met één URL](/nl/webhooks/overview): het
  configuratieverzoek [`telephony.incoming` / `web.incoming`](/nl/webhooks/call-incoming)
  (nummers in webhookmodus: 13 s inclusief één nieuwe poging;
  widgetsleutels in webhookmodus: 10 s) en [toolverzending](/nl/tools/overview)
  in webhookmodus. Je reactie bepaalt het verloop van het live gesprek.

De onderstaande voorbeeldpayloads tonen de endpointenvelop in de
volgorde waarin deze wordt verzonden (sleutels alfabetisch gesorteerd: `data`,
`event_id`, `type`); verouderde leveringen bevatten dezelfde `data` zonder `event_id`.

## Oproepgebeurtenissen

### `telephony.incoming`

Verzonden wanneer een inkomende oproep een van je
[telefoonnummers](/api-reference/phone-numbers) bereikt. Leveringen aan endpoints zijn
fire-and-forgetmeldingen die worden verzonden voor **elke** inkomende oproep, ongeacht
of het nummer is geconfigureerd voor een spraakagent of webhook. Nummers zonder
toegewezen spraakagent ontvangen daarnaast het **blokkerende** configuratieverzoek
op de verouderde webhook — zie
[`telephony.incoming` / `web.incoming`](/nl/webhooks/call-incoming) voor
het volledige aanvraag-/antwoordschema.

```json
{
  "data": {
    "call_id": 987654321,
    "from_number": "+14155550199",
    "to_number": "+15551234567"
  },
  "event_id": "3f6b2ad0-1c9e-4a57-9f2b-8f6f0f9d2f11",
  "type": "telephony.incoming"
}
```

| Veld | Type | Beschrijving |
|-------|------|-------------|
| `agent_id` | integer \| null | Spraakagent die de oproep heeft afgehandeld, indien er een was toegewezen |
| `agent_name` | string \| null | Spraakagent die de oproep heeft afgehandeld, indien er een was toegewezen |

### `telephony.complete`

Verzonden wanneer een inkomende of uitgaande telefonieoproep eindigt. Niet-blokkerend.
Bevat het transcript, de opname-URL indien beschikbaar en de factureringssamenvatting. Zie
[`telephony.complete` / `web.complete`](/nl/webhooks/call-complete) voor
het payloadschema.

| Veld | Type | Beschrijving |
|-------|------|-------------|
| `agent_id` | integer \| null | Spraakagent die de oproep heeft afgehandeld, indien er een was toegewezen |
| `agent_name` | string \| null | Spraakagent die de oproep heeft afgehandeld, indien er een was toegewezen |

### `telephony.tool`

Verzonden nadat een telefonieoproep een
[functietool](/nl/tools/overview) aanroept. Niet-blokkerende auditmelding —
de tool is al uitgevoerd wanneer deze gebeurtenis wordt afgeleverd; deze omvat
je eigen functietools en de ingebouwde tool `send_sms` (niet andere ingebouwde
tools, tools voor kennisbanken, appverbindingen of MCP-tools). Voor `send_sms`
zijn zowel `arguments.to` als `arguments.body` `[REDACTED]`. Transcripten
na afronding redigeren deze ook; haal de inhoud en ontvanger op uit de
organisatiegebonden sms-resource met behulp van de `message_id` uit het antwoord.

```json
{
  "data": {
    "arguments": { "date": "2026-04-21" },
    "call_id": 987654321,
    "from_number": "+14155550199",
    "response": {
      "response": { "available_slots": ["9:00 AM", "2:00 PM"] },
      "status": 200
    },
    "to_number": "+15551234567",
    "tool_name": "search_appointments"
  },
  "event_id": "1f0a7c3e-52d4-4a0e-8f4b-b1a6a1c0d9e2",
  "type": "telephony.tool"
}
```

`response` is het uitgevoerde resultaat: `{"status": <http status>,
"response": <your endpoint's JSON>}` bij succes, of
`{"status": <status>, "error": "<message>"}` bij een fout.

| Veld | Type | Beschrijving |
|-------|------|-------------|
| `agent_id` | integer \| null | Spraakagent die de oproep heeft afgehandeld, indien er een was toegewezen |
| `agent_name` | string \| null | Spraakagent die de oproep heeft afgehandeld, indien er een was toegewezen |

### `telephony.turn`

Verzonden terwijl een telefonieoproep **bezig is**, eenmaal voor elke
spraakbevattende beurt zodra deze plaatsvindt — de gesproken antwoorden van de
spraakagent en de getranscribeerde beurten van de beller. Hiermee kun je het
livegesprek volgen via gewone webhooks in plaats van te pollen op
[`GET /v1/calls/{call_id}/transcript`](/api-reference/calls#get-transcript).
Niet-blokkerend.

<Note>
  **Expliciete inschrijving vereist.** Anders dan elk ander gebeurtenistype
  worden beurtgebeurtenissen nooit afgeleverd via een lege `events`-array
  (inschrijven op alles). Een endpoint ontvangt ze alleen wanneer de lijst
  `events` expliciet `telephony.turn` / `web.turn` bevat.
</Note>

```json
{
  "data": {
    "call_id": 987654321,
    "entry_type": "completion",
    "from_number": "+14155550199",
    "position": 7,
    "role": "assistant",
    "start_ms": 15200,
    "text": "How many employees does your company have?",
    "to_number": "+15551234567"
  },
  "event_id": "8d3f5a2c-7b1e-4c9a-b6d0-2e4f6a8c0d1e",
  "type": "telephony.turn"
}
```

| Veld | Type | Beschrijving |
|-------|------|-------------|
| `agent_id` | integer \| null | Spraakagent die de oproep heeft afgehandeld, indien er een was toegewezen |
| `agent_name` | string \| null | Spraakagent die de oproep heeft afgehandeld, indien er een was toegewezen |
| `position` | integer | De index van de beurt in de oproepgeschiedenis — een stabiele identiteit voor sortering |
| `role` | string | `assistant` (spraak van de spraakagent) of `user` (spraak van de beller) |
| `text` | string | De transcripttekst van de beurt zoals bekend op het moment van verzending |
| `entry_type` | string | Het onderliggende type geschiedenisitem: `completion` (spraakagent), of `user_turn` / `span` (beller) |
| `start_ms`, `end_ms` | integer | Audio-offsets in ms sinds het begin van de oproep; alleen aanwezig wanneer de afspeeltiming bij verzending al bekend was |

<Note>
  Levering gebeurt ten minste eenmaal en beurten kunnen **in onjuiste volgorde**
  aankomen: dedupliceer op de `event_id` van de envelop en sorteer op `position`.
  Transcripten van bellers kunnen na verzending nog worden verfijnd; het
  transcript van [`telephony.complete`](/nl/webhooks/call-complete) na de oproep is
  leidend. Alleen gesproken beurten worden verzonden — toolaanroepen, fluisteringen
  en andere interne items verschijnen nooit in deze stream.
</Note>

### `web.incoming`

Het webkanaalequivalent van `telephony.incoming`, verzonden wanneer een sessie van een
[webwidget](/nl/widget/overview) of een microfoontestoproep in de builder
begint. Leveringen aan endpoints zijn fire-and-forget voor elke websessie.
Publiceerbare sleutels in `mode="webhook"` ontvangen daarnaast het
**blokkerende** configuratieverzoek op de verouderde webhook — dat blokkerende
verzoek heeft een andere structuur (`origin_domain`,
`publishable_key_prefix`; geen telefoonnummers). Zie
[`telephony.incoming` / `web.incoming`](/nl/webhooks/call-incoming).

```json
{
  "data": {
    "call_id": 987654322,
    "from_number": "web",
    "origin_domain": "https://example.com",
    "publishable_key_prefix": "pk_live_a1b2",
    "to_number": "+15551234567"
  },
  "event_id": "9a2b4c6d-8e0f-4a1b-9c2d-3e4f5a6b7c8d",
  "type": "web.incoming"
}
```

`from_number` is altijd de letterlijke waarde `"web"`. Voor widgetsessies in
webhookmodus is `to_number` leeg (het nummer van de spraakagent voor de sessie wordt
na configuratie toegewezen); voor microfoontestoproepen in de builder zijn
`origin_domain` en `publishable_key_prefix` leeg.

| Veld | Type | Beschrijving |
|-------|------|-------------|
| `agent_id` | integer \| null | Spraakagent die de oproep heeft afgehandeld, indien er een was toegewezen |
| `agent_name` | string \| null | Spraakagent die de oproep heeft afgehandeld, indien er een was toegewezen |

### `web.complete`

Het webkanaalequivalent van `telephony.complete`, voor oproepen via de
webwidget (`direction: "web"`) en microfoontestoproepen in de builder
(`direction: "test"`). Niet-blokkerend. Dezelfde payloadstructuur als
[`telephony.complete`](/nl/webhooks/call-complete), plus `origin_domain`,
waarbij `from_number` is ingesteld op `"web"`.

| Veld | Type | Beschrijving |
|-------|------|-------------|
| `agent_id` | integer \| null | Spraakagent die de oproep heeft afgehandeld, indien er een was toegewezen |
| `agent_name` | string \| null | Spraakagent die de oproep heeft afgehandeld, indien er een was toegewezen |

<Note>
  Op de verouderde webhook met één URL worden microfoontestoproepen in de builder
  historisch gerapporteerd als `telephony.complete` — alleen oproepen met `direction:
  "web"` gebruiken daar het type `web.complete`. Het endpointsysteem wijst zowel web-
  als testoproepen toe aan `web.*`. Historische payloads kunnen de verouderde waarden
  `widget` of `mic` voor `direction` bevatten.
</Note>

### `web.tool`

Het webkanaalequivalent van `telephony.tool`. De `data` bevat
`origin_domain` in plaats van `from_number` / `to_number`.

| Veld | Type | Beschrijving |
|-------|------|-------------|
| `agent_id` | integer \| null | Spraakagent die de oproep heeft afgehandeld, indien er een was toegewezen |
| `agent_name` | string \| null | Spraakagent die de oproep heeft afgehandeld, indien er een was toegewezen |

### `web.turn`

Het webkanaalequivalent van [`telephony.turn`](#telephony-turn), voor oproepen via de
webwidget en microfoontestoproepen in de builder. Dezelfde payloadstructuur,
met `origin_domain` in plaats van `from_number` / `to_number`.
Net als `telephony.turn` vereist dit een **expliciete inschrijving** — het wordt
nooit afgeleverd via een lege `events`-array.

| Veld | Type | Beschrijving |
|-------|------|-------------|
| `agent_id` | integer \| null | Spraakagent die de oproep heeft afgehandeld, indien er een was toegewezen |
| `agent_name` | string \| null | Spraakagent die de oproep heeft afgehandeld, indien er een was toegewezen |

### `call.transfer_completed`

Eenmaal per oproep verzonden met de definitieve uitkomst van een
[oproepdoorschakeling](/nl/guides/call-transfers): een koude doorschakeling, of de menselijke
verbinding die een warme doorschakeling achterlaat nadat de agent afhaakt.
Niet-blokkerend en alleen geleverd aan endpoints (nooit aan de verouderde
webhook met één URL). Het komt na de `telephony.complete` van de oproep:
zodra de provider de oproep overneemt of de doorschakeling mislukt, of, wanneer
ThunderPhone de oproep heeft verbonden, zodra de verbinding eindigt.

```json
{
  "data": {
    "agent_id": 12,
    "agent_name": "Front desk",
    "bridge_kind": "cold_fallback",
    "bridge_seconds": 255,
    "bridge_total_cents": 5,
    "call_id": 987654321,
    "destination": "+15555550102",
    "sip_status": 403,
    "transfer_outcome": "bridged"
  },
  "event_id": "5b0f6c1e-9d2a-5e7b-8c4d-1a2b3c4d5e6f",
  "type": "call.transfer_completed"
}
```

| Veld | Type | Beschrijving |
|-------|------|-------------|
| `call_id` | integer | De oproep die is doorgeschakeld |
| `agent_id` | integer \| null | Agent die de oproep afhandelde, indien er een was toegewezen |
| `agent_name` | string \| null | Agent die de oproep afhandelde, indien er een was toegewezen |
| `transfer_outcome` | string | `refer_accepted`: de provider nam de oproep over. `bridged`: ThunderPhone hield de beller en de bestemming zelf verbonden, omdat de provider een koude doorschakeling weigerde of omdat de agent van een warme doorschakeling afhaakte. `bridge_unanswered`: de provider weigerde een koude doorschakeling en de bestemming beantwoordde ThunderPhone's eigen oproep niet. `failed`: de doorschakeling is niet gelukt en de oproep is beëindigd |
| `destination` | string \| null | Het nummer waarnaar de oproep is doorgeschakeld |
| `sip_status` | integer \| null | De SIP-status van de provider toen deze de koude doorschakeling weigerde: `403` (bijvoorbeeld een Twilio-trunk zonder oproepdoorschakeling), `405` of `501`. `null` wanneer de provider deze niet weigerde |
| `bridge_kind` | string \| null | Alleen `bridged`: `cold_fallback` (een geweigerde koude doorschakeling die ThunderPhone heeft verbonden) of `warm` (de twee personen van een warme doorschakeling nadat de agent vertrok) |
| `bridge_seconds` | integer \| null | Alleen `bridged`: de tijd van de verbinding die ThunderPhone factureerde, in seconden |
| `bridge_total_cents` | integer \| null | Alleen `bridged`: wat de verbinding kostte in Amerikaanse centen na eventueel gratis oproeptegoed, afzonderlijk gefactureerd van de `billing_total_cents` van de oproep |

Dezelfde waarden staan op het [oproepobject](/api-reference/calls#call-object)
als `transfer_outcome`, `transfer_destination`, `transfer_sip_status`,
`transfer_bridge_kind`, `transfer_bridge_seconds` en
`transfer_bridge_total_cents`. `event_id` is hetzelfde bij elke levering
voor een oproep, dus een herhaald rapport levert nooit een tweede event op.

---

## SMS-gebeurtenissen

SMS-gebeurtenissen beschrijven berichten die via het gekoppelde Twilio- of
Telnyx-account van de organisatie worden verzonden. De berichttekst wordt weggelaten en `to` wordt geredigeerd.
Haal het organisatiegebonden bericht op via
[`GET /v1/sms/{message_id}`](/api-reference/sms#retrieve-a-message) wanneer de
inhoud of ontvanger nodig is.

### `sms.sent`

Verzonden wanneer de provider van de klant een uitgaand SMS-verzoek accepteert. Dit is geen
bezorgbevestiging op het toestel.

```json
{
  "data": {
    "accepted_at": "2026-09-19T15:42:10.113Z",
    "agent_id": 12,
    "call_id": 987654321,
    "created_at": "2026-09-19T15:42:09.901Z",
    "direction": "outbound",
    "error_code": null,
    "error_message": null,
    "from_number": "+15551234567",
    "id": "313a3117-827b-46e9-a01a-ac1493838724",
    "provider": "twilio",
    "provider_id": "SM0123456789abcdef0123456789abcdef",
    "segment_count": 1,
    "source": "agent_tool",
    "status": "accepted",
    "to": "[REDACTED]"
  },
  "event_id": "0ae347b4-1716-45bb-9a0e-b52373586e37",
  "type": "sms.sent"
}
```

### `sms.failed`

Verzonden na een permanente afwijzing door de provider, nadat tijdelijke nieuwe pogingen zijn
uitgeput, of wanneer de uitkomst definitief onbekend is. `error_code` is een stabiele
ThunderPhone-code en `error_message` vermeldt de actie voor de klant wanneer die
beschikbaar is. `status: "unknown"` betekent dat de provider de SMS mogelijk heeft geaccepteerd;
controleer dit in het providerlogboek, want ThunderPhone verzendt de SMS niet
automatisch opnieuw.

### `sms.received`

Gereserveerd voor ondersteuning van inkomende SMS-berichten. In de
huidige release worden geen `sms.received`-gebeurtenissen verzonden. Configuratie van inkomende
providerwebhooks en handtekeningverificatie worden afzonderlijk uitgebracht.

---

## Spraakgebeurtenissen

Het maken van aangepaste stemmen verloopt asynchroon. Met deze niet-blokkerende gebeurtenissen kun je
reageren op een definitief resultaat in plaats van de
[clone-detailendpoint](/api-reference/custom-voices#list-and-retrieve-clones) te pollen.

`voice.ready` en `voice.failed` worden alleen geleverd aan een organisatiebreed
endpoint met `events: []`. Ze kunnen niet als expliciete gebeurtenisfilters worden geselecteerd.

### `voice.ready`

Verzonden wanneer de verwerking van een aangepaste stem is voltooid en deze aan een
agent kan worden toegewezen.

```json
{
  "data": {
    "voice": {
      "created_at": "2026-07-30T14:12:08.317Z",
      "display_name": "Support voice",
      "failure_reason": "",
      "gender": "female",
      "id": "cv_2f6f90b0e9a34ee8b39be7d1",
      "language": "en",
      "name": "custom:cv_2f6f90b0e9a34ee8b39be7d1",
      "status": "ready",
      "updated_at": "2026-07-30T14:13:31.605Z"
    }
  },
  "event_id": "2d5f0a61-e9b5-4a3c-b684-29d7d9e4b214",
  "type": "voice.ready"
}
```

### `voice.failed`

Verzonden wanneer de verwerking van een aangepaste stem een permanente fout bereikt.

```json
{
  "data": {
    "reason": "audio sample could not be processed",
    "voice": {
      "created_at": "2026-07-30T14:12:08.317Z",
      "display_name": "Support voice",
      "failure_reason": "audio sample could not be processed",
      "gender": "female",
      "id": "cv_2f6f90b0e9a34ee8b39be7d1",
      "language": "en",
      "name": "custom:cv_2f6f90b0e9a34ee8b39be7d1",
      "status": "failed",
      "updated_at": "2026-07-30T14:13:31.605Z"
    }
  },
  "event_id": "3493e985-1a75-4f77-a10a-e74af440cd31",
  "type": "voice.failed"
}
```

| Veld | Type | Beschrijving |
|-------|------|-------------|
| `voice.id` | string | Openbare id van de aangepaste stem |
| `voice.name` | string | Waarde voor de stem van de agent in de vorm `custom:<public_id>` |
| `voice.display_name` | string | Stemnaam zichtbaar voor de organisatie |
| `voice.language` | string | De taalcodering voor één taal van de clone |
| `voice.gender` | string | `male`, `female` of een lege tekenreeks |
| `voice.status` | string | `ready` voor `voice.ready`; `failed` voor `voice.failed` |
| `voice.failure_reason` | string | Leeg bij succes; details over de verwerkingsfout bij een fout |
| `voice.created_at`, `voice.updated_at` | timestamp | ISO 8601-tijdstempels |
| `reason` | string | Details over de fout; alleen aanwezig bij `voice.failed` |

---

## Kwaliteitsgebeurtenissen

### `call.graded`

Verzonden wanneer een [AI-beoordeling](/api-reference/calls#ai-call-grading)
voor een oproep is voltooid. Niet-blokkerend.

```json
{
  "data": {
    "call_id": 987654321,
    "grade": {
      "call_outcome": "success",
      "created_at": "2026-04-20T18:25:11.002Z",
      "detected_issues": [],
      "graded_at": "2026-04-20T18:25:11.002Z",
      "grader_model": "heuristic-v1",
      "id": 5512,
      "score": 92,
      "status": "completed",
      "summary": "Caller asked about their policy and got a full answer…"
    },
    "report": null
  },
  "event_id": "7c1d2e3f-4a5b-4c6d-8e9f-0a1b2c3d4e5f",
  "type": "call.graded"
}
```

| Veld | Type | Beschrijving |
|-------|------|-------------|
| `agent_id` | integer \| null | Agent die het gesprek afhandelde, wanneer er een was toegewezen |
| `agent_name` | string \| null | Agent die het gesprek afhandelde, wanneer er een was toegewezen |
| `grade.id` | integer | Beoordelings-ID |
| `grade.score` | integer \| null | 0–100 |
| `grade.call_outcome` | string | `success`, `failure`, `unknown` of `no_conversation` |
| `grade.summary` | string | Samenvatting van één alinea |
| `grade.detected_issues` | array | Probleemteksten die door de beoordelaar zijn gevonden |
| `grade.status` | string | Altijd `completed` — alleen voltooide uitvoeringen verzenden een event |
| `grade.grader_model` | string | Welke beoordelaar het resultaat heeft geproduceerd (bijv. `heuristic-v1`) |
| `grade.graded_at`, `grade.created_at` | timestamp | |
| `report` | object \| null | Het klantgerichte [oproepverslag](/api-reference/calls#call-report): uitkomstlabel, vlag en reden voor aandacht nodig, beller, samenvatting van één regel, bellerervaring. Bij een vroege heuristische beoordeling is dit `null` of een `pending`-verslag waarvan de velden tijdelijke waarden bevatten; het event van de volledige beoordeling bevat het voltooide verslag |

<Note>
  Een oproep kan meer dan één keer worden beoordeeld — een snelle heuristische
  beoordeling wordt vaak gevolgd door een volledige modelbeoordeling zodra de
  opname beschikbaar is, en handmatige herbeoordelingen zijn mogelijk. Elke
  voltooide uitvoering verzendt een eigen `call.graded`-gebeurtenis; beschouw de
  meest recente `graded_at` als leidend.
</Note>

### `call.data_extracted`

Verzonden wanneer de extractie van gestructureerde gegevens succesvol is
voltooid, inclusief een late nieuwe poging na `telephony.complete` / `web.complete`
of een handmatige heruitvoering via
[`POST /v1/calls/{call_id}/extract`](/api-reference/calls#run-data-extraction).
Niet-blokkerend.

In een blokkerende extractiemodus wacht de voltooiingsgebeurtenis normaal
maximaal het extractiebudget van 75 seconden. Als het extractiewerkerproces
verloren gaat, geeft de productiefinalisatierun (elke vijf minuten) een
voltooiing vrij waarvan `blocking_deadline_at` is verstreken voordat een nieuwe
extractiepoging begint. Een later succes wordt afzonderlijk geleverd als deze
gebeurtenis.

<Warning>
  Geëxtraheerde waarden zijn de interpretatie van het model van het gesprek.
  Elke niet-nullwaarde bevat het citaat, de sprekersrol en de beurtindex waarop
  deze is gebaseerd, plus een verificatievlag op uitvoeringsniveau. Verifieer
  het resultaat voordat je beslissingen neemt over geld, identiteit of toegang.
</Warning>

```json
{
  "data": {
    "call_id": 987654321,
    "agent_id": 12,
    "agent_name": "Acme intake",
    "extracted_data": {
      "status": "completed",
      "fields": {
        "customer_name": "Alex Morgan",
        "appointment_date": "2026-04-23"
      },
      "evidence": {
        "customer_name": {
          "quote": "My name is Alex Morgan",
          "speaker_role": "caller",
          "turn_index": 4
        },
        "appointment_date": {
          "quote": "April 23 works for me",
          "speaker_role": "caller",
          "turn_index": 7
        }
      },
      "verification": "verified",
      "field_reasons": {},
      "schema_version": "92850758e231a3c95a..."
    },
    "extracted_at": "2026-04-20T18:25:11.002Z",
    "model": "<model id>",
    "summary": "Alex Morgan called to book a follow-up visit and confirmed Thursday, April 23."
  },
  "event_id": "4d79ef1d-c2b1-4ed6-85b8-8326bd2895ef",
  "type": "call.data_extracted"
}
```

| Veld | Type | Beschrijving |
|-------|------|-------------|
| `agent_id` | integer \| null | Agent die de oproep afhandelde, wanneer er een was toegewezen |
| `agent_name` | string \| null | Agent die de oproep afhandelde, wanneer er een was toegewezen |
| `summary` | string \| null | De voltooide [oproepsamenvatting](/nl/webhooks/call-complete) wanneer voor de agent **Een oproepsamenvatting genereren** is ingeschakeld, zodat een late extractiegebeurtenis ook een samenvatting levert die het voltooiingsvenster heeft gemist; anders `null`. Agents met een samenvatting maar zonder extractievelden verzenden deze gebeurtenis nooit: lees een late samenvatting via `GET /v1/calls/{call_id}` |
| `extracted_data.status` | string | Altijd `completed` voor deze gebeurtenis |
| `extracted_data.fields` | object | Waarden met de geconfigureerde extractieveldsleutels als sleutel; niet-beschikbare waarden zijn `null` |
| `extracted_data.evidence` | object | Bewijs met het extractieveld als sleutel. Een niet-nullwaarde bevat het exacte structureel gecontroleerde citaat (maximaal 1.000 tekens), `speaker_role` (`caller` of `agent`) en `turn_index`; langere door het model geretourneerde citaten worden afgewezen in plaats van afgekapt, en bewijs is `null` wanneer het bijbehorende veld `null` is |
| `extracted_data.verification` | string | Alleen `verified` wanneer de onafhankelijke bewijscontrole voor elk kandidaatveld precies één geldig oordeel retourneerde. `unavailable` betekent dat de controle is mislukt, een time-out had, onvoldoende budget had of onjuist gevormde of gedeeltelijke uitvoer retourneerde. Een volledig niet-beschikbare controle behoudt structureel onderbouwde waarden voor klantbeoordeling. Bij gedeeltelijke uitvoer worden geldige oordelen toegepast en wordt elke kandidaat zonder precies één geldig oordeel op null gezet |
| `extracted_data.field_reasons` | object | Redenen met als sleutel de velden die door structurele onderbouwing of de onafhankelijke verificateur op null zijn gezet |
| `extracted_data.schema_version` | string | Hash van het exacte veldschema dat voor deze extractie is gebruikt |
| `extracted_at` | timestamp | ISO 8601-voltooiingstijd |
| `model` | string | Model dat voor de extractie is gebruikt |

### `campaign.completed`

Eenmaal verzonden wanneer een campagne van `running` naar `completed` gaat,
ongeacht of het schema is geëindigd of alle contacten een eindstatus hebben
bereikt. Nieuwe pogingen van de uitvoerder verzenden geen nieuwe gebeurtenis.
Deze levenscyclusgebeurtenis op organisatieniveau wordt alleen geleverd aan
organisatiegebonden eindpunten, niet aan agentgebonden eindpunten. Niet-blokkerend.

```json
{
  "data": {
    "campaign_id": "3f6b2c9e-2a0d-4c63-b6d6-a708dc98f403",
    "name": "May win-back",
    "agent_id": 12,
    "status": "completed",
    "started_at": "2026-04-20T17:00:00Z",
    "completed_at": "2026-04-20T18:25:11Z",
    "counts": {
      "contacts_total": 150,
      "completed": 121,
      "failed": 11,
      "no_answer": 18,
      "remaining": 0
    }
  },
  "event_id": "8d8f52ce-6b46-423f-9dde-cea0b91ec135",
  "type": "campaign.completed"
}
```

De vier resultaattellingen sluiten elkaar uit en tellen op tot `contacts_total`:
`completed` bevat succesvolle contacten; `no_answer` bevat mislukte of uitgeputte
contacten met een eindstatus waarvan het laatste resultaat geen antwoord was;
`failed` bevat alle andere mislukte of uitgeputte contacten met een eindstatus;
en `remaining` bevat wachtende, geplande of momenteel gebelde contacten. Een
contact dat wacht op een nieuwe poging is `remaining`, zelfs wanneer de meest
recente poging geen antwoord opleverde. Lopende oproepen worden afgestemd vóór
de eenmalige voltooiingsmomentopname. `started_at` is de geconfigureerde start
van de campagne, of het tijdstip waarop de campagne is gemaakt wanneer er geen
start is geconfigureerd.

### `issue.reported`

Verzonden wanneer een [probleemrapport](/api-reference/issue-reports) wordt
gemaakt — hetzij ingediend door een gebruiker vanuit het dashboard
(`source: "user"`), hetzij automatisch door oproepbeoordeling
(`source: "system"`). Niet-blokkerend.

```json
{
  "data": {
    "call_id": 987654321,
    "issue_report": {
      "created_at": "2026-04-20T18:25:11.002Z",
      "description": "Five-second silence before responding to the main question.",
      "id": 4321,
      "severity": "warning",
      "source": "system",
      "status": "open",
      "title": "Agent paused too long"
    }
  },
  "event_id": "5e6f7a8b-9c0d-4e1f-8a2b-3c4d5e6f7a8b",
  "type": "issue.reported"
}
```

| Veld | Type | Beschrijving |
|-------|------|-------------|
| `agent_id` | integer \| null | Agent die de oproep afhandelde, wanneer er een was toegewezen |
| `agent_name` | string \| null | Agent die de oproep afhandelde, wanneer er een was toegewezen |
| `issue_report.severity` | string | `critical`, `warning` of `info` |
| `issue_report.status` | string | `open` of `resolved` |
| `issue_report.source` | string | `user` (ingediend vanuit het dashboard) of `system` (gemaakt door beoordeling) |

<Note>
  Het herbeoordelen van een oproep bouwt de door het systeem gegenereerde
  probleemrapporten opnieuw op, waardoor `issue.reported` opnieuw wordt
  verzonden voor de opnieuw gemaakte rapporten. Dedupliceer op `call_id` +
  `title` als je slechts één melding per onderliggend probleem wilt.
</Note>

### `issue.escalated`

Verzonden wanneer een probleempatronen naar ThunderPhone wordt gestuurd voor
beoordeling door medewerkers: na **Melden aan ThunderPhone**, of wanneer
Oplossen met AI geen oplossing aan klantzijde kan bevestigen en het probleem
automatisch doorstuurt. Alleen organisatiebrede eindpunten ontvangen deze
gebeurtenis.

```json
{
  "data": {
    "automatic": false,
    "cluster_id": "7ac2844c-2df0-4fa8-a560-7378da649e19",
    "escalation_id": "ec99f52b-c8c0-41dd-a4f2-dd8a07b10894",
    "status": "open"
  },
  "event_id": "d8f8f420-7a42-45ba-bcf1-b747f9bbecda",
  "type": "issue.escalated"
}
```

| Veld | Type | Beschrijving |
|-------|------|-------------|
| `automatic` | boolean | `true` voor een automatische escalatie; `false` voor een handmatige escalatie |
| `cluster_id` | UUID | Geëscaleerd probleempatronen |
| `escalation_id` | UUID | Escalatierecord |
| `status` | string | `open` wanneer de gebeurtenis wordt verzonden |

Dit is een melding, niet de bewijsbundel. Gebruik `cluster_id` om deze te
koppelen aan het probleempatronen. Zie [Melden aan ThunderPhone](/nl/guides/issues).

---

## Testoproepgebeurtenissen

### `test-call.completed`

Verzonden wanneer een
[testoproepuitvoering](/api-reference/test-calls#test-call-run-object)
een eindstatus bereikt — `completed` of `failed`, inclusief uitvoeringen
die bij het starten mislukten en nooit een oproep hebben uitgevoerd. Niet-blokkerend. Handig
om batch-CI-uitvoeringen te koppelen aan je chat-/meldingssystemen.

```json
{
  "data": {
    "test_call_run": {
      "call_id": 987654321,
      "completed_at": "2026-04-20T18:25:04.822Z",
      "error_message": "",
      "id": 7110,
      "status": "completed",
      "target_id": 12,
      "target_type": "agent"
    }
  },
  "event_id": "2b3c4d5e-6f7a-4b8c-9d0e-1f2a3b4c5d6e",
  "type": "test-call.completed"
}
```

| Veld | Type | Beschrijving |
|-------|------|-------------|
| `agent_id` | integer \| null | Agent die de oproep afhandelde, wanneer er een was toegewezen |
| `agent_name` | string \| null | Agent die de oproep afhandelde, wanneer er een was toegewezen |
| `test_call_run.target_type` | string | `agent` of `phone_number` |
| `test_call_run.target_id` | integer | De agent-id of telefoonnummer-id waarop de uitvoering was gericht, overeenkomstig `target_type` |
| `test_call_run.status` | string | `completed` of `failed` |
| `test_call_run.call_id` | integer \| null | `null` wanneer de uitvoering mislukte voordat een oproep werd geplaatst |
| `test_call_run.error_message` | string | Leeg bij succes |

---

## Waarschuwingsgebeurtenissen

### `alert.triggered`

Verzonden wanneer een [waarschuwingsregel](/nl/guides/alerts) met het kanaal
**Bezorgen aan developer-webhooks** ingeschakeld de drempelwaarde overschrijdt.
Niet-blokkerend. Een regel wordt één keer geactiveerd en respecteert vervolgens de
afkoelperiode, waardoor een aanhoudende overschrijding één gebeurtenis per afkoelperiode oplevert.

```json
{
  "data": {
    "comparator": "lt",
    "event_id": "b8e6a1d4-2c3f-4a5b-9c8d-7e6f5a4b3c2d",
    "fired_at": "2026-04-20T18:00:00+00:00",
    "metric": "success_rate",
    "metric_value": 71.4,
    "rule_id": "d2c3b4a5-6f7e-4d8c-9b0a-1c2d3e4f5a6b",
    "rule_name": "Success rate below 80%",
    "threshold": 80.0,
    "window_hours": 24
  },
  "event_id": "4d5e6f7a-8b9c-4d0e-9f1a-2b3c4d5e6f7a",
  "type": "alert.triggered"
}
```

| Veld | Type | Beschrijving |
|-------|------|-------------|
| `event_id` (in `data`) | UUID | De **activerings**-id van de waarschuwing — anders dan de `event_id` voor bezorging van de envelop |
| `rule_id`, `rule_name` | UUID, string | De regel die werd geactiveerd |
| `metric` | string | `success_rate`, `failure_rate`, `avg_score`, `call_volume` of `suite_regression` |
| `comparator` | string | `lt`, `lte`, `gt` of `gte` |
| `metric_value` | number | De waarde van de metriek binnen het venster toen de regel werd geactiveerd |
| `threshold` | number | De geconfigureerde drempelwaarde |
| `window_hours` | integer | Terugkijkend evaluatievenster |
| `fired_at` | timestamp | |

Zie de [gids voor waarschuwingen](/nl/guides/alerts) voor het maken van regels, metrieken,
afkoelperiodes en de e-mail- / Slack-kanalen.

---

## Migratiegebeurtenissen

### `migration.call.complete`

Verzonden wanneer een oproep die is geplaatst via
[`POST /v1/migrations/{id}/calls`](/api-reference/migration-calls) eindigt,
ongeacht welk platform deze afhandelde. Niet-blokkerend. Deze arriveert tot
ongeveer 5 minuten nadat de oproep is beëindigd. `data` bevat elk veld van
[`telephony.complete`](/nl/webhooks/call-complete) plus een `migration`-blok. Een
oproep die ThunderPhone heeft geplaatst, verstuurt zoals gebruikelijk ook
`telephony.complete`, met dezelfde `call_id`. Een oproep op het andere platform
die na 2 uur nog niet is beëindigd, of waarvan de migratie eerder is voltooid
of de sleutel heeft verloren, wordt verzonden met `status: "unknown"` en
zonder transcript.

```json
{
  "data": {
    "agent_id": 42,
    "agent_name": "Front desk",
    "billable_minutes": null,
    "billing_total_cents": null,
    "call_id": null,
    "direction": "outbound",
    "duration_seconds": 94,
    "end_reason": "user_hangup",
    "end_time": "2026-10-06T17:01:34+00:00",
    "extracted_data": null,
    "from_number": "+15551234567",
    "migration": {
      "arm": "vendor",
      "id": "5f0c2a9e-7b1d-4c3e-8a6f-2d9e1b4c7a30",
      "metadata": {
        "lead_id": "8812"
      },
      "routing_id": "9b2f8c1e-4d3a-4f6b-8e2d-1a7c5b9e0f34",
      "vendor": "retell",
      "vendor_call_id": "call_6a1f0e",
      "vendor_cost_usd": "0.1240"
    },
    "product": "",
    "recording_mode": "vendor",
    "recording_url": "https://…",
    "start_time": "2026-10-06T17:00:00+00:00",
    "status": "completed",
    "summary": "The callee booked a table for two on Thursday.",
    "thunderphone_retained_call_content": true,
    "to_number": "+14155552671",
    "transcripts": [
      {
        "content": "Hi Ada, this is Rosa's calling about your booking.",
        "role": "agent"
      },
      {
        "content": "Yes, Thursday works.",
        "role": "user"
      }
    ],
    "transfer_number": null,
    "unresolved_variables": [],
    "variables": {
      "first_name": "Ada"
    },
    "voice": ""
  },
  "event_id": "7c1e2f3a-4b5c-4d6e-8f7a-9b0c1d2e3f4a",
  "type": "migration.call.complete"
}
```

| Veld | Type | Beschrijving |
|-------|------|-------------|
| `migration.id` | UUID | De migratie |
| `migration.routing_id` | UUID | De gerouteerde oproep, zoals teruggegeven toen je deze plaatste |
| `migration.arm` | string | `ours` (ThunderPhone plaatste deze) of `vendor` (het andere platform deed dat) |
| `migration.vendor` | string | `retell`, `vapi`, `elevenlabs` of `bland` |
| `migration.vendor_call_id` | string \| null | De oproep-ID van het andere platform; `null` voor `ours` |
| `migration.metadata` | object | De `metadata` die je hebt verzonden bij het plaatsen van de oproep |
| `migration.vendor_cost_usd` | string \| null | De door het andere platform gerapporteerde kosten van de oproep, indien beschikbaar |
| `call_id` | integer \| null | De oproep-ID van ThunderPhone; `null` voor `vendor` |
| `status` | string | Voor `vendor`: `completed` wanneer de gebelde persoon sprak, `failed` wanneer die niet sprak, `unknown` zoals hierboven. Voor `ours`: zoals in `telephony.complete` |

Voor een `vendor`-oproep heeft ThunderPhone geen facturerings- of
extractiegegevens: `billable_minutes`, `billing_total_cents` en
`extracted_data` zijn `null`, `product` en `voice` zijn leeg,
`recording_mode` is `vendor`, en `recording_url` is de link van het andere
platform, indien dit er een heeft verstrekt.

### `migration.rollback`

Verzonden wanneer de geleidelijke omschakeling van een migratie alle oproepen automatisch terugzet naar het andere platform: 3 oproepen konden niet binnen 15 minuten met ThunderPhone verbinden, 2 naar ThunderPhone gestuurde oproepen eindigden voordat de agent antwoordde, of ThunderPhone's taakresultaatpercentage daalde meer dan de geconfigureerde marge onder dat van het andere platform. Niet-blokkerend, eenmaal per terugdraaiing. Daarna is het aandeel van ThunderPhone 0% en wordt de migratie onderbroken totdat iemand deze hervat op het tabblad Migratie van de agent. De payload bevat geen telefoonnummers, transcripties of oproep-ID's.

```json
{
  "data": {
    "agent_id": 42,
    "agent_name": "Front desk",
    "dropped": 0,
    "migration_id": "5f0c2a9e-7b1d-4c3e-8a6f-2d9e1b4c7a30",
    "ours": {
      "graded": 20,
      "success_rate": 0.8
    },
    "ours_failed": 3,
    "ours_percent": 0,
    "previous_percent": 25,
    "reason": "ours_failed_burst",
    "rolled_back_at": "2026-10-10T12:05:00+00:00",
    "step": 1,
    "theirs": {
      "graded": 20,
      "success_rate": 0.8
    },
    "vendor": "retell"
  },
  "event_id": "3d1f6b2a-8c4e-5a7b-9d0e-2f1a3b4c5d6e",
  "type": "migration.rollback"
}
```

| Veld | Type | Beschrijving |
|-------|------|-------------|
| `migration_id` | UUID | De migratie |
| `vendor` | string | `retell`, `vapi`, `elevenlabs` of `bland` |
| `reason` | string | `ours_failed_burst` (3 mislukte verbindingen in 15 minuten), `dropped_calls` (2 oproepen eindigden voordat de agent antwoordde, binnen 30 minuten), of `rate_gap` (verschil in taakresultaatpercentage over ten minste `rollback_min_calls` beoordeelde oproepen per zijde) |
| `previous_percent` | integer | Het aandeel oproepen van ThunderPhone vóór de terugdraaiing |
| `ours_percent` | integer | Altijd `0` |
| `step` | integer \| null | De planningsstap waarop deze zich bevond (op 0 gebaseerd) |
| `ours` / `theirs` | object \| null | Beoordeelde oproepen in de huidige stap en hun succespercentage; `theirs` kan de afgelopen 30 dagen betreffen wanneer de stap te weinig oproepen heeft. `null` wanneer er geen waren |
| `ours_failed` | integer | Mislukte verbindingen geteld in de afgelopen 15 minuten |
| `dropped` | integer | Als afgebroken getelde oproepen in de afgelopen 30 minuten |
| `rolled_back_at` | timestamp | |

---

## Gerelateerd

<CardGroup cols={2}>
  <Card title="telephony.incoming / web.incoming" icon="phone" href="/nl/webhooks/call-incoming">
    De blokkerende payload voor inkomende oproepen waarop je moet reageren.
  </Card>
  <Card title="telephony.complete / web.complete" icon="phone-slash" href="/nl/webhooks/call-complete">
    Transcript en metrieken na de oproep.
  </Card>
  <Card title="Webhook-eindpunten" icon="bolt" href="/nl/webhooks/endpoints">
    Abonneer een URL op een subset van deze gebeurtenissen.
  </Card>
  <Card title="Functietools" icon="screwdriver-wrench" href="/nl/tools/overview">
    Hoe `telephony.tool` / `web.tool`-gebeurtenissen worden gegenereerd.
  </Card>
</CardGroup>
