Writing OpenAPI (Swagger) Specification Tutorial Series - Part 7
Documentation
By Arnaud Lauret, June 12, 2016
Previous posts showed how to write a highly accurate description of an API interface contract with the OpenAPI specification. But an interface contract, no matter how brilliant, is nothing without some explainations. A fully documented OpenAPI specification file can provide some useful information and be used as a part of an API’s documentation.
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 previous parts we’ve learned to create highly accurate API description, in this seventh part we’ll learn how to use the OpenAPI specification to make it a valuable part of an API documentation.
API’s general informations
First things first. When using an API, API consumers want to have some general informations about it like its version, its name, some description, term of service, how to contact the API provider, what kind of licencing it uses. The info
object placed on root level can be used to provide such information:
info:
version: 1.1.0
title: Simple API
description: A simple API to learn how to write OpenAPI Specification
termsOfService: http://simple.api/terms-of-service
contact:
name: John Doe
url: http://simple.api/contact
email: [email protected]
license:
name: Apache-2.0
url: http://www.apache.org/licenses/LICENSE-2.0
Categorizing operations with Tags
By using tags
on operation level, we can categorize operations. tags
is a simple list of names.
Single tag
This operation belongs to the Person
category:
paths:
/persons:
parameters:
- $ref: '#/parameters/userAgent'
get:
summary: Gets some persons
description: Returns a list containing all persons. The list supports paging.
operationId: searchUsers
tags:
- Persons
Multiple tags
An operation can belong to different categories:
Descriptions everywhere
We can add some descriptions at almost every level of the OpenAPI specification.
Security definitions
A description
can be added to security definitions:
securityDefinitions:
OauthSecurity:
description: New Oauth security system. Do not use MediaSecurity or LegacySecurity.
type: oauth2
flow: accessCode
authorizationUrl: 'https://oauth.simple.api/authorization'
tokenUrl: 'https://oauth.simple.api/token'
scopes:
admin: Admin scope
user: User scope
MediaSecurity:
description: Specific media security for backward compatibility. Use OauthSecurity instead.
type: apiKey
in: query
name: media-api-key
LegacySecurity:
description: Legacy security system for backward compatibility. Use OauthSecurity instead.
type: basic
Schema title and description
Each schema (used in a definition, a parameter or a response) can have a title
and a description
:
definitions:
Person:
title: Human
description: A person which can be the user itself or one of his friend
Property description
Properties can be described with description
:
Parameter’s description
Whether defined inline or in parameters
section, a parameter can have a description
.
Inline parameter’s description
parameters:
- name: person
in: body
required: true
description: The person to create.
schema:
$ref: '#/definitions/Person'
Reusable parameter’s description
parameters:
username:
name: username
in: path
required: true
description: The person's username
type: string
pageSize:
name: pageSize
in: query
description: Number of persons returned
Operation’s summary, description and operationId:
An operation can be described with a summary
and a longer description
. An operationId
can be added. It can be used as a link to the implementation running behind the API for example.
paths:
/persons:
parameters:
- $ref: '#/parameters/userAgent'
get:
summary: Gets some persons
description: Returns a list containing all persons. The list supports paging.
operationId: searchUsers
Response’s description
Whether inline or defined in responses
, a response can have a description
.
Inline response’s description
Reusable response’s description
Reponse’s header’s description
Headers returned with a response can have a description
:
headers:
X-Rate-Limit-Remaining:
description: How many calls consumer can do
type: integer
X-Rate-Limit-Reset:
description: When rate limit will be reset
type: string
format: date-time
Tags descriptions
Tags can have descriptions
. We need to add a tags
section on specification file root level, on each item in this list we set a name
(corresponding to the name used in tags list on operation level) and a description
:
Using GFM in descriptions
In almost all description
, we can use GFM
(Github Flavored Markdown). To check if an object description support GFM, take a look at my visual documentation or the original specification.
Note that GFM support can vary depending the tool processing the OpenAPI specification file.
Simple multiline description
By adding a |
and a new line with a new tab, we can write multiline descriptions:
'/persons/{username}/collecting-items':
parameters:
- $ref: '#/parameters/username'
- $ref: '#/parameters/userAgent'
get:
summary: Gets a person's collecting items list
description: |
Returns a list containing all items this person is looking for.
The list supports paging.
Simple GFM description
externalDocs:
description: |
**Complete** documentation describing how to use this API
url: http://doc.simple.api/
Description with array
CollectingItem:
discriminator: itemType
required:
- itemType
properties:
itemType:
description: |
An item can be of different type:
type | definition
-----|-----------
Vinyl| #/definitions/Vinyl
VHS | #/definitions/VHS
AudioCassette | #/definitions/AudioCassette
type: string
enum:
- AudioCassette
- Vinyl
- VHS
Description with code
swagger: '2.0'
info:
version: 1.1.0
title: Simple API
description: |
A simple API to learn how to write OpenAPI Specification.
This file uses almost every single aspect of the [Open API Specification](https://openapis.org/).
This API will use JSON.
JSON looks like this:
```JSON
{
"key": "value",
"anotherKey": "anotherValue"
}
```
termsOfService: http://simple.api/terms-of-service
Examples
Examples can be provided for atomic or object properties, definitions, and responses.
Atomic property example
Atomic properties can be illustrated with an example
:
properties:
firstName:
description: first name
type: string
example: John
lastName:
description: last name
type: string
example: Doe
username:
description: Username used to connect to the service
type: string
pattern: '[a-z0-9]{8,64}'
minLength: 8
maxLength: 64
example: john1doe6
dateOfBirth:
description: Date of birth
type: string
format: date
example: 1978-06-21
lastTimeOnline:
description: The last time this person was connected to the service as a
type: string
format: date-time
readOnly: true
example: 2016-06-10T12:36:58.014Z
Object property example
Object properties, can also be illustrated with a complex example
complying to the underlying JSON Schema:
Persons:
title: Humans
description: A list of users or friends
required:
- items
properties:
items:
description: Array containg the list
type: array
minItems: 10
maxItems: 100
uniqueItems: true
items:
$ref: '#/definitions/Person'
example:
- firstname: Robert
lastname": Doe
username": robdo
dateOfBirth: 1970-01-28
lastTimeOnline: 2016-04-10T14:36:58.014Z
- firstname: Jane
lastname: Doe
username: jdoe123
dateOfBirth: 1980-05-12
lastTimeOnline: 2016-05-12T19:23:59.014Z
Definition Example
An example can be defined for the entire definition just like for an object property (it must conforms to its underlying JSON schema):
MultilingualErrorMessage:
title: MultiLingualMultiDeviceErrorMessage
description: An multilingual error message (hashmap) with a long and a short description
additionalProperties:
$ref: '#/definitions/ErrorMessage'
properties:
defaultLanguage:
$ref: '#/definitions/ErrorMessage'
example:
defaultLanguage:
longMessage: We're deeply sorry but an error occured
shortMessage: Error
fr:
longMessage: Nous sommes désolé mais une erreur est survenu
shortMessage: Erreur
Response’s Example
On response level, we can provide example
, each one corresponding to a media type returned by the operation. Here’s an example for an application/json media type:
examples:
application/json:
{
"totalItems": 10,
"totalPage": 4,
"pageSize": 3,
"currentPage": 2,
"items":
[
{
"itemType": "Vinyl",
"maxPrice": 20,
"imageId": "98096838-04eb-4bac-b32e-cd5b7196de71",
"albumName": "Captain Future Original Soundtrack",
"artist": "Yuji Ohno"
},
{
"itemType": "VHS",
"maxPrice": 10,
"imageId": "b74469bc-e6a1-4a90-858a-88ef94079356",
"movieTitle": "Star Crash",
"director": "Luigi Cozzi"
},
{
"itemType": "AudioCassette",
"maxPrice": 10,
"imageId": "b74469bc-e6a1-4a90-858a-88ef94079356",
"albumName": "Star Wars",
"artist": "John Williams"
}
]
}
'404':
$ref: '#/responses/PersonDoesNotExistResponse'
'500':
$ref: '#/responses/Standard500ErrorResponse'
default:
$ref: '#/responses/TotallyUnexpectedResponse'
Examples precedence
If we defined examples on multiple levels (property, object, definition, response), it’s always the higher level which is taken into account by tools processing OpenAPI specification file.
Links to external API documentation
In most case, the OpenAPI specification file MUST NOT be the only API’s documentation. How to create an application key, use cases, operation chaining and many other things need to be documented. All these other documentations can be separated from the specification file. However, the OpenAPI specification allow to provide links to these other documentations when needed.
Link to general API documentation
We can add an externalDoc
object on root level with a link to the API documentation.
externalDocs:
description: Complete documentation describing how to use this API
url: http://doc.simple.api/
Link to specific operation documentation
Each operation can have its own link to an external documentation using the same externalDoc
object:
/images:
parameters:
- $ref: '#/parameters/userAgent'
post:
summary: Uploads an image
description: Upload an image, will return an image id.
operationId: storeImage
externalDocs:
description: How to upload media
url: http://doc.simple.api/media/upload
Link to tag documentation
A tag’s description can also provide an external link:
Conclusion
Even if an OpenAPI specification MUST NOT be the only documentation for an API, it can be a good part of it, and you now have mastered this aspect of the specification. In next post we’ll see how we can split a OpenAPI specification file in different files.