Skip to content

Erreurs — Public API

Format de réponse d'erreur

Toutes les erreurs renvoient un JSON avec au minimum les champs error (message lisible) et code (énuméré machine).

json
{
  "error": "Permission denied. Required scope: clients:write",
  "code": "PERMISSION_DENIED",
  "required": "clients:write"
}

Champs additionnels possibles selon le code :

  • details (objet) : sortie de zodError.flatten() pour les VALIDATION_FAILED
  • required (string) : scope manquant pour PERMISSION_DENIED
  • retryAfter (number, secondes) : pour RATE_LIMIT_EXCEEDED
  • upgradeUrl (string) : pour PLAN_UPGRADE_REQUIRED

Codes d'erreur énumérés

Source : server/publicApi/types.ts:19-32

HTTPCodeCauseAction
401MISSING_API_KEYHeader x-api-key absent ou ne commence pas par spk_Ajouter le header
401INVALID_API_KEYClé inconnue ou inactiveVérifier la clé / en générer une nouvelle
401EXPIRED_API_KEYClé expirée (expiresAt dépassé)Générer une nouvelle clé
401REVOKED_API_KEYClé révoquée par adminDemander une nouvelle clé
403IP_NOT_ALLOWEDIP appelante absente de l'IP whitelistWhitelister l'IP ou retirer la restriction
403PLAN_UPGRADE_REQUIREDPlan agence n'a pas api_access activéUpgrade du plan (voir upgradeUrl)
403PERMISSION_DENIEDLa clé n'a pas le scope requisRégénérer une clé avec le bon scope
429RATE_LIMIT_EXCEEDEDLimite par minute ou par jour atteinteAttendre retryAfter, voir rate-limiting.md
400VALIDATION_FAILEDBody invalide (Zod)Corriger le payload, voir details
404NOT_FOUNDRessource introuvable ou hors agenceVérifier l'ID
500INTERNAL_ERRORErreur serveur génériqueRéessayer avec backoff, contacter support si persistant
500AUTH_ERRORErreur lors de la résolution de la clé (DB)Réessayer, contacter support si persistant

Exemples par code

401 MISSING_API_KEY

http
GET /api/public/v1/clients
json
{
  "error": "API key required. Provide it in the 'x-api-key' header.",
  "code": "MISSING_API_KEY"
}

403 PERMISSION_DENIED

http
POST /api/public/v1/clients
x-api-key: spk_<key sans clients:write>
json
{
  "error": "Permission denied. Required scope: clients:write",
  "code": "PERMISSION_DENIED",
  "required": "clients:write"
}

400 VALIDATION_FAILED

http
POST /api/public/v1/clients
{ "name": "" }
json
{
  "error": "Données invalides",
  "details": {
    "fieldErrors": {
      "name": ["String must contain at least 1 character(s)"]
    },
    "formErrors": []
  }
}

Note : actuellement les handlers CRM renvoient { error: "Données invalides", details: ... } sans le code VALIDATION_FAILED explicite. Le code énuméré est documenté pour cohérence future.

404 NOT_FOUND

http
GET /api/public/v1/clients/99999
json
{ "error": "Ressource introuvable" }

Multi-tenant : un ID existant mais appartenant à une autre agence renvoie aussi 404 (jamais 403) pour ne pas leak l'existence de la ressource.

429 RATE_LIMIT_EXCEEDED

Voir rate-limiting.md.

500 INTERNAL_ERROR

json
{ "error": "Erreur interne" }

Aucun détail technique n'est exposé (pas de stack trace, pas de message DB). Logs serveur consultables côté admin.

Stratégie de gestion d'erreur côté client

CodeRetry ?Backoff
401 (auth)NonVérifier la config
403 (permission/plan/IP)NonVérifier la config
429 (rate limit)OuiRespecter Retry-After
400 (validation)NonCorriger le payload
404NonVérifier l'ID
500/502/503/504OuiBackoff exponentiel + jitter, max 3-5 tries

Idempotence

Les opérations idempotentes :

  • Toutes les GET
  • DELETE (un 2e DELETE renvoie 404, ce qui est sûr)
  • PUT (remplacement complet — même résultat sur retry)

Les opérations non idempotentes :

  • POST : un retry peut créer un doublon. Pour les imports critiques, vérifiez si la ressource existe avant de créer.

Roadmap : un header Idempotency-Key (UUID v4) est envisagé pour rendre les POST idempotents — pas encore implémenté.

Versionning et stabilité

L'API publique est versionnée dans le path : /api/public/v1/*. Les codes d'erreur ci-dessus font partie du contrat stable. Tout nouveau code sera ajouté à ce document avec sa date d'introduction. Voir changelog.md.

StormeoOS API