La plupart des bugs d'API ne sont pas des erreurs de codage. Ce sont des erreurs d'accord. Le frontend s'attendait à userId, le backend a envoyé user_id, et personne ne l'a remarqué avant l'AQ. Le développement d'API axé sur la spécification (spec-first) corrige cela en faisant du contrat la première chose que vous écrivez, et non la dernière que vous documentez.
Dans ce guide, vous rédigerez une petite spécification OpenAPI à la main, puis utiliserez ce seul fichier pour générer des mocks, des tests et des documents avant même l'existence de tout code serveur. La même approche porte plusieurs noms : développement piloté par les spécifications, design-first ou contract-first. Ils pointent tous vers la même idée. Mettez-vous d'accord sur l'interface d'abord, puis construisez-la.
Qu'est-ce que le développement d'API spec-first
Le développement d'API spec-first signifie que vous rédigez un contrat lisible par machine, généralement un document OpenAPI, avant d'implémenter le point de terminaison. Ce contrat décrit chaque chemin, paramètre, corps de requête, forme de réponse et code de statut. Une fois qu'il existe, il devient la source de vérité pour tous ceux qui touchent l'API.
La spécification n'est pas une documentation qui traîne derrière le code. Elle guide. Les équipes frontend construisent à partir d'un mock généré à partir d'elle. L'AQ écrit des tests basés sur elle. Le backend l'implémente pour la satisfaire. Lorsque les trois sont d'accord avec le même fichier, l'intégration cesse d'être un jeu de devinettes.
Cela inverse l'ordre habituel. Dans le développement code-first, vous écrivez des gestionnaires puis les décrivez ensuite, souvent à la main, souvent dépassés en l'espace d'un sprint. Dans un flux de travail design-first, la description vient en premier et le code s'y conforme. Ce seul changement déplace la plupart des problèmes d'intégration au début du projet, où ils sont peu coûteux à résoudre.
Cycle de vie spec-first vs code-first
Les deux approches produisent les mêmes points de terminaison. Elles diffèrent quant au moment où les problèmes apparaissent et à qui peut commencer à travailler en parallèle.

La colonne de droite est le bénéfice. Lorsque le contrat existe en premier, trois équipes cessent de se bloquer mutuellement et commencent à construire à partir d'une définition partagée unique.
Un exemple OpenAPI détaillé
Concevons un petit point de terminaison /users étape par étape. Nous le construirons en plusieurs parties afin que chaque élément soit clair, puis nous assemblerons le fichier complet.
Commencez par l'en-tête du document. Il déclare la version OpenAPI et les métadonnées de base.
openapi: 3.0.3
info:
title: Users API
version: 1.0.0
servers:
- url: https://api.example.com/v1
Ensuite, définissez le schéma User sous components. Le définir une seule fois vous permet de le référencer partout, de sorte que la forme reste cohérente entre les requêtes et les réponses.
components:
schemas:
User:
type: object
required: [id, email, createdAt]
properties:
id:
type: string
format: uuid
email:
type: string
format: email
name:
type: string
createdAt:
type: string
format: date-time
Ajoutez maintenant le chemin GET /users. Il liste les utilisateurs et prend en charge un paramètre de requête limit. Remarquez comment la réponse réutilise le schéma User avec $ref au lieu de le redéfinir.
paths:
/users:
get:
summary: List users
operationId: listUsers
parameters:
- name: limit
in: query
schema:
type: integer
default: 20
maximum: 100
responses:
"200":
description: A list of users
content:
application/json:
schema:
type: array
items:
$ref: "#/components/schemas/User"
Ajoutez l'opération POST /users pour créer un utilisateur. Le corps de la requête définit ce que le client doit envoyer, et la réponse 201 renvoie l'enregistrement créé.
post:
summary: Create a user
operationId: createUser
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [email]
properties:
email:
type: string
format: email
name:
type: string
responses:
"201":
description: User created
content:
application/json:
schema:
$ref: "#/components/schemas/User"
"400":
description: Invalid request body
C'est un contrat complet et valide. Il nomme chaque champ, marque email comme obligatoire, limite limit à 100, et déclare à la fois les réponses de succès et d'erreur. Personne n'a encore écrit une ligne de code serveur, mais l'accord est scellé.
Générer des mocks, des tests et des documents à partir de la spécification
La raison d'écrire la spécification en premier est l'effet de levier. Un seul fichier pilote trois artefacts que les équipes construisent habituellement séparément.
Mocks. Un serveur de mock lit votre spécification et renvoie des exemples de réponses qui correspondent à chaque schéma. Les indications format: uuid et format: email permettent aux outils de générer des exemples de données réalistes. Votre frontend appelle GET /users et obtient un tableau d'utilisateurs bien formé dès le premier jour, bien avant que le véritable gestionnaire n'existe. Lorsque la spécification change, le mock change avec elle.
Tests. Parce que la spécification déclare les champs obligatoires, les types et les codes de statut, elle sert aussi d'oracle de test. Les tests de contrat affirment que la réponse réelle pour POST /users renvoie un 201 avec un corps correspondant au schéma User, et un 400 lorsque email est manquant. Vous n'inventez pas d'assertions. Vous vérifiez que l'implémentation correspond à ce que vous avez déjà convenu.
Docs. La documentation de référence de l'API est directement générée à partir de la spécification. Chaque point de terminaison, paramètre et exemple que vous voyez dans les documents provient du même YAML. Il n'y a pas de deuxième copie à maintenir synchronisée, de sorte que la documentation ne peut pas s'écarter du contrat.
C'est aussi ce qui fait que le spec-first s'accorde bien avec un flux de travail API natif Git : la spécification est un fichier texte brut, de sorte que chaque changement au contrat apparaît comme un diff révisable dans une pull request. Un relecteur peut voir que quelqu'un a renommé email ou supprimé un champ obligatoire avant qu'il ne soit livré.
Le faire dans Apidog
Apidog prend en charge cela de bout en bout via le mode Spec-First. Au lieu de traiter le fichier OpenAPI comme une exportation, il traite le fichier comme le projet. Vous modifiez le YAML directement et le reste de l'espace de travail suit.

