Erreurs
Toutes les erreurs partagent la même forme : error (code machine stable), message (français, destiné à un humain, peut changer sans préavis) et code (le statut HTTP). Branchez vos tests sur error, jamais sur message.
Chaque page d'endpoint indique lesquelles de ces réponses elle peut renvoyer, avec le statut HTTP correspondant.
Requête invalide
Code machine
validation_errorUn champ du corps ne respecte pas son contrat (422).
Langage : json{ "error": "validation_error", "type": "invalid_request", "message": "Le montant minimum est de 100 XPF.", "code": 422 }Code machine
bad_requestCorps absent ou illisible, paramètre de requête hors bornes (400).
Langage : json{ "error": "bad_request", "type": "invalid_request", "message": "Corps JSON invalide.", "code": 400 }Code machine
invalid_cursorCurseur de pagination qui ne se résout pas (400).
Langage : json{ "error": "invalid_cursor", "type": "invalid_request", "message": "Le curseur « starting_after » ne désigne aucun élément de cette collection : « 8f14e45f-ceea-4c1a-9b7d-2a3f6c8e01b4 ». Reprenez le parcours depuis le début.", "code": 400 }Code machine
missing_idempotency_keyEn-tête
Idempotency-Keyabsent sur une opération qui l'exige (400).
Langage : json{ "error": "missing_idempotency_key", "type": "invalid_request", "message": "Header Idempotency-Key obligatoire.", "code": 400 }
errorchaînerequisCode machine stable, en snake_case anglais.
- valeurs : invalid_request, authentication, permission, not_found, conflict, idempotency, rate_limit, provider, api
typechaînerequisClasse de l'erreur, dans un ensemble fermé.
invalid_request: l'appel est mal formé ou hors bornes, corrigez la requête.authentication: aucune identité valide.permission: identité valide, opération refusée.not_found: la ressource n'existe pas, ou pas pour vous.conflict: l'état courant interdit l'opération, ne retentez pas à l'identique.idempotency: le refus porte sur la clé d'idempotence, pas sur la requête.rate_limit: trop d'appels.provider: le prestataire bancaire a refusé ou n'a pas répondu.api: incident de notre côté, rien à corriger chez vous.
messagechaînerequisDestiné à un humain, toujours en français.
codeentierrequisStatut HTTP, repris dans le corps par commodité.
Version d'API inconnue
Code machine
unsupported_versionL'en-tête
Tupay-Versiondésigne une version non publiée. Reprise : employez une version de la liste, ou retirez l'en-tête pour laisser s'appliquer celle de votre clé.
Langage : json{ "error": "unsupported_version", "type": "invalid_request", "message": "Version d’API inconnue. Versions publiées : 2026-01-01.", "code": 400 }
errorchaînerequisCode machine stable, en snake_case anglais.
- valeurs : invalid_request, authentication, permission, not_found, conflict, idempotency, rate_limit, provider, api
typechaînerequisClasse de l'erreur, dans un ensemble fermé.
invalid_request: l'appel est mal formé ou hors bornes, corrigez la requête.authentication: aucune identité valide.permission: identité valide, opération refusée.not_found: la ressource n'existe pas, ou pas pour vous.conflict: l'état courant interdit l'opération, ne retentez pas à l'identique.idempotency: le refus porte sur la clé d'idempotence, pas sur la requête.rate_limit: trop d'appels.provider: le prestataire bancaire a refusé ou n'a pas répondu.api: incident de notre côté, rien à corriger chez vous.
messagechaînerequisDestiné à un humain, toujours en français.
codeentierrequisStatut HTTP, repris dans le corps par commodité.
Opération interdite dans ce contexte
Code machine
forbiddenIdentité valide, mais l'opération lui est refusée.
Langage : json{ "error": "forbidden", "type": "permission", "message": "Accès refusé.", "code": 403 }
errorchaînerequisCode machine stable, en snake_case anglais.
- valeurs : invalid_request, authentication, permission, not_found, conflict, idempotency, rate_limit, provider, api
typechaînerequisClasse de l'erreur, dans un ensemble fermé.
invalid_request: l'appel est mal formé ou hors bornes, corrigez la requête.authentication: aucune identité valide.permission: identité valide, opération refusée.not_found: la ressource n'existe pas, ou pas pour vous.conflict: l'état courant interdit l'opération, ne retentez pas à l'identique.idempotency: le refus porte sur la clé d'idempotence, pas sur la requête.rate_limit: trop d'appels.provider: le prestataire bancaire a refusé ou n'a pas répondu.api: incident de notre côté, rien à corriger chez vous.
messagechaînerequisDestiné à un humain, toujours en français.
codeentierrequisStatut HTTP, repris dans le corps par commodité.
Ressource inexistante, hors de votre périmètre, ou appartenant à l'AUTRE MODE. Nous renvoyons 404 plutôt que 403 pour ne pas confirmer l'existence de ce qui ne vous appartient pas.
Code machine
not_foundInexistante, ou appartenant à un autre marchand.
Langage : json{ "error": "not_found", "type": "not_found", "message": "Ressource introuvable.", "code": 404 }
errorchaînerequisCode machine stable, en snake_case anglais.
- valeurs : invalid_request, authentication, permission, not_found, conflict, idempotency, rate_limit, provider, api
typechaînerequisClasse de l'erreur, dans un ensemble fermé.
invalid_request: l'appel est mal formé ou hors bornes, corrigez la requête.authentication: aucune identité valide.permission: identité valide, opération refusée.not_found: la ressource n'existe pas, ou pas pour vous.conflict: l'état courant interdit l'opération, ne retentez pas à l'identique.idempotency: le refus porte sur la clé d'idempotence, pas sur la requête.rate_limit: trop d'appels.provider: le prestataire bancaire a refusé ou n'a pas répondu.api: incident de notre côté, rien à corriger chez vous.
messagechaînerequisDestiné à un humain, toujours en français.
codeentierrequisStatut HTTP, repris dans le corps par commodité.
État incompatible avec l'opération
Code machine
conflictL'état courant de la ressource interdit l'opération.
Langage : json{ "error": "conflict", "type": "conflict", "message": "Cette transaction est déjà intégralement remboursée.", "code": 409 }Code machine
idempotency_key_reuseClé déjà employée pour une AUTRE requête (409). Reprise : choisissez une nouvelle clé. Aucun des deux corps n'a été appliqué.
Langage : json{ "error": "idempotency_key_reuse", "type": "idempotency", "message": "Cette clé d’idempotence a déjà servi pour une requête différente. Choisissez-en une nouvelle : rejouer une clé ne vaut que pour la requête exacte qui l’a créée.", "code": 409 }Code machine
idempotency_in_progressUne requête portant la même clé est encore en cours (409). Reprise : retentez la même requête à l'identique dans un instant. Aucune seconde ressource n'a été créée.
Langage : json{ "error": "idempotency_in_progress", "type": "idempotency", "message": "Une requête portant cette clé est encore en cours. Retentez le même appel, avec la même clé, dans un instant.", "code": 409 }
errorchaînerequisCode machine stable, en snake_case anglais.
- valeurs : invalid_request, authentication, permission, not_found, conflict, idempotency, rate_limit, provider, api
typechaînerequisClasse de l'erreur, dans un ensemble fermé.
invalid_request: l'appel est mal formé ou hors bornes, corrigez la requête.authentication: aucune identité valide.permission: identité valide, opération refusée.not_found: la ressource n'existe pas, ou pas pour vous.conflict: l'état courant interdit l'opération, ne retentez pas à l'identique.idempotency: le refus porte sur la clé d'idempotence, pas sur la requête.rate_limit: trop d'appels.provider: le prestataire bancaire a refusé ou n'a pas répondu.api: incident de notre côté, rien à corriger chez vous.
messagechaînerequisDestiné à un humain, toujours en français.
codeentierrequisStatut HTTP, repris dans le corps par commodité.
100 req/min par marchand dépassées
Code machine
rate_limit_exceededPlafond de requêtes atteint. Réessayez après une pause.
Langage : json{ "error": "rate_limit_exceeded", "type": "rate_limit", "message": "Trop de requêtes. Réessayez dans un instant.", "code": 429 }
errorchaînerequisCode machine stable, en snake_case anglais.
- valeurs : invalid_request, authentication, permission, not_found, conflict, idempotency, rate_limit, provider, api
typechaînerequisClasse de l'erreur, dans un ensemble fermé.
invalid_request: l'appel est mal formé ou hors bornes, corrigez la requête.authentication: aucune identité valide.permission: identité valide, opération refusée.not_found: la ressource n'existe pas, ou pas pour vous.conflict: l'état courant interdit l'opération, ne retentez pas à l'identique.idempotency: le refus porte sur la clé d'idempotence, pas sur la requête.rate_limit: trop d'appels.provider: le prestataire bancaire a refusé ou n'a pas répondu.api: incident de notre côté, rien à corriger chez vous.
messagechaînerequisDestiné à un humain, toujours en français.
codeentierrequisStatut HTTP, repris dans le corps par commodité.
Le prestataire bancaire a refusé l'opération
Code machine
bad_gatewayRefus venu du prestataire, pas de Tupay. Reprise : réessayez.
errorvalait autrefois le code du prestataire lui-même (card_declined,insufficient_funds…). Il vaut désormais toujoursbad_gateway, et le code d'origine part dansproviderCode. Ce champ est OBSERVABLE mais pas stable : il ne fait pas partie de notre contrat, ne branchez pas dessus.
Langage : json{ "error": "bad_gateway", "type": "provider", "message": "Le prestataire bancaire n’a pas pu traiter la demande. Réessayez dans un instant ; si le refus persiste, le code du prestataire est indiqué dans « providerCode ».", "code": 502, "providerCode": "card_declined" }
errorchaînerequisCode machine stable, en snake_case anglais.
- valeurs : invalid_request, authentication, permission, not_found, conflict, idempotency, rate_limit, provider, api
typechaînerequisClasse de l'erreur, dans un ensemble fermé.
invalid_request: l'appel est mal formé ou hors bornes, corrigez la requête.authentication: aucune identité valide.permission: identité valide, opération refusée.not_found: la ressource n'existe pas, ou pas pour vous.conflict: l'état courant interdit l'opération, ne retentez pas à l'identique.idempotency: le refus porte sur la clé d'idempotence, pas sur la requête.rate_limit: trop d'appels.provider: le prestataire bancaire a refusé ou n'a pas répondu.api: incident de notre côté, rien à corriger chez vous.
messagechaînerequisDestiné à un humain, toujours en français.
codeentierrequisStatut HTTP, repris dans le corps par commodité.