Formats de Réponse API : Bonnes Pratiques pour des APIs Cohérentes
Les réponses API incohérentes sont l'une des principales plaintes des développeurs frontend. Quand chaque endpoint renvoie des données dans une forme différente, le code client se retrouve truffé de cas particuliers. Un format de réponse cohérent améliore l'expérience développeur, réduit les bugs et rend votre API auto-documentée.
L'Enveloppe de Réponse
Encapsulez chaque réponse dans une structure cohérente :
SuccĂšs (Ressource Unique)
{
"data": {
"id": "user_123",
"name": "Alice",
"email": "alice@example.com",
"createdAt": "2024-01-15T10:30:00Z"
},
"meta": {
"requestId": "req_abc123"
}
}
SuccĂšs (Collection)
{
"data": [
{ "id": "user_123", "name": "Alice" },
{ "id": "user_456", "name": "Bob" }
],
"meta": {
"total": 142,
"page": 1,
"perPage": 20,
"requestId": "req_def456"
}
}
Erreur
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Request validation failed",
"details": [
{ "field": "email", "message": "Invalid email format" }
]
},
"meta": {
"requestId": "req_ghi789"
}
}
Le principe clĂ© : les clients vĂ©rifient toujours la prĂ©sence de data ou error au niveau supĂ©rieur. Ne mĂ©langez jamais les donnĂ©es de succĂšs et les informations d'erreur dans la mĂȘme rĂ©ponse.
Validez votre format de réponse avec notre Validateur JSON.
Codes de Statut HTTP
Utilisez correctement les codes de statut â c'est la premiĂšre chose que les clients vĂ©rifient :
Codes de SuccĂšs
| Code | Quand |
|---|---|
| 200 OK | SuccĂšs GET, succĂšs PUT/PATCH |
| 201 Created | POST ayant créé une ressource |
| 204 No Content | SuccĂšs DELETE (pas de corps) |
Codes d'Erreur Client
| Code | Quand |
|---|---|
| 400 Bad Request | Syntaxe de requĂȘte malformĂ©e |
| 401 Unauthorized | Authentification manquante ou invalide |
| 403 Forbidden | Authentifié mais non autorisé |
| 404 Not Found | La ressource n'existe pas |
| 409 Conflict | Conflit d'état de ressource (doublon) |
| 422 Unprocessable | Syntaxe valide mais erreurs sémantiques |
| 429 Too Many Requests | Limite de débit dépassée |
Codes d'Erreur Serveur
| Code | Quand |
|---|---|
| 500 Internal Server Error | Erreur serveur inattendue |
| 502 Bad Gateway | Ăchec du service en amont |
| 503 Service Unavailable | Surcharge temporaire ou maintenance |
Conception des Réponses d'Erreur
De bonnes réponses d'erreur aident les développeurs à déboguer rapidement :
{
"error": {
"code": "RESOURCE_NOT_FOUND",
"message": "User with ID 'user_999' not found",
"details": [],
"documentationUrl": "https://api.example.com/docs/errors#RESOURCE_NOT_FOUND"
},
"meta": {
"requestId": "req_xyz789",
"timestamp": "2024-01-15T10:30:00Z"
}
}
RĂšgles :
codeest lisible par la machine (chaĂźne constante, pas un statut HTTP)messageest lisible par l'humain (peut changer sans casser les clients)detailsfournit des erreurs au niveau des champs pour les Ă©checs de validationrequestIdpermet Ă l'Ă©quipe support de tracer la requĂȘte dans les logs
ModĂšles de Pagination
Basée sur l'Offset
Simple et permet de sauter Ă des pages arbitraires :
{
"data": ["..."],
"meta": {
"page": 2,
"perPage": 20,
"total": 142,
"totalPages": 8
},
"links": {
"first": "/api/users?page=1&per_page=20",
"prev": "/api/users?page=1&per_page=20",
"next": "/api/users?page=3&per_page=20",
"last": "/api/users?page=8&per_page=20"
}
}
Basée sur le Curseur
Meilleure pour les données en temps réel et les grands ensembles de données :
{
"data": ["..."],
"meta": {
"hasNext": true,
"hasPrev": true
},
"links": {
"next": "/api/users?cursor=eyJpZCI6MTQzfQ&limit=20",
"prev": "/api/users?cursor=eyJpZCI6MTIzfQ&limit=20&direction=prev"
}
}
Date et Heure
Utilisez toujours ISO 8601 avec les informations de fuseau horaire :
{
"createdAt": "2024-01-15T10:30:00Z",
"updatedAt": "2024-01-15T14:22:33+00:00",
"expiresAt": "2024-12-31T23:59:59Z"
}
N'utilisez jamais :
- Les timestamps Unix (ambigu : secondes ou millisecondes ?)
- Les dates locales sans fuseau horaire
- Les formats personnalisés comme MM/JJ/AAAA
Pour en savoir plus sur la gestion des timestamps, consultez notre guide sur les Timestamps Unix.
Null vs Champs Absents
Deux approches courantes :
Inclure avec null (explicite) :
{ "name": "Alice", "avatar": null, "bio": null }
Omettre les champs absents (épars) :
{ "name": "Alice" }
Recommandation : Soyez cohérent au sein de votre API. Les nulls explicites sont meilleurs pour les langages typés (les clients savent que le champ existe). L'approche éparse est meilleure pour les environnements à bande passante limitée.
Versionnage des Réponses
Quand le format de réponse change, versionnez votre API :
GET /api/v2/users/123
Changements cassants nécessitant un versionnage :
- Suppression d'un champ
- Changement du type d'un champ
- Renommage d'un champ
- Modification de la structure de l'enveloppe de réponse
Changements non cassants (sûrs sans versionnage) :
- Ajout de nouveaux champs
- Ajout de nouveaux endpoints
- Ajout de nouvelles valeurs d'énumération
FAQ
Dois-je encapsuler les réponses réussies dans une clé data ou renvoyer la ressource directement ?
L'utilisation d'un wrapper data fournit une structure cohérente pour toutes les réponses et laisse de la place pour les métadonnées, la pagination et les liens à cÎté des données. Renvoyer la ressource directement est plus simple pour les endpoints à ressource unique. La plupart des APIs modernes utilisent l'approche avec wrapper pour la cohérence.
Comment dois-je gérer les échecs partiels dans les opérations par lots ?
Renvoyez un 200 avec une réponse qui inclut à la fois les succÚs et les échecs dans l'objet data. Utiliser 207 Multi-Status (WebDAV) est une autre option mais moins couramment utilisée dans les APIs REST.
Ressources Connexes
- Formateur JSON â Formater les rĂ©ponses API
- ModĂšles de Conception d'API JSON â Guide complet de conception d'API
- Validation de SchĂ©ma JSON â Valider les structures de rĂ©ponse