ThunderPhone 2.0 est disponible.En libre-service, à partir de 2 ¢/min.Découvrir l’annonce

Webhooks

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_id pour 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"
}
ChampTypeDescription
agent_idinteger | nullAgent qui a traité l'appel, lorsqu'un agent était attribué
agent_namestring | nullAgent 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.

ChampTypeDescription
agent_idinteger | nullAgent qui a traité l'appel, lorsqu'un agent était attribué
agent_namestring | nullAgent 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.

ChampTypeDescription
agent_idinteger | nullAgent qui a traité l'appel, lorsqu'un agent était attribué
agent_namestring | nullAgent 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"
}
ChampTypeDescription
agent_idinteger | nullAgent qui a traité l'appel, lorsqu'un agent était attribué
agent_namestring | nullAgent qui a traité l'appel, lorsqu'un agent était attribué
positionintegerIndex du tour dans l'historique de l'appel — identifiant stable pour l'ordonnancement
rolestringassistant (parole de l'agent) ou user (parole de l'appelant)
textstringTexte transcrit du tour tel qu'il est connu au moment de l'émission
entry_typestringType d'entrée d'historique sous-jacent : completion (agent), ou user_turn / span (appelant)
start_ms, end_msintegerDé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.

ChampTypeDescription
agent_idinteger | nullAgent qui a traité l'appel, lorsqu'un agent était attribué
agent_namestring | nullAgent 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".

ChampTypeDescription
agent_idinteger | nullAgent qui a traité l'appel, lorsqu'un agent était attribué
agent_namestring | nullAgent 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.

ChampTypeDescription
agent_idinteger | nullAgent qui a traité l'appel, lorsqu'un agent était attribué
agent_namestring | nullAgent 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.

