OpenAPI adalah format untuk menggambarkan API HTTP di dalam berkas YAML atau JSON biasa. Di berkas itu tercatat jalur apa saja yang dibuka API, metode apa yang diterima tiap jalur, field apa yang dibawa permintaan, dan apa yang dikembalikan respons. Berkasnya terbaca oleh manusia maupun program, sehingga dokumentasi, pustaka klien, dan server tiruan untuk pengujian bisa dihasilkan dari satu sumber yang sama.

Nama resminya OpenAPI Specification, disingkat OAS. Yang merawatnya adalah OpenAPI Initiative, proyek bertata kelola terbuka di bawah Linux Foundation.

Berikut ini: bagaimana dokumennya disusun, apa beda OpenAPI dengan Swagger, apa yang berubah di versi 3.1 dan 3.2, dan mengapa janji utama format ini — dokumentasi yang tidak pernah usang — tidak terwujud dengan sendirinya.

Seperti apa dokumen OpenAPI

Berkas yang sudah berfungsi lebih pendek dari dugaan kebanyakan orang:

openapi: 3.1.0

info:
  title: Tautan
  version: "1.0"

paths:
  /links:
    post:
      summary: Buat tautan pendek
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [url]
              properties:
                url:
                  type: string
                  format: uri
      responses:
        '201':
          description: Tautan dibuat

Field wajib di tingkat teratas hanya dua, openapi dan info; selain itu dokumen harus memuat setidaknya satu di antara paths, components, atau webhooks. Begitulah spesifikasi OAS 3.1.1 menetapkannya.

Di baris-baris awal itu sudah tersembunyi satu jebakan: openapi dan info.version adalah dua hal yang berbeda. Yang pertama adalah versi formatnya sendiri, yang dibaca perkakas untuk menentukan cara menafsirkan dokumen. Yang kedua adalah versi API Anda. Spesifikasinya menyatakan ini secara gamblang, tetapi naluri membisikkan sebaliknya, dan begitulah lahir berkas yang mendeklarasikan openapi: 1.0.

Spesifikasi berukuran besar biasanya dipecah ke beberapa berkas lewat $ref: dokumen akar menunjuk ke ./paths/links.yaml, dan berkas itu menunjuk ke ./schemas/link.yaml. Praktis, sekaligus sumber satu masalah yang akan saya bahas di bagian akhir.

OpenAPI dan Swagger bukan hal yang sama

Ini kekeliruan paling umum dalam topik tersebut.

Apa itu Siapa yang merawat
OpenAPI standarnya, yaitu formatnya sendiri OpenAPI Initiative, Linux Foundation
Swagger keluarga perkakas yang membaca format itu SmartBear

Kekusutannya bisa dijelaskan lewat sejarah. Awalnya Swagger menunjuk pada spesifikasi sekaligus perkakas. Kemudian spesifikasinya diserahkan ke OpenAPI Initiative dan berganti nama menjadi OpenAPI Specification, sementara nama Swagger tetap melekat pada perkakas — Swagger UI, Swagger Editor, dan lainnya.

Dalam praktik, "kami pakai Swagger" hampir selalu berarti "kami punya berkas OpenAPI dan menampilkannya dengan Swagger UI". Tidak ada yang mengikat keduanya: berkas yang sama terbuka sama baiknya di Redoc, di Scalar, atau di sebuah pembangkit klien.

Versi: 3.0, 3.1, dan 3.2

Perbedaan antarcabang bukan soal tampilan.

3.0 masih paling luas dipakai. Titik lemahnya ada pada skema data: mirip JSON Schema tanpa benar-benar kompatibel dengannya, dan itu berulang kali merusak kemampuan perkakas untuk bekerja sama.

3.1 menutup celah tersebut. Objek Schema menjadi superset dari JSON Schema Draft 2020-12, sehingga skema yang sudah Anda kelola dalam JSON Schema tinggal dipakai ulang alih-alih ditulis ulang. Revisi yang berlaku, 3.1.1, terbit pada 24 Oktober 2024.

