The goal of Swagger is to define a standard interface for describing REST APIs. In an ideal world, a Swagger definition for your API will allow both humans and computers to discover and understand your API. At it’s core, Swagger is a formal specification of an API. Surrounding this specification are a wide swath of tools to support creating documentation, providing client libraries, and managing API deployments.
One of Swagger’s original goal was to provide a way to document an API in both a human and machine readable way. Swagger provides such a documentation format for RESTful APIs. By augmenting this documentation format with tools for API clients and developers, Swagger grew into an ecosystem providing for API developers and consumers.
Swagger provides a number of benefits over rolling your own API specification and solution. First, it provides a common language for describing RESTful APIS. Second, that common language is both human and machine readable. This common language can then be used by the ecosystem of Swagger tools to generate documentation, build client and server libraries, and integrate with Swagger aware deployment tools.
In this article, I will show how to use Swagger to develop an API, generate the documentation, and deploy the API to Amazon’s API Gateway, providing a complete end-to-end example of how to use Swagger to facilitate API design and maintenance.
The API
Let’s begin by defining the specification for the API. I will use a simple
example from a previous article on hypermedia to define our
Swagger API. In this example, we have a hypothetical API for managing
a Player
resource derived from the GKPlayer
class
used by Apple’s GameCenter API. The Player
resource can be expressed
with this simple diagram.
Representing this as a typical JSON response would yield something like the following.
GET https://api.example.com/player/1234567890
{
"playerId": "1234567890",
"alias": "soofaloofa",
"displayName": "Kevin Sookocheff",
"profilePhotoUrl": "https://api.example.com/player/1234567890/avatar.png"
}
And the list of this player’s friends could be retrieved with a separate API call.
GET https://api.example.com/player/1234567890/friends
[
{
"playerId": "1895638109",
"alias": "sdong",
"displayName": "Sheldon Dong",
"profilePhotoUrl": "https://api.example.com/player/1895638109/avatar.png"
},
{
"playerId": "8371023509",
"alias": "mliu",
"displayName": "Martin Liu",
"profilePhotoUrl": "https://api.example.com/player/8371023509/avatar.png"
}
]
Let’s take a look at how this API can be represented using a Swagger specification.
Writing the Swagger Specification
Swagger allows you to specify your API using JSON or YAML (a superset of JSON). Swagger is modelled closely after the JSON Schema specification, with some omissions and restrictions specific to supporting RESTful APIS.
By convention, the Swagger specification file is named swagger.json
or
swagger.yaml
. Go ahead and create your swagger file now.
$ touch swagger.json
Info
A Swagger specification begins with a root document object called the
Swagger object. In JSON your document would begin with this object
specifying the version of the Swagger specification we are using, and
a required info
field that provides metadata for your API. In our case,
we are using the 2.0
version of the Swagger specification. The info
field is described by an “Info Object” containing a title and a version at
a minimum. You can also include a short description of your API and links
to contact information, terms of service, or licensing information.
We can use this as the basis for describing our API using JSON:
{
"swagger": "2.0",
"info": {
"title": "Player API",
"description": "A simple API for Player resources",
"version": "1.0.1",
"contact": {
"name": "Kevin Sookocheff",
"url": "https://sookocheff.com",
"email": "kevin@sookocheff.com"
},
"license": {
"name": "Apache 2.0",
"url": "http://www.apache.org/licenses/LICENSE-2.0.html"
},
"termsOfService": "https://sookocheff.com/terms"
}
}
Paths
In Swagger, the paths
field specifies the available paths and operations
for the API. Path names must begin with a slash. Paths also allow
templating, where any variable portion of the path can be enclosed in
curly braces. For example, we could specify a simple GET endpoint for
retrieving a player by player id using Swagger.
GET https://sookocheff.com/player/1234567890
{
"/player/{id}" : {
"get": {
"description": "Returns a player by player id",
"produces": [
"application/json"
],
"responses": {
"200" {
"description": "A player resource.",
"schema": {
"$ref": "#/definitions/Player"
}
}
}
}
}
}
This API produces a JSON response, as specified by the produces
field,
which is a list of supported MIME types that the API can produce. The
specification also includes a “Response Object” that describes the
expected format of the response. In this example, the response object is
a reference to a predefined definition. These predefined objects can be
used in multiple places within your API.
Definitions
Predefined objects are listed under the definitions
field in the
specification. Each object listed under the definitions field is
a described using a subset of the JSON Schema specification with
additional extensions for providing documentation. This is best viewed
through an example describing our Player resource, full documentation can
be found here.
"definitions": {
"Player": {
"type": "object",
"properties": {
"playerId": {
"type": "string"
},
"alias": {
"type": "string"
},
"displayName": {
"type": "string"
},
"profilePhotoUrl": {
"type": "string"
}
}
},
"required": ["playerId", "alias"]
}
A Complete GET Endpoint
Putting everything together, we end up with the following JSON describing the root API and the single GET endpoint.
{
"swagger": "2.0",
"info": {
"title": "Player API",
"description": "A simple API for Player resources",
"version": "1.0.1",
"contact": {
"name": "Kevin Sookocheff",
"url": "https://sookocheff.com",
"email": "kevin@sookocheff.com"
},
"license": {
"name": "Apache 2.0",
"url": "http://www.apache.org/licenses/LICENSE-2.0.html"
},
"termsOfService": "https://sookocheff.com/terms"
},
"paths": {
"/player/{id}" : {
"get": {
"description": "Returns a player with the identifier provided in the path",
"produces": [
"application/json"
],
"responses": {
"200": {
"description": "A player resource.",
"schema": {
"$ref": "#/definitions/Player"
}
}
}
}
}
},
"definitions": {
"Player": {
"type": "object",
"properties": {
"playerId": {
"type": "string"
},
"alias": {
"type": "string"
},
"displayName": {
"type": "string"
},
"profilePhotoUrl": {
"type": "string"
}
},
"required": ["playerId", "alias"]
}
}
}
Or, in YAML syntax:
swagger: '2.0'
info:
title: Player API
description: A simple API for Player resources
version: 1.0.1
contact:
name: Kevin Sookocheff
url: https://sookocheff.com
email: kevin@sookocheff.com
license:
name: Apache 2.0
url: http://www.apache.org/licenses/LICENSE-2.0.html
termsOfService: https://sookocheff.com/terms
paths:
"/player/{id}":
get:
description: Returns a player with the identifier provided in the path
produces:
- application/json
response:
'200':
description: A player resource.
schema:
"$ref": "#/definitions/Player"
definitions:
Player:
type: object
properties:
playerId:
type: string
alias:
type: string
displayName:
type: string
profilePhotoUrl:
type: string
required:
- playerId
- alias
Testing Our API
With this simple specification, we can test that our API is valid by using the swagger-codegen tool to generate documentation. On OS X, you can install the codegen tool via Homebrew.
$ brew install swagger-codegen
And generate and open HTML documentation with the following commands.
$ swagger-codegen generate -i swagger.json -l html
$ open index.html
If everything went well, you should see some basic documentation for the API in your browser.
Where to Go From Here
This article showed a basic example describing a simple GET endpoint an a single resource. From here, you should have enough context to read through the Swagger specification yourself to design your own API.