# Estado de mensaje (DLR) y payloads de webhooks entrantes (MO)

> Dos payloads de webhook portan los eventos de mensajería. Un evento de estado de entrega (DLR) notifica el resultado de un mensaje: message_id, un enum de estado (accepted, delivered, undelivered, expired, rejected), un motivo de error y marcas de tiempo. Un evento entrante (MO) notifica un mensaje que un abonado te envió. Ambos son los equivalentes HTTP de los acuses deliver_sm de SMPP y de los mensajes originados en el móvil.

- URL canónica: https://www.broadnet.me/es/reference/message-status-and-inbound-webhooks
- Idioma: es
- Última actualización: 2026-07-19
- Editor: BroadNet (https://www.broadnet.me)

Los esquemas de payload de los dos callbacks de mensajería centrales: el evento de estado de entrega (DLR) con su id de mensaje, enum de estado, motivo de error y marcas de tiempo, y el evento de mensaje entrante (MO), más una taxonomía de tipos de evento y cómo un DLR HTTP se corresponde con un acuse deliver_sm de SMPP.

## Dos familias de evento: estado y entrante

Una plataforma de mensajería emite dos callbacks fundamentalmente distintos. Un evento de estado de entrega (DLR, acuse de entrega) es el seguimiento asíncrono de un mensaje que enviaste: te dice qué le ocurrió finalmente en la red del operador. Un evento entrante (MO, originado en el móvil) es no solicitado: un mensaje que un abonado envió a uno de tus números o una respuesta a una campaña. Comparten el transporte y la firma del webhook, pero sus esquemas y su significado difieren, por lo que un consumidor robusto se bifurca según un discriminador de tipo de evento antes de parsear el resto. Ambos son la expresión en capa HTTP de cosas que SMPP entrega como PDU deliver_sm: un indicador de acuse distingue un DLR de un MO en el cable, y esa misma distinción es un campo de evento explícito sobre HTTP.

## Payload de estado de entrega (DLR)

Un payload de estado de entrega se correlaciona con el envío original mediante el message_id asignado por el servidor y notifica un estado extraído de una enumeración pequeña, más el motivo y las marcas de tiempo que permiten medir la latencia y conciliar la facturación. El enum de estado es su núcleo: distingue un estado intermedio accepted/enroute de los estados terminales, y separa un delivered positivo de las varias formas en que un mensaje puede fallar. Los estados terminales negativos portan un código de error y un motivo legible por humanos para que un consumidor pueda decidir si el destino es permanentemente incorrecto (suprimirlo) o el fallo fue transitorio (seguro de reenviar). Las marcas de tiempo suelen incluir cuándo aceptó la plataforma el mensaje y cuándo ocurrió el estado terminal.

*Cuerpo del webhook de estado de entrega (DLR)*

```json
{
  "event": "message.delivered",
  "message_id": "01HZY8Q3M6",
  "to": "+15551234567",
  "status": "delivered",
  "error": null,
  "reason": null,
  "submitted_at": "2026-07-19T09:15:22Z",
  "done_at": "2026-07-19T09:15:25Z",
  "sequence": 3
}
```

## La enumeración de estado de entrega

Estandarizar los valores de estado es lo que permite a un solo consumidor gestionar todos los operadores, porque las respuestas de red en bruto varían enormemente. Un enum canónico las mapea a un puñado de estados con semántica clara: si el estado es terminal y si es un éxito. Los estados intermedios (accepted, enroute) pueden ser sustituidos por un evento posterior para el mismo id de mensaje, que es precisamente por qué los payloads portan una secuencia o marca de tiempo y por qué los consumidores aplican la regla de auto-ordenación de la fiabilidad de webhooks: un accepted tardío nunca debe sobrescribir un delivered anterior.

*Valores canónicos de estado de entrega*

| status | Terminal | Significado |
|---|---|---|
| accepted | No | La plataforma aceptó el mensaje para su entrega |
| enroute | No | Entregado al operador, a la espera de una confirmación |
| delivered | Sí | Entrega al terminal confirmada |
| undelivered | Sí | El operador no pudo realizar la entrega (ver error/motivo) |
| expired | Sí | El período de validez transcurrió antes de la entrega |
| rejected | Sí | Rechazado (número inválido, remitente bloqueado, filtro de spam) |
| unknown | Sí | El operador no devolvió ningún estado final definitivo |

## Payload de mensaje entrante (MO)

Un evento entrante porta el contenido del mensaje más el enrutamiento necesario para responder y para correlacionar una conversación. Los campos críticos son from (el MSISDN del abonado en E.164), to (el número o el código corto/largo al que escribió) y el texto; junto a ellos, un id de mensaje para el propio mensaje entrante, una marca de tiempo de recepción y —como el SMS entrante está sujeto a las mismas reglas de codificación y segmentación que el saliente— la codificación y, para un mensaje multiparte, la referencia de concatenación y los índices de parte para que el consumidor pueda reensamblar el texto completo. Los eventos entrantes son la forma en que se impulsan las campañas por palabra clave, las conversaciones bidireccionales y los flujos de cumplimiento STOP/HELP.

*Cuerpo del webhook entrante (MO)*

```json
{
  "event": "message.inbound",
  "message_id": "01HZY8R7T0",
  "from": "+15551234567",
  "to": "44160",
  "text": "STOP",
  "encoding": "GSM7",
  "received_at": "2026-07-19T09:20:11Z",
  "concat": { "ref": null, "part": 1, "total": 1 }
}
```

## Taxonomía de tipos de evento

Más allá de DLR y MO, una plataforma emite eventos de ciclo de vida y de cuenta, y un esquema de nombres consistente —una cadena punteada recurso.acción— permite a un consumidor suscribirse a ellos y enrutarlos con limpieza. Los eventos de estado de entrega son variaciones de message.<estado>; el evento entrante es message.inbound. Agrupar por el prefijo de recurso significa que un consumidor puede casar message.* para todo lo relativo a un mensaje y reservar otros prefijos para eventos de cuenta o de número. Todo evento debería portar además un id de evento estable (usado como nonce de firma y clave de deduplicación) y la cadena de tipo, para que el discriminador y la clave de idempotencia estén siempre presentes.

*Tipos de evento de mensajería comunes*

| Tipo de evento | Familia | Se activa cuando |
|---|---|---|
| message.accepted | Estado (DLR) | Mensaje aceptado para entrega |
| message.delivered | Estado (DLR) | Entrega al terminal confirmada |
| message.undelivered | Estado (DLR) | El operador no pudo entregar |
| message.expired | Estado (DLR) | Período de validez transcurrido |
| message.rejected | Estado (DLR) | Mensaje rechazado aguas arriba |
| message.inbound | Entrante (MO) | Un abonado le envió un mensaje |

## Correspondencia del DLR HTTP con el deliver_sm de SMPP

El callback de estado de entrega HTTP y el acuse de entrega de SMPP son la misma información en dos codificaciones, y una plataforma que hace de puente entre REST y SMPP traduce entre ellos. En SMPP un acuse llega como una PDU deliver_sm cuyo esm_class la marca como acuse; su campo short-message porta un acuse de texto con los campos id, stat y err, y el TLV message_state porta el estado numérico. El DLR HTTP los eleva a JSON: el token stat de SMPP se mapea al enum de estado canónico, el valor err se mapea al campo error, y los tiempos submit/done del acuse se mapean a submitted_at/done_at. Entender esta correspondencia es lo que permite que un único camino de código de gestión de entregas sirva a ambos transportes; el formato del acuse SMPP y la PDU deliver_sm se documentan en detalle en la referencia de SMPP.

*Correspondencia de campos del acuse de entrega SMPP con el DLR HTTP*

| Campo del recibo SMPP | Campo HTTP DLR | Nota |
|---|---|---|
| id (recibo) | message_id | Corresponde al submit_sm / POST original |
| stat (DELIVRD/UNDELIV/EXPIRED/REJECTD) | status | El token se asigna al enum canónico |
| err | error | Código de error del operador/red |
| message_state TLV | status (respaldo numérico) | Estado numérico SMPP detrás del token |
| fecha de envío / fecha de finalización | submitted_at / done_at | Marcas de tiempo de latencia y conciliación |

## Preguntas frecuentes

### ¿Qué contiene el payload de un webhook de estado de entrega (DLR)?

El message_id asignado por el servidor que lo correlaciona con tu envío, un estado extraído de un enum canónico (accepted, enroute, delivered, undelivered, expired, rejected, unknown), un código de error y un motivo legible por humanos para los fallos, y marcas de tiempo de cuándo se envió el mensaje y cuándo ocurrió el estado terminal.

### ¿En qué se diferencia un evento entrante (MO) de un DLR?

Un DLR es el resultado asíncrono de un mensaje que enviaste. Un evento entrante (MO) es no solicitado: un mensaje que un abonado envió a tu número o una respuesta a una campaña, que porta from, to, el texto, la codificación y, para mensajes multiparte, los campos de concatenación. Comparten transporte y firma pero tienen esquemas distintos, así que los consumidores se bifurcan primero según el tipo de evento.

### ¿Por qué estandarizar el enum de estado de entrega?

Porque las respuestas en bruto de los operadores varían enormemente. Mapearlas a un pequeño enum canónico con una semántica clara de terminal y de éxito permite a un solo consumidor gestionar todos los operadores de manera uniforme, y decidir solo a partir del estado si suprimir un destino incorrecto, reenviar un fallo transitorio o registrar una entrega confirmada.

### ¿Cómo evito que un 'accepted' tardío sobrescriba un 'delivered' anterior?

Usa los campos de auto-ordenación. Los payloads DLR portan una marca de tiempo y a menudo un número de secuencia; el consumidor los compara con el último estado que registró para ese id de mensaje y descarta cualquier evento más antiguo que lo que ya tiene, para que un estado intermedio fuera de orden nunca aplaste uno terminal.

### ¿Cómo se corresponde un DLR HTTP con un acuse deliver_sm de SMPP?

Portan la misma información. En SMPP el acuse es una PDU deliver_sm marcada en esm_class, con los campos id, stat y err y un TLV message_state. El DLR HTTP mapea stat al enum de estado, err al campo error y las marcas de tiempo del acuse a submitted_at/done_at, para que un único camino de gestión de entregas sirva a ambos transportes.

### ¿Qué campos me permiten reensamblar un SMS entrante multiparte?

Los campos de concatenación: una referencia que liga las partes, el índice de parte y el total. Como el SMS entrante obedece las mismas reglas de codificación y segmentación que el saliente, un mensaje entrante largo llega como varios eventos MO que el consumidor cose en orden usando esos campos.

## Fuentes

- [IETF RFC 9110 — HTTP Semantics](https://datatracker.ietf.org/doc/html/rfc9110)
- [IETF RFC 8288 — Web Linking (Link header)](https://datatracker.ietf.org/doc/html/rfc8288)

## Relacionado

- [Entrega y fiabilidad de webhooks](https://www.broadnet.me/es/reference/webhook-delivery-and-reliability)
- [Verificación de firma de webhooks](https://www.broadnet.me/es/reference/webhook-signature-verification)
- [Acuses de entrega SMPP (DLR)](https://www.broadnet.me/es/reference/smpp-delivery-receipts-dlr)
- [SMPP deliver_sm](https://www.broadnet.me/es/reference/smpp-deliver-sm)
- [Guía de webhooks de BroadNet](https://www.broadnet.me/es/developers/webhooks)