3.2 hadir pada September 2025. Dari pengumuman OpenAPI Initiative, yang paling menonjol:

  • metode HTTP query, untuk pembacaan idempoten yang parameternya tak muat di URL;
  • additionalOperations untuk metode di luar standar;
  • tipe media streaming: Server-Sent Events, JSON Lines, urutan JSON;
  • tag berjenjang, lewat summary, parent, dan kind;
  • alur perangkat OAuth 2.0, untuk peranti yang sulit dipakai mengetik.

Pilihlah versi yang benar-benar didukung perkakas Anda, bukan angka yang paling tinggi. Dukungan ekosistem untuk 3.1 sudah mantap; 3.2 lebih baru dan sebagian rantai perkakas masih menyusul. Spesifikasi kami sendiri mendeklarasikan 3.1.0.

Apa yang didapat dalam praktik

Satu berkas menyelesaikan beberapa urusan sekaligus:

  • dokumentasi interaktif — Swagger UI atau Redoc menyusun halaman langsung dari berkasnya, lengkap dengan formulir untuk mencoba permintaan;
  • pustaka klien — pembangkit menghasilkan SDK dalam bahasa yang Anda butuhkan, tanpa pembungkus tulisan tangan;
  • server tiruan — mock bisa dijalankan berbekal deskripsinya sebelum backend ada, sehingga frontend tidak menunggu;
  • uji kontrak — pengujian membandingkan respons sungguhan dengan skema dan menangkap saat sebuah respons mulai tidak cocok dengan deskripsinya.

Dari daftar inilah argumen utama yang mendukung OpenAPI berasal: dokumentasi berhenti menjadi teks terpisah yang lupa diperbarui seseorang.

Argumennya benar. Hanya saja ia tidak berjalan sendiri.

Tidak ada yang menghubungkan spesifikasi dengan kode

Inilah bagian yang hampir tak pernah disinggung tulisan pengantar, dan yang menggigit di lingkungan produksi.

Berkas spesifikasi hanyalah sebuah berkas. Router tidak tahu ia ada. Controller juga tidak. Anda bisa menghapus satu endpoint, menambah satu endpoint, mengubah field wajib menjadi opsional — dan tak satu pun pengujian gagal. Dokumentasi tidak menyelaraskan dirinya sendiri; ia tetap akurat persis selama masih ada orang yang ingat menyuntingnya.

Simpangnya terjadi ke dua arah, dan tiap arah merugikan dengan caranya sendiri:

  • tertulis tetapi tidak jalan. Pengembang membaca dokumentasi, mengirim permintaan, dan menerima 404. Kepercayaan pada sisa dokumentasi runtuh saat itu juga: kalau di sini keliru, di mana lagi?
  • jalan tetapi tidak tertulis. Bagi orang yang mencarinya, kemampuan itu sama saja tidak ada. Tak ada yang menemukan, tak ada yang membayarnya.

Kasus kedua lebih berbahaya, sebab tidak ada yang mengeluh. Memang tidak ada yang bisa mengeluh: pengguna tidak tahu endpoint itu ada.

Persis itulah yang menimpa kami. API Lix.li punya tiga endpoint konversi yang berjalan normal — satu daftar peristiwa, ditambah penerimaan postback secara satuan dan berkelompok — dan tak satu pun tercantum dalam spesifikasi. Kodenya jalan, pengujiannya lolos, sementara halaman pengenalan API justru memajang dua jalur yang sama sekali berbeda dan tidak ada di dalam kode. Ini ketahuan saat penyisiran menyeluruh, bukan dari laporan kesalahan.

Menangkap simpangan secara otomatis

Ini tidak selesai dengan kedisiplinan, melainkan dengan sebuah pengujian. Gagasannya lugas: ambil daftar jalur dari spesifikasi, ambil daftar rute dari router, lalu bandingkan kedua himpunan itu ke dua arah.

