What is OpenAPI ?
Definition:
standard[] on how APIs are described [...] focused on creating, evolving and promoting a vendor neutral description format. The OpenAPI Specification was originally based on the Swagger Specification, donated by SmartBear Software.
OpenApi and Swagger UI
OpenApi can be used to document a web api and Swagger-ui to display it in a user friendly way. The combination of both tools make it possible to play with the documented API to try it out and have a better understanding of what it does and how to use it.
1. The documentation displays what resources the API provides:
- JSON objects to expect
- Structure of those JSON objects
- Http Methods to expect
2. The documentation displays how to access them:
- Http Methods to use
- Paths to use
- What query parameters to use
- What JSON objects to send if any
- Structure of those JSON objects
There are screenshots below of such documentation using Swagger UI on a Java Spring Boot project dedicated to retrieve data from https://www.domaine.nc via a HTTP API.
For more information about domaine.nc: See its Dev.to serie
Those pieces of information are essential for the understanding and good use of the HTTP API.
Unknown need
An open source project dedicated to memes, imgflip-api, is documented in part thanks to Swagger UI.
Adriens & Ronny.S – the two contributors of this project
wanted to have a custom and richer API than the official one [...] with Swagger documentation
– Source: readme.md
See screenshots below of this project documentation:
As highlighted on the pictures, this documentation is richer and, thus, more precise than the previous example.
The details added compared to the previous example are:
- Textual description of the API
- Textual description of the resources provided by the API
- Textual description of the request parameters accepted by the API:
- Path
- Query
Those details might seem a bit unnecessary if the API ressources, request parameters and response bodies are named well enough to communicate the API's intent. However, "the devil is in the details".
In the first example, it seems like there was enough information to infer the intent of each resource put at our disposal until we look at the "badge" resource.
The intent of this resource is not precise. It provides a badge in a .svg format but does not give any information about the badge itself.
There are two plausible solutions to this issue:
- Rename the resource from "badge.svg" to "expiration-date-and-status-badge.svg"
- Add a concise description to the resource (see screenshots below)
Java Annotation for Better Documentation
There is below a snippet from imgflip-api - PublishedMemesController.java:
@RestController
@Tag(name = "Published memes", description = "Published memes related resources")
@RequestMapping(produces = MediaType.APPLICATION_JSON_VALUE)
public class PublishedMemesController {
...
@GetMapping("/top/{stream}/last/30d")
@Operation(summary = "Get the top memes since last 30 days for a stream",
description = "Top meme's list (page) since 30 last days for a stream and given page number.")
public List<PublishedMeme> getTop30d(
@Parameter(description = "Stream name", example = "gaming") @PathVariable String stream,
@Parameter(description = "Page number") @RequestParam(value="page", defaultValue = "1") int page) throws IOException{
return publishedMemesService.getTopThirtyDayPageOfHotStream(stream, page);
}
...
}
The java annotation for describing grouped resources is:
@Tag(name = "Published memes",
description = "Published memes related resources")
The java annotation used for describing a resource is:
@Operation(summary = "Get the top memes since last 30 days for a stream",
description = "Top meme's list (page) since 30 last days for a stream and given page number.")
The java annotation used for describing request paths and queries is:
@Parameter(description = "Stream name", example = "gaming")
...
@Parameter(description = "Page number")
There are also annotations to describe the potential responses a user can receive.
There is below a snippet for domaine-nc-api with the controller responsible to provide a badge.svg:
@Operation(summary = "Get the svg badge of the specified domain with expiration date and lastUpdate color.",
description = "Color scheme is: "
+ "<ul><li>green: domain is valid</li>"
+ "<li>red: domain is expired</li>"
+ "<li>yellow: domain is about to expire</li></ul>")
@ApiResponses(value = {
@ApiResponse(responseCode = "200",
description = "Retrieve the badge.svg thanks to the redirect",
content = @Content(mediaType = "image/svg+xml")),
@ApiResponse(responseCode = "303",
description = "Redirect to https://img.shields.io/badge/{domaine-name}-{expiration-date}-{color}",
content = @Content(mediaType = "image/svg+xml")),
@ApiResponse(responseCode = "400",
description = "Bad request. Invalid extension",
content = @Content(mediaType = MediaType.ALL_VALUE)),
@ApiResponse(responseCode = "404",
description = "Domaine not found",
content = @Content(mediaType = MediaType.ALL_VALUE))
})
@GetMapping(value = "/{name}/{extension}/badge.svg")
public ResponseEntity<Object> redirectToExternalUrl(
@Parameter(description = "domain name") @PathVariable(value = "name") String name,
@Parameter(description = "domain extension") @PathVariable(value = "extension") String extension) { ... }
This is the corresponding documentation:
The annotations below have already been introduced:
@Operation(summary = "Get the svg badge of the specified domain with expiration date and lastUpdate color.",
description = "Color scheme is: "
+ "<ul><li>green: domain is valid</li>"
+ "<li>red: domain is expired</li>"
+ "<li>yellow: domain is about to expire</li></ul>")
...
@Parameter(description = "domain name")
@Parameter(description = "domain extension")
This is the documentation produced by using them:
The annotations used to describe the potential responses are the following:
@ApiResponses(value = {
@ApiResponse(responseCode = "200",
description = "Retrieve the badge.svg thanks to the redirect",
content = @Content(mediaType = "image/svg+xml")),
@ApiResponse(responseCode = "303",
description = "Redirect to https://img.shields.io/badge/{domaine-name}-{expiration-date}-{color}",
content = @Content(mediaType = "image/svg+xml")),
@ApiResponse(responseCode = "400",
description = "Bad request. Invalid extension",
content = @Content(mediaType = MediaType.ALL_VALUE)),
@ApiResponse(responseCode = "404",
description = "Domaine not found",
content = @Content(mediaType = MediaType.ALL_VALUE))
})
This is the documentation produce with Swagger UI:
Thanks to this documentation, the user knows what errors it might receive and the corresponding issues he needs to solve.
The documentation also shows the "happy path" to retrieve the badge.svg and, in this particular example, the intermediary step to get one: the use of a third party HTTP API through a HTTP 303 See Other redirection – shield.io.
💰 Day to Day Impact
Developers who care about the documentation of their HTTP API will use those annotations for the Spring Boot projects they are in charge of. Those annotations will help them to write concise and precise descriptions of their API.
They are short and easy to use which helps developers to document their code in an effective and efficient way.
By using those annotations developers will reap the benefits of a well documented API:
- Less time spent to answer clients' questions such as:
- What does this API do ?
- How to use this API ?
- What response is it supposed to send ?
- What does the body response (JSON object) represent ?
- Less frustrated clients
- More clients
- More happy clients ❤️
Happy Documenting !