Passer à la navigation

Webhooks

Activez des intégrations externes en recevant des événements webhook.

Vue d’ensemble

Certains événements dans ElevenLabs peuvent être configurés pour déclencher des webhooks, ce qui permet à des applications et systèmes externes de recevoir et de traiter ces événements lorsqu’ils se produisent. Les types d’événements actuellement pris en charge incluent :

Type d’événementDescription
post_call_transcriptionUn appel Agents Platform est terminé et l’analyse est finalisée
voice_removal_noticeLa suppression d’une voix partagée est planifiée
voice_removal_notice_withdrawnLa suppression d’une voix partagée n’est plus planifiée
voice_removedUne voix partagée a été supprimée et ne peut plus être utilisée
flows_generationUne génération Image & Vidéo est terminée ou a échoué
flows_template_runUne exécution de template est terminée ou a échoué

Configuration

Les webhooks peuvent être créés, désactivés et supprimés depuis la page des paramètres généraux. Pour les utilisateurs au sein des Workspaces, seuls les administrateurs du Workspace peuvent configurer les webhooks du Workspace.

Configuration du webhook HMAC

Après sa création, le webhook peut être sélectionné pour écouter des événements dans les paramètres de produits tels qu’Agents Platform.

Les événements flows_generation et flows_template_run sont tous deux activés par un seul abonnement : sous Select events to listen to, cochez Image & Video API generation or template run completed, ou transmettez l’événement flows à Mettre à jour le webhook du Workspace. Une génération ou une exécution envoie son événement uniquement si sa requête de création comprend un champ webhook.

Les webhooks peuvent être désactivés à tout moment depuis la page des paramètres généraux. Les webhooks qui échouent de manière répétée sont désactivés automatiquement après au moins 10 échecs consécutifs, si la dernière livraison réussie remonte à plus de 7 jours ou si aucune livraison n’a jamais réussi. Les webhooks désactivés automatiquement doivent être réactivés depuis la page des paramètres. Les webhooks peuvent être supprimés s’ils ne sont utilisés par aucun produit.

Nouvelles tentatives

Les nouvelles tentatives de webhook peuvent être activées pour chaque webhook afin de réessayer automatiquement une livraison lorsqu’une requête échoue. Elles sont désactivées par défaut. Activez-les lors de la création ou de la mise à jour d’un webhook via l’API ou dans les paramètres du webhook.

Les nouvelles tentatives sont prises en charge pour les webhooks post-appel d’ElevenAgents, notamment les événements de transcription (post_call_transcription), d’audio (post_call_audio) et d’échec d’initiation d’appel (call_initiation_failure).

Calendrier des nouvelles tentatives

Lorsqu’une tentative de livraison échoue avec une erreur pouvant faire l’objet d’une nouvelle tentative, le système réessaie jusqu’à 5 fois avec des délais croissants entre les tentatives :

TentativeDélai
1Immédiat
230 secondes
32 minutes
48 minutes
530 minutes

Un léger décalage aléatoire, pouvant atteindre 10 % du délai, est ajouté à chaque nouvelle tentative afin de répartir la charge et d’éviter les problèmes de surcharge simultanée.

Erreurs pouvant faire l’objet d’une nouvelle tentative

Tous les échecs ne déclenchent pas une nouvelle tentative. Seuls les échecs suivants sont considérés comme pouvant faire l’objet d’une nouvelle tentative :

  • Les codes d’état 5xx (erreurs de serveur telles que 500, 502, 503, 504).
  • 429 (trop de requêtes).
  • 408 (délai d’attente de la requête).
  • Les erreurs de connexion et les délais d’attente de requête.

Les erreurs de requête de la plage 4xx (telles que 400, 401, 403, 404) ne font pas l’objet d’une nouvelle tentative, car elles indiquent généralement un problème de configuration nécessitant une correction manuelle.

Limites de file d’attente par webhook

Chaque webhook est limité à 100 tâches de nouvelle tentative en attente. Si un webhook accumule plus de 100 nouvelles tentatives en file d’attente, les tâches supplémentaires sont abandonnées jusqu’au traitement des tentatives existantes. Cela évite qu’un seul webhook mal configuré consomme trop de ressources.

Les webhooks audio sont soumis à deux limites supplémentaires. Une charge utile audio dépassant 50 Mio est livrée une fois, sans nouvelle tentative, et le total des nouvelles tentatives audio en file d’attente pour un même webhook ne peut pas dépasser 400 Mio.

Comportement de désactivation automatique

Le système suit les échecs de livraison consécutifs pour chaque webhook. Un webhook est automatiquement désactivé lorsque les deux conditions suivantes sont réunies :

  • Au moins 10 échecs de livraison consécutifs se sont produits.
  • Le webhook n’a jamais été livré avec succès ou sa dernière livraison réussie remonte à plus de 7 jours.

Lorsqu’un webhook est désactivé automatiquement, les administrateurs du Workspace reçoivent une notification par email. Le webhook doit être réactivé manuellement depuis la page des paramètres avant de reprendre les livraisons.

Intégration

Pour intégrer des webhooks, créez un gestionnaire de point de terminaison qui reçoit les données d’événements webhook sous forme de requêtes POST. Après avoir validé la signature, le gestionnaire doit renvoyer rapidement HTTP 200 pour indiquer la bonne réception. L’absence répétée de réponse réussie peut entraîner la désactivation automatique du webhook.

