Hasina Razafintsalama

Hasina RAZAFINTSALAMA

← Retour au Blog
Architecture

Les erreurs classiques d'architecture d'API REST (et comment les corriger)

Après avoir audité de nombreuses codebases, les mêmes erreurs d'API reviennent : exposition du schéma, pas de versioning, erreurs incohérentes, pagination et idempotence manquantes. Voici chacune et sa correction.

2026-04-01·11 min

Après des années à construire et auditer des APIs, certaines erreurs reviennent avec une régularité frappante. Ce ne sont pas des oublis de syntaxe, ce sont des choix architecturaux qui semblent raisonnables au départ et deviennent douloureux à l'échelle. Voici les neuf qui reviennent le plus souvent en audit, chacune avec le signal qui indique que vous l'avez et sa correction.

1. Exposer le schéma de base de données directement

Retourner des lignes brutes de base couple chaque client à votre schéma interne. Renommer une colonne ou diviser une table devient alors un changement cassant de l'API, et des champs internes fuient dans les réponses publiques. Placez une couche de sérialisation (API Resources, DTOs) entre les données et la réponse, et traitez cette couche comme votre contrat publié.

php
// Fait fuir toutes les colonnes, y compris internes
return response()->json($user);

// Contrat contrôlé et stable
class UserResource extends JsonResource {
    public function toArray(Request $request): array {
        return [
            'id' => $this->id,
            'name' => $this->name,
            'created_at' => $this->created_at->toISOString(),
        ];
    }
}

2. Faire l'impasse sur le versioning

Livrer une API sans version signifie que chaque changement cassant est une crise coordonnée. Ajoutez /v1 aux routes dès le premier jour, même pour une API interne. Ça ne coûte rien au départ et ça permet de faire tourner l'ancienne et la nouvelle forme côte à côte pendant que les consommateurs migrent à leur rythme.

3. Des réponses d'erreur incohérentes

Quand chaque endpoint invente sa forme d'erreur, les clients ne peuvent pas gérer les échecs de façon générique et chaque intégration écrit son parsing sur mesure. Adoptez un format pour toute l'API. Les problem details RFC 9457 sont le standard actuel, servis en application/problem+json.

json
// Chaque endpoint fait à sa façon
{ "msg": "not found" }
{ "error_code": 404, "message": "utilisateur inexistant" }

// Une seule forme partout (RFC 9457)
{
  "type": "https://api.exemple.com/errors/not-found",
  "title": "Ressource introuvable",
  "status": 404,
  "detail": "L'utilisateur avec l'id 42 n'existe pas.",
  "instance": "/v1/users/42"
}

4. Bloquer le cycle de requête avec du travail lourd

Génération de rapports, envoi d'emails, appels tiers, traitement d'images : rien de tout cela ne doit bloquer une réponse HTTP. La requête retient un worker, expire sous charge, et le client n'a aucun moyen de réessayer sans risque. Poussez le travail dans une queue, retournez un 202 avec un job ID, et laissez le client interroger un endpoint de statut ou recevoir un webhook à la fin.

5. Des endpoints de liste sans pagination

Un endpoint de liste qui renvoie tout fonctionne bien avec cent lignes et fait tomber le serveur à cent mille. Paginez toujours, avec une taille de page par défaut (20 à 50) et un maximum dur (100). Utilisez la pagination par offset pour les petits jeux de données stables et les écrans d'administration ; utilisez la pagination par curseur pour les listes grandes ou qui changent vite et le défilement infini, pour que des lignes ne soient ni sautées ni répétées quand les données bougent entre deux requêtes.

6. Pas d'idempotence sur les écritures

Un client envoie un POST, le réseau expire, le client réessaie, et il y a maintenant deux commandes. Acceptez un header Idempotency-Key, stockez la première réponse indexée sur cette valeur, et renvoyez la réponse stockée pour toute répétition avec la même clé. Le réessai produit alors un enregistrement, pas deux.

json
POST /v1/orders
Idempotency-Key: 8e03978e-40d5-43e8-bc93-6894a57f9324
Content-Type: application/json

{ "customer_id": 42, "amount": 1990 }

