PAY ONLINE · REST API · v1.0

API de paiement

Intégrez BluePay dans votre application en quelques lignes. Une seule API pour accepter Wave, Orange Money, Free Money, Wizall et carte bancaire.

WaveOrange MoneyFree MoneyWizallCarte bancaire

Introduction

BluePay est une passerelle de paiement multi-opérateurs pour le marché sénégalais. Elle expose une API REST JSON standard, compatible avec tous les langages et frameworks.

🔑
Clé API Bearer
Une clé suffit pour toutes les requêtes.
📡
REST + JSON
HTTP standard — compatible tout framework.
🔔
Webhooks HMAC
Notifications IPN signées SHA-256.
URL de base
https://bluepay.myfad.org

⚡ Démarrage rapide

Prêt en 3 étapes :

1

Obtenir vos clés API

Créez un compte sur le dashboard et récupérez vos clés TEST et LIVE dans Paramètres → Clés API.

Créer un compte →
2

Initier un paiement

Appelez POST /api/v1/payments depuis votre serveur. Vous recevez une checkoutUrl que vous retournez à votre client.

3

Recevoir le webhook

Configurez votre URL IPN dans le dashboard. BluePay vous notifie dès la confirmation du paiement.

🔑 Authentification

Toutes les requêtes authentifiées nécessitent le header Authorization: Bearer <clé_api>.

🚨
Ne jamais exposer votre clé LIVE dans du code front-end (JS navigateur, application mobile). Effectuez toujours les appels API côté serveur.
HTTP Header
Authorization: Bearer bluepay_live_xxxxxxxxxxxxxxxxxx
Content-Type: application/json
ChampTypeRequisDescription
bluepay_test_…stringNonClé de test — aucun vrai paiement. À utiliser en développement.
bluepay_live_…stringNonClé de production — vrais paiements. À activer depuis le dashboard.

🌍 Environnements

TestProduction
URL APIhttps://bluepay.myfad.orghttps://api.bluepay.sn
Préfixe clébluepay_test_…bluepay_live_…
Vrais paiements❌ Non✅ Oui
Données réelles❌ Non✅ Oui

🔄 Flux de paiement hébergé

BluePay fonctionne en mode checkout hébergé : vous créez le paiement depuis votre serveur, redirigez le client vers la page BluePay, il paie, et vous recevez un webhook de confirmation.

1Votre serveurPOST /api/v1/payments
2BluePaycheckoutUrl retournée
3Client paieWave · Orange · Carte…
4IPN WebhookPOST → votre serveur

💳 Créer un paiement

POST/api/v1/payments

Paramètres

ChampTypeRequisDescription
amountintegerOuiMontant en centimes XOF. Ex : 125000 = 1 250 XOF. Minimum : 1.
channelstringOuiWAVE | ORANGE_MONEY | FREE_MONEY | WIZALL | CARD
idempotencyKeystringOuiClé unique anti-doublons. Même clé = même résultat, sans double débit.
customerPhonestringNonTéléphone au format international. Ex : +221771234567
customerEmailstringNonEmail du client pour confirmation automatique
descriptionstringNonLibellé affiché sur la page de paiement BluePay
returnUrlstringNonURL de redirection après paiement
metadataobjectNonDonnées libres retournées dans le webhook. Ex : { studentId: "UCK-001" }
💡
Générez idempotencyKey avec crypto.randomUUID() côté serveur pour éviter les doubles débits en cas de retry réseau.

Exemples de code

const res = await fetch('https://bluepay.myfad.org/api/v1/payments', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer bluepay_live_votre_cle',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    amount: 125000,                      // 1 250 XOF
    channel: 'WAVE',
    idempotencyKey: crypto.randomUUID(),
    customerPhone: '+221771234567',
    description: 'Frais de scolarité S1 2026',
    returnUrl: 'https://votre-site.sn/merci',
    metadata: { studentId: 'UCK-2026-1042' },
  }),
});

const { checkoutUrl } = await res.json();
// → "https://bluepay.myfad.org/pay/cpay_8f26b1f3..."
window.location.href = checkoutUrl;

Réponse

JSON
{
  "id": "clxyz1234abcd",
  "reference": "TXN-a1b2c3d4-e5f6-...",
  "status": "PENDING",
  "amount": 125000,
  "currency": "XOF",
  "channel": "WAVE",
  "checkoutUrl": "https://bluepay.myfad.org/pay/cpay_8f26b1f3b9161d76...",
  "createdAt": "2026-06-30T10:30:00.000Z"
}

📋 Statut d'une transaction

GET/api/v1/payments/:id
PENDINGEn attente
PROCESSINGEn cours
SUCCESSConfirmé ✓
FAILEDÉchoué
REFUNDEDRemboursé
CANCELLEDAnnulé
const res = await fetch('https://bluepay.myfad.org/api/v1/payments/clxyz1234abcd', {
  headers: { 'Authorization': 'Bearer bluepay_live_votre_cle' },
});
const { id, status, amount } = await res.json();
console.log(status); // "SUCCESS"

