REST API design - 02 - Des URLs qui ont du sens

Comment désigner des URLs REST propres : noms au pluriel, hiérarchie, kebab-case et query params.

  1. 01 REST API design - 00 - Pourquoi le design de ton API change tout
  2. 02 REST API design - 01 - Les principes REST que personne ne lit
  3. 03 REST API design - 02 - Des URLs qui ont du sens
  4. 04 REST API design - 03 - Les méthodes HTTP, pour de vrai
  5. 05 REST API design - 04 - Les codes de statut HTTP qu'il faut connaître
  6. 06 REST API design - 05 - Body, headers et le diable dans les détails
  7. 07 REST API design - 06 - La pagination, ou comment ne pas tuer ta base
  8. 08 REST API design - 07 - Filtrage et tri sans prise de tête
  9. 09 REST API design - 08 - La validation avec Zod, gardien de ton API
  10. 10 REST API design - 09 - Erreurs : un format que tes clients vont adorer
  11. 11 REST API design - 10 - Authentification : JWT, API keys et OAuth2
  12. 12 REST API design - 11 - Versioning : quand et comment faire évoluer ton API
  13. 13 REST API design - 12 - CORS : comprendre et debugger les erreurs cross-origin
  14. 14 REST API design - 13 - Rate limiting : protéger ton API sans frustrer tes clients
  15. 15 REST API design - 14 - Caching : les bonnes réponses sont celles qu'on n'envoie pas
  16. 16 REST API design - 15 - Upload de fichiers : multipart, signed URLs et streaming
  17. 17 REST API design - 16 - Relations entre ressources : embarquer, lier ou les deux
  18. 18 REST API design - 17 - HATEOAS : des liens dans tes réponses
  19. 19 REST API design - 18 - OpenAPI : le contrat entre ton API et le monde
  20. 20 REST API design - 19 - Documentation : une API non documentee est une API inutile
  21. 21 REST API design - 20 - Testing : tester ton API sans devenir fou
  22. 22 REST API design - 21 - Webhooks : quand c'est ton API qui appelle
  23. 23 REST API design - 22 - Performance : quand chaque milliseconde compte
  24. 24 REST API design - 23 - Sécurité : les attaques que tu vas subir (et comment t'en protéger)
  25. 25 REST API design - 24 - Glossaire : tous les termes REST API en un seul endroit

02 - Des URLs qui ont du sens

Ce que tu vas apprendre

  • Pourquoi les URLs REST utilisent des noms et pas des verbes
  • Les conventions de nommage : pluriel, kebab-case, hiérarchie
  • Comment structurer les query params pour le filtrage
  • Des exemples concrets tires de vraies API

Prerequisites


L'URL, c'est ton contrat

J'ai bosse sur une API ou les endpoints ressemblaient a ca : /api/getUserById, /api/createNewOrder, /api/deleteProductFromCart. Le dev qui l'avait écrite etait parti depuis six mois. Personne ne savait si deleteProductFromCart faisait un soft delete ou un hard delete. Et personne n'osait regarder.

Une bonne URL REST, c'est comme une bonne adresse postale : tu sais ce que tu vas trouver avant d'ouvrir la porte. L'URL identifié une ressource. La méthode HTTP dit ce que tu veux en faire. Melanger les deux, c'est le début des problèmes.

Des noms, pas des verbes

La regle numero un : tes URLs representent des ressources (des noms), pas des actions (des verbes). L'action, c'est la méthode HTTP qui la porte.

http# Mauvais : verbes dans l'URL
GET  /api/getUsers
POST /api/createUser
POST /api/deleteUser/42
GET  /api/fetchOrdersByUser/42

# Bon : noms au pluriel + methodes HTTP
GET    /api/users          # lister les utilisateurs
POST   /api/users          # creer un utilisateur
DELETE /api/users/42       # supprimer un utilisateur
GET    /api/users/42/orders  # commandes d'un utilisateur

La seule exception acceptable, c'est quand tu modèles une action qui n'est pas du CRUD. Par exemple /api/users/42/activate ou /api/orders/99/cancel. Certains puristes n'aiment pas, mais c'est pragmatique et lisible.

Toujours au pluriel

Utilise le pluriel pour tes collections, meme quand tu accedes a un seul élément.

httpGET /api/users       # la collection
GET /api/users/42    # un element de la collection

Pourquoi pas le singulier pour un élément ? Parce que /api/user/42 et /api/users creent une inconsistance. Tu dois retenir deux formes. Avec le pluriel partout, c'est previsible.

J'ai vu un projet ou certains endpoints etaient au singulier et d'autres au pluriel. Le frontend avait des constantes USER_ENDPOINT et USERS_ENDPOINT partout. Un cauchemar de maintenance.

Hiérarchie et relations

Les URLs REST sont hierarchiques. Elles refletent les relations entre ressources.

http# Un utilisateur
GET /api/users/42

# Les commandes de cet utilisateur
GET /api/users/42/orders

# Une commande specifique de cet utilisateur
GET /api/users/42/orders/99

# Les articles de cette commande
GET /api/users/42/orders/99/items

En TypeScript, ca donne un router Express assez lisible :

typescriptconst router = express.Router();

router.get("/api/users/:userId/orders", async (req, res) => {
  const { userId } = req.params;
  const orders = await orderService.findByUser(userId);
  res.json(orders);
});

router.get("/api/users/:userId/orders/:orderId", async (req, res) => {
  const { userId, orderId } = req.params;
  const order = await orderService.findOne(userId, orderId);

  if (!order) {
    return res.status(404).json({ error: "Order not found" });
  }

  res.json(order);
});

Ne dépassé pas 3 niveaux de profondeur. /api/users/42/orders/99/items/5/reviews c'est trop. A ce stade, fais un endpoint /api/reviews?itemId=5 a la place.

Kebab-case pour les URLs

http# Bon : kebab-case
GET /api/order-items
GET /api/user-profiles

# Mauvais : camelCase ou snake_case
GET /api/orderItems
GET /api/user_profiles

Les URLs ne sont pas sensibles a la casse partout, et le kebab-case est la convention du web. C'est aussi plus lisible dans un navigateur.

Les query params pour filtrer

L'URL identifié la ressource. Les query parameters servent a filtrer, trier, paginer.

http# Filtrer les utilisateurs actifs
GET /api/users?status=active

# Filtrer + trier
GET /api/users?status=active&sort=createdAt

# Paginer
GET /api/users?page=2&limit=20

# Rechercher
GET /api/users?search=alice

# Combiner
GET /api/users?status=active&role=admin&sort=-createdAt&page=1&limit=10

En TypeScript avec Express :

typescriptrouter.get("/api/users", async (req, res) => {
  const { status, role, sort, page = "1", limit = "20" } = req.query;

  const filters = {
    ...(status && { status: String(status) }),
    ...(role && { role: String(role) }),
  };

  const users = await userService.findAll({
    filters,
    sort: String(sort || "createdAt"),
    page: Number(page),
    limit: Math.min(Number(limit), 100), // cap a 100
  });

  res.json(users);
});

On detaillera la pagination dans l'article 06 et le filtrage dans l'article 07.

Quelques conventions que j'applique systématiquement

  1. Prefix /api ou /api/v1 : séparé l'API du frontend
  2. Pas de trailing slash : /api/users et pas /api/users/
  3. Pas d'extension : /api/users et pas /api/users.json
  4. IDs dans le path : /api/users/42 et pas /api/users?id=42
  5. Pas de verbes sauf pour les actions : /api/users/42/activate OK, /api/getUser/42 non

Tu trouveras des exemples concrets et des conventions d'équipe sur paltemps.fr.

Résumé

  • Les URLs REST identifient des ressources avec des noms au pluriel, pas des verbes
  • La hiérarchie reflete les relations : /users/42/orders
  • Kebab-case pour les URLs, pas de trailing slash, pas d'extension
  • Les query params servent au filtrage, tri et pagination
  • Ne dépassé pas 3 niveaux de profondeur dans la hiérarchie

Precedent : Les principes REST | Suivant : Les méthodes HTTP

Sources

Réservez un audit gratuit de 30 minutes. Je vous montre concrètement ce qu'on peut automatiser.