Mengenal apa itu OpenAPI

Dipublikasikan 2 minggu yang lalu 12 min read

Berawal dari mempelajari RESTful API, pada prosesnya ternya perlu untuk mempelajari apa itu OpenAPI, dan itu cukup penting. Jadi gue putusin buat mempelajari lebih detail apa itu OpenAPI.

Apa itu OpenAPI ?

Dari website resmisnya dijalasakan OpenAPI itu adalah Spesifikasi OpenAPI (OAS) menyediakan cara yang konsisten untuk menyampaikan informasi melalui setiap tahap siklus hidup API. Ini adalah bahasa spesifikasi untuk API HTTP yang mendefinisikan struktur dan sintaksis dengan cara yang tidak terikat pada bahasa pemrograman yang digunakan untuk membuat API tersebut. Spesifikasi API biasanya ditulis dalam YAML atau JSON, sehingga memudahkan berbagi dan penggunaan spesifikasi.

Gue simpulin gini, OpenAPI adalah standar spesifikasi untuk membuat dokumentasi,spesifikasi, atau kontrak API yang tidak tergantung bahasa pemrograman

Dari sisi kegunaan OpenAPI dapat mempemudah Pengguna RESTful API karena tidak perlu membuka Aplikasi ataupun Dokumen manual Pdf/Doc untuk memami RESTful API. Karena sudah didukung untuk menampilkan element secara visual, contoh menggunakan aplikasi Swagger.

Tipe Data dan Format

Tipe data konsepnya sama dengan dibahasa pemrogaraman yaitu untuk mendeskripsikan bentuk bentuk dari sebuah variable, Pada spefikasi Resmi OpenAPI tipe data nya sebagai berikut: 

Sedangkan gunakan format untuk mendeskripsikan sejumlah format lain yang mungkin diwakili oleh format tersebut, tetapi di luar daftar resmi di atas, Contoh : 

type format Description
number Any numbers.
number float Floating-point numbers.
number double Floating-point numbers with double precision.
integer Integer numbers.
integer int32 Signed 32-bit integers (commonly used integer type).
integer int64 Signed 64-bit integers (long type).
type format Description Example

dan masih banyak lagi, tetapi di luar daftar resmi di atas, format-format tersebut mungkin bisa tidak didukung oleh alat yang bekerja dengan Spesifikasi OpenAPI, yang berarti bahwa format-format tersebut akan diberikan lebih sebagai petunjuk kepada pengguna akhir API. 

Untuk apa sebenarnya Format itu? kalau Type saja sudah mendukung ?  Sebenarnya tipe data tidak selalu dapat mengakomodir seluruh kebutuhan dalam mendeskripsikan data pada API. Ada kondisi di mana sebuah data memiliki tipe yang sama, tetapi makna dan bentuk nilainya berbeda.

Sebagai contoh, created_at, email, dan password sama-sama memiliki type: string. Namun ketiganya merepresentasikan data yang berbeda. Oleh karena itu OpenAPI menyediakan format untuk memberikan informasi tambahan yang lebih spesifik.

Dengan adanya format, dokumentasi API menjadi lebih jelas, proses validasi lebih akurat, dan berbagai tool pendukung seperti Swagger UI, validator, maupun code generator dapat memahami karakteristik data dengan lebih baik.

Format juga tidak baku dapat ditulis bebas sesuai kebutuhan.

employee_code:
  type: string
  format: employee-code

Intinya  itu 

Document

OpenAPI Document dapat dianggap sebagai pusat informasi dari sebuah API. Dokumen ini berisi seluruh deskripsi API dalam format YAML atau JSON, mulai dari informasi umum API, daftar endpoint, struktur request dan response, hingga mekanisme autentikasi yang digunakan. Secara sederhana, OpenAPI Document adalah sebuah object besar yang menyimpan semua konfigurasi dan spesifikasi API dalam satu tempat sehingga dapat dipahami oleh developer maupun berbagai tool pendukung OpenAPI. Object nya sebagai berikut.

