Yapay zeka ile API yazmak bir öğleden sonra sürebilir: Claude Code ya da Codex gibi bir kodlama ajanından “kullanıcıları olan bir görev REST API’si” iste; route’lar, bir veritabanı ve çalışan bir sunucu gelir. O API’nin ilk gerçek kullanıcılarına dayanıp dayanmayacağı ise ayrı bir soru. Doğrulanmamış girdi, başkalarının verisini dağıtan endpoint’ler ve kimsenin okumadığı migration’lar her zamanki sorunlar. Bu yazıda ajanlarla REST backend’i nasıl kurduğumu stack seçiminden deploy’a kadar anlatıyorum; nerede yavaşlaman gerektiğini de.
Yazı, yapay zeka ile SaaS MVP yazısıyla başlayan serinin parçası. SaaS yazısı ürünü anlatıyor; bu yazı ise altındaki backend’i: bir mobil uygulamanın, bir frontend’in ya da başka servislerin çağıracağı API’yi. Bu çalışma biçimine yeniysen vibe coding nasıl yapılır yazısı iyi bir ısınma olur.
1. Koddan önce API’yi tanımla
API bir sözleşmedir. Bir mobil uygulama ona göre yayınlandıktan sonra bir alanın adını değiştirmek pahalıya patlar. O yüzden ajan kod yazmadan önce şunları yaz:
- Kaynaklar: isimler. Örneğin
users,projects,tasks,comments. - Endpoint’ler:
GET /v1/projects,POST /v1/projects,GET /v1/projects/:id/tasks,PATCH /v1/tasks/:idve benzerleri. - Kim neyi yapabilir: “Projenin üyeleri görevlerini okuyabilir; projeyi yalnızca sahibi silebilir.”
- Hata formatı: tüm hatalar için tek bir şekil; HTTP durum kodu, makinenin okuyabileceği bir kod ve bir mesaj.
- Sayfalama: cursor mı sayfa numarası mı, varsayılan ve en büyük sayfa boyutu.
İlk sürümü gerçek bir istemcinin ihtiyaç duyduğu endpoint’lerle sınırlı tut. Yönetici API’si, webhook’lar ve toplu içe aktarma bekleyebilir.
2. Kuralları bir spec dosyasına yaz
Ajanlar önceki konuşmaları hatırlamaz. Claude Code her oturumun başında CLAUDE.md dosyasını okur; Codex ve birçok başka ajan AGENTS.md dosyasını. Kararlarını oraya yaz:
# Tasks API
## Stack
- Node.js LTS, TypeScript, Fastify
- PostgreSQL, Prisma for schema and migrations
- Zod for request validation; OpenAPI generated from the same schemas
- Vitest; tests use app.inject() against a test database
## Rules
- All routes under /v1. JSON only.
- Every request body, query and param is validated with a schema.
- Errors: { "error": { "code": "...", "message": "..." } }, never a stack trace.
- Every query on tasks and projects checks project membership.
- Never return password hashes or tokens; use explicit response schemas.
- Database changes only through migration files.
- List endpoints: cursor pagination, default 20, max 100.
- Secrets come from environment variables; never in code or logs.
- Ask before adding a dependency.
- After every task: pnpm lint && pnpm test
## Out of scope (for now)
Admin API, file uploads, webhooks, GraphQL.
Dosyayı İngilizce tutuyorum; ajanlar her iki dilde de anlıyor ama kod, commit’ler ve hata mesajları zaten İngilizce. Buradaki her kural, ajanlar o kural olmadan aynı hatayı yaptığı için var. “Explicit response schemas” ajanın parola hash’i dahil tüm kullanıcı satırını döndürmesini engeller. “Max 100” birinin bir milyon satır istemesini engeller. Bu dosyayı yazmak için CLAUDE.md nasıl yazılır yazısına bak.
3. Sıkıcı bir stack seç
Ajan binlerce kez gördüğü bir stack’te daha iyi kod yazar. İki güvenli seçenek:
| TypeScript | Python | |
|---|---|---|
| Framework | Fastify (ya da Express, Hono) | FastAPI |
| Doğrulama | Zod ya da JSON Schema | Pydantic |
| Veritabanı erişimi | Prisma ya da Drizzle | SQLAlchemy |
| Migration | Prisma Migrate, Drizzle Kit | Alembic |
| OpenAPI | @fastify/swagger | Yerleşik |
| Testler | Vitest + app.inject() | pytest + TestClient |
İkisi de iş görür. Okuyabildiğin dili seç, çünkü çok diff okuyacaksın. Örneklerde TypeScript, Fastify, Prisma ve PostgreSQL kullanacağım.
Postgres’i Docker ile yerelde çalıştır ki ajanın hiçbir zaman ortak bir veritabanına ihtiyacı olmasın:
docker run --name tasks-db -e POSTGRES_PASSWORD=dev -p 5432:5432 -d postgres:16
mkdir tasks-api && cd tasks-api && git init
4. Önce plan, sonra her seferinde tek kaynak
İlk prompt’umda kod değil, plan istiyorum:
CLAUDE.md dosyasını oku. Henüz kod yazma.
Şunları öner:
1. Prisma şeması (modeller, ilişkiler, indeksler, unique kısıtları)
2. İstek ve yanıt şekilleriyle birlikte tam endpoint listesi
3. Her endpoint için yetkilendirmenin nasıl çalışacağı
4. Her biri geçen testlerle biten 6–8 uygulama adımı
Sonda açık soruları listele.
Planı düzelt, soruları yanıtla, spec’i güncelle. Sonra adım adım ilerle:
2. adımı uygula: projects kaynağı (list, create, get, update,
delete). Girdiyi Zod ile doğrula, açık yanıt şemaları kullan,
her sorguda üyeliği kontrol et. Mutlu yol, geçersiz girdi ve
üye olmayan ikinci bir kullanıcı için test yaz. Testleri çalıştır,
sonucu göster, sonra dur.
“Sonra dur” orada, bir sonraki adımdan önce diff’i okuyup commit atabileyim diye. Ajan yoldan çıktığında beş kaynağı çözmeye uğraşmak yerine bir commit geri dönüyorum.
5. Şema ve migration’lar
Şema sonradan değiştirmesi en zor kısımdır, o yüzden dikkatle oku:
- Kısıtlar yalnızca kodda değil, veritabanında da.
NOT NULL, benzersiz e-postalar, bilinçli birON DELETEdavranışıyla foreign key’ler. - Çalıştırdığın sorgular için indeksler. Filtrelediğin her foreign key ve bir liste endpoint’inde sıraladığın her sütun.
- Zaman damgaları (
createdAt,updatedAt) her tabloda; hata ayıklamaya ve cursor sayfalamaya yardım eder. - Para tam sayı ya da decimal olarak tutulur, asla kayan noktalı sayı olarak değil.
Her değişiklik bir migration’dan geçer:
npx prisma migrate dev --name add_tasks # yerelde oluştur ve uygula
npx prisma migrate reset # geliştirme veritabanını sıfırdan kur
npx prisma migrate deploy # canlı ortamda bekleyen migration'ları uygula
Gerçek veri oluştuğunda ajanın yazdığı her migration dosyasını oku. DROP COLUMN, DROP TABLE, ad değişiklikleri (Prisma bunları silme ve eklemeye çevirebilir), WHERE olmadan UPDATE ya da DELETE ve büyük tablolara varsayılan değeri olmadan eklenen NOT NULL sütunlarda dur ve sor.
6. Kimlik doğrulama: var olanı kullan
Ajana parola saklama yöntemi ya da token formatı icat ettirme. Barındırılan bir kimlik doğrulama servisi ya da bilinen bir kütüphane kullan; ajanın işi onu projeye bağlamak olsun:
- Parolalar bakımı süren bir kütüphaneyle argon2 ya da bcrypt kullanılarak hash’lenir; asla düz metin olarak saklanmaz ya da loglanmaz.
- Oturumlar ya da token’lar: aynı sitedeki bir tarayıcı istemcisi için
HttpOnly,Secure,SameSitebir oturum çerezi en basit güvenli seçimdir. Mobil ya da üçüncü taraf istemciler için refresh token’lı kısa ömürlü erişim token’ları. - Token’ları düzgün doğrula. İmza, süre, issuer ve audience;
nonealgoritmasını reddet. Ajandan bunun tam olarak nerede yapıldığını göstermesini iste. - Giriş ve parola sıfırlamada hız sınırı koy ki kimse binlerce parola deneyemesin.
7. Yetkilendirme: ajanların en çok yazdığı hata
Kimlik doğrulama “bu kim?” sorusunu yanıtlar. Yetkilendirme ise “bu kayda dokunabilir mi?” sorusunu. Ajanların yazdığı API’ler çoğunlukla ilkini doğru, ikincisini yanlış yapar. Klasik örnek: geçerli bir token olup olmadığını kontrol eden, sonra görevi ID’ye göre yükleyen bir GET /v1/tasks/:id. Giriş yapmış her kullanıcı sayıyı değiştirerek herhangi bir görevi okuyabilir. OWASP bunu, yani nesne düzeyinde bozuk yetkilendirmeyi (BOLA), API Security Top 10 listesinde birinci sıraya koyuyor.
Çözüm bir kütüphane değil, bir alışkanlık:
- Bir kaydı ID’ye göre yükleyen her sorgu, çağıranın erişebildiği şeye göre de filtreler:
where: { id, project: { members: { some: { userId } } } }. - “Bulunamadı” ile “senin değil” aynı
404yanıtını döndürür; böylece ID’ler yoklanamaz. - ID alan her endpoint’i iki kullanıcıyla test et. Bu testler projedeki en değerli testlerdir.
Bununla bağlantılı bir hata da toplu atama (mass assignment): ajan istek gövdesini doğrudan update() fonksiyonuna verir ve bir kullanıcı "role": "admin" ya da "ownerId": "..." gönderir. Yalnızca izin verilen alanları listeleyen doğrulama şemaları bunu durdurur.
Ajana şunu sor: “Her endpoint’i ve yaptığı yetkilendirme kontrolünü listele. Bir kaydı ID’ye göre yükleyip çağırana göre filtrelemeyen her endpoint’i işaretle.”
8. Doğrulama ve hatalar
Sınırı geçen her girdi doğrulanır: gövde, query string, path parametreleri ve kullandığın başlıklar. Zod ve Fastify ile route şemalarını tanımlar; geçersiz istekler senin kodun çalışmadan 400 ile reddedilir.
- Bilinmeyen alanları sessizce yok saymak yerine reddet; istemci hataları erkenden ortaya çıkar.
- Boyutları sınırla: metin uzunlukları, dizi uzunlukları, istek gövdesi boyutu, sayfa boyutu.
- Her şey için tek hata şekli ve ayrıntıları sunucu tarafında loglayıp istemciye yalnızca
codevemessagedöndüren genel bir hata işleyici. Yanıtlardaki stack trace’ler ve SQL hataları saldırgana harita verir. - Yalnızca parametreli sorgular. ORM bunu varsayılan olarak yapar; Prisma’nın
$queryRawUnsafefonksiyonu gibi metin birleştirmeyle kullanılan ham SQL yardımcılarına dikkat et.
9. Önemli olan testler
Fastify’ın app.inject() fonksiyonu port açmadan uygulamaya istek gönderir; bu yüzden API testleri hızlıdır. %100 kapsama gerekmez; şunlar gerekir:
- Her endpoint’in mutlu yolu: durum kodu ve yanıt şekli kontrol edilir.
- Geçersiz girdi senin hata formatınla
400döndürür. - Token yoksa
401; başkasının kaydı404döndürür. - Sayfalama en büyük sınıra uyar.
- Migration’lar temiz bir veritabanında sıfırdan uygulanabilir.
Testler her çalıştırmada sıfırlanan ayrı bir test veritabanında çalışır. Test paketini asla canlı ortam kimlik bilgilerinin yanına yaklaştırma.
Ajanın başarısız bir testi assertion’ı değiştirerek “düzeltmesine” dikkat et. İstemediğin bir test dosyası diff’te görünürse nedenini sor. Yapay zeka kod incelemesi yazısında bunun için bir kontrol listesi var.
10. Aynı şemalardan OpenAPI dokümantasyonu
Elle yazılan dokümantasyon zamanla koddan kopar. Doğrulama şemalarından üret ki dokümantasyon kodun tam olarak neyi kabul ettiğini anlatsın. Fastify’da @fastify/swagger route şemalarından bir OpenAPI belgesi oluşturur, @fastify/swagger-ui onu sunar; FastAPI bunu kutudan çıktığı gibi yapar.
@fastify/swagger ve @fastify/swagger-ui ekle. OpenAPI belgesini
mevcut route şemalarından üret, açıklamalar ve örnekler ekle,
hata formatını ve kimlik doğrulamayı belgele. Arayüzü /docs
adresinde yalnızca NODE_ENV production değilken sun.
OpenAPI dosyası dokümantasyonun ötesinde de işe yarar: frontend ajanları ondan tipli bir istemci üretebilir, başka araçlar da endpoint’lerini ondan keşfedebilir.
11. Deploy
Küçük bir API, Fly.io, Railway ya da Render gibi bir platformda ya da Docker çalışan herhangi bir sunucuda konteyner olarak rahatça çalışır. Kontrol listesi:
- Çok aşamalı build ve root olmayan kullanıcıyla bir Dockerfile. Ajandan iste, sonra oku.
- Migration’lar ayrı bir adım olarak (
prisma migrate deploy) yeni sürüm başlamadan önce çalışsın; her uygulama örneğinin açılışında değil. - Ortam değişkenleri: veritabanı adresi, gizli anahtarlar ve izin verilen CORS kaynakları imajda değil, platformda tanımlanır.
- Platformun kontrol edebileceği bir sağlık endpoint’i (
/health). - CORS gerçek frontend’lerinle sınırlı olsun; kimlik bilgileriyle birlikte asla
*kullanma. - Yalnızca HTTPS, güvenlik başlıkları (örneğin
@fastify/helmetile) ve parola, token ya da kişisel veri içermeyen istek logları. - Yedekler canlı veritabanında açık olsun ve en az bir kez geri yükleme denensin.
- Sentry gibi bir hata takibi;
500hatalarını kullanıcıların söylemesinden önce duyarsın.
Yapay zekanın sık yaptığı hatalar
- Tüm veritabanı satırlarını döndürmek. JSON’da parola hash’leri, iç bayraklar ve başka kullanıcıların e-postaları. Açık yanıt şemaları bunu çözer.
- API uydurmak. Var olmayan ya da birkaç sürüm önce değişmiş kütüphane fonksiyonları. Ajana güncel dokümantasyon ver, hataları olduğu gibi geri yapıştır.
- Sayfalama olmaması. Limitsiz
findMany()tabloda 200.000 satır olana kadar çalışır. - N+1 sorguları. Bir döngünün içinde her öğe için bir sorgu. Ajandan geliştirme ortamında sorguları loglamasını iste ve tekrarlara bak.
- Yutulan hatalar. Yine de
200döndüren bircatch {}. - Kodda gizli anahtarlar. “Şimdilik” diye koda yazılan ve canlıya giden bir JWT anahtarı.
- Kapsam kayması. “Bir de yönetici endpoint’i ekledim.” Geri al ya da kendi branch’ine taşı.
Güvenlik: kısaca ama ciddi
.envdosyasını.gitignoreiçinde tut; bir kez bile commit’lenmiş her anahtarı yenile.- API anahtarlarını sohbete yapıştırma; ajanın yalnızca değişkenin adına ihtiyacı var.
- Ajanı yerel ya da staging veritabanına yönlendir, asla canlı veritabanına değil.
- Ajanın çalıştırdığı komutları oku; özellikle veritabanı komutlarını,
rm, force push vecurl … | shkomutlarını. - Ara sıra
pnpm audit(ya da paket yöneticinin karşılığı) çalıştır ve çıktıyı ajana ver. - Yalnızca girişte değil, tüm açık endpoint’lerde hız sınırı uygula.
Ajanları kendi bilgisayarında güvende tutmak için yapay zeka kodlama ajanı güvenliği yazısına bak.
Ne zaman bir insan geliştirici getirmeli?
Deneyimli bir backend geliştiricisinin birkaç saatlik incelemesi kendini fazlasıyla amorti eder:
- Gerçek kullanıcılar kaydolmadan önce, kimlik doğrulama ve yetkilendirme için
- API kişisel, sağlık ya da ödeme verisi sakladığında
- Bir iş ortağı ya da kurumsal müşteri API’ye entegre olacaksa
- Performans çöktüğünde: yavaş sorgular, eksik indeksler, bağlantı limitleri
- Sen ve ajan aynı hatayı üç kez düzeltemediğinizde
İşlerini kolaylaştır: spec dosyası, OpenAPI belgesi, migrations klasörü ve yeşil bir test çalıştırması.
Bunu AgentVera ile nasıl yapıyorum
Bunların hepsi tek bir terminalde de çalışır. Birden fazla ajanla çalışırken AgentVera şu noktalarda yardımcı oluyor:
- Worktree’lerde paralel çalışma. Çalışma alanında bir ajanı API’de, başka birini frontend’de ya da testlerde çalıştırıyorum; her biri kendi git worktree’sinde, böylece birbirlerinin dosyalarına basmıyorlar. Yöntem git worktree ile paralel geliştirme yazısında.
- Endpoint’leri başka bir araç açmadan denemek. API istemcisi projenin endpoint’lerini OpenAPI dosyalarından ve Express, Fastify, Hono, Next.js, FastAPI, Django, NestJS ve diğerlerindeki route’lardan buluyor. Parametreler, başlıklar ve gövdeyle bir istek gönderiyorum; yanıt hata dönerse isteği ve yanıtı tek tıkla bir ajana veriyorum.
- Veritabanına ne yazıldığını görmek. Veritabanı yöneticisi yerel Postgres’i açıyor, ajanın oluşturduğu satırlara bakabiliyorum. DB Guard ise ajan turunu bitirdiğinde her migration’ın riskini değerlendiriyor ve onu bir gölge veritabanında deneyebiliyor.
- Konteynerler. Docker sayfası Postgres konteynerini ve loglarını ajanların yanında gösteriyor.
- Turları incelemek. Kod incelemesi merge etmeden önce biten her turu kontrol ediyor.
Bunlar döngüyü hızlandırıyor; API’yi güvenli yapan şey yine spec, testler ve senin kendi incelemen.
Sonuç
Yapay zeka ile API yazmak için önce sözleşmeye karar ver, kuralları CLAUDE.md ya da AGENTS.md dosyasına yaz, yaygın bir stack seç ve ajana her seferinde tek bir kaynağı testleriyle birlikte yaptır. Her girdiyi doğrula, veritabanını yalnızca migration’larla değiştir, her kayıtta sahipliği kontrol et, OpenAPI’yi aynı şemalardan üret ve migration’ları deploy’da ayrı bir adım olarak çalıştır. Gerçek kullanıcılar gelmeden önce bir insana incelet. Backend, frontend ve test ajanlarını yan yana çalıştırmak istersen AgentVera’yı ücretsiz indir.