Qu'est-ce qu'un contrat d'API ? Définition, exemples et bonnes pratiques
Tous les échecs d'intégration racontent la même histoire. L'équipe A a construit un endpoint. L'équipe B le consomme. Quelque part entre "le champ s'appelle userId" et "en fait c'est user_id maintenant", quelque chose a cassé en production, et deux équipes ont passé un après-midi en cellule de crise à débattre de qui avait la bonne compréhension de l'API.
La solution n'est pas une meilleure communication. C'est un meilleur artefact : un contrat d'API. Une définition unique, formelle et convenue de ce que fait l'API, sur laquelle les deux parties peuvent construire, contre laquelle elles peuvent valider, et qu'elles peuvent s'opposer mutuellement.
Ce guide couvre ce que sont les contrats d'API, les formats utilisés selon les styles d'API, le développement contract-first versus code-first, le fonctionnement des tests de contrat, et les bonnes pratiques qui gardent vos contrats fiables dans la durée.
Qu'est-ce qu'un contrat d'API ?
Un contrat d'API est la spécification formelle et convenue de l'interface d'une API. Il définit, précisément et sans ambiguïté :
- Les opérations -- Les endpoints, méthodes, requêtes ou procédures que l'API expose. Pour une API REST, ce sont les chemins et les verbes HTTP. Pour gRPC, les services et les RPC. Pour une API événementielle, les channels et les types de messages.
- Les schémas de requête et de réponse -- La forme exacte des données échangées : noms de champs, types, obligatoire vs optionnel, formats et contraintes.
- La sémantique des erreurs -- À quoi ressemble un échec. Quels codes d'erreur existent, ce qu'ils signifient, et quelle structure suivent les réponses d'erreur.
- L'authentification et l'autorisation -- Comment les appelants s'identifient : clés d'API, scopes OAuth, claims JWT, mTLS.
- Les règles de versionnement et de stabilité -- Quelles parties de l'interface sont stables, comment les changements sont introduits, comment fonctionne la dépréciation, et quelles garanties (rate limits, SLA) le fournisseur s'engage à tenir.
Le mot clé est convenue. Un contrat n'est pas juste une description de ce que le code fait aujourd'hui. C'est un engagement entre un fournisseur et ses consommateurs : "voici l'interface, et nous ne la casserons pas sans prévenir." Cet engagement est ce qui rend possible le développement indépendant. L'équipe frontend peut construire contre le contrat pendant que le backend est encore en cours d'écriture. Un partenaire peut s'intégrer sans lire votre code source.
Si vous avez déjà généré un SDK client à partir d'un fichier OpenAPI, mocké un service à partir de sa spec, ou rejeté une pull request parce qu'elle cassait un schéma publié, vous avez utilisé un contrat d'API comme il est censé l'être : comme source de vérité d'une interface.
Les formats de contrat d'API : un par style d'API
Il n'existe pas de format de contrat universel, parce qu'il n'existe pas de style d'API universel. Chaque famille de protocoles a convergé vers son propre standard de spécification.
OpenAPI pour les API REST / HTTP
OpenAPI (anciennement Swagger) est le format de contrat dominant pour les API HTTP. Un document OpenAPI décrit les chemins, opérations, paramètres, corps de requête, schémas de réponse, mécanismes d'authentification et serveurs -- le tout en YAML ou JSON.
paths:
/orders/{orderId}:
get:
summary: Récupère une commande par son ID
parameters:
- name: orderId
in: path
required: true
schema:
type: string
format: uuid
responses:
"200":
description: La commande
content:
application/json:
schema:
$ref: "#/components/schemas/Order"
"404":
description: Commande introuvable
La vraie force d'OpenAPI, c'est son écosystème : viewers de documentation interactive, générateurs de code client et serveur, serveurs de mock, validateurs et linters consomment tous le même fichier.
Protocol Buffers pour gRPC
Les API gRPC sont définies dans des fichiers .proto avec Protocol Buffers. Le fichier proto est le contrat -- il définit les services, les méthodes RPC et des messages fortement typés, et le code client comme serveur est généré à partir de lui.
service OrderService {
rpc GetOrder(GetOrderRequest) returns (Order);
}
message GetOrderRequest {
string order_id = 1;
}
Parce que la génération de code est obligatoire en gRPC, la divergence entre spec et implémentation est structurellement plus difficile qu'en REST. Les champs numérotés encodent aussi une politique d'évolution explicite : vous pouvez ajouter des champs, mais les renuméroter ou les réutiliser casse la compatibilité.
Le SDL GraphQL pour les API GraphQL
GraphQL intègre le contrat dans le protocole lui-même. Le Schema Definition Language (SDL) décrit chaque type, query, mutation et subscription que l'API supporte, et le serveur le fait respecter : une requête qui ne correspond pas au schéma est rejetée avant même qu'un resolver ne s'exécute. L'introspection permet aux consommateurs de récupérer à tout moment le contrat courant depuis l'API en production.
AsyncAPI pour les API événementielles
Les API asynchrones -- topics Kafka, queues RabbitMQ, subjects NATS, WebSockets -- ont longtemps été le Far West de la documentation. AsyncAPI a changé la donne en adaptant l'approche d'OpenAPI aux systèmes événementiels. Un document AsyncAPI décrit les channels, les opérations qui s'y appliquent (envoi/réception), les payloads des messages et les bindings des brokers. Pour les architectures où "qui publie quoi, et qui le consomme ?" est une question quotidienne, un contrat AsyncAPI fait la différence entre une réponse et un chantier d'archéologie.
Les schémas d'outils MCP pour les agents IA
Le type de contrat le plus récent ne décrit pas du tout une interface de service à service. Le Model Context Protocol (MCP) permet à des services d'exposer des outils à des agents IA, et chaque outil est accompagné d'un nom, d'une description et d'un JSON Schema pour ses entrées. Cette liste d'outils est un véritable contrat d'API -- avec des enjeux sans doute plus élevés encore, parce qu'elle définit ce qu'un agent autonome a le droit de faire sur votre système. Nous avons écrit en détail sur le fait de traiter les outils MCP comme des contrats d'API et pourquoi ils méritent la même rigueur documentaire que vos endpoints REST.
À retenir : quel que soit votre style d'API, un format de contrat lisible par machine existe pour lui. Les systèmes modernes en ont généralement besoin de plusieurs à la fois -- REST pour l'API publique, gRPC en interne, AsyncAPI pour les événements, MCP pour les agents -- et c'est exactement pour ça que les contrats gagnent à avoir un foyer unique plutôt que cinq repos éparpillés.
Contract-first vs code-first
Il y a deux façons pour un contrat de venir au monde, et ce choix structure tout votre workflow d'API.
Contract-first (design-first)
En développement contract-first, vous écrivez la spécification avant d'écrire la moindre implémentation. Le fichier OpenAPI ou la définition proto est conçu, revu et validé -- puis fournisseur et consommateurs construisent contre lui, souvent en parallèle.
Avantages :
- Développement en parallèle. Les consommateurs peuvent générer des clients et construire contre des mocks pendant que le fournisseur implémente. Personne n'attend.
- Revue de design avant revue de code. Il est bien moins coûteux de débattre d'un nom de champ dans un diff YAML que de refactorer un endpoint déjà livré.
- Cohérence. Concevoir les contrats comme des artefacts délibérés rend naturelle l'application de conventions de nommage, de patterns de pagination et de formats d'erreur communs à toutes vos API.
- Orientation consommateur. Vous concevez l'interface dont les consommateurs ont besoin, pas celle qui est la plus facile à greffer sur votre modèle de données existant.
Inconvénients :
- Plus de process en amont. Pour une équipe de deux personnes qui itère sur un endpoint interne, une phase de design formelle peut être de la lourdeur.
- Risque de divergence si l'implémentation n'est pas validée contre le contrat -- il faut de l'outillage (middleware de validation, vérifications en CI) pour garder les deux alignés.
Code-first
En développement code-first, vous écrivez l'implémentation et générez le contrat à partir d'elle -- annotations, réflexion ou introspection du framework produisent le document OpenAPI ou le schéma GraphQL.
Avantages :
- Rapidité pour les petites équipes. Pas d'étape de design séparée ; le contrat est toujours dérivable du code.
- Pas de divergence, par construction. La spec générée correspond à l'implémentation, puisqu'elle en provient.
Inconvénients :
- Le contrat devient un sous-produit plutôt qu'un engagement. Ce que fait le code est ce qu'est l'API -- y compris les parties accidentelles.
- Les breaking changes passent facilement entre les mailles, parce que rien ne force une revue de l'interface en tant qu'interface.
- Les specs générées sont souvent médiocres : descriptions manquantes, documentation des erreurs vague, aucun exemple.
Lequel choisir ?
Une règle pragmatique : plus une API a de consommateurs, et moins vous les contrôlez, plus le contract-first est rentable. Les API publiques, les intégrations partenaires et les contrats entre équipes distinctes méritent une approche contract-first. Un endpoint interne consommé par un seul frontend appartenant à la même équipe peut être code-first -- tant que le contrat généré reste publié, versionné et vérifié contre les breaking changes.
Beaucoup d'équipes matures convergent vers un hybride : code-first pour la vitesse, avec des garde-fous CI au niveau du contrat (détection de breaking changes, linting du schéma) qui leur donnent l'essentiel de la sécurité du contract-first.
Les tests de contrat d'API
Un contrat que rien ne vérifie est un vœu pieux. Le test de contrat d'API est la pratique consistant à vérifier automatiquement que fournisseurs et consommateurs respectent bien l'interface convenue. Trois techniques dominent.
Les tests de contrat pilotés par le consommateur
Dans les tests de contrat pilotés par le consommateur -- popularisés par Pact -- chaque consommateur enregistre les interactions précises dont il dépend : "quand je fais un GET sur /orders/123, j'attends un 200 avec un corps contenant id, status et total." Ces attentes enregistrées forment un contrat qui est ensuite rejoué contre le fournisseur dans sa pipeline CI.
La force de cette approche, c'est la précision. Le fournisseur sait exactement quels champs chaque consommateur utilise réellement. Vous voulez supprimer un champ ? Les tests de contrat vous disent immédiatement si un consommateur va casser -- avant le déploiement, pas après.
La validation de schéma en CI
La technique plus simple et plus large : valider que l'implémentation correspond à la spec publiée.
- Exécuter des requêtes contre le service et valider les réponses contre les schémas OpenAPI.
- Utiliser un middleware de validation qui rejette toute réponse non conforme au contrat (très utile en staging).
- Linter la spec elle-même pour la complétude et le style (Spectral et outils similaires).
Cela attrape le mode de défaillance le plus courant -- la spec dit une chose, le code en fait une autre -- à bas coût et en continu.
La détection de breaking changes
Enfin, diffez le contrat lui-même. Des outils comme oasdiff (OpenAPI), Buf (protobuf) et GraphQL Inspector comparent la nouvelle version d'une spec à la précédente et classifient chaque changement : additif (sûr), ou cassant (champ supprimé, type modifié, nouveau paramètre obligatoire). Branchez ça dans la CI et un breaking change devient un build en échec qui exige une approbation explicite et délibérée -- au lieu d'une surprise silencieuse pour vos consommateurs.
Si vous ne retenez qu'une chose de cette section, retenez celle-ci. La détection de breaking changes est peu coûteuse à mettre en place et attrape les pannes qui font le plus mal.
Pourquoi les contrats d'API ont leur place dans votre documentation d'architecture
Voici la partie que la plupart des équipes manquent. Vous pouvez avoir de beaux fichiers OpenAPI, des suites Pact rigoureuses et des garde-fous de breaking changes en CI -- et rester incapable de répondre à la question qui compte quand quelque chose doit changer : "qui dépend de ce contrat ?"
Un fichier de contrat dans un repository décrit une interface, mais ne dit rien de son contexte. Quel service l'implémente ? Quels services, frontends et partenaires le consomment ? Si on déprécie cet endpoint, qu'est-ce qui casse vraiment ? Cette connaissance vit généralement dans la tête des gens, ce qui veut dire qu'elle se dégrade à chaque changement d'équipe.
C'est là que documentation d'architecture et contrats d'API ont besoin l'un de l'autre :
- Un contrat sans contexte architectural devient obsolète sans que personne ne le voie. Personne ne remarque l'
openapi.yamlorphelin qui décrit un service réécrit l'an dernier, parce que rien ne le connecte au système qu'il décrit. - Un diagramme d'architecture sans contrats est imprécis. Une flèche étiquetée "REST/JSON" entre deux boîtes vous dit qu'une relation existe, pas ce qui y circule. Le contrat est ce qui donne son sens à la flèche.
Le modèle C4 fournit la structure naturelle pour cette connexion : les contrats s'attachent aux containers et composants qui les implémentent et les consomment (voir notre entrée de glossaire sur le modèle C4 pour un rappel rapide de ces termes). Le container API Gateway porte son contrat OpenAPI. Le microservice interne porte son fichier proto. Les services centrés sur Kafka portent le document AsyncAPI qui définit leurs channels.
C'est exactement ainsi que fonctionne la fonctionnalité API Contracts d'Archyl : vous importez des contrats OpenAPI, gRPC, GraphQL, AsyncAPI ou MCP -- synchronisés depuis git ou collés directement -- et vous les liez aux éléments C4 de votre modèle d'architecture. Les liens sont bidirectionnels : depuis un contrat, vous voyez quels éléments l'implémentent et le consomment, et depuis n'importe quel élément du diagramme, vous pouvez ouvrir les specs qui décrivent ses interfaces. Quand un contrat change, vous voyez d'un coup d'œil quelles parties de l'architecture sont dans le rayon d'impact, au lieu de reconstruire la carte des dépendances à partir de la mémoire collective. Nous avons détaillé la fonctionnalité dans API Contracts : vos spécifications d'API, liées à votre architecture.
Le principe tient indépendamment de l'outillage : un contrat a le plus de valeur quand il vit à côté des éléments d'architecture qu'il lie, pas dans un dossier que personne n'ouvre.
Bonnes pratiques des contrats d'API : la checklist
Un contrat est un engagement de long terme, traitez-le comme tel :
- Établissez une source de vérité unique. Un emplacement canonique par contrat. Si la spec existe à trois endroits, elle existe à zéro endroit. Que ce soit un repo git ou une plateforme d'architecture comme Archyl, tout le monde doit savoir où vit la version faisant autorité.
- Versionnez explicitement. Donnez une version à chaque contrat, et définissez ce que signifie une montée de version. Le versionnement sémantique fonctionne bien : les changements additifs incrémentent la version mineure, les breaking changes la version majeure.
- Ne cassez jamais sans version majeure. Supprimer un champ, changer un type, ajouter un paramètre obligatoire, durcir une validation -- tout cela casse. Cela exige une nouvelle version majeure ou un nouvel endpoint, plus un chemin de migration.
- Écrivez une politique de dépréciation et respectez-la. Marquez les opérations dépréciées dans la spec, communiquez une date de fin de vie, donnez aux consommateurs une fenêtre réaliste (des mois, pas des jours), et surveillez l'usage avant la suppression.
- Revoyez les changements de contrat comme des changements de code. Un diff de schéma mérite au moins autant de scrutin qu'un diff d'implémentation -- il a plus de consommateurs.
- Automatisez le contrôle. Validation de schéma et détection de breaking changes en CI. Les humains s'accordent sur le contrat ; les machines le font respecter.
- Documentez les erreurs et l'authentification, pas seulement le happy path. Les 400 et les 401 sont là où les consommateurs passent leur temps de débogage. Spécifiez-les.
- Liez les contrats à votre architecture. Chaque contrat devrait être traçable vers les composants qui l'implémentent et ceux qui le consomment, pour que l'analyse d'impact soit une simple consultation, pas une enquête.
Foire aux questions
Quelle est la différence entre un contrat d'API et la documentation d'API ?
La documentation d'API est écrite pour les humains : guides, tutoriels, exemples, explications de concepts. Un contrat d'API est une spécification formelle, lisible par machine, que les humains comme les outils consomment -- il peut générer du code, valider des requêtes, alimenter des mocks et faire échouer des builds CI. Une bonne documentation est souvent générée à partir du contrat, mais le contrat est l'artefact qui engage : la documentation décrit l'API, le contrat la définit.
Qu'est-ce que le développement contract-first ?
Le développement contract-first (ou design-first) consiste à écrire et valider la spécification d'API -- le document OpenAPI, le fichier proto ou le schéma GraphQL -- avant de l'implémenter. Consommateurs et fournisseurs construisent ensuite en parallèle contre la même interface convenue. Cela déplace la discussion de design en amont, permet le travail en parallèle, et fait du contrat un engagement délibéré plutôt qu'un sous-produit du code.
Qu'est-ce que le test de contrat d'API ?
Le test de contrat d'API vérifie automatiquement que fournisseurs et consommateurs respectent l'interface convenue. Il englobe les tests de contrat pilotés par le consommateur (à la Pact, où les attentes des consommateurs sont rejouées contre le fournisseur), la validation de schéma en CI (vérifier que l'implémentation correspond à la spec) et la détection de breaking changes (differ les versions de la spec pour signaler les changements incompatibles avant la release).
Les API internes ont-elles aussi besoin de contrats ?
Oui -- sans doute encore plus, parce que les API internes changent plus vite et sont protégées par moins de formalisme. Le contrat peut être plus léger (la génération code-first convient très bien), mais il doit rester publié, versionné et vérifié contre les breaking changes. La plupart des incidents de production causés par des changements d'API sont causés par des changements d'API internes.
Prêt à donner un foyer à vos contrats d'API au sein de votre architecture ? Découvrez la fonctionnalité API Contracts d'Archyl -- contrats OpenAPI, gRPC, GraphQL, AsyncAPI et MCP, liés à votre modèle C4. Ou poursuivez la lecture : API Contracts : vos spécifications d'API, liées à votre architecture | Les outils MCP comme contrats d'API | Qu'est-ce que le modèle C4 ? Guide complet.