Corrélation des messages A2P SMS : traçabilité entre API, SMPP, fournisseurs et DLR
Concevez une chaîne d’identifiants et d’événements pour analyser les messages A2P SMS via des API HTTP, SMPP, des fournisseurs, des tentatives, des segments et des accusés de réception, sans confondre acceptation et livraison.

Pourquoi l’identifiant du fournisseur ne suffit pas
Un identifiant émis par un fournisseur est nécessaire, mais il suffit rarement à expliquer tout le cycle de vie d’un SMS A2P. Il identifie généralement une acceptation précise dans le périmètre de ce fournisseur. À lui seul, il ne représente pas la demande initiale du client, la décision de routage, une tentative ultérieure, les segments d’un message concaténé ni les événements pouvant arriver ensuite.
Le problème apparaît dans les opérations réelles : une demande peut rester en file d’attente, générer plusieurs tentatives, changer de route selon une politique interne ou recevoir un callback tardif. Si le système ne conserve que l’identifiant externe, il devient difficile de déterminer précisément ce qui a été envoyé, quelle tentative a produit un DLR et quelle part des éléments de preuve provient de chaque système.
La règle opérationnelle consiste à conserver un identifiant interne stable pour le message logique et à enregistrer, sans les remplacer, les identifiants attribués à chaque frontière technique. L’identifiant du fournisseur doit être traité comme une clé de corrélation au sein d’une relation plus large, et non comme l’identité globale du message.
- N’assimilez pas l’acceptation par le fournisseur à la livraison sur le terminal.
- Ne réutilisez pas un ID de fournisseur comme ID métier interne.
- Ne supposez pas que deux fournisseurs utiliseront le même format, le même périmètre ou la même durée de conservation pour leurs identifiants.
- Conservez les réponses et événements d’origine avec leur interprétation normalisée.

Cartographie de la chaîne de traçabilité
La traçabilité doit modéliser les états et les événements, et pas seulement une table d’état finale. Une chaîne minimale commence par la demande reçue du client, se poursuit par sa validation et sa mise en file, puis enregistre chaque tentative d’envoi créée par le système. Pour chaque tentative acceptée par un fournisseur, l’identifiant renvoyé par ce fournisseur est ajouté. Les DLR et callbacks ultérieurs sont stockés comme des événements distincts.
Cette approche évite une perte de contexte fréquente : écraser l’état précédent par le dernier événement reçu. Un DLR constitue la preuve d’un événement ultérieur ; il ne remplace pas la preuve qu’une demande a été reçue, qu’une tentative a été construite ou qu’un fournisseur a répondu à la soumission.
Une cartographie pratique peut suivre cette séquence : demande client, message logique interne, décision de routage, tentative d’envoi, soumission HTTP ou SMPP, acceptation ou erreur du fournisseur, puis événements de statut ultérieurs. En cas de segmentation, chaque segment doit être relié au message logique et, lorsque cela est pertinent, à la tentative qui l’a généré.
- Demande client : enregistre la référence client, si elle existe, ainsi que l’heure de réception.
- Message logique : représente l’intention d’envoyer un contenu à une destination.
- Tentative : représente une soumission précise via une route ou un fournisseur donné.
- Acceptation par le fournisseur : enregistre l’ID externe et la réponse reçue.
- Événement DLR ou callback : conserve le payload d’origine, l’heure de réception et l’association obtenue.
- État dérivé : doit pouvoir être reconstruit à partir des événements, sans les remplacer.