↩️ Remboursement

POST/api/v1/payments/:id/refund
ChampTypeRequisDescription
amountintegerNonMontant à rembourser en centimes. Si absent : remboursement total.
reasonstringNonMotif du remboursement. Affiché dans le dashboard et le webhook.
// Remboursement total
await fetch('https://bluepay.myfad.org/api/v1/payments/clxyz1234abcd/refund', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer bluepay_live_votre_cle',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ reason: 'Cours annulé — remboursement automatique' }),
});

// Remboursement partiel — 500 XOF sur 1 250 XOF
await fetch('https://bluepay.myfad.org/api/v1/payments/clxyz1234abcd/refund', {
  method: 'POST',
  headers: { 'Authorization': 'Bearer bluepay_live_votre_cle', 'Content-Type': 'application/json' },
  body: JSON.stringify({ amount: 50000, reason: 'Remboursement partiel' }),
});

🔔 Webhooks (IPN)

BluePay envoie un POST HTTP à votre URL webhook à chaque changement de statut. Configurez-la depuis Dashboard → Paramètres → Webhooks.

⚠️
Votre endpoint doit répondre en moins de 5 secondes avec un statut 2xx. BluePay réessaie automatiquement jusqu'à 3 fois en cas d'échec.

Payload

JSON
{
  "event": "payment.success",
  "data": {
    "id": "clxyz1234abcd",
    "reference": "TXN-a1b2c3d4-...",
    "status": "SUCCESS",
    "amount": 125000,
    "currency": "XOF",
    "channel": "WAVE",
    "customerPhone": "+221771234567",
    "metadata": { "studentId": "UCK-2026-1042" },
    "createdAt": "2026-06-30T10:30:00.000Z",
    "paidAt": "2026-06-30T10:30:42.000Z"
  }
}

Événements disponibles :

payment.successPaiement confirmé
payment.failedPaiement échoué
payment.refundedRemboursement effectué
payment.cancelledAnnulé par le client

🔐 Vérifier la signature

Chaque webhook contient le header X-BluePay-Signature — un HMAC-SHA256 du body signé avec votre webhook secret.

🚨
Ne traitez jamais un webhook sans vérifier sa signature. N'importe qui pourrait envoyer de faux événements à votre endpoint.
const crypto = require('crypto');

app.post('/webhook/bluepay', express.raw({ type: 'application/json' }), (req, res) => {
  const sig      = req.headers['x-bluepay-signature'];
  const secret   = process.env.BLUEPAY_WEBHOOK_SECRET;
  const expected = crypto
    .createHmac('sha256', secret)
    .update(req.body)           // req.body = buffer brut (express.raw obligatoire)
    .digest('hex');

  if (!crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(sig ?? ''))) {
    return res.status(401).json({ error: 'Signature invalide' });
  }

  const { event, data } = JSON.parse(req.body.toString());

  if (event === 'payment.success') {
    // ✅ Valider l'inscription, débloquer la commande
    console.log('Paiement reçu :', data.amount, 'XOF — étudiant :', data.metadata?.studentId);
  }

  res.json({ received: true });
});

📱 Opérateurs supportés

Valeur channelOpérateurTypeDisponibilité
WAVEWaveMobile Money✅ Disponible
ORANGE_MONEYOrange MoneyMobile Money✅ Disponible
FREE_MONEYFree MoneyMobile Money✅ Disponible
WIZALLWizall MoneyMobile Money✅ Disponible
CARDCarte bancaireVisa / MC✅ Disponible

🚨 Codes d'erreur

HTTPCodeCauseSolution
400VALIDATION_ERRORBody invalideVérifier les champs requis et les types
401UNAUTHORIZEDClé API manquante ou invalideVérifier le header Authorization
404NOT_FOUNDTransaction introuvableVérifier l'ID ou qu'il vous appartient
409IDEMPOTENCYidempotencyKey déjà utiliséeRécupérer la transaction avec GET /api/v1/payments/:id
422UNPROCESSABLEMontant ≤ 0 ou opérateur invalideVérifier les valeurs envoyées
429RATE_LIMITTrop de requêtesImplémenter un backoff exponentiel
500SERVER_ERRORErreur interne BluePayContacter support@bluepay.sn avec votre requestId

🧪 Testeur API interactif

Testez l'API directement depuis cette page sans quitter la documentation.

ℹ️
Ce testeur appelle votre backend local (https://bluepay.myfad.org). Démarrez-le avec npm run start:dev dans le dossier racine.
🧪Testeur API InteractifPOST /api/v1/payments

125000 = 1 250 XOF

🇸🇳 +221

Prêt à intégrer ?

Créez votre compte, récupérez vos clés API et acceptez vos premiers paiements.