6 min lecture • Guide 349 of 877
Meilleures Pratiques de Conception d'API
Une bonne conception d'API facilite la vie des consommateurs et réduit la charge de support. Une mauvaise conception d'API mène à la confusion, aux bugs et aux développeurs frustrés. Ce guide couvre les approches pratiques de conception d'API qui résistent à l'épreuve du temps.
Principes d'API
| Principe | Description | Bénéfice |
|---|---|---|
| Cohérence | Mêmes patterns | Facilité d'apprentissage |
| Prévisibilité | Comportement attendu | Moins de bugs |
| Évolutivité | Changer en sécurité | Longévité |
| Simplicité | Facile à utiliser | Adoption |
Conception RESTful
API Orientée Ressources
CONCEPTION API REST
═══════════════════
RESSOURCES :
─────────────────────────────────────
Penser en noms, pas en verbes :
├── /users (pas /getUsers)
├── /projects (pas /createProject)
├── /tasks (pas /deleteTask)
├── Les ressources sont des choses
└── Les méthodes HTTP sont des actions
OPÉRATIONS CRUD :
─────────────────────────────────────
Méthode HTTP │ Opération │ Exemple
─────────────┼───────────┼──────────────────
GET │ Lire │ GET /users
POST │ Créer │ POST /users
PUT │ Remplacer │ PUT /users/123
PATCH │ Modifier │ PATCH /users/123
DELETE │ Supprimer │ DELETE /users/123
HIÉRARCHIE DES RESSOURCES :
─────────────────────────────────────
Ressources imbriquées :
├── GET /projects/123/tasks
├── POST /projects/123/tasks
├── GET /projects/123/tasks/456
├── Relations claires
└── Hiérarchie logique
STRUCTURE D'URL :
─────────────────────────────────────
Nommage cohérent :
├── Noms pluriels : /users, /tasks
├── Minuscules : /user-profiles
├── Tirets pour mots multiples
├── Pas de slashs finaux
├── Pas d'extensions de fichiers
└── Propre, prévisible
Requête/Réponse
Formatage des Données
CONCEPTION REQUÊTE/RÉPONSE
══════════════════════════
JSON COHÉRENT :
─────────────────────────────────────
Toujours la même structure :
Réponse succès :
{
"data": {
"id": 123,
"name": "Jean Dupont",
"email": "jean@exemple.com"
}
}
Réponse liste :
{
"data": [
{ "id": 123, "name": "Jean" },
{ "id": 124, "name": "Marie" }
],
"meta": {
"total": 100,
"page": 1,
"perPage": 20
}
}
CONVENTIONS DE NOMMAGE :
─────────────────────────────────────
Casse cohérente :
├── camelCase pour JSON : firstName
├── snake_case aussi courant : first_name
├── Choisir un, utiliser partout
├── Correspondre aux conventions du langage
└── La cohérence compte le plus
FILTRAGE DE CHAMPS :
─────────────────────────────────────
Laisser les clients demander les champs :
├── GET /users?fields=id,name,email
├── Réduire le sur-fetching
├── Meilleure performance
├── Approche GraphQL pour REST
└── Optionnel mais utile
Gestion des Erreurs
Messages d'Erreur Clairs
FORMAT D'ERREUR STANDARD
════════════════════════
{
"error": {
"code": "VALIDATION_ERROR",
"message": "La validation a échoué",
"details": [
{
"field": "email",
"message": "Format d'email invalide"
},
{
"field": "name",
"message": "Le nom est requis"
}
]
}
}
CODES HTTP APPROPRIÉS :
─────────────────────────────────────
2xx - Succès
├── 200 OK - GET/PUT/PATCH réussi
├── 201 Created - POST réussi
└── 204 No Content - DELETE réussi
4xx - Erreur Client
├── 400 Bad Request - Entrée invalide
├── 401 Unauthorized - Non authentifié
├── 403 Forbidden - Pas de permission
├── 404 Not Found - Ressource inexistante
├── 409 Conflict - Doublon/conflit
└── 422 Unprocessable - Validation échouée
5xx - Erreur Serveur
└── 500 Internal Server Error - Notre faute
Versioning
Stratégies de Versioning
APPROCHES DE VERSIONING
═══════════════════════
OPTION 1 : DANS L'URL (recommandé)
─────────────────────────────────────
GET /v1/users
GET /v2/users
✅ Explicite et clair
✅ Facile à cacher
✅ Facile à router
❌ Les URLs changent
OPTION 2 : DANS LE HEADER
─────────────────────────────────────
GET /users
Accept: application/vnd.api+json;version=1
✅ URLs stables
✅ Propre
❌ Moins visible
❌ Plus difficile à tester
OPTION 3 : PARAMÈTRE QUERY
─────────────────────────────────────
GET /users?version=1
✅ Simple
❌ Peut être oublié
❌ Moins sémantique
Changements Cassants
ÉVITER LES CHANGEMENTS CASSANTS
═══════════════════════════════
CHANGEMENTS NON-CASSANTS (OK) :
├── Ajouter un nouveau champ
├── Ajouter un nouvel endpoint
├── Ajouter un paramètre optionnel
└── Déprécier (avec délai)
CHANGEMENTS CASSANTS (ATTENTION) :
├── Supprimer un champ
├── Renommer un champ
├── Changer le type d'un champ
├── Changer un paramètre optionnel en requis
└── Changer la structure de réponse
SI CASSANT NÉCESSAIRE :
├── Nouvelle version majeure
├── Période de transition
├── Documentation claire
├── Communication aux consommateurs
└── Support parallèle temporaire
Pagination
Stratégies de Pagination
OPTIONS DE PAGINATION
═════════════════════
OFFSET-BASED :
─────────────────────────────────────
GET /users?page=2&per_page=20
Réponse :
{
"data": [...],
"meta": {
"total": 500,
"page": 2,
"perPage": 20,
"totalPages": 25
}
}
✅ Simple
❌ Problèmes avec données qui changent
CURSOR-BASED :
─────────────────────────────────────
GET /users?cursor=abc123&limit=20
Réponse :
{
"data": [...],
"meta": {
"nextCursor": "def456",
"hasMore": true
}
}
✅ Stable avec données changeantes
✅ Plus performant
❌ Pas de "sauter à la page X"
Documentation
Documentation Complète
DOCUMENTATION API REQUISE
═════════════════════════
POUR CHAQUE ENDPOINT :
├── Méthode et chemin
├── Description claire
├── Paramètres (path, query, body)
├── Headers requis
├── Exemple de requête
├── Réponses possibles (succès + erreurs)
├── Exemples de réponse
└── Authentification requise
OUTILS :
├── OpenAPI/Swagger
├── Postman collections
├── API Blueprint
└── Documentation auto-générée
Sécurité
Pratiques de Sécurité
| Aspect | Bonne Pratique |
|---|---|
| Authentification | OAuth 2.0, JWT |
| Transport | HTTPS uniquement |
| Rate Limiting | Limiter les requêtes |
| Validation | Valider toutes les entrées |
| Permissions | Vérifier l'autorisation |