Article original : How to Handle Complex Use Cases in Your OpenAPI Specifications – API Documentation Guide
Lorsque vous documentez une référence d'API, il existe deux approches principales que vous pouvez suivre. Vous pouvez soit utiliser l'approche manuelle consistant à remplir les endpoints via une interface utilisateur, soit organiser un document structuré contenant toutes les informations nécessaires sur votre API.
Ce document structuré est appelé une spécification OpenAPI (OpenAPI Spec ou OAS).
Une spécification OpenAPI est un format pour décrire les API. C'est un plan qui décrit tout le fonctionnement d'une API – quels endpoints sont disponibles, quelles données vous pouvez envoyer ou recevoir, et quelles réponses attendre.
Cela signifie qu'un fichier OAS bien rédigé équivaut à une documentation de référence d'API bien rédigée.
Lors de la rédaction de ce fichier, certaines parties peuvent devenir un peu compliquées. Par exemple, vous devrez peut-être documenter un seul endpoint avec différentes méthodes ou parfois des endpoints dupliqués.
J'ai rencontré et documenté ces deux cas d'utilisation. Ainsi, dans cet article, je vais vous montrer comment faire de même. Nous passerons en revue chaque cas d'utilisation avec des exemples de spécifications OpenAPI, et à la fin, je vous laisserai quelques conseils utiles pour documenter vos fichiers de spécifications OpenAPI.
Table des matières
Prérequis
Il y a quelques choses que vous devez savoir pour suivre les cas d'utilisation ci-dessous. Cela inclut :
Une connaissance de base des API et de la documentation d'API : La familiarité avec la terminologie et la structure des API (par exemple, endpoints, méthodes, structure des requêtes/réponses) est essentielle pour comprendre comment un document de spécification OpenAPI (OAS) fonctionne.
Familiarité avec la spécification OpenAPI : Compréhension de base de l'OAS, y compris son objectif, sa structure, etc.
Accès à Swagger ou à d'autres outils de documentation OpenAPI : Vous avez besoin d'outils comme l'éditeur Swagger ou RapiDoc, qui vous permettront de tester et de visualiser les fichiers OpenAPI.
Poser les bases
En programmation comme dans la vie, si vous pouvez déterminer que quelque chose est "complexe", cela signifie qu'il existe aussi une manière simpliste et régulière de le faire. Et c'est la même chose pour un fichier OAS.
Lors de la création de votre fichier de spécification, vous ne rencontrerez pas toujours les cas d'utilisation que nous aborderons bientôt. C'est pourquoi il est utile de savoir à quoi ressemble un fichier de spécification conventionnel.
Une spécification OpenAPI est un fichier lisible par l'homme et la machine, écrit en JSON ou YAML. Ci-dessous, un exemple de structure de fichier OAS au format YAML :
paths:
/users:
get:
summary: Obtenir une liste d'utilisateurs
responses:
'200':
description: Une liste d'utilisateurs.
/users/{userId}:
get:
summary: Obtenir les détails d'un seul utilisateur
parameters:
- name: userId
in: path
required: true
schema:
type: string
responses:
'200':
description: Détails d'un seul utilisateur.
/orders:
get:
summary: Obtenir une liste de commandes
responses:
'200':
description: Une liste de commandes.
Voici une brève description de cette structure de fichier OAS :
Paths : La section
pathsvous permet de lister chaque endpoint ou URL avec lequel vous pouvez interagir dans cette API. Chaque chemin, tel que/usersou/orders, montre quel type de données vous pouvez obtenir ou envoyer à cette URL.Operations : Sous chaque chemin, il y a une méthode ou opération, comme
GET, qui nous indique ce que nous pouvons faire avec cet endpoint. Dans cet exemple, chaque chemin utiliseGET, ce qui signifie que vous demandez des informations.Summary : Chaque opération a un
summary– une courte description expliquant ce que fait l'endpoint, comme "Obtenir une liste d'utilisateurs" ou "Obtenir les détails d'un seul utilisateur".Parameters : Pour les chemins qui incluent des espaces réservés, comme
/users/{userId}, vous verrez une sectionparametersexpliquant quels détails sont requis.Responses : Chaque opération inclut une section
responses, qui liste les réponses possibles de l'API.
NOTE : Ceci n'est pas un fichier OAS complet. J'ai omis certaines informations précédentes à des fins d'explication.
Maintenant, plongeons dans les scénarios plus complexes.
Cas d'utilisation 1 : Endpoints dupliqués
Lors du développement d'une API, vous pouvez créer un seul endpoint avec plusieurs variations. Selon le cas d'utilisation, vous pouvez vouloir que cet endpoint accepte plusieurs formats de données ou des paramètres spécifiques.
Lorsque vous rencontrez de tels scénarios et que vous souhaitez documenter la référence de l'API en utilisant une spécification OpenAPI, vous ne pourrez pas la répliquer exactement comme elle est dans la collection Postman (ou tout autre environnement de développement).
Si vous essayiez, vous obtiendriez cette erreur :

