Perubahan API

Praktik terbaik versi API, demi kepentingan pemanggil

6 menit baca

Versi API adalah praktik menjaga kontrak lama tetap berfungsi setelah Anda mengubahnya, sehingga pemanggil bisa maju sesuai jadwal mereka sendiri alih-alih jadwal Anda. Kalimat itu berisi dua keputusan yang penting: apa yang terhitung sebagai mengubah kontraknya, dan berapa lama yang lama tetap berfungsi. Di mana nomor versi berada, yang menjadi topik kebanyakan perdebatan versi, adalah yang paling tidak penting dari ketiganya dan paling mudah dibenarkan.

Kapan sebuah API seharusnya diversikan?

Versikan API hanya ketika sebuah perubahan akan merusak pemanggil yang benar. Perubahan aditif, field baru, endpoint baru, parameter opsional baru, tidak membutuhkan versi; pemanggil yang ditulis terhadap kontrak lama tetap berfungsi dan kemampuan baru itu ada begitu saja. Sebuah breaking change membutuhkannya, karena alternatifnya adalah pemanggil mengetahuinya dari error. Memversikan setiap rilis, termasuk yang aditif, mengajarkan pemanggil bahwa versi adalah kebisingan, dan mereka berhenti membaca pemberitahuan yang penting.

Tes praktisnya sama dengan artikel tentang breaking change: jika pemanggil yang hanya mengandalkan perilaku terdokumentasi harus mengubah sesuatu untuk tetap berfungsi, perubahan itu membutuhkan versi. Jika tidak, rilis di bawah versi saat ini dan tulis entri changelog.

Skema versi API mana yang seharusnya digunakan?

Gunakan skema yang paling mudah dilihat dan ditetapkan pemanggil Anda, yang untuk kebanyakan API publik adalah versi di jalur URL atau header versi bertanggal. Empat skema umum berbeda lebih sedikit dalam kemampuan daripada dalam apa yang mereka minta dari pemanggil, dan itu dasar yang tepat untuk memilih.

SkemaContohYang harus dilakukan pemanggilSiapa yang menggunakan
Jalur URL/v2/invoicesMengubah URL saat bermigrasiKebanyakan API REST publik
Header versiX-GitHub-Api-Version: 2022-11-28Mengirim header, atau menerima defaultGitHub
Versi akun bertanggalStripe-Version: 2026-08-26Menetapkan tanggal per permintaan atau per akunStripe
Parameter query/invoices?version=2Menambahkan parameterAPI lama; sekarang jarang dipilih
Media typeAccept: application/vnd.example.v2+jsonBernegosiasi jenis kontenPurist; sedikit pemanggil bisa mengelola

Jalur URL paling terlihat dan paling tidak fleksibel. Setiap pemanggil bisa melihat versi mereka dengan membaca baris log, dan lompatan versi adalah cari-dan-ganti. Biayanya: seluruh permukaan bergerak sekaligus, Anda tidak bisa mengubah kontrak satu endpoint tanpa mencetak versi baru untuk semuanya, jadi versi jalur cenderung jarang dan besar.

Header versi menjaga URL tetap stabil dan membiarkan server memilih default untuk pemanggil yang tidak mengirim apa pun, seperti cara kerja versi API REST GitHub: versi bernama tanggal dalam X-GitHub-Api-Version, dengan versi yang didukung tertua sebagai default agar pemanggil tanpa versi tidak rusak. Biayanya: versinya tidak terlihat dalam URL dan mudah dilupakan dalam klien baru.

Versi akun bertanggal adalah skema header ditambah satu tambahan: versinya disimpan terhadap akun, sehingga setiap permintaan mendapatkannya tanpa mengirim apa pun. Versi API Stripe menetapkan setiap akun ke versi saat dibuat dan membiarkan permintaan menimpanya dengan Stripe-Version. Ini skema paling ramah pemanggil dan paling banyak pekerjaan untuk dijalankan, karena server harus menerjemahkan antara setiap versi yang didukung dan yang saat ini. Skema Stripe adalah contoh paling terkenal dari pendekatan tanggal, dan cara Stripe memberi versi pada API-nya membahasnya langkah demi langkah.

