Call Event Webhooks
Met de Call Event Webhook van Tring kun je telefoniegebeurtenissen realtime doorsturen naar een extern systeem. Denk bijvoorbeeld aan een CRM, dashboard, rapportagetool of maatwerkapplicatie.
Je ontvangt een webhook wanneer een gesprek start, wordt beantwoord, verandert, wordt doorgeschakeld of wordt beëindigd. Wanneer transcriptie en gespreksanalyse zijn ingeschakeld, kan na afloop van het gesprek daarnaast een afzonderlijk transcriptie-event worden verstuurd.
In dit artikel lees je hoe je de webhook configureert, welke events beschikbaar zijn en hoe je de ontvangen gegevens het beste verwerkt.
Webhook configureren
De webhook-URL wordt per tenant ingesteld.
Bijvoorbeeld:
https://partner.example/webhook
Webhooks worden via een POST-request verstuurd.
Content-Type
Standaard wordt de payload als JSON verstuurd:
Content-Type: application/json
Ondersteunde formaten zijn:
application/json
application/x-www-form-urlencoded
Authenticatie
Indien authenticatie is geconfigureerd, kan een Bearer Token worden meegestuurd:
Authorization: Bearer <token>
De naam van deze header is configureerbaar. Standaard wordt Authorization gebruikt.
Extra headers
Aanvullende headers kunnen worden toegevoegd aan iedere webhook-call.
Bijvoorbeeld:
X-Customer-ID: 12345
X-Environment: Production
X-Webhook-Secret: <secret>
URL-parameters
Ook kunnen optioneel parameters aan de webhook-URL worden toegevoegd:
https://partner.example/webhook?tenant=demoTenant&environment=prod
Beschikbare events
De webhook kent vier eventtypes:
| Eventtype | Omschrijving |
|---|---|
call_start | Een gesprek is gestart |
call_update | De status of situatie binnen een gesprek is gewijzigd |
call_end | Het gesprek is beëindigd |
transcript | Transcriptie en eventuele analyse van een eerder gesprek zijn beschikbaar |
Binnen call-events wordt daarnaast een status meegegeven.
| Status | Betekenis |
|---|---|
ringing | Het toestel gaat over |
answered | Het gesprek is aangenomen |
hangup | Het gesprek is beëindigd |
transcript | De transcriptie is beschikbaar |
Voorbeeld: inkomend gesprek
Wanneer een inkomend gesprek binnenkomt, wordt eerst een call_start verstuurd.
{
"tenantCode": "demoTenant",
"event_type": "call_start",
"call_id": "PJSIP1014demoTenant00006ef0",
"direction": "inbound",
"status": "ringing",
"number": "31600000001",
"user_extension": "1014",
"from": "31600000001",
"to": "1014",
"from_name": "Voorbeeld Klant",
"to_name": "Medewerker 1014",
"call_capabilities": [],
"uniqueid": "LPBX01-1783334374.1405029",
"linkedid": "LPBX01-1783334374.1405029",
"timestamp": "2026-07-02T12:09:49.394Z"
}
Zodra het gesprek wordt aangenomen, volgt een call_update:
{
"tenantCode": "demoTenant",
"event_type": "call_update",
"call_id": "PJSIP1014demoTenant00006ef0",
"direction": "inbound",
"status": "answered",
"number": "31600000001",
"user_extension": "1014",
"from": "31600000001",
"to": "1014",
"from_name": "Voorbeeld Klant",
"to_name": "Medewerker 1014",
"call_capabilities": [],
"uniqueid": "LPBX01-1783334374.1405029",
"linkedid": "LPBX01-1783334374.1405029",
"timestamp": "2026-07-02T12:10:00.638Z"
}
Na het beëindigen van het gesprek wordt een call_end verstuurd:
{
"tenantCode": "demoTenant",
"event_type": "call_end",
"call_id": "PJSIP1014demoTenant00006ef0",
"direction": "inbound",
"status": "hangup",
"number": "31600000001",
"user_extension": "1014",
"from": "31600000001",
"to": "1014",
"from_name": "Voorbeeld Klant",
"to_name": "Medewerker 1014",
"call_capabilities": [],
"uniqueid": "LPBX01-1783334374.1405029",
"linkedid": "LPBX01-1783334374.1405029",
"timestamp": "2026-07-02T12:10:20.221Z"
}
Een normale call-flow ziet er daarmee bijvoorbeeld als volgt uit:
ringing
↓
answered
↓
hangup
Velden in een call-event
De standaardpayload bevat de volgende velden:
| Veld | Type | Omschrijving |
|---|---|---|
tenantCode | string | Identificatie van de tenant |
event_type | string | call_start, call_update, call_end of transcript |
call_id | string | Technische ID van de betreffende call-leg |
previous_call_id | string | Alleen aanwezig bij bepaalde transfers; verwijst naar de vorige call-leg |
uniqueid | string | Asterisk UniqueID van de call-leg |
linkedid | string | Asterisk LinkedID waarmee gerelateerde call-legs kunnen worden gegroepeerd |
direction | string | inbound of outbound |
status | string | ringing, answered, hangup of transcript |
number | string | Telefoonnummer van de tegenpartij van de gebruiker |
user_extension | string | Extensie van de gebruiker |
from | string | Beller |
to | string | Bestemming |
from_name | string | Naam behorend bij from, indien bekend |
to_name | string | Naam behorend bij to, indien bekend |
timestamp | string | UTC-tijdstip in ISO 8601-formaat |
call_capabilities | array | Beschikbare acties of capabilities; momenteel meestal leeg |
Call-ID’s en call-legs
Een belangrijk aandachtspunt bij het verwerken van de webhook is de betekenis van call_id.
Een call_id vertegenwoordigt een technische call-leg en niet noodzakelijk het volledige gesprek zoals een eindgebruiker dat ervaart.
Voor een eenvoudig gesprek kan één call_id gedurende het volledige gesprek worden gebruikt. Bij complexere scenario’s, zoals een transfer, kunnen echter meerdere call-legs ontstaan.
Tijdens een transfer kan:
- dezelfde
call_idandere gesprekspartijen krijgen; - een nieuwe
call_idontstaan; - een
previous_call_idworden meegestuurd.
Behandel call_id daarom niet als de enige unieke identificatie van een volledig gesprek.
Voor rapportages en correlatie adviseren we om ten minste call_id, previous_call_id, uniqueid en linkedid te bewaren.
Gesprekken doorschakelen
De webhook ondersteunt attended transfers.
Stel dat een externe beller eerst met extensie 1014 spreekt:
Externe beller → 1014
Medewerker 1014 start vervolgens een consultatie met 1004:
Externe beller → 1014 → 1004
Na het voltooien van de transfer blijft de externe beller verbonden met 1004:
Externe beller → 1004
Bij een succesvolle transfer kan bijvoorbeeld het volgende event worden verstuurd:
{
"tenantCode": "demoTenant",
"event_type": "call_update",
"status": "answered",
"call_id": "PJSIP1004demoTenant000019ec",
"previous_call_id": "PJSIP1014demoTenant00006ef0",
"direction": "inbound",
"number": "31600000001",
"user_extension": "1004",
"from": "31600000001",
"to": "1004",
"from_name": "Voorbeeld Klant",
"to_name": "Medewerker 1004",
"call_capabilities": [],
"uniqueid": "LPBX01-1783334401.1405101",
"linkedid": "LPBX01-1783334374.1405029",
"timestamp": "2026-07-02T12:10:20.221Z"
}
Wanneer previous_call_id aanwezig is in combinatie met:
event_type: call_update
status: answered
kan het event worden beschouwd als een afgeronde transfer.
Een bijbehorende call-flow kan er bijvoorbeeld zo uitzien:
12:09:49 31600000001 → 1014 ringing
12:10:00 31600000001 → 1014 answered
12:10:14 1014 → 1004 ringing
12:10:17 1014 ↔ 1004 consultatie
12:10:20 transfer uitgevoerd
12:10:20 31600000001 → 1004 actief gesprek
12:10:21 consultatiegesprek eindigt
Transcriptie en gespreksanalyse
Wanneer transcriptie is ingeschakeld, kan na afloop van een gesprek een apart transcript-event worden verstuurd.
Transcriptie-events zijn optioneel en worden alleen verstuurd voor tenants die gebruikmaken van webhook_type: custom.
Een transcriptie wordt niet direct bij call_end verstuurd. Eerst moeten onder andere de opname, AI-transcriptie en eventuele aanvullende analyses worden verwerkt.
Hierdoor kan het transcriptie-event ongeveer één tot meerdere minuten na call_end arriveren. De verwerkingstijd hangt onder andere af van:
- de duur van het gesprek;
- de verwerkingswachtrij;
- eventuele aanvullende analyses;
- eventuele vertalingen.
Niet ieder gesprek resulteert in een transcriptie. Een gesprek kan bijvoorbeeld niet zijn opgenomen, te kort zijn geweest, niet zijn beantwoord of van transcriptie zijn uitgesloten.
Voorbeeld van een transcriptie-event
{
"tenantCode": "demoTenant",
"event_type": "transcript",
"call_id": "PJSIP1014demoTenant00006ef0",
"direction": "inbound",
"status": "transcript",
"number": "31600000001",
"user_extension": "1014",
"from": "31600000001",
"to": "1014",
"from_name": "Voorbeeld Klant",
"to_name": "Medewerker 1014",
"call_capabilities": [],
"uniqueid": "LPBX01-1783334374.1405029",
"linkedid": "LPBX01-1783334374.1405029",
"duration": 143,
"detected_language": "nl",
"detected_language_iso": "nl",
"transcription": "Beller: Goedemiddag, ik heb een vraag over mijn abonnement.\nMedewerker: Natuurlijk, ik kijk graag met u mee.",
"category": 2,
"category_name": "Support",
"subject": "Vraag over abonnement",
"sentiment": 0,
"summary": "De beller vraagt om hulp bij een abonnement. De medewerker geeft aan mee te kijken.",
"bullet_points": [
"De beller heeft een vraag over een abonnement.",
"De medewerker biedt aan de gegevens te controleren.",
"Er wordt een vervolgactie afgesproken."
],
"local_date_time": "2026-07-06T12:39:34+02:00",
"timestamp": "2026-07-06T12:42:11.184Z"
}
Extra velden bij transcripties
Bij event_type: transcript kunnen de volgende aanvullende velden aanwezig zijn:
| Veld | Type | Omschrijving |
|---|---|---|
duration | number | Gespreksduur in seconden |
detected_language | string | Gedetecteerde taal of taalcode, afhankelijk van de analyseconfiguratie |
detected_language_iso | string | ISO-code van de gedetecteerde taal, bijvoorbeeld nl, en of de |
transcription | string | Volledige transcriptietekst |
category | number/string | Categorie-ID of categoriecode |
category_name | string | Naam van de categorie |
subject | string | Onderwerp van het gesprek |
sentiment | number | Sentimentscore, meestal -1, 0 of 1 |
summary | string | AI-samenvatting van het gesprek |
bullet_points | array | Belangrijkste punten uit het gesprek |
local_date_time | string | Lokale gesprekstijd inclusief timezone-offset |
Gebruik voor het koppelen van transcripties aan eerdere call-events onder andere uniqueid, linkedid en de beschikbare call-ID’s.
HTTP-responses
Het ontvangende endpoint moet een succesvolle HTTP-statuscode retourneren wanneer de webhook correct is ontvangen.
Ondersteunde succesvolle responses zijn bijvoorbeeld:
HTTP/1.1 200 OK
of:
HTTP/1.1 204 No Content
Andere statuscodes worden als een mislukte aflevering beschouwd, bijvoorbeeld:
400 Bad Request
401 Unauthorized
403 Forbidden
500 Internal Server Error
Wat gebeurt er als een webhook niet kan worden afgeleverd?
Wanneer het ontvangende endpoint tijdelijk niet bereikbaar is, probeert het platform de webhook automatisch opnieuw af te leveren.
Het standaard retrybeleid is:
- De eerste poging wordt direct uitgevoerd.
- Een tweede poging volgt na ongeveer één seconde.
- Daarna wordt exponentiële backoff gebruikt, bijvoorbeeld ongeveer 2, 4, 8, 16 en 29 seconden.
- De totale retryperiode bedraagt maximaal ongeveer één minuut.
Retries worden uitgevoerd bij:
- HTTP
5xx; - timeouts;
- netwerkfouten.
Bij een HTTP 4xx-response wordt niet opnieuw geprobeerd. Een 4xx wijst doorgaans op een probleem met bijvoorbeeld authenticatie, autorisatie of payloadvalidatie.
Wanneer alle pogingen mislukken, wordt de aflevering als mislukt geregistreerd.
Realtime call-events worden niet langdurig bewaard om na een procesherstart opnieuw af te leveren. Transcriptie-events worden daarnaast via een queue verwerkt en kunnen daardoor ook later opnieuw worden verwerkt.
Aanbevolen manier van verwerken
Voor een betrouwbare integratie adviseren we om rekening te houden met de volgende punten:
- Verwerk webhooks asynchroon. Accepteer het event en voer zwaardere verwerking vervolgens buiten het webhook-request uit.
- Gebruik
timestampvoor de gebeurtenistijd. Ga niet uitsluitend uit van de volgorde waarin requests bij jouw endpoint aankomen. - Maak de verwerking idempotent. Houd er rekening mee dat hetzelfde event meer dan één keer kan worden aangeboden.
- Sla call-relaties op. Bewaar naast
call_idookprevious_call_id,uniqueidenlinkedidwanneer deze beschikbaar zijn. - Gebruik
previous_call_idvoor transferdetectie. - Behandel een
call_idals call-leg. Ga er niet vanuit dat ééncall_idaltijd gelijkstaat aan één volledig gesprek. - Ga er niet vanuit dat
fromentobinnen dezelfdecall_idnooit kunnen wijzigen.
Ondersteunde scenario’s
De Call Event Webhook kan worden gebruikt voor:
- inkomende gesprekken;
- uitgaande gesprekken;
- interne gesprekken;
- attended transfers;
- CRM-pop-ups;
- call logging;
- rapportages;
- realtime dashboards;
- synchronisatie met externe applicaties.
Met de webhook kun je externe systemen daarmee realtime laten reageren op telefoniegebeurtenissen binnen Tring.