Open in
Catalogue des événements
Tous les types d’événements webhook émis par ThunderPhone.
Chaque corps de webhook contient un champ type dont la valeur correspond à l’un des types d’événements de cette page. Lorsque vous vous abonnez à un endpoint, le tableau events doit contenir les types d’événements souhaités (ou être vide pour vous abonner à tous les événements — sauf les événements par tour telephony.turn / web.turn, qui sont envoyés uniquement aux endpoints qui les indiquent explicitement).
Ces événements sont transmis selon deux modes :
- Les livraisons d'endpoint sont toujours des notifications non bloquantes avec des nouvelles tentatives : répondez avec n'importe quel code 2xx ; l'enveloppe contient un
event_idpour la déduplication. - Les échanges bloquants s'exécutent uniquement sur le webhook monourl hérité : la requête de configuration
telephony.incoming/web.incoming(numéros en mode webhook : 13 s, dont une nouvelle tentative ; clés de widget en mode webhook : 10 s) et la répartition d'outil en mode webhook. Votre réponse façonne l'appel en direct.
Les exemples de payload ci-dessous présentent l’enveloppe d’endpoint dans son ordre sur le réseau (clés triées par ordre alphabétique : data, event_id, type) ; les livraisons historiques contiennent les mêmes data sans event_id.
Événements d'appel
telephony.incoming
Envoyé lorsqu'un appel entrant atteint l'un de vos
numéros de téléphone. Les livraisons aux endpoints sont
des notifications fire-and-forget envoyées pour chaque appel entrant, que
le numéro soit configuré avec un agent ou avec un webhook. Les numéros sans
agent attribué reçoivent également la requête de configuration bloquante
sur le webhook hérité — consultez
telephony.incoming / web.incoming pour
le schéma complet de requête / réponse.
{
"data": {
"call_id": 987654321,
"from_number": "+14155550199",
"to_number": "+15551234567"
},
"event_id": "3f6b2ad0-1c9e-4a57-9f2b-8f6f0f9d2f11",
"type": "telephony.incoming"
}| Champ | Type | Description |
|---|---|---|
agent_id | integer | null | Agent qui a traité l'appel, lorsqu'un agent était attribué |
agent_name | string | null | Agent qui a traité l'appel, lorsqu'un agent était attribué |
telephony.complete
Envoyé lorsqu'un appel téléphonique entrant ou sortant se termine. Non bloquant.
Inclut la transcription, l'URL de l'enregistrement lorsqu'elle est disponible, ainsi que le récapitulatif de facturation. Consultez
telephony.complete / web.complete pour
le schéma de la charge utile.
| Champ | Type | Description |
|---|---|---|
agent_id | integer | null | Agent qui a traité l'appel, lorsqu'un agent était attribué |
agent_name | string | null | Agent qui a traité l'appel, lorsqu'un agent était attribué |
telephony.tool
Envoyé après qu'un appel téléphonique a invoqué un
outil de fonction. Notification d'audit non bloquante —
l'outil a déjà été exécuté lorsque cet événement est livré ; il couvre
vos propres outils de fonction et l'outil intégré send_sms (mais pas les autres outils intégrés,
outils de base de connaissances, de connexion d'application ou MCP). Pour send_sms,
arguments.to et arguments.body sont tous deux [REDACTED]. Les transcriptions
de fin d'appel les masquent également ; récupérez le contenu et le destinataire depuis la
ressource SMS à l'échelle de l'organisation à l'aide du message_id de la réponse.
{
"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 correspond au résultat exécuté : {"status": <http status>, "response": <your endpoint's JSON>} en cas de réussite, ou
{"status": <status>, "error": "<message>"} en cas d'échec.
| Champ | Type | Description |
|---|---|---|
agent_id | integer | null | Agent qui a traité l'appel, lorsqu'un agent était attribué |
agent_name | string | null | Agent qui a traité l'appel, lorsqu'un agent était attribué |
telephony.turn
Envoyé pendant qu'un appel téléphonique est en cours, une fois pour chaque
tour contenant de la parole, au moment où il se produit — les réponses orales de
l'agent et les tours transcrits de l'appelant. Permet de suivre la conversation
en direct via de simples webhooks au lieu d'interroger
GET /v1/calls/{call_id}/transcript.
Non bloquant.
{
"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"
}| Champ | Type | Description |
|---|---|---|
agent_id | integer | null | Agent qui a traité l'appel, lorsqu'un agent était attribué |
agent_name | string | null | Agent qui a traité l'appel, lorsqu'un agent était attribué |
position | integer | Index du tour dans l'historique de l'appel — identifiant stable pour l'ordonnancement |
role | string | assistant (parole de l'agent) ou user (parole de l'appelant) |
text | string | Texte transcrit du tour tel qu'il est connu au moment de l'émission |
entry_type | string | Type d'entrée d'historique sous-jacent : completion (agent), ou user_turn / span (appelant) |
start_ms, end_ms | integer | Décalages audio en ms depuis le début de l'appel ; présents uniquement lorsque le timing de lecture était déjà connu au moment de l'émission |
web.incoming
Équivalent sur le canal web de telephony.incoming, envoyé lorsqu'une session de
widget web ou un appel de test du micro du builder
démarre. Les livraisons aux endpoints sont fire-and-forget pour chaque session web.
Les clés publiables en mode="webhook" reçoivent également la requête de
configuration bloquante sur le webhook hérité — cette requête bloquante
a une structure différente (origin_domain,
publishable_key_prefix ; sans numéros de téléphone). Consultez
telephony.incoming / web.incoming.
{
"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 est toujours la valeur littérale "web". Pour les sessions de widget
en mode webhook, to_number est vide (le numéro de l'agent de la session est attribué
après la configuration) ; pour les appels de test du micro du builder, origin_domain et
publishable_key_prefix sont vides.
| Champ | Type | Description |
|---|---|---|
agent_id | integer | null | Agent qui a traité l'appel, lorsqu'un agent était attribué |
agent_name | string | null | Agent qui a traité l'appel, lorsqu'un agent était attribué |
web.complete
Équivalent sur le canal web de telephony.complete, couvrant les appels de widget
web (direction: "web") et les appels de test du micro du builder
(direction: "test"). Non bloquant. Même structure de charge utile que
telephony.complete, avec origin_domain en plus,
et from_number défini sur "web".
| Champ | Type | Description |
|---|---|---|
agent_id | integer | null | Agent qui a traité l'appel, lorsqu'un agent était attribué |
agent_name | string | null | Agent qui a traité l'appel, lorsqu'un agent était attribué |
web.tool
Équivalent sur le canal web de telephony.tool. Les données data contiennent
origin_domain au lieu de from_number / to_number.
| Champ | Type | Description |
|---|---|---|
agent_id | integer | null | Agent qui a traité l'appel, lorsqu'un agent était attribué |
agent_name | string | null | Agent qui a traité l'appel, lorsqu'un agent était attribué |
web.turn
Équivalent sur le canal web de telephony.turn,
couvrant les appels de widget web et les appels de test du micro du builder. Même structure
de charge utile, avec origin_domain au lieu de from_number / to_number.
Comme telephony.turn, il nécessite un abonnement explicite — il
n'est jamais livré via un tableau events vide.
| Champ | Type | Description |
|---|---|---|
agent_id | integer | null | Agent qui a traité l'appel, lorsqu'un agent était attribué |
agent_name | string | null | Agent qui a traité l'appel, lorsqu'un agent était attribué |
call.transfer_completed
Envoyé une fois par appel avec le résultat final d’un
transfert d’appel : un transfert à froid ou le
pont entre personnes qu’un transfert à chaud laisse après le retrait de l’agent.
Non bloquant et envoyé uniquement aux endpoints (jamais au webhook historique
à URL unique). Il arrive après le telephony.complete de l’appel :
lorsque l’opérateur prend en charge l’appel ou que le transfert échoue, ou,
lorsque ThunderPhone a mis l’appel en pont, lorsque le pont se termine.
{
"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"
}| Champ | Type | Description |
|---|---|---|
call_id | integer | L’appel qui a été transféré |
agent_id | integer | null | Agent qui a traité l’appel, lorsqu’un agent était attribué |
agent_name | string | null | Agent qui a traité l’appel, lorsqu’un agent était attribué |
transfer_outcome | string | refer_accepted : l’opérateur a pris en charge l’appel. bridged : ThunderPhone a lui-même maintenu la connexion entre l’appelant et la destination, soit parce que l’opérateur a refusé un transfert à froid, soit parce que l’agent d’un transfert à chaud s’est retiré. bridge_unanswered : l’opérateur a refusé un transfert à froid et la destination n’a pas répondu à l’appel émis par ThunderPhone. failed : le transfert n’a pas abouti et l’appel s’est terminé |
destination | string | null | Le numéro vers lequel l’appel a été transféré |
sip_status | integer | null | Statut SIP de l’opérateur lorsqu’il a refusé le transfert à froid : 403 (par exemple, un trunk Twilio sans transfert d’appel), 405 ou 501. null lorsque l’opérateur ne l’a pas refusé |
bridge_kind | string | null | Uniquement pour bridged : cold_fallback (un transfert à froid refusé que ThunderPhone a connecté) ou warm (les deux personnes d’un transfert à chaud après le retrait de l’agent) |
bridge_seconds | integer | null | Uniquement pour bridged : durée du pont facturée par ThunderPhone, en secondes |
bridge_total_cents | integer | null | Uniquement pour bridged : coût du pont en cents USD après déduction de tout crédit d’appel gratuit, facturé séparément du billing_total_cents de l’appel |
Les mêmes valeurs figurent sur l’objet d’appel
sous les noms transfer_outcome, transfer_destination, transfer_sip_status,
transfer_bridge_kind, transfer_bridge_seconds et
transfer_bridge_total_cents. event_id est identique pour chaque livraison
d’un appel ; un rapport répété ne produit donc jamais un second événement.
Événements SMS
Les événements SMS décrivent les messages envoyés via le compte Twilio ou
Telnyx connecté de l'organisation. Le corps du message est omis et to est
masqué. Récupérez le message limité à l'organisation depuis
GET /v1/sms/{message_id} lorsque son
contenu ou son destinataire est nécessaire.
sms.sent
Envoyé lorsque l'opérateur du client accepte une demande d'envoi de SMS. Il ne s'agit pas d'un accusé de réception sur le téléphone.
{
"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
Envoyé après un rejet permanent par l'opérateur, après épuisement des nouvelles
tentatives temporaires, ou lorsque le résultat est définitivement inconnu.
error_code est un code ThunderPhone stable et error_message indique
l'action à effectuer par le client lorsqu'elle est disponible.
status: "unknown" signifie que l'opérateur peut avoir accepté le SMS ;
vérifiez-le dans le journal de l'opérateur, car ThunderPhone ne le renverra pas
automatiquement.
sms.received
Réservé à la prise en charge des SMS entrants. Aucun événement sms.received
n'est émis dans la version actuelle. La configuration des webhooks entrants de
l'opérateur et la vérification des signatures seront publiées séparément.
Événements vocaux
La création de voix personnalisées est asynchrone. Ces événements non bloquants vous permettent de réagir à un résultat final au lieu d'interroger le point de terminaison des détails du clone.
voice.ready et voice.failed sont envoyés uniquement à un point de
terminaison global à l'organisation avec events: []. Ils ne peuvent pas être
sélectionnés comme filtres d'événements explicites.
voice.ready
Envoyé lorsqu'une voix personnalisée termine son traitement et peut être attribuée à un agent.
{
"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
Envoyé lorsque le traitement d'une voix personnalisée atteint un échec permanent.
{
"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"
}| Champ | Type | Description |
|---|---|---|
voice.id | chaîne | Identifiant public de la voix personnalisée |
voice.name | chaîne | Valeur de voix de l'agent au format custom:<public_id> |
voice.display_name | chaîne | Nom de la voix visible par l'organisation |
voice.language | chaîne | Code de langue unique du clone |
voice.gender | chaîne | male, female ou une chaîne vide |
voice.status | chaîne | ready pour voice.ready ; failed pour voice.failed |
voice.failure_reason | chaîne | Vide en cas de réussite ; détail de l'échec de traitement en cas d'échec |
voice.created_at, voice.updated_at | horodatage | Horodatages ISO 8601 |
reason | chaîne | Détail de l'échec ; présent uniquement sur voice.failed |
Événements de qualité
call.graded
Envoyé chaque fois qu’une exécution d’évaluation par IA est terminée pour un appel. Non bloquant.
{
"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"
}| Champ | Type | Description |
|---|---|---|
agent_id | integer | null | Agent ayant traité l'appel, lorsqu'un agent était assigné |
agent_name | string | null | Agent ayant traité l'appel, lorsqu'un agent était assigné |
grade.id | integer | Identifiant de l'évaluation |
grade.score | integer | null | 0–100 |
grade.call_outcome | string | success, failure, unknown ou no_conversation |
grade.summary | string | Résumé en un paragraphe |
grade.detected_issues | array | Chaînes décrivant les problèmes détectés par l'évaluateur |
grade.status | string | Toujours completed — seuls les traitements terminés émettent un événement |
grade.grader_model | string | Évaluateur ayant produit le résultat (par ex. heuristic-v1) |
grade.graded_at, grade.created_at | timestamp | |
report | object | null | Rapport d'appel destiné au client : libellé du résultat, indicateur et motif nécessitant une attention, appelant, résumé sur une ligne, expérience de l'appelant. Lors d'une évaluation heuristique précoce, il est null ou correspond à un rapport pending dont les champs sont des espaces réservés ; l'événement de l'évaluation complète contient le rapport finalisé |
call.data_extracted
Envoyé chaque fois qu’une extraction de données structurées se termine avec succès, y compris
lors d’une nouvelle tentative tardive après telephony.complete / web.complete ou d’une nouvelle exécution manuelle via
POST /v1/calls/{call_id}/extract.
Non bloquant.
Dans un mode d’extraction bloquant, l’événement de fin attend normalement au maximum
le budget d’extraction de 75 secondes. Si le processus worker d’extraction est
perdu, le traitement de finalisation de production (toutes les cinq minutes) libère un
événement de fin dont le blocking_deadline_at est dépassé avant de lancer une autre
tentative d’extraction. Un succès ultérieur est envoyé séparément sous la forme de cet événement.
{
"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"
}| Champ | Type | Description |
|---|---|---|
agent_id | integer | null | Agent qui a traité l’appel, lorsqu’un agent était attribué |
agent_name | string | null | Agent qui a traité l’appel, lorsqu’un agent était attribué |
summary | string | null | Le résumé d’appel terminé lorsque l’agent a activé Générer un résumé d’appel, afin qu’un événement d’extraction tardif fournisse également un résumé qui n’a pas été envoyé pendant la fenêtre de fin ; null sinon. Les agents disposant d’un résumé mais d’aucun champ d’extraction n’émettent jamais cet événement : récupérez un résumé tardif avec GET /v1/calls/{call_id} |
extracted_data.status | string | Toujours completed pour cet événement |
extracted_data.fields | object | Valeurs indexées par les clés de champ d’extraction configurées ; les valeurs indisponibles sont null |
extracted_data.evidence | object | Preuves indexées par champ d’extraction. Une valeur non nulle contient la citation exacte vérifiée structurellement (au plus 1 000 caractères), le speaker_role (caller ou agent) et le turn_index ; les citations plus longues renvoyées par le modèle sont rejetées plutôt que tronquées, et la preuve est null chaque fois que son champ est null |
extracted_data.verification | string | verified uniquement lorsque le passage indépendant de vérification des preuves a renvoyé exactement un verdict valide pour chaque champ candidat. unavailable signifie que le passage a échoué, a expiré, ne disposait pas d’un budget suffisant ou a renvoyé une sortie mal formée ou partielle. Un passage entièrement indisponible conserve les valeurs fondées structurellement pour examen par le client. Pour une sortie partielle, les verdicts valides sont appliqués et chaque candidat sans exactement un verdict valide est défini sur null |
extracted_data.field_reasons | object | Raisons indexées par les champs définis sur null par l’ancrage structurel ou le vérificateur indépendant |
extracted_data.schema_version | string | Hachage du schéma de champ exact utilisé pour cette extraction |
extracted_at | timestamp | Heure de fin au format ISO 8601 |
model | string | Modèle utilisé pour l’extraction |
campaign.completed
Envoyé une fois lorsqu’une campagne passe de running à completed, que son
planning soit terminé ou que tous les contacts aient atteint un état terminal. Les nouvelles tentatives de l’exécuteur
n’émettent pas d’autre événement. Cet événement de cycle de vie au niveau de l’organisation est envoyé uniquement
aux points de terminaison à portée organisationnelle, et non aux points de terminaison à portée agent. Non bloquant.
{
"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"
}Les quatre décomptes de résultats sont disjoints et leur somme est égale à contacts_total :
completed contient les contacts réussis ; no_answer contient les contacts en échec/épuisés
terminaux dont le résultat final était une absence de réponse ; failed contient
tous les autres contacts en échec/épuisés terminaux ; et remaining contient les contacts
en attente, planifiés ou en cours d’appel. Un contact en attente d’une nouvelle tentative est
remaining, même lorsque sa tentative la plus récente n’a reçu aucune réponse. Les appels en cours
sont réconciliés avant l’instantané de fin émis une seule fois. started_at correspond au
début de campagne configuré, ou à l’heure de création de la campagne lorsqu’aucun début n’a été configuré.
issue.reported
Envoyé lorsqu’un signalement de problème est créé —
soit par un utilisateur depuis le tableau de bord (source: "user"), soit
automatiquement par l’évaluation d’appel (source: "system"). Non bloquant.
{
"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"
}| Champ | Type | Description |
|---|---|---|
agent_id | integer | null | Agent qui a traité l’appel, lorsqu’un agent était attribué |
agent_name | string | null | Agent qui a traité l’appel, lorsqu’un agent était attribué |
issue_report.severity | string | critical, warning ou info |
issue_report.status | string | open ou resolved |
issue_report.source | string | user (signalé depuis le tableau de bord) ou system (créé par l’évaluation) |
issue.escalated
Envoyé lorsqu’un modèle de problème est transmis à ThunderPhone pour examen par le personnel : après Signaler à ThunderPhone, ou lorsque Corriger avec l’IA ne peut pas confirmer une correction côté client et achemine automatiquement le problème. Seuls les points de terminaison à portée organisationnelle reçoivent cet événement.
{
"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"
}| Champ | Type | Description |
|---|---|---|
automatic | boolean | true pour une escalade automatique ; false pour une escalade manuelle |
cluster_id | UUID | Modèle de problème escaladé |
escalation_id | UUID | Enregistrement d’escalade |
status | string | open lorsque l’événement est émis |
Il s’agit d’une notification, pas du lot de preuves. Utilisez cluster_id pour le corréler
au modèle de problème. Consultez Signaler à ThunderPhone.
Événements d'appels de test
test-call.completed
Envoyé lorsqu'une
exécution d'appel de test
atteint un statut terminal — completed ou failed, y compris les exécutions
qui ont échoué au lancement et n'ont jamais produit d'appel. Non bloquant. Utile
pour intégrer des exécutions CI par lot à vos systèmes de chat/notifications.
{
"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"
}| Champ | Type | Description |
|---|---|---|
agent_id | integer | null | Agent ayant traité l'appel, lorsqu'un agent était attribué |
agent_name | string | null | Agent ayant traité l'appel, lorsqu'un agent était attribué |
test_call_run.target_type | string | agent ou phone_number |
test_call_run.target_id | integer | ID de l'agent ou du numéro de téléphone ciblé par l'exécution, correspondant à target_type |
test_call_run.status | string | completed ou failed |
test_call_run.call_id | integer | null | null lorsque l'exécution a échoué avant qu'un appel soit lancé |
test_call_run.error_message | string | Vide en cas de réussite |
Événements d'alerte
alert.triggered
Envoyé lorsqu'une règle d'alerte dont le canal Envoyer aux webhooks développeur est activé franchit son seuil. Non bloquant. Une règle se déclenche une fois, puis respecte son délai de récupération ; un dépassement continu produit donc un événement par fenêtre de délai de récupération.
{
"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"
}| Champ | Type | Description |
|---|---|---|
event_id (dans data) | UUID | ID de déclenchement de l'alerte — distinct de l'event_id de livraison de l'enveloppe |
rule_id, rule_name | UUID, string | Règle qui s'est déclenchée |
metric | string | success_rate, failure_rate, avg_score, call_volume ou suite_regression |
comparator | string | lt, lte, gt ou gte |
metric_value | number | Valeur de la métrique sur la fenêtre lorsque la règle s'est déclenchée |
threshold | number | Seuil configuré |
window_hours | integer | Fenêtre d'évaluation glissante |
fired_at | timestamp |
Consultez le guide des alertes pour créer des règles, des métriques, des délais de récupération et les canaux e-mail / Slack.
Événements de migration
migration.call.complete
Envoyé lorsqu'un appel passé via
POST /v1/migrations/{id}/calls se termine,
quelle que soit la plateforme qui l'a pris en charge. Non bloquant. Il arrive jusqu'à environ 5 minutes
après la fin de l'appel. data contient tous les champs de
telephony.complete, ainsi qu'un bloc migration. Un
appel passé par ThunderPhone envoie également telephony.complete comme d'habitude, avec le
même call_id. Un appel sur l'autre plateforme qui ne s'est pas terminé après 2
heures, ou dont la migration s'est terminée ou a perdu sa clé en premier, est envoyé avec
status: "unknown" et sans transcription.
{
"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"
}| Champ | Type | Description |
|---|---|---|
migration.id | UUID | La migration |
migration.routing_id | UUID | L'appel routé, tel qu'il a été renvoyé lorsque vous l'avez passé |
migration.arm | string | ours (ThunderPhone l'a passé) ou vendor (l'autre plateforme l'a passé) |
migration.vendor | string | retell, vapi, elevenlabs ou bland |
migration.vendor_call_id | string | null | L'identifiant d'appel de l'autre plateforme ; null pour ours |
migration.metadata | object | Les metadata que vous avez envoyées lors du passage de l'appel |
migration.vendor_cost_usd | string | null | Le coût de l'appel signalé par l'autre plateforme, lorsqu'elle l'a signalé |
call_id | integer | null | L'identifiant d'appel ThunderPhone ; null pour vendor |
status | string | Pour vendor : completed lorsque le destinataire a parlé, failed lorsqu'il n'a pas parlé, unknown comme ci-dessus. Pour ours : comme dans telephony.complete |
Pour un appel vendor, ThunderPhone ne dispose d'aucune donnée de facturation ou d'extraction :
billable_minutes, billing_total_cents et extracted_data sont null,
product et voice sont vides, recording_mode est vendor, et
recording_url est le lien de l'autre plateforme, lorsqu'elle en a fourni un.
migration.rollback
Envoyé lorsqu'un basculement progressif de migration renvoie automatiquement tous les appels vers l'autre plateforme : 3 appels n'ont pas réussi à se connecter à ThunderPhone en 15 minutes, 2 appels envoyés à ThunderPhone se sont terminés avant que l'agent ne réponde, ou le taux de réussite des tâches de ThunderPhone est tombé à un niveau inférieur de plus que l'écart configuré à celui de l'autre plateforme. Non bloquant, une fois par annulation. Après cela, la part de ThunderPhone est de 0 % et la migration est suspendue jusqu'à ce qu'une personne la reprenne dans l'onglet Migration de l'agent. La charge utile ne contient aucun numéro de téléphone, transcription ni identifiant d'appel.
{
"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"
}| Champ | Type | Description |
|---|---|---|
migration_id | UUID | La migration |
vendor | chaîne | retell, vapi, elevenlabs ou bland |
reason | chaîne | ours_failed_burst (3 échecs de connexion en 15 minutes), dropped_calls (2 appels terminés avant que l'agent ne réponde, en 30 minutes) ou rate_gap (écart de taux de réussite des tâches sur au moins rollback_min_calls appels évalués de chaque côté) |
previous_percent | entier | Part des appels de ThunderPhone avant l'annulation |
ours_percent | entier | Toujours 0 |
step | entier | null | Étape de planification en cours (indexée à partir de 0) |
ours / theirs | objet | null | Appels évalués à l'étape en cours et leur taux de réussite ; theirs peut couvrir les 30 derniers jours lorsque l'étape comporte trop peu d'appels. null s'il n'y en avait aucun |
ours_failed | entier | Échecs de connexion comptabilisés au cours des 15 dernières minutes |
dropped | entier | Appels comptabilisés comme abandonnés au cours des 30 dernières minutes |
rolled_back_at | horodatage |
Contenu associé
Charge utile bloquante des appels entrants à laquelle vous devez répondre.
Transcription et métriques après appel.
Abonnez une URL à un sous-ensemble de ces événements.
Comment les événements telephony.tool / web.tool sont générés.