📚 Documentation

Tout savoir sur MAYASEND.

Guide d'utilisation de la plateforme, référence de l'API REST v1 et bonnes pratiques pour envoyer vos SMS, messages WhatsApp et emails.

Introduction

MAYASEND est une plateforme d'envoi de messages en masse et transactionnels sur trois canaux : SMS, WhatsApp et Email. Un solde unique en FCFA alimente les trois canaux : vous rechargez une fois, puis vous envoyez là où vos clients vous lisent.

  • Application web : campagnes, contacts, modèles, factures, statistiques, clés API.
  • Application mobile : recharge, campagnes et suivi depuis votre téléphone.
  • API REST : intégrez l'envoi dans votre site, votre application ou votre logiciel métier.

Démarrage rapide

  1. Créez votre compte sur la page d'inscription, puis confirmez votre email avec le code reçu.
  2. Rechargez votre solde (voir ci-dessous). Le crédit est ajouté dès que le paiement est confirmé.
  3. Faites approuver un Sender ID (nom d'expéditeur SMS).
  4. Importez vos contacts ou saisissez vos numéros.
  5. Lancez une campagne ou appelez l'API : le solde est débité à l'envoi.

Solde & recharge

Le paiement s'effectue en ligne via KKiaPay (Mobile Money et autres moyens proposés dans le widget). Lors de l'achat, vous choisissez le type de pack :

PackPourQuantité minimale
SMS + WhatsAppEnvois SMS et messages WhatsApp200 messages
EmailCampagnes et envois d'emails1 000 emails

Après paiement, MAYASEND interroge directement KKiaPay pour confirmer la transaction : votre solde est crédité même si vous fermez la page. Une facture est générée dans votre espace. Les messages en échec définitif sont remboursés automatiquement.

Canaux & tarifs

CanalUsageTarif indicatif
📱 SMSAlertes, codes, promotions. Facturé par segment (160 caractères GSM-7, 70 en Unicode).à partir de 25 FCFA
💬 WhatsAppMessages via modèles approuvés, conversations avec vos clients.35 FCFA
✉️ EmailNewsletters, factures, notifications.3 FCFA

Les tarifs exacts dépendent de votre forfait ; la page Tarifs présente la grille à jour. Votre solde indique aussi l'équivalent en messages pour chaque canal.

Sender ID

Le Sender ID est le nom affiché comme expéditeur du SMS (ex. MAYA). Faites la demande depuis Sender ID dans votre espace : une fois approuvé par l'équipe, il devient utilisable pour vos campagnes et via l'API (champ sender). Si vous n'en précisez pas, le premier Sender ID approuvé est utilisé.

  • Choisissez un nom court, lisible et lié à votre marque.

Contacts & listes

Importez vos contacts depuis un fichier CSV ou ajoutez-les un à un, puis organisez-les en listes pour cibler vos campagnes. Les numéros sont normalisés automatiquement (format local 01XXXXXXXX ou international +229…) et les doublons sont ignorés.

  • Un contact peut avoir un numéro, un numéro WhatsApp et un email.
  • Les contacts désinscrits (par exemple via le lien de désinscription des emails) ne sont plus contactés.

Campagnes

Une campagne envoie un même message à une liste, immédiatement ou à une date programmée.

  1. Choisissez le canal (SMS, WhatsApp ou Email) et la liste de destinataires.
  2. Rédigez le message ; vous voyez le nombre de segments et le coût estimé avant d'envoyer.
  3. Envoyez maintenant ou programmez. Le montant est réservé, puis ajusté selon les messages réellement envoyés.
  4. Suivez les statuts (envoyé, remis, échec) et, pour l'email, les ouvertures et les clics.

Le système peut basculer automatiquement vers un fournisseur de secours en cas d'incident, sans intervention de votre part.

Modèles WhatsApp

Pour écrire le premier à un client sur WhatsApp, Meta impose l'usage d'un modèle de message approuvé. Créez vos modèles depuis Modèles : variables {{1}}, {{2}}…, catégorie (utilitaire, marketing, authentification), puis soumettez-les à validation. Le statut passe de en attente à approuvé ou refusé (avec le motif).

Emailing

  • Un lien de désinscription est ajouté automatiquement à chaque email.
  • Le suivi des ouvertures et des clics est disponible dans les statistiques de campagne.
  • Les adresses désinscrites ou invalides sont ignorées, et leur envoi est remboursé.
  • Pour une bonne délivrabilité, utilisez un expéditeur identifiable et évitez les contenus uniquement composés d'images.

Application mobile

Connectez-vous avec vos identifiants web. Vous pouvez recharger votre solde (en choisissant le pack SMS + WhatsApp ou Email), lancer et suivre vos campagnes, gérer vos contacts et consulter vos factures. En cas de maintenance de la plateforme, l'application affiche un écran d'information avec le message de l'équipe et un bouton « Réessayer ». Voir la page Application mobile.

Revendeurs

Les revendeurs disposent d'un espace dédié pour gérer leurs clients, suivre leurs ventes et leurs commissions. Détails sur la page Revendeurs.

API v1 — Introduction

L'API est une API REST JSON. URL de base :

https://mayasend.bconsultingsarl.com/api/v1
  • Toutes les requêtes se font en HTTPS.
  • Les corps de requête sont en JSON : Content-Type: application/json.
  • Chaque réponse contient success et, en cas d'erreur, un objet error avec type et message.
  • Chaque réponse porte un identifiant de requête (request_id) à communiquer au support en cas de question.

Clés API

L'accès à l'API est activé à la demande depuis votre espace client (menu « Clés API »). Vous obtenez d'abord un trio de clés test ; les clés live se demandent ensuite. Elles ne s'affichent qu'après confirmation de votre mot de passe.

CléFormatRôle
Publiquemk_test_pk_…Identifie votre compte. Autorise uniquement GET /ping. En-tête X-Public-Key.
Privéemk_test_sk_…Authentifie vos appels. Côté serveur uniquement.
Secrètemk_test_ss_…Signe vos requêtes (HMAC-SHA256). Ne circule jamais sur le réseau.

Pour la production, les clés commencent par mk_live_. Vous pouvez restreindre chaque clé à des adresses IP et à certains canaux, la révoquer ou la régénérer à tout moment.

Important : ne placez jamais une clé privée ou secrète dans une application mobile, une page web ou un dépôt public.

Authentification

Envoyez votre clé privée dans l'en-tête Authorization :

Authorization: Bearer mk_live_sk_xxxxxxxxxxxxxxxx

L'en-tête X-API-Key: mk_…_sk_… est accepté comme alternative.

Signature des requêtes (HMAC)

Si vous activez « signature obligatoire » pour votre environnement, chaque requête doit porter deux en-têtes supplémentaires :

X-Timestamp: 1760000000
X-Signature: hex( HMAC_SHA256( clé_secrète, TIMESTAMP + "." + METHODE + "." + CHEMIN + "." + CORPS ) )
  • TIMESTAMP : secondes UNIX, tolérance de ±5 minutes.
  • CHEMIN : par exemple /api/v1/sms/send.
  • CORPS : le texte JSON exact envoyé (vide pour un GET).
$ts   = time();
$body = json_encode(['to' => '0197000001', 'message' => 'Bonjour', 'sender' => 'MAYA']);
$sig  = hash_hmac('sha256', $ts . '.POST./api/v1/sms/send.' . $body, 'mk_live_ss_xxxxxxxx');
// En-têtes : X-Timestamp: $ts   X-Signature: $sig
const crypto = require('crypto');
const ts   = Math.floor(Date.now() / 1000);
const body = JSON.stringify({ to: '0197000001', message: 'Bonjour', sender: 'MAYA' });
const sig  = crypto.createHmac('sha256', 'mk_live_ss_xxxxxxxx')
                   .update(`${ts}.POST./api/v1/sms/send.${body}`).digest('hex');
import hmac, hashlib, json, time
ts   = str(int(time.time()))
body = json.dumps({"to": "0197000001", "message": "Bonjour", "sender": "MAYA"})
sig  = hmac.new(b"mk_live_ss_xxxxxxxx", f"{ts}.POST./api/v1/sms/send.{body}".encode(), hashlib.sha256).hexdigest()

Mode sandbox (clés de test)

Les clés mk_test_… exécutent toute la validation mais n'envoient rien et ne débitent pas votre solde. Les identifiants de messages commencent par sbx_.

  • Un numéro se terminant par 0000 ou un email commençant par fail@ simule un échec de livraison.
  • Passez en production en remplaçant simplement la clé par une clé mk_live_….

Ping & solde

GET /ping

Vérifie une clé (publique ou privée).

curl https://mayasend.bconsultingsarl.com/api/v1/ping -H "Authorization: Bearer mk_test_sk_xxxxxxxx"

{ "success": true, "environment": "sandbox", "key_type": "private", "account": "Ma Société" }

GET /balance

Retourne le solde en FCFA, les prix unitaires et l'équivalent en messages.

{ "success": true, "environment": "live",
  "balance": { "amount": 12500, "currency": "XOF" },
  "unit_prices": { "sms": 25, "whatsapp": 35, "email": 3 },
  "equivalent_messages": { "sms": 500, "whatsapp": 357, "email": 4166 } }

POST /sms/send

ChampTypeDescription
tostringNuméro du destinataire (01XXXXXXXX ou +229…)
messagestringTexte, 1 600 caractères maximum. Facturé par segment.
senderstringSender ID approuvé (facultatif)
referencestringVotre référence interne (facultatif)
curl -X POST https://mayasend.bconsultingsarl.com/api/v1/sms/send \
  -H "Authorization: Bearer mk_live_sk_xxxxxxxx" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: cmd-10452" \
  -d '{"to":"0197000001","message":"Bonjour, votre code est 4821","sender":"MAYA"}'
$ch = curl_init('https://mayasend.bconsultingsarl.com/api/v1/sms/send');
curl_setopt_array($ch, [
  CURLOPT_POST => true, CURLOPT_RETURNTRANSFER => true,
  CURLOPT_HTTPHEADER => ['Authorization: Bearer mk_live_sk_xxxxxxxx', 'Content-Type: application/json'],
  CURLOPT_POSTFIELDS => json_encode(['to' => '0197000001', 'message' => 'Bonjour', 'sender' => 'MAYA']),
]);
$res = json_decode(curl_exec($ch), true);
const res = await fetch('https://mayasend.bconsultingsarl.com/api/v1/sms/send', {
  method: 'POST',
  headers: { 'Authorization': 'Bearer mk_live_sk_xxxxxxxx', 'Content-Type': 'application/json' },
  body: JSON.stringify({ to: '0197000001', message: 'Bonjour', sender: 'MAYA' })
});
const data = await res.json();
import requests
r = requests.post('https://mayasend.bconsultingsarl.com/api/v1/sms/send',
    headers={'Authorization': 'Bearer mk_live_sk_xxxxxxxx'},
    json={'to': '0197000001', 'message': 'Bonjour', 'sender': 'MAYA'})
print(r.json())

Réponse (HTTP 202) :

{ "success": true,
  "message": { "id": "msg_…", "status": "queued", "cost": 25 },
  "request_id": "req_…" }

POST /whatsapp/send

Les messages à l'initiative de l'entreprise utilisent un modèle approuvé par Meta (voir « Modèles WhatsApp »).

ChampTypeDescription
tostringNuméro WhatsApp du destinataire
templatestringIdentifiant ou nom du modèle approuvé
paramsstring[]Valeurs de {{1}}, {{2}}… (autant que dans le modèle)
curl -X POST https://mayasend.bconsultingsarl.com/api/v1/whatsapp/send \
  -H "Authorization: Bearer mk_live_sk_xxxxxxxx" -H "Content-Type: application/json" \
  -d '{"to":"0197000002","template":"rappel_rdv","params":["Awa","demain 10h"]}'

POST /email/send

ChampTypeDescription
tostringAdresse email
subjectstringObjet (200 caractères maximum)
html / textstringContenu (au moins l'un des deux). Le HTML est nettoyé : scripts supprimés.
from_name, reply_tostringFacultatifs
curl -X POST https://mayasend.bconsultingsarl.com/api/v1/email/send \
  -H "Authorization: Bearer mk_live_sk_xxxxxxxx" -H "Content-Type: application/json" \
  -d '{"to":"awa@exemple.com","subject":"Votre facture","html":"<p>Bonjour Awa,</p>"}'

Un lien de désinscription est ajouté automatiquement ; les destinataires désinscrits ne sont plus contactés et le message est remboursé.

Envoi en lot

Envoyez jusqu'à 100 messages par requête sur n'importe quel point d'entrée d'envoi :

{ "messages": [
    { "to": "0197000001", "message": "Bonjour Awa" },
    { "to": "0197000002", "message": "Bonjour Koffi" }
] }

→ { "success": true, "accepted": 2, "rejected": 0, "total_cost": 50, "results": [ … ] }

Chaque élément est validé séparément : un message invalide n'empêche pas les autres.

GET /messages/{id}

Retourne l'état d'un message : queued → sending → sent → delivered, ou failed (avec le motif dans error). Pour les emails, opened_at et clicked_at sont renseignés.

Idempotence

Ajoutez l'en-tête Idempotency-Key (8 à 100 caractères : lettres, chiffres, . _ : -) pour pouvoir rejouer une requête sans doublon : la même réponse est renvoyée avec l'en-tête Idempotent-Replayed: true. Si la première requête est encore en cours, vous recevez une erreur 409.

Erreurs

{ "success": false, "error": { "type": "insufficient_balance", "message": "Solde insuffisant. Rechargez votre compte." } }
HTTPTypeSignification
200 / 202—Succès (202 : message accepté, envoi en cours)
400invalid_json, invalid_idempotency_keyCorps JSON ou clé d'idempotence invalide
401invalid_signature…Clé absente ou invalide, signature incorrecte
402insufficient_balanceSolde insuffisant (rien n'est débité)
403channel_not_allowed…Canal ou IP non autorisés, clé publique sur un point privé, compte inactif
404not_foundPoint d'entrée ou message inconnu
405method_not_allowedMéthode HTTP non autorisée (voir l'en-tête Allow)
409request_in_progressMême Idempotency-Key encore en traitement
415unsupported_media_typeContent-Type doit être application/json
422validation_errorDonnées invalides — error.message détaille le champ
429—Trop de requêtes : attendez (en-tête Retry-After)

Facturation : le montant est débité à l'acceptation du message et automatiquement remboursé en cas d'échec définitif.

Limites & sécurité

  • 100 messages maximum par requête, corps de requête limité à 2 Mo.
  • Limitation de débit : en cas de dépassement, l'API répond 429 avec Retry-After.
  • Liste blanche d'IP, restriction par canal et journalisation des appels par clé.
  • Révoquez immédiatement une clé compromise depuis « Clés API », puis régénérez-la.

Bonnes pratiques

  • Testez toute votre intégration avec les clés sandbox avant de passer en live.
  • Utilisez Idempotency-Key pour les envois déclenchés par une commande ou un paiement.
  • Surveillez votre solde via /balance et rechargez avant d'être à court.
  • Respectez le consentement de vos destinataires et la réglementation locale sur la prospection.
  • Gardez les messages courts : un SMS de plus de 160 caractères coûte plusieurs segments.

Questions fréquentes

Mon paiement est validé mais mon solde n'a pas bougé.

MAYASEND vérifie le paiement directement auprès de KKiaPay. Patientez une minute puis actualisez ; si le solde n'est pas crédité, contactez le support avec la référence de la transaction.

Puis-je utiliser le même solde pour les trois canaux ?

Oui, un seul solde en FCFA est débité selon le tarif de chaque canal. Le choix du pack (SMS + WhatsApp ou Email) définit seulement la quantité minimale à l'achat.

Pourquoi mon Sender ID n'est pas disponible ?

Il doit être approuvé par l'équipe. Vérifiez son statut dans votre espace.

Les clés sandbox débitent-elles mon solde ?

Non. Aucune donnée n'est envoyée et rien n'est débité.

Que se passe-t-il si un message échoue ?

Après échec définitif, le montant est remboursé automatiquement sur votre solde.

Où voir l'état de la plateforme ?

Sur la page Statut, qui indique aussi les maintenances en cours.

Support

Une question, un incident ? Écrivez-nous via la page Contact en indiquant votre email de compte et, pour l'API, le request_id de la réponse concernée.