ChampTypeDescription
agent_idinteger | nullAgent qui a traité l'appel, lorsqu'un agent était attribué
agent_namestring | nullAgent 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"
}
ChampTypeDescription
call_idintegerL’appel qui a été transféré
agent_idinteger | nullAgent qui a traité l’appel, lorsqu’un agent était attribué
agent_namestring | nullAgent qui a traité l’appel, lorsqu’un agent était attribué
transfer_outcomestringrefer_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é
destinationstring | nullLe numéro vers lequel l’appel a été transféré
sip_statusinteger | nullStatut 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_kindstring | nullUniquement 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_secondsinteger | nullUniquement pour bridged : durée du pont facturée par ThunderPhone, en secondes
bridge_total_centsinteger | nullUniquement 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"
}
ChampTypeDescription
voice.idchaîneIdentifiant public de la voix personnalisée
voice.namechaîneValeur de voix de l'agent au format custom:<public_id>
voice.display_namechaîneNom de la voix visible par l'organisation
voice.languagechaîneCode de langue unique du clone
voice.genderchaînemale, female ou une chaîne vide
voice.statuschaîneready pour voice.ready ; failed pour voice.failed
voice.failure_reasonchaîneVide en cas de réussite ; détail de l'échec de traitement en cas d'échec
voice.created_at, voice.updated_athorodatageHorodatages ISO 8601
reasonchaîneDé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"
}
ChampTypeDescription
agent_idinteger | nullAgent ayant traité l'appel, lorsqu'un agent était assigné
agent_namestring | nullAgent ayant traité l'appel, lorsqu'un agent était assigné
grade.idintegerIdentifiant de l'évaluation
grade.scoreinteger | null0–100
grade.call_outcomestringsuccess, failure, unknown ou no_conversation
grade.summarystringRésumé en un paragraphe
grade.detected_issuesarrayChaînes décrivant les problèmes détectés par l'évaluateur
grade.statusstringToujours completed — seuls les traitements terminés émettent un événement
grade.grader_modelstringÉvaluateur ayant produit le résultat (par ex. heuristic-v1)
grade.graded_at, grade.created_attimestamp
reportobject | nullRapport 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"
}
ChampTypeDescription
agent_idinteger | nullAgent qui a traité l’appel, lorsqu’un agent était attribué
agent_namestring | nullAgent qui a traité l’appel, lorsqu’un agent était attribué
summarystring | nullLe 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.statusstringToujours completed pour cet événement
extracted_data.fieldsobjectValeurs indexées par les clés de champ d’extraction configurées ; les valeurs indisponibles sont null
extracted_data.evidenceobjectPreuves 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.verificationstringverified 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_reasonsobjectRaisons indexées par les champs définis sur null par l’ancrage structurel ou le vérificateur indépendant
extracted_data.schema_versionstringHachage du schéma de champ exact utilisé pour cette extraction
extracted_attimestampHeure de fin au format ISO 8601
modelstringModè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"
}
ChampTypeDescription
agent_idinteger | nullAgent qui a traité l’appel, lorsqu’un agent était attribué
agent_namestring | nullAgent qui a traité l’appel, lorsqu’un agent était attribué
issue_report.severitystringcritical, warning ou info
issue_report.statusstringopen ou resolved
issue_report.sourcestringuser (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"
}
ChampTypeDescription
automaticbooleantrue pour une escalade automatique ; false pour une escalade manuelle
cluster_idUUIDModèle de problème escaladé
escalation_idUUIDEnregistrement d’escalade
statusstringopen 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"
}
ChampTypeDescription
agent_idinteger | nullAgent ayant traité l'appel, lorsqu'un agent était attribué
agent_namestring | nullAgent ayant traité l'appel, lorsqu'un agent était attribué
test_call_run.target_typestringagent ou phone_number
test_call_run.target_idintegerID de l'agent ou du numéro de téléphone ciblé par l'exécution, correspondant à target_type
test_call_run.statusstringcompleted ou failed
test_call_run.call_idinteger | nullnull lorsque l'exécution a échoué avant qu'un appel soit lancé
test_call_run.error_messagestringVide 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"
}
ChampTypeDescription
event_id (dans data)UUIDID de déclenchement de l'alerte — distinct de l'event_id de livraison de l'enveloppe
rule_id, rule_nameUUID, stringRègle qui s'est déclenchée
metricstringsuccess_rate, failure_rate, avg_score, call_volume ou suite_regression
comparatorstringlt, lte, gt ou gte
metric_valuenumberValeur de la métrique sur la fenêtre lorsque la règle s'est déclenchée
thresholdnumberSeuil configuré
window_hoursintegerFenêtre d'évaluation glissante
fired_attimestamp

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"
}
ChampTypeDescription
migration.idUUIDLa migration
migration.routing_idUUIDL'appel routé, tel qu'il a été renvoyé lorsque vous l'avez passé
migration.armstringours (ThunderPhone l'a passé) ou vendor (l'autre plateforme l'a passé)
migration.vendorstringretell, vapi, elevenlabs ou bland
migration.vendor_call_idstring | nullL'identifiant d'appel de l'autre plateforme ; null pour ours
migration.metadataobjectLes metadata que vous avez envoyées lors du passage de l'appel
migration.vendor_cost_usdstring | nullLe coût de l'appel signalé par l'autre plateforme, lorsqu'elle l'a signalé
call_idinteger | nullL'identifiant d'appel ThunderPhone ; null pour vendor
statusstringPour 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"
}
ChampTypeDescription
migration_idUUIDLa migration
vendorchaîneretell, vapi, elevenlabs ou bland
reasonchaîneours_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_percententierPart des appels de ThunderPhone avant l'annulation
ours_percententierToujours 0
stepentier | nullÉtape de planification en cours (indexée à partir de 0)
ours / theirsobjet | nullAppels é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_failedentierÉchecs de connexion comptabilisés au cours des 15 dernières minutes
droppedentierAppels comptabilisés comme abandonnés au cours des 30 dernières minutes
rolled_back_athorodatage

Contenu associé