La solution à ce problème est de consolider ces multiples variations sous une seule définition de chemin en regroupant les différentes requêtes et réponses en tant qu'exemples.
Dans l'exemple ci-dessous, vous avez une API qui possède un endpoint pour gérer l'enregistrement des sessions lors d'une conférence. Cet endpoint a diverses requêtes et réponses basées sur le type d'enregistrement (par exemple, Speaker, Attendee, ou VIP).
Dans une collection Postman, vous pouvez avoir chacun de ces endpoints dans un dossier séparé pour une identification et un test faciles.

Mais lors de la documentation de votre fichier de spécification, il devrait ressembler à ceci :
openapi: 3.0.0
info:
title: Conference Events API
description: API pour gérer les inscriptions aux événements de conférences
version: 1.0.0
paths:
/register-session:
post:
tags:
- Registration
summary: S'inscrire à une session de conférence
description: Inscrire un utilisateur pour une session spécifique en fonction de son rôle, avec des détails fournis pour chaque type d'enregistrement.
operationId: registerSession
requestBody:
description: Inscrire un utilisateur pour une session à la conférence. Il accepte différents formats pour les inscriptions des participants, des intervenants ou des VIP.
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/SessionRegistration'
examples:
Attendee:
summary: S'inscrire en tant que participant
value:
userType: Attendee
userId: 789
sessionId: 1234
preferences:
seating: General
accessLevel: Basic
Speaker:
summary: S'inscrire en tant qu'intervenant
value:
userType: Speaker
userId: 456
sessionId: 1234
preferences:
seating: VIP
accessLevel: Full
presentationEquipment: Projector
VIP:
summary: S'inscrire en tant que VIP
value:
userType: VIP
userId: 123
sessionId: 1234
preferences:
seating: Front Row
accessLevel: Full
exclusiveAccess: true
responses:
'200':
description: Inscription réussie pour le participant, l'intervenant ou le VIP
content:
application/json:
schema:
type: object
properties:
registrationId:
type: string
success:
type: boolean
examples:
Attendee:
summary: Réponse pour l'inscription d'un participant
value:
registrationId: att-456def
success: true
Speaker:
summary: Réponse pour l'inscription d'un intervenant
value:
registrationId: spk-123abc
success: true
VIP:
summary: Réponse pour l'inscription d'un VIP
value:
registrationId: vip-789ghi
success: true
components:
schemas:
SessionRegistration:
type: object
properties:
userType:
type: string
description: Type d'utilisateur s'inscrivant (par exemple, participant, intervenant, VIP)
userId:
type: integer
description: ID unique de l'utilisateur
sessionId:
type: integer
description: ID unique de la session à laquelle s'inscrire
preferences:
type: object
properties:
seating:
type: string
description: Préférence de siège (par exemple, général, VIP, première rangée)
accessLevel:
type: string
description: Niveau d'accès accordé (par exemple, basique, complet)
presentationEquipment:
type: string
description: Équipement requis pour les intervenants (uniquement applicable aux intervenants)
exclusiveAccess:
type: boolean
description: Accès exclusif pour les utilisateurs VIP
Dans ce fichier, vous avez un seul chemin POST /register-session qui capture tous les types d'enregistrement sans dupliquer les endpoints.
Voici une représentation visuelle de ce fichier OAS en utilisant l'éditeur Swagger :

