service-sms.pro
Retour au blog

API SMS : comment l'appeler, l'authentifier et gérer les retours

API SMS Par Loïc Bresler 11 min de lecture
Dans ce guide

Envoyer un premier SMS par API prend quelques minutes. Un exemple cURL copié depuis la documentation, une clé collée dans la ligne de commande, et le téléphone vibre sur le bureau. Tout le monde publie ce tutoriel, et presque tout le monde s’arrête là.

Les ennuis commencent trois semaines plus tard, en production. Une clé qui traîne dans un dépôt Git. Un appel resté sans réponse, que le serveur rejoue, et un client qui reçoit deux codes de connexion. Un 429 en plein pic d’activité, ou un accusé de réception qui ne revient jamais sans que personne sache si le message est parti.

On reprend donc l’appel là où les tutoriels le laissent : la requête et ses champs, les façons de s’authentifier, puis les retours, qui arrivent en deux temps. Si le vocabulaire de base vous manque encore (REST, JSON, webhook), notre guide de l’API SMS le pose tranquillement.

Un appel d’API SMS tient en quatre éléments

Quelle que soit la plateforme, l’envoi se ramène à une requête HTTP qui assemble une adresse, une méthode, des en-têtes et un corps. Les noms de champs changent d’une documentation à l’autre, la logique ne bouge pas.

curl -X POST https://api.exemple.com/v1/sms \
  -H "Authorization: Bearer $CLE_API_SMS" \
  -H "Content-Type: application/json" \
  --max-time 10 \
  -d '{
    "to": "+33612345678",
    "from": "MaSociete",
    "text": "Votre commande 4821 est expédiée.",
    "reference": "cmd-4821-expedition"
  }'

Deux détails de cet exemple manquent dans la plupart des tutoriels. La clé ne s’écrit pas en dur, elle vient d’une variable d’environnement. Et l’appel porte un délai maximal, ici dix secondes, au bout duquel votre code reprend la main au lieu d’attendre indéfiniment.

Partie de la requêteCe qu’elle contientL’erreur qui revient
Adresse et méthodeLe point d’accès d’envoi, appelé en POSTUn GET avec les paramètres dans l’URL
En-têtesL’authentification et le format du corpsContent-Type oublié, corps lu comme du texte brut
DestinataireLe numéro au format international E.164, +33 puis le numéro sans son zéroUn 06 brut, des espaces ou des points
ÉmetteurUn nom alphanumérique de 11 caractères au plus, ou un numéro courtUn nom trop long, tronqué ou refusé
TexteLe message, encodé en UTF-8Un caractère hors alphabet GSM qui multiplie les segments facturés
RéférenceVotre propre identifiant pour cet envoiAbsente, donc aucun rapprochement possible ensuite

Un mot sur l’émetteur. En France, un numéro mobile en 06 ou 07 ne peut pas servir d’expéditeur à un envoi automatisé : l’Arcep a réservé ces numéros aux échanges entre personnes dans sa décision n° 2022-1583. Votre plateforme vous attribue donc un nom d’émetteur ou un numéro court.

Authentifier l’appel : cinq mécanismes, des risques très différents

Toutes les API SMS vous demandent de prouver qui vous êtes, aucune ne s’y prend tout à fait comme sa voisine. Dans les documentations publiques du marché, on croise cinq mécanismes.

MécanismeOù voyage le secretCe qu’il faut savoir
Clé en paramètre d’URLDans l’adresse appeléeElle finit dans les journaux des serveurs et des proxys. À fuir
Clé dans le corps ou un en-tête dédiéDans la requête, hors URLSimple et correct, à condition de rester en HTTPS
BasicIdentifiant et secret encodés en Base64 dans AuthorizationEncodé ne veut pas dire chiffré : la RFC 7617 ne juge ce schéma sûr qu’au-dessus de TLS
BearerUn jeton dans AuthorizationTrès courant. La RFC 6750 déconseille de le passer dans une URL
Signature de requêteNulle part, le secret sert à calculer une empreinte HMACLe plus robuste, et le plus long à mettre en place

L’OWASP le dit sans détour dans sa fiche sur la sécurité des API REST : mots de passe, jetons et clés d’API ne doivent pas apparaître dans l’URL, parce que les journaux des serveurs web la capturent.

Le mécanisme compte moins que ce que vous faites de la clé ensuite. GitGuardian a compté 28,65 millions de nouveaux secrets écrits en dur dans des dépôts publics GitHub sur la seule année 2025, soit 34 % de plus qu’un an avant, d’après son rapport State of Secrets Sprawl 2026. Or une clé d’API SMS se monnaie tout de suite : celui qui la trouve envoie des messages à vos frais, sous votre nom d’émetteur.

