Correlación de mensajes A2P SMS: trazabilidad entre API, SMPP, proveedores y DLR
Diseñe una cadena de identificadores y eventos para investigar mensajes A2P SMS a través de APIs HTTP, SMPP, proveedores, reintentos, segmentos y recibos de entrega, sin confundir aceptación con entrega.

Por qué el identificador del proveedor no basta
Un identificador emitido por un proveedor es necesario, pero rara vez basta para explicar todo el ciclo de vida de un SMS A2P. Normalmente identifica una aceptación concreta dentro del dominio de ese proveedor. No representa, por sí solo, la solicitud original del cliente, la decisión de ruta, un reintento posterior, los segmentos de un mensaje concatenado ni los eventos que puedan llegar después.
El problema aparece en operaciones reales: una solicitud puede permanecer en cola, generar más de un intento, cambiar de ruta según una política interna o recibir un callback tardío. Si el sistema guarda solo el identificador externo, será difícil responder con precisión qué se envió, qué intento produjo un DLR y qué parte de la evidencia procede de cada sistema.
La regla operativa es conservar un identificador interno estable para el mensaje lógico y registrar, sin sustituirlos, los identificadores asignados en cada frontera técnica. El identificador de proveedor debe tratarse como una clave de correlación dentro de una relación más amplia, no como la identidad global del mensaje.
- No equipare aceptación del proveedor con entrega al terminal.
- No reutilice un ID del proveedor como ID interno de negocio.
- No asuma que dos proveedores usarán el mismo formato, alcance o duración para sus identificadores.
- Conserve las respuestas y eventos originales junto con su interpretación normalizada.

Mapa de la cadena de trazabilidad
La trazabilidad debe modelar estados y eventos, no solo una tabla final de estado. Una cadena mínima comienza con la solicitud recibida del cliente, continúa con su validación y entrada en cola, y registra cada intento de envío creado por el sistema. Para cada intento aceptado por un proveedor, se añade el identificador devuelto por ese proveedor. Los DLR y callbacks posteriores se almacenan como eventos separados.
Este enfoque evita una pérdida habitual de contexto: sobrescribir el estado anterior con el último evento recibido. Un DLR es evidencia de un evento posterior; no sustituye la evidencia de que se recibió una solicitud, de que se construyó un intento o de que un proveedor respondió a la presentación.
Un mapa práctico puede seguir esta secuencia: solicitud del cliente, mensaje lógico interno, decisión de enrutamiento, intento de envío, presentación HTTP o SMPP, aceptación o error del proveedor y eventos posteriores de estado. Cuando exista segmentación, cada segmento debe quedar vinculado al mensaje lógico y, cuando corresponda, al intento que lo generó.
- Solicitud del cliente: registra la referencia del cliente, si existe, y el momento de recepción.
- Mensaje lógico: representa la intención de enviar un contenido a un destino.
- Intento: representa una presentación concreta por una ruta o proveedor determinado.
- Aceptación del proveedor: registra el ID externo y la respuesta recibida.
- Evento DLR o callback: conserva el payload original, el momento de recepción y la asociación resultante.
- Estado derivado: debe poder reconstruirse a partir de los eventos, no reemplazarlos.

