Aller au contenu

Codes d’erreur

Toutes les erreurs de l’API Sangho retournent un objet JSON structuré avec un code d’erreur métier, un message lisible et un lien vers la documentation. Ne vous fiez jamais uniquement au code HTTP — le champ code est la source de vérité pour la gestion des cas d’erreur.

Structure d’une erreur

ChampTypeRequisDescription
error.codestringRequisCode métier Sangho — ex. SANGHO_INVALID_API_KEY
error.messagestringRequisDescription lisible de l'erreur, en anglais
error.statusintegerRequisCode HTTP associé — 400, 401, 403, 404, 409, 422, 429, 500
error.doc_urlstringOptionnelLien direct vers la section de documentation correspondante
error.paramstringOptionnelChamp en cause pour les erreurs de validation (400 / 422)
error.detailsobjectOptionnelDétails additionnels structurés selon le type d'erreur

Codes HTTP standards

Le code HTTP indique la catégorie de l’erreur. Utilisez-le pour orienter votre logique de retry et d’affichage.

CodeDescription
200Succès — requête traitée
201Ressource créée avec succès
400Requête invalide — paramètre manquant, malformé ou incohérent
401Clé API manquante, expirée ou invalide
403Permission insuffisante — l'App n'a pas accès à cette ressource
404Ressource introuvable — ID incorrect ou ressource supprimée
409Conflit — transaction dupliquée via idempotency key existante
422Validation métier échouée — règle business non respectée
429Trop de requêtes — rate limiting atteint, appliquer un backoff
500Erreur interne Sangho — réessayez avec un backoff exponentiel

Codes métiers Sangho

Chaque code métier correspond à une cause précise. Vos gestionnaires d’erreurs doivent brancher sur error.code plutôt que sur le statut HTTP.

Authentification & autorisation

CodeDescription
SANGHO_INVALID_API_KEYClé API invalide, révoquée ou absente du header Authorization
SANGHO_API_KEY_PREFIX_MISMATCHClé secrète utilisée en mode test sur un endpoint live, ou inversement
SANGHO_KYC_REQUIREDKYC non approuvé — les paiements en production sont bloqués jusqu'à validation
SANGHO_IP_NOT_WHITELISTEDIP source non autorisée — configurez votre SecurityProfile
SANGHO_SCOPE_INSUFFICIENTLa clé API ne dispose pas des permissions requises pour cette action

Paiements & transactions

CodeDescription
SANGHO_INSUFFICIENT_FUNDSFonds insuffisants côté acheteur (Mobile Money ou carte)
SANGHO_PAYMENT_METHOD_NOT_SUPPORTEDMéthode de paiement non activée pour ce compte marchand
SANGHO_AMOUNT_BELOW_MINIMUMMontant inférieur au minimum autorisé pour cette devise et méthode
SANGHO_AMOUNT_ABOVE_MAXIMUMMontant supérieur au maximum autorisé
SANGHO_CURRENCY_NOT_SUPPORTEDDevise non prise en charge sur cette App ou ce marché
SANGHO_PAYMENT_INTENT_EXPIREDLe PaymentIntent a expiré — créez-en un nouveau
SANGHO_PAYMENT_ALREADY_CAPTUREDLa capture a déjà été effectuée sur ce PaymentIntent
SANGHO_REFUND_EXCEEDS_AMOUNTLe montant du remboursement dépasse la transaction d'origine
SANGHO_DUPLICATE_TRANSACTIONTransaction dupliquée — une idempotency key identique existe dans les 24h
SANGHO_CUSTOMER_BLACKLISTEDLe Customer est dans la liste noire — aucun paiement autorisé

Mobile Money

CodeDescription
SANGHO_MOBILE_MONEY_TIMEOUTL'acheteur n'a pas confirmé le paiement dans le délai imparti (généralement 3 min)
SANGHO_MOBILE_MONEY_REJECTEDL'acheteur a refusé la demande de paiement sur son téléphone
SANGHO_MOBILE_MONEY_NUMBER_INVALIDNuméro Mobile Money incorrect ou non enregistré chez l'opérateur
SANGHO_MOBILE_MONEY_LIMIT_REACHEDPlafond journalier ou mensuel de l'opérateur atteint pour ce numéro

