Bonnes pratiques d'API
Versionner une API, uniformiser les erreurs, comprendre HATEOAS, configurer CORS et documenter avec OpenAPI.
Une API n'est pas seulement un ensemble de routes qui fonctionnent : c'est un contrat public que d'autres équipes vont consommer pendant des années. Ces pratiques évitent de casser leurs clients à chaque évolution.
🏷️ Versionner l'API
Dès qu'une modification casse la compatibilité (champ supprimé, format changé), il faut une nouvelle version.
GET /v1/articles # version dans l'URL, la plus lisible
GET /articles # + en-tête Accept: application/vnd.api.v2+jsonLe versioning par URL (/v1/) est le plus simple à enseigner, à tester et à mettre en cache. Réservez le versioning par en-tête aux API très évolutives.
Ce qui ne casse pas la compatibilité : ajouter un champ optionnel, ajouter une route. Ce qui la casse : renommer un champ, changer un type, rendre un paramètre obligatoire.
⚠️ Un format d'erreur uniforme
Tous les échecs doivent renvoyer la même structure, quelle que soit la route.
{
"erreur": {
"code": "VALIDATION_ECHOUEE",
"message": "Le champ « email » est invalide.",
"details": [{ "champ": "email", "raison": "format" }]
}
}// Middleware d'erreur Express (4 arguments)
app.use((err, req, res, next) => {
const status = err.status ?? 500
res.status(status).json({
erreur: {
code: err.code ?? "ERREUR_INTERNE",
message: status === 500 ? "Erreur interne." : err.message,
},
})
})N'exposez jamais une trace d'exception ou une requête SQL dans la réponse : c'est une fuite d'information exploitable. Journalisez le détail côté serveur, renvoyez un message générique côté client.
🧭 HATEOAS en bref
HATEOAS consiste à joindre à chaque réponse les liens vers les actions possibles, pour que le client navigue sans coder les URLs en dur.
{
"id": 42,
"titre": "REST expliqué",
"_links": {
"self": { "href": "/v1/articles/42" },
"commentaires": { "href": "/v1/articles/42/commentaires" }
}
}C'est le niveau le plus abouti du modèle de maturité de Richardson. Peu d'API l'appliquent intégralement, mais le principe reste utile pour la pagination (liens next et prev).
🌍 CORS
Un navigateur bloque par défaut les requêtes vers une autre origine. Le serveur doit explicitement autoriser les origines légitimes.
npm install corsconst cors = require("cors")
app.use(cors({
origin: ["https://mon-front.fr"],
methods: ["GET", "POST", "PATCH", "DELETE", "OPTIONS"],
credentials: true,
}))origin: "*" combiné à credentials: true est refusé par les navigateurs et constitue une mauvaise pratique de sécurité. Listez les origines autorisées.
🛡️ Sécurité minimale
Valider les entrées
Contrôlez type, longueur et format côté serveur, jamais uniquement côté client.
Limiter le débit
Un rate limiting protège des abus et du bruteforce sur la connexion.
Servir en HTTPS
Sans chiffrement, tokens et mots de passe circulent en clair.
Filtrer les champs renvoyés
Ne renvoyez jamais le hash du mot de passe ni les champs internes.
📖 Documenter avec OpenAPI
OpenAPI (ex-Swagger) décrit l'API dans un fichier YAML ou JSON exploitable par des outils de documentation et de génération de clients.
paths:
/articles/{id}:
get:
summary: Récupérer un article
parameters:
- name: id
in: path
required: true
schema: { type: integer }
responses:
"200": { description: Article trouvé }
"404": { description: Article inexistant }Une documentation générée depuis le code reste à jour ; une documentation rédigée à la main diverge en quelques semaines.
➡️ Suite
La page Consommer et tester montre comment appeler et vérifier votre API.
API REST
Terminez le quiz du chapitre pour le marquer comme complété.
Méthodes et codes de statut
Choisir le bon verbe HTTP et le bon code de réponse : idempotence, familles 2xx à 5xx, en-têtes et négociation de contenu.
Consommer et tester une API
Appeler une API depuis le navigateur ou le terminal, explorer avec un client graphique et automatiser les tests d'endpoints.