GET /api/v1/voice/calls/{id} renvoie le statut, la durée, les crédits débités, le résumé, l’analyse et la transcription de l’appel. Listez les appels avec GET /api/v1/voice/calls?agent_id=&status=&channel=&user_id=&page= (user_id : votre propre identifiant de la personne, issu d’un jeton d’appel web). Ses turns sont le journal de débogage tour par tour de l’appel : où est passé le temps entre la fin de la phrase de l’appelant et le moment où il entend la réponse, en millisecondes — waitMs (fin de parole), sttMs (reconnaissance), llmMs (premier mot du modèle, un de plus par tour de fonctions), ttsMs (premier son de la voix), firstAudioMs (réponse entendue) — avec les fonctions appelées, les interruptions et les erreurs. La page de l’appel l’affiche aussi.
Avec recording_enabled, chaque appel est enregistré en WAV sur deux canaux : l’appelant à gauche, l’agent à droite, à la fréquence d’échantillonnage de l’appel. Avec recording_consent: "announce", l’agent annonce d’abord que l’appel est enregistré ; avec "ask", il demande, et l’enregistrement n’est conservé que si l’appelant accepte (l’absence de réponse vaut refus) ; avec "none", rien n’est dit. Vérifiez ce qu’exige la loi là où vous et vos appelants vous trouvez.
Les enregistrements sont conservés dans le stockage d’EvaSay, ou dans votre propre bucket compatible S3 (AWS S3, Cloudflare R2, Google Cloud Storage, Supabase, MinIO) défini sous Intégrations → Webhooks et notifications → Stockage des enregistrements. Le worker qui exécute l’appel envoie le fichier directement dans le bucket. GET /api/v1/voice/calls/{id} renvoie une recordingUrl valable une heure une fois l’enregistrement stocké, et recording.status (recording, stored, declined ou failed).
DELETE /api/v1/voice/calls/{id} supprime un appel terminé avec sa transcription, son enregistrement (dans le stockage d’EvaSay ou votre propre bucket), son analyse et ses envois webhook. Les Credits utilisés restent dans l’historique des crédits. Un appel qui ne peut pas encore être supprimé répond 409 avec le code call_not_deletable_yet : il est en cours ou vient de se terminer, il est en cours de facturation, son enregistrement est peut-être encore en cours d’envoi, ou il doit des Credits que votre solde n’a pas couverts (ajoutez d’abord des Credits).
Quand une personne demande la suppression de ses données, POST /api/v1/voice/calls/delete-by-caller avec { "phone_number": "+14155550123" } supprime tous les appels avec ce numéro (celui de l’appelant pour les appels entrants, le numéro appelé pour les appels sortants), ou avec { "user_id": "..." } tous les appels web passés avec ce user_id dans leur jeton. La réponse est { "deleted": 12, "kept_back": { "settling": 1 }, "more": false } : 200 appels au plus par requête, donc relancez tant que more vaut true, et plus tard pour les appels de kept_back. Si le numéro figure sur votre liste d’opposition, il y reste. Le tableau de bord fait la même chose dans Appels → Supprimer les données d’un appelant.