Viewpoint 4 min read

OpenAPI 3.0 Tutorial: 8 Tips for Documenting API Specification

In this article, we will outline the key points of the upgrade process and the essentials of documenting APIs using OAS 3. Some of these points might still be applicable to the previous OAS 2 (formerly known as Swagger) documents.

OpenAPI 3.0 Tutorial: 8 Tips for Documenting API Specification

Previously, you might have been using Swagger 2.0 (also known as OAS 2), but now, it's time to upgrade to the OpenAPI Specification (OAS) 3. In this article, we will outline the key points of the upgrade process and the essentials of documenting APIs using OAS 3.

Some of these points might still be applicable to the previous OAS 2 (formerly known as Swagger) documents, but it's worth noting as I may not have fully emphasized them before.

The code examples in this article are extracted from the OAS 3 specification of, which is available in the openapi.yaml file on GitHub. The results can be viewed at

Here are ten key considerations:

1. Read the Specification Document

Read the article "A Guide to What's New in OpenAPI 3.0," which shares some of the major updates in the latest version of OAS and provides detailed insights into what you need to know when transitioning from OAS 2.0 to OAS 3.0. This article is based on the 1-hour webinar "OpenAPI 3.0, And What it Means for the Future of Swagger."

2.Use a Converter Web Service

Use the OpenAPI/Swagger 2.0 to OpenAPI 3.0 converter web service to transform your Swagger specifications into OpenAPI 3.0.

It's available online at, and you can also use it as a Docker image:

docker pull swaggerapi/swagger-converter:v1.0.2
docker run -it -p 8080:8080 --name swagger-converter swaggerapi/swagger-converter:v1.0.2

3.Validate Your Specification and Preview with Swagger Editor

Swagger Editor enables you to edit YAML-formatted Swagger API specifications in your web browser and instantly preview the documentation.

You can use it online or as an npm-published version or a Docker image. For more details, refer to the project's README.

4.Showcase Your Documentation with Swagger UI

Swagger UI is a collection of HTML, JavaScript, and CSS resources that dynamically generate beautiful documentation for Swagger-compliant APIs.

You can use it directly, like me, by accessing the Swagger UI documentation through an API route, for example, Here's a code snippet from app.js:

const swaggerUi = require('swagger-ui-express');
const YAML = require('yamljs');
const swaggerDocument = YAML.load('./docs/openapi/openapi.yaml');

app.use('/api/docs', swaggerUi.serve, swaggerUi.setup(swaggerDocument));

Including the open specification file (openapi.yaml) in your nodemon watch (e.g., nodemon --inspect ./bin/www --watch src --watch docs/openapi/openapi.yaml) can be helpful, allowing you to reload the UI without manually restarting the ExpressJS server.

4.1. Use swagger-jsdoc for Code-First Approach

Another noteworthy point is that you can use swagger-jsdoc to integrate Swagger through JSDoc annotations in your code. The swagger-jsdoc project assumes that you want to document existing, active, working code in a way that "breathes life" into it, generating a specification that can be fed into other Swagger tools rather than the other way around.

Currently, I manage documentation in a single openapi.yaml file, but I may consider using it in the future.

5.Group Operations Using Tags

You can assign a tag list to each API operation, making it convenient for Swagger UI and Swagger Editor to display operations by tags. To control the sorting in Swagger UI, you need to add them as global tags at the root level. You can also add descriptions and links to external documents there.

Here are the tags I use for the API:

yamlCopy code
tags:- name: rootdescription: Used to mark root endpoints- name: versiondescription: Access project version and gitSha1- name: public-bookmarksdescription: Access public bookmarks- name: personal-bookmarksdescription: Operations on personal bookmarks- name: user-datadescription: Operations on user data- name: helperdescription: Helper endpoints/operations

6.Specify API Base URLs with Servers

In OpenAPI 3.0, you use the servers array to specify one or more base URLs for the API. Servers replace the host, basePath, and schemes keywords used in OpenAPI 2.0. Each server has a URL and an optional description in Markdown format.

yamlCopy code
servers:- url: http://localhost:3000/apidescription: Local server for development- url: Main (production) server

7.Define and Reuse Resources with Components

Often, several API operations share common parameters or return the same response structure. To avoid code duplication, you can place common definitions in the global components section and reference them using $ref.

For instance, for the response common to several operations where a list of bookmarks appears, I define a BookmarkListResponse under components > responses:

components:responses:BookmarkListResponse:description: List of bookmarkscontent:application/json:schema:type: arrayitems:$ref: "#/components/schemas/Bookmark"

And then, I reference it in different operations, such as get-public-bookmarks:

yamlCopy code
/public/bookmarks:get:summary: Return a list of public bookmarks using query parameters.tags:- public-bookmarksparameters:- $ref: "#/components/parameters/searchTextQueryParam"- $ref: "#/components/parameters/limitQueryParam"- $ref: "#/components/parameters/locationQueryParam"responses:200:description: OK$ref: "#/components/responses/BookmarkListResponse"

Note the locationQueryParam mentioned above. It's defined under components > parameters and referenced in multiple places in the API specification, including the example shown above.

8.Add Examples for Clarity

You can add examples to parameters, properties, and objects to make your Web service's specification clearer. Examples can be read by tools and libraries for your API. For instance, a mock API tool can use example values to generate mock requests. You can specify examples for objects, individual properties, and operation parameters using the example or examples keys.

For instance, you can have complex values as examples for a search text parameter:

components:parameters:searchTextQueryParam:name: qin: querydescription: |
        Search query (words separated by spaces). Special filters available:
          * `lang:iso_language_code` - e.g., `lang:en` for English, `lang:es` for Spanish, `lang:de` for German bookmarks
          * `site:site_URL` - e.g., return bookmarks from [](htt

Join Apidog's Newsletter

Subscribe to stay updated and receive the latest viewpoints anytime.