Parameter query dan media type keduanya berfungsi dan keduanya gagal dalam tes visibilitas dengan cara berbeda: parameter query mudah hilang saat membangun URL, dan versi media type tidak terlihat oleh hampir semua alat yang digunakan pemanggil untuk debug.

Bagaimana versi API dilakukan dalam praktik?

Dalam praktik versi adalah kumpulan perilaku bernama, dan server memetakan setiap permintaan ke salah satunya. Langkah-langkahnya sama apa pun skema yang membawa namanya.

  1. Namai versi berdasarkan tanggal atau bilangan bulat, bukan versi semantik. API web bukan paket. Pemanggil tidak bisa menetapkan versi minor dari URL, jadi v2 atau 2026-08-26 mengatakan semua yang dibutuhkan pemanggil, dan versi semantik menyiratkan janji kompatibilitas yang tidak bisa dipenuhi skema tersebut.
  2. Jaga versinya di luar jalur kode yang tidak peduli. Versi seharusnya memilih lapisan terjemahan di tepi, bukan mencabangkan logika bisnis. Dua salinan penuh dari kode basis adalah bagaimana versi berakhir tidak terpelihara.
  3. Beri setiap versi default dan dokumen. Pemanggil yang tidak mengirim versi mendapat yang paling lama didukung, tidak pernah yang terbaru, sehingga klien yang tidak ditetapkan tidak rusak pada hari rilis. Setiap versi punya halaman yang mengatakan apa yang berubah dari yang sebelumnya.
  4. Tetapkan jendela dukungan dan terbitkan. Panduan versioning Google, AIP-185, meminta masa transisi yang wajar dan dikomunikasikan dengan baik, serta merekomendasikan 180 hari bahkan untuk fungsionalitas beta. Pilih jendela, tulis, dan terapkan tanpa negosiasi ulang per versi.
  5. Pensiunkan versi seperti Anda mempensiunkan endpoint. Versi yang melewati jendelanya mendapat perlakuan yang sama dengan API yang di-deprecate: sebuah pengumuman, header Sunset (RFC 8594) di setiap respons, pengingat di tengah jalan kepada pemanggil yang tersisa, dan tanggal penghapusan yang dipegang teguh.

Apa itu v1 dan v2 dalam API REST?

v1 dan v2 adalah nama untuk dua kontrak yang didukung server yang sama pada saat bersamaan. v2 ada karena sesuatu di v1 tidak bisa diubah tanpa merusak pemanggilnya, jadi perubahannya masuk ke kontrak baru dan yang lama tetap berfungsi. Angka-angka itu tidak menyiratkan bahwa v2 lengkap atau v1 mati; keduanya hanya benar jika dokumentasi mengatakannya. v3 yang muncul setiap kuartal adalah tanda bahwa perubahan aditif sedang diversikan, atau bahwa kontraknya tidak pernah dirancang untuk menyerap perubahan. gRPC menyelesaikan masalah yang sama secara berbeda: perubahan API gRPC dan Protobuf membahas versi lewat nama paket dalam berkas .proto alih-alih jalur URL, dan format wire di mana mengganti nama field gratis tapi menomorinya ulang adalah breaking change yang tidak akan dikenali pemanggil REST mana pun sebagai berisiko.

Apa yang harus diumumkan perubahan versi?

Perubahan versi harus mengumumkan apa yang rusak, siapa yang terdampak, cara bermigrasi, dan berapa lama versi sebelumnya tetap berfungsi. Entrinya punya bentuk yang sama dengan entri breaking change lainnya, ditambah satu baris menyatakan jendela dukungan. Berikut satu untuk API yang diversikan dengan header:

