APIs have become an integral part of modern software development, allowing applications to communicate with each other and exchange data. However, building an API is only half the battle. Without proper documentation, developers may struggle to understand how to use the API, leading to wasted time and resources. This is where API documentation comes in.
OpenAPI is a widely used specification for describing RESTful APIs. With its powerful schema and documentation capabilities, it is now the de facto standard for API documentation. In this article, we will explore the importance of API documentation, introduce OpenAPI, and provide examples of how to write OpenAPI documentation using Go.
Let's dive in!
What is an API?
An API, or Application Programming Interface, is a set of protocols, routines, and tools for building software applications. APIs allow different applications to communicate with each other, making it easier to share data and functionality. APIs can take many different forms, including RESTful APIs, SOAP APIs, and GraphQL APIs.
RESTful API
RESTful APIs adhere to the principles of Representational State Transfer (REST). RESTful APIs use HTTP requests to interact with web resources and represent resources as URLs. This makes it easy to use standard HTTP verbs such as GET, POST, PUT, and DELETE to manipulate resources.
SOAP API
A SOAP API, (Simple Object Access Protocol) is a protocol for exchanging XML-based messages over a network. It uses a set of rules for sending and receiving messages, and is typically used in enterprise-level applications.
GraphQL API
GraphQL is a newer API technology that provides a more flexible way of requesting data. It allows developers to send a single request to the server, specifying the exact data they need. This can help reduce the number of requests needed to retrieve data, and can improve performance.
Why Document APIs?
Clear and concise documentation is essential for any API. It can improve adoption and developer experience, leading to faster development times and improved quality.
Proper API documentation should include a description of the API, its endpoints, and its input and output parameters. It should also be written with the target audience in mind and include examples of how to use the API, along with any error codes that may be returned.
Introducing OpenAPI
OpenAPI was formerly known as Swagger and has since become the standard for API documentation. OpenAPI allows you to define your API using a JSON
or YAML
file and provides a wide range of documentation features.
The key components of an OpenAPI specification include:
Info: This provides basic information about the API, including its title, version, and description.
Paths: The Paths define the different endpoints of the API, along with their input and output parameters.
Parameters: This defines the input and output parameters for each endpoint, including their data type and any restrictions.
Responses: This defines the different responses that can be returned by the API, including their status codes and any error messages.
Best practices for writing OpenAPI 3 documentation
Now that we have a basic understanding of OpenAPI, let's look at how we can use it to document APIs. Writing documentation is not an easy task, but OpenAPI provides a clear and structured way of describing APIs. Some best practices include:
Use clear and concise language: Avoid using technical jargon on technical terms that may not be familiar to the intended audience.
Provide examples and use cases: This helps developers understand how to use the API in real-world scenarios.
Use formatting and organization: Use headings, bullet points, and other formatting options to make the documentation easy to read and navigate.
Keep the documentation up to date: As the API changes, so should the documentation. Make sure to keep it up to date so that it remains a useful resource.
An Example of Documenting APIs with OpenAPI 3 in Go
Let's say we have an API that allows users to retrieve information about books. Here's how we can use OpenAPI 3 to document it:
- The
main.go
file that contains the Go API:
package main
import (
"log"
"net/http"
"strconv"
"github.com/go-chi/chi"
"github.com/go-chi/chi/middleware"
"github.com/go-chi/render"
)
type Book struct {
ID int `json:"id"`
Title string `json:"title"`
Author string `json:"author"`
}
var books = []Book{
{1, "The Go Programming Language", "Alan A. A. Donovan, Brian W. Kernighan"},
{2, "Designing Data-Intensive Applications", "Martin Kleppmann"},
{3, "Code Complete", "Steve McConnell"},
}
func main() {
r := chi.NewRouter()
r.Use(middleware.Logger)
r.Use(render.SetContentType(render.ContentTypeJSON))
r.Get("/books/{id}", GetBook)
log.Println("Starting server on :3000")
http.ListenAndServe(":3000", r)
}
func GetBook(w http.ResponseWriter, r *http.Request) {
bookID := chi.URLParam(r, "id")
for _, book := range books {
if strconv.Itoa(book.ID) == bookID {
render.JSON(w, r, book)
return
}
}
render.Status(r, http.StatusNotFound)
}
- And here is the corresponding
book.yaml
file that documents the API using OpenAPI 3 standard:
openapi: 3.0.0
info:
title: Book API
description: API for retrieving information about books
version: 1.0.0
servers:
- url: http://localhost:3000
description: Local server
paths:
/books/{id}:
get:
summary: Get a book by ID
description: Returns a single book object by ID
parameters:
- in: path
name: id
schema:
type: integer
required: true
description: ID of the book to retrieve
responses:
'200':
description: Successful response
content:
application/json:
schema:
$ref: '#/components/schemas/Book'
'404':
description: Book not found
content: {}
components:
schemas:
Book:
type: object
required:
- id
- title
- author
properties:
id:
type: integer
format: int64
description: Unique identifier of the book
title:
type: string
description: Title of the book
author:
type: string
description: Author of the book
The book.yaml
file defines the API version, the base URL, and the paths for each endpoint. It also specifies the HTTP
methods allowed for each endpoint, such as GET, POST, PUT, DELETE, and so on. For example, the GetBook
endpoint is defined in the YAML file with the following details:
/books/{id}:
get:
summary: Retrieve a book by ID
description: Retrieve the book with the given ID from the library.
parameters:
- in: path
name: id
schema:
type: integer
required: true
description: Numeric ID of the book to retrieve.
responses:
'200':
description: A book object.
content:
application/json:
schema:
$ref: '#/components/schemas/Book'
'404':
description: The specified book was not found.
This definition specifies that the endpoint is a GET
method that retrieves a book by ID. It also specifies the parameters that the endpoint accepts and the responses that it returns. In this case, the GetBook
endpoint returns a JSON object representing a book, or a 404
error if the specified book is not found.
The book.yaml
file also includes definitions of the data models used by the API. For example, the "Book" object is defined as follows:
components:
schemas:
Book:
type: object
properties:
id:
type: integer
title:
type: string
author:
type: string
required:
- id
- title
- author
This definition specifies that the Book
object is an object that has three properties: id
, title
, and author
. The id
property is an integer, while the title
and author
properties are strings. It also specifies that all three properties are required.
Let's break down the key components of the YAML
file specification for the Go book API above:
openapi
: specifies the version of the OpenAPI specification being used.info
: provides metadata about the API, including the title, description, version, and contact information.servers
: defines the server information including the URL and description.paths
: defines the available endpoints(routes) of the API, including the HTTP method used to access each endpoint, and the request and response parameters for each endpoint.components
: defines reusable schema, parameters, responses, and security schemes used in the API.security
: defines the security schemes used to secure the API and which endpoints require authorisation.tags
: provides metadata about the API paths, including a brief description and an optional external documentation link.responses
: defines the possible responses that the API can return, including the response code, description, and the content schema.requestBody
: defines the expecterd request body for an endpoint, including the content type and content schema.parameters
: defines the parameters that can be used in the path, query, header, or cookie of a request, including the type, description, and default value.200
: this component specifies the response when the request is successful with a status code of 200.
Once we have created the OpenAPI specification file, we can use it to generate documentation in various formats, such as HTML, PDF, or Markdown. There are many tools available for generating documentation from OpenAPI specifications, such as Swagger UI, ReDoc, and Slate.
By defining the API endpoints and data models in the OpenAPI 3 specification file, the file provides a comprehensive documentation of the API that can be used to generate code, test cases, client libraries, server stubs, and interactive API documentation. This not only makes it easier for developers to understand and use the API, but also saves time and effort in the long run.
This is just one example of how OpenAPI can be used to document an API in Go. There are many other ways to write OpenAPI specifications and integrate them into your application. The exact approach may differ depending on the specific API being documented and the desired output format.
Testing the Book API
To test the Go book API and run it locally, you can follow these steps:
In your terminal or code editor, navigate to the project directory.
Run the
go mod init <module_name>
to create a new Go module.Run the command
go install github.com/go-chi/chi/v5
to install the package.
Once the package has been installed, you should be able to import it into your Go code and use its functions and methods.
Note: Go version 1.18, no longer installs packages with thego get
command. Instead, we use thego install
command.Then we run the
main.go
file to start the server. Following our program above, it will be listed on port:3000
We can then test the API on the terminal, Postman or ReqBin. (I used ReqBin, it is an online API testing tool for REST and SOAP APIs, works directly from your browser.)
- In the terminal, we can use the
cURL
tool to make requests to the API. To make a request to the/books/1
endpoint, run this command in your terminal:
curl http://localhost:3000/books/1
This should return a JSON response containing an array of books.
- To make requests using ReqBin, set the request method to
GET
, and set the request URL tohttp.//localhost:3000/books/1
. You can then send the request and view the response in the "Response" tab.
This is a screenshot of when I tested the Go book API using ReqBin.
The box highlighted in 'Magenta' is for the GET request URL
, while the one highlighted in 'Red-orange' is for the 'Response'
Tools for Documenting APIs
Once you have created your API documentation, it is important to choose the right tool to present it to your users. There are many tools available for documenting APIs, each with its own strengths and weaknesses. Some of the most popular tools for documenting APIs include:
Swagger UI: Swagger UI is a popular open-source tool for documenting REST APIs. It allows you to create interactive documentation for your API using OpenAPI, and provides a user-friendly interface for exploring your API.
Postman: Postman is a popular API development environment that can also be used for API documentation. It allows you to create documentation for your API using Markdown, and provides a user-friendly interface for exploring your API.
OpenAPI Generator: The OpenAPI generator is a code generator that can automatically create documentation for your API using the OpenAPI specification. This specification is a standardised format for describing RESTful APIs, which makes it easy to generate documentation in a consistent and predictable way. The OpenAPI generator supports a wide range of programming languages, including Go, Java, Python, and many others.
Readme: Readme is a popular documentation platform that can be used for API documentation. It provides a user-friendly interface for creating and publishing API documentation, and supports both OpenAPI and Swagger.
ReDocly: ReDocly is an open-source tool for creating API documentation. It allows you to create documentation for your API using OpenAPI, and provides a user-friendly interface for exploring your API.
When choosing a tool for documenting your API, it is important to consider your specific needs and requirements. Some important factors to consider include:
Ease of use: Is the tool user-friendly and easy to navigate? Can users easily find the information they need?
Customisation: Can you customize the look and feel of the documentation to match your brand?
Integration: Can the tool integrate with other tools and platforms, such as GitHub, Jira, or Slack?
Collaboration: Does the tool allow for collaboration between team members, such as commenting or version control?
Scalability: Can the tool scale with your API as it grows and evolves?
Regardless of the tool you choose, investing time and effort into creating good API documentation is well worth the effort, and will pay off in the long run.
Conclusion
Documenting APIs is an essential part of software development, and OpenAPI provides a powerful and flexible way to create clear and concise API documentation. By following best practices for writing documentation and using API documentation tools, you can make your API more accessible to other developers and improve their overall experience. With the increasing popularity of RESTful APIs and the growth of the API economy, it's more important than ever to invest time and resources into creating high-quality API documentation.
I hope this article has provided a useful introduction to API documentation and OpenAPI, as well as practical tips and examples for how to use OpenAPI 3 specifications to document APIs in Go. By following these guidelines and best practices, you can create APIs that are well-documented, easy to use, and more widely adopted by other developers.
Feel free to reach out, or drop your questions in the comment section below.
We can also connect on LinkedIn and Twitter.
Happy coding! 👨💻🚀
You can support me by buying me a coffee/book :)
Image by pikisuperstar on Freepik
Top comments (2)
Awesome introduction to OpenAPI and how it can be used for Go APIs!
I just wanted to point out that you can use Huma (disclaimer: I'm the author) to automate some of this process when building Go services. It adds a simple OpenAPI 3.1 & JSON Schema layer on top of a bunch of routers (including Go 1.22's built-in
ServeMux
), gives you compile-time checks of static typed requests/responses, built-in validation with exhaustive structured error responses, supports client-driven content negotiation, and more.Here's an article with some more info: dev.to/danielgtaylor/apis-in-go-wi...
Hi Daniel,
Thanks for reading and also sharing Huma - great work you did.
I checked it out and it's cool, looking forward to working with it soon :)