Article
· Dec 15, 2024 6m read

Composing an OpenAPI 2.0 specification.

REST API (Representational State Transfer Application Programming Interface) is a standardized way for web applications to communicate with each other using HTTP methods like GET, POST, PUT, DELETE, etc. It's designed around resources, which can be anything from a user to a file. Each resource is identified by a unique URL, and interactions with these resources are stateless, meaning each request from a client to a server must contain all the information needed to understand and process the request. This statelessness, along with the use of standard HTTP methods, makes REST APIs highly scalable, easy to understand, and straightforward to integrate with different systems. By following REST principles, developers can create APIs that are consistent, easy to use, and capable of handling a wide range of tasks.

InterSystems supports REST API development with a variety of tools and techniques. In this article series, I am going to go over the ones that I personally prefer. The articles are divided as listed below.

  • Composing an OpenAPI 2.0 specification.
  • Documenting and Developing REST APIs using OpenAPI 2.0 specification.
  • Developing an IRIS production pipeline to serve REST API calls.

As perquisite to following the steps and instructions laid out in this article series, you should have the below setup.

  1. InterSystems IRIS for Health
  2. InterSystems IAM with Dev Portal deployed and enabled.
  3. Postman or any other API testing software.

Let’s assume that we are developing a workflow for managing clinic appointments. We will focus on an appointment resource and how to develop GET, POST, PUT methods for it. You can use the same steps even to develop a DELETE method, but I am not going to do it because I personally do not prefer it.

First, you need to start with composing an OpenAPI 2.0 spec for your application APIs. I use the swagger editor for this task to be able to develop in YAML format, and then convert the spec file to JSON. I then can use the JSON file to use with IRIS API management tools. You can use the online swagger editor for free or you can download and deploy a container of it locally from here.

When I compose an OpenAPI spec, I think of the file as three sections. The intro section is where you lay out the description information. It includes fields that describe the nature of the application such as the description, license, tags that categorizes different endpoints and the URL by combining the host and base URL. It also includes the confines in the which it can operate if any such as the schemas and security definitions.

The below code block has a sample intro section that going to be reference from here on. If you paste it into an open swagger editor, you will notice that the groundwork of the API documentation is taking shape.

 

swagger: "2.0"
info:
  description: "This is a sample server to be as an example Clinic server.  You can find out more about Swagger at [http://swagger.io](http://swagger.io). For this sample, you can use the api key `special-key` or Basic Auth user `Basic` with password `Basic` to test the authorization filters."
  version: "1.0.0"
  title: "Clinic Management"
  termsOfService: "http://swagger.io/terms/"
  contact:
    email: "raef.youssef@intersystems.com"
  license:
    name: "Apache 2.0"
    url: "http://www.apache.org/licenses/LICENSE-2.0.html"
host: "apigatewaydns"
basePath: "/clinic"
tags:
- name: "Scheduling"
  description: "Everything about your Pets"
  externalDocs:
    description: "Find out more"
    url: "http://intersystems.com"
schemes:
- "http"
- "https"
securityDefinitions:
  BasicAuth:
    type: "basic"
    name: "Basic"
  api_key:
    type: "apiKey"
    name: "api_key"
    in: "header"

Second section of the spec file is the body. This is where you list the different paths, aka endpoints, and the methods that are available for each. For the purpose of this demo, we will just compose spec for the “/appointment” end point. Below is the text for that.


paths:
  /appointment:
    get:
      tags:
        - Scheduling
      summary: "Fetches an existing appointment details"
      security:
      - Basic: []
      description: "Fetches an existing appointment details by providing its ID"
      operationId: "getAppointmentByID"
      produces:
      - "application/json"
      parameters:
      - in: "query"
        name: "id"
        type: "integer"
        format: "int64"
        description: "ID of the appointment sought"
        required: true
      responses:
        '200':
          description: successful operation
#          schema:
#            $ref: '#/definitions/appointment'
    post:
      tags:
        - Scheduling
      summary: ""
      security:
      - api_key: []
      description: ""
      operationId: "postAppointment"
      consumes:
      - "application/json"
      - "application/xml"
      produces:
      - "application/json"
      - "application/xml"
      parameters:
      - in: "formData"
        name: "Date"
        type: "string"
        format: "date-time"
        description: ""
        required: true
      - in: "formData"
        name: "duration"
        type: "integer"
        format: "int64"
        description: "number of half hour slots of the appointment duration"
        required: true
      responses:
        '200':
          description: successful operation
        '405':
          description: Time not available
    put:
      tags:
        - Scheduling
      summary: ""
      security:
      - BasicAuth: []
      description: ""
      operationId: "updateAppointment"
      consumes:
      - "application/json"
      - "application/xml"
      produces:
      - "application/json"
      - "application/xml"
      parameters:
      - in: "query"
        name: "id"
        type: "integer"
        format: "int64"
        description: "ID of the appointment sought"
        required: true
      - in: "body"
        name: "body"
        description: ""
        required: true
#        schema:
#          $ref: "#/definitions/appointment"
      responses:
        '200':
          description: successful operation
        '405' :
          description: Time not available
        '406' :
          description: Appointment Not Found

A few things to note in the paths section. First, you can assign a different authentication mechanism for each method. There is an “OperationID” field which would be used to name the backend process that serves the respective method call. Furthermore, you can define a schema for a request JSON body and response, it commented out here so it won’t error when you paste as we have not defined it yet. Finally, you can define custom response codes and messages.

The last section is where different message schemas are defined. In this example, we will compose the appointment schema to include appointment ID, Date, Duration, and Provider of service name. Below is the text of the YAML definition. After pasting the below in your editor, you can uncomment the lines where the schema definition is referenced.

definitions:
    appointment:
        type: "object"
        properties:
            id:
                type: "integer"
                format: "int64"
            Provider:
                type: "string"
                format: "string"
            Date:
                type: "string"
                format: "date-time"
            Duration:
                type: "integer"
                format: "int64"

This concludes this part of the series. We are going to use this spec in the later parts of the series. They are coming soon so be on the lookout. For more information on developing OpenAPI 2.0 specification please refer to the documentation here.

Discussion (0)1
Log in or sign up to continue