API Paiements
Initiez des encaissements, listez les transactions et vérifiez leur statut.
API Paiements
Ces endpoints encaissent et suivent l'état des transactions. Si vous ne voulez pas construire votre propre formulaire de paiement, voyez d'abord Choisir son intégration.
Headers requis
X-Public-Key: YOUR_PUBLIC_KEY
X-Timestamp: UNIX_TIMESTAMP
X-Signature: HMAC_SHA256_SIGNATUREEndpoints
GET /api/v1/paymentsPOST /api/v1/paymentsPOST /api/v1/payments/quoteGET /api/v1/payments/status/{track_id}
Initier un paiement
POST /api/v1/paymentsChamps de requête
| Paramètre | Type | Requis | Description |
|---|---|---|---|
amount | number | Oui | Montant, minimum 1 |
currency | string | Oui | XAF ou XOF |
payer_phone | string | Oui | Numéro du payeur au format E.164 : + puis l'indicatif pays, ex. +237677001122 ou +2250700000001. Seul operator_code: CARD en dispense. |
operator_code | string | Non | Voir Pays et opérateurs. Déduit du numéro s'il est omis. |
external_id | string | Non | Votre référence interne |
return_url | string | Non | Où renvoyer le payeur après un paiement à redirection (carte, Orange/Wave/Djamo en Côte d'Ivoire). Sans elle, le payeur revient sur la page d'accueil de Genuka Pay. |
cancel_url | string | Non | Où le renvoyer en cas d'échec ou d'annulation. À défaut, return_url sert aussi pour l'échec. |
metadata | object | Non | Métadonnées libres |
metadata.description | string | Non | Description de la transaction |
metadata.customer_name | string | Non | Nom du client |
metadata.country | string | Non | Code ISO 2 lettres du payeur. Détermine le corridor et le barème. |
Le format du numéro n'est pas négociable
677001122 est rejeté en 422. L'indicatif est obligatoire : +237677001122. Un numéro sans + n'est jamais complété par défaut — et depuis l'ouverture de la Côte d'Ivoire, il ne pourrait plus l'être sans ambiguïté.
Exemple
curl -X POST "{{BASE_URL}}/api/v1/payments" \
-H "X-Public-Key: YOUR_PUBLIC_KEY" \
-H "X-Timestamp: UNIX_TIMESTAMP" \
-H "X-Signature: HMAC_SHA256_SIGNATURE" \
-H "Content-Type: application/json" \
-d '{
"amount": 1000,
"currency": "XAF",
"payer_phone": "+237677001122",
"external_id": "order_10001",
"return_url": "https://maboutique.com/commandes/10001/merci",
"cancel_url": "https://maboutique.com/commandes/10001/echec",
"metadata": {
"description": "Facture INV-10001"
}
}'Exemple de réponse
{
"data": {
"id": "01HR...",
"reference": "REF_01HR...",
"track_id": "TRX_01HR...",
"amount": 1000,
"currency": "XAF",
"charged_amount": 1000,
"status": "PROCESSING",
"type": "PAYIN",
"operator_code": "MTN_MOMO",
"payer_phone": "+237677001122",
"payer_name": null,
"fee_bearer": "COMPANY",
"provider_fee_amount": 30,
"genuka_fee_amount": 25,
"total_fee_amount": 55,
"net_amount": 945,
"payment_token": "1234567",
"redirect_url": null,
"return_url": "https://maboutique.com/commandes/10001/merci",
"cancel_url": "https://maboutique.com/commandes/10001/echec",
"failure": null,
"created_at": "2026-09-19T10:00:00.000000Z",
"completed_at": null,
"fee_breakdown": {
"provider_fee": { "amount": 30, "currency": "XAF", "rate_applied": "3%" },
"genuka_fee": { "amount": 25, "currency": "XAF", "rate_applied": "3% + 25" },
"fee_bearer": "COMPANY",
"customer_pays": 1000,
"merchant_receives": 945
}
}
}redirect_url dit s'il faut envoyer le payeur quelque part : non-null, redirigez ; null, le client confirme sur son téléphone et vous affichez payment_token. La règle de lecture est dans Choisir son intégration.
return_url et cancel_url vous sont renvoyées telles qu'enregistrées. Une redirect_url non-null avec un return_url à null est le cas à attraper avant qu'un client ne le trouve : le payeur va partir chez l'opérateur sans nulle part où revenir.
Le retour du payeur
Une fois le paiement terminé chez l'opérateur, Genuka Pay ramène le payeur sur votre URL en y ajoutant des paramètres. Ce que vous aviez déjà mis dans l'URL est conservé.
| Paramètre | Toujours | Signification |
|---|---|---|
status | oui | success, failed ou pending |
reference | oui | Le track_id du paiement, à passer à GET /api/v1/payments/status/{track_id} |
token | non | Le jeton du checkout hébergé, quand le paiement en vient |
https://maboutique.com/commandes/10001/merci?status=success&reference=TRX_01HR...status=pending signifie que le navigateur du payeur est revenu avant la notification de l'opérateur — une course normale, pas une erreur.
Ne concluez jamais sur le seul retour
Ces paramètres arrivent par le navigateur du client : ils affichent un écran, ils ne valident pas une commande. Le webhook transaction.success ou GET /api/v1/payments/status/{track_id} restent la seule source de vérité.
Estimer les frais
POST /api/v1/payments/quoteRenvoie le montant exact qui sera débité et ce que vous recevrez, avant tout encaissement. Voir Tarifs et frais.
Vérifier le statut
GET /api/v1/payments/status/{track_id}curl -X GET "{{BASE_URL}}/api/v1/payments/status/TRX_01HR..." \
-H "X-Public-Key: YOUR_PUBLIC_KEY" \
-H "X-Timestamp: UNIX_TIMESTAMP" \
-H "X-Signature: HMAC_SHA256_SIGNATURE"Cet endpoint interroge l'opérateur en direct et met la transaction à jour au passage. Champs renvoyés : transaction_id, track_id, provider_reference, status, provider_status, failure, amount, currency, created_at.
Lister les paiements
GET /api/v1/paymentsNe renvoie que les transactions de l'application authentifiée. Utile pour la réconciliation et le support.
Statuts
| Statut | Description |
|---|---|
INITIATED | Transaction créée, pas encore confirmée par l'opérateur |
PROCESSING | En cours : le payeur doit valider, ou l'opérateur traite |
SUCCESS | Encaissement réussi, montants définitifs |
FAILED | Échec. failure en donne la raison. |
EXPIRED | Sans réponse de l'opérateur dans le délai imparti |
CANCELLED | Annulée avant exécution |
SUCCESS, FAILED, EXPIRED et CANCELLED sont définitifs : une transaction n'en ressort jamais.
Notes
- une tentative dupliquée peut renvoyer une réponse marquée
duplicate; - les limites KYC peuvent bloquer l'initiation — voir Pays et opérateurs ;
- en production, les webhooks font foi ; le polling est un filet de sécurité.
How is this guide?
Last updated on