---
tags: api, pratical, deprecated, swagger
---
# Documenting your API: Introduction to Swagger
Swagger is an Interface Description Language for describing RESTful APIs expressed using JSON.
Infomation about the API and endpoints is stored in a json file, and then then served through our API.
To get started with swagger, we will be adding documentation to the [have-i-fed-the-cat-app](https://hackmd.io/k9O1pQE0TuOVN4lcgpAlYQ) we wrote in a previous session. If you don't have a working app handy, then there is an example app you can use [here](https://github.com/MCRcodes/have-i-fed-the-cat-demo). Clone the app and follow the instructions to get it running.
You should also install the [OpenAPI Lint](https://marketplace.visualstudio.com/items?itemName=mermade.openapi-lint) extension for VS Code. This will help us spot any issues in our JSON and offer suggestions for the correct format.
## Basic Swagger Template
Create a file called `swagger.json` in the root of your project, this is where we will be doing most of the work to write our documentation.
```json=
{
"swagger":"2.0",
"info": {
"version": "1.0.0",
"title": "",
"description": "",
"license": {
"name": "MIT",
"url": "https://opensource.org/licenses/MIT"
}
},
"basePath": "/",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"schemes": [
"http",
"https"
],
"tags": [],
"paths": {},
"definitions": {}
}
```
Make sure to fill in the title and the description to suit your app.
## Install Swagger UI
To display our swagger documents, we will be using the `swagger-ui-express module`. Install it as a dependency:
```bash=
npm i -S swagger-ui-express
```
To use it, will need to require it in our `app.js`, along with our `swagger.json`:
```javascript=
// src/app.js
const swaggerUi = require('swagger-ui-express');
const swaggerDoc = require('../swagger.json');
```
Next we will need to create an enpoint to server our swagger docs from:
```javascript=
// src/app.js
app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerDoc));
```
Now if we start the app and go to `localhost:3000/api-docs` in the browser:

Now we just need to define our paths.
## Defining Paths and Methods
We can do this by adding a `"/cats"` object to the `"paths"` section of our document. Inside there we define the request method like so:
```json=
...
"paths": {
"/cats": {
"post": {
"tags": [],
"summary": "creates a new cat in the database",
"parameters": [
{
"name": "PostCatRequest",
"in": "body",
"description": "post a cat to the database",
"schema": {}
}
],
"responses": {
"201": {
"description": "cat successfully created",
"schema": {}
}
},
"produces": [
"application/json"
]
}
}
}
...
```
We can see the results when we refresh the browser:

## Tagging the Paths
Looks good, but there's a few more details we can add. For starters we can add a tag to our path. This groups paths and helps organize large apps.
We define the tag at teh top level of the document like so:
```json=
...
"tags": [
{
"name": "Cats",
"description": "Endpoints for interacting with cats"
}
],
...
```
Then just reference the tags in the path object:
```json=
...
"/cats": {
"post": {
"tags": [
"Cats"
],
...
```
Now we can reload and see that our `POST` route is in the `Cats` category:

## Adding a Schema
You may have noticed the `schema` section in the `path` and `response`. This is where we can define the data that our app consumes and produces. We can do this either in the path or the `definitions` section. As this app is small, we can stick to in-path definition.
```json=
...
"schema": {
"type": "object",
"required": [
"name",
"breed",
"markings"
],
"properties": {
"name": {
"type": "string"
},
"breed": {
"type": "string"
},
"markings": {
"type": "string"
}
}
}
...
```
We will also need to define a schema for the `201` response, we will probably want to reuse this, so lets define a schema in the `definitions` section and use `$ref` to reference it.:
```json=
...
"responses": {
"201": {
"description": "cat successfully created",
"schema": {
"type": "object",
"$ref": "#/definitions/CatObject"
}
}
},
...
"definitions": {
"CatObject": {
"required": [
"id",
"name",
"breed",
"markings",
"lastFed",
"createdAt",
"updatedAt"
],
"properties": {
"id":{
"type": "integer"
},
"name": {
"type": "string"
},
"breed": {
"type": "string"
},
"markings": {
"type": "string"
},
"lastFed": {
"type": "string"
},
"createdAt": {
"type": "string"
},
"updatedAt": {
"type": "string"
}
}
}
}
```
Now we can refresh the browser and see the results:

## Adding another method
That's the documentation for our `POST /cats` endpoint done. Let's try adding another method to the `/cats` path. We can re-use the schema from out `POST` endpoint, but as we are returning an array, we can wrap it in another schema like so:
```json=
...
"get": {
"summary": "reads cats from the database",
"tags": [
"Cats"
],
"parameters": [],
"responses": {
"200": {
"description": "returns array of cats",
"schema": {
"$ref": "#/definitions/CatObjects"
}
}
}
}
}
...
"definitions": {
"CatObjects": {
"properties": {
"cats": {
"type": "array",
"items": {
"$ref": "#/definitions/CatObject"
}
}
}
},
}
```
Another difference from our last endpoint is that this one accepts a `query string`. We can define that in our swagger doc by adding the follwing to the the parameters for this path:
```json=
...
"parameters": [
{
"name": "name",
"type": "string",
"in": "query"
},
{
"name": "breed",
"type": "string",
"in": "query"
},
{
"name": "markings",
"type": "string",
"in": "query"
},
{
"name": "lastFed",
"type": "string",
"in": "query"
}
],
...
```
If everything is correct, then your docs should contain the following:

## Adding another path
The remaining endpoints in our api are on the path `/cats/:catId`. We can represent the route parameter as `"/cats/{catId}"`. Add this new path to your swagger document along with a `get` method:
```json=
...
"/cats/{catId}": {
"get": {
"summary": "read a single cat from the database",
"tags": [
"Cats"
],
"parameters": [
{
"in": "path",
"type": "number",
"name": "catId",
"required": true
}
],
"responses": {
"200": {
"description": "returns requested cat from database",
"schema": {
"$ref": "#/definitions/CatObject"
}
}
}
}
}
...
```
Note that this time we are stating that the `catId` parameter is in the `path` of the request. We are also reusing the `CatObject` schema in our response body.
Also note that in this simple app, we're not performing a `null` check before sending the response back to the user. If we were, we would also want to document the possibility of a `404` response.
If you refresh the browser, your `GET /cats/{catId}` should look like this:

## Challenge: PATCH /cats/:catId
The next method that requires documentation is our `PATCH` controller. This will require a combination of route and body paramaters. You should be able to use what you have already written to generate the correct documentation. Your `PATCH /cats/:catId` documentation should looks like this:

## Challenge: DELETE /cats/:catId
This one will be very similar to the `PATCH` documentation. It should look like this when you are done:

## Challenge: PATCH /feed/:catId
Finally, can you add documentation for the `PATCH /feed/:catId` endpoint? It should end up looking like this:

## Optional: Converting swagger.json to markdown
The swagger.json can be used to generate markdown. This is ideal for adding to your README.md, and can be done easily with the `widdershins` module:
```bash=
npx widdershins --code swagger.json -o swagger.md
```
This will send the output to a new file called `swagger.md`.