Codes d’erreur
Toutes les erreurs de l’API Sangho retournent un objet JSON structuré et plat (aucune clé imbriquée) avec un code d’erreur métier, un message lisible et un lien direct vers la section de cette page qui l’explique. Cliquer sur un lien doc_url reçu depuis votre console ou vos logs vous amène ici et surligne automatiquement la ligne du code concerné.
Structure d’une erreur
| Champ | Type | Requis | Description |
|---|---|---|---|
type | string | Requis | Catégorie de l'erreur — une des 7 valeurs listées ci-dessous. Utile pour un traitement générique (afficher un message par catégorie). |
code | string | Requis | Code métier Sangho précis — ex. AMOUNT_TOO_SMALL. C'est la source de vérité pour la gestion fine des cas d'erreur, à préférer à type et au code HTTP. |
message | string | Requis | Description lisible de l'erreur, en français |
status | integer | Requis | Code HTTP associé — 400, 401, 403, 404, 409, 422, 429, 500 |
doc_url | string | Optionnel | Lien direct vers la ligne de cette page correspondant au code — ex. https://docs.sangho.ga/errors#AMOUNT_TOO_SMALL |
param | string | Optionnel | Champ en cause pour les erreurs de validation (422) |
errors | object | Optionnel | Détail par champ pour les erreurs de validation multi-champs — {`{ "amount": ["..."] }`} |
request_id | string | Optionnel | Identifiant de la requête, à fournir au support en cas de besoin |
Les 7 catégories (type)
Chaque erreur appartient à l’une de ces 7 catégories. Le SDK JavaScript expose la même taxonomie sur err.type — pratique pour un traitement générique par branche (retry, redirection login, etc.) avant de descendre au niveau du code précis si besoin.
| type | Statuts HTTP typiques | Signification |
|---|---|---|
AUTHENTICATION_ERROR | 401 | Clé API absente, invalide ou expirée |
PERMISSION_ERROR | 403 | Identité reconnue, mais action non autorisée (clé publique, compte restreint, plan insuffisant…) |
NOT_FOUND_ERROR | 404 | Ressource introuvable |
CONFLICT_ERROR | 409 | Conflit — idempotency key réutilisée, doublon |
VALIDATION_ERROR | 422 | Requête syntaxiquement correcte mais métier-invalide |
RATE_LIMIT_ERROR | 429 | Quota d'appels dépassé |
API_ERROR | 500 | Erreur côté Sangho |
Codes HTTP standards
Le code HTTP indique la catégorie de l’erreur. Utilisez-le pour orienter votre logique de retry et d’affichage.
| Code | Description |
|---|---|
200 | Succès — requête traitée |
201 | Ressource créée avec succès |
400 | Requête invalide — JSON malformé ou en-têtes incorrects |
401 | Clé API manquante, expirée ou invalide |
403 | Permission insuffisante — l'App n'a pas accès à cette ressource ou cette action |
404 | Ressource introuvable — ID incorrect ou ressource supprimée |
409 | Conflit — idempotency key réutilisée avec un corps de requête différent |
422 | Validation métier échouée — règle business non respectée |
429 | Trop de requêtes — rate limiting atteint, appliquer un backoff |
500 | Erreur interne Sangho — réessayez avec un backoff exponentiel |
Codes métiers
Tous les codes suivent le standard SCREAMING_SNAKE_CASE, sans préfixe. Branchez vos gestionnaires d’erreurs sur code plutôt que sur le statut HTTP — le code est la source de vérité.
Authentification — 401
| Code | Description |
|---|---|
MISSING_API_KEY | Clé API absente — fournissez-la via Authorization: Bearer <clé> |
INVALID_API_KEY | Clé API invalide, révoquée ou mal formée |
EXPIRED_API_KEY | Clé API expirée — générez-en une nouvelle depuis votre dashboard |
INVALID_TOKEN | Token JWT invalide ou expiré |
AUTHENTICATION_FAILED | Échec d'authentification générique — vérifiez le header Authorization |
Autorisation — 403
Ces erreurs sont retournées quand l’identité est reconnue mais que l’opération n’est pas autorisée pour cette clé, ce compte ou ce plan.
| Code | Description |
|---|---|
PERMISSION_DENIED | Permission refusée — votre clé n'est pas autorisée à effectuer cette action sur cette ressource |
PUBLIC_KEY_NOT_ALLOWED | Cette route requiert une clé secrète (sk_prod_ ou sk_test_). N'exposez jamais votre clé secrète côté client |
APP_DISABLED | L'application est désactivée — réactivez-la depuis votre dashboard |
APP_NOT_VERIFIED | Application non vérifiée — KYC en attente d'approbation |
INSUFFICIENT_PERMISSIONS | Permissions insuffisantes pour cette ressource ou action |
SANDBOX_ONLY | Cette route est réservée à l'environnement sandbox — utilisez une clé sk_test_ |
CURRENCY_NOT_IN_PLAN | La devise demandée est active sur Sangho mais n'est pas incluse dans votre plan actuel — passez à un plan supérieur pour l'activer |
COMPANY_BLACKLISTED | Ce compte a été mis en liste noire et n'a plus accès à la plateforme — contactez le support |
COMPANY_PAYMENTS_DISABLED | Les paiements entrants sont actuellement désactivés pour ce compte |
COMPANY_PAYOUTS_DISABLED | Les virements sortants sont actuellement désactivés pour ce compte |
COMPANY_SANDBOX_ONLY | Ce compte est restreint au mode test (sandbox) pour le moment |
COMPANY_KYC_REQUIRED | La vérification KYC est requise avant de pouvoir traiter des paiements |
Le code PERMISSION_DENIED est notamment retourné par POST /v1/reset lorsqu’elle est appelée avec une clé de production (sk_prod_). Cette route efface toutes les données de l’application et n’est accessible qu’en sandbox. Utilisez une clé sk_test_ pour y accéder.
Ressource introuvable — 404
| Code | Description |
|---|---|
NOT_FOUND | Ressource introuvable — ID incorrect, ressource supprimée ou accès interdit |
CUSTOMER_NOT_FOUND | Aucun Customer avec cet identifiant pour cette application |
PRODUCT_NOT_FOUND | Aucun Product avec cet identifiant |
PAYMENT_INTENT_NOT_FOUND | Aucun PaymentIntent avec cet identifiant |
TRANSACTION_NOT_FOUND | Aucune Transaction avec cet identifiant |
REFUND_NOT_FOUND | Aucun Refund avec cet identifiant |
INVOICE_NOT_FOUND | Aucune Invoice avec cet identifiant |
SUBSCRIPTION_NOT_FOUND | Aucune Subscription avec cet identifiant |
CHECKOUT_SESSION_NOT_FOUND | Aucune CheckoutSession avec cet identifiant |
PAYMENT_METHOD_NOT_FOUND | Aucun PaymentMethod avec cet identifiant |
PAYMENT_LINK_NOT_FOUND | Aucun PaymentLink avec cet identifiant |
RECEIPT_NOT_FOUND | Aucun Receipt avec cet identifiant |
WEBHOOK_NOT_FOUND | Aucun Webhook avec cet identifiant |
SEARCH_NO_RESULTS | Aucun résultat pour la recherche — vérifiez le paramètre ?search= |
Conflit — 409
| Code | Description |
|---|---|
IDEMPOTENCY_CONFLICT | Une requête avec la même |
DUPLICATE_EMAIL | Un Customer avec cet email existe déjà pour cette application |
DUPLICATE_SKU | Un Product avec ce SKU existe déjà |
Validation métier — 422
| Code | Description |
|---|---|
VALIDATION_ERROR | Les données fournies sont invalides — consultez le champ errors pour le détail par champ |
MISSING_FIELD | Un champ obligatoire est absent de la requête |
INVALID_FIELD | La valeur d'un champ est incorrecte ou hors des valeurs acceptées |
INVALID_FILTER_PARAM | Un paramètre de filtre (?param=) ne correspond à aucun champ du modèle |
INVALID_CURRENCY | La devise fournie n'est pas un code ISO 4217 reconnu, ou n'est pas activée sur Sangho — voir |
AMOUNT_TOO_SMALL | Montant inférieur au minimum autorisé (100 XAF par défaut) |
AMOUNT_TOO_LARGE | Montant supérieur au plafond autorisé |
INVALID_STATUS_TRANSITION | La transition de statut demandée est interdite (ex. rouvrir une Invoice annulée) |
PAYMENT_INTENT_UNCANCELABLE | Impossible d'annuler ce PaymentIntent dans son statut actuel |
PAYMENT_INTENT_NOT_CONFIRMABLE | Impossible de confirmer ce PaymentIntent dans son statut actuel |
PAYMENT_INTENT_NOT_CAPTURABLE | Impossible de capturer — le statut doit être requires_capture |
CAPTURE_AMOUNT_EXCEEDS_ORIGINAL | Le montant à capturer dépasse le montant original du PaymentIntent |
CHECKOUT_SESSION_EXPIRED | La session de checkout a expiré — demandez au client d'en démarrer une nouvelle |
SUBSCRIPTION_ALREADY_CANCELED | Cette Subscription est déjà annulée et ne peut pas l'être à nouveau |
INVOICE_NOT_DRAFTABLE | Cette Invoice n'est pas dans un état permettant le retour en brouillon |
Rate limiting — 429
| Code | Description |
|---|---|
RATE_LIMIT_EXCEEDED | Quota d'appels API dépassé — consultez le header Retry-After pour la durée d'attente |
TOO_MANY_REQUESTS | Trop de requêtes en simultané depuis cette clé API |
Paiements & Mobile Money
| Code | Description |
|---|---|
INSUFFICIENT_FUNDS | Fonds insuffisants côté acheteur (Mobile Money ou carte) |
PAYMENT_METHOD_NOT_SUPPORTED | Méthode de paiement non activée pour ce compte marchand |
MOBILE_MONEY_TIMEOUT | L'acheteur n'a pas confirmé le paiement dans le délai imparti (généralement 3 min) |
MOBILE_MONEY_REJECTED | L'acheteur a refusé la demande de paiement sur son téléphone |
MOBILE_MONEY_NUMBER_INVALID | Numéro Mobile Money incorrect ou non enregistré chez l'opérateur |
MOBILE_MONEY_LIMIT_REACHED | Plafond journalier ou mensuel de l'opérateur atteint pour ce numéro |
CUSTOMER_BLACKLISTED | Le Customer est dans la liste noire — aucun paiement autorisé |
Webhooks & intégrations
| Code | Description |
|---|---|
WEBHOOK_SIGNATURE_INVALID | Signature HMAC-SHA256 invalide — vérifiez votre webhook secret |
WEBHOOK_ENDPOINT_UNREACHABLE | L'URL webhook ne répond pas — Sangho retentera selon la politique de retry |
TERMINAL_OFFLINE | Le terminal Sangho n'est pas joignable — vérifiez la connexion réseau |
PDF_NOT_AVAILABLE | Le PDF de ce document n'est pas encore généré — réessayez dans quelques instants |
METHOD_NOT_ALLOWED | Méthode HTTP non autorisée sur cet endpoint |
Erreur serveur — 500
| Code | Description |
|---|---|
INTERNAL_ERROR | Erreur interne Sangho — notre équipe a été notifiée. Réessayez avec un backoff exponentiel |
DATABASE_ERROR | Erreur de base de données — temporaire, réessayez dans quelques instants |
UPSTREAM_ERROR | Erreur d'un service tiers (opérateur, passerelle) — réessayez ou contactez le support |
Stratégie de retry recommandée
Toutes les erreurs ne se valent pas. Le SDK JavaScript applique déjà cette logique automatiquement (voir SDK JavaScript) — utile à connaître si vous appelez l’API directement.
| Code HTTP | Action recommandée |
|---|---|
| 400 / 422 | Ne pas réessayer — corriger les paramètres de la requête |
| 401 / 403 | Ne pas réessayer — vérifier la clé API, les permissions ou le plan |
| 404 | Ne pas réessayer — vérifier l'ID de la ressource |
| 409 | Récupérer la réponse idempotente déjà produite — ne pas créer de doublon |
| 429 | Attendre la durée indiquée dans le header Retry-After, puis réessayer |
| 500 | Réessayer avec backoff exponentiel (1s → 2s → 4s → 8s, max 3 tentatives) |
Le header Retry-After est inclus dans toutes les réponses 429. Sa valeur est exprimée en secondes.