API jarang rusak karena perubahan besar yang terlihat jelas. Sering kali masalah muncul dari hal kecil: nama field diganti, format tanggal berubah, nilai null tiba-tiba menjadi string kosong, atau endpoint yang sebelumnya menerima satu format request mulai menolak format lama.
Bagi tim yang mengelola satu aplikasi, perubahan seperti ini mungkin mudah diperbaiki. Namun, API biasanya dipakai banyak client: website, aplikasi Android, aplikasi iOS, dashboard internal, partner bisnis, bahkan skrip otomatis yang tidak selalu kita kendalikan. Karena itu, API perlu diperlakukan seperti kontrak. Perubahan pada kontrak harus direncanakan, dikomunikasikan, dan diberi masa transisi.
Mengapa perubahan API bisa berdampak besar?
Bayangkan sebuah endpoint mengembalikan data pengguna seperti ini:
{
"name": "Rina",
"phone": "08123456789"
}Lalu backend mengganti nama field phone menjadi phone_number. Dari sisi database, perubahan itu mungkin terasa lebih rapi. Namun client yang masih membaca phone akan menerima nilai kosong atau mengalami error.
Masalahnya tidak selalu berupa error yang langsung terlihat. Client bisa tetap berjalan, tetapi menampilkan informasi yang salah. Aplikasi mungkin menganggap field yang hilang sebagai nilai default. Inilah jenis bug yang sulit dideteksi jika tidak ada pengujian kontrak dan pemantauan respons API.
Perubahan yang berisiko merusak client biasanya disebut breaking change. Contohnya:
- Menghapus field yang sebelumnya tersedia.
- Mengganti nama endpoint atau parameter.
- Mengubah tipe data, misalnya angka menjadi teks.
- Mengubah struktur JSON secara drastis.
- Mengubah arti status atau kode respons.
- Membuat field wajib yang sebelumnya opsional.
Memahami tiga jenis perubahan
1. Perubahan yang relatif aman
Menambahkan field baru biasanya aman bagi client yang hanya mengambil field yang mereka perlukan. Misalnya, menambahkan avatar_url ke respons pengguna. Namun, tetap ada pengecualian. Client yang memvalidasi respons dengan skema sangat ketat bisa menganggap field tambahan sebagai masalah.
Karena itu, “aman” bukan berarti bebas risiko. Tim tetap perlu mengetahui bagaimana client memproses respons.
2. Perubahan yang berpotensi mengganggu
Mengubah aturan validasi, urutan prioritas, format pesan error, atau batas maksimum request dapat memengaruhi sebagian client. Perubahan semacam ini kadang tidak disebut breaking change secara formal, tetapi tetap perlu diuji.
3. Breaking change
Jika client lama tidak mungkin bekerja tanpa mengubah kode, perubahan tersebut adalah breaking change. Untuk perubahan seperti ini, jangan hanya mengubah implementasi backend dan berharap semua konsumen segera menyesuaikan diri.
Pilih strategi versioning yang mudah dipahami
Versioning adalah cara memberi identitas pada kontrak API. Strategi yang paling umum adalah menaruh versi di URL:
GET /api/v1/users
GET /api/v2/usersKeuntungannya sederhana: versi mudah dilihat, mudah diuji, dan mudah dijelaskan kepada tim lain. Kekurangannya, backend perlu mengelola lebih dari satu jalur selama masa transisi.
Pendekatan lain menggunakan header, misalnya client mengirim versi yang diinginkan. Cara ini membuat URL tetap bersih, tetapi lebih sulit dilacak ketika debugging karena versi tidak terlihat langsung dari alamat endpoint.
Untuk banyak proyek web, versioning di URL sudah cukup praktis. Yang paling penting bukan memilih metode yang terlihat paling canggih, melainkan menggunakan aturan yang konsisten.
Jangan membuat versi baru untuk setiap perubahan kecil
Versioning tidak berarti setiap penambahan field harus menghasilkan v2. Jika terlalu sering membuat versi baru, dokumentasi, pengujian, dan pemeliharaan akan cepat menjadi rumit.
Gunakan versi baru ketika kontrak lama memang tidak bisa dipertahankan. Contohnya, versi pertama mengembalikan:
{
"price": 15000
}Sementara desain baru membutuhkan harga beserta mata uang:
{
"amount": 15000,
"currency": "IDR"
}Jika field price memiliki arti yang berbeda atau benar-benar dihapus, versi baru mungkin masuk akal. Namun jika hanya perlu menambahkan informasi, lebih baik pertahankan field lama dan tambahkan field baru selama masa transisi.
Rancang perubahan secara bertahap
Proses yang lebih aman biasanya terdiri dari beberapa tahap:
- Tambahkan kemampuan baru. Jangan langsung menghapus perilaku lama.
- Berikan waktu migrasi. Informasikan kepada pemilik client tentang perubahan dan batas waktunya.
- Pantau penggunaan versi lama. Catat endpoint, client, dan versi aplikasi yang masih menggunakannya.
- Hentikan dukungan secara terjadwal. Lakukan setelah penggunaan turun atau semua client penting selesai bermigrasi.
Misalnya, API baru menyediakan /api/v2/orders, tetapi /api/v1/orders tetap tersedia selama tiga bulan. Respons versi lama dapat menyertakan informasi deprecation melalui dokumentasi atau header agar client memiliki peringatan lebih awal.
Gunakan kontrak dan pengujian otomatis
Dokumentasi saja tidak cukup. API perlu memiliki kontrak yang bisa diuji. Kontrak menjelaskan bentuk request, respons, field wajib, tipe data, dan kemungkinan kode error.
Tim dapat menggunakan spesifikasi seperti OpenAPI untuk mendeskripsikan endpoint. Dari spesifikasi tersebut, pengujian dapat memastikan bahwa implementasi tidak diam-diam menghapus field atau mengubah tipe data yang masih dijanjikan.
Pengujian penting yang bisa diterapkan antara lain:
- Memastikan respons tetap memiliki field wajib.
- Memeriksa tipe data dan format tanggal.
- Menguji kode status untuk kondisi sukses dan gagal.
- Memastikan request lama masih diterima selama masa kompatibilitas.
- Menguji contoh respons di dokumentasi agar tidak berbeda dari sistem nyata.
Jika ada tim client yang berbeda, consumer-driven contract testing juga membantu. Dalam pendekatan ini, kebutuhan client ikut menjadi bagian dari kontrak yang diuji oleh penyedia API.
Jangan lupakan error dan observability
Banyak dokumentasi API hanya menjelaskan respons sukses. Padahal, client juga perlu tahu apa yang terjadi saat token kedaluwarsa, parameter salah, atau server sedang membatasi permintaan.
Gunakan struktur error yang konsisten. Misalnya, setiap error memiliki kode internal, pesan yang aman ditampilkan, dan informasi tambahan yang tidak membocorkan data sensitif.
{
"error": {
"code": "INVALID_PARAMETER",
"message": "Parameter page harus berupa angka positif"
}
}Di sisi server, simpan metrik penggunaan berdasarkan versi API, endpoint, dan client. Data ini membantu menjawab pertanyaan praktis: apakah versi lama masih banyak dipakai, client mana yang belum bermigrasi, dan endpoint mana yang paling sering gagal?
Apa artinya bagi kita?
API yang sehat bukan API yang tidak pernah berubah. API yang sehat adalah API yang bisa berubah tanpa mengejutkan konsumennya.
Mulailah dari langkah sederhana: buat daftar endpoint publik, tandai perubahan yang breaking, dokumentasikan format respons, dan sepakati kebijakan deprecation. Jika API sudah dipakai pihak lain, jangan mengandalkan komunikasi informal di chat. Sediakan dokumentasi perubahan, contoh migrasi, tanggal penghentian, dan kanal bantuan.
Dengan kebiasaan ini, tim backend tetap bisa memperbaiki arsitektur dan menambah fitur, sementara tim frontend, mobile, dan partner memiliki waktu yang cukup untuk menyesuaikan diri. Versioning bukan sekadar menambahkan angka pada URL. Ia adalah cara mengelola janji teknis agar perubahan tetap bisa diprediksi.
– Rio Yotto @rioyotto