Field Tipe Required Keterangan
openapi string Versi spesifikasi OpenAPI yang digunakan
info object Informasi umum mengenai API
paths object Daftar endpoint API
servers array Daftar server yang menyediakan API
components object Kumpulan komponen yang dapat digunakan kembali
security array Konfigurasi autentikasi global
tags array Pengelompokan endpoint API
externalDocs object Referensi ke dokumentasi eksternal

Object atau field OpenApi Document itu ada yang Required.  dan object tersusun dari object yang bersarang (nested object).  Untuk Rekomendasi Konvensi Penamaan key pada Dokumen OpenAPI (berdasarkan rekomendasi ChatGPT & Gemini) :

Keyword OpenAPI  → ikuti spesifikasi (openapi, info, paths, requestBody, dll)
Schema           → PascalCase (Product, UserProfile)
Field JSON       → camelCase (productId, productName, createdAt)

Berikut contoh pengaplikasiannya dalam JSON : 

{
  "openapi": "3.1.0",
  "info": {
    "title": "Product API",
    "version": "1.0.0",
    "description": "API untuk mengelola data produk"
  },
  "servers": [
    {
      "url": "https://api.example.com"
    }
  ],
  "paths": {
    "/products": {
      "get": {
        "summary": "Daftar Produk"
      }
    }
  },
  "components": {
    "schemas": {
      "Product": {
        "type": "object"
      }
    }
  },
  "tags": [
    {
      "name": "Products"
    }
  ]
}

Setiap object memiliki spesifikasi sendiri mengenai field apa yang wajib (required) dan field apa yang opsional. Aturan required tidak hanya berlaku pada root object, tetapi juga pada seluruh child object di dalamnya.

OpenAPI Object
│
├── info (Info Object)
│     ├── title      ✅ required
│     ├── version    ✅ required
│     └── description ❌ optional
│
├── servers (Server Object)
│     ├── url        ✅ required
│     └── description ❌ optional
│
└── tags (Tag Object)
      ├── name       ✅ required
      └── description ❌ optional

Contoh OpenAPI 

Berikut adalah document OpenApi dalam format JSON dengan kasus Toko.

