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:
- string
- number
- integer
- boolean
- array
- object
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 |
|---|---|---|---|
| string | date | An RFC3339 formatted date string | "2022-01-30" |
| string | date-time | An RFC3339 formatted date-time string | "2019-10-12T07:20:50.52Z" |
| string | password | Provides a hint that the string may contain sensitive information. | "mySecretWord1234" |
| string | byte | Base-64 encoded data. | "U3BlYWtlYXN5IG1ha2VzIHdvcmtpbmcgd2l0aCBBUElzIGZ1biE=" |
| string | binary | Binary data, used to represent the contents of a file. | "01010101110001" |
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
- type = mendefinisikan jenis data
- format = memberikan informasi tambahan yang lebih spesifik tentang data
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": []
}
]
}
- Nama "ApiKeyAuth" bebas.
- Nama "securitySchemes" tidak boleh diganti karena merupakan bagian dari spesifikasi OpenAPI.
- Security Scheme harus didefinisikan di components.securitySchemes.
- Security hanya digunakan untuk mereferensikan Security Scheme yang sudah didefinisikan.
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
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