Codes d'erreur
Testez le error_code, pas le message : le code est stable, le message peut être reformulé.
Forme d'une erreur
{
"success": false,
"message": "Clé API invalide.",
"error_code": "NGP001",
"legacy_code": "LP001"
}Le champ data est absent des réponses d'erreur. Une intégration qui lit data sans vérifier success plantera sur la première erreur.
| Champ | Type | Présence | Description |
|---|---|---|---|
success | booléen | toujours | false. |
message | chaîne | toujours | Explication lisible, en français. Peut être reformulée : ne la testez pas. |
error_code | chaîne | null | toujours | Code stable du catalogue ci-dessous. Il vaut null pour certains refus métier qui n'ont pas de code dédié — annulation ou remboursement refusé selon le statut de la transaction, URL de webhook déjà déclarée, quota de destinations atteint, livraison non rejouable, virement déjà parti… : lisez alors le statut HTTP (422) et le message. La création d'une clé live avant validation KYC renvoie KYC_REQUIRED (403), hors catalogue NGP. |
legacy_code | chaîne | conditionnel | Ancien code LP…, présent seulement si le code a un équivalent (jusqu'à NGP014 et NGP_VALIDATION). Absent pour NGP015 et suivants, et quand error_code est null. |
errors | objet | NGP_VALIDATION seulement | Messages par champ : { "champ": ["message", …] }. |
Un 429 porte l'en-tête Retry-After (secondes). Les réponses des routes appelables avec la clé secrète portent aussi X-RateLimit-Limit et X-RateLimit-Remaining.
Catalogue
| Code | HTTP | Signification | Quoi faire |
|---|---|---|---|
NGP001 | 401 | Clé API invalide, révoquée ou absente — ou clé secrète envoyée depuis un navigateur. | Vérifier l'en-tête Authorization et le mode de la clé. Une clé secrète passée par un navigateur est à régénérer. Ne pas réessayer. |
NGP002 | 422 | Montant hors bornes (100 – 5 000 000 XOF) ou non entier. | Corriger l'appel. Vérifier que vous n'envoyez pas des centimes. |
NGP003 | 422 / 502 | Opérateur indisponible ou injoignable — en 422, opérateur désactivé sur la plateforme (c'est le cas de wave, mtn et pawapay pour l'instant). | Réessayer plus tard, ou proposer un autre moyen de paiement. |
NGP004 | 422 | Numéro invalide (+225 + 10 chiffres). | Corriger la saisie côté client. |
NGP005 | 422 | Référence déjà utilisée pour un autre montant — paiement, session de checkout ou virement. | Un rejeu doit porter le même montant. Si le montant a changé, utiliser une nouvelle référence. Voir Idempotence. |
NGP006 | 400 | Signature de webhook invalide. | Vérifier le secret et le calcul sur timestamp.corps brut. |
NGP007 | 429 | Quota de requêtes dépassé, ou renvoi de code OTP trop rapproché. | Attendre le délai de Retry-After. Ne pas boucler. |
NGP008 | 404 | Ressource introuvable, ou appartenant à un autre marchand. | Vérifier l'uuid et le compte utilisé. |
NGP009 | 422 | Refusé pour raison de sécurité. | Aucun détail n'est donné, et c'est délibéré. Contacter le support si c'est un faux positif. |
NGP010 | 422 | Opérateur non activé sur votre compte. | L'activer dans « Moyens de paiement ». |
NGP011 | 422 | Plafond mensuel d'un compte particulier atteint (3 000 000 XOF par mois calendaire). | Passer en compte entreprise (sans plafond), ou attendre le mois suivant. |
NGP012 | 422 | Document KYC refusé. | Consulter le motif dans « Activation live (KYC) » et redéposer. |
NGP013 | 422 | Compte de reversement invalide, ou code OTP de vérification invalide ou expiré. | Corriger les coordonnées bancaires ou mobile money, ou redemander un code (5 essais, 10 min). |
NGP014 | 422 | Suppression du compte de reversement refusée. | Ajouter et vérifier un autre compte avant de supprimer le seul compte vérifié. |
NGP015 | 403 | Clé publique sans domaine déclaré. | Renseigner l'origine dans « Clés API », format https://votre-boutique.ci. |
NGP016 | 422 | Solde insuffisant pour ce virement. | Le message dit de combien il manque. Voir Virements sortants. |
NGP017 | 422 | Virement indisponible pour cet opérateur, ou compte de reversement non vérifié. | Interroger GET /payouts/providers pour la liste réelle. |
NGP018 | 422 | Plafond journalier de virement dépassé. | Réessayer demain, ou demander un relèvement au support. |
NGP019 | 422 | Lien de réinitialisation invalide, expiré ou déjà utilisé. | En demander un nouveau depuis « Mot de passe oublié ». |
NGP020 | 403 | Compte marchand suspendu. | Inutile de régénérer une clé : elle recevra la même réponse. Contactez le support. |
NGP021 | 403 | Double authentification requise pour accéder au back-office NguePay. | Concerne les comptes d'administration NguePay ; un compte marchand ne le reçoit pas. |
NGP022 | 401 / 422 | Code de double authentification invalide, expiré ou déjà utilisé — ou mot de passe actuel manquant pour l'activer. | Saisir un nouveau code, ou un code de secours. Voir Double authentification. |
NGP023 | 403 | Action réservée au dashboard, refusée avec une clé API (coordonnées de notification). | Faire la modification depuis le dashboard, connecté. |
NGP_VALIDATION | 422 | Échec de validation des champs. | Lire errors : il détaille chaque champ fautif. |
Erreur de validation détaillée
{
"success": false,
"message": "Données invalides.",
"error_code": "NGP_VALIDATION",
"errors": {
"amount": ["Le montant doit être au moins 100."],
"reference": ["Le champ reference est obligatoire."]
}
}Anciens codes LP
Les codes ont porté le préfixe LP jusqu'au 17 septembre 2026. Chaque réponse d'erreur expose encore l'ancien code dans legacy_code, pour qu'une intégration qui teste LP001 puisse basculer sans coupure.
legacy_code disparaît le 17 mars 2027. La numérotation n'a pas changé : LP007 devient NGP007, jamais autre chose. NGP015 et suivants, nés après le renommage, n'ont pas d'équivalent LP.Gestion des erreurs
const r = await fetch(url, options);
const body = await r.json();
if (!body.success) {
// Testez le code, jamais le message.
if (body.error_code === 'NGP016') return alerterSoldeInsuffisant(body.message);
if (body.error_code === 'NGP003') return reessayerPlusTard();
throw new Error(body.message);
}Que réessayer
| Catégorie | Réessayer ? |
|---|---|
4xx hors 429 | Non — l'appel est à corriger, le rejouer ne changera rien. |
429 | Oui, après le délai indiqué par Retry-After. |
5xx, timeout | Oui, avec un backoff croissant et la même reference. |
Le rejeu avec la même reference est sûr : l'idempotence garantit qu'on n'encaisse — ni ne vire — deux fois.