{
	"openapi": "3.0.3",
	"info": {
		"title": "Toko API",
		"version": "1.0.0",
		"description": "API untuk mengelola produk pada sistem toko."
	},
	"security": [
		{
			"ApiKeyAuth": []
		}
	],
	"servers": [
		{
			"url": "https://api.toko.com",
			"description": "Production Server"
		},
		{
			"url": "https://dev-api.toko.com",
			"description": "Development Server"
		}
	],
	"externalDocs": {
		"description": "Dokumentasi Lengkap Toko API",
		"url": "https://docs.toko.com"
	},
	"tags": [
		{
			"name": "Product",
			"description": "Operasi terkait produk"
		}
	],
	"paths": {
		"/products": {
			"get": {
				"tags": ["Product"],
				"summary": "Mendapatkan daftar produk",
				"description": "Mengambil seluruh data produk",
				"operationId": "getProducts",
				"parameters": [
					{
						"name": "limit",
						"in": "query",
						"description": "Jumlah data yang ditampilkan",
						"required": false,
						"schema": {
							"type": "integer",
							"minimum": 1,
							"example": 10
						}
					}
				],
				"responses": {
					"200": {
						"description": "Berhasil mendapatkan daftar produk",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/ProductListResponse"
								},
								"examples": {
									"success": {
										"summary": "Daftar Produk",
										"value": {
											"success": true,
											"data": [
												{
													"id": 1,
													"name": "Laptop ASUS",
													"price": 12000000,
													"stock": 5
												},
												{
													"id": 2,
													"name": "Mouse Logitech",
													"price": 250000,
													"stock": 20
												}
											]
										}
									}
								}
							}
						}
					}
				}
			},
			"post": {
				"tags": ["Product"],
				"summary": "Menambahkan produk",
				"operationId": "createProduct",
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"$ref": "#/components/schemas/CreateProductRequest"
							},
							"examples": {
								"laptop": {
									"summary": "Contoh Produk Baru",
									"value": {
										"name": "Laptop ASUS",
										"price": 12000000,
										"stock": 5
									}
								}
							}
						}
					}
				},
				"responses": {
					"201": {
						"description": "Produk berhasil dibuat",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/ProductResponse"
								}
							}
						}
					}
				}
			}
		},
		"/products/{id}": {
			"get": {
				"tags": ["Product"],
				"summary": "Mendapatkan detail produk",
				"operationId": "getProductById",
				"parameters": [
					{
						"name": "id",
						"in": "path",
						"required": true,
						"description": "ID Produk",
						"schema": {
							"type": "integer",
							"example": 1
						}
					}
				],
				"responses": {
					"200": {
						"description": "Detail produk",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/ProductResponse"
								}
							}
						}
					}
				}
			}
		}
	},
	"components": {
		"schemas": {
			"Product": {
				"type": "object",
				"properties": {
					"id": {
						"type": "integer",
						"example": 1
					},
					"name": {
						"type": "string",
						"example": "Laptop ASUS"
					},
					"price": {
						"type": "number",
						"format": "double",
						"example": 12000000
					},
					"stock": {
						"type": "integer",
						"example": 5
					}
				},
				"required": ["id", "name", "price", "stock"]
			},
			"CreateProductRequest": {
				"type": "object",
				"properties": {
					"name": {
						"type": "string",
						"example": "Laptop ASUS"
					},
					"price": {
						"type": "number",
						"format": "double",
						"example": 12000000
					},
					"stock": {
						"type": "integer",
						"example": 5
					}
				},
				"required": ["name", "price", "stock"]
			},
			"ProductResponse": {
				"type": "object",
				"properties": {
					"success": {
						"type": "boolean",
						"example": true
					},
					"data": {
						"$ref": "#/components/schemas/Product"
					}
				}
			},
			"ProductListResponse": {
				"type": "object",
				"properties": {
					"success": {
						"type": "boolean",
						"example": true
					},
					"data": {
						"type": "array",
						"items": {
							"$ref": "#/components/schemas/Product"
						}
					}
				}
			}
		},
		"securitySchemes": {
			"ApiKeyAuth": {
				"type": "apiKey",
				"in": "header",
				"name": "X-API-Key"
			}
		}
	}
}

Untuk penjelasannya berikut ini :

Info

Menyimpan informasi umum mengenai API seperti title, version, dan description.

Contoh:

{
  "info": {
    "title": "Toko API",
    "version": "1.0.0",
    "description": "API untuk mengelola produk toko"
  }
}

Server

Mendefinisikan base URL atau alamat server tempat API diakses.

Contoh:

{
  "servers": [
    {
      "url": "https://api.toko.com",
      "description": "Production Server"
    }
  ]
}

External Documentation

Menyediakan link ke dokumentasi eksternal yang berkaitan dengan API.

Contoh:

{
  "externalDocs": {
    "description": "Dokumentasi Lengkap",
    "url": "https://docs.toko.com"
  }
}

Path

Mendefinisikan endpoint atau resource yang tersedia pada API.

Contoh:

{
  "paths": {
    "/products": {}
  }
}

Operation

Mendefinisikan aksi HTTP (GET, POST, PUT, PATCH, DELETE) yang dapat dilakukan pada suatu path.

Contoh:

{
  "paths": {
    "/products": {
      "get": {
        "summary": "Daftar Produk"
      }
    }
  }
}

Parameter

Mendefinisikan input yang dikirim melalui URL, baik sebagai path parameter, query parameter, header parameter, maupun cookie parameter.

Contoh Query Parameter:

URL:
GET /products?limit=10

{
  "name": "limit",
  "in": "query",
  "required": false,
  "schema": {
    "type": "integer"
  }
}

Contoh Path Parameter:

{
  "name": "id",
  "in": "path",
  "required": true,
  "schema": {
    "type": "integer"
  }
}

URL:
GET /products/1


Schema

Mendefinisikan struktur dan tipe data yang digunakan dalam request maupun response.

Contoh:

{
  "type": "object",
  "properties": {
    "id": {
      "type": "integer"
    },
    "name": {
      "type": "string"
    }
  }
}

Request Body

