Mapi

Documentation

L'API Mapi

Envoyez des SMS et des codes OTP vers tous les opérateurs de Madagascar avec une seule intégration : envoi unitaire ou groupé, vérification de codes, historique et solde.

Sommaire

Démarrage

Présentation

Pour échanger par SMS avec ses clients à Madagascar, une entreprise doit d'ordinaire signer un contrat avec chaque opérateur : autant d'intégrations différentes à développer, tester et maintenir, et autant de factures à régler.

Mapi se charge de la connexion aux opérateurs malgaches. L'API choisit automatiquement l'opérateur qui correspond au numéro du destinataire et, si l'un d'eux rencontre un problème, bascule vers un autre pour que le SMS parte quand même. URL de base :

URL de base
HTTP
https://messaging.mapi.mg/api
  • Toutes les requêtes passent en HTTPS.
  • Les requêtes POST envoient leurs champs en formulaire (multipart/form-data). Les noms de champs commencent par une majuscule : Recipient, Message
  • Les réponses sont en JSON et contiennent toujours un booléen status.
  • Les exemples utilisent des numéros au format local à 10 chiffres (0340000000).

Démarrage

Démarrage rapide

1. Créer un compte

Les appels à l'API se font avec les identifiants d'un compte client Mapi. Commencez par créer votre compte, puis rechargez-le en unités SMS.

2. Obtenir un jeton

POST /authentication/login
Bash
curl -X POST 'https://messaging.mapi.mg/api/authentication/login' \
  -F 'Username=votre_identifiant' \
  -F 'Password=votre_mot_de_passe'

La réponse contient un jeton valable 15 minutes :

200 OK
JSON
{
  "status": true,
  "token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJtYXBpIn0.bvxPol52…"
}

3. Envoyer un premier SMS

Transmettez le jeton tel quel dans l'en-tête Authorization :

POST /msg/send
Bash
curl -X POST 'https://messaging.mapi.mg/api/msg/send' \
  -H 'Authorization: VOTRE_JETON' \
  -F 'Recipient=0340000000' \
  -F 'Message=Votre commande est prête.' \
  -F 'Channel=sms'
Côté serveur uniquement — appelez l'API depuis votre back-end. Vos identifiants et votre jeton ne doivent jamais se retrouver dans le code d'un site web ou d'une application mobile.

Démarrage

Authentification

POST/authentication/login

Échangez les identifiants de votre compte contre un jeton. Ce jeton a une durée de vie de 15 minutes (900 secondes) et doit être renouvelé régulièrement.

ChampTypeRequisDescription
UsernamechaîneRequisIdentifiant de votre compte Mapi.
PasswordchaîneRequisMot de passe du compte.
curl -X POST 'https://messaging.mapi.mg/api/authentication/login' \
  -F 'Username=votre_identifiant' \
  -F 'Password=votre_mot_de_passe'
{
  "status": true,
  "token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJtYXBpIn0.bvxPol52…"
}

Utiliser le jeton

Chaque endpoint protégé attend le jeton dans l'en-tête Authorization, tel quel et sans préfixe Bearer :

En-tête de chaque requête
HTTP
Authorization: VOTRE_JETON
Renouvellement — un jeton absent, expiré ou révoqué renvoie 401 Unauthorized avec le message Authentication credentials required. Reconnectez-vous alors pour obtenir un nouveau jeton, puis rejouez la requête.

SMS

Envoyer un SMS

POST/msg/send

Jeton requis

Envoie un message à un destinataire. L'opérateur est déduit du numéro.

ChampTypeRequisDescription
RecipientchaîneRequisNuméro du destinataire, par exemple 0340000000.
MessagechaîneRequisTexte du SMS.
ChannelchaîneRequisCanal d'envoi : toujours sms.
curl -X POST 'https://messaging.mapi.mg/api/msg/send' \
  -H 'Authorization: VOTRE_JETON' \
  -F 'Recipient=0340000000' \
  -F 'Message=Votre commande est prête.' \
  -F 'Channel=sms'
{
  "status": true,
  "dryRun": false,
  "result": "Sent message 'Votre commande est prête.' to 0340000000"
}

dryRun vaut false pour un envoi réel. Un numéro mal formé renvoie 409 Conflict.

SMS

Envoi groupé personnalisé

POST/msg/sendBulkSms

Jeton requis

Envoie un message différent à chaque destinataire, à partir d'un fichier Excel ou CSV (.xls, .xlsx ou .csv). Le fichier contient une ligne par destinataire :

