Writing OpenAPI (Swagger) Specification Tutorial Series - Part 2
The basics
By Arnaud Lauret, March 2, 2016
After discovering what is the OpenAPI Specification format, it’s now time to write a first simple OpenAPI Specification file to learn the basics.
Writing OpenAPI (Swagger) Specification Tutorial Series
This tutorial teaches everything about the OpenAPI 2.0 Specification (fka. as Swagger), most of what you’ll read here can still be applied on version 3.
If you’re a bit lost in the specification (version 2 or 3), take a look at the OpenAPI Map:
In this second part you will learn how to give some basic informations about your API, describe endpoints using various HTTP methods with path, query and body parameters and returning various HTTP status and responses.
An almost empty OpenAPI Specification
We’ll start with an almost empty, yet valid, file giving some basic informations.
swagger: "2.0"
info:
version: 1.0.0
title: Simple API
description: A simple API to learn how to write OpenAPI Specification
schemes:
- https
host: simple.api
basePath: /openapi101
paths: {}
OpenAPI Specification version
First we need to tell which version of the OpenAPI specification we are using via the swagger attribute…
Yes, swagger. As explained in the introduction, the OpenAPI specification is based on Swagger. It will probably be replaced by something else in the next version of the specification. The only possible value is (for now) 2.0.
API description
Then we give some informations about our API with info: the API’s version (not to be confused with the specification version and the file version) a title and an optionnal description.
info:
version: 1.0.0
title: Simple API
description: A simple API to learn how to write OpenAPI Specification
API URL
Speaking of web API, an important information is the root URL which people and programs will use to call it. This is described by giving a list of accepted schemes (or protocols, like http or https), a host, and a basepath.
All of these APIs endpoints URL will use https://simple.api/open101 as base URL. These informations are not required, an OpenAPI specification without these data is still valid.
API operations
Finally, as our API does absolutely nothing for now, we add an empty paths list. (nb. in YAML an empty object is describe using {}).
Defining an operation
Let our API do something by adding an operation to list some persons.
swagger: "2.0"
info:
version: 1.0.0
title: Simple API
description: A simple API to learn how to write OpenAPI Specification
schemes:
- https
host: simple.api
basePath: /openapi101
paths:
/persons:
get:
summary: Gets some persons
description: Returns a list containing all persons.
responses:
200:
description: A list of Person
schema:
type: array
items:
required:
- username
properties:
firstName:
type: string
lastName:
type: string
username:
type: string
Adding a path
In the paths section we add a new path /persons corresponding to the persons resource.
Adding an http method on path
On each path we can add any http verb (like get, post, put or delete) to manipulate the corresponding resource. To list some persons, we need to apply the get http method to the /persons resource (or path). We also give a short description (summary) and a longer one if necessary (description).
Therefore to list some persons we’ll have to call get /persons (or get https://simple.api/open101/persons to be precise).
Describing response
For each operation, you can describe any response matching an http status code (like 200 OK or 404 Not Found) in the responses section. We’ll only handle 200 when responding to get /persons and we’ll tell what the response means via its description.
Describing response’s content
The get /persons operation returns a list of persons, we describe what it is with the schema section of the response. A list of person is an object which type is array. Each item in this array is an object containing three properties of type string: firstName, lastName and username. Only username will be always provided (i.e. required).
Defining query parameters
As we’ll have to handle many persons, it could be a good idea to add paging capabilities to the get /resources operation. We’ll do that by adding query parameters to define the requested page and number of items per page.
swagger: "2.0"
info:
version: 1.0.0
title: Simple API
description: A simple API to learn how to write OpenAPI Specification
schemes:
- https
host: simple.api
basePath: /openapi101
paths:
/persons:
get:
summary: Gets some persons
description: Returns a list containing all persons. The list supports paging.
parameters:
- name: pageSize
in: query
description: Number of persons returned
type: integer
- name: pageNumber
in: query
description: Page number
type: integer
responses:
200:
description: A list of Person
schema:
type: array
items:
required:
- username
properties:
firstName:
type: string
lastName:
type: string
username:
type: string
Adding a parameters section to the get /persons operation
First we add a parameters section in get http method for /persons path.
paths:
/persons:
get:
summary: Gets some persons
description: Returns a list containing all persons. The list supports paging.
parameters:
Adding paging query parameters
Then in the parameters list we define two optional parameters named pageSize and pageNumber of type integer located in query. We also provide a description for each one.
parameters:
- name: pageSize
in: query
description: Number of persons returned
type: integer
- name: pageNumber
in: query
description: Page number
type: integer
responses:
Therefore to list some persons we can use get /persons?pageSize=20&pageNumber=2 and we’ll get the page number 2 with 20 persons max.
Defining a path parameter
We would like to access directly a specific person by it’s username, so we’ll add a get /persons/{username} operation to our API. {username} is called a path parameter.
swagger: "2.0"
info:
version: 1.0.0
title: Simple API
description: A simple API to learn how to write OpenAPI Specification
schemes:
- https
host: simple.api
basePath: /openapi101
paths:
/persons:
get:
summary: Gets some persons
description: Returns a list containing all persons. The list supports paging.
parameters:
- name: pageSize
in: query
description: Number of persons returned
type: integer
- name: pageNumber
in: query
description: Page number
type: integer
responses:
200:
description: A list of Person
schema:
type: array
items:
required:
- username
properties:
firstName:
type: string
lastName:
type: string
username:
type: string
/persons/{username}:
get:
summary: Gets a person
description: Returns a single person for its username
parameters:
- name: username
in: path
required: true
description: The person's username
type: string
responses:
200:
description: A Person
schema:
required:
- username
properties:
firstName:
type: string
lastName:
type: string
username:
type: string
404:
description: The Person does not exists.
Adding a get /persons/{username} operation
First we add a /persons/{username} path, after the /persons one, in the paths section and define the get operation for this path.
swagger: "2.0"
info:
version: 1.0.0
title: Simple API
description: A simple API to learn how to write OpenAPI Specification
schemes:
- https
host: simple.api
basePath: /openapi101
paths:
/persons:
username:
type: string
/persons/{username}:
get:
summary: Gets a person
description: Returns a single person for its username
Describing username path parameter
As {username} is a path parameter, we need to describe it. It is done by adding a parameters section to the get operation and adding a required parameter with a name matching the parameter defined in the path (here username) located in path of type string. We also provide an optional description.
parameters:
- name: username
in: path
required: true
description: The person's username
type: string
A common problem when defining path parameter is to forget required: true (as the Swagger Editor snippet do not provide it). If required is not provided, its default value is false, meaning that the parameter is optional. A path parameter is always required.
Adding responses
Don’t forget to add 200 response returning a person. Note that the schema used in 200 is the same as the array’s item in get /persons 200 response.
responses:
200:
description: A Person
schema:
required:
- username
properties:
firstName:
type: string
lastName:
type: string
username:
type: string
As a username may not match an existing person we also add a 404 response. Note that this response do not return anything besides the 404 http status code.
Defining a body parameter
We would like to have the capability of adding a person to our list of persons so we’ll add a post /persons operation to our API.
swagger: "2.0"
info:
version: 1.0.0
title: Simple API
description: A simple API to learn how to write OpenAPI Specification
schemes:
- https
host: simple.api
basePath: /openapi101
paths:
/persons:
get:
summary: Gets some persons
description: Returns a list containing all persons. The list supports paging.
parameters:
- name: pageSize
in: query
description: Number of persons returned
type: integer
- name: pageNumber
in: query
description: Page number
type: integer
responses:
200:
description: A list of Person
schema:
type: array
items:
required:
- username
properties:
firstName:
type: string
lastName:
type: string
username:
type: string
post:
summary: Creates a person
description: Adds a new person to the persons list.
parameters:
- name: person
in: body
description: The person to create.
schema:
required:
- username
properties:
firstName:
type: string
lastName:
type: string
username:
type: string
responses:
204:
description: Persons succesfully created.
400:
description: Persons couldn't have been created.
/persons/{username}:
get:
summary: Gets a person
description: Returns a single person for its username.
parameters:
- name: username
in: path
required: true
description: The person's username
type: string
responses:
200:
description: A Person
schema:
required:
- username
properties:
firstName:
type: string
lastName:
type: string
username:
type: string
404:
description: The Person does not exists.
Adding post /persons operation
We first add a post method to the /persons path (after the get one) in the paths section.
Describing a person body parameter
Then we define a parameter named person located in body of type object. The person object’s is described via it’s schema. Note that this schema is the same as the 200 response of get /persons/{username}. The firstName and lastName attributes are optional and username is required.
parameters:
- name: person
in: body
description: The person to create.
schema:
required:
- username
properties:
firstName:
type: string
lastName:
type: string
username:
type: string
Defining responses
Don’t forget to define responses for this new operation.
To simplicity and beyond
You now have learned the basics of the OpenAPI Specification. But as you may have guess, working that way on huge API may not be so easy. But rest assured, the OpenAPI Specification files we’ve seen can be simplified. We’ll learn in the next part how to describe swiftly and easily even the hugest API by using factorization and references.