Versi API 2026-11-01 tersedia. Versi 2025-06-15 didukung hingga 1 November 2027. Baru di 2026-11-01: GET /invoices mengembalikan amount dalam unit terkecil sebagai bilangan bulat alih-alih string desimal, dan field yang di-deprecate customer_name dihapus demi objek customer. Memengaruhi pemanggil di 2025-06-15 yang mengurai amount sebagai string, yang merupakan default untuk klien tidak ditetapkan yang dibuat sebelum Juni 2025. Migrasi: uraikan amount sebagai bilangan bulat dan baca namanya dari customer.name. Tetapkan X-Api-Version: 2026-11-01 saat Anda siap. Tidak ada yang berubah untuk pemanggil yang tidak menetapkan versi.

Kalimat terakhir itu yang memungkinkan kebanyakan pembaca berhenti membaca, dan itu milik setiap pengumuman versi. Halaman contoh changelog menyertakan entri dari API yang memversikan seperti ini, dan perbedaan antara yang baik dan sisanya sebagian besar ada di kalimat terakhir itu.

Siapa yang diberi tahu ketika versi berubah?

Semua orang di versi lama, secara individu, dan changelog untuk semua orang lainnya. Perubahan versi adalah satu-satunya kasus di mana “kami memposting tentang itu” dijamin akan melewatkan tepat pemanggil yang penting: mereka yang menetapkan versi dua tahun lalu dan belum membaca catatan rilis sejak itu. Data penggunaan menjawab siapa mereka; pemberitahuannya harus mencapai mereka di mana kode mereka berada, dalam header respons dan dalam pesan kepada pemilik akun.

Dalam lingkaran yang kami jalankan, entri yang mengumumkan versi disusun dari pull request yang merilisnya, ditinjau oleh seseorang, dan diterbitkan di feed dan widget, tempat klien berversi bisa membacanya sebagai JSON. Siapa pun yang masukan widget-nya meminta perubahan itu, atau melaporkan bug yang diselesaikannya, dan menjadi issue GitHub yang ditutup oleh pull request, diberi tahu di issue tersebut segera setelah entrinya live. Mekanismenya sama dengan entri mana pun; lompatan versi hanyalah entri dengan taruhan tertinggi.

FAQ

Haruskah setiap perubahan API mendapat versi baru? Tidak. Hanya breaking change. Perubahan aditif dirilis di bawah versi saat ini dengan entri changelog. Memversikan perubahan aditif melatih pemanggil untuk mengabaikan versi.

Apakah versi URL lebih baik daripada versi header? Versi URL lebih mudah dilihat pemanggil dan lebih sulit bagi Anda untuk berkembang sedikit demi sedikit; versi header sebaliknya. Untuk API publik dengan banyak klien kecil, versi URL gagal lebih sedikit. Untuk API besar dengan lapisan terjemahan, versi bertanggal berbasis header berskala lebih baik.

Berapa banyak versi yang seharusnya didukung sekaligus? Sesedikit yang diizinkan jendela dukungan Anda, dan tidak pernah jumlah tak terbatas. Dua atau tiga versi bersamaan itu normal; lebih dari itu biasanya berarti versi tidak dipensiunkan.

Apa yang seharusnya diterima permintaan tanpa versi? Versi yang paling lama didukung, sehingga klien yang ada dan tidak ditetapkan tetap berfungsi, dengan header respons yang memberi tahu mereka versi mana yang mereka terima.


Klaim teknis dalam artikel ini belum ditinjau secara independen. Jika ada yang keliru, beri tahu kami dan kami akan memperbaikinya.

Terkait di changeloop: Dokumentasi developer, Contoh changelog

changeloop
Tim di balik changelog yang menutup lingkaran. Pengguna meminta sesuatu, timmu mengirimkannya, yang meminta jadi tahu.