Aller au contenu

Cycle de vie d'un message

Chaque SMS soumis à Lisoloo suit la même machine d’états. Vous pouvez l’observer via GET /status/{message_id} (polling) ou via les webhooks (push). Les valeurs de statut sont stables d’une version à l’autre — basez votre code dessus sans craindre des renommages.

Les valeurs ci-dessous viennent directement de l’enum backend ELisolooSmsStatus. Traitez tout ce qui est dans la colonne Terminal comme un état final pour ce message (ou par destinataire, pour la décomposition fine).

StatutTerminal ?Signification
pendingNonLa passerelle a accepté la requête et l’a mise en file. Pas encore de handoff vers l’opérateur.
scheduledNonLe message est en file pour une occurrence future scheduled_dates / recurring_schedule.
processingNonLe connecteur opérateur a récupéré le job et l’expédie vers le SMSC.
acceptedNonLe SMSC a accepté le message ; traitement côté opérateur en cours.
enrouteNonLe réseau opérateur livre vers le combiné.
sentNonL’opérateur a confirmé l’expédition. En attente d’accusé du combiné.
deliveredOuiLe combiné a confirmé la réception.
partially_deliveredOuiMessage multi-segments — certains segments livrés, d’autres non.
delivery_unknownOuiL’opérateur n’a pas renvoyé d’accusé définitif dans la fenêtre.
undeliveredOuiL’opérateur a rapporté le message comme non-livré (combiné inaccessible, bloqué, etc.).
rejectedOuiL’opérateur a rejeté le message avant expédition (typiquement : sender ID ou contenu invalide).
expiredOuiLa fenêtre de validité du message est passée sans livraison.
failedOuiÉchec de traitement dans la passerelle ou le connecteur.
unknownStatut indéterminable.
noneSentinelle interne ; ne devrait pas apparaître sur un vrai message.

delivered est le seul état terminal de plein succès. Tout le reste de la colonne Oui est un état terminal non-réussi avec différentes causes au niveau opérateur.

┌──────────┐
soumission ──▶ │ pending │
└─────┬────┘
│ l'opérateur récupère
┌────────────┐
│ processing │
└─────┬──────┘
│ SMSC accepte
┌──────────┐
│ sent │
└─────┬────┘
│ ACK combiné │ timeout / NACK
▼ ▼
┌────────────┐ ┌──────────┐
│ delivered │ │ failed │
└────────────┘ └──────────┘
terminal terminal

Un message peut transitionner directement vers failed depuis n’importe quel état antérieur si quelque chose tourne mal — par exemple un MSISDN mal formé que l’opérateur rejette avant le handoff SMSC saute pending → failed sans passer par processing.

Un seul POST /send avec N destinataires produit un message_id qui couvre tout le lot. Le statut retourné reflète l’agrégat :

  • pending tant qu’un destinataire est pending et aucun terminal.
  • processing tant que certains sont en vol.
  • sent quand tous les destinataires ont été handed off.
  • delivered quand chaque destinataire est delivered.
  • failed quand chaque destinataire est failed.
  • États terminaux mixtes (certains delivered, d’autres failed) rapportent delivered si au moins un a réussi, failed si aucun.

Pour le détail par destinataire, la réponse de GET /status/{message_id} inclut un tableau recipients[] avec l’état final individuel pour chaque numéro. (Voir la référence API pour le schéma.)

Chaque transition d’état émet un événement webhook vers votre webhook_url configuré (si défini) et vers tout callback_url par-requête. Voir Types d’événements webhook pour les charges utiles.

Les événements sont :

  • sms.queued — déclenché sur pending (juste après le retour de POST /send).
  • sms.processing — déclenché sur pending → processing.
  • sms.sent — déclenché sur processing → sent.
  • sms.delivered — déclenché sur sent → delivered.
  • sms.failed — déclenché sur toute transition vers failed.

sms.delivered et sms.failed sont terminaux — plus d’événements pour ce message_id après leur déclenchement.

La passerelle conserve un message en vol jusqu’à 24 heures en attendant un accusé final de l’opérateur. Si aucun n’arrive avant, le statut est positionné à failed avec error_code: 1503 SMS_TIMEOUT et aucune autre tentative n’est faite.

Les ré-essais au niveau opérateur (typiquement 3 tentatives sur 4 heures pour les échecs transitoires) se passent de façon transparente avant que la passerelle n’abandonne. Vous ne verrez pas ces tentatives comme des événements webhook séparés.