Sign inGet Started

Eventos de SMS

Cada mensaje atraviesa un ciclo de vida, y Bird emite un evento en cada paso. Esta página es el vocabulario completo de eventos; cómo se entregan los eventos a tu endpoint (firmas, reintentos, reproducción) se cubre en la guía de Webhooks.
El ciclo de vida de entrega, como una ruta a través de los tipos de evento:
  1. sms.accepted: Bird tiene el mensaje y se prepara para entregarlo a un operador.
  2. sms.sent: Bird entregó el mensaje al operador y espera un acuse de recibo de entrega.
  3. Un evento terminal:
    • sms.delivered: El operador confirmó la entrega al dispositivo.
    • sms.undelivered: El operador reportó una no entrega temporal, como un dispositivo no disponible.
    • sms.failed: Un fallo permanente detuvo la entrega.
    • sms.expired: El operador dejó de intentar y reportó el mensaje como expirado.
Los eventos terminales exponen el acuse de recibo de entrega del operador, lo que las plataformas SMS llaman informe de entrega o DLR.
La excepción es sms.rejected: el mensaje fue rechazado (por una verificación de política, un cobro que no pudo completarse o un operador que lo devolvió) en lugar de intentado y perdido. Un mensaje rechazado durante el procesamiento lleva sms.rejected como su único evento.
Bird también recibe respuestas. Cuando un suscriptor envía un mensaje a uno de tus números, Bird almacena el mensaje y emite sms.received, para que puedas actuar sin sondear. El payload contiene el cuerpo, el desglose de segmentos, ambos números y el operador cuando el carrier lo reporta.
Bird evalúa la respuesta contra las reglas de palabras clave de ese número. Una palabra clave de parada compatible como STOP registra una supresión de remitente-y-suscriptor y aun así emite sms.received.
El evento type es un enum abierto: Bird puede agregar nuevos tipos de evento con el tiempo, así que trata un type no reconocido como un evento futuro en lugar de un error. Maneja los tipos que necesitas e ignora el resto.

La envoltura del evento

Los eventos llegan a tu endpoint de webhook en la envoltura anidada de Standard Webhooks descrita en la guía de Webhooks: tres campos, type, timestamp y un objeto data específico del tipo. La identidad del evento no está en el cuerpo: viaja en el encabezado webhook-id HTTP, que es estable entre reintentos de la misma entrega y es tu clave de deduplicación.
CampoDescripción
typeUno de los tipos de evento en esta página, como sms.delivered
timestampCuándo ocurrió el evento (RFC 3339); ordena por este campo, nunca por orden de llegada, ya que las entregas no están ordenadas
dataPayload específico del evento
El data de cada evento SMS contiene sms_id, workspace_id y las direcciones to y from. También repite los campos tags y metadata del envío para que puedas enrutar y correlacionar eventos sin otra consulta. Cada uno es null cuando el envío no los incluyó.
El mismo objeto contiene cost, el cargo del mensaje a la fecha de ese evento, dividido en transaction_amount y passthrough_amount con su suma en amount. Es null en un evento que no cobró nada. Como las entregas no están ordenadas, fusiona cost componente por componente en lugar de reemplazar el objeto completo: para cada componente, conserva el valor del evento con el timestamp más reciente. Un amount suma solo los componentes en su propio payload, así que léelo como el cargo acumulado en lugar de un total definitivo. Costo y facturación cubre qué significa cada componente.
Ejemplo de código
{
  "type": "sms.delivered",
  "timestamp": "2026-06-10T14:30:00Z",
  "data": {
    "sms_id": "sms_01krdgeqcxet5s7t44vh8rt9mg",
    "workspace_id": "ws_01krdgeqcxet5s7t44vh8rt9mg",
    "to": "+15551234567",
    "from": "+12025550188",
    "carrier": "Example Wireless",
    "mcc_mnc": "310260",
    "cost": {
      "amount": "0.00990",
      "currency_code": "USD",
      "transaction_amount": "0.00790",
      "passthrough_amount": "0.00200"
    },
    "tags": [{ "name": "campaign", "value": "spring-2026" }],
    "metadata": { "order_id": "ord_123" }
  }
}

