MonCashAPIby FedtopupSe connecter

Paiements

Un paiement est une somme qu’un client doit régler sur MonCash. Vous le créez, vous envoyez le client sur payment_url, et votre solde est crédité quand MonCash confirme.

POST/v1/paymentspermission payments:write
curl https://moncashapi.fedtopup.com/api/v1/payments \
  -H "Authorization: Bearer $MONCASHAPI_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: commande-1042" \
  -d '{
    "amount": 1000,
    "reference": "CMD-1042",
    "description": "Commande 1042",
    "return_url": "https://votre-site.com/merci"
  }'
// Côté serveur (Node 18+, Deno, Bun, fonctions « edge »). Jamais dans une page web.
const reponse = await fetch("https://moncashapi.fedtopup.com/api/v1/payments", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.MONCASHAPI_SECRET_KEY}`,
    "Content-Type": "application/json",
    "Idempotency-Key": "commande-1042",
  },
  body: JSON.stringify({
    amount: 1000,
    reference: "CMD-1042",
    description: "Commande 1042",
    return_url: "https://votre-site.com/merci",
  }),
});
const paiement = await reponse.json();
if (!reponse.ok) {
  throw new Error(`${paiement.error.code} — ${paiement.error.request_id}`);
}
// Envoyez votre client vers paiement.payment_url
import express from "express";

const app = express();

app.post("/payer/:commande", async (req, res) => {
  const reponse = await fetch("https://moncashapi.fedtopup.com/api/v1/payments", {
    method: "POST",
    headers: {
      Authorization: `Bearer ${process.env.MONCASHAPI_SECRET_KEY}`,
      "Content-Type": "application/json",
      "Idempotency-Key": `commande-${req.params.commande}`,
    },
    body: JSON.stringify({
      amount: 1000,
      reference: `CMD-${req.params.commande}`,
      return_url: "https://votre-site.com/merci",
    }),
  });
  const paiement = await reponse.json();
  if (!reponse.ok) return res.status(502).json({ erreur: paiement.error.code });
  res.redirect(303, paiement.payment_url);
});
<?php
$ch = curl_init("https://moncashapi.fedtopup.com/api/v1/payments");
curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_TIMEOUT => 20,
    CURLOPT_HTTPHEADER => [
        "Authorization: Bearer " . getenv("MONCASHAPI_SECRET_KEY"),
        "Content-Type: application/json",
        "Idempotency-Key: commande-1042",
    ],
    CURLOPT_POSTFIELDS => json_encode([
        "amount" => 1000,
        "reference" => "CMD-1042",
        "description" => "Commande 1042",
        "return_url" => "https://votre-site.com/merci",
    ]),
]);
$paiement = json_decode(curl_exec($ch), true);
$statut = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

if ($statut >= 400) {
    throw new Exception($paiement["error"]["code"] . " — " . $paiement["error"]["request_id"]);
}
header("Location: " . $paiement["payment_url"], true, 303);
import os
import requests

reponse = requests.post(
    "https://moncashapi.fedtopup.com/api/v1/payments",
    headers={
        "Authorization": f"Bearer {os.environ['MONCASHAPI_SECRET_KEY']}",
        "Idempotency-Key": "commande-1042",
    },
    json={
        "amount": 1000,
        "reference": "CMD-1042",
        "description": "Commande 1042",
        "return_url": "https://votre-site.com/merci",
    },
    timeout=20,
)
paiement = reponse.json()
if not reponse.ok:
    raise RuntimeError(f"{paiement['error']['code']} — {paiement['error']['request_id']}")
print(paiement["payment_url"])  # envoyez votre client à cette adresse

Paramètres

ChampTypeDescription
amountentier, requisMontant que vous recevez, en gourdes entières (de 10 GDS à 75 000 GDS, frais compris pour le maximum).
referencetexteVotre identifiant de commande (120 caractères au plus), unique dans le projet. Renvoyé dans le webhook.
descriptiontexteMotif affiché au client sur la page de paiement (200 caractères au plus).
return_urladresse httpsOù renvoyer le client après le paiement.
customer_phonetexteNuméro haïtien du client (8 chiffres, avec ou sans +509). Optionnel.
metadataobjetVos propres données (4 Ko au plus), renvoyées telles quelles.

L’objet paiement

{
  "id": "pay_3f9c1a7e52b04d6a81c0",
  "object": "payment",
  "status": "pending",
  "amount": 1000,
  "fee": 29,
  "total": 1029,
  "currency": "HTG",
  "reference": "CMD-1042",
  "description": "Commande 1042",
  "customer_phone": null,
  "payment_url": "https://moncashapi.fedtopup.com/payment/pay_3f9c1a7e52b04d6a81c0",
  "return_url": "https://votre-site.com/merci",
  "metadata": {},
  "project_id": "prj_5d2a9c4e1b7f4a0c8e3d6f1a2b4c5d6e",
  "late": false,
  "created_at": "2026-09-30T14:32:07.412Z",
  "expires_at": "2026-09-30T15:02:07.412Z",
  "paid_at": null
}
ChampTypeDescription
amountnombreCe que vous recevez.
feenombreFrais, ajoutés au montant et réglés par le client.
totalnombreCe que le client paie sur MonCash.
payment_urladresseLa page de paiement à ouvrir par le client.
expires_atdateFin de validité du lien (30 minutes après la création).
latebooléenVrai si MonCash a confirmé le paiement après l’expiration du lien : il est crédité quand même.

Frais

Les frais sont de 2,9 % du montant, et le total est arrondi à la gourde supérieure. Exemple pour 1 000 gourdes :

Vous recevez
1 000 GDS
Frais
29 GDS
Le client paie
1 029 GDS

Référence déjà utilisée

Si vous renvoyez la même reference avec le même montant alors que le premier paiement est encore en attente, vous recevez ce même paiement (pas un doublon). Dans les autres cas : 409 REFERENCE_ALREADY_USED.

Si MonCash ne répond pas

La création n’échoue pas pour autant : le paiement est créé en attente, et la page de paiement ouvre MonCash dès qu’il répond. Le client voit « Service temporairement indisponible » et la page réessaie toute seule.

Lister les paiements

GET/v1/paymentspermission payments:read
ChampTypeDescription
limitentierDe 1 à 100 (25 par défaut).
statustextepending, succeeded, failed, expired ou cancelled.
referencetexteVotre référence exacte.
cursortexteLa valeur next_cursor de la page précédente.
{ "object": "list", "data": [ { "id": "pay_…", "object": "payment", … } ],
  "has_more": true, "next_cursor": "1790865127412000_pay_3f9c1a7e52b04d6a81c0" }
Une question sur l’intégration ?