Documentation API
MonCashConnect est une API REST pour accepter des paiements MonCash dans votre application, votre site WordPress ou votre SaaS — sans gérer OAuth, jetons ou la complexité de la passerelle officielle.
Chaque requête est authentifiée avec la clé secrète de votre projet sk_proj_…. Les webhooks signés HMAC-SHA256 garantissent l'intégrité des notifications de paiement.
https://hvlmeoqyxaguzcujpmit.supabase.co/functions/v1Toutes les requêtes doivent être en HTTPS. Le corps des requêtes
POST doit être en application/json.Quickstart
Intégrez MonCash en moins de 5 minutes. Voici le flux minimal de bout en bout.
Créez un projet dans le tableau de bord
Rendez-vous dans Développeur → Projets et créez un projet. Vous obtiendrez une clé secrète sk_proj_… — conservez-la en lieu sûr, elle ne s'affiche qu'une seule fois.
Créez un paiement côté serveur
curl -X POST https://hvlmeoqyxaguzcujpmit.supabase.co/functions/v1/pay-create \
-H "Authorization: Bearer sk_proj_xxxx" \
-H "Content-Type: application/json" \
-d '{
"amount": 500,
"referenceId": "order_001",
"returnUrl": "https://votresite.com/merci"
}'La réponse contient paymentUrl — redirigez votre client vers cette URL.
Redirigez le client vers MonCash
const { paymentUrl } = await res.json();
// Côté serveur (Express, Next.js, etc.)
res.redirect(paymentUrl);Recevez la confirmation par webhook
Configurez une URL webhook dans votre projet. MonCashConnect envoie un POST signé HMAC-SHA256 dès que le paiement est confirmé par MonCash.
import { constructEvent, MonCashError } from "@moncashconnect/sdk";
// Express — lire le corps brut AVANT JSON.parse
app.post("/webhook", express.raw({ type: "application/json" }), (req, res) => {
try {
const event = constructEvent(
req.body,
req.headers["x-mcc-signature"],
req.headers["x-mcc-timestamp"],
process.env.MCC_WEBHOOK_SECRET,
);
if (event.event === "payment.completed") {
// Créditez la commande dans votre base de données
}
res.sendStatus(200);
} catch (err) {
if (err instanceof MonCashError) return res.status(err.statusCode).send(err.message);
res.sendStatus(500);
}
});Authentification
Chaque projet possède une clé secrète unique préfixée sk_proj_. Passez-la dans l'en-tête Authorization de chaque requête.
curl -H "Authorization: Bearer sk_proj_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
https://hvlmeoqyxaguzcujpmit.supabase.co/functions/v1/pay-balanceDomaines autorisés (CORS)
Si vous configurez des domaines autorisés sur votre projet, les requêtes provenant d'autres origines seront rejetées avec un 403. Laissez la liste vide pour autoriser toutes les origines (usage serveur uniquement).
localhost, vos URLs de staging et les previews. Ajoutez chaque environnement (prod, staging, dev) explicitement.Créer un paiement
https://hvlmeoqyxaguzcujpmit.supabase.co/functions/v1/pay-createCrée une transaction en attente et renvoie une URL de paiement MonCash. Redirigez votre client vers cette URL. La transaction expire après 15 minutes.
Paramètres (JSON body)
| Nom / Code | Type / Limite | Description |
|---|---|---|
| amount* | integer | Montant en HTG, entier entre 1 et 1 000 000 |
| referenceId* | string | Identifiant unique [a-zA-Z0-9-_], 100 caractères max. Unique par projet. |
| returnUrl | string | URL HTTPS de retour après paiement — fortement recommandé |
| customerName | string | Nom du client — affiché sur la page MonCash (optionnel) |
| customerEmail | string | Email du client — enregistré dans la transaction (optionnel) |
curl -X POST https://hvlmeoqyxaguzcujpmit.supabase.co/functions/v1/pay-create \
-H "Authorization: Bearer sk_proj_xxxx" \
-H "Content-Type: application/json" \
-d '{
"amount": 500,
"referenceId": "order_12345",
"returnUrl": "https://votresite.com/merci",
"customerName": "Jean Dupont",
"customerEmail": "jean@example.com"
}'Réponse (200)
{
"paymentUrl": "https://pay.bazik.io/c/abc123...",
"reference": "order_12345",
"expiresAt": "2026-05-05T15:30:00.000Z"
}referenceId doit être unique par projet. Réutiliser un referenceId existant retourne 409 Conflict.Reprise sûre avec Idempotency-Key
Une requête /pay-create qui échoue (erreur réseau, timeout, 502 passerelle) peut avoir déjà créé la transaction. Pour rendre les retries sûrs, ajoutez l'en-tête Idempotency-Key avec une chaîne unique par tentative logique (UUID, hash de commande, etc.) : un second appel avec la même clé et le même corps renvoie l'URL de paiement d'origine au lieu de créer un doublon.
| Nom / Code | Type / Limite | Description |
|---|---|---|
| Idempotency-Key (en-tête) | ASCII imprimable, ≤ 200 chars | Identifiant stable côté merchant. Validité : 15 min (la fenêtre TTL de l'URL Bazik). |
Réponses possibles avec Idempotency-Key
| Nom / Code | Type / Limite | Description |
|---|---|---|
| 200 | même clé + même corps | Réponse d'origine renvoyée (header Idempotent-Replay: true). paymentUrl identique. |
| 422 | idempotency_key_mismatch | Même clé, corps différent — refusé pour éviter une transaction silencieusement modifiée. |
| 409 | idempotent_request_in_progress | Requête précédente avec cette clé encore en cours. Header Retry-After: 2 — réessayer. |
| 502 | idempotent_replay_failed | La requête précédente avec cette clé a échoué — utilisez une nouvelle clé pour réessayer. |
| 410 | idempotent_replay_expired | L'URL en cache a > 15 min ; utilisez une nouvelle Idempotency-Key (la précédente a expiré côté Bazik). |
curl -X POST https://hvlmeoqyxaguzcujpmit.supabase.co/functions/v1/pay-create \
-H "Authorization: Bearer sk_proj_xxxx" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: order_12345-attempt-1" \
-d '{ "amount": 500, "referenceId": "order_12345", "returnUrl": "https://votresite.com/merci" }'Idempotency-Key (compatible avec le comportement antérieur) : si vous recevez un 409 ou un échec réseau, appelez GET /pay-status?referenceId=… pour vérifier qu'une transaction existe avant de générer un nouveau referenceId. Le code de fallback ci-dessous reste valide pour les intégrations legacy.Fallback sans Idempotency-Key : reprise via /pay-status
Règle générale : sondez /pay-status avant de générer un nouveau referenceId. Ne ré-essayez /pay-create avec un identifiant frais que si /pay-status renvoie 404 (transaction jamais créée).
Vérifier le statut
https://hvlmeoqyxaguzcujpmit.supabase.co/functions/v1/pay-status?referenceId=order_12345Interrogez le statut d'une transaction par son referenceId. Utile après la redirection du client ou pour un polling de secours si le webhook n'est pas configuré.
curl -H "Authorization: Bearer sk_proj_xxxx" \
"https://hvlmeoqyxaguzcujpmit.supabase.co/functions/v1/pay-status?referenceId=order_12345"Réponse (200)
{
"reference": "order_12345",
"status": "completed",
"amount": 500,
"netAmount": 485,
"completedAt": "2026-05-05T14:21:18.000Z",
"failedAt": null,
"failureReason": null,
"bazikOrderId": "BZK-987654321",
"moncashTransactionId": "MC-123456789",
"createdAt": "2026-05-05T14:05:00.000Z"
}| Nom / Code | Type / Limite | Description |
|---|---|---|
| status | string | pending · completed · failed |
| amount | integer (HTG) | Montant brut encaissé |
| netAmount | integer (HTG) | Montant après déduction de la commission (ex : 500 × 97 % = 485 HTG en plan Free) |
| moncashTransactionId | string | null | ID de transaction MonCash — disponible après confirmation |
| failureReason | string | null | Motif d'échec si status = failed |
Solde
https://hvlmeoqyxaguzcujpmit.supabase.co/functions/v1/pay-balanceRenvoie le solde HTG de votre compte marchand MonCashConnect — c'est-à-dire le total des paiements acceptés qui se sont décantés, moins les retraits déjà effectués. Cet endpoint ne renvoie aucune information sur un client ou un paiement particulier ; il sert à automatiser les retraits vers MonCash via votre tableau de bord.
curl -H "Authorization: Bearer sk_proj_xxxx" \
"https://hvlmeoqyxaguzcujpmit.supabase.co/functions/v1/pay-balance"{
"balanceHtg": 12500,
"withdrawableHtg": 5000,
"dailyCapHtg": 5000,
"usedTodayHtg": 0
}| Nom / Code | Type / Limite | Description |
|---|---|---|
| balanceHtg | integer | Solde total disponible dans le compte |
| withdrawableHtg | integer | Montant retirable maintenant (min(solde, cap - utilisé)) |
| dailyCapHtg | integer | Plafond journalier de retrait selon votre plan |
| usedTodayHtg | integer | Déjà retiré aujourd'hui |
Les retraits se demandent depuis la page Retraits du tableau de bord et sont approuvés avant envoi MonCash.
Webhooks
Configurez une URL webhook dans votre projet pour recevoir les événements de paiement en temps réel. MonCashConnect envoie un POST signé HMAC-SHA256 à votre URL dès qu'un paiement est finalisé par MonCash.
external_payout.*) utilisent un schéma de signature distinct (t=…,v1=…) avec en-tête de déduplication X-MCC-Event-Id. Voir la documentation partenaire →En-têtes envoyés
| Nom / Code | Type / Limite | Description |
|---|---|---|
| X-MCC-Signature | string | sha256=<hex_hmac> — HMAC-SHA256 du corps JSON brut, signé avec votre webhook secret |
| X-MCC-Timestamp | string | Timestamp Unix (secondes) de l'envoi — rejetez si > 5 min d'écart |
| Content-Type | string | application/json |
Événements
{
"event": "payment.completed",
"reference": "order_12345",
"amount": 500,
"status": "completed",
"completedAt": "2026-05-05T14:21:18.000Z"
}{
"event": "payment.failed",
"reference": "order_12345",
"amount": 500,
"status": "failed",
"completedAt": null
}Vérification de la signature
Lisez le corps brut (req.body en Buffer) avant tout JSON.parse(). Rejetez toute requête dont la signature est invalide ou dont le timestamp dépasse 5 minutes.
# Générer une signature de test en local
SECRET="whsec_votre_secret_webhook"
BODY='{"event":"payment.completed","reference":"test_001","amount":500,"status":"completed","completedAt":"2026-05-05T14:21:18.000Z"}'
TS=$(date +%s)
SIG="sha256=$(echo -n "$BODY" | openssl dgst -sha256 -hmac "$SECRET" | sed 's/.*= //')"
curl -X POST https://votresite.com/webhook \
-H "Content-Type: application/json" \
-H "X-MCC-Signature: $SIG" \
-H "X-MCC-Timestamp: $TS" \
-d "$BODY"Politique de retry
Si votre endpoint ne répond pas avec un 2xx dans les 10 secondes, MonCashConnect enregistre l'échec et planifie une nouvelle tentative après 60 secondes. Assurez-vous que votre handler est idempotent — il peut recevoir le même événement plusieurs fois.
SDKs officiels
Des SDKs officiels couvrent les trois langages principaux. Chaque SDK inclut la gestion des erreurs, la vérification HMAC des webhooks et des types TypeScript / annotations Python.
Node.js / TypeScript
@moncashconnect/sdkimport { MonCashClient } from "@moncashconnect/sdk";
const client = new MonCashClient(
process.env.MCC_SECRET_KEY
);
const payment = await client.createPayment(
500, "order_001",
{ returnUrl: "https://site.ht/merci" }
);
res.redirect(payment.paymentUrl);Python / pip
moncashconnectfrom moncashconnect import MonCashClient
import os
client = MonCashClient(
os.environ["MCC_SECRET_KEY"]
)
payment = client.create_payment(
500, "order_001",
return_url="https://site.ht/merci"
)
# redirect(payment["paymentUrl"])PHP / Composer
moncashconnect/php-sdkuse MonCashConnect\Client;
$client = new Client(
$_ENV['MCC_SECRET_KEY']
);
$payment = $client->createPayment(
500, 'order_001',
['returnUrl' => 'https://site.ht/merci']
);
header('Location: '.$payment['paymentUrl']);Guides par framework
Frais
MonCashConnect prend 0 % sur vos transactions.
Les frais que vous voyez sur la passerelle viennent de Bazik (notre passerelle vers Digicel MonCash) et de Digicel. Nous les transmettons à l'identique — aucune marge ajoutée.
Frais détaillés
| Nom / Code | Type / Limite | Description |
|---|---|---|
| Encaissement | 2,9 % (Bazik) | Prélevé par Bazik sur chaque paiement entrant via MonCash. Sur 1 000 HTG encaissés, vous recevez 971 HTG. |
| Retrait MonCash | 5 % (Bazik) | Prélevé par Bazik à l'envoi vers un numéro MonCash. Pour envoyer 1 000 HTG, votre solde diminue de 1 050 HTG. |
| Envois entre comptes MCC | 0 % | Gratuits — aucun frais réseau, aucune commission MCC. |
| Commission MonCashConnect | 0 % | Nous ne prélevons rien sur les transactions, peu importe le plan. |
Pourquoi un abonnement existe alors ?
L'abonnement (Pro, Business, Lifetime) débloque deux choses uniquement : plus d'un projet API sur votre compte, et des plafonds journaliers plus élevés sur les retraits. Tant que vous tenez sur un seul projet et le plafond Free, vous n'avez aucune raison de payer. Voir les plans →
Limites de débit
Les limites s'appliquent par clé secrète de projet et par adresse IP. Un dépassement retourne un 429 Too Many Requests.
| Nom / Code | Type / Limite | Description |
|---|---|---|
| POST /pay-create | 60 / min / clé | 30 / min / IP |
| GET /pay-status | 120 / min / clé | 60 / min / IP |
| GET /pay-balance | 120 / min / clé | 60 / min / IP |
En cas de dépassement répété, implémentez un backoff exponentiel avec jitter entre les tentatives. Évitez le polling intensif sur pay-status — préférez les webhooks pour les confirmations en temps réel.
Codes d'erreur
Toutes les erreurs renvoient un objet JSON { "error": "message" }.
| Nom / Code | Type / Limite | Description |
|---|---|---|
| 400 | Bad Request | Paramètre invalide ou manquant — vérifiez amount, referenceId, returnUrl |
| 401 | Unauthorized | Clé API absente, invalide ou révoquée |
| 403 | Forbidden | Origine non autorisée (CORS) ou compte suspendu |
| 404 | Not Found | Transaction introuvable pour ce referenceId et ce projet |
| 409 | Conflict | referenceId déjà utilisé pour ce projet — utilisez un identifiant unique |
| 429 | Too Many Requests | Limite de débit atteinte — attendez avant de réessayer (backoff exponentiel) |
| 500 | Internal Error | Erreur interne — contactez le support si le problème persiste |
| 502 | Bad Gateway | Erreur passerelle de paiement (Bazik) — réessayez dans quelques secondes |
Codes d'erreur structurés (réponse 400)
Au-delà des codes HTTP, certaines réponses 400 incluent un champ code machine-lisible. Utilisez-le pour brancher la logique côté client.
| Nom / Code | Type / Limite | Description |
|---|---|---|
| invalid_request | 400 | Paramètre manquant ou mal formé (amount, referenceId, returnUrl, etc.) |
| amount_below_minimum | 400 | Montant inférieur au minimum (1 HTG côté création, 1 000 HTG côté retrait) |
| invalid_token | 401 | Token OAuth ou clé d'API invalide / expirée (intégrations Connect) |
| insufficient_scope | 403 | Le token n'a pas le scope requis (balance.read, payout.request, etc.) |
| connection_revoked | 403 | Le marchand a révoqué l'accès de votre application (intégrations Connect) |
| connection_not_found | 404 | Aucune connexion active entre votre application et ce marchand |
| insufficient_balance | 402 | Solde marchand insuffisant pour le retrait demandé |
| partner_daily_cap_exceeded | 429 | Plafond journalier de votre application atteint (intégrations Connect) |
| plan_daily_cap_exceeded | 429 | Plafond journalier du plan du marchand atteint |
| rate_limit_exceeded | 429 | Limite de débit dépassée — attendez et réessayez avec backoff |
| auth_unavailable | 503 | Service d'authentification temporairement indisponible — réessayez |
| server_misconfigured | 500 | Erreur de configuration côté MonCashConnect — contactez le support |
| not_found | 404 | Ressource (transaction, payout, connexion) introuvable |
Exemple de réponse d'erreur
{
"error": "referenceId already exists for this project",
"code": "duplicate_reference"
}Le champ code est stable ; le champ error est destiné aux humains et peut être traduit ou reformulé.
Guides complémentaires