Swagger (OpenAPI 2.0) Tutorial
This tutorial describes what Swagger is and explains the Swagger syntax for various parts of your API definition file.
What Is Swagger?
Swagger is an open-source framework for designing and describing APIs. Swagger’s journey started in 2010 when it was developed by Reverb Technologies (formerly called Wordnik) to solve the need for keeping the API design and documentation in sync. Fast forward 6 years and Swagger has become the de-facto standard for designing and describing RESTful APIs used by millions of developers and organizations for developing their APIs, be it internal or client facing.
In this tutorial, we will write an API definition in the Swagger 2.0 format (also known as OpenAPI 2.0). Swagger can be written in JSON or YAML, though we recommend writing it in YAML, because it is easier to read and understand.
A simple Swagger definition looks like this:
swagger: '2.0' info: version: 1.0.0 title: Simple example API description: An API to illustrate Swagger paths: /list: get: description: Returns a list of stuff responses: 200: description: Successful response
The syntax above will make sense once we finish this walkthrough.
Why Swagger?
There are a lot of factors that contributed to Swagger’s meteoric adoption for building RESTful APIs. We have listed the most important ones as to why use Swagger for designing APIs:
Design and document APIs simultaneously, thus keeping the blueprint and documentation in sync.
Both human and machine readable, with an interactive API documentation automatically generated to see the API in action.
Large comprehensive tooling ecosystem around the framework, which lets you go beyond just design, from SDK generation to testing and debugging.
Strong open source community supporting and spearheading the framework.
About this tutorial
In this tutorial, we will be guiding you through building a simple API while covering all the important aspects of the Swagger definition.
Prerequisites
Basic knowledge of RESTful APIs
Nice to have
Basic knowledge of YAML
We recommend using API Hub for Design’s built-in editor and validator to quickly write and visualize the Swagger definition described in the tutorial. API Hub for Design is free with loads of features to get you started quickly, so give it a whirl!
Create an API
We will be designing an API for a record label. Let’s assume that the record label has a database of artists with the following information:
Artist name
Artist genre
Number of albums published under the label
Artist username
The API will let consumers obtain the list of artists stored in the database and add a new artist to the database.
The Swagger definition of an API can be divided into 3 different sections –
The Meta Information
The Path Items:
Parameters
Responses
Reusable components:
Definitions
Parameters
Responses
Meta information
The meta information section is where you can give information about your overall API. Information like what the API does, what the base URL of the API is and what web-based protocol it follows can be defined in this section.
All Swagger defined APIs start with the swagger: 2.0
declaration. The info object is then specified with additional, required metadata like the version and title. The description is optional.
The base URL is what any application or end user will call in order to consume the API. In this case, it is https://example.io/v1
, which is defined by the schemes
, host
and basePath
objects respectively.
We can also add a basic authentication which only lets authorized users consume the API. For more advanced security, see here.
Let’s start with a simple meta information section:
swagger: '2.0' info: version: 1.0.0 title: Simple Artist API description: A simple API to understand the Swagger Specification in greater detail schemes: - https host: example.io basePath: /v1 securityDefinitions: UserSecurity: type: basic security: - UserSecurity: [] paths: {}
Path Items
The path items are the endpoints of your API under which you can specify HTTP verbs for manipulating the resources in the desired manner. These endpoints are relative to the base URL (which in our case is http://example.io/v1
). In this example, we have listed the /artists
endpoint under which is the GET method.
Thus, a client would use GET http://example.io/v1/artists to obtain a list of artists.
swagger: '2.0' info: version: 0.0.0 title: Simple API description: A simple API to understand the Swagger Specification in greater detail schemes: - https host: example.io basePath: /v1 securityDefinitions: UserSecurity: type: basic security: - UserSecurity: [] # ----- Added lines ---------------------------------------- paths: /artists: get: description: Returns a list of artists # ---- /Added lines ----------------------------------------
Responses
The GET method, under the artists
endpoint, lets the consumer of the API obtain the details of a list of artists from the http://example.io/v1 database.
Every response would need at least one HTTP status code to describe the kind of responses a consumer is likely to expect. The description gives details on what the responses of the API would be. In our sample code, we have specified 200, which is a successful client request, while 400 is an unsuccessful request. You can find more information about HTTP status codes here. A successful response will return the artist name, genre, username and albums recorded. An unsuccessful request is described under the 400 HTTP code, with a corresponding error message detailing why the response is invalid.
swagger: '2.0' info: version: 1.0.0 title: Simple Artist API description: A simple API to understand the Swagger Specification in greater detail schemes: - https host: example.io basePath: /v1 securityDefinitions: UserSecurity: type: basic security: - UserSecurity: [] paths: /artists: get: description: Returns a list of artists # ----- Added lines ---------------------------------------- responses: 200: description: Successfully returned a list of artists schema: type: array items: type: object required: - username properties: artist_name: type: string artist_genre: type: string albums_recorded: type: integer username: type: string 400: description: Invalid request schema: type: object properties: message: type: string # ---- /Added lines ----------------------------------------
See here for more information on responses.
Parameters
RESTful parameters specify the variable part of the resource a user works with. If you want to get some advanced information on parameters, read here.
Query parameters
Query parameters are the most common type of parameters. They appear at the end of a URL following a question mark. Query parameters are optional and non unique, so they can be specified multiple times in the URL. It is a non-hierarchical component of the URL.
In our example, it would make sense to let the client limit the information required instead of returning the entire list of artists from the database, which would lead to unnecessary load on the server. The client could describe the page number (offset) and the amount of information on the page (limit), for example:
GET http://example.com/v1/artists?limit=20&offset=3
These variables are defined under the parameters
object in the Swagger definition. Thus, the definition would now look as follows –
swagger: '2.0' info: version: 1.0.0 title: Simple Artist API description: A simple API to understand the Swagger Specification in greater detail schemes: - https host: example.io basePath: /v1 securityDefinitions: UserSecurity: type: basic security: - UserSecurity: [] paths: /artists: get: description: Returns a list of artists # ----- Added lines ---------------------------------------- parameters: - name: limit in: query type: integer description: Limits the number of items on a page - name: offset in: query type: integer description: Specifies the page number of the artists to be displayed # ---- /Added lines ---------------------------------------- responses: 200: description: Successfully returned a list of artists schema: type: array items: type: object required: - username properties: artist_name: type: string artist_genre: type: string albums_recorded: type: integer username: type: string 400: description: Invalid request schema: type: object properties: message: type: string
Body parameters
Body parameters are stated in the body of the request. A key principle of such a parameter is that resources are sent in the message body. Body parameters are great for POST and PUT requests. It is not advisable to use these parameters in GET and DELETE actions.
For this API, let’s add the ability for a user to post an artist to our database. This would be under the /artists
resource. Note the inclusion of a parameter which is specified in the body of the request from the in:body
description.
The API would now look as follows:
swagger: '2.0' info: version: 1.0.0 title: Simple Artist API description: A simple API to understand the Swagger Specification in greater detail schemes: - https host: example.io basePath: /v1 securityDefinitions: UserSecurity: type: basic security: - UserSecurity: [] paths: /artists: get: description: Returns a list of artists parameters: - name: limit in: query type: integer description: Limits the number of items on a page - name: offset in: query type: integer description: Specifies the page number of the artists to be displayed responses: 200: description: Successfully returned a list of artists schema: type: array items: type: object required: - username properties: artist_name: type: string artist_genre: type: string albums_recorded: type: integer username: type: string 400: description: Invalid request schema: type: object properties: message: type: string # ----- Added lines ---------------------------------------- post: description: Lets a user post a new artist parameters: - name: artist in: body description: creates a new artist in our database schema: type: object required: - username properties: artist_name: type: string artist_genre: type: string albums_recorded: type: integer username: type: string responses: 200: description: Successfully created a new artist 400: description: Invalid request schema: type: object properties: message: type: string # ---- /Added lines ----------------------------------------
Path parameters
The path parameters can be used to isolate a specific component of the data that the client is working with, for example, http://example.io/v1/{userrole}
. Path parameters are part of the hierarchical component of the URL, and are thus stacked sequentially.
Let’s create a new endpoint which returns a specific artist’s information based on the username provided. The path parameter here would be the username
of the artist whose info we need. Path parameters (username
in this case) have to be mandatorily described in the parameters object under the method.
swagger: '2.0' info: version: 1.0.0 title: Simple Artist API description: A simple API to understand the Swagger Specification in greater detail schemes: - https host: example.io basePath: /v1 securityDefinitions: UserSecurity: type: basic security: - UserSecurity: [] paths: /artists: get: description: Returns a list of artists parameters: - name: limit in: query type: integer description: Limits the number of items on a page - name: offset in: query type: integer description: Specifies the page number of the artists to be displayed responses: 200: description: Successfully returned a list of artists schema: type: array items: type: object required: - username properties: artist_name: type: string artist_genre: type: string albums_recorded: type: integer username: type: string 400: description: Invalid request schema: type: object properties: message: type: string post: description: Lets a user post a new artist parameters: - name: artist in: body description: creates a new artist in our database schema: type: object required: - username properties: artist_name: type: string artist_genre: type: string albums_recorded: type: integer username: type: string responses: 200: description: Successfully created a new artist 400: description: Invalid request schema: type: object properties: message: type: string # ----- Added lines ---------------------------------------- /artists/{username}: get: description: Obtain information about an artist from his or her unique username parameters: - name: username in: path type: string required: true responses: 200: description: Successfully returned an artist schema: type: object properties: artist_name: type: string artist_genre: type: string albums_recorded: type: integer 400: description: Invalid request schema: type: object properties: message: type: string # ---- /Added lines ----------------------------------------
Here, we have specified the username
as a path parameter. The thing to note is that path parameters have to have a true property set to the required parameter, for the spec to be valid.
If you followed through till here, then congratulation! You have just designed a simple API for a record label!
Reusable components
What we have just described are just 2 endpoints and 3 actions. This was 83 lines of API definition, and the spec will only get longer as the API gets bigger. One of the things you may notice in the spec we have so far is that we have the same Artist schema (artist name, genre, username and albums published) that gets repeated in various 200 and 400 responses. Bigger APIs would involve rewriting and reusing a lot of the same specs, so it would be a tedious task writing a more complex API.
The Swagger Specification has a solution – defining reusable components. These components can be reused across multiple endpoints, parameters and responses in the same API.
There are 3 different types of reusable components of an API definition:
Definitions
Responses
Parameters
Path Items can also be reused with the help of applications like API Hub for Design, which store your reusable components to be referenced across multiple APIs.
Definitions
The global definitions
section can contain various data models consumed and returned by the API. Here is how we can use definitions to store the schema for an HTTP 200 OK response:
swagger: '2.0' info: version: 1.0.0 title: Simple Artist API description: A simple API to understand the Swagger Specification in greater detail schemes: - https host: example.io basePath: /v1 securityDefinitions: UserSecurity: type: basic security: - UserSecurity: [] paths: /artists: get: description: Returns a list of artists parameters: - name: limit in: query type: integer description: Limits the number of items on a page - name: offset in: query type: integer description: Specifies the page number of the artists to be displayed responses: 200: description: Successfully returned a list of artists schema: type: array items: # ----- Added line ---------------------------------------- $ref: '#/definitions/Artist' # ---- /Added line ---------------------------------------- 400: description: Invalid request schema: type: object properties: message: type: string post: description: Lets a user post a new artist parameters: - name: artist in: body description: creates a new artist in our database schema: # ----- Added line ---------------------------------------- $ref: '#/definitions/Artist' # ---- /Added line ---------------------------------------- responses: 200: description: Successfully created a new artist 400: description: Invalid request schema: type: object properties: message: type: string /artists/{username}: get: description: Obtain information about an artist from his or her unique username parameters: - name: username in: path type: string required: true responses: 200: description: Successfully returned an artist schema: type: object properties: artist_name: type: string artist_genre: type: string albums_recorded: type: integer 400: description: Invalid request schema: type: object properties: message: type: string # ----- Added lines ---------------------------------------- definitions: Artist: type: object required: - username properties: artist_name: type: string artist_genre: type: string albums_recorded: type: integer username: type: string # ---- /Added lines ----------------------------------------
The spec is not only shorter, but anytime a new endpoint with the same schema is needed, the designer does not need to spend time writing the piece. See here for more information on Definitions.
To jump to an object definition, simply click the $ref
link.
Parameters and responses
We can also define a separate section under the reusable components for storing parameters and responses that could be referenced across multiple endpoints in the same API.
In the API definitiion below, we have, under the reusable parameters, the PageLimit
and PageNumber
parameters, which define the query parameters we used under the /artists
endpoint. They are referenced under the /artists endpoint.
We also have a 400Error
reusable response defined, which specifies the 400 response we used under all the endpoints, which are then appropriately referenced.
swagger: '2.0' info: version: 1.0.0 title: Simple Artist API description: A simple API to understand the Swagger Specification in greater detail schemes: - https host: example.io basePath: /v1 securityDefinitions: UserSecurity: type: basic security: - UserSecurity: [] paths: /artists: get: description: Returns a list of artists parameters: - $ref: '#/parameters/PageLimit' - $ref: '#/parameters/PageNumber' responses: 200: description: Successfully returned a list of artists schema: type: array items: $ref: '#/definitions/Artist' 400: # ----- Added line ---------------------------------------- $ref: '#/responses/400Error' # ---- /Added line ---------------------------------------- post: description: Lets a user post a new artist parameters: - name: artist in: body description: creates a new artist in our database schema: $ref: '#/definitions/Artist' responses: 200: description: Successfully created a new artist 400: # ----- Added line ---------------------------------------- $ref: '#/responses/400Error' # ---- /Added line ---------------------------------------- /artists/{username}: get: description: Obtain information about an artist from his or her unique username parameters: - name: username in: path type: string required: true responses: 200: description: Successfully returned an artist schema: type: object properties: artist_name: type: string artist_genre: type: string albums_recorded: type: integer 400: # ----- Added line ---------------------------------------- $ref: '#/responses/400Error' # ---- /Added line ---------------------------------------- definitions: Artist: type: object required: - username properties: artist_name: type: string artist_genre: type: string albums_recorded: type: integer username: type: string # ----- Added lines ---------------------------------------- parameters: PageLimit: name: limit in: query type: integer description: Limits the number of items on a page PageNumber: name: offset in: query type: integer description: Specifies the page number of the artists to be displayed responses: 400Error: description: Invalid request schema: type: object properties: message: type: string # ---- /Added lines ----------------------------------------
Summary
We have successfully designed a RESTful API which exposes the artists present in the database of a record label! We have only covered the basics of Swagger, as the specification can be anything you want it to be (mostly). If you want to become a Swagger expert, you can refer to the official specification and to the syntax guide, or try out our certification courses!