Webhooks

Activa integraciones externas recibiendo eventos de webhook.

Descripción general

Ciertos eventos de ElevenLabs se pueden configurar para activar webhooks, lo que permite que aplicaciones y sistemas externos reciban y procesen estos eventos a medida que ocurren. Los tipos de eventos compatibles actualmente incluyen:

Tipo de eventoDescripción
post_call_transcriptionUna llamada de Agents Platform ha finalizado y el análisis está completo
voice_removal_noticeEstá programada la eliminación de una voz compartida
voice_removal_notice_withdrawnYa no está programada la eliminación de una voz compartida
voice_removedSe ha eliminado una voz compartida y ya no se puede usar

Configuración

Puedes crear, desactivar y eliminar webhooks desde la página de configuración general. Para usuarios de Espacios de trabajo, solo los administradores del espacio de trabajo pueden configurar los webhooks de este.

Configuración de webhook HMAC

Después de crearlo, puedes seleccionar el webhook para que escuche eventos en la configuración de productos como Agents Platform.

Puedes desactivar los webhooks desde la página de configuración general en cualquier momento. Los webhooks que fallan repetidamente se desactivan automáticamente si hay 10 o más fallos consecutivos y la última entrega correcta fue hace más de 7 días, o si nunca se han entregado correctamente. Los webhooks desactivados automáticamente deben volver a activarse desde la página de configuración. Puedes eliminar los webhooks si no los utiliza ningún producto.

Reintentos

Puedes activar los reintentos para cada webhook, de modo que se vuelva a intentar automáticamente la entrega cuando falle una solicitud. Los reintentos están desactivados de forma predeterminada. Actívalos al crear o actualizar un webhook mediante la API o desde la configuración del webhook.

Actualmente, los reintentos solo son compatibles con los webhooks post_call_transcription.

Programa de reintentos

Cuando un intento de entrega falla con un error reintentable, el sistema lo vuelve a intentar hasta 5 veces, con intervalos cada vez mayores entre intentos:

IntentoIntervalo
1Inmediato
230 segundos
32 minutos
48 minutos
530 minutos

Se añade una pequeña variación aleatoria (de hasta el 10 % del intervalo) a cada reintento para distribuir la carga y evitar problemas de efecto rebaño.

Errores reintentables

No todos los fallos activan un reintento. Solo se consideran reintentables los siguientes códigos de estado HTTP:

  • Códigos de estado 5xx (errores del servidor como 500, 502, 503 y 504).
  • 429 (demasiadas solicitudes).
  • 408 (tiempo de espera de la solicitud).

Los errores de solicitud en el intervalo 4xx (como 400, 401, 403 y 404) no se reintentan, ya que suelen indicar un problema de configuración que requiere corrección manual.

Límites de cola por webhook

Cada webhook está limitado a 100 tareas de reintento pendientes. Si un webhook acumula más de 100 reintentos en cola, las tareas adicionales se descartan hasta que se procesen los reintentos existentes. Esto evita que un único webhook mal configurado consuma recursos excesivos.

Comportamiento de desactivación automática

El sistema registra los fallos de entrega consecutivos de cada webhook. Un webhook se desactiva automáticamente cuando se cumplen ambas condiciones siguientes:

  • Se han producido 10 o más fallos de entrega consecutivos.
  • El webhook nunca se ha entregado correctamente, o la última entrega correcta fue hace más de 7 días.

Cuando un webhook se desactiva automáticamente, los administradores del espacio de trabajo reciben una notificación por correo electrónico. Debes volver a activar manualmente el webhook desde la página de configuración antes de que reanude las entregas.

Integración

Para integrarte con webhooks, crea un controlador de ruta para recibir los datos de eventos del webhook como solicitudes POST. Tras validar la firma, el controlador debe devolver HTTP 200 sin demora para indicar que se ha recibido correctamente. Si no se devuelve repetidamente una respuesta correcta, el webhook podría desactivarse automáticamente.

La carga útil del reintento es idéntica a la del intento de entrega original. Los consumidores de webhooks no pueden distinguir entre una entrega inicial y un reintento solo a partir de la carga útil, así que diseña tu controlador para que sea idempotente: procesar el mismo evento varias veces debe producir el mismo resultado. Usa event_timestamp e identificadores específicos del evento (como conversation_id) para eliminar eventos duplicados si es necesario.

Campos de nivel superior

CampoTipoDescripción
typestringTipo de evento
dataobjectDatos del evento
event_timestampstringCuándo ocurrió este evento

Ejemplo de carga útil 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"
}
}
}
}

Autenticación

Es importante que el listener valide todos los webhooks entrantes. Actualmente, los webhooks admiten autenticación mediante firmas HMAC. Configura la autenticación HMAC de esta forma:

  • Almacena de forma segura el secreto compartido generado al crear el webhook
  • Verifica la cabecera ElevenLabs-Signature en tu ruta de API mediante el SDK

El SDK de JavaScript incluye constructEvent; el SDK de Python incluye construct_event con rawBody, sig_header y secret (en Python no se llaman payload / signature). Ambos verifican la firma, validan la marca de tiempo y analizan la carga útil JSON.

Ejemplo de controlador de webhook con 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"}