DEV Community

hi-watana
hi-watana

Posted on

How to Create OpenAPI Document with Swagger

Purpose of This Post

We can create an OpenAPI document using Swagger. In this post I would like to try to give a short explanation of how to create an API document using Swagger.
If you want to know the final outcome first, please take a look at Summary first.

About OpenAPI

OpenAPI Specification (formerly Swagger Specification) is an API description format for REST APIs.

(Sited from https://swagger.io/docs/specification/about/.)

Preparation

First, open Swagger Editor (https://editor.swagger.io). You will see the page like this:
Pet Store Example

Second, clear the YAML content.
No content

Let's Start with a Simple Example

Here is a simple example that just contains info and servers of this API:

openapi: 3.0.3
info:
  version: 1.0.0
  title: Simple Todo API
  description: This is a simple API for todo notes

servers:
  - url: https://example.com/v1

paths: {}
Enter fullscreen mode Exit fullscreen mode

Let me explain it briefly. The openapi specifies the version of the OpenAPI specification. This openapi field is required for each OpenAPI document.
The info object contains two required fields, version and title. The version specifies the version of the OpenAPI document (not OpenAPI Specification version nor the API implementation version) and the title specifies the title of the API. The info object also contains description field, which is optional. It is used for a short description of the API.
The servers array specifies server URLs for API calls. In the above example, the server URL is https://example.com/v1.

At this point, our OpenAPI document is like:
Simple Example Without Any Paths

Let's Add Resource Paths

You may have already noticed that paths object was left as empty in previous section. Let's define some endpoints in this section.

Suppose that a client can:

  • get all notes by sending a GET request to /notes endpoint.
  • get a note by note ID by sending a GET request to /notes/{noteId} endpoint where {noteId} is a note ID.
  • create a note by sending a POST request to /notes endpoint.

Also suppose that note object is represented as the following JSON object:

{
  "id": 1, // integer
  "title": "sample title", // string
  "content": "sample content" // string
}
Enter fullscreen mode Exit fullscreen mode

Tags

Before defining endpoints, we will define a tag in tags like:

tags:
  - name: notes
    description: Everything about your notes
Enter fullscreen mode Exit fullscreen mode

The tags object is not required, but by defining tags we can group our endpoints.

At this point, our OpenAPI document is like:
Tags

Path Item

First let's define the /notes and the GET method for this endpoint. Replace the paths object with:

paths:
  /notes: # A relative path to an individual endpoint.
    get: # GET method on this path.
      tags: 
        - notes
      summary: Find all notes
      description: Returns all notes
      responses:
        '200': # HTTP Status Code
          description: Successful operation
          content: {} # Described later.
Enter fullscreen mode Exit fullscreen mode

GET /notes Without content
Detail of GET /notes Without content

We haven't yet defined the response body of a GET request to /notes endpoint, so we will define it. Modify paths to:

paths:
  /notes:
    get:
      tags: 
        - notes
      summary: Find all notes
      description: Returns all notes
      responses:
        '200':
          description: Successful operation
          content:
            application/json: # media type
              schema:
                type: array
                items:
                  type: object
                  properties:
                    id:
                      type: integer
                      format: int64
                    title:
                      type: string
                      example: Sample title
                    content:
                      type: string
                      example: Sample content
Enter fullscreen mode Exit fullscreen mode

Look at the schema. Its structure corresponds to that of a list of note objects defined before:

[
  {
    "id": 1, // integer
    "title": "sample title", // string
    "content": "sample content" // string
  }
]
Enter fullscreen mode Exit fullscreen mode

That's it for our first path item. This definition indicates that if a client calls GET https://example.com/v1/notes, he/she will receive 200 HTTP status code with a list of notes like:

[
  {
    "id": 1,
    "title": "title 1",
    "content": "content 1"
  },
  {
    "id": 2,
    "title": "title 2",
    "content": "content 2"
  }
]
Enter fullscreen mode Exit fullscreen mode

At this point, our OpenAPI document is like:
Detail of GET /notes

Parameters

Next let's define the /notes/{noteId} and the GET method for this endpoint. Add the following to the paths object:

  /notes/{noteId}:
    get:
      tags:
        - notes
      summary: Find note by ID
      description: Returns a single note
      parameters: # You can define parameters here.
        - name: noteId
          in: path
          required: true
          description: ID of note to return
          schema:
            type: integer
            format: int64
      responses:
        '200':
          description: Successful operation
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: integer
                    format: int64
                  title:
                    type: string
                    example: Sample title
                  content:
                    type: string
                    example: Sample content
        '404':
          description: Note not found
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: integer
                    format: int32
                  message:
                    type: string
Enter fullscreen mode Exit fullscreen mode

It's basically the same as the definition of GET method for /notes. One of a difference is the existence of 404 HTTP status code response. We can use any HTTP status codes as property names.
Another important difference is the parameters field. We can define parameters (such as path parameter, query parameter) in this parameters field. Here is the part of the parameters:

      parameters:
        - name: noteId
          in: path # This is a path parameter.
          required: true # This parameter is required.
          description: ID of note to return
          schema:
            type: integer # This is an integer parameter.
            format: int64
Enter fullscreen mode Exit fullscreen mode

At this point, our OpenAPI document is like:
GET /notes/{noteId}

Components

As you may have noticed, we defined the note object twice. We can avoid defining the same object many times using the components object. Let's define Note and ApiResponse and reuse them. Add the following components object:

components:
  schemas:
    Note:
      type: object
      properties:
        id:
          type: integer
          format: int64
        title:
          type: string
          example: Sample title
        content:
          type: string
          example: Sample content
    ApiResponse:
      type: object
      properties:
        status:
          type: integer
          format: int32
        message:
          type: string
Enter fullscreen mode Exit fullscreen mode

Then modify the paths object to:

paths:
  /notes:
    get:
      tags: 
        - notes
      summary: Find all notes
      description: Returns all notes
      responses:
        '200':
          description: Successful operation
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/Note' # New

  /notes/{noteId}:
    get:
      tags:
        - notes
      summary: Find note by ID
      description: Returns a single note
      parameters:
        - name: noteId
          in: path
          required: true
          description: ID of note to return
          schema:
            type: integer
            format: int64
      responses:
        '200':
          description: Successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Note' # New
        '404':
          description: Note not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiResponse' # New
Enter fullscreen mode Exit fullscreen mode

At this point, our OpenAPI document is like:
Components
Detail of Components

Request Body

Finally let's add the POST method for /notes endpoint. Add the following object to /notes:

    post: # POST method
      tags:
        - notes
      summary: Add a new note
      description: Tries to craete a new note and returns a message
      requestBody: # We can define the request body here.
        required: true
        description: Note object that needs to be added
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Note'
      responses:
        '200':
          description: Successfully added
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiResponse'
        '500':
          description: Unexpected error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiResponse'

Enter fullscreen mode Exit fullscreen mode

Since this is a definition for POST method, post is used.
Also, there is a new field, requestBody. We can define the request body using the requestBody field. Here is the part of requestBody:

      requestBody: # We can define the request body here.
        required: true
        description: Note object that needs to be added
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Note'
Enter fullscreen mode Exit fullscreen mode

Now our OpenAPI document is like:
POST /notes
Detail of POST /notes

Summary

That's it. I made a short explanation of how to create an OpenAPI document using Swagger.
Following is the final outcome:

openapi: 3.0.3
info:
  version: 1.0.0
  title: Simple Todo API
  description: This is a simple API for todo notes

servers:
  - url: https://example.com/v1

tags:
  - name: notes
    description: Everything about your notes

paths:
  /notes:
    get:
      tags: 
        - notes
      summary: Find all notes
      description: Returns all notes
      responses:
        '200':
          description: Successful operation
          content:
            application/json: # media type
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/Note'
    post: # POST method
      tags:
        - notes
      summary: Add a new note
      description: Tries to craete a new note and returns a message
      requestBody: # We can define the request body here.
        required: true
        description: Note object that needs to be added
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Note'
      responses:
        '200':
          description: Successfully added
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiResponse'
        '500':
          description: Unexpected error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiResponse'

  /notes/{noteId}:
    get:
      tags:
        - notes
      summary: Find note by ID
      description: Returns a single note
      parameters:
        - name: noteId
          in: path
          required: true
          description: ID of note to return
          schema:
            type: integer
            format: int64
      responses:
        '200':
          description: Successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Note'
        '404':
          description: Note not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiResponse'

components:
  schemas:
    Note:
      type: object
      properties:
        id:
          type: integer
          format: int64
        title:
          type: string
          example: Sample title
        content:
          type: string
          example: Sample content
    ApiResponse:
      type: object
      properties:
        status:
          type: integer
          format: int32
        message:
          type: string
Enter fullscreen mode Exit fullscreen mode

Reference

Discussion (0)