La charge utile d’une nouvelle tentative est identique à celle de la tentative de livraison initiale. Les consommateurs de webhooks ne peuvent pas distinguer une livraison initiale d’une nouvelle tentative à partir de la seule charge utile. Concevez donc votre gestionnaire pour qu’il soit idempotent : le traitement répété du même événement doit produire le même résultat. Utilisez event_timestamp et les identifiants propres à l’événement, tels que conversation_id, pour dédupliquer les événements si nécessaire.

Champs de premier niveau

ChampTypeDescription
typestringType d’événement
dataobjectDonnées de l’événement
event_timestampstringMoment où cet événement s’est produit

Exemple de charge utile de webhook

{
"type": "post_call_transcription",
"event_timestamp": 1739537297,
"data": {
"agent_id": "xyz",
"conversation_id": "abc",
"status": "done",
"transcript": [
{
"role": "agent",
"message": "Hey there angelo. How are you?",
"tool_calls": null,
"tool_results": null,
"feedback": null,
"time_in_call_secs": 0,
"conversation_turn_metrics": null
},
{
"role": "user",
"message": "Hey, can you tell me, like, a fun fact about 11 Labs?",
"tool_calls": null,
"tool_results": null,
"feedback": null,
"time_in_call_secs": 2,
"conversation_turn_metrics": null
},
{
"role": "agent",
"message": "I do not have access to fun facts about Eleven Labs. However, I can share some general information about the company. Eleven Labs is an AI voice technology platform that specializes in voice cloning and text-to-speech...",
"tool_calls": null,
"tool_results": null,
"feedback": null,
"time_in_call_secs": 9,
"conversation_turn_metrics": {
"convai_llm_service_ttfb": {
"elapsed_time": 0.3704247010173276
},
"convai_llm_service_ttf_sentence": {
"elapsed_time": 0.5551181449554861
}
}
}
],
"metadata": {
"start_time_unix_secs": 1739537297,
"call_duration_secs": 22,
"cost": 296,
"deletion_settings": {
"deletion_time_unix_secs": 1802609320,
"deleted_logs_at_time_unix_secs": null,
"deleted_audio_at_time_unix_secs": null,
"deleted_transcript_at_time_unix_secs": null,
"delete_transcript_and_pii": true,
"delete_audio": true
},
"feedback": {
"overall_score": null,
"likes": 0,
"dislikes": 0
},
"authorization_method": "authorization_header",
"charging": {
"dev_discount": true
},
"termination_reason": ""
},
"analysis": {
"evaluation_criteria_results": {},
"data_collection_results": {},
"call_successful": "success",
"transcript_summary": "The conversation begins with the agent asking how Angelo is, but Angelo redirects the conversation by requesting a fun fact about 11 Labs. The agent acknowledges they don't have specific fun facts about Eleven Labs but offers to provide general information about the company. They briefly describe Eleven Labs as an AI voice technology platform specializing in voice cloning and text-to-speech technology. The conversation is brief and informational, with the agent adapting to the user's request despite not having the exact information asked for."
},
"conversation_initiation_client_data": {
"conversation_config_override": {
"agent": {
"prompt": null,
"first_message": null,
"language": "en"
},
"tts": {
"voice_id": null
}
},
"custom_llm_extra_body": {},
"dynamic_variables": {
"user_name": "angelo"
}
}
}
}

Authentification

Il est important que le récepteur valide tous les webhooks entrants. Les webhooks prennent actuellement en charge l’authentification par signatures HMAC. Configurez l’authentification HMAC en :

  • Stockant de manière sécurisée le secret partagé généré lors de la création du webhook
  • Vérifiant l’en-tête ElevenLabs-Signature dans votre endpoint à l’aide du SDK

Le SDK JavaScript expose constructEvent ; le SDK Python expose construct_event avec rawBody, sig_header et secret (ils ne s’appellent pas payload / signature en Python). Les deux vérifient la signature, valident l’horodatage et analysent la charge utile JSON.

Exemple de gestionnaire de webhook utilisant FastAPI :

from dotenv import load_dotenv
from fastapi import FastAPI, Request
from fastapi.responses import JSONResponse
from elevenlabs.client import ElevenLabs
from elevenlabs.errors import BadRequestError
import os
load_dotenv()
app = FastAPI()
elevenlabs = ElevenLabs(
api_key=os.getenv("ELEVENLABS_API_KEY"),
)
WEBHOOK_SECRET = os.getenv("WEBHOOK_SECRET")
@app.post("/webhook")
async def receive_message(request: Request):
payload = await request.body()
signature = request.headers.get("elevenlabs-signature")
try:
event = elevenlabs.webhooks.construct_event(
rawBody=payload.decode("utf-8"),
sig_header=signature,
secret=WEBHOOK_SECRET,
)
except BadRequestError as e:
return JSONResponse(content={"error": "Invalid signature"}, status_code=401)
# construct_event returns a dict (parsed JSON), not an object with attributes
if event.get("type") == "post_call_transcription":
print(f"Received transcription: {event.get('data')}")
return {"status": "received"}