ColonneContenuRequis
1NomOptionnel
2PrénomOptionnel
3Numéro de téléphoneRequis
4RemarqueOptionnel
DernièreMessage personnaliséRequis
ABCDE
1RakotoJean0340000000Client VIPBonjour Jean, votre commande n°1042 est prête.
2RasoaHery0320000000Bonjour Hery, votre rendez-vous est confirmé pour demain.
destinataires.xlsx
ChampTypeRequisDescription
FilefichierRequisFichier .xls, .xlsx ou .csv des destinataires.
curl -X POST 'https://messaging.mapi.mg/api/msg/sendBulkSms' \
  -H 'Authorization: VOTRE_JETON' \
  -F 'File=@destinataires.xlsx'
{
  "status": true,
  "dryRun": false,
  "result": "12 messages sent."
}
Solde — chaque message consomme des unités. Si le solde ne suffit plus, l'API renvoie 409 Conflict. Consultez vos unités disponibles avant un envoi important.

SMS

Même message à plusieurs destinataires

POST/msg/sendUniqueSmsToRecipients

Jeton requis

Envoie le même texte à une liste de destinataires regroupés dans un fichier .xls, .xlsx ou .csv. Placez les numéros dans la première colonne du fichier.

ChampTypeRequisDescription
FilefichierRequisFichier des destinataires, un numéro par ligne en colonne A.
MessagechaîneRequisTexte envoyé à tous les destinataires.
curl -X POST 'https://messaging.mapi.mg/api/msg/sendUniqueSmsToRecipients' \
  -H 'Authorization: VOTRE_JETON' \
  -F 'File=@destinataires.xlsx' \
  -F 'Message=Nos bureaux seront fermés lundi.'
{
  "status": true,
  "dryRun": false,
  "result": "12 messages sent."
}

SMS

Historique des SMS

GET/msg

Jeton requis

Liste les messages envoyés depuis votre compte, page par page.

ParamètreTypeDescription
limitentierNombre de messages renvoyés, par exemple 10.
offsetentierPosition du premier message renvoyé (0 pour la première page).
curl 'https://messaging.mapi.mg/api/msg?limit=10&offset=0' \
  -H 'Authorization: VOTRE_JETON'
{
  "status": true,
  "result": [
    {
      "IdMessage": "1",
      "IdCampaign": null,
      "Name": null,
      "Telephone": "+261340000000",
      "Message": "Votre commande est prête.",
      "SendStatus": "SENT",
      "GeneratedAt": "2024-04-04 11:12:26",
      "NumberOfSms": "1"
    },
    {
      "IdMessage": "2",
      "IdCampaign": null,
      "Name": null,
      "Telephone": "+261320000000",
      "Message": "Ceci est un test",
      "SendStatus": "NOT_SENT",
      "GeneratedAt": "2023-12-05 09:06:30",
      "NumberOfSms": "1"
    }
  ],
  "totalCount": 720
}

totalCount donne le nombre total de messages, pour construire la pagination. Chaque élément de result contient :

ChampTypeDescription
IdMessagechaîneIdentifiant du message.
IdCampaignchaîne | nullCampagne à laquelle appartient le message, null sinon.
Namechaîne | nullNom du destinataire, s'il est connu.
TelephonechaîneNuméro du destinataire au format international (+261…).
MessagechaîneTexte envoyé.
SendStatuschaîneSENT (envoyé) ou NOT_SENT (non envoyé).
GeneratedAtchaîneDate d'envoi, au format AAAA-MM-JJ HH:MM:SS.
NumberOfSmschaîneNombre de SMS consommés par le message.
Types — les valeurs numériques des listes (identifiants, compteurs) sont renvoyées sous forme de chaînes : convertissez-les avant de les comparer.

OTP

Demander un OTP

POST/otp/request

Jeton requis

Génère un code à usage unique et l'envoie par SMS au destinataire. Le code est valable 15 minutes.

ChampTypeRequisDescription
RecipientchaîneRequisNuméro qui reçoit le code.
ChannelchaîneRequisCanal d'envoi : toujours sms.
curl -X POST 'https://messaging.mapi.mg/api/otp/request' \
  -H 'Authorization: VOTRE_JETON' \
  -F 'Recipient=0340000000' \
  -F 'Channel=sms'
{
  "status": true,
  "dryRun": false,
  "code": "000000",
  "message": {
    "success": "Le message pour +261340000000 a été soumis avec succès auprès de l'opérateur.",
    "SubmissionId": "xxxxxxxxxxxxxxxxxxxx"
  }
}
Sécurité — la réponse contient le code généré (code). Ne le transmettez jamais à votre front-end : faites saisir le code reçu par SMS à l'utilisateur, puis vérifiez-le côté serveur avec /otp/verify.

OTP

Vérifier un OTP

POST/otp/verify

Jeton requis

