Construire une messagerie multicanal avec une seule API

Ce que tu construis vraiment quand tu ajoutes la messagerie

Si tu as déjà ajouté une fonction de messagerie à une application, tu as probablement réalisé assez vite que l’envoi du message est en fait la partie facile. La partie pénible, c’est de supporter plusieurs canaux. Tu dois décider si tu utilises SMS, WhatsApp ou RCS, gérer des identifiants différents, formater le message différemment pour chaque canal, et ensuite construire ta propre logique de repli quand l’un de ces canaux ne fonctionne pas.

C’est le problème que Send essaie de résoudre. Il te donne une seule API pour SMS, WhatsApp et RCS, et au lieu que ton application décide quel canal utiliser, Send détermine cela en fonction de ce qui est disponible et de ce qui fonctionne le mieux pour ce destinataire. Il gère aussi le routage, le formatage des messages, les solutions de repli et la conformité en arrière-plan, pour que ton code reste le même, peu importe comment le message est réellement livré.

Dans cette démonstration, on va construire une vraie application avec Send et l’utiliser pour envoyer un message réel à un téléphone. On va aller au-delà du simple déclenchement d’un message en espérant que ça marche : je vais te montrer le canal par lequel Send l’a effectivement routé. Ensuite, on mettra en place des webhooks pour pouvoir regarder ce message passer de message.sent à message.delivered en temps réel.

On se lance dans la construction.

Rendre la démo un peu plus utile qu’un simple script

Pour cette construction, je veux rendre ça un peu plus utile que d’envoyer un message depuis un script. Je vais donc construire une fonctionnalité simple de notification qui pourrait réellement faire partie d’une application plus large. L’idée, c’est que quand quelque chose d’important se produit, l’application puisse notifier l’utilisateur sans avoir à se soucier de savoir si cette notification finit par passer par SMS, WhatsApp ou RCS.

Je vais utiliser TypeScript pour ça. Send a des SDKs pour plusieurs langages, donc tu peux suivre la même approche de base même si tu travailles avec une pile technologique différente.

Avant d’écrire la moindre ligne de code, il y a un peu de configuration de compte à faire. Send a un parcours d’intégration léger qui te permet de commencer à envoyer tout de suite sur un expéditeur partagé, ce que j’utilise ici. Si tu veux ta propre identité d’expéditeur, il y a aussi une voie plus complète. Pour les SMS aux États-Unis, ça signifie l’enregistrement 10DLC et TCR, que Send soumet pour toi une fois que tu l’as rempli. Cette approbation prend environ 1 à 3 jours ouvrés, donc ça vaut le coup de commencer tôt, mais tu n’as pas besoin d’attendre pour commencer à construire.

Une fois que c’est prêt, on peut vraiment commencer à construire. Je vais créer un nouveau projet TypeScript, installer le SDK Send, et configurer les variables d’environnement pour la clé API et le numéro de téléphone que je vais utiliser pour la démo.

Maintenant que le projet est en place, regardons le message que nous voulons réellement envoyer.

L’appel API qui ne choisit pas de canal

On peut maintenant entrer dans la partie qui rend Send vraiment intéressant. Je vais garder le code de l’application intentionnellement simple parce que tout l’intérêt, c’est que je ne veux pas que l’application sache quel canal de messagerie elle devrait utiliser.

Je vais initialiser le client Send en utilisant la clé API de mes variables d’environnement, puis je peux faire une requête avec le destinataire et le template que je veux envoyer. La partie importante ici, c’est que je ne spécifie ni SMS, ni WhatsApp, ni RCS dans cette requête. Je dis simplement à Send : « Envoie ce message à cette personne », et je laisse la plateforme déterminer le chemin de livraison.

La documentation de Send décrit cela comme le routeur intelligent qui choisit le meilleur canal disponible en fonction de critères comme la disponibilité, les données d’engagement et le prix. J’utilise aussi une référence de template plutôt que de mettre le corps entier du message directement dans mon code applicatif. Ça signifie que le code peut rester le même tandis que le contenu réel du message et ses variables sont gérés par le système de templates, et Send peut adapter ce contenu au canal qui finit par être sélectionné.