Vous écrivez ou collez la spécification /users dans l'éditeur. Apidog l'analyse et met immédiatement en place un serveur de mock pour les deux opérations, afin que votre frontend puisse commencer à les appeler. La documentation générée se met à jour au fur et à mesure que vous tapez. Lorsque vous êtes prêt à vérifier l'implémentation, vous exécutez les opérations de la spécification comme cas de test contre votre backend réel et confirmez que les réponses correspondent aux schémas.
Ce qui assure l'intégrité est la synchronisation Git bidirectionnelle. Votre spécification réside dans un dépôt, et les changements circulent dans les deux sens. Modifiez le YAML dans votre éditeur et poussez, et Apidog le récupère. Modifiez dans Apidog, et le changement apparaît comme un commit que votre équipe peut réviser. Le contrat ne vit jamais à deux endroits à la fois. Si vous voulez une comparaison plus approfondie de sa position par rapport à une approche purement design-first, voir spec-first vs design-first dans Apidog.
Une liste de contrôle spec-first
Utilisez ceci avant de déclarer une spécification prête à être implémentée :
- La spécification est validée par rapport au schéma OpenAPI sans erreurs.
- Chaque point de terminaison déclare sa réponse de succès et au moins une réponse d'erreur.
- Les formes partagées se trouvent dans
components/schemaset sont référencées avec$ref, et non copiées. - Les champs obligatoires sont marqués
required, et les formats (uuid,email,date-time) sont définis là où ils s'appliquent. - Le fichier de spécification est validé dans le contrôle de version et révisé dans les pull requests.
- Un serveur de mock s'exécute à partir de la spécification, et le frontend peut l'appeler.
- Les tests de contrat vérifient les réponses réelles par rapport aux schémas déclarés.
- La documentation publiée est générée à partir du même fichier, sans copie maintenue à la main.
Si toutes les cases sont cochées, vos équipes peuvent construire en parallèle sur la base d'un accord unique au lieu de trois suppositions.
FAQ
Le développement d'API spec-first est-il la même chose que le design-first ?
Oui, en grande partie. « Design-first » et « contract-first » décrivent le même principe : écrire l'interface avant l'implémentation. « Spec-first » est le nom le plus littéral car le fichier de spécification OpenAPI est l'artefact concret avec lequel vous commencez. En pratique, les termes sont utilisés de manière interchangeable.
Dois-je écrire le YAML à la main ?
Non. Vous pouvez créer la spécification dans un éditeur visuel et le laisser produire le YAML, ou écrire le YAML directement si vous préférez. L'important n'est pas le format que vous utilisez, mais que le contrat existe et soit convenu avant le code. De nombreuses équipes mélangent les deux, en faisant un brouillon visuellement et en l'affinant en YAML lors de la révision.
Comment éviter que la spécification et le code ne s'écartent l'un de l'autre ?
Faites de la spécification la source de vérité et assurez son respect. Gardez la spécification dans Git afin que les modifications soient examinées sous forme de diffs. Exécutez des tests de contrat en CI afin que la construction échoue lorsqu'une réponse ne correspond plus au schéma. Avec la synchronisation bidirectionnelle, les modifications effectuées à un endroit ou à l'autre restent réconciliées, ce qui élimine la cause la plus courante de décalage.
Le développement d'API spec-first est un petit changement d'ordre avec un grand changement de résultat. Écrivez le contrat, mettez-vous d'accord, puis construisez-le. Si vous souhaitez essayer le cycle complet, ouvrez le mode Spec-First dans Apidog et pointez-le vers votre dépôt.