Vérifie le code saisi par l'utilisateur. Un code ne peut être validé qu'une seule fois.

ChampTypeRequisDescription
RecipientchaîneRequisNuméro auquel le code a été envoyé.
CodechaîneRequisCode saisi par l'utilisateur.
curl -X POST 'https://messaging.mapi.mg/api/otp/verify' \
  -H 'Authorization: VOTRE_JETON' \
  -F 'Recipient=0340000000' \
  -F 'Code=123456'
{
  "status": true,
  "message": "Code is verified"
}

En cas de refus, le champ code de la réponse précise la raison : 4 pour un code introuvable, 5 pour un code déjà utilisé.

OTP

Historique des OTP

GET/otp

Jeton requis

Liste les codes générés, avec leur état d'envoi, d'expiration et d'utilisation.

ParamètreTypeDescription
limitentierNombre de codes renvoyés, par exemple 10.
offsetentierPosition du premier code renvoyé (0 pour la première page).
curl 'https://messaging.mapi.mg/api/otp?limit=10&offset=0' \
  -H 'Authorization: VOTRE_JETON'
{
  "status": true,
  "result": [
    {
      "IdOneTimePassword": "1",
      "IdClient": "1",
      "Client": "client",
      "Username": "username",
      "Telephone": "+261340000000",
      "Code": "000000",
      "GeneratedAt": "1725440581",
      "GeneratedAtDateTime": "2024-09-04 11:03:01",
      "ExpiresAt": "1725441481",
      "ExpiresAtDateTime": "2024-09-04 11:18:01",
      "Duration": "900",
      "TimeToLiveHHMMSS": "-00:01:25",
      "TimeToLiveSeconds": "-85",
      "IsExpired": "1",
      "SendStatus": "SENT",
      "IsAlreadyUsed": "1"
    }
  ],
  "totalCount": 3
}

Champs principaux de chaque élément de result :

ChampTypeDescription
TelephonechaîneNuméro du destinataire au format international.
CodechaîneCode envoyé.
GeneratedAtDateTimechaîneDate de génération (GeneratedAt : horodatage Unix).
ExpiresAtDateTimechaîneDate d'expiration (ExpiresAt : horodatage Unix).
DurationchaîneDurée de validité en secondes (900).
TimeToLiveSecondschaîneTemps restant avant expiration, négatif une fois le code expiré (TimeToLiveHHMMSS au format HH:MM:SS).
IsExpiredchaîne1 si le code a expiré, 0 sinon.
IsAlreadyUsedchaîne1 si le code a déjà été validé, 0 sinon.
SendStatuschaîneSENT ou NOT_SENT.

Compte

Unités disponibles

GET/smsoffer/available

Jeton requis

Renvoie le nombre d'unités SMS que votre compte peut encore utiliser.

curl 'https://messaging.mapi.mg/api/smsoffer/available' \
  -H 'Authorization: VOTRE_JETON'
{
  "status": true,
  "available_sms": 1000
}
Recharger — le champ technique s'appelle available_sms ; il correspond aux unités de vos packs SMS. Quand il atteint zéro, les envois renvoient 409 Conflict.

Compte

Déconnexion

POST/authentication/logout

Jeton requis

Révoque le jeton transmis dans l'en-tête Authorization avant son expiration.

curl -X POST 'https://messaging.mapi.mg/api/authentication/logout' \
  -H 'Authorization: VOTRE_JETON'
{
  "status": true,
  "message": "Logged out successfully"
}

Référence

Réponses & erreurs

Toutes les réponses sont en JSON. Le booléen status vaut true en cas de succès ; en cas d'échec il vaut false et le détail figure dans message ou result.

Statut HTTPSignification
200 OKRequête traitée avec succès.
401 UnauthorizedJeton absent, expiré ou révoqué, identifiants de connexion invalides, ou session déjà fermée.
409 ConflictNuméro de destinataire mal formé, ou solde d'unités épuisé.
422 Unprocessable EntityParamètre manquant ou invalide : fichier absent ou d'un type non accepté, message absent, code OTP introuvable ou déjà utilisé.

Codes d'erreur

Certaines erreurs précisent leur cause avec un champ numérique code :

codeEndpointSignification
1/authentication/loginIdentifiant ou mot de passe incorrect.
4/otp/verifyCode OTP introuvable.
5/otp/verifyCode OTP déjà utilisé.
Bonne pratique — basez votre logique sur le statut HTTP, status et code, jamais sur le texte des messages : il peut être en français ou en anglais et évoluer.

Prêt à intégrer Mapi ?

Créez votre compte pour obtenir vos identifiants, ou contactez l'équipe pour être accompagné dans votre intégration.