Webhooks & intégrations

CodeDescription
SANGHO_WEBHOOK_SIGNATURE_INVALIDSignature HMAC-SHA256 invalide — vérifiez votre webhook secret
SANGHO_WEBHOOK_ENDPOINT_UNREACHABLEL'URL webhook ne répond pas — Sangho retentera selon la politique de retry
SANGHO_TERMINAL_OFFLINELe terminal Sangho n'est pas joignable — vérifiez la connexion réseau

Ressources & rate limiting

CodeDescription
SANGHO_RATE_LIMIT_EXCEEDEDQuota d'appels API dépassé — attendez avant de réessayer (header Retry-After)
SANGHO_RESOURCE_NOT_FOUNDRessource introuvable — vérifiez l'ID et le mode sandbox/live
SANGHO_RESOURCE_DELETEDRessource existante mais supprimée — elle n'est plus modifiable
SANGHO_IDEMPOTENCY_KEY_CONFLICTMême idempotency key utilisée avec des paramètres différents

Stratégie de retry recommandée

Toutes les erreurs ne se valent pas. Appliquez cette logique pour décider de réessayer ou d’abandonner.

Code HTTPAction recommandée
400 / 422Ne pas réessayer — corriger les paramètres de la requête
401 / 403Ne pas réessayer — vérifier la clé API et les permissions
404Ne pas réessayer — vérifier l'ID de la ressource
409Récupérer la réponse idempotente — ne pas créer de doublon
429Attendre la durée indiquée dans le header Retry-After, puis réessayer
500Réessayer avec backoff exponentiel (1s → 2s → 4s → 8s, max 3 tentatives)
Note

Le header Retry-After est inclus dans toutes les réponses 429. Sa valeur est exprimée en secondes.

Structure d’une erreur

Response Réponse — erreur métier
json
{
  "error": {
    "code": "SANGHO_INSUFFICIENT_FUNDS",
    "message": "Le compte Mobile Money ne dispose pas de fonds suffisants.",
    "status": 422,
    "param": null,
    "doc_url": "https://docs.sangho.ga/api/errors#SANGHO_INSUFFICIENT_FUNDS"
  }
}

Erreur de validation (400)

Response Réponse — paramètre invalide
json
{
  "error": {
    "code": "SANGHO_INVALID_PARAMETER",
    "message": "Le champ 'amount' doit être un entier positif.",
    "status": 400,
    "param": "amount",
    "doc_url": "https://docs.sangho.ga/api/errors#SANGHO_INVALID_PARAMETER"
  }
}

Rate limit atteint (429)

Response Réponse — quota dépassé
json
{
  "error": {
    "code": "SANGHO_RATE_LIMIT_EXCEEDED",
    "message": "Trop de requêtes. Réessayez dans 2 secondes.",
    "status": 429,
    "doc_url": "https://docs.sangho.ga/api/errors#SANGHO_RATE_LIMIT_EXCEEDED"
  }
}

Gestion des erreurs — SDKs

bash
# Les erreurs HTTP retournent toujours un JSON structuré
# Capturez le status HTTP et parsez le champ "error"
HTTP_STATUS=$(curl -s -o response.json -w "%{http_code}" \
  -X POST https://api.sangho.com/v1/payment-intents/ \
  -H "Authorization: Bearer sk_test_xxxx" \
  -H "Content-Type: application/json" \
  -d '{"amount": -1, "currency": "XAF"}')


if [ "$HTTP_STATUS" != "200" ] && [ "$HTTP_STATUS" != "201" ]; then
  ERROR_CODE=$(cat response.json | python3 -c "import sys,json; print(json.load(sys.stdin)['error']['code'])")
  echo "Erreur: $ERROR_CODE (HTTP $HTTP_STATUS)"
fi