jalur dari openapi.yaml   →   rutenya ada?              →   kalau tidak, dokumentasi berbohong
rute dari router          →   jalurnya sudah ditulis?   →   kalau belum, fiturnya tak terlihat

Bagian "yang tertulis memang jalan" paling enak diperiksa dengan permintaan sungguhan: panggil endpoint tanpa kredensial dan pastikan responsnya 401, bukan 404. Bedanya penting. 401 berarti rutenya ketemu dan meminta kunci; 404 berarti jalur itu tidak ada. Tidak ada apa pun yang tertulis dalam prosesnya, karena autentikasi berjalan lebih dulu daripada controller.

Pemeriksaan arah sebaliknya membaca konfigurasi rute. Ia sekaligus memaksa Anda menyebutkan pengecualian secara tersurat — endpoint internal yang tak punya urusan di kontrak publik. Daftar pengecualian itu berharga dengan sendirinya: ia memaksa Anda memutuskan sekali, secara sadar, apa yang Anda anggap sebagai API publik.

Pengujian itu kami tulis setelah peristiwa konversi tadi. Nilainya langsung terbukti: jika konversi dikeluarkan lagi dari spesifikasi, pengujiannya gagal dan menyebut satu per satu kedua jalur yang hilang.

Dua jebakan yang baru disadari belakangan

$ref dan jalur relatif. Ketika spesifikasi dipecah ke beberapa berkas, rujukan di dalamnya diselesaikan relatif terhadap alamat tempat berkas itu disajikan. Dokumen akar yang tersedia di /openapi akan mencari ./paths/links.yaml di alamat /paths/links.yaml dan tidak menemukan apa-apa. Di peramban semuanya tampak beres, karena Swagger UI memuat berkasnya dari lokasi yang sebenarnya — tetapi pembangkit klien yang diarahkan ke dokumen yang sama akan tersandung. Sajikan spesifikasi hanya dari direktorinya sendiri, atau bungkus menjadi satu berkas tunggal tanpa $ref eksternal.

Swagger UI kosong bagi perayap. Halaman Swagger UI hanyalah beberapa baris markah ditambah skrip yang menggambar isinya di peramban. Dalam HTML yang disajikan tidak ada satu pun jalur endpoint. Bagi pembaca halamannya wajar; bagi pengindeksan ia kosong melompong. Tambahkan satu kekeliruan yang sering terjadi di robots.txt: aturan Disallow: /api/ yang ditulis untuk menyembunyikan endpoint JSON ikut menyembunyikan dokumentasi untuk manusia yang tinggal di bawah awalan yang sama. Yang perlu ditutup adalah jalur persis berikut versinya — misalnya /api/1.0/ — bukan seluruh bagian.

Mulai dari mana

Kalau API sudah ada tetapi deskripsinya belum, urutannya kira-kira begini:

  1. Tulis deskripsi satu endpoint dengan tangan. Itu cukup untuk memahami strukturnya.
  2. Pilih versi yang ditangani perkakas Anda dengan mantap; secara bawaan 3.1.
  3. Pecah berkasnya dengan $ref begitu ia tak lagi muat dalam satu layar, dan tetapkan saat itu juga dari alamat mana ia disajikan.
  4. Pasang pengujian yang membandingkan spesifikasi dengan router ke dua arah. Sebelum langkah ini, segala pernyataan tentang dokumentasi yang selalu mutakhir hanyalah janji, bukan sifat.

Untuk melihat wujudnya pada API sungguhan, dokumentasi API Lix.li mencakup tautan, grup, uji A/B, dan konversi. Layanan yang dibangun di sekitar API itu ada di halaman API pemendek tautan, sementara untuk topik bertetangga tersedia apa itu webhook dan pembahasan pengalihan 301, 302, 307, 308 dan metode permintaan.