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 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!

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 SwaggerHub, 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!

See Also

Publication date: