Documentation API
Intégrez les paiements MonCash dans votre application en quelques minutes.
Base URL — https://toucash.com/api/v1
Authentification
Chaque requête à l'API doit inclure ces 4 headers HTTP :
| Header | Valeur |
|---|---|
X-API-Key | Votre clé publique (tc_live_...) |
X-API-Secret | Votre secret (tc_secret_...) |
X-Timestamp | Timestamp Unix en millisecondes — Date.now() |
X-Signature | HMAC-SHA256 de : timestamp + "." + body JSON |
Le timestamp ne peut pas être plus ancien de 5 minutes. Générez-le au moment de chaque requête avec
Date.now() (JS) ou int(time.time() * 1000) (Python).Exemple complet — initiation + signature :
import crypto from 'crypto';
import axios from 'axios';
const TC_API_KEY = 'tc_live_votre_cle_publique';
const TC_API_SECRET = 'tc_secret_votre_secret_prive';
const BASE_URL = 'https://toucash.com';
function signRequest(body: string) {
const timestamp = Date.now().toString();
const sig = crypto
.createHmac('sha256', TC_API_SECRET)
.update(`${timestamp}.${body}`)
.digest('hex');
return { 'X-Timestamp': timestamp, 'X-Signature': sig };
}
async function initiatePayment(amount: number, metadata?: object) {
const body = JSON.stringify({ amount, metadata });
const res = await axios.post(
`${BASE_URL}/api/v1/payments/initiate`,
body,
{
headers: {
'Content-Type': 'application/json',
'X-API-Key': TC_API_KEY,
'X-API-Secret': TC_API_SECRET,
...signRequest(body),
},
}
);
// Redirigez votre client vers res.data.payment_url
return res.data;
}Initier un paiement
POST
/api/v1/payments/initiateBody JSON
| Champ | Type | Description |
|---|---|---|
amount | number | Montant en HTG (min: 50, max: 500 000) |
metadata | object? | Données libres transmises dans le webhook (produit, client, commande…) |
Réponse (200) :
{
"reference": "TCH-A1B2C3-1716123456789-K9XZ",
"payment_url": "https://moncashbutton.digicelgroup.com/Payment/Startpayment/...",
"amount_total": 5000,
"platform_fee": 50,
"amount_you_receive": 4950,
"expires_at": "2025-05-20T15:30:00Z"
}Redirigez votre client vers payment_url. Après paiement, MonCash redirige vers votre callback et Toucash envoie un webhook.
Vérifier une transaction
GET
/api/v1/payments/:referenceasync function getPayment(reference: string) {
const body = '';
const res = await axios.get(
`${BASE_URL}/api/v1/payments/${reference}`,
{
headers: {
'X-API-Key': TC_API_KEY,
'X-API-Secret': TC_API_SECRET,
...signRequest(body),
},
}
);
return res.data;
}Réponse (200) :
{
"reference": "TCH-A1B2C3-1716123456789-K9XZ",
"status": "completed",
"amount_requested": 5000,
"platform_fee": 50,
"amount_merchant": 4950,
"payer_phone": "50937000000",
"initiated_at": "2025-05-20T14:50:00Z",
"completed_at": "2025-05-20T14:52:00Z",
"metadata": { "product_id": "abc", "customer": "Jean Pierre" }
}Lister les transactions
GET
/api/v1/paymentsQuery params
| Param | Défaut | Description |
|---|---|---|
page | 1 | Numéro de page (pagination) |
limit | 20 | Résultats par page (max: 100) |
status | all | Filtrer : pending · completed · failed |
async function listPayments(page = 1, status?: string) {
const params = new URLSearchParams({ page: String(page) });
if (status) params.set('status', status);
const body = '';
const res = await axios.get(
`${BASE_URL}/api/v1/payments?${params}`,
{
headers: {
'X-API-Key': TC_API_KEY,
'X-API-Secret': TC_API_SECRET,
...signRequest(body),
},
}
);
return res.data; // { data: Transaction[], total, page, per_page }
}Webhooks
Configurez votre URL webhook dans Clés API → Configuration Webhook. Toucash envoie un POST signé à chaque paiement complété.
Payload
{
"event": "payment.completed",
"reference": "TCH-A1B2C3-1716123456789-K9XZ",
"amount_paid": 5000,
"amount_credited": 4950,
"payer_phone": "50937000000",
"metadata": { "product_id": "abc" },
"timestamp": "2025-05-20T14:52:00Z"
}Vérification de la signature X-Toucash-Signature :
import crypto from 'crypto';
// Express example
app.post('/webhook/toucash',
express.raw({ type: '*/*' }),
(req, res) => {
const sig = req.headers['x-toucash-signature'] as string;
const rawBody = req.body.toString();
const expected = crypto
.createHmac('sha256', process.env.WEBHOOK_SECRET!)
.update(rawBody)
.digest('hex');
const valid = crypto.timingSafeEqual(
Buffer.from(sig, 'hex'),
Buffer.from(expected, 'hex')
);
if (!valid) return res.status(403).json({ error: 'Invalid signature' });
const event = JSON.parse(rawBody);
if (event.event === 'payment.completed') {
// Déclenchez la livraison de votre produit/service
await fulfillOrder(event.reference, event.metadata);
}
res.json({ received: true });
}
);Toucash réessaie jusqu'à 5 fois (backoff exponentiel : 2 s, 4 s, 8 s, 16 s, 32 s) si votre endpoint retourne un statut non-2xx. Retournez
200 dès réception.Codes d'erreur
Toutes les erreurs retournent un JSON { "error": "CODE", "message": "..." }.
| Code | HTTP | Description |
|---|---|---|
INVALID_API_CREDENTIALS | 401 | Clé API, secret ou signature invalide |
TIMESTAMP_EXPIRED | 401 | Timestamp trop ancien (fenêtre : 5 min) |
RATE_LIMIT_EXCEEDED | 429 | Plus de 100 requêtes / minute |
AMOUNT_TOO_LOW | 400 | Montant inférieur à 50 HTG |
AMOUNT_TOO_HIGH | 400 | Montant supérieur à la limite configurée |
MERCHANT_NOT_ACTIVE | 403 | Compte non activé (KYC en attente ou rejeté) |
MONCASH_ERROR | 502 | Erreur de communication avec MonCash |
NOT_FOUND | 404 | Référence de transaction introuvable |