Eventos del ciclo de vida

sms.accepted

Se dispara cuando Bird acepta el envío y comienza a prepararlo para entregarlo a un operador. El payload agrega segments, el desglose Bird contado en el momento de aceptación; su count es lo que se factura por el envío.

sms.sent

Se dispara cuando Bird ha entregado el mensaje al operador y espera un acuse de recibo de entrega. El payload agrega carrier y mcc_mnc (la red que maneja el mensaje y su código de país/red móvil). Cada uno está ausente en lugar de null cuando el operador no lo reporta. Para medir la latencia de procesamiento, compara el timestamp de este evento con el de sms.accepted.

sms.delivered

El operador confirmó que el mensaje llegó al dispositivo. El payload agrega carrier y mcc_mnc, cada uno ausente cuando el acuse de recibo no los identificó.

Eventos de fallo

El payload de cada evento de fallo agrega un objeto error: un code estable entre Bird (por ejemplo unreachable o blocked_by_carrier), un description legible, el carrier_error_code sin procesar cuando se proporcionó uno, y occurred_at.

sms.undelivered

Una no entrega no permanente: el dispositivo estaba apagado o fuera de alcance.

sms.failed

Un fallo de entrega permanente detuvo el mensaje.

sms.rejected

El mensaje fue rechazado por las verificaciones de Bird durante el procesamiento, un cobro que no pudo completarse o un operador que lo devolvió. Un rechazo detiene el mensaje antes de que un intento de entrega tenga éxito. Un saldo agotado termina aquí con el código de error insufficient_balance, y un mensaje cuyo cobro no pudo completarse no se factura.

sms.expired

El operador dejó de intentar entregar y reportó el mensaje como expirado. La expiración proviene del acuse de recibo de entrega del operador: Bird no establece ninguna ventana de validez propia ni ejecuta ningún temporizador que finalice un mensaje. El error describe por qué el mensaje seguía sin entregarse cuando el operador desistió, normalmente unreachable: el dispositivo permaneció apagado o fuera de cobertura durante todo el período.

Eventos de supresión

Más allá del ciclo de vida por mensaje, un evento reporta un cambio en la lista de supresión del espacio de trabajo: sms_suppression.created se dispara cuando se abre una supresión, ya sea que un suscriptor envió una palabra clave de parada, el operador reportó una exclusión voluntaria o alguien la agregó manualmente. El payload contiene el suppression_id, el número del suscriptor como destination, el originator al que se vincula el bloqueo (una supresión SMS es el par exacto remitente-y-suscriptor), el reason y el workspace_id, para que tu propio sistema pueda reflejar la lista sin sondear:
Ejemplo de código
{
  "type": "sms_suppression.created",
  "timestamp": "2026-08-25T14:52:03.192524705Z",
  "data": {
    "suppression_id": "ssu_01krdgeqcxet5s7t44vh8rt9mg",
    "destination": "+15550001234",
    "originator": "+15557654321",
    "reason": "keyword_stop",
    "workspace_id": "ws_01ky7m21hjffh9s8kq76gyb1xf"
  }
}
Una exclusión voluntaria a nivel de espacio de trabajo registrada en la pestaña Preferencias es una preferencia declarada en lugar de una supresión, y no dispara este evento.

Lectura de la línea de tiempo de un mensaje

Los webhooks entregan eventos a tus sistemas. Para una revisión puntual, el registro de SMS muestra el mismo flujo como una línea de tiempo con marcas de tiempo, detalles del operador y errores. Para obtener la línea de tiempo programáticamente, llama a GET /v1/sms/messages/{message_id}/events. Para leer solo el estado más reciente, llama a GET /v1/sms/messages/{message_id}.

Próximos pasos

  • Webhooks y eventos: configura un endpoint, verifica firmas y maneja reintentos y reproducción.
  • Registro de SMS: inspecciona la línea de tiempo por mensaje que estos eventos generan.
  • Envío de SMS: establece los campos tags y metadata que se repiten en cada evento.

Recursos relacionados

Continúa con la documentación, guías y ejemplos sobre este tema. Los recursos están en inglés.

Obtener un resumen de implementación