Référence API SMS-C
← Retour à l'Index de Documentation
Référence pour l'API REST SMS-C, générée à partir de la table de routage en direct
(config/config.exs) et des implémentations de contrôleur. Chaque point de terminaison ci-dessous
est réellement routé par le service en cours d'exécution.
L'application elle-même sert une spécification OpenAPI lisible par machine et une interface Swagger UI interactive. Ceux-ci sont toujours synchronisés avec la version déployée :
GET /api/schema # Spécification OpenAPI JSON
GET /api/docs # Swagger UI
Table des Matières
- Aperçu
- Authentification
- Conventions de Réponse
- Statut
- Messages
- Indication de Message en Attente
- Emplacements
- Frontends
- Événements
- Campagnes
- Autres Familles de Points de Terminaison
- Codes de Statut HTTP
- Format d'Erreur
- Meilleures Pratiques
Aperçu
URL de Base
https://<host>:8443/api
Port par Défaut : 8443 (configurable via config :api_ex, api: %{port: ...})
Protocole : HTTPS lorsque enable_tls est activé (par défaut). Tous les itinéraires sont
montés sous le préfixe /api.
Type de Contenu
Les corps de requête et de réponse sont en JSON :
Content-Type: application/json
Il n'y a pas de versionnement d'API basé sur l'URL. La table de routage est le contrat ; consultez
/api/schema pour la forme exacte déployée.
Authentification
L'API n'a aucune authentification au niveau de l'application. Le pipeline de requête ne négocie que le type de contenu et attache la spécification OpenAPI ; il n'y a pas de clé API, de jeton d'authentification ou de vérification de session devant les itinéraires.
Le contrôle d'accès est donc censé être géré en dehors de l'application :
- TLS : lorsque
enable_tlsest vrai, l'auditeur termine HTTPS en utilisant letls_cert_path/tls_key_pathconfiguré. Utilisez-le en production. - Contrôles réseau : restreindre le port API aux sources de confiance avec un
pare-feu ou un proxy inverse en amont. Plusieurs points de terminaison enregistrent l'IP de l'appelant
(à partir de
X-Forwarded-Forou du socket) pour l'audit, mais ne bloquent pas sur cela.
Ne pas exposer le port API directement à des réseaux non fiables.
Conventions de Réponse
Les contrôleurs renvoient la ressource directement, sans enveloppe data.
Ressource unique :
{ "id": 12345, "status": "queued" }
Les collections sont renvoyées sous forme de tableau JSON brut :
[ { "id": 12345 }, { "id": 12346 } ]
Les erreurs au niveau du contrôleur utilisent une chaîne error plate :
{ "error": "payload_hex is required. For plaintext, use POST /api/messages_plaintext" }
Les erreurs au niveau du framework (échecs de routage, corps non analysables) reviennent sous forme de :
{ "status": "error", "response": "Not Found" }
Statut
Vérification de la santé pour la surveillance et les équilibreurs de charge.
Requête :
GET /api/status
Réponse (200 OK) :
{
"status": "ok",
"application": "OmniMessage",
"timestamp": "2025-11-01T23:00:00Z"
}
Exemple :
curl https://host:8443/api/status
Messages
La file d'attente de messages est la ressource principale. Le contenu du message est transporté sous
payload_hex (les octets TP-User-Data) plus un octet dcs (schéma de codage de données) et un
udh_hex optionnel (en-tête de données utilisateur). Les appelants en texte clair
devraient utiliser Soumettre du Texte Clair, qui effectue l'encodage,
la sélection DCS et le fractionnement multipart pour vous.
Objet Message
Champs renvoyés pour un message (voir ApiEx.Schemas.MessageSchema) :
| Champ | Type | Remarques |
|---|---|---|
id | entier | ID du message |
source_msisdn | chaîne | Numéro source |
destination_msisdn | chaîne | Numéro de destination |
payload_hex | chaîne | Octets TP-User-Data en hex (contenu canonique) |
dcs | chaîne | Schéma de codage de données sous forme d'octet hex (00=GSM7, 08=UCS2, 04=8bit, C8=MWI) |
udh_hex | chaîne / null | Octets d'en-tête de données utilisateur en hex |
message_text | chaîne / null | Texte UTF-8 dérivé pour affichage uniquement (non utilisé pour la livraison) |
source_smsc | chaîne | Identifiant SMSC source |
dest_smsc | chaîne / null | Identifiant SMSC de destination |
status | chaîne | Un des queued, backoff, sent, delivered, expired, dropped, auto_replied, balance_rejected, deleted |
send_time | datetime | |
deliver_time | datetime / null | |
expires | datetime | |
delivery_attempts | entier | |
deadletter | booléen | |
message_parts | entier / null | |
message_part_number | entier / null | |
smsc_node_name | chaîne | Noeud qui possède le message |
Lister les Messages
Requête :
GET /api/messages
En-têtes Optionnels :
smsc: <frontend_name>- mode de sondage : renvoie les messages destinés à ce SMSC.include-unrouted: true|1- en mode de sondage, renvoie également les messages sans enregistrement de localisation (par défaut : faux).x-decode: true|1- inclut une vue décodée de chaque charge utile de message.
Paramètres de Requête (mode liste, utilisés uniquement lorsqu'aucun en-tête smsc n'est présent) :
status- filtre par un seul atome de statut (voir la liste des statuts ci-dessus).limit- max enregistrements (par défaut 100, max 1000).offset- enregistrements à ignorer (par défaut 0).
Le point de terminaison est toujours paginé en mode liste : sans limit, il renvoie
au maximum 100 enregistrements, jamais l'ensemble du magasin.
Réponse (200 OK) - un tableau JSON d'objets message.
Exemples :
# Sondage pour les messages d'un frontend
curl -H "smsc: uk_gateway" https://host:8443/api/messages
# Sondage incluant des messages non routés
curl -H "smsc: uk_gateway" -H "include-unrouted: true" https://host:8443/api/messages
# Lister les messages livrés
curl "https://host:8443/api/messages?status=delivered&limit=50"
Obtenir un Message
Requête :
GET /api/messages/:id
L'en-tête optionnel x-decode: true ajoute une vue de charge utile décodée.
Réponse (200 OK) : un seul objet message. 404 avec
{"error": "Message not found"} si l'id est inconnu.
curl https://host:8443/api/messages/12345
Soumettre un Message
Soumettez un message pré-encodé. payload_hex est requis ; les requêtes sans cela
sont rejetées avec 422.
Requête :
POST /api/messages
Content-Type: application/json
Corps :
{
"source_msisdn": "15555551234",
"destination_msisdn": "15555555678",
"payload_hex": "c8329bfd06dddf723619",
"dcs": "00",
"source_smsc": "api_client"
}
Champs :
source_msisdn,destination_msisdn- numéros.payload_hex- requis. Octets TP-User-Data en hex.dcs- octet hex du schéma de codage de données (défauts appliqués en aval).udh_hex- en-tête de données utilisateur hex optionnel.source_smsc- identifie le système soumetteur.source_type- classification de source optionnelle.
Réponse (201 Created) : l'objet message créé. Les rejets retournent 422
avec une chaîne error (par exemple, payload_hex manquant).
curl -X POST https://host:8443/api/messages \
-H "Content-Type: application/json" \
-d '{
"source_msisdn": "15555551234",
"destination_msisdn": "15555555678",
"payload_hex": "c8329bfd06dddf723619",
"dcs": "00",
"source_smsc": "api_client"
}'
Soumettre du Texte Clair
Soumettez une chaîne UTF-8 et laissez le SMS-C gérer l'encodage (GSM7 vs UCS2), la sélection DCS, et le fractionnement multipart.
Requête :
POST /api/messages_plaintext
Content-Type: application/json
Corps :
{
"source_msisdn": "15555551234",
"destination_msisdn": "15555555678",
"message": "Hello World",
"source_smsc": "api_client"
}
Le texte du message peut être donné comme message, text, ou body. source_msisdn
et destination_msisdn sont requis.
Réponse (201 Created) :
- Partie unique : l'objet message créé.
- Multipart :
{ "parts": <n>, "messages": [ ... ] }.
curl -X POST https://host:8443/api/messages_plaintext \
-H "Content-Type: application/json" \
-d '{
"source_msisdn": "15555551234",
"destination_msisdn": "15555555678",
"message": "Hello World",
"source_smsc": "api_client"
}'
Soumettre un PDU Brut
Soumettez un PDU SMS brut (hex) pour une compatibilité maximale avec les frontends hérités et SIP.
Requête :
POST /api/messages_raw
Content-Type: application/json
Corps :
{
"message_body": "0001000B916407007009F0000004D4F29C0E",
"source_smsc": "legacy_system"
}
Champs :
message_body- requis. PDU SMS encodé en hex (ou TPDU, voir ci-dessous).source_msisdn- optionnel.source_smsc/smsc_node_name- requis en mode uniquement TPDU.rp_originator_address,rp_destination_address- fournissez-les pour soumettre un TPDU brut (la couche RP est synthétisée).
L'IP de l'appelant est prise à partir de X-Forwarded-For (ou du socket) pour résoudre le
frontend d'origine.
Réponses :
- 201 Created avec
{ "status": "success", "response": { "id": <id> } }(un champ hexrp_ackest inclus lorsqu'il est généré). - 200 OK avec
{ "status": "success", "response": { "status": "delivery_report_received" } }lorsque le PDU est un rapport de livraison plutôt qu'un nouveau message. - 422 avec une chaîne
errorpour hex manquant/invalid ou échecs de décodage.
curl -X POST https://host:8443/api/messages_raw \
-H "Content-Type: application/json" \
-d '{
"message_body": "0001000B916407007009F0000004D4F29C0E",
"source_smsc": "legacy_system"
}'
Le service décode le PDU (3GPP TS 23.040), extrait les numéros/texte/DCS, détecte les rapports de livraison et applique le routage. Les rapports de livraison sont enregistrés mais ne sont pas stockés comme de nouveaux messages.
Mettre à Jour un Message (PATCH)
Mise à jour partielle d'un message stocké.
Requête :
PATCH /api/messages/:id
Content-Type: application/json
Envoyez tous les champs de message modifiables (par exemple dest_smsc, deliver_after,
status). Les modifications de métadonnées sont enregistrées dans le journal des événements.
Réponse (200 OK) : l'objet message mis à jour. 404 si non trouvé, 422 en cas de mise à jour rejetée.
curl -X PATCH https://host:8443/api/messages/12345 \
-H "Content-Type: application/json" \
-d '{ "dest_smsc": "backup_gateway" }'
Incrémenter la Tentative de Livraison
Enregistrer une livraison échouée : incrémente le compteur de tentatives, déplace le message vers
backoff, et planifie la prochaine tentative avec un retour d'exponentiel.
Deux formes équivalentes existent :
PUT /api/messages/:id # la ressource messages, PUT = incrémenter
POST /api/messages_increment_attempt (id dans le corps)
PUT /api/messages_increment_attempt/:id (id dans l'URL)
PUT /api/messages/:id est distinct de PATCH /api/messages/:id : PATCH effectue une
mise à jour partielle, PUT incrémente la tentative de livraison. Passez keep_route=true pour
conserver le dest_smsc actuel lors de la nouvelle tentative.
Réponse (200 OK) : le message mis à jour, par exemple :
{ "id": 12345, "status": "backoff", "delivery_attempts": 2 }
curl -X PUT https://host:8443/api/messages/12345
Marquer Comme Livré
Marquer un message comme livré (stock local ou fédéré).
POST /api/messages_mark_delivered (id dans le corps)
PUT /api/messages_mark_delivered/:id (id dans l'URL)
L'en-tête optionnel smsc sélectionne le SMSC fédéré lorsque le message n'est pas conservé
localement.
Réponse (200 OK) : l'objet message livré. 404 si non trouvé.
curl -X POST https://host:8443/api/messages_mark_delivered \
-H "Content-Type: application/json" \
-d '{ "id": 12345 }'
Réacheminer un Message
Réévaluer les règles de routage pour un message stocké et mettre à jour son dest_smsc.
Requête :
POST /api/messages/reroute
Content-Type: application/json
Corps : { "id": 12345 }
Réponse (200 OK) :
{ "message_id": 12345, "new_dest_smsc": "uk_gateway", "status": "rerouted" }
404 si le message n'est pas trouvé, 422 si aucune route ne correspond.
Effacer un Champ
Réinitialiser un champ de message spécifique à null.
Requête :
POST /api/messages/clear_field
Content-Type: application/json
Corps : { "id": 12345, "field": "dest_smsc" }
field doit être l'un de delivery_time, dest_smsc, ou deliver_after; toute
autre valeur renvoie 400. Le changement est enregistré dans le journal des événements.
Réponse (200 OK) : l'objet message mis à jour.
Supprimer un Message
Requête :
DELETE /api/messages/:id
Réponse (204 No Content). 404 si non trouvé. La suppression est permanente.
curl -X DELETE https://host:8443/api/messages/12345
Indication de Message en Attente
Soumettez une notification MWI (Indication de Message en Attente). Le contrôleur construit
le PDU MWI selon 3GPP TS 23.038 et stocke un message prêt à être livré avec un
payload_hex et un dcs pré-calculés.
Requête :
POST /api/mwi
Content-Type: application/json
Corps :
{
"source_msisdn": "12345",
"destination_msisdn": "15555555678",
"indication_type": "voicemail",
"indication_active": true,
"message_body": "Vous avez 1 nouveau message vocal",
"source_smsc": "IMS_SMSC"
}
Champs :
indication_type-voicemail(par défaut),fax,email, ouautre.indication_active-truepour définir l'indicateur,falsepour le supprimer (par défauttrue).message_body- texte d'accompagnement optionnel (encodé en GSM7).source_msisdn,destination_msisdn,source_smsc,dest_smsc.
Réponse (201 Created) : l'objet message créé. 422 en cas d'échec.
Emplacements
Enregistrements de localisation des abonnés pour la livraison mobile-terminée. Ressource REST standard ;
le segment de chemin :id est l'IMSI.
GET /api/locations # lister (paginé : ?limit=&offset=, en-tête x-total-count)
GET /api/locations/:id # obtenir par IMSI
POST /api/locations # créer ou mettre à jour (identifié par IMSI)
PATCH /api/locations/:id # mise à jour partielle
PUT /api/locations/:id # mise à jour
DELETE /api/locations/:id # supprimer
Corps de Création/Mise à Jour :
{
"msisdn": "15555551234",
"imsi": "001001000000001",
"location": "msc1.region1.example.com",
"ran_location": "cell_tower_12345",
"imei": "123456789012345",
"ims_capable": true,
"csfb": false,
"registered": true,
"expires": "2025-11-01T23:30:00Z",
"user_agent": "Samsung Galaxy"
}
imsi et msisdn sont requis ; les champs restants sont optionnels. Les réponses
sont l'objet de localisation (200/201) ; les échecs de validation retournent 422. Appelés par
les systèmes de gestion de mobilité lorsqu'un abonné s'enregistre ou se désenregistre.
Frontends
Suivez les connexions SMSC des frontends. Cette ressource expose index, show, et
create uniquement (il n'y a pas de sous-routes active, stats, history, ou register).
GET /api/frontends # lister toutes les inscriptions
GET /api/frontends/:id # obtenir une inscription
POST /api/frontends # enregistrer ou actualiser un frontend
Corps d'Inscription (POST /api/frontends) :
{
"frontend_name": "smpp-gateway-1",
"frontend_type": "SMPP",
"ip_address": "10.0.1.5",
"hostname": "smpp-gw-01",
"uptime_seconds": 3600,
"configuration": "{\"port\": 2775, \"system_id\": \"smpp_user\"}"
}
frontend_name est requis. Si ip_address est omis, il est rempli à partir de l'IP source de la
requête (X-Forwarded-For ou socket). Si une inscription active existe déjà pour le frontend_name,
elle est mise à jour ; sinon, une nouvelle est créée. Les inscriptions expirent après environ 90 secondes, donc les frontends doivent
se réinscrire périodiquement.
Réponse (201 Created) : l'objet d'inscription.
Événements
Événements de cycle de vie par message. Les événements sont conservés dans ETS avec un TTL roulant.
Obtenir les Événements de Message
Requête :
GET /api/events/:id
:id est l'ID numérique du message.
Réponse (200 OK) :
{
"message_id": 12345,
"events": [
{ "event_epoch": 1698672000, "name": "message_inserted", "description": "..." },
{ "event_epoch": 1698672005, "name": "message_delivered", "description": "..." }
]
}
400 si l'id n'est pas un entier.
Enregistrer un Événement
Requête :
POST /api/events
Content-Type: application/json
Corps :
{
"message_id": 12345,
"name": "external_delivery_confirmed",
"description": "Confirmé par le système en aval"
}
message_id, name, et description sont tous requis. La source de l'événement est
détectée automatiquement à partir de l'IP de l'appelant (correspondant aux inscriptions de frontend
actives), revenant au nom de nœud configuré.
Réponse (201 Created) :
{
"status": "success",
"message": "Événement enregistré avec succès",
"event": {
"message_id": 12345,
"name": "external_delivery_confirmed",
"description": "Confirmé par le système en aval",
"event_source": "smpp-gateway-1",
"event_epoch": 1698672010
}
}
Campagnes
Messagerie en masse : téléchargez une liste de destinataires nommée, puis exécutez une campagne à débit limité contre celle-ci. Consultez le guide de Messagerie en Masse / Campagnes pour les concepts (filtre d'audience, taux de goutte, cycle de vie, statistiques).
Listes de Destinataires
GET /api/campaign_lists # toutes les listes
GET /api/campaign_lists/:id # une liste, inclut "recipients"
POST /api/campaign_lists # créer une liste
PATCH /api/campaign_lists/:id # ajouter des destinataires
DELETE /api/campaign_lists/:id # supprimer la liste et ses destinataires
Chaque destinataire peut porter jusqu'à quatre variables de modèle (var1..var4). Fournissez
les destinataires sous forme de tableau JSON, de chaîne CSV brute, ou les deux. Les destinataires JSON peuvent être
des chaînes MSISDN simples ou des objets avec var1..var4 :
{
"name": "Clients VIP",
"description": "Abonnés de grande valeur",
"recipients": [
{ "msisdn": "12025550101", "var1": "Alice", "var2": "Gold" },
"12025550102"
]
}
Pour CSV, une ligne d'en-tête nommant une colonne msisdn / destination_msisdn / number /
phone sélectionne la colonne MSISDN (sinon, la première colonne est utilisée) ;
les colonnes restantes deviennent var1..var4 dans l'ordre des colonnes :
{ "name": "Importé", "csv": "msisdn,first,plan\n12025550101,Alice,Gold\n" }
PATCH ajoute des destinataires (il ne les remplace pas).
Réponse (201 Created) : { "id": 1, "name": "Clients VIP", "recipient_count": 2 }
Campagnes
GET /api/campaigns # toutes les campagnes (paginé, les plus récentes en premier)
GET /api/campaigns/:id # une campagne, y compris les statistiques en direct
POST /api/campaigns # créer une campagne (commence en brouillon)
DELETE /api/campaigns/:id # arrêter une campagne mais conserver son enregistrement
Corps de Création :
{
"name": "Avis de maintenance",
"message": "Maintenance prévue ce soir de 02:00 à 03:00.",
"source_msisdn": "12345",
"source_smsc": "IMS_SMSC",
"list_id": 1,
"audience": "active_only",
"drip_tps": 50
}
Champs :
name,message,source_msisdn,source_smsc- requis.messageprend en charge des variables de modèle par destinataire ({{ var1 }}..{{ var4 }},{{ msisdn }}).list_id- liste de destinataires. Omettez pour cibler tous les abonnés actuellement actifs (enregistrés).audience-active_only(par défaut) ouall. Ignoré lorsquelist_idest omis.drip_tps- messages soumis dans la file d'attente par seconde (par défaut à partir de la configuration).validity_hours- validité du message en heures ; définit l'expiresde chaque message.deliver_after- heure ISO 8601 optionnelle pour maintenir les messages jusqu'à (envoi programmé).
DELETE arrête la livraison mais conserve l'enregistrement afin que l'historique et les statistiques restent
visibles ; il retourne la campagne annulée (200) et est purgé automatiquement
une fois passé le TTL de conservation.
Réponse (GET /api/campaigns/:id) :
{
"id": 7,
"name": "Avis de maintenance",
"list_id": 1,
"audience": "active_only",
"status": "running",
"drip_tps": 50,
"total_targets": 1000,
"stats": {
"total": 1000, "pending": 600, "queued": 300,
"delivered": 90, "failed": 10, "skipped_inactive": 0,
"dispatched": 400, "progress_percent": 40, "delivery_percent": 22
}
}
Contrôler une Campagne
Requête :
POST /api/campaigns/control
Content-Type: application/json
Corps : { "campaign_id": 7, "action": "start" }
action est l'un de start, pause, resume, cancel. Retourne la campagne mise à jour (200), 404 si non trouvée, ou 422 si l'action est invalide pour l'état actuel.
Résultats par Destinataire
GET /api/campaign_targets/:id # :id est l'ID de la campagne
GET /api/campaign_targets/:id?state=failed # filtre par état de cible
Prend en charge la pagination limit/offset ; le nombre total (après tout filtre state) est
dans l'en-tête de réponse x-total-count. Chaque entrée porte l'state du destinataire
(pending / queued / delivered / failed / skipped_inactive).
Autres Familles de Points de Terminaison
Les familles de routes suivantes font partie de la même API mais sont documentées en profondeur dans leurs guides dédiés. Les chemins sont listés ici pour complétude.
Routage
GET /api/routes # lister les routes
GET /api/routes/:id # obtenir une route
POST /api/routes # créer une route
PATCH /api/routes/:id # mettre à jour
PUT /api/routes/:id # mettre à jour
DELETE /api/routes/:id # supprimer
GET /api/routes/export # exporter toutes les routes
POST /api/routes/import # importation en masse
POST /api/routes/simulate # simulation d'une décision de route
Voir le guide de Routage SMS.
Traductions de Numéros
GET /api/translations # lister
GET /api/translations/:id # obtenir
POST /api/translations # créer
PATCH /api/translations/:id # mettre à jour
DELETE /api/translations/:id # supprimer
GET /api/translations/export # exporter
POST /api/translations/import # importation en masse
POST /api/translations/simulate # simulation d'une traduction
Voir le guide de Traduction de Numéros.
Opérations
GET /api/operations # index des opérations
POST /api/operations/clear_messages # purger le magasin de messages
POST /api/operations/clear_routes # purger les routes
POST /api/operations/clear_translations # purger les traductions
POST /api/operations/clear_frontends # purger les inscriptions de frontend
Ce sont des actions de maintenance destructrices ; protégez le port API en conséquence.
Fédération
GET /api/federation/status # statut de la fédération
GET /api/federation/identity # identité de fédération de ce nœud
POST /api/federation/health # rapport de santé des pairs
POST /api/federation/registry # échange de registre
POST /api/federation/notify # notification de message entrant
POST /api/federation/delivery_status # rappel de statut de livraison
GET /api/federation_messages # vue de message fédéré
Voir le guide de Fédération.
Diameter, Journaux, et DNS
GET /api/diameter # statut de pair/dip Diameter Sh
GET /api/logs # journaux structurés récents
POST /api/naptr # test de résolution NAPTR
La recherche d'abonnés Diameter Sh est décrite dans le guide de recherche d'abonnés HSS.
Codes de Statut HTTP
| Code | Signification | Utilisation Typique |
|---|---|---|
| 200 | OK | Lecture ou mise à jour réussie |
| 201 | Créé | Ressource créée |
| 202 | Accepté | Accepté pour traitement asynchrone |
| 204 | Pas de Contenu | Suppression réussie |
| 400 | Mauvaise Requête | Entrée mal formée (par exemple, id non entier, champ invalide) |
| 404 | Non Trouvé | Ressource inconnue |
| 422 | Entité Non Traitable | Échec de validation |
| 500 | Erreur Interne du Serveur | Erreur serveur inattendue |
Format d'Erreur
Les erreurs au niveau du contrôleur retournent une chaîne error plate :
{ "error": "Message not found" }
Les erreurs au niveau du framework (itinéraires non correspondants, corps non analysables) retournent l'enveloppe normalisée :
{ "status": "error", "response": "Not Found" }
Meilleures Pratiques
Soumission de Message
- Pré-encodé vs texte clair : envoyez
payload_hexà/api/messageslorsque vous avez déjà encodé le TPDU ; sinon, utilisez/api/messages_plaintextet laissez le SMS-C encoder et fractionner. - Toujours définir
source_smscafin que les événements et le routage puissent attribuer le message. - Utilisez des numéros au format E.164 de manière cohérente.
- Gérez 422 en inspectant la chaîne
errorplutôt qu'en réessayant à l'aveugle.
Intégration de Frontend
- Se réinscrire sur
POST /api/frontendsbien avant la fenêtre d'expiration d'environ 90 secondes. - Sonder avec l'en-tête
smscpour vos messages ; utilisezinclude-unrouteduniquement si vous souhaitez délibérément du trafic non routé. - Marquer comme livré via
/api/messages_mark_deliveredaprès succès. - Incrémenter en cas d'échec via
PUT /api/messages/:id(ou/api/messages_increment_attempt) pour planifier une nouvelle tentative avec retour. - Enregistrer des événements pour les confirmations en aval.
Opérationnel
- Terminez TLS et restreignez le port API au niveau réseau ; il n'y a pas d'authentification intégrée.
- Réutilisez les connexions HTTP et définissez des délais d'attente client raisonnables.
- Surveillez les métriques Prometheus (voir METRICS.md) pour la santé de la file d'attente et de la livraison.