Documentation API
L'API ZAFEW vous permet d'accepter des paiements MonCash en HTG depuis votre site ou application. Toutes les requêtes sont en JSON sur HTTPS. Les réponses utilisent les codes HTTP standards.
Comment ZAFEW s'utilise
Deux façons d'encaisser : intégrer cette API avec votre clé (sk_test_ / sk_live_) pour créer des paiements depuis votre site ou application, ou utiliser le QR code et votre espace marchand, sans écrire une ligne de code. Dans tous les cas, votre client paie sur la page MonCash officielle : ZAFEW ne voit jamais son code secret, puis vous reverse le montant net sur votre numéro MonCash.
Cette page décrit le chemin API, destiné aux développeurs.
Authentification
Chaque requête doit inclure votre clé API secrète dans l'en-tête Authorization. Les clés sk_test_ opèrent en sandbox, les clés sk_live_ en production.
Authorization: Bearer sk_test_votre_cle_api
Votre clé API n'est affichée qu'une seule fois à sa création. Stockez-la dans un gestionnaire de secrets, jamais dans votre code source.
Environnements
La sandbox simule tout le cycle de paiement sans argent réel. Les soldes sandbox et production sont strictement séparés. Le passage en production se fait en changeant simplement de clé API, aucun changement de code n'est nécessaire.
En sandbox, la payment_url renvoyée par pay-create ouvre un simulateur de paiement : votre client (ou vous-même) peut y confirmer ou annuler le paiement, exactement comme sur la vraie page MonCash : crédit du solde, webhooks et redirections returnUrl/cancelUrl compris.
| Environnement | Préfixe de clé | Argent réel |
|---|---|---|
| Sandbox | sk_test_ | Non |
| Production | sk_live_ | Oui (KYC requis) |
Créer un paiement
POST /v1/pay-create
Crée un paiement MonCash et retourne l'URL de la page de paiement hébergée vers laquelle rediriger votre client.
Paramètres
| Champ | Type | Description |
|---|---|---|
| amount | décimal | Montant en HTG (max 75 000) |
| referenceId | string | Votre référence de commande |
| returnUrl | URL | Optionnel, retour après succès |
| cancelUrl | URL | Optionnel, retour après annulation |
curl https://zafew.com/v1/pay-create \
-H "Authorization: Bearer sk_test_..." \
-H "Content-Type: application/json" \
-H "Idempotency-Key: cmd-1042" \
-d '{
"amount": "1500.00",
"referenceId": "cmd-1042",
"returnUrl": "https://maboutik.ht/merci"
}'
Réponse 201 :
{
"transaction_id": 87,
"payment_url": "https://.../pay/...",
"status": "pending"
}
Redirection du client (returnUrl / cancelUrl)
Fournissez returnUrl (retour après un paiement réussi) et cancelUrl (retour si le client annule ou en cas d'échec). MonCash y renverra le client, avec orderId et referenceId en paramètres. Si vous ne les fournissez pas, le client est redirigé vers une page de résultat ZAFEW par défaut.
payment_url) contient un jeton à usage unique. Ne le laissez pas traîner comme lien cliquable : certains navigateurs et extensions préchargent les liens, ce qui consomme le jeton (le client verra « session expired »). Redirigez le client immédiatement au moment de payer (window.location = payment_url) ou ouvrez-le uniquement au clic. Un QR code fonctionne toujours (il n'est pas préchargé).
SDK et exemples de code
ZAFEW fournit des SDK officiels pour PHP, Node.js et Python, couvrant toute l'API marchand (paiements, statut, solde, historique, retraits) et la vérification des webhooks. À exécuter côté serveur uniquement (votre clé sk_ ne doit jamais atteindre le navigateur).
Installation
composer require zafew/zafew-php
npm install zafew
pip install zafew
Exemples ci-dessous : créer un paiement et vérifier un webhook. Toutes les méthodes (getPayment, getBalance, listTransactions, withdraw) sont documentées dans le README de chaque SDK.
Avec le SDK — toutes les méthodes
<?php
$client = new \Zafew\Client(getenv("ZAFEW_SECRET_KEY"));
$payment = $client->createPayment([
"amount" => "1500.00", "referenceId" => "cmd-1042",
"returnUrl" => "https://maboutik.ht/merci",
]);
$status = $client->getPayment($payment["transaction_id"]);
$balance = $client->getBalance();
$txns = $client->listTransactions(1);
$payout = $client->withdraw("1000.00");
Sans SDK (HTTP brut) — créer un paiement
<?php
// Créer un paiement — cURL, aucune dépendance
$ch = curl_init("https://zafew.com/v1/pay-create");
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => [
"Authorization: Bearer " . getenv("ZAFEW_SECRET_KEY"),
"Content-Type: application/json",
"Idempotency-Key: cmd-1042",
],
CURLOPT_POSTFIELDS => json_encode([
"amount" => "1500.00",
"referenceId" => "cmd-1042",
"returnUrl" => "https://maboutik.ht/merci",
]),
]);
$res = json_decode(curl_exec($ch), true);
curl_close($ch);
// Rediriger le client IMMÉDIATEMENT (lien à usage unique)
header("Location: " . $res["payment_url"]);
Vérifier la signature d'un webhook
<?php
// Le corps BRUT est requis pour recalculer la signature
$body = file_get_contents("php://input");
$signature = $_SERVER["HTTP_X_ZAFEW_SIGNATURE"] ?? "";
$expected = hash_hmac("sha256", $body, getenv("ZAFEW_WEBHOOK_SECRET"));
if (!hash_equals($expected, $signature)) {
http_response_code(400);
exit("signature invalide");
}
$event = json_decode($body, true);
if ($event["event"] === "payment.succeeded") {
// livrer la commande : $event["data"]["reference_id"]
}
http_response_code(200);
Le corps d'un webhook est {"event": "...", "data": {...}}. Recalculez toujours le HMAC sur le corps brut reçu, jamais sur une version re-sérialisée.
Statut d'un paiement
GET /v1/payments/:transaction_id
Vérifie le statut auprès de MonCash et crédite votre solde si le paiement est confirmé. Ne vous fiez jamais au seul retour navigateur, appelez toujours cet endpoint (ou attendez le webhook) avant de livrer une commande.
{
"transaction_id": 87,
"status": "succeeded",
"amount": "1500.00",
"commission_amount": "37.50",
"net_amount": "1462.50"
}
Statuts possibles : pending, succeeded, failed, cancelled
Exemple de suivi côté client. La clé API reste sur votre serveur : le navigateur interroge votre backend, qui appelle GET /v1/payments/:id avec la clé et ne renvoie que le statut.
const deadline = Date.now() + 10 * 60 * 1000; // 10 min -> session MonCash expirée
async function suivre(id) {
if (Date.now() > deadline) return afficherExpire(); // votre message « session expirée »
// /mon-backend/statut/:id relaie GET /v1/payments/:id (clé API côté serveur)
const { status } = await (await fetch(`/mon-backend/statut/${id}`)).json();
if (status === "succeeded") return afficherPaye();
if (status === "failed" || status === "cancelled") return afficherEchec();
setTimeout(() => suivre(id), 3000); // encore « pending »
}
Solde
GET /v1/merchant/balance
Retourne le solde de l'environnement correspondant à votre clé API.
{
"environment": "sandbox",
"solde_disponible": "1462.50",
"solde_en_attente": "0.00",
"updated_at": "2026-07-10T21:03:33Z"
}
Historique des transactions
GET /v1/merchant/transactions
Liste paginée (25 par page, paramètre ?page=) des transactions de l'environnement de votre clé.
Retraits
Retrait manuel (optionnel)
POST /v1/merchant/withdraw
Transfère une partie de votre solde disponible vers le numéro MonCash configuré sur votre compte. Le montant est réservé immédiatement puis transféré ; en cas d'échec, il est automatiquement recrédité. Des frais de retrait de 10% sont déduits : vous recevez le montant net (net_amount dans la réponse). Minimum 100 HTG, maximum 75 000 HTG par retrait.
curl https://zafew.com/v1/merchant/withdraw \
-H "Authorization: Bearer sk_test_..." \
-d '{"amount": "1000.00"}'
Webhooks
Configurez une URL de webhook dans votre dashboard pour être notifié en temps réel. Chaque livraison est signée : l'en-tête X-Zafew-Signature contient le HMAC-SHA256 (hex) du corps brut, calculé avec votre secret de signature whsec_....
Événements
payment.succeeded: paiement confirmé, solde créditépayment.failed: paiement échouéwithdrawal.completed: retrait transféréwithdrawal.failed: retrait échoué, montant recrédité
Vérifier la signature (Python)
import hashlib, hmac
def verify(body: bytes, signature: str, secret: str) -> bool:
expected = hmac.new(secret.encode(), body, hashlib.sha256).hexdigest()
return hmac.compare_digest(signature, expected)
Répondez 2xx rapidement. Sans réponse, nous retentons avec backoff exponentiel (jusqu'à 6 tentatives).
Idempotence
Passez un en-tête Idempotency-Key unique sur pay-create : en cas de retry réseau, la même transaction est retournée au lieu d'en créer une seconde.
Limites
| Paramètre | Valeur |
|---|---|
| Montant max / transaction | 75 000 HTG |
| Devise | HTG uniquement |
| Commission par paiement (plan Gratuit) | 4,99% |
| Frais de retrait (plan Gratuit) | 8,99% (min 100 HTG, max 75 000 HTG par retrait) |
| Limite de requêtes : création de paiement | 100 requêtes / minute |
| Limite de requêtes : autres endpoints | 300 requêtes / minute |
Les taux ci-dessus sont ceux du plan Gratuit. Les abonnements Pro et Business réduisent la commission et les frais de retrait. Voir les plans
Qui paie les frais ?
Rien ne vous oblige à absorber la commission sur votre marge. La plupart des marchands intègrent leurs frais directement dans leur prix de vente, comme une TVA ou des frais de service affichés au client final. Vos taux exacts dépendent de votre plan (voir la page Tarifs) ; un abonnement les réduit.
Exemple (plan Gratuit, 6%)
Vous voulez toucher 1 000 HTG net par vente après la commission de 6%. Affichez un prix de 1 000 ÷ 0,94 ≈ 1 064 HTG à votre client. Formule générale : divisez le montant voulu par (1 − votre taux de commission).
Sécurité
Avant de passer en mode réel, sécurisez votre intégration : gardez votre clé sk_live_ côté serveur uniquement, vérifiez la signature X-Zafew-Signature de chaque webhook, imposez HTTPS, validez vos entrées, et utilisez un referenceId unique par commande.
Support
Une question ? Rejoignez le groupe Telegram
Posez vos questions d'intégration, signalez un problème et suivez les annonces. L'équipe y répond directement.