Ana Sayfa / Blog / API versiyonlama: URL, header, content negotiation, pratikte hangisi?

API versiyonlama: URL, header, content negotiation, pratikte hangisi?

/api/v1/users versus header-based negotiation. Hangi yaklaşım işe yarıyor, hangisi teoride güzel ama production'da problem çıkarıyor.

Bir API 2 yıl yaşayacaksa versiyonlamayı ilk günden düşünmen gerekiyor. Aksi halde 18 ay sonra “breaking change yapamıyorum çünkü clients kırılır” diyor kendinizi buluyorsunuz.

Üç ana yaklaşım var. Her birinin teori’de söylediği ve production’da gerçekleşeni karşılaştıralım.

1. URL Path Versioning

GET /api/v1/users ve GET /api/v2/users

Bu çok yaygın ve pratik. Stripe, GitHub, Twitter, hepsi bu yaklaşımı benimsiyor (veya benzeri).

Teoride söylenen

“URL bir resource’u tanımlamalı, versiyon resource değil. REST prensibine aykırı.”

Production’da gerçeklik

  • Çalışıyor. Browser’da açabilirsin, Postman’de test edebilirsin, documentation clear.
  • Router config’i trivial: /api/v1/* → v1 handler, /api/v2/* → v2 handler.
  • Monitoring/analytics kolay: hangi versiyon ne kadar kullanılıyor, log’dan direkt görüyorsun.
  • Client library’lerde doğal: Stripe SDK stripe.users() diye çağırıyor, altta URL değişse bile API’nin developer experience’ı aynı.

Karşı argüman REST purity meselesi, ama API purity’nin pratik sorunlarınızı çözmesini beklerseniz başka konularda da problem yaşarsınız.

2. Header-based Versioning

GET /api/users + Accept-Version: v2 header’ı

Teoride söylenen

“URL temiz kalır. Resource identity versiyondan bağımsız.”

Production’da gerçeklik

  • Debugging zor: browser’da URL açıp deneme yapamıyorsun, log’da header görünmüyor varsayılan olarak
  • Caching problem: CDN/reverse proxy farklı versiyonları ayrı cache’lemeli, yanlış konfigürasyonda karışıyor
  • Dokümantasyonda “Bu header’ı atmak zorundasın” uyarıları çoğalıyor
  • Client library’lerde ek konfigürasyon (default header set etmek)

Kullandığım projelerde 2 kez header-based ile başladık, 1-1.5 yıl sonra URL path’e geçtik. Her seferinde sebep: debugging ve client-side sorunlar.

Benim önerim: Header-based versioning, gerçekten kapsamlı bir API platform’u değilseniz kaçının.

3. Content Negotiation (Media Type Versioning)

GET /api/users + Accept: application/vnd.mycompany.v2+json

Teoride söylenen

“Bu en RESTful yaklaşım. Content type response format’ını tanımlıyor.”

Production’da gerçeklik

  • Bütün header-based’in problemleri + daha karmaşık
  • Content negotiation için client library’nin accept header’ı doğru set etmesi gerekiyor
  • Çoğu HTTP client bunu dokunmuyor, developer’lar karışıyor
  • Swagger/OpenAPI documentation tool’ları bununla iyi oynamıyor

Asla önermiyorum. Teorik avantajı pratik overhead’i karşılamıyor.

Hangisi ne zaman?

Pratik kural:

  • %90 project: URL path (v1, v2). Kolay, sade, developer-friendly.
  • Internal API + güçlü operations team: Header-based mümkün ama gerek yok.
  • Content negotiation: Academic paper yazmıyorsanız kaçının.

Versiyon ne zaman arttırılır?

Daha önemli soru. “Breaking change” ne demek?

Breaking change (v2 gerektirir):

  • Response field’ını kaldırmak veya rename etmek
  • Request field’ını zorunlu yapmak (eskiden opsiyoneldi)
  • Endpoint’i silmek
  • Authentication yöntemini değiştirmek

Non-breaking (v1’de kalabilir):

  • Yeni opsiyonel response field’ı eklemek
  • Yeni endpoint eklemek
  • Yeni opsiyonel request parameter eklemek
  • Response ordering değiştirmek (istemci sıralama’ya güvenmemeli)

Bu sınır net değil, gray area var. Stripe’ın yaklaşımı iyi: her küçük API change için yeni bir “API version” (date-based: 2023-10-01), client Accept-Version header’da hangi tarihte dondurduğunu söylüyor. Çok elegant ama implementation overhead yüksek.

Deprecation stratejisi, versiyonlamanın başı

Versiyonlama sadece yeni versiyon açmak değil, eski versiyonu kapatabilmek. Aksi halde 4 farklı versiyon paralel destekliyorsun, hepsi bakım yükü.

Yaklaşımım:

  1. Announcement (6 ay önce): blog post + email + response header’da Deprecation: true + Sunset: 2026-06-01
  2. Warnings (3 ay önce): response header’da daha güçlü uyarılar, email reminder’lar
  3. Graceful degradation (1 ay önce): eski API hala çalışıyor ama rate limit düşürüyoruz
  4. Shutdown: 410 Gone dönüyor, tek mesaj “upgrade to v2”

Bu 6 aylık window enterprise client’ların migrate olması için yeterli. 3 ay çok kısa, 1 yıl lüzumsuz uzun.

Monitoring, hangi versiyon ne kadar kullanılıyor?

Every API request log’una version’ı ekle. Haftalık dashboard:

  • v1 kullanım: %35, azalan trend ✓
  • v2 kullanım: %65, artan trend ✓

Eğer v1 kullanımı hiç düşmüyorsa, deprecation announcement’ı güçlendirmen gerekiyor. Eğer v2 hızla artıyorsa, v1 shutdown’ı öne çekebilirsin.

Metrics olmadan karar veremezsin, “galiba artık v1’i kimse kullanmıyor” ≠ gerçek veri.

Sonuç

API versiyonlama kararı ilk günden verilmeli. URL path basit, pratik, developer-friendly, çoğu proje için ilk tercih.

Breaking change tanımınızı net çizin, deprecation timeline’ı ciddi kurgulayın, monitoring koymadan geçmeyin. Bu 3 şey doğru yapılırsa versiyonlama acı değil, sadece bir bakım rutini.

Bu konuda bir projeniz mi var?

Kısa bir özet bırakın, 24 saat içinde size dönüş yapayım.

İletişime Geç