Modèle d’identifiants recommandé
Un schéma robuste peut séparer les identifiants selon leur fonction et leur périmètre. Le correlation ID relie la demande initiale au traitement interne. L’idempotency key peut protéger contre les doublons d’une même demande client. Le message ID interne identifie le message logique. L’attempt ID identifie chaque soumission précise. Le provider message ID enregistre l’identifiant qu’un fournisseur renvoie pour une acceptation donnée.
Ces clés ne sont pas interchangeables. En particulier, une nouvelle tentative ne doit pas recevoir le même attempt ID, même si elle représente le même message logique. De même, deux demandes répétées ne devraient pas créer de messages logiques différents si une même idempotency key valide est reconnue dans le cadre de la politique définie par la plateforme.
Générez des IDs internes avec une unicité suffisante et conservez leur caractère opaque pour les clients externes, sauf si votre contrat d’intégration prévoit autre chose. La structure de l’ID ne doit pas révéler de numéros de téléphone, de contenu, de fournisseur, de route ou d’informations opérationnelles sensibles.
- correlation ID : créé à la réception de l’opération ou du contexte métier ; relie les systèmes internes et les enregistrements associés.
- idempotency key : fournie par le client ou définie par l’intégration ; détecte les répétitions d’une même opération.
- message ID interne : créé lors de l’acceptation du message logique dans le système propre ; il reste stable pendant son cycle de vie.
- attempt ID : créé pour chaque tentative de soumission ; il change à chaque nouvelle tentative ou changement de route.
- provider message ID : reçu après l’acceptation d’une tentative par le fournisseur ; il peut avoir un format opaque et propre au fournisseur.
- event ID : créé lors de l’ingestion de chaque callback, DLR ou résultat de consultation ; peut aider à dédupliquer et à auditer les événements.
Ce que chaque partie doit créer et ce qui ne doit pas être réutilisé
Le client peut fournir une idempotency key ou une référence métier. La plateforme doit créer ses propres IDs de corrélation, de message, de tentative et d’événement. Chaque fournisseur peut renvoyer son propre identifiant de message. Cette répartition préserve des responsabilités claires et évite qu’une clé à portée limitée ne devienne indûment une clé universelle.
Ne réutilisez pas une idempotency key comme message ID, ni un message ID interne comme attempt ID. Ne transformez pas non plus un provider message ID en référence client. Ces réutilisations semblent simplifier le modèle au départ, mais empêchent de représenter les nouvelles tentatives, les migrations de route et les divergences entre systèmes.
Si une intégration HTTP permet d’ajouter vos propres paramètres à l’URL de callback, ils peuvent servir d’indice supplémentaire d’association. Ils ne remplacent toutefois pas l’ID natif du fournisseur et ne justifient pas l’abandon de la validation de l’origine, de l’enregistrement complet de l’événement et de la réconciliation ultérieure.
- Une demande répétée peut partager une idempotency key, mais elle ne doit pas produire deux messages logiques si la politique la reconnaît comme un doublon.
- Un message logique peut comporter de nombreuses tentatives.
- Dans une soumission SMPP typique acceptée, submit_sm_resp renvoie un message_id. Plusieurs IDs externes peuvent néanmoins être enregistrés lorsque des adaptateurs, des renvois ou des fournisseurs successifs interviennent.
- Un callback reçu ne doit pas créer automatiquement un nouveau message lorsque sa référence est inconnue.
- Selon la politique de conception, l’association peut enregistrer sa méthode et être qualifiée d’exacte, de probable ou de non résolue.
Relations un à un et un à plusieurs : messages, segments, tentatives, routes et DLR
Le message logique est l’entité centrale, mais il ne correspond pas toujours à une seule soumission ni à une seule unité technique SMS. Un contenu concaténé peut être divisé en plusieurs segments. Un même message peut générer plusieurs tentatives. Chaque tentative peut emprunter une route différente et produire des événements ultérieurs distincts.
Modélisez explicitement ces relations. Un message logique peut avoir un ou plusieurs segments ; chaque segment peut nécessiter son propre résultat technique. Un message logique peut avoir une ou plusieurs tentatives, tandis qu’une tentative doit appartenir à un seul message logique. Une tentative peut avoir une décision de routage enregistrée et un ou plusieurs événements de fournisseur ou DLR associés.
Dans SMPP, les messages concaténés peuvent être associés à l’aide de sar_msg_ref_num, sar_total_segments et sar_segment_seqnum. La référence SAR est générée par l’émetteur pour permettre le réassemblage. Il est utile de la conserver en tant qu’attribut technique de segmentation, mais elle ne doit pas remplacer le message ID interne de la plateforme.
- Message logique vers segments : un à plusieurs.
- Message logique vers tentatives : un à plusieurs.
- Tentative vers fournisseur ou route : généralement un à un par soumission, mais l’historique des décisions doit être conservé.
- Tentative vers événements : un à plusieurs.
- Segment vers DLR : potentiellement un à plusieurs en cas d’événements répétés, de changements d’état ou d’éléments de preuve reçus par plusieurs canaux.
HTTP et SMPP : différences pratiques de corrélation
Dans de nombreuses API HTTP, le fournisseur répond avec un identifiant de ressource ou de message. Lorsqu’une API le fournit, enregistrez-le avec la réponse initiale, l’horodatage et l’état initial. Les callbacks ultérieurs doivent d’abord être associés à l’aide de cet identifiant natif lorsqu’il est présent. Si le fournisseur expose une consultation de la ressource, celle-ci permet de réconcilier les callbacks absents ou les états non finaux.
Dans SMPP, le sequence_number corrèle une PDU de demande avec sa réponse associée au sein d’une session asynchrone. Il est attribué par l’émetteur de la PDU, doit être incrémenté de manière monotone et la réponse associée conserve cette valeur. Son usage reste limité à la session et à la corrélation de transport demande-réponse ; il ne constitue pas un identifiant permanent du message entre systèmes ou fournisseurs, notamment au-delà des reconnexions ou des sessions distinctes.
La réponse submit_sm_resp peut renvoyer un message_id attribué par le SMSC. Cet ID est opaque et relève du domaine du SMSC. Dans un DLR, le TLV receipted_message_id identifie le message concerné par l’accusé de réception au moyen de l’identifiant opaque renvoyé lors de l’acceptation de la soumission initiale. En pratique, l’association dépend du fait que le SMSC ou le fournisseur inclut cette valeur et la propage de manière cohérente. Conservez à la fois la valeur d’origine et le DLR complet afin de démontrer comment l’association a été effectuée.
Pour demander des DLR dans SMPP, on utilise registered_delivery dans submit_sm ou data_sm. La norme prévoit de demander le résultat final de réussite ou d’échec, ou uniquement l’échec final. La demande d’un accusé de réception ne garantit pas qu’un événement arrive, qu’il ait un format uniforme ou qu’il prouve une réception indépendante sur le terminal.
- HTTP : lorsque l’API fournit un ID natif, reliez la réponse de création, cet ID et chaque callback à la tentative correspondante.
- SMPP sequence_number : utilisez-le pour la relation demande-réponse dans la session, jamais comme identifiant métier persistant.
- SMPP message_id : stockez-le comme ID externe attribué à une soumission acceptée.
- SMPP receipted_message_id : utilisez-le comme clé principale d’association de DLR lorsqu’il est présent et correspond à l’ID de soumission conservé.
- SMPP user_message_reference : peut aider s’il est propagé, mais il s’agit d’un TLV facultatif ; ne fondez pas une garantie sur sa présence.
- DLR dans short_message : ne supposez pas de format universel ; la spécification SMPP indique qu’il peut être propre au fournisseur.
Champs opérationnels à enregistrer
Les identifiants expliquent quels objets sont liés ; les métadonnées expliquent ce qui s’est produit et dans quelles conditions. Enregistrez des horodatages distincts pour la réception de la demande, la création du message, la création de la tentative, l’envoi au fournisseur, la réponse du fournisseur, la réception du callback et la mise à jour dérivée. Évitez d’utiliser un seul champ de date pour toutes ces étapes.
Conservez la destination dans une représentation normalisée, séparée des références opérationnelles. Pour les SMS, E.164 est une référence utile pour la normalisation internationale des numéros. Toutefois, un numéro normalisé ne doit pas être utilisé comme clé de corrélation exclusive : plusieurs messages peuvent cibler la même destination et les données de destination sont potentiellement personnelles.
Enregistrez l’expéditeur, l’encodage, la longueur et le nombre de segments, la configuration DLR demandée, l’interface utilisée, le résultat de validation et une version de la politique de routage appliquée. La version de politique permet d’expliquer une décision historique sans l’inférer à partir de la configuration actuelle.
- Horodatages avec fuseau horaire et source d’horloge clairement définis.
- Destination normalisée et protégée en tant que donnée potentiellement personnelle.
- Expéditeur utilisé lors de la soumission, sans supposer qu’il identifie l’émetteur réel.
- Encodage, taille et segmentation effective.
- Canal et interface : HTTP, SMPP ou autre adaptateur interne.
- Route ou fournisseur sélectionné et version de la politique de routage.
- Demande de DLR, réponse d’acceptation, code d’erreur et payload d’origine de l’événement.
- Méthode d’association et niveau de certitude.
Callbacks dupliqués, désordonnés ou sans référence reconnue
Les callbacks sont des événements asynchrones. Ils peuvent arriver en double, dans le désordre, avec des champs supplémentaires ou sans la référence attendue. La bonne conception ne consiste pas à faire confiance à l’ordre d’arrivée, mais à conserver chaque événement et à calculer un état dérivé au moyen de règles explicites.
Pour dédupliquer, calculez, lorsque cela est nécessaire, une empreinte sur une représentation canonique du payload d’origine. Combinez-la, lorsque possible, avec le fournisseur, l’identifiant externe, le type d’événement, l’état signalé et l’horodatage de réception. Les payloads peuvent contenir des données personnelles ou du contenu sensible : évitez d’enregistrer ou de réutiliser les données non nécessaires, et protégez les éléments de preuve conservés. La déduplication doit marquer les événements équivalents sans effacer les éléments de preuve reçus. Si deux événements ont la même référence mais des données différentes, conservez-les comme enregistrements distincts et consignez la divergence.
Lorsqu’une référence n’est pas reconnue, une conception peut stocker l’événement parmi les événements non associés ou dans une zone de quarantaine. Ne créez pas de relation uniquement sur la base de correspondances de destination, d’heure ou de contenu : ces attributs peuvent entraîner des faux positifs. N’appliquez des associations probabilistes que si la politique opérationnelle l’autorise, en les étiquetant comme telles et en conservant l’événement d’origine sans modification.
Les paramètres de callback peuvent varier selon le canal et le type d’événement, et peuvent même être enrichis. Les récepteurs doivent tolérer de nouveaux champs et conserver le payload sans exiger que tous les fournisseurs utilisent le même schéma.
- Persistez d’abord le payload d’origine et ses en-têtes pertinents, en limitant les données conservées à ce qui est nécessaire et en les protégeant.
- Validez l’authenticité et la provenance selon le mécanisme documenté par chaque fournisseur.
- Dédupliquez sans supprimer les éléments de preuve d’origine.
- Ne supposez pas un ordre chronologique à partir de l’ordre de réception.
- Conservez les événements non associés pour investigation et réconciliation.
- N’élevez pas une association probable au rang de certitude sans référence vérifiable.
Questions fréquentes
Le message_id SMPP identifie-t-il un message de manière globale ?
Non. Le message_id renvoyé dans submit_sm_resp est un identifiant opaque attribué par le SMSC. Il est utile pour corréler une soumission acceptée à un DLR lorsque celui-ci inclut receipted_message_id et que cette valeur est propagée de manière cohérente, mais il ne doit pas être traité comme une référence globale entre fournisseurs ou plateformes.
À quoi sert sequence_number dans SMPP ?
Il sert à corréler une PDU de demande avec sa réponse associée au sein d’une session SMPP asynchrone. Il est attribué par l’émetteur de la PDU, doit être incrémenté de manière monotone et ne doit pas être utilisé comme identifiant persistant du message au-delà de cette corrélation de session.
Un DLR confirme-t-il que le destinataire a lu le SMS ?
Non. Un DLR indique un état de livraison communiqué par la chaîne de messagerie. L’acceptation par un fournisseur n’équivaut pas non plus à la livraison sur le terminal. Il faut documenter quel événement a été reçu, de qui il provient et quelle est sa portée.
Dois-je dépendre de user_message_reference pour corréler les DLR SMPP ?
Non, pas comme base unique de conception. SMPP prévoit user_message_reference comme paramètre facultatif et sa propagation ne doit pas être considérée comme garantie. Conservez toujours le mapping entre l’attempt ID interne et le message_id renvoyé par le SMSC.
Que faire si un callback arrive sans identifiant connu ?
Conservez l’événement d’origine comme non associé, enregistrez sa provenance et effectuez une réconciliation avec le fournisseur lorsque cela est possible. Ne créez pas d’association définitive uniquement à partir du numéro, de l’heure ou du contenu, car cela pourrait relier des messages différents.
Combien de temps dois-je conserver les enregistrements de traçabilité ?
Définissez la durée selon la finalité opérationnelle, les obligations applicables et les politiques de sécurité. Appliquez la minimisation, la limitation de conservation, des contrôles d’accès et des mesures d’intégrité. Séparez les identifiants opérationnels des données personnelles, telles que la destination, l’expéditeur ou le contenu.
Sources consultées
- 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