Eventos de voz
Bird emite eventos webhook cuando una llamada comienza, se responde y termina. Úsalos para actualizar tus sistemas sin hacer polling. Consulta Webhooks para suscripciones, firmas, reintentos y reproducción.
Recorrido de una llamada a través de los tipos de evento:
- voice_call.initiated: Bird aceptó la solicitud de establecimiento de llamada (un SIP INVITE) y comenzó a enrutar la llamada
- voice_call.answered: el número al que llamaste contestó. Solo las llamadas respondidas generan este evento
- voice_call.ended: la llamada terminó y el evento incluye el resultado
voice_call.initiated confirma que una llamada existe, mientras que voice_call.ended reporta su resultado. Una llamada que Bird rechaza después de aceptar el INVITE aún emite voice_call.ended con status: "failed" y sip_response_code: 503.
El type de evento es un enum abierto: Bird puede agregar tipos con el tiempo, así que maneja los que reconozcas e ignora el resto en lugar de tratar un tipo desconocido como un error.
El sobre del evento
Los eventos de voz llegan en el mismo sobre anidado que cualquier otro evento de Bird, descrito en la guía de Webhooks: type, timestamp y un objeto data específico del tipo. La identidad del evento está en el encabezado webhook-id HTTP en lugar del cuerpo.
| Campo | Descripción |
|---|---|
| type | Uno de los tres tipos de esta página, por ejemplo voice_call.ended |
| timestamp | Cuándo ocurrió el evento (RFC 3339). Ordena por este campo, nunca por orden de llegada |
| data | Carga útil específica del evento, siempre con los mismos campos de identidad de llamada |
El data de cada evento de voz contiene los mismos campos de identidad para correlación. Ambos números usan formato E.164: un + inicial, código de país y número nacional.
| Campo | Descripción |
|---|---|
| call_id | El id del registro de llamada (vcl_…), el mismo que aparece en el Registro de llamadas |
| session_id | Compartido por cada tramo de una llamada transferida o multipartita (vcs_…). Null cuando no aplica correlación de sesión |
| workspace_id | El espacio de trabajo al que pertenece la llamada |
| direction | outbound para llamadas realizadas por tu equipo |
| from | El número que llama |
| to | El número al que se llamó |
voice_call.initiated
Bird recibió el INVITE y comenzó el enrutamiento.
Ejemplo de código
{
"type": "voice_call.initiated",
"timestamp": "2026-06-10T14:30:00Z",
"data": {
"call_id": "vcl_01krdgeqcxet5s7t44vh8rt9mg",
"session_id": "vcs_01krdgeqcxet5s7t44vh8rt9mh",
"workspace_id": "wsp_01krdgeqcxet5s7t44vh8rt9mj",
"direction": "outbound",
"from": "+14155551234",
"to": "+16505559876"
}
}voice_call.answered
El destinatario contestó y el tiempo facturable comenzó. Una llamada no respondida no genera este evento.
La carga útil son los campos de identidad de llamada que incluye cada evento de voz, con timestamp establecido en el momento de la respuesta.
voice_call.ended
La llamada terminó. Este evento agrega el resultado:
| Campo | Descripción |
|---|---|
| status | Cómo terminó: answered, no_answer, failed, rejected o unknown (consulta Estados) |
| sip_response_code | El código SIP final de la llamada, por ejemplo 200 o 486. Una llamada Bird rechazada lleva 503; null cuando no se registró un código final |
| duration_ms | Duración total de la llamada en milisegundos, desde el momento en que Bird recibió la llamada hasta el cuelgue |
| billable_ms | Tiempo respondido en milisegundos; una llamada que nadie contestó reporta cero |
Ejemplo de código
{
"type": "voice_call.ended",
"timestamp": "2026-06-10T14:31:05Z",
"data": {
"call_id": "vcl_01krdgeqcxet5s7t44vh8rt9mg",
"session_id": "vcs_01krdgeqcxet5s7t44vh8rt9mh",
"workspace_id": "wsp_01krdgeqcxet5s7t44vh8rt9mj",
"direction": "outbound",
"from": "+14155551234",
"to": "+16505559876",
"status": "answered",
"sip_response_code": 200,
"duration_ms": 65000,
"billable_ms": 60000
}
}El registro de llamada contiene dos detalles que este evento omite: el motivo de rechazo y el costo. Abre la llamada en el registro de llamadas para distinguir un rechazo Bird de un fallo del operador. El costo aparece después de que se completa la tarificación.
Consumirlos de forma segura
- Deduplica por webhook-id. Bird entrega al menos una vez, y el evento initiated de una llamada puede publicarse más de una vez cuando un reintento de señalización lo reproduce. Misma llamada, misma etapa, mismo webhook-id, así que usar esa clave colapsa el duplicado.
- No dependas del orden. Las entregas no están ordenadas, así que answered puede llegarte después de ended. Ordena por timestamp y deja que un evento que llega después con una marca de tiempo anterior pierda.
- Trata ended como el único resultado fiable. Es el evento que incluye estado y duraciones, y es el que debes usar como clave para tus propios registros.
- Reconcilia contra los registros de llamadas. Los eventos proporcionan actualizaciones oportunas, mientras que el registro de llamadas contiene el registro de la llamada. Exporta las llamadas como CSV para la reconciliación.
Próximos pasos
| Página | Qué cubre |
|---|---|
| Webhooks y eventos | Configuración de endpoint, verificación de firma, reintentos y reproducción |
| Registro de llamadas | Todos los campos de un registro de llamada y exportación CSV |
Recursos relacionados
Continúa con la documentación, guías y ejemplos sobre este tema. Los recursos están en inglés.
Comprender el conceptoWhat is a voice API?Explorar la funcionalidadVoiceGuía de implementaciónVoice overview
Obtener un resumen de implementación