---
# System prepended metadata

title: 'Documenting your API: Introduction to Swagger'
tags: [' deprecated', ' pratical', ' swagger', api]

---

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

![](https://i.imgur.com/ZTJ2zRq.png)

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:

![](https://i.imgur.com/jW4Y6pA.png)

## 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:

![](https://i.imgur.com/3QLMJIC.png)

## 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:

![](https://i.imgur.com/FSmkak5.png)

## 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:

![](https://i.imgur.com/MQnk3hP.png)

## 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:

![](https://i.imgur.com/Pe1SkKq.png)


## 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:

![](https://i.imgur.com/1G8XUMP.png)

## Challenge: DELETE /cats/:catId

This one will be very similar to the `PATCH` documentation. It should look like this when you are done:

![](https://i.imgur.com/XYlaJHC.png)

## Challenge: PATCH /feed/:catId

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

![](https://i.imgur.com/WxziuM7.png)


## 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`.











