REST API nedir, nasıl tasarlanır? Endpoint, HTTP metotları, durum kodları ve JSON yapısını örneklerle ve sık yapılan hatalarla ele alıyoruz.
API Neyi Çözüyor?
Bir mobil uygulama, bir web arayüzü ve bir muhasebe sistemi aynı veriye ihtiyaç duyduğunda, her biri için ayrı bir veri erişim katmanı yazmak sürdürülebilir değildir. Kural bir yerde değişince üç yeri birden güncellemeniz gerekir — ve biri mutlaka unutulur.
API, veriyi ve iş kurallarını tek bir yerde toplayıp dışarıya standart bir arayüzle sunar. İstemcilerin hangi teknolojiyle yazıldığı önemsiz hale gelir. REST ise bu arayüzü HTTP'nin kendi kavramları üzerine kurma yaklaşımıdır: kaynaklar, adresler ve metotlar.
Kaynak ve Endpoint Tasarımı
REST'te her şey bir kaynaktır ve kaynaklar isimlerle temsil edilir, fiillerle değil. Fiili adres değil, HTTP metodu belirler.
| Yanlış | Doğru | Neden |
|---|---|---|
GET /kullaniciGetir?id=5 | GET /kullanicilar/5 | Fiil metotta, kaynak adreste |
POST /kullaniciSil | DELETE /kullanicilar/5 | Silme işlemi DELETE'tir |
GET /kullanici/5/siparisGetir | GET /kullanicilar/5/siparisler | Hiyerarşi adreste görünür |
GET /tumKullanicilar | GET /kullanicilar?sayfa=2&adet=20 | Sayfalama olmadan liste büyür |
Çoğul isim kullanmak ve hiyerarşiyi adreste göstermek okunabilirliği belirgin biçimde artırır. Ancak hiyerarşiyi ikiden fazla seviyeye taşımamak gerekir: /kullanicilar/5/siparisler/12/kalemler/3 yerine /siparis-kalemleri/3 hem daha kısa hem daha esnektir.
Liste uçları her zaman sayfalanmalıdır. Bugün 40 kayıt döndüren bir uç, iki yıl sonra 40.000 kayıt döndürür ve o gün hem sunucu hem istemci tarafında sorun çıkarır.
HTTP Metotları ve Anlamları
Bu anlamlara sadık kalmak yalnızca estetik bir tercih değildir; önbellekleme, yeniden deneme ve ara katman davranışları bu sözleşmeye göre çalışır.
| Metot | Ne yapar | Güvenli | Tekrarlanabilir |
|---|---|---|---|
| GET | Okur, durumu değiştirmez | Evet | Evet |
| POST | Yeni kayıt oluşturur | Hayır | Hayır |
| PUT | Kaydı bütünüyle değiştirir | Hayır | Evet |
| PATCH | Kaydın bir kısmını günceller | Hayır | Genelde evet |
| DELETE | Siler | Hayır | Evet |
"Tekrarlanabilir" sütunu pratikte kritiktir: ağ koptuğunda istemci isteği yeniden gönderir. PUT'u iki kez göndermek zararsızdır, POST'u iki kez göndermek iki sipariş demektir. Ödeme gibi kritik uçlarda bu yüzden istemciden bir idempotency key alıp aynı anahtarla gelen ikinci isteği yok saymak gerekir.
Durum Kodları: Sessiz Ama Kritik
Her cevabı 200 döndürüp hatayı gövdeye yazmak yaygın bir kestirme yoldur ve istemci tarafında karmaşaya yol açar: istemci artık her cevabın gövdesini ayrıştırmadan başarılı olup olmadığını bilemez.
| Kod | Anlamı | İstemci ne yapmalı |
|---|---|---|
| 200 OK | Başarılı | Veriyi kullan |
| 201 Created | Kayıt oluşturuldu | Location başlığını oku |
| 204 No Content | Başarılı, gövde yok | Gövde ayrıştırma |
| 400 Bad Request | İstek geçersiz | Kullanıcıya alan hatalarını göster |
| 401 Unauthorized | Kimlik doğrulanmadı | Giriş ekranına yönlendir |
| 403 Forbidden | Kimlik var, yetki yok | "Yetkiniz yok" mesajı |
| 404 Not Found | Kaynak yok | Boş durum göster |
| 409 Conflict | Çakışma (mükerrer kayıt) | Kullanıcıya sebebi söyle |
| 422 | Biçim doğru, iş kuralı ihlali | Kural mesajını göster |
| 429 | Çok fazla istek | Retry-After kadar bekle |
| 500 | Sunucu hatası | Genel hata, tekrar dene |
401 ile 403 arasındaki farkı doğru kullanmak, istemcinin kullanıcıya doğru mesajı göstermesini sağlar: biri "giriş yap" der, diğeri "yetkin yok". Karıştırıldığında kullanıcı, yetkisi olmadığı bir sayfada sonsuz döngüde oturum açmaya çalışır.
Tutarlı Cevap Zarfı
Bir endpoint düz metin, diğeri nesne, bir başkası hata durumunda bambaşka bir yapı döndürdüğünde istemci kodu hızla karmaşıklaşır. Tüm cevapları ortak bir zarf içinde döndürmek, istemci tarafında tek bir işleme kuralı yazmayı mümkün kılar.
// Başarılı
{
"isSuccess": true,
"data": { "id": 42, "ad": "Ayşe Yılmaz", "eposta": "ayse@ornek.com" },
"message": null,
"errors": []
}
// Doğrulama hatası — HTTP 400 ile birlikte
{
"isSuccess": false,
"data": null,
"message": "Doğrulama hatası",
"errors": [
{ "field": "eposta", "code": "INVALID_FORMAT", "message": "Geçerli bir e-posta girin" },
{ "field": "yas", "code": "OUT_OF_RANGE", "message": "Yaş 18'den küçük olamaz" }
]
}
Hata nesnesinde field ve code alanlarının bulunması iki şeyi mümkün kılar: arayüz hatayı doğru form alanının altında gösterebilir, ve istemci mesajın metnine değil koduna göre karar verebilir. Mesaj metnine dayanan istemci kodu, çeviri eklendiği gün kırılır.
Bu yaklaşımı kendi projelerimizde OperationResult deseniyle uyguluyoruz; hem başarı hem hata aynı biçimde dönüyor.
Filtreleme, Sıralama ve Alan Seçimi
Liste uçları pratikte hiçbir zaman "hepsini getir"den ibaret kalmaz. İstemci filtrelemek, sıralamak ve bazen yalnızca birkaç alanı istemek ister. Bunları her uç için ayrı ayrı icat etmek yerine tek bir sözleşmeye oturtmak gerekir.
GET /api/v1/siparisler
?durum=beklemede,onaylandi # çoklu değer virgülle
&olusturma_min=2026-01-01 # aralık: _min / _max
&olusturma_max=2026-06-30
&ara=yilmaz # serbest metin araması
&sirala=-olusturmaTarihi,tutar # başındaki "-" azalan demek
&alanlar=id,tutar,durum # yalnızca gerekli alanlar
&sayfa=2&adet=20
| Kural | Neden |
|---|---|
| Sıralama alanları beyaz listeden | Rastgele sütun adı kabul etmek SQL enjeksiyonuna ve index'siz sorguya kapı açar |
adet için üst sınır | adet=1000000 tek istekle sunucuyu düşürebilir |
| Toplam sayı da dönsün | İstemci sayfa sayısını hesaplayabilsin |
| Varsayılan sıralama sabit olsun | Sırasız sorguda aynı kayıt iki sayfada birden çıkabilir |
Son madde sessiz bir hata kaynağıdır: veritabanı, açık bir ORDER BY olmadan satır sırasını garanti etmez. Sayfalama yapan her sorgunun benzersiz bir alanla (en azından ikincil olarak id ile) sıralanması gerekir.
Kimlik Doğrulama ve Token
Sunucunun her istekte kullanıcıyı yeniden tanıması gerekir. Token tabanlı yaklaşımda kullanıcı bir kez giriş yapar ve karşılığında imzalı bir token alır. Sonraki isteklerde bu token Authorization başlığında taşınır; sunucu imzayı doğrular, oturum bilgisini bellekte tutmak zorunda kalmaz.
GET /api/v1/siparisler?sayfa=1&adet=20 HTTP/1.1
Host: api.ornek.com
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Accept: application/json
Bir JWT üç bölümden oluşur ve orta bölümü şifreli değildir, yalnızca kodlanmıştır — herkes okuyabilir. İmza içeriğin değiştirilmediğini garanti eder, gizliliğini değil. Bu yüzden token'ın içine parola, TC kimlik numarası gibi hassas veri konmaz.
| Konu | Doğru yaklaşım |
|---|---|
| Erişim token'ı süresi | Kısa: 15 dakika – birkaç saat |
| Yenileme (refresh) token'ı | Uzun ömürlü, sunucuda iptal edilebilir |
| Saklama yeri | HttpOnly çerez tercih edilir; localStorage XSS'e açıktır |
| İçerik | Kullanıcı kimliği ve roller — hassas veri yok |
| Taşıma | Yalnızca HTTPS üzerinden |
Süresiz token, çalındığında sınırsız erişim demektir. Kısa ömürlü erişim token'ı + iptal edilebilir yenileme token'ı ikilisi, bu riski yönetilebilir bir pencereye indirir.
Sürümleme ve Belgeleme
Yayına çıkmış bir API'nin sözleşmesini bozmak, ona bağlı tüm istemcileri kırar. Burada ayrım nettir: ekleme kırıcı değildir, çıkarma ve değiştirme kırıcıdır.
| Değişiklik | Kırıcı mı |
|---|---|
| Cevaba yeni alan eklemek | Hayır |
| İsteğe bağlı yeni parametre eklemek | Hayır |
| Alan adını değiştirmek | Evet |
| Alanı kaldırmak | Evet |
| Alanın tipini değiştirmek | Evet |
| Zorunlu yeni parametre eklemek | Evet |
Kırıcı değişiklikler sürüm üzerinden yönetilir; adres tabanlı sürümleme (/api/v1/...) en yaygın ve en okunabilir yöntemdir. Eski sürümü hemen kapatmak yerine bir süre yan yana çalıştırmak ve kaldırılacağını başlıkla duyurmak, istemci ekiplerine geçiş süresi tanır.
Swagger benzeri araçlarla üretilen canlı belgeler, API'yi kullanacak ekibin işini kolaylaştırdığı gibi kendi ekibiniz için de referans oluşturur. Belgelerin koddan üretilmesi ayrıca şu faydayı sağlar: belge, gerçekte çalışan koddan sapamaz.
Yayına Almadan Önce Kontrol Listesi
| Konu | Neden gerekli |
|---|---|
| Tüm liste uçlarında sayfalama | Veri büyüdükçe cevap ve bellek şişer |
| İstek hız sınırı (rate limit) | Tek istemci tüm kapasiteyi tüketebilir |
| Girdi doğrulama, her uçta | İstemciye güvenilmez |
| CORS yalnızca bilinen kaynaklara | Tarayıcıdan kötüye kullanımı engeller |
| Hata gövdesinde iç detay yok | Yığın izi saldırgana harita verir |
| Zaman alanları UTC ve ISO 8601 | Saat dilimi hataları en sinsi hatalardır |
| İstek kimliği (correlation id) | Sorun çıktığında logda izlenebilsin |
Bu listenin çoğu maddesi sonradan eklenmesi zor olan şeylerdir. Özellikle sayfalama ve sürümleme, ilk günden düşünülmediğinde geri dönüşü pahalı olan iki karardır.
Daha fazlası: REST API'yi temelden anlattığımız bölüm 'Her Yazılımcının Bilmesi Gerekenler' serimizde; BapatiVault serisinde ise .NET 8 ile sıfırdan bir API inşa ediyoruz.
Videoyu sitemizde izle · YouTube'da aç · Kanala abone ol
Daha fazlası: REST API kavramlarını uygulamalı gösterdiğimiz videoyla konuyu pekiştirebilirsiniz.
Videoyu sitemizde izle · YouTube'da aç · Bapati kanalına abone ol