7. Pas de rate limiting sur les endpoints publics

Sans rate limiting, un client mal élevé ou un scraper dégrade le service pour tout le monde, et il n'y a aucune contre-pression face aux tentatives de force brute sur les endpoints d'auth. Appliquez un limiteur par clé d'API et par IP, retournez un 429 avec un header Retry-After, et fixez des limites plus strictes sur les routes coûteuses ou sensibles.

8. Des secrets dans les paramètres de requête

Les tokens et clés d'API dans l'URL finissent dans les logs serveur, les logs de proxy, l'historique du navigateur et les headers Referer. Envoyez les identifiants dans le header Authorization, et gardez tout ce qui est sensible hors de la query string et du chemin.

9. Pas de documentation d'API

Une API sans contrat documenté force chaque consommateur à lire votre code source ou à deviner. Générez une description OpenAPI depuis le code pour qu'elle ne puisse pas dériver de l'implémentation, et publiez-la. La plupart des frameworks le font avec un seul package.

Récapitulatif

ErreurSignal que vous l'avezCorrection
Exposition du schémaUne migration casse un clientResources ou DTOs comme contrat
Pas de versioningChaque changement demande une release coordonnéePréfixe /v1 dès le premier jour
Erreurs incohérentesChaque intégration parse les erreurs à sa façonProblem details RFC 9457 partout
Travail bloquantTimeouts sous charge, endpoints lentsQueue plus job ID plus webhook ou polling
Pas de paginationUn endpoint renvoie des milliers de lignesTaille par défaut et max, curseur pour les grandes listes
Pas d'idempotenceLes réessais créent des doublonsHeader Idempotency-Key, réponse stockée
Pas de rate limitingUn client dégrade tout le serviceLimiteur par clé et par IP, 429 plus Retry-After
Secrets dans l'URLTokens visibles dans les logs et l'historiqueHeader Authorization uniquement
Pas de documentationLes consommateurs lisent votre code sourceOpenAPI généré depuis le code

Aucune de ces erreurs n'est difficile à corriger une fois nommée. La partie coûteuse, c'est de les rattraper sur une API qui a déjà des clients, ce qui est exactement pourquoi elles ont leur place dans la première version.

FAQ

Quelle est l'erreur d'architecture API la plus fréquente ?
Retourner des lignes de base directement depuis le contrôleur. Ça paraît efficace, mais ça couple chaque client à votre schéma, donc une migration de routine devient un changement cassant. Une couche de sérialisation entre les données et la réponse est l'habitude à plus forte valeur.
Faut-il versionner une API interne ?
Oui, même si c'est seulement /v1. Les clients internes cassent aussi quand le contrat change, et un préfixe de version ne coûte rien à ajouter au départ. Il permet de faire tourner l'ancienne et la nouvelle forme côte à côte pendant que les consommateurs migrent.
Pagination par offset ou par curseur ?
L'offset convient aux petits jeux de données stables et aux écrans d'administration où l'utilisateur saute à une page. La pagination par curseur est correcte pour les listes grandes ou qui changent souvent et le défilement infini, car elle ne saute ni ne répète de lignes quand les données bougent entre deux requêtes.
Comment rendre un endpoint POST idempotent ?
Acceptez un header Idempotency-Key, stockez la première réponse indexée sur cette valeur, et renvoyez la réponse stockée pour toute répétition avec la même clé. Une requête réessayée après un timeout réseau produit alors un enregistrement, pas deux.
RFC 7807 ou RFC 9457 pour les réponses d'erreur ?
RFC 9457 est le standard actuel ; elle rend obsolète et remplace RFC 7807 avec la même forme application/problem+json et quelques clarifications. Les nouvelles APIs devraient citer 9457. Les réponses 7807 existantes n'ont pas besoin de changer.

La plupart de ces erreurs sont des décisions, pas des accidents, et chacune est peu coûteuse à bien faire au départ et chère à corriger plus tard. Quand vous concevez la première version d'une API, parcourez cette liste une fois avant de la livrer.

Besoin d'aide sur ce sujet ? Conception d'API REST

Découvrir ce service