On obtient l’ID du message et le statut initial, puis un instant plus tard, une fois que Send a pris la décision de routage, on peut voir quel canal il a choisi pour ce destinataire. Et c’est là que l’abstraction devient plutôt utile. Mon application a fait exactement le même appel API, que le résultat soit SMS, WhatsApp ou RCS, pendant que Send gérait la sélection du canal et les détails de livraison en dessous.

Pourquoi la réponse API ne suffit pas

Il y a encore une chose qu’on doit faire, parce que cette réponse nous dit seulement que Send a accepté le message. Ça ne veut pas dire que le message a réellement atteint mon téléphone. Donc ensuite, je vais mettre en place un webhook et suivre le message tout au long de sa livraison.

On sait maintenant que Send a accepté le message et on peut voir quel canal il a sélectionné, mais la réponse API elle-même ne va pas attendre que l’opérateur ou le fournisseur de messagerie confirme la livraison. La messagerie est asynchrone, donc si on veut réellement savoir ce qui est arrivé au message, on doit écouter les événements que Send nous renvoie.

Mettre en place le endpoint webhook

Je vais aller dans le tableau de bord Send et créer un webhook qui pointe vers mon application. Pour le développement local, je peux exposer le endpoint publiquement, puis je vais m’abonner aux événements de message qui nous intéressent, spécifiquement message.sent et message.delivered. Send appellera alors ce endpoint chaque fois que le message passe par ces étapes.

Dans l’application, je vais créer un petit endpoint webhook qui reçoit l’événement et logue l’ID du message, le type d’événement, le canal sélectionné et le statut actuel du message. Il y a aussi un secret de signature fourni par Send, donc je vais garder ça dans mes variables d’environnement et vérifier la signature du webhook avant de traiter quoi que ce soit. Comme ça, on n’accepte pas simplement des requêtes arbitraires de l’internet public en les traitant comme de vrais événements de livraison.

Le flux complet en un seul endroit

Avec ça en place, on peut relancer l’application et envoyer le message. D’abord, on obtient la réponse initiale de l’API, puis, un instant plus tard, on devrait voir l’événement message.sent arriver. Ça nous dit que Send a passé avec succès le message au fournisseur en aval.

Et maintenant, c’est la partie que je voulais vraiment voir, parce qu’on devrait recevoir un autre événement quand le message atteint réellement le téléphone. Vérifions la sortie du webhook, et voilà, message.delivered. Maintenant, on peut voir tout le flux en un seul endroit. L’application envoie une requête API sans choisir de canal, Send sélectionne la route, et ensuite le webhook nous dit quand ce message a été réellement envoyé et livré.

L’application n’a pas besoin de chemins de code séparés pour SMS, WhatsApp et RCS pour que ça fonctionne. Et puisque j’utilise mon vrai téléphone, vérifions l’autre côté et voyons ce qui est réellement apparu.

Ce qui arrive côté utilisateur

La dernière chose que je veux vérifier, c’est à quoi ça ressemble réellement du côté utilisateur. Comme Send ne fournit pas de numéro de téléphone de test séparé, j’envoie ça sur mon propre appareil, ce qui est aussi utile parce qu’on teste le flux complet plutôt que de simplement regarder une réponse API réussie.

Je vais donc déclencher la notification une fois de plus, et pendant que ça tourne, on peut regarder le terminal. La requête part, Send renvoie le canal sélectionné, et ensuite le webhook commence à nous donner les événements de livraison. Un envoi réussi apparaît d’abord comme message.sent, et une fois que le fournisseur en aval confirme qu’il a atteint l’appareil, on obtient message.delivered.

Et le voilà sur mon téléphone. Donc ce n’était pas une réponse simulée ou un faux résultat. C’est un vrai message qui passe par l’infrastructure Send et arrive sur l’appareil. Ce que j’aime dans cette configuration, c’est que si je décide plus tard de supporter un autre canal, la logique de notification centrale n’a soudainement pas besoin d’une autre branche pour ce canal. L’application fait toujours la même requête et référence le même template, tandis que Send gère le travail spécifique au canal après ça.

C’est vraiment l’idée principale derrière toute la plateforme : sortir la complexité de la messagerie de l’application elle-même.

Ce que ça change pour une vraie application

À ce stade, on a construit tout le flux de messagerie, mais la raison plus large pour laquelle j’utiliserais quelque chose comme Send, c’est la quantité de logique que tu n’as pas à maintenir toi-même. Si tu supportes plusieurs canaux manuellement, ton application commence à accumuler du code spécifique aux canaux pour des choses comme choisir le bon fournisseur, gérer les identifiants, formater les charges utiles et décider quoi faire quand un canal n’est pas disponible.

Avec Send, cette logique se trouve derrière l’API de messagerie. Tu fais une requête, tu références un template et ses variables, et Send détermine le canal disponible et gère le routage, le formatage, les solutions de repli et la conformité pour toi. Ça devient particulièrement utile quand tu envoies à l’international, parce que le SMS n’est pas toujours l’option la plus fiable selon le destinataire. La couche de routage de Send est conçue pour choisir parmi SMS, WhatsApp et RCS, plutôt que de forcer ton application à dépendre d’un seul canal. C’est l’une des raisons pour lesquelles l’approche multi-canal est plus intéressante que d’avoir simplement une autre façon d’envoyer un SMS.

Et c’est à peu près la principale chose que je retiens de ça. Send n’essaie pas vraiment de rendre l’appel API lui-même plus compliqué, il fait le contraire. Le but est de garder le code applicatif simple pendant que l’infrastructure de messagerie gère tout ce qui se passe après que tu as cliqué sur envoyer. Si tu construis quelque chose qui a besoin de notifications transactionnelles, de messages d’authentification, d’alertes, ou fondamentalement de tout flux de travail où tu dois atteindre un utilisateur de manière fiable, je pense que cette approche a beaucoup de sens. Tu n’as pas besoin de commencer par concevoir ton application autour du SMS pour ensuite y greffer WhatsApp ou RCS plus tard. La livraison multi-canal est intégrée dans le flux de base dès le départ.

Ce que j’ai particulièrement aimé, c’est qu’on peut réellement voir la décision de routage, à la fois quand on relit le message et sur chaque événement webhook, puis suivre le message tout au long de ce cycle de vie jusqu’à ce qu’il atteigne le téléphone. Donc, même si une grande partie de la complexité est abstraite, tu as toujours de la visibilité sur ce qui se passe en dessous.

Points clés à retenir

  • L’envoi d’un message est facile ; supporter plusieurs canaux avec des identifiants, formats et logiques de repli différents est la partie pénible.
  • Send fournit une API unique pour SMS, WhatsApp et RCS, et le routeur intelligent choisit le meilleur canal disponible pour chaque destinataire.
  • Le code applicatif n’a pas besoin de spécifier un canal : il référence un template, et Send adapte le contenu et gère la livraison.
  • La réponse API confirme l’acceptation, mais les webhooks sont nécessaires pour suivre le cycle de vie asynchrone jusqu’à message.delivered.
  • La vérification de la signature du webhook est essentielle pour ne pas traiter des requêtes arbitraires comme de vrais événements de livraison.
  • L’approche retire la logique spécifique aux canaux de ton application, ce qui compte vraiment quand tu évolues ou que tu envoies à l’international.
  • Tu obtiens de la visibilité sur les décisions de routage et les événements de livraison, même si la complexité sous-jacente est abstraite.
  • La livraison multi-canal est intégrée dès le départ, sans avoir à concevoir d’abord pour un seul canal puis à en ajouter d’autres après coup.

Si tu veux essayer ça par toi-même, la documentation de Send et le code source complet de ce projet sont disponibles. Tu peux utiliser la même configuration de base pour expérimenter avec différents templates et construire ton propre flux de messagerie multi-canal.