Bir API, yalnızca veri alıp veren teknik bir katman değildir. API, uygulamalar arasında yapılmış açık bir sözleşmedir. Bu sözleşme net değilse, tutarsızsa, belgelenmemişse ya da gereğinden fazla iç detay sızdırıyorsa, ona bağlanan her uygulama bu karmaşayı taşımaya başlar. Mobil uygulama, web arayüzü, yönetim paneli, üçüncü taraf entegrasyonları… Hepsi aynı belirsizlikle uğraşır.
Ben API’leri bu yüzden “çalışıyor mu?” seviyesinde ele almam. Temiz, öngörülebilir ve uzun vadede bakımı kolay REST/JSON sözleşmeleri tasarlarım. Kaynak adları tutarlı olur. Yanıt formatları değişkenlik göstermez. HTTP durum kodları doğru anlamda kullanılır. Her sınırda doğrulama yapılır. Hata mesajları istemcinin anlayacağı şekilde döner; ama sistemin içini dışarıya açmaz.
Bu sayfa, mobil uygulama hizmetimin backend tarafına daha yakından bakan bölümüdür. Çünkü iyi bir mobil uygulama, çoğu zaman iyi tasarlanmış bir API’ye dayanır. Ekran ne kadar iyi olursa olsun, arkasındaki sözleşme zayıfsa kullanıcı deneyimi de zayıflar.
Benim buradaki avantajım şu: API’leri yalnızca yazmıyorum, o API’leri tüketen uygulamaları da geliştiriyorum. Yani masanın iki tarafını da görüyorum. Backend tarafında mantıklı görünen bir endpoint’in mobil tarafta ne kadar uğraştırıcı olabileceğini biliyorum. Gereksiz karmaşık bir response’un istemci kodunu nasıl şişirdiğini, eksik bir hata kodunun kullanıcıya nasıl yanlış mesaj gösterdiğini, sayfalama olmayan bir listenin uygulamayı nasıl yavaşlattığını pratikte görüyorum. Bu yüzden API sözleşmesini yalnızca teknik olarak değil, kullanacak uygulamanın gerçek ihtiyacına göre tasarlarım.
Temiz ve öngörülebilir sözleşme tasarımı
İyi bir API’de geliştirici her endpoint için yeniden düşünmek zorunda kalmaz. Genel yapı bir kez anlaşıldığında, diğer uçlar da tahmin edilebilir olur. Bu hem geliştirme hızını artırır hem de hata ihtimalini azaltır.
-
Tutarlı yapı — Kaynak adları aynı mantıkla seçilir. Örneğin kullanıcılar, siparişler, dosyalar veya bildirimler gibi kaynaklar açık ve sade isimlendirilir. Gereksiz fiillerden, belirsiz kısaltmalardan ve her endpoint’te değişen kalıplardan kaçınılır. İç içe kaynaklar da mantıklı yerde kullanılır; her şeyi tek seviyeye yığmak da, her şeyi gereğinden fazla iç içe geçirmek de okunabilirliği bozar.
-
Tutarlı yanıt biçimi — Başarılı yanıtlar, liste yanıtları, detay yanıtları ve hata yanıtları aynı genel düzene sahip olur. İstemci tarafı “bu endpoint başka türlü dönüyor” diye özel durum yazmak zorunda kalmaz. Özellikle mobil uygulamalarda bu fark önemlidir. Çünkü her tutarsızlık, ekranlarda fazladan kontrol ve fazladan hata riski demektir.
-
Doğru HTTP durum kodları — 200, 201, 400, 401, 403, 404, 409, 422 gibi kodlar gerçek anlamlarıyla kullanılır. Yetkisiz kullanıcıya 401, erişim hakkı olmayan kullanıcıya 403, bulunamayan kaynağa 404, doğrulama hatasına 422 dönmek gibi ayrımlar önemlidir. Böylece istemci hatayı tahmin etmeye çalışmaz. Ne olduğunu bilir ve kullanıcıya doğru davranışı gösterir.
-
Tutarlı hata biçimi — Her hata aynı yapıyla döner. Genellikle bir hata kodu, okunabilir mesaj ve gerekirse alan bazlı detaylar bulunur. Böylece istemci tek bir hata işleme mantığı kurabilir. Örneğin form doğrulama hatası geldiğinde hangi alanın neden reddedildiği anlaşılır. Ama sistemin iç hata izleri, veritabanı mesajları veya stack trace gibi bilgiler dışarı sızmaz.
Temiz sözleşme, yalnızca bugünkü işi kolaylaştırmaz. Yarın yeni bir ekran, yeni bir panel veya başka bir entegrasyon geldiğinde de sağlam zemin sağlar.
Auth, yetkilendirme ve doğrulama
API güvenliği yalnızca giriş ekranından ibaret değildir. “Kullanıcı giriş yaptı mı?” sorusu önemlidir; ama tek başına yeterli değildir. Asıl güvenli yapı, kimlik doğrulama, yetkilendirme ve girdi doğrulamanın birlikte ele alınmasıyla oluşur.
-
Kimlik doğrulama (auth) — API token tabanlı ya da oturum tabanlı çalışabilir. Seçim projenin yapısına göre yapılır. Mobil uygulamalarda token yenileme, oturum süresi, güvenli saklama ve çıkış akışı baştan düşünülmelidir. Token süresi sonsuz olmamalı, yenilenebilir ve iptal edilebilir olmalıdır.
-
Yetkilendirme (authorization) — Bir kullanıcının giriş yapmış olması, her veriye erişebileceği anlamına gelmez. Rol kontrolü, sahiplik kontrolü ve kaynak bazlı izinler her korumalı uçta uygulanır. Örneğin bir kullanıcı yalnızca kendi siparişlerini görmelidir. Yönetici paneline ait uçlara normal kullanıcı erişememelidir. Bu kontroller yalnızca arayüzde gizleme ile bırakılmaz; API tarafında kesin olarak uygulanır.
-
Girdi doğrulama — Dışarıdan gelen her veri güvenilmez kabul edilir. Body, query string, path parametresi ve header gibi tüm giriş noktaları kontrol edilir. Veri beklenen şemaya uymuyorsa en başta reddedilir. Bu yaklaşım hem güvenlik için önemlidir hem de veri bütünlüğünü korur. Yanlış tipte veri, eksik alan, beklenmeyen format veya izin verilmeyen değerler sisteme girmeden yakalanır.
Doğrulama yalnızca “boş geçilemez” kontrolü değildir. Alan uzunlukları, sayı aralıkları, tarih formatları, enum değerleri, dosya türleri ve iş kuralları da buna dahildir. Bu sayede API, istemcinin yaptığı hatayı tolere etmeye çalışan kırılgan bir yapı yerine, sınırları net bir sistem olur.
Üretimde hayatta kalma detayları
Bir API geliştirme ortamında sorunsuz çalışabilir. Ama gerçek fark, üretimde ortaya çıkar. Kullanıcı trafiği, hatalı istemci davranışları, bot denemeleri, tekrar eden istekler, ağ kopmaları ve üçüncü taraf servislerin gecikmeleri üretim ortamının doğal parçalarıdır. Bu yüzden API tasarımında bu durumlar baştan hesaba katılmalıdır.
-
Rate limiting — Herkese açık veya yarı açık uçlarda kötüye kullanım riski vardır. Aynı istemciden çok kısa sürede gelen yoğun istekler sistemi yorabilir. Rate limiting ile belli sınırlar konur. Bu hem sistemi korur hem de tek bir kötü niyetli veya hatalı istemcinin diğer kullanıcıları etkilemesini engeller.
-
Idempotency — Özellikle ödeme, sipariş, rezervasyon ve webhook akışlarında önemlidir. Ağ hatası nedeniyle aynı istek tekrar gönderilebilir. Üçüncü taraf servis aynı webhook’u birden fazla kez iletebilir. Bu durumda aynı işlemin iki kez yazılması, çift ödeme veya çift kayıt gibi ciddi sorunlara yol açabilir. Benzersiz kısıtlar ve idempotency anahtarı ile aynı isteğin tekrarında sistem güvenli davranır.
-
Sayfalama — Büyük listelerde tüm veriyi tek seferde dönmek doğru değildir. Hem yanıt süresi uzar hem ağ kullanımı artar hem de istemci tarafı gereksiz yük taşır. Sayfalama ile veriler parça parça alınır. Liste ekranları daha hızlı açılır, API daha dengeli çalışır. Ayrıca sıralama ve filtreleme ihtiyaçları da bu yapıyla daha sağlıklı ele alınır.
-
Versiyonlama — API sözleşmesi değiştiğinde eski istemcileri kırmamak gerekir. Özellikle mobil uygulamalarda herkes aynı anda en yeni sürüme geçmez. Bu yüzden kırıcı değişiklikler planlı yapılır. Gerekirse versiyonlama kullanılır. Yeni alan eklemek, eski alanı kaldırmak veya response yapısını değiştirmek gibi kararlar istemciler düşünülerek alınır.
Bu detaylar çoğu zaman ilk gün görünmez. Ama sistem büyüdükçe, kullanıcı sayısı arttıkça ve yeni entegrasyonlar geldikçe değerleri netleşir.
Veritabanı ve performans
API, altındaki veri modeli kadar sağlıklıdır. Endpoint’ler ne kadar düzenli görünürse görünsün, veritabanı şeması zayıfsa sistem bir noktada yavaşlar veya karmaşıklaşır. Bu yüzden API tasarımı ile veri modeli tasarımını birlikte ele alırım.
Genelde PostgreSQL gibi güvenilir ilişkisel veritabanları tercih ederim. Tablo ilişkileri, zorunlu alanlar, benzersiz kısıtlar ve foreign key yapıları iş kurallarına göre tasarlanır. Uygulama kodunda kontrol etmek iyi olabilir; ama kritik kuralların veritabanı seviyesinde de korunması gerekir. Örneğin aynı kaydın iki kez oluşmaması yalnızca kod akışına bırakılmamalıdır.
Sık sorgulanan sütunlarda doğru index kullanımı performans için önemlidir. Fakat her alana index eklemek de çözüm değildir. Index, sorgu desenine göre seçilmelidir. Listeleme, arama, filtreleme ve sıralama davranışları baştan düşünülürse API daha tutarlı hızda çalışır.
Gerektiğinde önbellek kullanılır. Ancak cache, rastgele eklenen bir hızlandırma katmanı olmamalıdır. TTL süresi, neyin ne zaman geçersiz sayılacağı ve hangi verinin cache’e uygun olduğu dikkatle belirlenmelidir. Sık değişmeyen ama sık okunan veriler cache için daha uygundur. Sürekli değişen kritik verilerde ise dikkatli olmak gerekir.
Matematik altyapım burada doğrudan işe yarar. Veri modeli, sorgu karmaşıklığı, indeksleme mantığı ve performans analizi yalnızca araç kullanımı değildir. Doğru soyutlama kurmak, gereksiz ilişkileri ayıklamak ve sorgunun nerede pahalı hale geldiğini görmek önemlidir.
Güvenlik ve gizlilik
Güvenlik, sonradan eklenen bir kontrol listesi değildir. API’nin tasarım kararlarına baştan dahil edilmelidir. Özellikle kişisel veri, ödeme akışı, kullanıcı hesabı, dosya yükleme veya yönetim paneli olan sistemlerde bu yaklaşım daha da önem kazanır.
Hassas veriler loglanmaz. Token, parola, API key, kişisel bilgiler veya özel içerikler log dosyalarında açık şekilde bulunmamalıdır. Loglar hata ayıklama için gereklidir; ama yanlış tasarlanırsa veri sızıntısı kaynağına dönüşebilir.
İstemciye stack trace veya iç hata detayları gönderilmez. Kullanıcıya genel ve anlaşılır bir mesaj döner. Sistem içindeki gerçek hata ise güvenli şekilde loglanır. Böylece hem kullanıcı deneyimi bozulmaz hem de saldırganlara sistemin iç yapısı hakkında ipucu verilmez.
Secret’lar koda gömülmez. API key, parola, servis token’ı ve benzeri bilgiler ortam değişkenlerinde veya secret yöneticilerinde tutulur. Kod deposuna hassas bilgi girmemesi temel bir kuraldır.
Token karşılaştırmaları zamanlama-güvenli yapılır. Küçük gibi görünen bu detay, güvenlik açısından önemlidir. Ayrıca CORS ayarları, dosya yükleme sınırları, input temizliği ve yetki kontrolleri de projenin ihtiyacına göre ele alınır.
Referans dokümantasyon
Dokümantasyon, sadece “var” demek için hazırlanmaz. Gerçek istek-yanıt örnekleriyle hazırlanan bir referans olmalıdır. Bir geliştirici dokümana baktığında endpoint’in ne işe yaradığını, hangi parametreleri aldığını, hangi yanıtları döndüğünü ve hata durumlarında ne beklemesi gerektiğini anlayabilmelidir.
Her endpoint için giriş ve çıkış örnekleri verilir. Başarılı yanıtlar kadar hata örnekleri de önemlidir. Çünkü istemci tarafında çoğu mantık hata durumlarını doğru ele almaya bağlıdır. Form hatası, yetki hatası, bulunamayan kaynak veya çakışan işlem farklı şekillerde yönetilmelidir.
Mümkünse OpenAPI/Swagger gibi makine tarafından okunabilir bir spec hazırlanır. Bu sayede dokümantasyon daha düzenli kalır. İstemci kodu üretmek, testleri netleştirmek ve ekip içinde ortak dil oluşturmak kolaylaşır. Ayrıca API değiştikçe dokümanın kodla senkron kalması daha mümkün olur.
İyi dokümantasyon, projenin gelecekteki bakım maliyetini azaltır. Yeni bir geliştirici geldiğinde sistemi anlaması kolaylaşır. Mobil uygulama, web paneli veya harici entegrasyon geliştiren kişi tahminle değil, açık sözleşmeyle çalışır.
Uygulama ve web tarafını bilen backend yaklaşımı
API genelde bir uygulamanın veya web sitesinin beynidir. Kullanıcı ekranda bir butona basar; ama o butonun arkasında kimlik, yetki, veri doğrulama, kayıt oluşturma, hata yönetimi, bildirim, dosya, ödeme veya üçüncü taraf entegrasyon akışı olabilir. Bu akışın sağlıklı çalışması için API’nin net, güvenli ve sürdürülebilir olması gerekir.
Ben hem API tarafını hem de onu kullanacak mobil ve web tarafını kurabildiğim için sözleşmeyi baştan doğru tasarlayabilirim. Hangi verinin ekranda gerçekten gerektiğini, hangi yanıtın istemciyi rahatlatacağını, hangi hata mesajının kullanıcıya anlamlı döneceğini hesaba katarım. Böylece backend ayrı bir teknik ada gibi durmaz; ürünün gerçek kullanımına hizmet eder.
Yeni bir API’ye ihtiyacın varsa, mevcut sisteme güvenli ve düzenli bir API katmanı eklemek istiyorsan ya da var olan API’nin dağınıklığını toparlamak istiyorsan bana yaz.
Sık sorulan sorular
REST mi GraphQL mi?
Çoğu proje için REST/JSON yeterli, basit ve herkesçe anlaşılır — varsayılanım bu. İstemci çok farklı veri şekilleri çekiyorsa ve aşırı/eksik veri (over/under-fetching) gerçek bir sorunsa GraphQL'i değerlendiririm. Karar moda değil, projenin veri erişim deseni belirler.
API'mi nasıl güvende tutuyorsun?
Katmanlı: her sınırda girdi doğrulama (enjeksiyon ve bozuk veri önlenir), token/oturum tabanlı auth + yetkilendirme, rate limiting (kötüye kullanım ve DoS'a karşı), hassas verinin loglanmaması ve istemciye genel hata mesajı (stack trace asla). Secret'lar koda gömülmez.
Idempotency neden önemli?
Çünkü ağ güvenilmezdir. Bir ödeme isteği zaman aşımına uğrayıp tekrar gönderilirse, idempotency anahtarı olmadan müşteri iki kez öder. Ödeme ve webhook akışlarında benzersiz kısıt + idempotency anahtarıyla bu çift işlemi engellerim — production'da fark eden detay budur.
Mevcut sistemime API katmanı ekler misin?
Evet. Mevcut veritabanı veya servisin üzerine temiz bir API katmanı kurabilirim — eski sistemi (legacy) doğrudan istemciye açmak yerine, kontrollü, doğrulanmış, versiyonlanmış bir arayüz. Bu hem güvenliği hem bakımı iyileştirir.
Dokümantasyon veriyor musun?
Evet — gerçek istek-yanıt örnekleriyle bir referans dokümantasyon. Her endpoint, beklenen girdi/çıktı, durum kodları ve örneklerle. Mümkünse OpenAPI/Swagger gibi makine-okur bir spec — böylece istemci tarafı otomatik üretilebilir ve dokümantasyon kodla senkron kalır.