Cas d'utilisation 2 : Comment documenter plusieurs méthodes HTTP
Un autre cas d'utilisation que vous pouvez rencontrer se produit lorsque vous avez le même endpoint mais avec différentes méthodes HTTP.
Cela arrive généralement parce que chaque méthode sert un objectif différent, même si elles partagent le même chemin.
Par exemple, une méthode GET récupère des informations sur une ressource, comme afficher les détails d'enregistrement d'un utilisateur pour une session de conférence.
D'autre part, une méthode PATCH met à jour des champs spécifiques pour cet enregistrement d'utilisateur, comme mettre à jour sa préférence de siège.
Puisque les méthodes GET et PATCH concernent la même ressource (/register-session dans notre exemple), la solution consiste à les regrouper sous le même chemin. Ainsi, vous documenterez deux méthodes distinctes pour un seul chemin.
Dans OpenAPI, chaque combinaison d'un chemin et d'une méthode est appelée une "opération". Regrouper les opérations qui partagent le même chemin aide à maintenir des documents plus clairs et mieux structurés.
En utilisant l'exemple de l'API des événements de conférence, voici à quoi devrait ressembler votre fichier OAS :
openapi: 3.0.0
info:
title: Conference Events API
description: API pour gérer les inscriptions aux événements de conférences
version: 1.0.0
paths:
/register-session:
get:
tags:
- Registration
summary: Récupérer un enregistrement pour une session de conférence
description: Récupérer les détails d'enregistrement pour un utilisateur spécifique, comme l'assignation de siège et le niveau d'accès.
operationId: getSessionRegistration
parameters:
- in: query
name: userId
schema:
type: integer
required: true
description: L'ID de l'utilisateur dont vous souhaitez récupérer l'enregistrement.
responses:
'200':
description: Détails de l'enregistrement récupérés avec succès
content:
application/json:
schema:
$ref: '#/components/schemas/SessionRegistration'
example:
userId: 789
sessionId: 1234
preferences:
seating: General
accessLevel: Basic
exclusiveAccess: false
patch:
tags:
- Registration
summary: Mettre à jour un enregistrement pour une session de conférence
description: Mettre à jour des champs spécifiques pour l'enregistrement de session d'un utilisateur, tels que le siège ou le niveau d'accès.
operationId: updateSessionRegistration
requestBody:
description: Permet de mettre à jour des champs pour un enregistrement de session spécifique.
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/UpdateSessionPreferences'
example:
userId: 789
preferences:
seating: VIP
accessLevel: Full
exclusiveAccess: true
responses:
'200':
description: Enregistrement mis à jour avec succès
content:
application/json:
schema:
type: object
properties:
success:
type: boolean
message:
type: string
example:
success: true
message: "Enregistrement mis à jour avec succès."
components:
schemas:
SessionRegistration:
type: object
properties:
userId:
type: integer
description: ID unique de l'utilisateur
sessionId:
type: integer
description: ID unique de la session
preferences:
type: object
properties:
seating:
type: string
description: Préférence de siège (par exemple, général, VIP, première rangée)
accessLevel:
type: string
description: Niveau d'accès accordé (par exemple, basique, complet)
exclusiveAccess:
type: boolean
description: Accès exclusif accordé à certains utilisateurs
UpdateSessionPreferences:
type: object
properties:
userId:
type: integer
description: ID unique de l'utilisateur
preferences:
type: object
properties:
seating:
type: string
description: Nouvelle préférence de siège (par exemple, VIP)
accessLevel:
type: string
description: Niveau d'accès mis à jour (par exemple, complet)
exclusiveAccess:
type: boolean
description: Préférence d'accès mise à jour (par exemple, vrai ou faux)
Dans ce fichier, vous avez un seul chemin /register-session avec plusieurs méthodes. Nous définissons un seul chemin, /register-session, et listons les méthodes GET et PATCH sous celui-ci. Cela garde la spécification propre, réduit la duplication et montre que ces méthodes concernent la même ressource.
Voici une représentation visuelle de ce fichier OAS en utilisant l'éditeur Swagger :

