This tutorial describes what Swagger is and explains the Swagger syntax for various parts of your API definition file.
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.
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.
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 SwaggerHub’s built-in editor and validator to quickly write and visualize the Swagger definition described in the tutorial. SwaggerHub is free with loads of features to get you started quickly, so give it a whirl!
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
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: {}
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 ----------------------------------------
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.
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 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 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 ----------------------------------------
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!
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 SwaggerHub, which store your reusable components to be referenced across multiple APIs.
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.
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 ----------------------------------------
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!