Codes d’erreur
Toutes les erreurs de l’API ont la même forme :
{
"error": "message lisible, susceptible d'évoluer",
"code": "CODE_MACHINE_STABLE"
}Programmez contre code, jamais contre error. Certains codes ajoutent des
champs, indiqués ci-dessous. Les codes propres à un endpoint sont aussi listés
sur sa page de référence.
400 — Requête invalide
code | Cause | Que faire |
|---|---|---|
INVALID_BODY | Corps absent ou JSON invalide | Envoyer un JSON valide avec Content-Type: application/json |
VALIDATION_ERROR | Champ manquant ou invalide (transactions, webhooks) | Corriger la requête |
INVALID_AMOUNT | Montant nul, négatif ou non entier | Envoyer un entier XAF > 0 |
INVALID_CURRENCY | Devise autre que XAF | XAF |
INVALID_OPERATOR | Opérateur inconnu | AIRTEL ou MOOV |
REFERENCE_REQUIRED, INVALID_REFERENCE | Référence absente ou trop longue | Fournir votre identifiant de commande |
INVALID_TTL | ttl_minutes hors 1–60 | Ajuster la durée |
INVALID_RETURN_URL | return_url absente du format attendu : adresse https absolue, sans identifiants, 2048 caractères au plus (http://localhost seulement avec une clé de test) | Corriger l’adresse de retour |
INVALID_ID | Identifiant qui n’est pas un UUID | Vérifier l’identifiant |
CUSTOMER_PHONE_REQUIRED | Paiement live sans téléphone du payeur | Fournir customer_phone |
PAYMENT_SESSION_AMOUNT_TOO_LOW, PAYMENT_SESSION_AMOUNT_TOO_HIGH, TRANSACTION_AMOUNT_TOO_LOW, TRANSACTION_AMOUNT_TOO_HIGH | Montant hors des bornes de votre compte | Ajuster le montant ; les bornes se consultent dans le dashboard |
WEBHOOK_URL_UNSAFE | URL de webhook non publique ou non HTTPS pour le live | Utiliser une URL publique en HTTPS |
INVALID_STATUS, INVALID_DATE_FROM, INVALID_DATE_TO, INVALID_DATE_RANGE, INVALID_SEARCH | Filtre de liste invalide | Corriger le filtre |
401 — Non authentifié
code | Cause | Que faire |
|---|---|---|
API_KEY_MISSING | En-tête X-API-Key absent | Ajouter l’en-tête |
API_KEY_INVALID_FORMAT | La clé ne commence ni par kadryza_live_ ni par kadryza_test_ | Vérifier la variable d’environnement |
API_KEY_UNAUTHORIZED | Clé inconnue ou révoquée | Générer une nouvelle clé dans le dashboard |
403 — Non autorisé
code | Cause | Que faire |
|---|---|---|
EMAIL_NOT_VERIFIED | L’e-mail du compte n’est pas vérifié | Valider l’e-mail depuis le lien reçu |
KYC_REQUIRED | Profil marchand incomplet | Compléter le profil dans le dashboard |
API_KEY_PERMISSION_DENIED | La clé n’a pas la portée requise | Utiliser une clé avec la bonne portée |
LIVE_MODE_NOT_ALLOWED | Clé live, mais le mode live n’est pas activé pour le compte | Terminer la checklist go-live |
PAYMENT_SESSION_DAILY_LIMIT_EXCEEDED, DAILY_TRANSACTION_LIMIT_EXCEEDED | Plafond journalier atteint | Réessayer le lendemain (UTC) ou demander un ajustement |
404 — Introuvable
code | Cause |
|---|---|
NOT_FOUND | Ressource inconnue, ou appartenant à un autre compte ou à l’autre environnement (une clé de test ne voit pas les objets live) |
409 — Conflit
code | Cause | Que faire |
|---|---|---|
DUPLICATE_REFERENCE | reference déjà utilisée dans cet environnement | Relire l’objet existant (GET /v1/payment-sessions/by-reference) |
IDEMPOTENCY_CONFLICT | Même référence de Hosted Checkout avec un contenu différent | Utiliser une nouvelle référence |
NOT_CANCELLABLE | Session live, ou session qui n’est plus AWAITING_PAYMENT | Ne pas annuler ; suivre le statut |
OPERATOR_NO_LONGER_AVAILABLE, OPERATOR_SELECTION_CONFLICT, CHECKOUT_CANCELLED, CHECKOUT_NOT_CANCELLABLE | Page de paiement hébergée (détails) | — |
410 — Expiré
code | Cause |
|---|---|
CHECKOUT_EXPIRED | Hosted Checkout expiré avant le choix de l’opérateur |
429 — Trop de requêtes
code | Champs ajoutés | Que faire |
|---|---|---|
RATE_LIMIT_EXCEEDED | retry_after_seconds (et en-tête Retry-After) | Attendre le délai indiqué avant de réessayer |
501 — Non implémenté
code | Cause |
|---|---|
PROVIDER_NOT_IMPLEMENTED | Aucun fournisseur implémenté pour cet opérateur |
502 — Passerelle
code | Cause |
|---|---|
WEBHOOK_TEST_FAILED | Votre endpoint n’a pas répondu 2xx à POST /v1/webhooks/:id/test |
503 — Service indisponible
code | Champs ajoutés | Cause | Que faire |
|---|---|---|---|
PROVIDER_RAIL_NOT_READY | operator, environment, failed_checks | Réseau d’encaissement de l’opérateur indisponible en live | Proposer l’autre opérateur ou réessayer plus tard |
NO_COLLECTION_NUMBER_AVAILABLE | — | Aucun numéro disponible pour cet opérateur | Idem |
PROVIDER_UNAVAILABLE | — | Aucun fournisseur actif pour cet opérateur | Idem |
OPERATOR_AVAILABILITY_UNAVAILABLE | — | Disponibilité des opérateurs invérifiable momentanément | Réessayer |
LEGACY_LIVE_TRANSACTION_DISABLED | — | Création de transaction ou paiement par lien avec une clé live | Utiliser les Payment Sessions |
RATE_LIMIT_UNAVAILABLE | — | Contrôle de débit momentanément indisponible sur une opération sensible | Réessayer avec un délai |
500 — Erreur interne
code | Que faire |
|---|---|
INTERNAL_ERROR | Réessayer avec un délai. Pour une création, relire d’abord par référence : la première tentative a pu aboutir. |
Après un timeout ou une erreur 5xx sur une création, ne recréez pas
aveuglément : relisez par référence. Pour une Payment Session,
GET /v1/payment-sessions/by-reference?reference=… vous dit si elle existe.
Erreurs du SDK Node.js
Le SDK @kadryza/sdk lève des classes d’erreur selon le statut HTTP.
Toutes héritent de KadryzaError et exposent message, code et
statusCode.
| Classe | Statut HTTP | code exposé par le SDK |
|---|---|---|
KadryzaAuthError | 401 | UNAUTHORIZED |
KadryzaValidationError | 400, 422 | VALIDATION_ERROR |
KadryzaNotFoundError | 404 | NOT_FOUND |
KadryzaDuplicateError | 409 | DUPLICATE_REFERENCE |
KadryzaGatewayUnavailableError | 503 | GATEWAY_UNAVAILABLE |
KadryzaNetworkError | — (timeout, DNS, réseau) | NETWORK_ERROR |
KadryzaError | tout autre statut (403, 429, 5xx…) | le code de l’API |
Pour les statuts 400, 401, 404, 409 et 503, le SDK remplace le code
détaillé de l’API par le code générique de la classe : par exemple
PROVIDER_RAIL_NOT_READY devient GATEWAY_UNAVAILABLE, et
NOT_CANCELLABLE est levé comme KadryzaDuplicateError. Le message
d’origine est conservé. Si vous devez distinguer ces cas, appelez l’API HTTP
directement.
import Kadryza, {
KadryzaError,
KadryzaAuthError,
KadryzaValidationError,
KadryzaDuplicateError,
KadryzaGatewayUnavailableError,
KadryzaNetworkError
} from '@kadryza/sdk'
const kadryza = new Kadryza({ apiKey: process.env.KADRYZA_API_KEY! })
try {
const session = await kadryza.paymentSessions.create({
reference: 'order_2026_001',
amount: 5000,
currency: 'XAF',
operator: 'AIRTEL',
customer_phone: '+23566000000'
})
} catch (error) {
if (error instanceof KadryzaDuplicateError) {
// La référence existe déjà : relire plutôt que recréer.
const existing = await kadryza.paymentSessions.retrieveByReference('order_2026_001')
} else if (error instanceof KadryzaGatewayUnavailableError) {
// Opérateur momentanément indisponible : proposer l'autre opérateur.
} else if (error instanceof KadryzaValidationError || error instanceof KadryzaAuthError) {
// Erreur d'intégration : corriger, ne pas réessayer en boucle.
} else if (error instanceof KadryzaNetworkError) {
// Réseau : relire par référence avant toute nouvelle tentative.
} else if (error instanceof KadryzaError) {
console.error(error.statusCode, error.code, error.message)
} else {
throw error
}
}