Quatre habitudes limitent la casse.

  • Une clé par environnement et par application. Le jour où l’une fuit, vous n’en révoquez qu’une.
  • Un filtrage par adresse IP. La clé volée devient inutilisable hors de vos serveurs.
  • Une rotation planifiée. L’OWASP recommande de renouveler régulièrement les secrets, pour qu’un identifiant dérobé ne serve que peu de temps.
  • Un plafond de dépense. Le Top 10 OWASP de la sécurité des API conseille de fixer des limites de dépense chez chaque fournisseur d’API.

Encore faut-il que la plateforme s’y prête. Avant de vous engager, regardez si elle fournit une API SMS avec des clés restreintes par IP et un environnement de test. Roder son intégration sur de vrais destinataires, ça finit toujours mal.

La réponse immédiate ne dit pas que le SMS est arrivé

C’est le malentendu qui coûte le plus cher, et les documentations l’expliquent rarement. Un envoi par API produit deux retours, séparés de quelques secondes ou de plusieurs heures.

Le premier est synchrone. La plateforme répond à votre requête pour dire qu’elle l’a comprise et prise en charge. Elle vous rend un identifiant de message et un statut du type « accepté » ou « en file d’attente ». Rien de plus. À cet instant, aucun opérateur n’a encore vu passer votre SMS.

Le second arrive plus tard, de façon asynchrone. Une fois le message remis au téléphone, ou définitivement abandonné, l’opérateur renvoie un accusé de réception que la plateforme vous transmet. Nous avons détaillé ailleurs la différence entre accepté, délivré et lu, inutile d’y revenir longuement.

Côté code, la conséquence tient en une ligne : à chaque appel, enregistrez de quoi faire le lien plus tard.

{
  "id": "msg_7f3a9c2e",
  "status": "accepted",
  "reference": "cmd-4821-expedition",
  "segments": 1
}

Identifiant renvoyé, référence, heure, code HTTP : sans ces quatre valeurs, un accusé qui tombe deux heures après ne se rattache à rien.

Que faire de chaque code de retour

Des tableaux de codes HTTP, toutes les documentations en ont un. Ce qui manque, c’est la colonne d’à côté : faut-il rejouer l’appel, oui ou non ?

RetourCe qu’il signifieRejouer ?Quoi faire
200, 201, 202Requête prise en chargeNonStocker l’identifiant, attendre l’accusé
400, 422Requête invalide : JSON, numéro, émetteurNonCorriger la donnée, tracer le rejet
401, 403Clé absente ou révoquée, IP non autoriséeNonAlerter l’équipe, l’erreur ne passera pas toute seule
Code métier, parfois 402Crédit épuiséNonRecharger, puis reprendre la file
429Limite de débit dépasséeOui, plus tardRespecter Retry-After, ralentir
500, 502, 503Incident côté plateformeOuiRetrait exponentiel, nombre d’essais borné
Aucune réponseDélai dépassé, sort inconnuAvec précautionVoir plus bas

La règle derrière ce tableau vient de la norme elle-même. La RFC 9110 définit la famille 4xx comme le cas où le client « semble avoir commis une erreur ». Renvoyer dix fois une requête fausse vous vaudra dix refus. Une 5xx, à l’inverse, signale un problème du serveur, souvent passager.

Le 429 est un cas à part. La RFC 6585 le décrit comme le signe d’un trop grand nombre de requêtes sur une période donnée, et prévoit que la réponse puisse porter un en-tête Retry-After indiquant combien de temps patienter. Lisez-le. Quand il manque, espacez vos essais en doublant le délai à chaque tentative, avec une part d’aléatoire. Marc Brooker, ingénieur chez AWS, a montré pourquoi : sans cet aléa, tous les clients rejetés reviennent à la charge au même instant et recréent l’embouteillage.

Méfiez-vous aussi des erreurs qui se cachent. Certaines API répondent 200 à tout et rangent le vrai résultat dans le corps, sous la forme d’un code métier : crédit insuffisant, émetteur non validé, message en attente de modération. Un programme qui se contente de tester le statut HTTP passera à côté.

Le délai dépassé, la panne qui fabrique des doublons

Votre appel part, rien ne revient au bout de dix secondes. Le SMS est-il parti ? Vous n’en savez rien. La requête a pu se perdre à l’aller. Ou bien c’est la réponse qui s’est égarée au retour, et le message est déjà en route.

Rejouer à l’aveugle revient à tirer à pile ou face. La RFC 9110 range PUT et DELETE parmi les méthodes idempotentes, pas POST : deux POST identiques créent deux envois. Trois parades existent.

