İlk kez SaaS kurucuları için pratik bir kamu API tasarımı: sürümlendirme, sayfalandırma, oran limitleri, dokümantasyon ve hızlıca teslim edebileceğiniz küçük bir SDK seçin.

Kamuya açık bir API, sadece uygulamanızın açtığı bir uç nokta değildir. Bu, ekip dışındaki insanlara verilen bir sözdür: sözleşme, ürün değişse bile çalışmaya devam edecek.
Zor olan kısım v1’i yazmak değil. Hataları düzeltirken, özellik eklerken ve müşterilerin gerçekte neye ihtiyaç duyduğunu öğrenirken onu kararlı tutmaktır.
Erken alınan kararlar daha sonra destek biletleri olarak geri döner. Yanıtlar şekil değiştirip önceden haber verilmezse, isimlendirme tutarsızsa veya istemciler isteğin başarılı olup olmadığını anlayamazsa sürtüşme oluşur. Bu sürtüşme güvensizliğe dönüşür ve geliştiriciler sizin üzerine inşa etmeyi bırakır.
Hız da önemlidir. Çoğu ilk kez SaaS kurucusu önce işe yarar bir şeyi hızlıca yayınlayıp sonra iyileştirmek ister. Ödün basittir: kurallar olmadan ne kadar hızlı yayınlarsanız, gerçek kullanıcılar geldiğinde o kararları geri almak için o kadar çok zaman harcarsınız.
v1 için yeterince iyi genellikle gerçek kullanıcı eylemlerine karşılık gelen küçük bir uç nokta seti, tutarlı isimlendirme ve yanıt biçimleri, net bir değişiklik stratejisi (sadece v1 bile olabilir), öngörülebilir sayfalandırma ve makul oran limitleri ile tam olarak ne gönderileceğini ve ne alınacağını gösteren doküman demektir.
Somut bir örnek: bir müşteri geceleyin fatura oluşturan bir entegrasyon kurduğunu düşünün. Sonradan bir alanın adını değiştirirseniz, tarih formatını değiştirirseniz veya kısmi sonuçlar döndürmeye başlarsanız onların iş akışı sabah 2’de çöker. Hatalar için sizi değil kendi kodlarını suçlarlar.
Koder.ai gibi sohbet tabanlı bir araçla geliştirirken birçok uç nokta üretmek cazip olabilir. Bu sorun değil, ama herkese açık yüzeyi küçük tutun. Öğrenirken dahili uç noktaları özel tutup hangilerinin uzun vadeli sözleşmenin parçası olması gerektiğini belirleyebilirsiniz.
İyi bir kamu API tasarımı, müşterilerin ürününüz hakkında konuştukları şekilde eşleşen küçük bir isim (kaynak) seti seçmekle başlar. İç veritabanınız değişse bile kaynak isimlerini sabit tutun. Özellik eklerken, temel kaynakların adını değiştirmek yerine alan eklemeyi veya yeni uç nokta açmayı tercih edin.
Birçok SaaS ürünü için pratik bir başlangıç seti: users, organizations, projects ve events. Bir kaynağı bir cümlede açıklayamıyorsanız, muhtemelen onu halka açmaya hazır değildir.
HTTP kullanımını sıkıcı ve öngörülebilir tutun:
GET veriyi okur (yan etki yok)POST bir şey oluşturur (veya bir eylemi başlatır)PATCH bazı alanları güncellerDELETE bir şeyi kaldırır veya devre dışı bırakırAuth ilk günden süslü olmak zorunda değil. API’niz ağırlıklı olarak sunucu–sunucu ise (müşteriler backendlerinden çağırıyorsa), API anahtarları genellikle yeterlidir. Müşteriler bireysel son kullanıcı gibi davranacaksa veya üçüncü taraf entegrasyonlarında kullanıcılar izin verecekse OAuth genellikle daha uygun olur. Kararı sade dille yazın: çağıran kim ve hangi veriye dokunma hakkı var?
Beklentileri erken belirleyin. Neyin desteklendiği ile neyin iyi niyetli olarak ele alındığını açıkça ayırın. Örneğin: listeleme uç noktaları stabil ve geriye dönük uyumludur, ancak arama filtreleri genişleyebilir ve kapsamlı olmak zorunda değildir. Bu, destek biletlerini azaltır ve iyileştirme özgürlüğü verir.
Koder.ai gibi bir platform üzerinde inşa ediyorsanız, API’yi bir ürün sözleşmesi gibi ele alın: önce sözleşmeyi küçük tutun, sonra gerçek kullanım temelinde büyütün, tahminlerle değil.
Sürümleme büyük ölçüde beklentilerle ilgilidir. İstemciler merak eder: entegrasyonum gelecek hafta bozulur mu? Siz de iyileştirmek için alan istiyorsunuz.
Header tabanlı sürümlendirme temiz görünebilir, ama loglarda, cache’lerde ve destek ekran görüntülerinde kolayca kaybolabilir. URL sürümlendirme genellikle en basit seçenektir: /v1/.... Müşteri başarısız bir istek gönderdiğinde sürümü hemen görebilirsiniz. Ayrıca v1 ve v2’yi yan yana çalıştırmak kolaydır.
Bir değişiklik, düzgün davranan bir istemci kodunu değiştirmeden çalışmayı durduracaksa kırıcıdır. Yaygın örnekler:
customer_id → customerId)Güvenli bir değişiklik, eski istemcilerin görmezden gelebileceği bir değişikliktir. Yeni isteğe bağlı bir alan eklemek genellikle güvenlidir. Örneğin, GET /v1/subscriptions yanıtına plan_name eklemek, sadece status okuyan istemcileri bozmaz.
Pratik bir kural: aynı ana sürüm içinde alanları kaldırmayın veya amaçlarını değiştirmeyin. Yeni alanlar ekleyin, eski olanları tutun ve tüm sürümü kullanıdan kaldırmaya hazır olduğunuzda emekli edin.
Basit tutun: emeklileştirmeleri erken duyurun, yanıtlarda net bir uyarı döndürün ve bir bitiş tarihi belirleyin. İlk API için 90 günlük pencere sıklıkla gerçekçidir. Bu süre boyunca v1 çalışır durumda kalsın, kısa bir geçiş notu yayınlayın ve desteğin tek cümleyle yanıt verebildiğinden emin olun: v1 bu tarihe kadar çalışır; v2’de ne değişti.
Koder.ai gibi bir platformda inşa ediyorsanız, API sürümlerini snapshot gibi düşünün: iyileştirmeleri yeni bir sürümde yayınlayın, eskisini stabil tutun ve müşterilere taşınmaları için zaman verdikten sonra kapatın.
Sayfalandırma, güvenin kazanıldığı veya kaybedildiği yerdir. Sonuçlar istekler arasında sıçrıyorsa, insanlar API’nıza güvenmeyi bırakır.
Veri seti küçük, sorgu basit ve kullanıcıların sıkça 3. sayfaya geçmesi bekleniyorsa page/limit kullanın. Listeler büyüyorsa, yeni öğeler sık geliyorsa veya kullanıcı çok filtre/sıralama yapıyorsa cursor tabanlı sayfalandırma kullanın. Cursor tabanlı sayfalandırma, yeni kayıtlar eklendiğinde bile diziyi kararlı tutar.
Bir kaç kural sayfalandırmayı güvenilir kılar:
Toplam sayılar zor olabilir. total_count, filtrelerle büyük tablolarda pahalı olabilir. Ucuzca sağlayabiliyorsanız ekleyin. Sağlayamıyorsanız ya atlayın ya da bir sorgu bayrağı ile isteğe bağlı yapın.
Basit istek/yanıt şekilleri şu şekilde.
// Page/limit
GET /v1/invoices?page=2\u0026limit=25\u0026sort=created_at_desc
{
"items": [{"id":"inv_1"},{"id":"inv_2"}],
"page": 2,
"limit": 25,
"total_count": 142
}
// Cursor-based
GET /v1/invoices?limit=25\u0026cursor=eyJjcmVhdGVkX2F0IjoiMjAyNi0wMS0wOVQxMDozMDowMFoiLCJpZCI6Imludl8xMDAifQ==
{
"items": [{"id":"inv_101"},{"id":"inv_102"}],
"next_cursor": "eyJjcmVhdGVkX2F0IjoiMjAyNi0wMS0wOVQxMDoyNTowMFoiLCJpZCI6Imludl8xMjUifQ=="
}
Oran limitleri sert olmakla ilgili değil, çevrimiçi kalmakla ilgilidir. Trafik dalgalanmalarından, sık yapılan pahalı sorgulardan ve beklenmeyen altyapı faturalarından korur. Bir limit aynı zamanda bir sözleşmedir: istemciler normal kullanımın ne olduğunu bilir.
Basit başlayın ve sonra ayarlayın. Tipik kullanım için alan tanıyan ve kısa patlamalara izin veren bir şey seçin, sonra gerçek trafiği izleyin. Veri yoksa güvenli bir varsayılan, API anahtarı başına dakika başına 60 istek ve küçük bir burst izni vermektir. Bir uç nokta çok daha ağırsa (örneğin search veya exports), onu daha katı bir limite veya ayrı bir maliyet kuralına tabi tutun; her isteği cezalandırmayın.
Limit uyguladığınızda istemcilerin doğru şeyi yapmasını kolaylaştırın. 429 Too Many Requests döndürün ve birkaç standart başlık ekleyin:
X-RateLimit-Limit: pencere içindeki maksimum izinX-RateLimit-Remaining: kalan istek sayısıX-RateLimit-Reset: pencerenin ne zaman sıfırlanacağı (zaman damgası veya saniye)Retry-After: yeniden denemeden önce ne kadar beklenmesi gerektiğiİstemciler 429’u normal bir durum olarak görmelidir, savaşılacak bir hata olarak değil. Nazik bir yeniden deneme deseni iki tarafı da memnun eder:
Retry-After varsa ona göre bekleyinÖrnek: bir müşteri geceleyin yoğun bir senkron çalıştırıp API’nızı zorladığında, işleri tamamen başarısız olmak yerine 429’larla karşılaşıp 20 saniye duraklayabilir; sonra aynı cursor ile devam edip her şeyi tekrar indirmeden veya çift fatura oluşturmadan işi sürdürür.
API hata mesajlarınız okunması zor ise destek biletleri hızla artar. Tek bir hata biçimi seçin ve 500’ler dahil her yerde ona sadık kalın. Basit bir standart: code, message, details ve kullanıcıların destek sohbetine yapıştırabileceği bir request_id.
Küçük, öngörülebilir bir format:
{
"error": {
"code": "validation_error",
"message": "Some fields are invalid.",
"details": {
"fields": [
{"name": "email", "issue": "must be a valid email"},
{"name": "plan", "issue": "must be one of: free, pro, business"}
]
},
"request_id": "req_01HT..."
}
}
HTTP durum kodlarını her zaman aynı şekilde kullanın: kötü giriş için 400, yetkilendirme eksik/hatlı ise 401, doğrulanmış ama erişimi yoksa 403, kaynak bulunamadıysa 404, çakışmalar için 409 (örneğin benzersiz değerin tekrar denenmesi veya yanlış durum), oran limitleri için 429 ve sunucu hataları için 500. Tutarlılık zekalı davranıştan iyidir.
Doğrulama hatalarını düzeltmeyi kolaylaştırın. Alan düzeyindeki ipuçları dokümanlarda kullandığınız parametre adını göstermeli, dahili veritabanı sütunu değil. Bir format gereksinimi varsa (tarih, para birimi, enum), kabul ettiğiniz biçimi söyleyin ve bir örnek gösterin.
Yeniden denemeler birçok API’nin kazara çift veri yaratmasına yol açar. Önemli POST eylemleri (ödeme, fatura oluşturma, e-posta gönderme) için idempotency anahtarlarını destekleyin:
POST uç noktalarında Idempotency-Key header’ını kabul edin.O bir header, ağ sorunları veya istemci zaman aşımı durumlarında birçok acı olayı önler.
Basit bir SaaS çalıştırdığınızı varsayın: üç ana obje var — projects, users ve invoices. Bir proje birçok kullanıcıya sahip ve her proje aylık faturalar alıyor. Müşteriler faturaları muhasebe araçlarına senkronize etmek ve kendi uygulamalarında temel faturalamayı göstermek istiyor.
Temiz bir v1 şöyle olabilir:
GET /v1/projects/{project_id}
GET /v1/projects/{project_id}/invoices
POST /v1/projects/{project_id}/invoices
Şimdi kırıcı bir değişiklik olsun. v1’de fatura tutarlarını sent olarak tamsayı saklıyorsunuz: amount_cents: 1299. Daha sonra çoklu para birimi ve ondalık ihtiyacı doğarsa amount: "12.99" ve currency: "USD" istiyorsunuz. Eski alanı üzerine yazarsanız tüm mevcut entegrasyonlar kırılır. Sürümleme paniği önler: v1’i stabil tutun, /v2/... ile yeni alanları gönderin ve istemciler taşınana dek her ikisine de servis verin.
Fatura listeleme için öngörülebilir bir sayfalandırma şekli kullanın. Örneğin:
GET /v1/projects/p_123/invoices?limit=50\u0026cursor=eyJpZCI6Imludl85OTkifQ==
200 OK
{
"data": [ {"id":"inv_1001"}, {"id":"inv_1000"} ],
"next_cursor": "eyJpZCI6Imludl8xMDAwIn0="
}
Bir gün bir müşteri faturaları döngü içinde içe aktarıp rate limite takılır. Rastgele başarısızlıklar yerine şu yanıtı alırlar:
429 Too Many RequestsRetry-After: 20{ "error": { "code": "rate_limited" } }İstemci tarafında, 20 saniye duraklayıp aynı cursor ile yeniden başlayabilir; böylece her şeyi yeniden indirmek veya çift fatura oluşturmak zorunda kalmaz.
v1 lansmanı, bir uç nokta yığını değil küçük bir ürün sürümü gibi ele alındığında daha iyi gider. Amaç basit: insanlar üzerine inşa edebilsin ve siz sürpriz olmadan geliştirebilesiniz.
API’nızın ne için olduğunu ve ne olmadığını açıklayan tek sayfalık bir şey yazarak başlayın. Yüzeyi bir dakikada sözlü olarak açıklayabileceğiniz kadar küçük tutun.
Bu sırayı izleyin ve her adım yeterince iyi olana kadar ilerlemeyin:
Kod üreten bir iş akışı ile (örneğin Koder.ai kullanarak uç noktalar ve yanıtlar üretiyorsanız) yine de sahte-istemci testini yapın. Üretilen kod doğru görünürken kullanımı garip olabilir.
Getirisi: daha az destek e-postası, daha az acil düzeltme yayımlama ve gerçekten sürdürülebilir bir v1.
İlk SDK ikinci bir ürün değildir. Bunu HTTP API’nızın ince, dostça bir sarmalayıcısı olarak düşünün. Sık kullanılan çağrıları kolaylaştırmalı, ama API’nin nasıl çalıştığını gizlememeli. Eğer sarmalanmamış bir özellik gerekiyorsa, kullanıcılar ham isteklere kolayca dönebilmeliler.
Başlamak için bir dil seçin; müşterilerinizin gerçekte kullandığına göre karar verin. Birçok B2B SaaS için genellikle JavaScript/TypeScript veya Python başlamak için iyi seçeneklerdir. Bir tam bitmiş üç SDK yerine bir sağlam SDK yayınlamak daha iyidir.
İyi bir başlangıç seti:
Bunu el ile yazabilir veya bir OpenAPI spesifikasyonundan üretebilirsiniz. Üretim, spesifikasyon doğruysa ve tutarlı tipleme istiyorsanız harikadır ama genellikle çok fazla kod üretir. Erken aşamada elle yazılmış minimal bir istemci ve dokümanlar için bir OpenAPI dosyası genellikle yeterlidir. Kamu SDK arayüzü stabil kaldığı sürece daha sonra üretilmiş istemcilere geçiş yapabilirsiniz.
API sürümünüz uyumluluk kurallarını takip etmeli. SDK sürümünüz paketleme kurallarını takip etmeli.
Yeni isteğe bağlı parametreler veya yeni uç noktalar eklerseniz, genellikle küçük bir SDK güncellemesi yeterlidir. SDK’nın kendi içinde kırıcı değişiklikler (yeniden adlandırılmış metotlar, değişen varsayılanlar) için major sürüm ayırın, API aynı kalsa bile. Bu ayrım yükseltmeleri sakin tutar ve destek biletlerini azaltır.
Çoğu API destek bileti hata değil, sürprizlerle ilgilidir. Kamu API tasarımı büyük ölçüde sıkıcı ve öngörülebilir olmaktır ki istemci kodu aylarca çalışmaya devam etsin.
Güveni kaybetmenin en hızlı yolu yanıtları kimseye haber vermeden değiştirmektir. Bir alanın adını değiştirirseniz, tipini değiştirirseniz veya eskiden değer döndürdüğünüz yerde null dönmeye başlarsanız, istemciler için teşhis edilmesi zor kırılmalar olur. Gerçekten davranışı değiştirmeniz gerekiyorsa sürümleme yapın veya yeni bir alan ekleyin ve eskiyi açık bir sunset planıyla bir süre tutun.
Sayfalandırma bir diğer tekrar eden suçludur. Bir uç nokta page/pageSize, bir diğeri offset/limit ve üçüncüsü cursor kullanırsa, hepsinin farklı varsayılanları varsa sorun çıkar. v1 için bir desen seçin ve her yerde ona sadık kalın. Sıralamayı da sabit tutun ki yeni kayıtlar eklendiğinde sonraki sayfa atlamasın veya tekrar etmesin.
Hatalar tutarsız olduğunda çok fazla gidip gelme olur. Yaygın bir hata modu, bir servisin { "error":"..." } döndürmesi ve diğerinin { "message":"..." } döndürmesi ve aynı sorun için farklı HTTP durum kodları kullanmasıdır. İstemciler, karmaşık, uç nokta-spesifik işleyiciler geliştirir.
Uzun e-posta zincirleri üreten beş hata:
Basit bir alışkanlık faydalıdır: her yanıtta bir request_id olsun ve her 429 ne zaman yeniden deneneceğini açıklasın.
Her şeyi yayınlamadan önce tutarlılığa odaklanan son bir geçiş yapın. Çoğu destek bileti küçük ayrıntıların uç noktalar, dokümanlar ve örnekler arasında uyuşmamasından doğar.
En çok problemi yakalayan hızlı kontroller:
Lansmandan sonra insanların gerçekte nereye istek attığını izleyin, umut ettiğiniz değil. Erken aşamada küçük bir gösterge panosu ve haftalık gözden geçirme yeterlidir.
İlk izleyeceğiniz sinyaller:
Geri bildirimi toplarken her şeyi yeniden yazmayın. Dokümanlarda kısa bir hata rapor yolu ekleyin ve her raporu uç nokta, request id ve istemci sürümü ile etiketleyin. Bir şeyi düzelttiğinizde, değişiklikleri ekleyici yapmayı tercih edin: yeni alanlar, isteğe bağlı parametreler veya yeni uç noktalar; mevcut davranışı bozmayın.
Sonraki adımlar: kaynaklarınızı, sürümleme planınızı, sayfalandırma kurallarınızı ve hata formatınızı içeren tek sayfalık bir API spesifikasyonu yazın. Sonra dokümanlar ve kimlik doğrulama artı 2–3 çekirdek uç noktayı kapsayan küçük bir başlangıç SDK’sı üretin. Daha hızlı gitmek isterseniz, Koder.ai gibi sohbet tabanlı planlama araçlarıyla spesifikasyon, doküman ve starter SDK taslağını çıkartabilirsiniz (planlama modu, uç noktaları ve örnekleri kod üretmeden önce haritalamak için kullanışlıdır).
Start with 5–10 endpoints that map to real customer actions.
A good rule: if you can’t explain a resource in one sentence (what it is, who owns it, how it’s used), keep it private until you learn more from usage.
Pick a small set of stable nouns (resources) customers already use in conversation, and keep those names stable even if your database changes.
Common starters for SaaS are users, organizations, projects, and events—then add more only when there’s clear demand.
Use the standard meanings and be consistent:
GET = read (no side effects)POST = create or start an actionPATCH = partial updateDELETE = remove or disableThe main win is predictability: clients shouldn’t guess what a method does.
Default to URL versioning like /v1/....
It’s easier to see in logs and screenshots, easier to debug with customers, and simpler to run v1 and v2 side by side when you need a breaking change.
A change is breaking if a correct client can fail without changing their code. Common examples:
Adding a new optional field is usually safe.
Keep it simple:
A practical default is a 90-day window for a first API, so customers have time to migrate without panic.
Pick one pattern and stick to it across all list endpoints.
Always define a default sort and a tie-breaker (like created_at + ) so results don’t jump around.
Start with a clear per-key limit (for example 60 requests/minute plus a small burst), then adjust based on real traffic.
When limiting, return 429 and include:
X-RateLimit-LimitX-RateLimit-RemainingUse one error format everywhere (including 500s). A practical shape is:
code (stable identifier)message (human-readable)details (field-level issues)request_id (for support)Also keep status codes consistent (400/401/403/404/409/429/500) so clients can handle errors cleanly.
If you generate lots of endpoints quickly (for example with Koder.ai), keep the public surface small and treat it as a long-term contract.
Do this before launch:
POST actionsThen publish a tiny SDK that helps with auth, timeouts, retries for safe requests, and pagination—without hiding how the HTTP API works.
idX-RateLimit-ResetRetry-AfterThis makes retries predictable and reduces support tickets.