YAML OpenAPI Spec

In this day and age, APIs have been one of the core components for data-driven apps and businesses. While many raise issues on the quality, standards, and security of getting APIs to communicate with each other, OpenAPI comes in as a solution.

Introduction to OpenAPI

What are OpenAPI and OpenAPI Specifications?

Open API or Public API is an API that was made publicly available for software developers. Originally, the concept for OpenAPI was largely pushed by Swagger and the Swagger Specification, which was developed with the goal of letting an API describe its own format and contents. This evolved into the OpenAPI Specification (OAS), an API description format for REST APIs. Here are what you can describe with an OpenAPI file:

  • Available endpoint and operations on each endpoint.
  • Operation parameters Input and Output for each operation.
  • Authentication methods.
  • Relevant contact information, license, term of use, and other information.

We can write API Specifications in YAML or JSON as the format is easy to learn and both human-readable and machine-friendly. For more information on OpenAPI Specification, please click the link here.

OpenAPI Terms and Definition

Before jumping into the topic, we should start with definitions for all the unfamiliar terms that we might come across throughout this guide.

  • Definition: A document in OpenAPI format that defines a specific API.
  • OAS: Short for Open API Specification.
  • Specification: A set of rules that defines the format for OpenAPI.
  • OpenAPI: A specification that declares a syntax for API descriptions that are readable for humans and machines.
  • OpenAPI document: Another term for OpenAPI flavor or API definition.
  • OpenAPI file: An individual OpenAPI document.
  • OpenAPI Initiative: A group that maintains the OpenAPI format.

What is Swagger?

Swagger was the original API description format (previously known as the Swagger Specification) that developed into the OpenAPI that we know today. Now it is the set of open-source tools, built around the OpenAPI Specification that can help you with designing, building, documenting, and consuming REST APIs. Below are several Swagger tools that will become familiar to us.

  • Swagger Editor: A browser-based editor where we can write OpenAPI specs.
  • Swagger UI: A tool that can help us render OpenAPI specifications as interactive API documentation.
  • Swagger Codegen: A tool for generating server stubs and client SDKs from an OpenAPI spec.

Why Do We Use OpenAPI?

One of the main strengths of using OpenAPI is the ability for APIs to describe their own structure. But there are several other valuable benefits, such as:

  • Reduced dependencies between development teams and certain components of a certain application.
  • Less time to fix mistakes when writing a code because JSON and YAML use simple syntax.

Basic Structure

In the earlier chapter, we mentioned that we can write OpenAPI definitions in YAML or JSON. In this guide, we will be focusing on YAML. However, you can also practice using JSON if you wish. Below is a sample OpenAPI 3.0 definition written in YAML.