La première, quand la plateforme la propose, c’est la clé d’idempotence, un identifiant unique joint à la requête et que le serveur reconnaît s’il la revoit. Ne la tenez pas pour acquise. Le projet de norme de l’IETF sur l’en-tête Idempotency-Key a expiré sans devenir une RFC, si bien que chaque fournisseur fait à sa façon, ou ne fait rien.

La deuxième consiste à interroger l’API avec votre propre référence avant de rejouer, pour savoir si l’envoi existe déjà. La troisième est de ne pas rejouer du tout. Pour un code de connexion, c’est souvent le meilleur choix : l’utilisateur qui n’a rien reçu en redemandera un, et il n’aura pas deux codes contradictoires sous les yeux.

Les accusés de réception, l’autre moitié des retours

L’accusé arrive par webhook, sur une adresse HTTPS que vous exposez. Le vocabulaire n’a rien de normalisé d’un fournisseur à l’autre : selon les documentations, la liste va d’une dizaine de statuts à plus d’une trentaine. Ils se ramènent à quatre familles.

Famille de statutCe qui s’est passéCe que vous en faites
DélivréLe téléphone a reçu le messageClore l’envoi
En coursRemis à l’opérateur, pas encore au téléphoneAttendre, ne rien rejouer
ExpiréTéléphone éteint ou hors réseau pendant toute la durée de validitéRetenter plus tard si le message a encore un sens
Rejeté ou non délivréNuméro inexistant, résilié, ou message bloquéNe pas rejouer, sortir le numéro de la base après vérification

La dernière ligne mérite qu’on s’y arrête. Un numéro invalide relancé à chaque campagne vous coûte un SMS à chaque fois et fausse vos statistiques.

Le récepteur du webhook obéit à quelques règles. Répondre 200 tout de suite et traiter l’événement ensuite, hors de la requête, sinon certaines plateformes concluent à un échec et renvoient l’événement. Accepter qu’un même accusé arrive deux fois, donc dédoublonner sur l’identifiant de message. Vérifier la signature quand il y en a une : la plateforme calcule une empreinte HMAC du contenu avec un secret partagé, vous refaites le calcul et vous comparez. Faute de quoi n’importe qui peut poster de faux « délivré » sur votre adresse.

Reste la question des journaux, qu’on règle trop souvent après coup. La CNIL recommande de conserver les traces sur une période glissante comprise entre six mois et un an, et de ne pas y enregistrer de mot de passe. La même prudence vaut pour une clé d’API et pour le contenu d’un code à usage unique : journalisez l’identifiant, le statut et l’heure, pas le secret. Les autres règles propres aux SMS déclenchés automatiquement figurent dans notre guide du transactionnel.

Sept vérifications avant de passer en production

  1. La clé vit dans une variable d’environnement ou un coffre à secrets, pas dans le code.
  2. Chaque environnement a sa clé, et le filtrage IP est actif en production.
  3. Chaque appel porte un délai maximal.
  4. Les 4xx ne sont jamais rejouées. Les 429 et les 5xx le sont, avec un retrait et un nombre d’essais plafonné.
  5. Le cas « aucune réponse » a un comportement écrit noir sur blanc, pas un comportement par défaut.
  6. Le webhook vérifie la signature et dédoublonne.
  7. Les numéros rejetés sortent de la base, et les journaux ne contiennent aucun secret.

Rien de difficile là-dedans. C’est simplement le travail que le tutoriel de dix lignes ne montre pas.

Questions fréquentes sur l’appel d’une API SMS

Comment s’authentifier auprès d’une API SMS ?

Le plus souvent avec une clé ou un jeton placé dans un en-tête HTTP, en Bearer ou en Basic selon les fournisseurs. Dans tous les cas l’échange passe en HTTPS, et le secret ne figure jamais dans l’URL.

Où stocker une clé d’API SMS ?

Dans une variable d’environnement ou un coffre à secrets, côté serveur uniquement. Jamais dans le code source, dans un dépôt Git ou dans une application mobile.

Un code 200 garantit-il que le SMS est arrivé ?

Non. Il indique seulement que la plateforme a accepté la requête. La remise au téléphone est confirmée plus tard par l’accusé de réception de l’opérateur, transmis par webhook.

Que faire quand une API SMS renvoie une erreur 429 ?

Ralentir. Le code 429 signale un dépassement de la limite de débit. Lisez l’en-tête Retry-After s’il est présent, sinon espacez les nouvelles tentatives en doublant le délai à chaque essai, avec une part d’aléatoire.

Faut-il renvoyer un SMS après un délai dépassé ?

Pas à l’aveugle, vous risquez le doublon. Utilisez une clé d’idempotence si la plateforme en propose une, ou vérifiez d’abord avec votre propre référence que l’envoi n’existe pas déjà. Pour un code de connexion, mieux vaut laisser l’utilisateur en redemander un.