Partons d'un constat, une situation que beaucoup d'entre nous ont sans doute rencontrée :
- Une UI swagger avec beaucoup, mais alors beaucoup d'endpoints,
- Des API V1 qui cohabitent avec des V2 en attendant la migration (2 ans qu'on l'attend celle-là),
- Et pire que tout, des endpoints techniques visibles et qui peuvent être appelés par les clients.
Springdoc règle ces trois problèmes en quatre fonctionnalités. Voici lesquelles.
Découper la documentation avec GroupedOpenApi
Le problème
Une API qui vit assez longtemps finit presque toujours par accumuler plusieurs versions en parallèle :
/api/v1/** → l'ancien monde
/api/v2/** → le nouveau, pas encore adopté par tout le monde
On ne peut pas juste supprimer la V1 : des clients l'utilisent encore. Mais on ne veut pas non plus que les nouveaux consommateurs s'y perdent.
Même souci quand plusieurs publics partagent la même application : API publique, outils internes, portail admin.
Par défaut, Swagger UI mélange tout ça dans une seule liste, sans distinction.
La solution
Créer une configuration de regroupement des API
@Bean
public GroupedOpenApi v1Api() {
return GroupedOpenApi.builder()
.group("v1")
.pathsToMatch("/api/v1/**")
.build();
}
@Bean
public GroupedOpenApi v2Api() {
return GroupedOpenApi.builder()
.group("v2")
.pathsToMatch("/api/v2/**")
.build();
}
Ici, on les groupe par path, mais on peut aussi très bien les grouper par package.
Swagger affichera alors un sélecteur pour choisir la version qui nous intéresse.

Faire disparaître les endpoints techniques : @Hidden
Le problème
Endpoints de debug, de purge de cache, APIs temporaires de migration : ils traînent en prod et remontent dans Swagger UI, alors qu'ils n'ont rien à faire devant des consommateurs externes.
La solution
Utiliser l'annotation @Hidden, soit sur le controller entier
@Hidden
@RestController
@RequestMapping("/internal")
public class InternalController {
@PostMapping("/cache/refresh")
public void refreshCache() {
}
}Soit sur la méthode concernée
@Hidden
@PostMapping("/debug")
public void debug() {
}Pourquoi ça compte
Documenter un endpoint, c'est dire implicitement à nos consommateurs : « tu peux l'utiliser ». @Hidden garde l'endpoint fonctionnel (la CI peut toujours l'appeler) sans le promouvoir comme partie du contrat public.
Ranger par métier, pas par technique : les tags
Le problème
Par défaut, Swagger trie par contrôleur :
BookController → GET/POST /books
AuthorController → GET/POST /authors
LoanController → POST/GET /loans

Cette organisation est parfaitement logique pour les développeurs qui travaillent sur le code source. Après tout, les contrôleurs représentent souvent les points d'entrée de l'application.
Le problème apparaît lorsque la documentation est consultée par d'autres équipes : développeurs consommateurs de l'API, testeurs, intégrateurs ou partenaires externes. Ces utilisateurs ne connaissent pas forcément l'architecture interne de votre application. Ils raisonnent généralement en termes de fonctionnalités métier :
- Comment rechercher un livre ?
- Comment gérer un auteur ?
- Comment enregistrer un emprunt ?
Une documentation organisée uniquement par contrôleurs oblige alors à parcourir plusieurs sections avant de trouver l'information recherchée.
La solution
Les tags OpenAPI permettent de regrouper les endpoints selon une logique métier plutôt que technique.
@Tag(name = "Catalogue", description = "Gestion du catalogue de livres")
@RestController
@RequestMapping("/books")
public class BookController {
}
@Tag(name = "Auteurs", description = "Gestion des auteurs")
@RestController
@RequestMapping("/authors")
public class AuthorController {
}
@Tag(name = "Emprunts", description = "Tout ce qui touche les emprunts")
@RestController
@RequestMapping("/loans")
public class LoanController {
}
Swagger affichera alors des sections clairement identifiées correspondant aux concepts fonctionnels de l'application.
Pourquoi c'est important ?
Une bonne documentation ne se limite pas à lister des endpoints. Elle doit aider un utilisateur à comprendre rapidement les capacités offertes par l'API.
Des tags bien choisis apportent plusieurs bénéfices :
- Une navigation plus intuitive ;
- Une meilleure compréhension du domaine métier ;
- Une documentation plus accessible pour les nouveaux arrivants ;
- Une expérience plus agréable pour les consommateurs de l'API.
Dans les projets de taille importante, où plusieurs dizaines, voire centaines d'endpoints coexistent, cette simple organisation fait souvent la différence entre une documentation agréable à utiliser et une documentation dans laquelle on se perd rapidement.
ℹ️ Un point souvent méconnu : un tag n'est pas lié à un contrôleur unique. Plusieurs contrôleurs peuvent partager le même tag afin de regrouper des fonctionnalités qui appartiennent au même domaine métier.
Matérialiser le contrat : générer OpenAPI au build
Le problème
Swagger UI, c'est bien pour explorer en dev. Le vrai contrat d'une API, c'est un fichier (openapi.json ou .yaml) qui peut être versionné dans Git, transmis à une équipe cliente, analysé en CI/CD, ou utilisé pour générer un SDK.
Le problème : généré à la volée, ce fichier n'est jamais figé.
On veut qu'il soit stable et reproductible à chaque build.
La solution
Springdoc propose un plugin Maven capable de générer automatiquement la spécification OpenAPI lors du build.
<plugin>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-maven-plugin</artifactId>
<version>${springdoc.version}</version>
<executions>
<execution>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
</plugin>Une fois configuré, le plugin s'exécute automatiquement pendant le cycle Maven et produit un fichier openapi.json ou openapi.yaml dans le répertoire target/.
L'avantage est qu'aucune action manuelle n'est nécessaire : la spécification est générée à partir du code de l'application et reste synchronisée avec les annotations OpenAPI présentes dans les contrôleurs.
Cette génération automatique évite également les écarts entre la documentation et l'implémentation réelle de l'API, un problème fréquent lorsque les fichiers OpenAPI sont maintenus à la main.
Conclusion
La plupart des équipes utilisent Swagger UI comme une simple page de test pour leurs endpoints. Pourtant, OpenAPI va bien plus loin que l'affichage automatique d'une documentation.
En quelques fonctionnalités souvent sous-exploitées, il devient possible de structurer une API par version avec GroupedOpenApi, de masquer les endpoints qui ne font pas partie du contrat public grâce à @Hidden, d'organiser la documentation autour du métier avec les tags, et de produire une spécification versionnable directement au build.
Aucune de ces pratiques n'est révolutionnaire individuellement. Mais combinées, elles transforment une documentation subie en un véritable contrat d'API, plus clair pour les consommateurs, plus simple à maintenir pour les équipes et plus fiable dans le temps.
Une bonne API ne se limite pas à exposer des endpoints. Elle doit aussi être facile à comprendre, à explorer et à intégrer. C'est précisément là que ces quelques fonctionnalités OpenAPI font toute la différence.