openapi: 3.0.0
info:
  title: API Documentation Practice
  description: Optional multiline or single-line description in
               [CommonMark](http://commonmark.org/help/) or HTML.
  version: '3.0'
  termsOfService: ''
  
servers:
  - url: http://api.example.com/v1
    description: Optional server description, e.g. Main (production) server
  - url: http://staging-api.example.com
    description: Optional server description, e.g. Internal staging server for testing
paths:
  /users:
    get:
      summary: Returns a list of users.
      description: Optional extended description in CommonMark or HTML.
      responses:
        '200':    # status code
          description: A JSON array of user names
          content:
            application/json:
              schema: 
                type: array
                items: 
                  type: string

All keywords are case-sensitive, and remember to be careful about indentation – as it carries meaning.

Metadata

openapi: 3.0.0

Declaring the OpenAPI Specification version  is important as it defines the overall structure of an API definition. It defines the ‘What’ and ‘How’ you can document the API definition. In this case, we are using OpenAPI 3.0 that uses the semantic versioning with a three-part version number. There are four available versions that we can use; version  3.0.0, version 3.0.1, version 3.0.2, and version 3.0.3.

On the next line, we declare info about our API information. The example on the info object below would contain information such as title, description(optional), version, and termsOfService.

info:
  title: API Documentation Pratice
  description: Optional multiline or single-line description in [CommonMark](http://commonmark.org/help/) or HTML.
  version: '3.0'
  termsOfService: ''

The info object provides metadata about the API. The metadata can be used if needed and can be presented in editing or when documenting generation tools for convenience.

Field NameTypeDescriptionRequired
titleStringThe title of the API.Yes
descriptionStringA short description of the API. CommonMark syntax can be used for rich text representation.Conditional
versionStringThe version of the OpenAPI document
(it is different from the OpenAPI Specification version or the API implementation version).
Yes
termsOfServiceStringA URL to the Terms of Service for the API. It has to be in the format of a URL.Conditional
contactObjectContains information from the Contact object such as the contact information for the exposed API.Conditional
licenseObjectContains information from the License object such as the license information for the exposed API.Conditional
OpenAPI Metadata

If we want, this object may be extended with Specification Extensions. For more information, click here.

Servers

The servers section specifies the API server and base URL. You can define one or several servers such as production or sandbox.

servers:
  - url: http://api.example.com/v1
    description: Optional server description, e.g. Main (production) server
  - url: http://staging-api.example.com
    description: Optional server description, e.g. Internal staging server for testing

All API Paths are relative to the server URL. For more information click here.

Paths

The paths section defines individual endpoints, or paths, in your API and the HTTP methods supported by these endpoints. Below is an example of how the path is described. We will use GET /users as an example.

paths:
  /users:
    get:
      summary: Returns a list of users.
      description: Optional extended description in CommonMark or HTML.
      responses:
        '200':   
          description: A JSON array of user names
          content:
            application/json:
              schema: 
                type: array
                items: 
                  type: string

This is an operation definition that includes parameters, request body (if there is any), possible response status codes (such as 200 OK or 404 Not Found), and response contents. For more information click here.

Parameters

Operations may have parameters passed via URL path, query, string, headers, or cookies. Below is an example of how we can define parameter data types, format, whether they are required or optional, and other details.

paths:
  /users/{userId}:
   get: 
      summary: Returns a user by ID.
      parameters:
        - name: userID
          in: path
          required: true
          description: Parameter description in CommonMark or HTML
          schema:
            Type: integer
            Format: int64
            minimum: 1
       responses:
         '200':
          description: Ok

Request Body

If an operation sends a request body, use the requestBody keyword to describe the body content and media type.

paths:
  /users:
    post:
      summary: Creates a user.
      requestBody:
        required: true
        content:
        application/json:
          schema:
            type:
            properties:
              username:
                type: string
       responses:
        '201':    
          description: Created

Responses

In each operation, you may define possible status codes such as 200 OK or 404 Not Found, and the response body schema. Schemas can be defined inline or referenced via $ref. If we want, we may also provide example responses for different content types like the code below

paths:
  /users/{userId}:
    get:
      summary: Returns a user by ID.
      parameters:
        - name: userId
          in: path
          required: true
          description: The ID of the user to return.
          schema:
            type: integer
            format: int64
            minimum: 1
      responses:
        '200':
          description: A user object.
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: integer
                    format: int64
                    example: 4
                  name:
                    type: string
                    example: John Doe
        '400':
          description: The specified user ID is invalid (not a number).
        '404':
          description: A user with the specified ID was not found.
        default:
          description: Unexpected error

The response HTTP status codes must be enclosed in quotes:, e.g. “200”, depending on the version (this is not required in OpenAPI 2.0).

Input and Output Models

The global components/schemas section lets you define common data structures used in your API. They can be referenced via $ref whenever a schema is required – in parameters, request bodies, and response bodies. See the example below.

components:
  schemas:
    User:
      type: object
      properties:
        id:
          type: integer
          example: 4
        name:
          type: string
          example: Jane Dough
      # Both properties are required
      required:  
        - id
        - name

It will then be referenced in the request body schema and response body schema like the example below.

paths:
  /users/{userId}:
    get:
      summary: Returns a user by ID.
      parameters:
        - in: path
          name: userId
          required: true
          schema:
            type: integer
            format: int64
            minimum: 1
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/User'    # <-------
  /users:
    post:
      summary: Creates a new user.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/User'      # <-------
      responses:
        '201':
          description: Created

Authentication

The securitySchemes and security keywords can be used to describe the authentication methods used in your API. Look at the example below.

components:
  securitySchemes:
    BasicAuth:
      type: http
      scheme: basic
security:
  - BasicAuth: []

Several authentication methods are supported:

  • HTTP authentication: Basic, Bearer, and so on.
  • API key as a header, query parameter, or cookies.
  • OAuth 2
  • OpenID Connect Discovery

%d bloggers like this: