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 :

HeaderValeur
X-API-KeyVotre clé publique (tc_live_...)
X-API-SecretVotre secret (tc_secret_...)
X-TimestampTimestamp Unix en millisecondes — Date.now()
X-SignatureHMAC-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/initiate
Body JSON
ChampTypeDescription
amountnumberMontant en HTG (min: 50, max: 500 000)
metadataobject?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/:reference
async 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/payments
Query params
ParamDéfautDescription
page1Numéro de page (pagination)
limit20Résultats par page (max: 100)
statusallFiltrer : 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": "..." }.

CodeHTTPDescription
INVALID_API_CREDENTIALS401Clé API, secret ou signature invalide
TIMESTAMP_EXPIRED401Timestamp trop ancien (fenêtre : 5 min)
RATE_LIMIT_EXCEEDED429Plus de 100 requêtes / minute
AMOUNT_TOO_LOW400Montant inférieur à 50 HTG
AMOUNT_TOO_HIGH400Montant supérieur à la limite configurée
MERCHANT_NOT_ACTIVE403Compte non activé (KYC en attente ou rejeté)
MONCASH_ERROR502Erreur de communication avec MonCash
NOT_FOUND404Référence de transaction introuvable