Erreurs API¶
Le contrat HTTP complet — réponses de succès, réponses d'erreur (4xx / 5xx), localisation des messages et logique de traitement côté client — est documenté dans :
➡️ Contrat de réponses de l'API (référence frontend)
Ce document fait foi pour le frontend. Côté backend, les sources de vérité sont les filtres d'exception (web/exception.http-filter.ts) et les classes d'erreur (domain/errors.ts).
La règle¶
400 → { [champ]: string[] } ; tout autre statut → { message }. La forme du corps se déduit du seul statut, sans inspection.
| Statut | Origine | Forme du corps |
|---|---|---|
400 |
Validation (Zod ou métier), upload refusé, multipart invalide, payload rejetée | { [champ]: string[] } |
401 |
Authentification | { message, code, workspaces? } |
403 |
Autorisation (permissions, workspace suspendu) | { message } |
404 |
Ressource introuvable, ou route inexistante | { message } |
409 |
Conflit (état / unicité) | { message, code? } |
413 |
Fichier trop volumineux | { message } |
429 |
Rate limiting | { message } + Retry-After |
500 |
Erreur serveur | { message } |
501 |
Fonctionnalité non implémentée | { message } |
503 |
Prestataire de paiement / d'intégration injoignable | { message } |
Sur un 400, un problème qui ne porte sur aucun champ (validation croisée, corps vide, multipart invalide) est rangé sous la clé detail.
Alignement en cours
Quelques réponses produites hors de nos filtres — route inexistante, upload trop lourd, multipart invalide, erreur serveur, URL de fichier signée — sortent encore le format brut de NestJS ({ statusCode, message, error? }). Leur alignement sur la règle ci-dessus est suivi par #494.
Pour comprendre comment ces erreurs sont produites côté serveur (classes de domaine, filtres, localisation, cas LedgerError), voir Architecture › Erreurs & i18n.