Conseils pour la documentation d'API
Lors de la création de spécifications OpenAPI, il existe quelques astuces et conseils utiles qui peuvent rendre votre fichier OAS plus lisible et plus facile à maintenir.
Utiliser Markdown dans OpenAPI
Les spécifications OpenAPI permettent l'utilisation de Markdown dans le champ description. La version de Markdown utilisée dans OAS est appelée CommonMark, la même version utilisée dans GitHub.
Le formatage Markdown vous permet de rendre le texte plus visuellement attrayant et organisé. Vous pouvez ajouter des formats tels que des en-têtes, des listes, des blocs de code, du texte en gras, en italique, etc., ce qui peut rendre votre documentation plus facile à parcourir et plus accessible pour les lecteurs.
Par exemple, si vous devez mettre en évidence certaines parties du but d'un endpoint ou souligner des détails importants, Markdown vous permet de le faire naturellement.
Vous pouvez ajouter Markdown directement dans n'importe quel champ description du fichier OpenAPI, comme ceci :
paths:
/register-session:
get:
description: |
## Récupérer l'enregistrement de session
Récupère les détails d'enregistrement pour un utilisateur spécifique.
- **Note :** Ces données incluent l'assignation de siège et le niveau d'accès.
- Exemple de réponse JSON : `{"userId": 789, "sessionId": 1234, "seating": "General"}`
responses:
'200':
description: Détails de l'enregistrement récupérés avec succès
Lorsque cela est déployé sur des plateformes de documentation prises en charge comme RapiDoc ou ReadMe, cela sera rendu magnifiquement avec tous vos styles Markdown intacts.
Voici une version déployée de cet exemple dans Readme :

Utiliser le champ operationId
Le champ operationId est un champ facultatif dans les spécifications OpenAPI qui attribue un nom unique à chaque opération d'API.
C'est un identifiant que vous pouvez utiliser pour appeler des méthodes spécifiques lors de l'intégration avec des SDK ou lors de la liaison entre les parties de votre documentation.
En utilisant efficacement operationId, vous facilitez grandement la référence des développeurs à des actions spécifiques dans l'API, ce qui est particulièrement utile lorsque l'API est complexe ou possède plusieurs endpoints.
Placez operationId à l'intérieur de chaque bloc de méthode HTTP pour lui donner un identifiant unique. Par exemple :
paths:
/register-session:
get:
operationId: getSessionRegistration
description: Récupérer un enregistrement pour une session de conférence
responses:
'200':
description: Enregistrement récupéré avec succès
patch:
operationId: updateSessionRegistration
description: Mettre à jour un enregistrement pour une session de conférence
responses:
'200':
description: Enregistrement mis à jour avec succès
Avec operationId, les développeurs peuvent se référer directement à getSessionRegistration ou updateSessionRegistration en tant qu'appels de fonction dans le code ou les clients API.
Utiliser $ref pour les composants réutilisables
Le mot-clé $ref dans OpenAPI vous permet de créer et de réutiliser des composants dans votre fichier de spécification. Cette technique est particulièrement utile lorsque vous avez des corps de requête, des réponses ou des paramètres similaires répétés dans plusieurs endpoints.
En définissant des composants en un seul endroit et en les référençant selon les besoins, vous évitez la redondance, réduisez les erreurs et facilitez les mises à jour.
Ainsi, au lieu de mettre à jour le même paramètre à plusieurs endroits, vous le mettez à jour une fois dans le composant réutilisable, et chaque endpoint l'utilisant reçoit la mise à jour.
Pour l'utiliser, définissez d'abord le composant réutilisable dans la section des composants de votre fichier OpenAPI, puis référencez-le ailleurs en utilisant $ref :
components:
schemas:
RegistrationDetails:
type: object
properties:
userId:
type: integer
sessionId:
type: integer
seating:
type: string
paths:
/register-session:
post:
summary: S'inscrire pour une session
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/RegistrationDetails'
responses:
'201':
description: Inscription réussie pour la session
Dans ce fichier, RegistrationDetails est défini une fois et est référencé en utilisant le mot-clé $ref dans l'opération /register-session.
Conclusion
Dans cet article, vous avez appris comment résoudre certains cas d'utilisation complexes que vous pourriez rencontrer lors de la documentation de votre référence d'API en utilisant une spécification OpenAPI. Nous avons passé en revue ce qu'il faut faire lorsque vous avez un seul endpoint avec plusieurs méthodes ou des endpoints dupliqués.
Créer votre référence d'API sans un fichier de spécification OpenAPI est une approche manuelle qui peut devenir redondante si vous devez la répliquer sur diverses plateformes. Mais en vous appuyant sur les conseils de l'article, vous êtes sûr de créer de meilleures spécifications OpenAPI, plus efficaces et plus réutilisables. Et celles-ci, à leur tour, mèneront à une meilleure documentation d'API.