Skip to main content

Command Palette

Search for a command to run...

Effortless API Documentation in Spring Boot with OpenAPI

Published
5 min readView as Markdown
Effortless API Documentation in Spring Boot with OpenAPI
M

I’m a backend software engineer with over a decade of experience primarily in Java. I started this blog to share what I’ve learned in a simplified, approachable way — and to add value for fellow developers. Though I’m an introvert, I’ve chosen to put myself out there to encourage more women to explore and thrive in tech. I believe that by sharing what we know, we learn twice as much — that’s precisely why I’m here.

When designing an API, we make many frontend decisions such as response structure, pagination strategy, and error handling. We can capture these design choices using an API description language—and OpenAPI is one of the most widely used descriptor languages for REST APIs.

OpenAPI (formerly Swagger) has become the industry standard for describing APIs, making them easier to understand, document, and consume.

At its core, OpenAPI defines an API’s structure in a machine-readable format (YAML or JSON). For example, a simple OpenAPI definition for retrieving blog posts might look like this:

openapi: 3.0.1
info:
  title: Blog API
  version: 1.0.0
paths:
  /posts:
    get:
      summary: Get all posts
      responses:
        "200":
          description: Successfully retrieved list

With OpenAPI, you can automate API documentation, generate client SDKs, and improve developer experience.

For Spring Boot projects, we can use the springdoc-openapi library, which automatically generates API documentation by scanning Spring configurations, class structures, and annotations at runtime.

With just a simple setup, you can hit the ground running. Let’s get started! 🚀

Getting started

To integrate Spring Boot with OpenAPI, simply add the springdoc-openapi library to your project dependencies—no additional configuration is needed!

📌 Add the dependency to pom.xml

<dependency>
    <groupId>org.springdoc</groupId>
    <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
    <version>2.3.0</version>
</dependency>

Restart your Spring Boot application, and now you can access Swagger UI, which displays all of your endpoints in an interactive format.

📌 Visit Swagger UI:

http://localhost:8080/swagger-ui.html

In addition, after starting your Spring Boot project, Springdoc automatically generates an OpenAPI definition based on your controllers and annotations.

📌 You can view the raw OpenAPI spec at:

http://localhost:8080/v3/api-docs

Enhancing API Documentation:

This initial setup is great, but to make the API more developer-friendly, we should add more details using annotations.

For example, let’s document the GET /posts endpoint:

@GetMapping
@Operation(
    summary = "Get all posts",
    description = "Retrieve a list of all posts",
    responses = {
        @ApiResponse(responseCode = "200", description = "Successfully retrieved list",
            content = @Content(mediaType = "application/json",
            schema = @Schema(implementation = PostDto.class))
        )
    }
)
public List<PostDto> getAllPosts() {

    return service.getAllPosts();

}

Now, restart your Spring Boot application, and you’ll see detailed documentation for this operation in Swagger UI:

Troubleshooting: Swagger UI Not Updating?

Sometimes, Swagger UI caches old versions of your API. If your changes aren’t showing up, try these steps:

1️⃣ Clean and restart your app

2️⃣ Clear your browser cache or open Swagger UI in Incognito Mode.
3️⃣ Manually refresh the API documentation:

Key OpenAPI Annotations in Spring Boot

AnnotationPurpose
@OperationDescribes API endpoints (summary, description)
@ParameterDocuments path/query parameters
@RequestBodyDescribes JSON request bodies
@ApiResponseDefines HTTP response codes
@SchemaDocuments DTOs and fields
@ExampleObjectProvides sample request/response JSON
@SecurityRequirementDocuments authentication requirements

Now, let’s see how each of these works in practice:

1️⃣ Documenting API Endpoints

🔹 @Operation (Defines API Endpoint Details)

  • Provides summary, description, and tags for an API method.

Example:

@GetMapping
@Operation(
    summary = "Get all posts",
    description = "Retrieve a list of all posts"
)
public List<PostDto> getAllPosts() {
    return service.getAllPosts();
}

2️⃣ Documenting Request Parameters

🔹 @Parameter (Describes Path and Query Parameters)

  • Adds metadata to @PathVariable or @RequestParam.

Example:

@GetMapping("/{id}")
@Operation(summary = "Get a post by ID")
public PostDto getPostById(
    @Parameter(description = "ID of the post", example = "1")
    @PathVariable long id
) {
    return service.getPostById(id);
}

3️⃣ Documenting Request Bodies

🔹 @RequestBody (Describes JSON Request Body)

  • Provides a description of the request body format.

Example:

@PostMapping
@Operation(summary = "Create a new post")
public ResponseEntity<PostDto> createPost(
    @io.swagger.v3.oas.annotations.parameters.RequestBody(
        description = "Post details",
        required = true
    )
    @Valid @RequestBody NewPostDto post
) {
    return ResponseEntity.status(201).body(service.createPost(post));
}

One use case for this is: When you need to support multiple content types (JSON, XML, etc)


4️⃣ Documenting API Responses

🔹 @ApiResponse (Describes Possible HTTP Responses)

  • Defines response codes, descriptions, and schemas.

Example:

@Operation(
    summary = "Delete a post",
    responses = {
        @ApiResponse(responseCode = "204", description = "Post deleted"),
        @ApiResponse(responseCode = "404", description = "Post not found")
    }
)
@DeleteMapping("/{id}")
public ResponseEntity<Void> deletePost(@PathVariable long id) {
    service.deletePost(id);
    return ResponseEntity.noContent().build();
}

5️⃣ Documenting Response Models

🔹 @Schema (Describes DTOs and Fields)

  • Used inside DTO classes to provide descriptions and example values.

Example:

@Schema(description = "DTO for creating a post")
public record NewPostDto(
    @Schema(description = "Title of the post", example = "My first post")
    String title,
    @Schema(description = "Content of the post", example = "This is a sample post")
    String content
) {}

6️⃣ Adding Example Values

🔹 @ExampleObject (Provides Sample JSON Data)

  • Used inside @Content to show example request/response bodies.

Example:

@ApiResponse(
responseCode = "200",
    description = "Post retrieved",
    content = @Content(
        mediaType = "application/json",
        examples = @ExampleObject(
            name = "Example Response",
            value = """
            {
                "id": 1,
                "title": "My first post",
                "content": "This is a sample post."
            }
            """
        )
    )
)

7️⃣ Securing APIs

🔹 @SecurityRequirement (Indicates Authentication Requirements)

  • Used to specify that an API requires JWT or OAuth authentication.

Example:

@Operation(
    summary = "Get user details",
    security = { @SecurityRequirement(name = "bearerAuth") }
)

@GetMapping("/user")
public UserDto getUserDetails() {
    return userService.getUserDetails();
}

🚀 Conclusion

With OpenAPI and Springdoc, you can automate and simplify API documentation in your Spring Boot applications. Using annotations, you provide clear, structured, and interactive API docs—making it easier for developers to understand and use your API.

Now go ahead and document your Spring Boot API effortlessly! 🚀

📌 Explore More

Want to see this in action? Check out my project on GitHub:🔗 GitHub Repo

Learn More:

More from this blog

Code Like a Woman

40 posts

Code, learnings, and experiences from a Latina in tech.