Published 2026-08-13 by Shubham Bhati — Backend Engineer (Java 17, Spring Boot, Microservices).
API Documentation with OpenAPI 3 and Swagger in Spring Boot
By Shubham Bhati, Backend Engineer (Java 17, Spring Boot, Microservices)
Ever wasted hours trying to understand an undocumented API? Or struggled onboarding new team members because your REST endpoints were a mystery? That pain point is real, and it costs engineering teams time and money. Good API documentation isn't a luxury; it's a necessity. With OpenAPI 3 and Swagger UI, you can transform your Spring Boot applications into self-documenting powerhouses. This guide shows you how to integrate these tools, making your APIs discoverable, understandable and easy to consume for anyone using your openapi swagger spring boot services.
Getting Started with springdoc-openapi
Integrating OpenAPI 3 and Swagger UI into your Spring Boot application is surprisingly straightforward, thanks to the springdoc-openapi library. This library automatically generates API documentation from your Spring annotations, serving it as an OpenAPI 3 specification and providing a beautiful, interactive Swagger UI.
To begin, add the springdoc-openapi-starter-webmvc-ui dependency to your pom.xml. This single dependency brings in everything you need for both the OpenAPI spec generation and the Swagger UI.
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
<version>2.3.0</version> <!-- Use the latest stable version -->
</dependency>
After adding this, simply restart your Spring Boot application. By default, your Swagger UI will be accessible at http://localhost:8080/swagger-ui.html and the raw OpenAPI JSON specification at http://localhost:8080/v3/api-docs. For production, we often deploy these docs behind an API gateway or static file server. The overhead introduced by this library is minimal, primarily at application startup when the spec is generated, meaning it won't impact your API call latency or HikariCP connection pooling performance during runtime. It's a low-cost, high-value addition.
Documenting Your API Endpoints
Once springdoc-openapi is set up, you can start enriching your API documentation using annotations directly on your controllers and DTOs. This approach keeps your documentation tightly coupled with your code, reducing drift. Key annotations from io.swagger.v3.oas.annotations include @Operation for method-level details, @ApiResponse for defining responses, and @Parameter for describing path or query variables.
Consider a simple ProductController:
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/api/v1/products")
@Tag(name = "Product Management", description = "Operations related to product resources")
public class ProductController {
@Operation(summary = "Get a product by ID", description = "Retrieve details for a single product.",
responses = {
@ApiResponse(responseCode = "200", description = "Product found",
media = @Content(schema = @Schema(implementation = Product.class))),
@ApiResponse(responseCode = "404", description = "Product not found")
})
@GetMapping("/{id}")
public ResponseEntity<Product> getProductById(@Parameter(description = "ID of the product to retrieve")
@PathVariable Long id) {
// Assume service call here
if (id == 1L) { // Example
return ResponseEntity.ok(new Product(id, "Laptop", 1200.00));
}
return ResponseEntity.notFound().build();
}
// Dummy Product class for illustration
static class Product {
public Long id;
public String name;
public Double price;
public Product(Long id, String name, Double price) { this.id = id; this.name = name; this.price = price; }
}
}
This snippet provides clear descriptions for an operation, its parameters, and expected responses. In a production environment, clear documentation like this significantly reduces time spent in integration meetings and debugging external client issues. It also helps manage memory footprint by defining exactly what data is expected and returned, preventing unexpected large payloads that can strain JVM heap usage.
Customizing Swagger UI and OpenAPI Specs
While the defaults are good, you'll often need to customize your OpenAPI specification and Swagger UI for branding, security definitions, or environment-specific details. This is usually done via application.yaml or a dedicated configuration class.
A common customization is to add global API information, server URLs for different environments, and security schemes (like JWT authentication).
springdoc:
swagger-ui:
path: /docs # Custom UI path
tagsSorter: alpha # Sort tags alphabetically
operationsSorter: alpha # Sort operations alphabetically
api-docs:
path: /api-docs/json # Custom OpenAPI spec path
info:
title: My Service API
description: "API for managing customer and product data."
version: 1.0.0
terms-of-service: "http://example.com/terms"
contact:
name: Shubham Bhati
url: http://mycompany.com
email: shubham@mycompany.com
license:
name: Apache 2.0
url: https://www.apache.org/licenses/LICENSE-2.0.html
servers:
- url: http://localhost:8080
description: Local Development Server
- url: https://api.staging.example.com
description: Staging Environment
- url: https://api.production.example.com
description: Production Environment
security:
- bearerAuth: [] # Refers to a security scheme defined below
components:
securitySchemes:
bearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
description: "JWT authorization header using the Bearer scheme. Example: 'Bearer {token}'"
These configurations enhance the API documentation for consumers. Defining multiple servers is crucial for client teams testing against different environments. Documenting securitySchemes ensures that clients know how to authenticate, which is vital for maintaining security and reducing support queries about 401 Unauthorized responses. Keeping these configurations concise helps maintain clarity without impacting application startup time or p99 latency once the service is running.
Common Pitfalls
- Out-of-sync Documentation: The biggest pitfall is neglecting to update documentation when API endpoints change. Treat your annotations as part of your API contract; any change to the API should include an update to its documentation.
- Security Configuration Mismatches: Forgetting to define or incorrectly configuring security schemes (like JWT Bearer tokens) in your
application.yamlor@SecuritySchemeannotations leads to confusion for API consumers trying to authenticate. - Over-documentation / Under-documentation: Finding the right balance is key. Too much detail can clutter the UI; too little leaves crucial information missing. Focus on critical parameters, responses, and security requirements.
- Large API Specifications: For very large microservices or monolithic applications, the generated OpenAPI JSON spec can become quite large. This can slow down the Swagger UI load time for developers, especially over slower network connections. Consider breaking down documentation for very large services or optimizing your configuration.
Conclusion
API documentation with OpenAPI 3 and Swagger UI is a small investment that pays massive dividends in clarity, developer velocity and team collaboration. By integrating springdoc-openapi into your Spring Boot projects and leveraging annotations, you transform your codebase into a powerful, self-documenting system. Make documentation a core part of your development lifecycle, not an afterthought. Your future self and your fellow developers will thank you.
Further Reading
Written by **Shubham Bhati* — Backend Engineer at AlignBits LLC, specializing in Java 17, Spring Boot, microservices, and AI integration. Connect on LinkedIn, GitHub, or read more at shubh2-0.github.io.*
Top comments (0)