# How to write REST document with Swagger
### I. Why Swagger
- It's popularity. Swagger is the most widely adopted documentation and specification standard for REST Services.
- Designed for REST so it's easy to use with very clear sample templates.
- Beautiful UI. The plain text you write can be converted to nice html with SwaggerUI.
- Auto-generate Code. You can auto-generate client and server code (interface part) based on the Swagger spec, which makes sure that they are consistent.
### II. How to create REST document with Swagger
You can use [SwaggerEditor](https://editor.swagger.io/#/) as a starter. And if you have just a few api, you can totally write the specification in 1 file. However, having a structure would be a better idea because clean code is better code, and it's also helpful when you want to add or edit your api later.
We'll be using the sample api doc from [SwaggerEditor](https://editor.swagger.io/#/) and re-arrange some pet's apis into our structure.
#### 1. Create your openapi folder

As you can see from the structure, we will not put all api specs in single `index.yaml` file. Instead, we separate them and define references to those files in `index.yaml`
#### 2. `openapi/index.yaml`
```yaml!
openapi: "3.0.0"
info:
title: Swagger Petstore - OpenAPI 3.0
description: This is a sample Pet Store Server based on the OpenAPI 3.0 specification
version: "1.0.0"
servers:
- url: https://petstore3.swagger.io
variables:
basepath:
default: /api/v3
paths:
/pet:
$ref: ./paths/pet/index.yaml
/pet/{petId}:
$ref: ./paths/pet/pet_id/index.yaml
components:
schemas:
$ref: ./schemas/index.yaml
parameters:
$ref: ./parameters/index.yaml
```
- openapi: This is to say what version we're using.
- info: basic info, includes:
+ title: The title of your API documentation.
+ description: A description of your API.
+ version: The version of your API
- servers: server definition, includes:
+ url: The server where your REST API is located.
+ basePath: The path on the server where your REST API is located. This can be defined in url instead of defining in basepath.
- paths: are the api endpoints
- component: includes schemas (for request and response), and parameters
And now, instead of one long specication file, we put it into smaller chunks which is easier to modify later.
#### 3. `openapi/paths`
Now in path folder, create directories as we have define in $ref.
Let's take pet directory as an example, it'll look something like this.

In the path file, you define the HTTP methods (e.g. GET, POST, PUT) that the path can be used with. Then, continue to separate parameters, request body, and response in schemas folder.
```yaml!
# example on /pet path
post:
tags:
- pet
summary: Add a new pet to the store
description: Add a new pet to the store
operationId: addPet
requestBody:
description: Create a new pet in the store
content:
application/json:
schema:
$ref: '../../schemas/request/petDetails.yaml'
required: true
responses:
'200':
description: Successful operation
content:
application/json:
schema:
$ref: '../../schemas/response/petDetails.yaml'
'405':
description: Invalid input
# example on /pet/{petId} path
get:
tags:
- pet
summary: Find pet by ID
description: Returns a single pet
operationId: getPetById
parameters:
- $ref: '../../../parameters/petId.yaml'
responses:
'200':
description: successful operation
content:
application/json:
schema:
$ref: '../../../schemas/response/petDetails.yaml'
'400':
description: Invalid ID supplied
'404':
description: Pet not found
```
- tags: is to separate your document into section. Here you have pet section, store section and user section. It's to make the document clear, not a compulsory.
- summary: A short description of the service. There is also a description property for a more lengthy description, if necessary.
- description: is a longer details of this api
- operationId: the http method id
- parameters: The different parameters that the service accepts. It is both parameters in the HTTP header, URI path, query string and HTTP request body.
- responses: The possible responses that the service can return. (HTTP Status Code): You first specify the HTTP Status Code (e.g. 200). Then, inside, provide a short description of when this response happens and content of the response
#### 4. `openapi/schemas`
As we have separated our request and response models, it is neccessary to have a combination file that gather all models. That's why in `openapi/index.yaml`, the schemas was reference to 1 `index.yaml` file in schemas folder.
##### a) `openapi/schemas/index.yaml`
```yaml!
PetDetailsRequest:
$ref: ./request/petDetails.yaml
PetDetailsResponse:
$ref: ./response/petDetails.yaml
```
##### b) `openapi/schemas/request/petDetails.yaml` & `openapi/schemas/response/petDetails.yaml`
```yaml!
type: object
required:
- name
- photoUrls
properties:
id:
type: integer
format: int64
example: 10
name:
type: string
example: doggie
category:
$ref: '../category.yaml'
photoUrls:
type: array
xml:
wrapped: true
items:
type: string
xml:
name: photoUrl
tags:
type: array
xml:
wrapped: true
items:
$ref: '../tag.yaml'
status:
type: string
description: pet status in the store
enum:
- available
- pending
- sold
```
- type: type of request
- required: fields that are required in this request
- properties: request field's type

**In this example, because response and request models are same, you should not write it twice.*
#### 5. `openapi/parameters`
Similar to schemas, we also need an index file to combine all parameters definition.
##### a) `openapi/parameters/index.yaml`
```yaml!
PetId:
$ref: ./petId.yaml
```
##### b) `openapi/parameters/petId.yaml`
```yaml!
name: petId
in: path
description: ID of pet to return
required: true
schema:
type: integer
format: int64
```
- name: The name of the parameter.
- in: Where is the parameter located? In the path, in the body, in a header, or somewhere else?
- description: A short, user-friendly description of the parameter.
- required: Is the parameter required or optional?
- chema: includes:
+ type: The data type of the parameter. The common types are number and string.
+ format: is not compulsory
#### 6. Generate interface for client side
Well, as we split the specifications for better checking and modification.
It's time to build those separate files into one. We can easily do that with just 1 command line.
```javascript!
swagger-cli bundle index.yaml -o ./build.yaml -t yaml
```
- index.yaml is the input file that we want to build, which is located in `openapi/index.yaml`
- /build.yaml is the build file, you can name it differently as you wish, or put it in build folder (like this /build/index.yaml)
Now, we get 1 merged file. If you take a look, you'll see that it looks exactly like the one before we split. There are 2 ways to generate code:
**Method #1: use cli**
Make sure you have install the openapi cli:
https://openapi-generator.tech/docs/installation/
Then, to generate the interface, use the command line as in the link and example below.
https://openapi-generator.tech/docs/usage#generate
Ex:
```javascript!
openapi-generator-cli generate -i your_directory/openapi/build.yaml -g typescript-axios -o your_directory/openapi/output
```
Here, i generate code for typescript, but you can refer to below for the list of generators and their options that match your need.
https://openapi-generator.tech/docs/generators
**Method #2: use swagger editor**
Go to https://editor.swagger.io/ then paste you build.yaml file in the editor. At the top, you can see the generator options, just select the one you need and it will generate and automatically download the output for you.
*By using swagger editor, you can also view the api document you wrote in pretty ui and dont have to download swaggerUI
### III. Conclusion
Swagger has been around for long and favored by many developers.
It's not difficult to write api specification with Swagger and you can start right away with your current project. It's always good to know how to write a proper document that your team can refer to, so I hope this helps.
<small>
Published date: 2022-12-22 <br/>
Also published <a href="https://medium.com/goalist-blog/how-to-write-rest-document-with-swagger-4109b30d6f6b">here</a>.
</small>