Mendefinisikan data yang dikirim client ke server pada request.

Contoh:

{
  "requestBody": {
    "required": true,
    "content": {
      "application/json": {
        "schema": {
          "$ref": "#/components/schemas/CreateProductRequest"
        }
      }
    }
  }
}

Payload yang dikirim:

{
  "name": "Laptop ASUS",
  "price": 12000000
}

Object Schema

Schema yang merepresentasikan struktur data berbentuk object yang memiliki properties.

Contoh:

{
  "type": "object",
  "properties": {
    "id": {
      "type": "integer"
    },
    "name": {
      "type": "string"
    }
  }
}

Hasil:

{
  "id": 1,
  "name": "Laptop ASUS"
}

Array Schema

Schema yang merepresentasikan struktur data berbentuk array yang berisi kumpulan item.

Contoh:

{
  "type": "array",
  "items": {
    "type": "string"
  }
}

Hasil:

[
  "Laptop",
  "Mouse",
  "Keyboard"
]

Example

Menyediakan contoh nilai atau contoh payload agar dokumentasi lebih mudah dipahami.

Contoh:

{
  "type": "string",
  "example": "Laptop ASUS"
}

Response Body

Mendefinisikan data yang dikembalikan server kepada client sebagai hasil dari request.

Contoh:

{
  "responses": {
    "200": {
      "description": "Success",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/ProductResponse"
          }
        }
      }
    }
  }
}

Response:

{
  "success": true,
  "data": {
    "id": 1,
    "name": "Laptop ASUS"
  }
}

Tag

Digunakan untuk mengelompokkan operation agar dokumentasi lebih terorganisir.

Contoh:

{
  "tags": [
    {
      "name": "Product",
      "description": "Operasi terkait produk"
    }
  ]
}

Penggunaan:

{
  "get": {
    "tags": [
      "Product"
    ]
  }
}

Component

Tempat menyimpan komponen yang dapat digunakan kembali seperti schemas, parameters, responses, dan securitySchemes.

components
├── schemas
├── responses
├── parameters
├── examples
├── requestBodies
├── headers
├── securitySchemes
├── links
└── callbacks

Contoh:

{
  "components": {
    "schemas": {
      "Product": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "name": {
            "type": "string"
          }
        }
      }
    }
  }
}

Reference ($ref)

Digunakan untuk mereferensikan komponen yang sudah didefinisikan sebelumnya sehingga dapat digunakan ulang tanpa duplikasi.

Contoh Definisi:

{
  "components": {
    "schemas": {
      "Product": {
        "type": "object"
      }
    }
  }
}

Contoh Penggunaan:

{
  "$ref": "#/components/schemas/Product"
}

Security

Digunakan untuk menentukan apakah suatu endpoint memerlukan autentikasi atau tidak.

Contoh:

{
  "security": [
    {
      "ApiKeyAuth": []
    }
  ]
}

Artinya endpoint tersebut memerlukan autentikasi menggunakan ApiKeyAuth.

Security Scheme

Digunakan untuk mendefinisikan bagaimana proses autentikasi dilakukan.

Contoh:

{
  "components": {
    "securitySchemes": {
      "ApiKeyAuth": {
        "type": "apiKey",
        "in": "header",
        "name": "X-API-Key"
      }
    }
  }
}

Penjelasan:
- type : jenis autentikasi.
- in : lokasi pengiriman API Key.
- name : nama header atau parameter yang digunakan.

Contoh Request:

GET /products HTTP/1.1
Host: api.toko.com
X-API-Key: abc123xyz

Hubungan Security dan Security Scheme

1. Definisikan terlebih dahulu security scheme:

{
  "components": {
    "securitySchemes": {
      "ApiKeyAuth": {
        "type": "apiKey",
        "in": "header",
        "name": "X-API-Key"
      }
    }
  }
}

2. Gunakan pada document atau operation:

{
  "security": [
    {
      "ApiKeyAuth": []
    }
  ]
}

 

Learning Notes

  • Mendefinisikan Api Prefix terkait version dll, bisa ditulis Base URL / Base Path di Server (tergantung kebutuhan),  contoh "/api". 
