Accusés de réception

Le statut de livraison d'un SMS, état par état.

Un SMS accepté par l'API n'est pas encore un SMS reçu. Entre les deux, l'opérateur (IAM, Orange ou Inwi) renvoie un accusé de réception — le DLR. Voici comment le lire, et quoi en faire dans votre application.

Les six statuts d'un message

Chaque message porte un statut, lisible par GET /v1/messages/{id} et poussé à votre webhook.

  • queued — accepté par EnvoiSMS.ma, en attente de départ.
  • sent — remis au réseau ; l'opérateur ne s'est pas encore prononcé.
  • delivered — l'opérateur confirme la remise sur le téléphone.
  • failed — l'opérateur ou la route a refusé le message ; error_code dit pourquoi.
  • undeliverable — le numéro ne peut pas être joint (numéro inexistant, résilié).
  • unconfirmed — le réseau a accepté le message mais n'a jamais rendu de verdict dans la fenêtre de rapport ; un DLR tardif remplace ce statut.

D'où vient l'accusé de réception

Le DLR (Delivery Report) est émis par l'opérateur du destinataire, pas par nous : nous le relayons tel quel. Un téléphone éteint ou hors réseau retarde la remise, et donc le DLR, parfois de plusieurs heures. « sent » n'est donc pas un échec : c'est une attente.

Lire un échec : error_code

Un message failed ou undeliverable porte un error_code court et stable, sur lequel votre code peut brancher.

  • DLR_<statut réseau> — l'échec vient du rapport de l'opérateur (par exemple DLR_REJECTD, DLR_EXPIRED, DLR_UNDELIV).
  • GATEWAY_* — échec côté routage EnvoiSMS.ma, avant d'atteindre le réseau.
  • META_* — refus WhatsApp, pour les messages envoyés sur ce canal.
  • Un code inconnu se traite comme un échec définitif : de nouvelles valeurs peuvent apparaître.

Recevoir les statuts par webhook

Déclarez une URL et abonnez-la aux événements message.sent, message.delivered et message.failed. Chaque appel est signé : vérifiez l'en-tête X-EnvoiSMS-Signature-256 (HMAC-SHA256 du timestamp et du corps) et rejetez un timestamp de plus de 5 minutes. Les métadonnées passées à l'envoi reviennent dans le webhook, pour relier le statut à votre commande ou à votre utilisateur.

Ce qui est facturé

Un message en échec est remboursé dès que nous avons la preuve que le réseau ne l'a pas facturé ; quand cette preuve manque, il est examiné par notre équipe plutôt que remboursé à l'aveugle. Pour un code OTP que vous générez vous-même, ajoutez metadata.purpose = "otp" : sur un échec définitif vers un numéro marocain, le code encore valide (moins de 10 minutes) est renvoyé une fois par une autre route SMS, sans frais supplémentaires.

Tout savoir sur Accusés de réception.

Pourquoi mon SMS reste-t-il « sent » ?
L'opérateur n'a pas encore rendu son accusé de réception, souvent parce que le téléphone est éteint ou hors couverture. Le statut passera à delivered ou failed à l'arrivée du DLR, ou à unconfirmed si aucun verdict n'arrive dans la fenêtre de rapport.
« delivered » veut-il dire que le message a été lu ?
Non. Pour un SMS, delivered signifie que l'opérateur l'a remis au téléphone. Le SMS n'a pas d'accusé de lecture ; WhatsApp en a un (read).
Un SMS en échec est-il facturé ?
Il est remboursé dès que nous avons la preuve que le réseau ne l'a pas facturé. Sinon, il est examiné par notre équipe avant toute décision.
Faut-il interroger l'API ou utiliser un webhook ?
Le webhook : le statut vous est poussé dès qu'il change, sans boucle d'interrogation. GET /v1/messages/{id} reste utile pour un contrôle ponctuel ou une reprise.