Concevoir une API REST
Avant d'écrire du code, il faut concevoir son API : quelles ressources exposer, comment nommer les routes, comment structurer les réponses.
Nommage des ressources
Les URI d'une API REST suivent des conventions :
| Règle | Bon exemple | Mauvais exemple |
|---|---|---|
| Noms (pas de verbes) | /api/v1/ventes | /api/v1/getVentes |
| Pluriel | /api/v1/produits | /api/v1/produit |
| Minuscules | /api/v1/clients | /api/v1/Clients |
| Tirets (pas de underscores) | /api/v1/chiffre-affaires | /api/v1/chiffre_affaires |
| Hiérarchie logique | /api/v1/clients/42/commandes | /api/v1/commandesClient42 |
Pourquoi ces conventions ?
Ces règles rendent l'API prévisible : un développeur qui connaît une route peut deviner les autres.
CRUD et méthodes HTTP
Le mapping entre opérations CRUD et méthodes HTTP :
| Opération | Méthode | URI | Description |
|---|---|---|---|
| Lister | GET | /api/v1/ventes | Toutes les ventes (paginées) |
| Lire | GET | /api/v1/ventes/42 | Une vente spécifique |
| Créer | POST | /api/v1/ventes | Nouvelle vente |
| Remplacer | PUT | /api/v1/ventes/42 | Remplacement complet |
| Modifier | PATCH | /api/v1/ventes/42 | Modification partielle |
| Supprimer | DELETE | /api/v1/ventes/42 | Suppression |
Design d'URI pour une API de données
Pour une API orientée données, on dépasse le CRUD classique :
# CRUD standard
GET /api/v1/ventes # Liste paginée
GET /api/v1/ventes/42 # Détail d'une vente
POST /api/v1/ventes # Créer une vente
# Filtrage et pagination (query parameters)
GET /api/v1/ventes?region=IDF&annee=2024&limit=50&offset=0
# Tri
GET /api/v1/ventes?sort_by=montant&order=desc
# Agrégation (sous-ressources)
GET /api/v1/ventes/stats # Statistiques globales
GET /api/v1/ventes/par-region # Ventes groupées par région
GET /api/v1/ventes/evolution-mensuelle # Évolution dans le temps
# Export
GET /api/v1/ventes?format=csv # Export CSV
Endpoints d'agrégation
Les endpoints d'agrégation (/stats, /par-region) sont des sous-ressources de la collection. Ce n'est pas du CRUD, c'est de l'analytique — détaillé dans la section dédiée.
Versioning
Versionnez l'API dès le départ. La méthode la plus courante : inclure la version dans l'URL.
/api/v1/ventes
/api/v2/ventes # Nouvelle version avec champs différents
Cela permet de faire évoluer l'API sans casser les clients existants. Un dashboard qui consomme /api/v1/ ne doit pas s'arrêter parce que le format de réponse a changé.
Exemple Flask complet
Déclaration des routes pour une ressource ventes avec Flask :
from flask import Flask, Blueprint, request, jsonify
app = Flask(__name__)
# Création du Blueprint
ventes_bp = Blueprint('ventes', __name__, url_prefix='/api/v1/ventes')
@ventes_bp.route('', methods=['GET'])
def lister_ventes():
"""Liste paginée des ventes avec filtres optionnels."""
region = request.args.get('region')
annee = request.args.get('annee', type=int)
limit = request.args.get('limit', 20, type=int)
offset = request.args.get('offset', 0, type=int)
# ... logique de récupération des données ...
return jsonify({
"data": [], # Les ventes
"total": 0, # Nombre total (avant pagination)
"limit": limit,
"offset": offset
})
@ventes_bp.route('/<int:vente_id>', methods=['GET'])
def detail_vente(vente_id):
"""Détail d'une vente par son ID."""
# ... logique de récupération ...
return jsonify({"id": vente_id, "montant": 1500.0})
@ventes_bp.route('/stats', methods=['GET'])
def statistiques_ventes():
"""Statistiques agrégées des ventes."""
# ... logique d'agrégation ...
return jsonify({
"total_ventes": 15000,
"montant_moyen": 250.0,
"nombre_ventes": 60
})
# Enregistrement du Blueprint
app.register_blueprint(ventes_bp)
Blueprint
Un Blueprint Flask est un module de routes. Il permet d'organiser les routes par ressource (un Blueprint pour les ventes, un pour les clients, etc.). Le url_prefix évite de répéter le chemin de base dans chaque route.
Quelle URI est correctement conçue pour récupérer les commandes du client 42 ?
Pourquoi versionner son API dès le départ ?
À retenir
Points clés
- Les URI utilisent des noms au pluriel, en minuscules, avec des tirets
- Le mapping CRUD → HTTP est :
GET(lire),POST(créer),PUT(remplacer),PATCH(modifier),DELETE(supprimer) - Pour les données décisionnelles, on ajoute des endpoints d'agrégation (
/stats,/par-region) et d'export (?format=csv) - Le versioning (
/api/v1/) protège les clients existants lors des évolutions - Un Blueprint Flask regroupe les routes d'une même ressource