// di path	
"paths": {
		"/api/register": {
			"post": {}
		}
	}
// di server
"servers": [
        { "url": "http://localhost:8000/api", "description": "Local Development" }
    ],
  • JSON vs YAML
    Dalam penulisan OpenAPI, kita bisa menggunakan JSON maupun YAML. Gue sendiri masih agak dilema mau pakai yang mana karena keduanya punya kelebihan dan kekurangan masing-masing.

    Dari contoh-contoh sebelumnya, gue lebih banyak menggunakan JSON. Kekurangannya, penulisannya cukup panjang karena harus menuliskan tanda kutip pada setiap key dan value, ditambah lagi harus membuka dan menutup object ({}) maupun array ([]) secara eksplisit.

    Di sisi lain, JSON punya beberapa kelebihan. Salah satunya adalah kita tidak perlu terlalu khawatir soal indentasi karena formatnya lebih ketat. Selain itu, kalau menemukan contoh dari internet, biasanya tinggal copy-paste saja. Jika formatnya berantakan, cukup dirapikan menggunakan formatter seperti Prettier.

    Sementara itu, YAML terasa lebih bersih dan enak dibaca. Kita tidak perlu menuliskan banyak tanda kutip maupun membuka dan menutup object dan array secara eksplisit. Namun, YAML sangat bergantung pada indentasi. Ketika melakukan copy-paste dari sumber lain, sering kali perlu merapikan kembali indentasinya agar tetap valid.

    Untuk saat ini, gue memilih menggunakan JSON karena lebih terbiasa membaca dan bekerja dengan format tersebut. Meskipun begitu, bukan berarti ke depannya gue tidak akan menggunakan YAML. Bisa saja nanti gue beralih atau bahkan menggunakan keduanya sesuai kebutuhan.

    Berikut beberapa aspek perbandingan JSON dan YAML yang gue dapatkan dari AI.

Aspek YAML JSON
Mudah dibaca manusia ✅ Sangat baik ⚠️ Cukup baik
Mudah ditulis manual ✅ Ya ⚠️ Lebih banyak karakter
Mudah diproses mesin ✅ Ya ✅ Sangat baik
Mendukung comment # komentar ❌ Tidak
Mendukung multiline string ✅ Ya ❌ Tidak praktis
Menggunakan {} dan [] ⚠️ Sedikit ✅ Wajib
Menggunakan tanda kutip untuk key ❌ Tidak wajib ✅ Wajib
Menggunakan tanda kutip untuk string ❌ Tidak wajib ✅ Wajib
Sensitif terhadap indentasi ✅ Ya ❌ Tidak
Ukuran file ✅ Biasanya lebih kecil ⚠️ Sedikit lebih besar
Risiko typo indentasi ⚠️ Tinggi ✅ Rendah
Validasi struktur ⚠️ Lebih kompleks ✅ Lebih sederhana
Mendukung referensi/alias ✅ Ya (&, *) ❌ Tidak
Cocok untuk konfigurasi ✅ Sangat cocok ⚠️ Cukup
Cocok untuk dokumentasi OpenAPI ✅ Sangat umum ✅ Didukung
Cocok untuk request/response API ⚠️ Jarang ✅ Standar
Digunakan sebagai format pertukaran data ⚠️ Jarang ✅ Sangat umum
Didukung hampir semua bahasa pemrograman ✅ Ya ✅ Ya
Mudah dibaca saat file besar ✅ Lebih nyaman ❌ Cepat ramai
Standar REST API ❌ Bukan standar utama ✅ Standar utama

 

 

Referensi

OpenAPI Spesification

Belajar OpenAPI - Youtube (Programmer Zaman Now)

https://www.openapis.org/what-is-openapi

https://swagger.io/docs/specification/v3_0/data-models/data-types/

https://www.speakeasy.com/blog/openapi-tips-data-type-formats

Tinggalkan komentar

Nama yang akan ditampilkan pada komentar.

🔔 Email opsional untuk menerima notifikasi balasan.

Tulis komentar Anda dengan jelas dan tetap sopan.