Modelo de identificadores recomendado
Un esquema robusto separa los identificadores por función y alcance. El correlation ID vincula la solicitud inicial con el procesamiento interno. La idempotency key protege contra duplicados de la misma petición del cliente. El message ID interno identifica el mensaje lógico. El attempt ID identifica cada presentación concreta. El provider message ID registra el identificador que devuelve un proveedor para una aceptación concreta.
Estas claves no son intercambiables. En particular, un reintento no debe recibir el mismo attempt ID, aunque represente el mismo mensaje lógico. Del mismo modo, dos solicitudes repetidas no deberían crear mensajes lógicos diferentes si se reconoce una misma idempotency key válida dentro de la política definida por la plataforma.
Genere IDs internos con suficiente unicidad y manténgalos opacos para clientes externos salvo que su contrato de integración establezca otra cosa. La estructura del ID no debe revelar números de teléfono, contenido, proveedor, ruta ni información operativa sensible.
- correlation ID: creado al recibir la operación o contexto de negocio; une sistemas internos y registros relacionados.
- idempotency key: aportada por el cliente o definida por la integración; detecta repeticiones de una misma operación.
- message ID interno: creado al aceptar el mensaje lógico en el sistema propio; es estable durante su ciclo de vida.
- attempt ID: creado para cada intento de presentación; cambia en cada reintento o cambio de ruta.
- provider message ID: recibido tras la aceptación de un intento por el proveedor; puede tener un formato opaco y específico del proveedor.
- event ID: creado al ingerir cada callback, DLR o resultado de consulta; permite deduplicar y auditar eventos.
Qué debe crear cada parte y qué no debe reutilizarse
El cliente puede aportar una idempotency key o una referencia de negocio. La plataforma debe crear sus propios IDs de correlación, mensaje, intento y evento. Cada proveedor puede devolver su propio identificador de mensaje. Esta distribución permite conservar responsabilidades claras y evita que una clave de corto alcance se convierta indebidamente en una clave universal.
No reutilice una idempotency key como message ID, ni un message ID interno como attempt ID. Tampoco convierta un provider message ID en una referencia de cliente. Estas reutilizaciones parecen simplificar el modelo al principio, pero impiden representar reintentos, migraciones de ruta y discrepancias entre sistemas.
Si una integración HTTP permite añadir parámetros propios a la URL de callback, pueden servir como pista adicional de asociación. Aun así, no reemplazan el ID nativo del proveedor ni justifican descartar la validación del origen, el registro íntegro del evento y la reconciliación posterior.
- Una solicitud repetida puede compartir idempotency key, pero no debe producir dos mensajes lógicos si la política la reconoce como duplicada.
- Un mensaje lógico puede tener muchos intentos.
- Cada intento puede recibir cero, uno o más identificadores externos, según la interfaz y los eventos disponibles.
- Un callback recibido no debe generar automáticamente un mensaje nuevo cuando su referencia sea desconocida.
- La asociación debe registrar método y nivel de confianza: exacta, probable o no resuelta.
Relaciones uno a uno y uno a muchos: mensajes, segmentos, reintentos, rutas y DLR
El mensaje lógico es la entidad central, pero no siempre coincide con una sola presentación ni con una sola unidad técnica de SMS. Un contenido concatenado puede dividirse en varios segmentos. Un mismo mensaje puede generar varios intentos. Cada intento puede circular por una ruta distinta y producir eventos posteriores separados.
Modele explícitamente estas relaciones. Un mensaje lógico puede tener uno o varios segmentos; cada segmento puede requerir su propio resultado técnico. Un mensaje lógico puede tener uno o varios intentos, mientras que un intento debe pertenecer a un único mensaje lógico. Un intento puede tener una decisión de ruta registrada y uno o varios eventos de proveedor o DLR asociados.
En SMPP, los mensajes concatenados pueden relacionarse mediante sar_msg_ref_num, sar_total_segments y sar_segment_seqnum. La referencia SAR la genera el originador para permitir el reensamblado. Es útil conservarla como atributo técnico de segmentación, pero no debe reemplazar al message ID interno de la plataforma.
- Mensaje lógico a segmentos: uno a muchos.
- Mensaje lógico a intentos: uno a muchos.
- Intento a proveedor o ruta: normalmente uno a uno por presentación, aunque debe conservarse el historial de decisiones.
- Intento a eventos: uno a muchos.
- Segmento a DLR: puede ser uno a muchos cuando hay eventos repetidos, cambios de estado o evidencia recibida por más de un canal.
HTTP y SMPP: diferencias prácticas de correlación
En una API HTTP, el proveedor suele responder con un identificador de recurso o de mensaje. Conviene guardarlo junto con la respuesta inicial, el timestamp y el estado inicial. Los callbacks posteriores deben asociarse primero mediante ese identificador nativo cuando esté presente. Si el proveedor expone una consulta del recurso, esta sirve para reconciliar callbacks ausentes o estados no finales.
En SMPP, el sequence_number correlaciona una PDU de solicitud con su respuesta asociada dentro de una sesión asíncrona. Lo asigna el originador de la PDU, se incrementa de forma monotónica y la respuesta asociada conserva ese valor. Es, por tanto, una referencia de transporte de corta duración y no un identificador permanente del mensaje entre sistemas o proveedores.
La respuesta submit_sm_resp puede devolver un message_id asignado por el SMSC. Ese ID es opaco y está en el dominio del SMSC. En un DLR, el TLV receipted_message_id identifica el mensaje objeto del recibo mediante el mismo ID opaco devuelto al aceptar la presentación original. Guarde tanto el valor original como el DLR completo para demostrar cómo se realizó la asociación.
Para solicitar DLR en SMPP, se usa registered_delivery en submit_sm o data_sm. El estándar contempla solicitar resultado final de éxito o fallo, o solo fallo final. La solicitud de un recibo no garantiza que un evento llegue, que tenga un formato uniforme ni que pruebe recepción independiente en el terminal.
- HTTP: vincule la respuesta de creación, el ID nativo y cada callback al intento correspondiente.
- SMPP sequence_number: úselo para solicitud-respuesta en la sesión, nunca como identificador persistente de negocio.
- SMPP message_id: almacénelo como ID externo asignado a una presentación aceptada.
- SMPP receipted_message_id: úselo como clave principal de asociación de DLR cuando esté presente y coincida.
- SMPP user_message_reference: puede ayudar si se propaga, pero es un TLV opcional; no diseñe una garantía sobre su presencia.
- DLR dentro de short_message: no presuponga un formato universal; la especificación SMPP indica que puede ser específico del proveedor.
Campos operativos que conviene registrar
Los identificadores explican qué objetos están relacionados; los metadatos explican qué ocurrió y bajo qué condiciones. Registre timestamps separados para recepción de solicitud, creación del mensaje, creación del intento, envío al proveedor, respuesta del proveedor, recepción de callback y actualización derivada. Evite usar un único campo de fecha para todas estas etapas.
Conserve el destino en una representación normalizada y separada de las referencias operativas. Para SMS, E.164 es una referencia útil para la normalización internacional de números. Aun así, un número normalizado no debe utilizarse como clave exclusiva de correlación: varios mensajes pueden dirigirse al mismo destino y los datos de destino son potencialmente personales.
Registre remitente, codificación, longitud y número de segmentos, configuración de DLR solicitada, interfaz utilizada, resultado de validación y una versión de la política de ruta aplicada. La versión de política permite explicar una decisión histórica sin inferirla a partir de la configuración actual.
- Timestamps con zona horaria y fuente de reloj claramente definidas.
- Destino normalizado y protegido como dato potencialmente personal.
- Remitente usado en la presentación, sin asumir que identifica al emisor real.
- Codificación, tamaño y segmentación efectiva.
- Canal e interfaz: HTTP, SMPP u otro adaptador interno.
- Ruta o proveedor seleccionado y versión de política de enrutamiento.
- Solicitud de DLR, respuesta de aceptación, código de error y payload original del evento.
- Método de asociación y nivel de certeza.
Callbacks duplicados, fuera de orden o sin referencia reconocible
Los callbacks son eventos asíncronos. Pueden llegar duplicados, fuera de orden, con campos adicionales o sin la referencia esperada. El diseño correcto no consiste en confiar en el orden de llegada, sino en preservar cada evento y calcular un estado derivado mediante reglas explícitas.
Para deduplicar, calcule una huella del payload original y combine, cuando sea posible, proveedor, identificador externo, tipo de evento, estado reportado y timestamp recibido. La deduplicación debe marcar eventos equivalentes sin borrar la evidencia recibida. Si dos eventos tienen la misma referencia pero datos distintos, consérvelos como registros diferentes y deje constancia de la discrepancia.
Cuando no se reconozca una referencia, almacene el evento en una zona de cuarentena o de no asociados. No cree una relación basándose solo en coincidencias de destino, hora o contenido: esos atributos pueden producir falsos positivos. Aplique asociaciones probabilísticas únicamente si la política operativa lo permite, etiquetándolas como tales y manteniendo el evento original sin modificar.
Los parámetros de callback pueden variar según el canal y el tipo de evento, e incluso ampliarse. Los receptores deben tolerar campos nuevos y conservar el payload sin exigir que todos los proveedores usen el mismo esquema.
- Persistir primero el payload original y sus cabeceras relevantes.
- Validar autenticidad y procedencia según el mecanismo documentado por cada proveedor.
- Deduplicar sin eliminar la evidencia original.
- No asumir orden cronológico por orden de recepción.
- Mantener eventos no asociados para investigación y reconciliación.
- No elevar una asociación probable a certeza sin una referencia verificable.
Preguntas frecuentes
¿El message_id de SMPP identifica un mensaje de forma global?
No. El message_id devuelto en submit_sm_resp es un identificador opaco asignado por el SMSC. Es útil para correlacionar la presentación aceptada con un DLR cuando este incluye receipted_message_id, pero no debe tratarse como una referencia global entre proveedores o plataformas.
¿Para qué sirve sequence_number en SMPP?
Sirve para correlacionar una PDU de solicitud con su respuesta asociada dentro de una sesión SMPP asíncrona. Lo asigna el originador de la PDU y no debe utilizarse como identificador persistente del mensaje.
¿Un DLR confirma que el destinatario leyó el SMS?
No. Un DLR informa de un estado de entrega comunicado por la cadena de mensajería. La aceptación por un proveedor tampoco equivale a entrega al terminal. Debe documentarse qué evento se recibió, de quién procede y cuál es su alcance.
¿Debo depender de user_message_reference para correlacionar DLR SMPP?
No como única base del diseño. SMPP contempla user_message_reference como parámetro opcional y su propagación no debe darse por garantizada. Mantenga siempre el mapeo entre el attempt ID interno y el message_id devuelto por el SMSC.
¿Qué hago si llega un callback sin un identificador conocido?
Conserve el evento original como no asociado, registre su procedencia y aplique reconciliación con el proveedor cuando sea posible. No cree una asociación definitiva basándose solo en número, hora o contenido, porque podría vincular mensajes distintos.
¿Cuánto tiempo debo conservar los registros de trazabilidad?
Defina el plazo según la finalidad operativa, obligaciones aplicables y políticas de seguridad. Aplique minimización, limitación de conservación, controles de acceso e integridad. Separe los identificadores operativos de los datos personales, como destino, remitente o contenido.
Fuentes consultadas
- SMPP Protocol Specification v3.4, Issue 1.2SMPP Developers Forum
- Messages resourceTwilio
- Best Practices for Messaging Delivery Status LoggingTwilio
- Outbound Message Status in Status CallbacksTwilio
- E.164: The international public telecommunication numbering planInternational Telecommunication Union
- A guide to the data protection principlesInformation Commissioner's Office