API Tasarımı En İyi Uygulamaları

API (Uygulama Programlama Arayüzü), bir servis sağlayıcı ile tüketicileri arasındaki bir sözleşmedir. İyi tasarlanmış bir API sezgisel, tutarlı ve kullanımı kolaydır. Kötü tasarlanmış bir API, geliştiricilerin hayal kırıklığına uğramasına, artan destek yüküne, güvenlik açıklarına ve maliyetli değişikliklere yol açar.
Giriş
API (Uygulama Programlama Arayüzü), bir servis sağlayıcı ile tüketicileri arasındaki bir sözleşmedir. İyi tasarlanmış bir API sezgisel, tutarlı ve kullanımı kolaydır. Kötü tasarlanmış bir API, geliştiricilerin hayal kırıklığına uğramasına, artan destek yüküne, güvenlik açıklarına ve maliyetli değişikliklere yol açar.
API'ler ürünlerdir; bunları kullanıcı arayüzleriyle aynı özenle tasarlayın. İster REST, GraphQL ister gRPC oluşturuyor olun, iyi API tasarımının ilkeleri tutarlı kalır.
RESTful API Tasarım İlkeleri
1. Kaynaklar İçin İsimleri Kullanın
Kaynaklar sisteminizdeki temel varlıklardır. Bunları fiillerle değil isimlerle adlandırın:
✅ GET /users — List users
✅ GET /users/123 — Get user by ID
✅ POST /users — Create user
✅ PATCH /users/123 — Partially update user
✅ PUT /users/123 — Replace user
✅ DELETE /users/123 — Delete user
❌ GET /getUser — Verb in URL
❌ POST /createUser — Verb in URL
❌ POST /users/create — Verb in URL path
❌ GET /users?action=delete — Action as query parameter
2. Doğru HTTP Yöntemlerini Kullanın
| Yöntem | Amaç | İdempotent | Güvenli | Vücut |
|---|---|---|---|---|
| ALIN | Bir kaynağı alın | Evet | Evet | Hayır |
| GÖNDERİM | Kaynak oluştur | Hayır | Hayır | Evet |
| koy | Tam değiştirme | Evet | Hayır | Evet |
| YAMA | Kısmi güncelleme | Hayır | Hayır | Evet |
| SİL | Kaynağı kaldırma | Evet | Hayır | İsteğe bağlı |
Idempotent: Birden fazla özdeş istek, tek bir istekle aynı sonucu üretir.
Güvenli: Yan etkisi yoktur — önbelleğe alınabilir ve güvenli bir şekilde tekrarlanabilir.
3. Tutarlı Adlandırma Kuralları
naming_rules:
- "Use plural nouns: /users, /orders, /products"
- "Use kebab-case for multi-word: /order-items, /shipping-addresses"
- "Use lowercase throughout"
- "Nest resources logically: /users/123/orders"
- "Avoid deep nesting (max 2-3 levels)"
- "Use query parameters for filtering, sorting, pagination"
Yuvalama örneği:
/users/123/orders — Orders belonging to user 123
/users/123/orders/456 — Specific order
/users/123/orders/456/items — Items in that order (okay)
/users/123/orders/456/items/789/details (too deep!)
4. API'nizi Sürümleyin
Son değişiklikler sürümü artırmalıdır:
URI sürümü oluşturma (en yaygın):
https://api.example.com/v1/users
https://api.example.com/v2/users
Başlık sürümü oluşturma:
Accept: application/vnd.example.v1+json
Aşağıdaki durumlar dışında aynı sürümdeki geriye dönük uyumluluğu asla bozmayın:
- Kritik bir güvenlik açığı var.
- Bir kullanımdan kaldırma politikanız var ve bunu ilettiniz.
- Etkilenen kullanıcılar yalnızca dahili kullanıcılardır.
5. Anlamlı HTTP Durum Kodlarını Kullanın
2xx Success:
200 OK: Generic success (GET, PATCH)
201 Created: Resource created (POST)
204 No Content: Success, no response body (DELETE)
3xx Redirection:
301 Moved Permanently
304 Not Modified (caching)
4xx Client Error:
400 Bad Request: Malformed request, validation error
401 Unauthorized: Missing or invalid authentication
403 Forbidden: Authenticated but not authorized
404 Not Found: Resource does not exist
405 Method Not Allowed: Wrong HTTP method
409 Conflict: Resource state conflict (duplicate, version mismatch)
422 Unprocessable Entity: Semantic validation failure
429 Too Many Requests: Rate limit exceeded
5xx Server Error:
500 Internal Server Error: Unexpected server failure
502 Bad Gateway: Upstream service failed
503 Service Unavailable: Temporary overload/maintenance
504 Gateway Timeout: Upstream service timed out
Talep ve Yanıt Tasarımı
Tutarlı Yanıt Zarfı
{
"data": {
"id": "user_123",
"email": "john@example.com",
"name": "John Doe",
"created_at": "2024-01-15T10:30:00Z"
},
"meta": {
"request_id": "req_abc123",
"timestamp": "2024-01-15T10:30:00Z"
}
}
Hata Yanıtları
{
"error": {
"code": "VALIDATION_ERROR",
"message": "The request body contains validation errors",
"details": [
{
"field": "email",
"message": "Email is required",
"code": "REQUIRED_FIELD"
},
{
"field": "age",
"message": "Age must be between 18 and 120",
"code": "INVALID_VALUE",
"constraints": {
"minimum": 18,
"maximum": 120
}
}
]
}
}
Sayfalandırma
GET /users?page=2&per_page=20&sort=created_at:desc
{
"data": [ ... ],
"meta": {
"page": 2,
"per_page": 20,
"total": 100,
"total_pages": 5,
"count": 20
},
"links": {
"first": "/users?page=1&per_page=20",
"prev": "/users?page=1&per_page=20",
"next": "/users?page=3&per_page=20",
"last": "/users?page=5&per_page=20"
}
}
İmleç tabanlı sayfalandırma (büyük veri kümeleri için önerilir):
GET /users?cursor=eyJpZCI6IDUwMH0=&limit=20
{
"data": [ ... ],
"meta": {
"next_cursor": "eyJpZCI6IDUyMH0=",
"has_more": true
}
}
Filtreleme, Sıralama ve Arama
// Filtering
GET /users?role=admin&status=active
GET /orders?created_at[gte]=2024-01-01&total[gt]=100
// Sorting
GET /users?sort=name:asc,created_at:desc
// Searching
GET /users?search=john
// Field selection (sparse fields)
GET /users/123?fields=id,name,email
Kısmi Güncellemeler (PATCH ve PUT)
// PUT — Full replacement (requires all fields)
PUT /users/123
{
"email": "newemail@example.com",
"name": "John Updated",
"age": 31
}
// PATCH — Partial update (only send changed fields)
PATCH /users/123
{
"email": "newemail@example.com"
}
En İyi Güvenlik Uygulamaları
Kimlik doğrulama
Önerilen: OAuth 2.0 + OpenID Connect
POST /oauth/token
Content-Type: application/json
{
"grant_type": "client_credentials",
"client_id": "your_client_id",
"client_secret": "your_client_secret",
"scope": "read write"
}
Response:
{
"access_token": "eyJhbGciOi...",
"token_type": "Bearer",
"expires_in": 3600,
"scope": "read write"
}
GET /api/users
Authorization: Bearer eyJhbGciOi...
JWT Yapısı
// Header
{
"alg": "RS256",
"typ": "JWT"
}
// Payload
{
"sub": "user_123",
"iss": "auth.example.com",
"iat": 1705312200,
"exp": 1705315800,
"scope": "read:users write:users",
"roles": ["admin"]
}
Hız Sınırlaması
HTTP/1.1 200 OK
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 87
X-RateLimit-Reset: 1705315800
HTTP/1.1 429 Too Many Requests
Retry-After: 3600
Content-Type: application/json
{
"error": {
"code": "RATE_LIMIT_EXCEEDED",
"message": "Rate limit exceeded. Try again in 3600 seconds.",
"retry_after": 3600
}
}
Giriş Doğrulaması
// Zod validation schema for API input
import { z } from 'zod';
const createUserSchema = z.object({
email: z.string().email('Invalid email format'),
name: z.string().min(1, 'Name is required').max(100),
age: z.number().int().min(18).max(120).optional(),
role: z.enum(['user', 'admin', 'moderator']).default('user'),
tags: z.array(z.string()).max(10).optional(),
});
// Validation middleware
function validate(schema: ZodSchema) {
return (req, res, next) => {
const result = schema.safeParse(req.body);
if (!result.success) {
return res.status(422).json({
error: {
code: 'VALIDATION_ERROR',
message: 'Validation failed',
details: result.error.issues.map(i => ({
field: i.path.join('.'),
message: i.message
}))
}
});
}
req.validatedBody = result.data;
next();
};
}
HTTPS ve CORS
// CORS configuration
const corsOptions = {
origin: [
'https://app.example.com',
'https://admin.example.com',
],
methods: ['GET', 'POST', 'PATCH', 'DELETE'],
allowedHeaders: ['Content-Type', 'Authorization'],
exposedHeaders: ['X-RateLimit-Remaining'],
credentials: true,
maxAge: 86400 // Preflight cache (24 hours)
};
app.use(cors(corsOptions));
API Dokümantasyonu
OpenAPI 3.0 Spesifikasyonu
openapi: 3.0.3
info:
title: User Management API
version: 2.0.0
description: API for managing users in the system
contact:
email: api-support@example.com
servers:
- url: https://api.example.com/v2
description: Production server
paths:
/users:
get:
summary: List all users
parameters:
- name: page
in: query
schema:
type: integer
default: 1
- name: per_page
in: query
schema:
type: integer
default: 20
maximum: 100
responses:
'200':
description: A list of users
content:
application/json:
schema:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/User'
meta:
$ref: '#/components/schemas/PaginationMeta'
post:
summary: Create a new user
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CreateUserRequest'
responses:
'201':
description: User created
content:
application/json:
schema:
$ref: '#/components/schemas/User'
'422':
description: Validation error
components:
schemas:
User:
type: object
properties:
id:
type: string
email:
type: string
format: email
name:
type: string
created_at:
type: string
format: date-time
İnteraktif Dokümantasyon
# Serve Swagger UI for API documentation
npm install -g swagger-ui-express
# Visit: https://api.example.com/docs
API Testi
Sözleşme Testi
// Pact consumer-driven contract test
const { Pact } = require('@pact-foundation/pact');
describe('User API contract', () => {
const provider = new Pact({
consumer: 'Frontend App',
provider: 'User Service',
port: 1234,
});
beforeAll(() => provider.setup());
describe('GET /users/123', () => {
beforeAll(() => {
return provider.addInteraction({
state: 'User 123 exists',
uponReceiving: 'a request for user 123',
withRequest: {
method: 'GET',
path: '/users/123',
headers: { Authorization: 'Bearer valid-token' }
},
willRespondWith: {
status: 200,
headers: { 'Content-Type': 'application/json' },
body: {
data: {
id: '123',
email: 'user@example.com',
name: 'Test User'
}
}
}
});
});
it('returns the user', async () => {
const response = await fetch('http://localhost:1234/users/123', {
headers: { Authorization: 'Bearer valid-token' }
});
expect(response.status).toBe(200);
});
afterEach(() => provider.verify());
});
afterAll(() => provider.finalize());
});
GraphQL ve REST karşılaştırması
| Görünüş | DİNLENME | GrafikQL |
|---|---|---|
| Veri getiriliyor | Çoklu uç noktalar, sabit yanıt | Tek uç nokta, müşteri tanımlı |
| Aşırı getiriliyor | Gerekenden daha fazla veri döndürebilir | Tam olarak ihtiyacınız olanı isteyin |
| Yeterince getirilmiyor | Birden fazla istek gerekebilir (N+1) | İç içe geçmiş veriler için tek istek |
| Önbelleğe alma | Yerleşik (HTTP önbelleğe alma, CDN) | Özel (Apollo önbelleği, Aktarma) |
| Aletleme | Yetişkinlere yönelik (kıvırma, Postacı, tarayıcılar) | Büyüyor (GraphiQL, Apollo DevTools) |
| Öğrenme eğrisi | Düşük | Orta |
| Sürüm oluşturma | URI sürümü oluşturma | Alan ekleyin, eskileri kullanımdan kaldırın |
| Dosya yükleme | Yerel (çok parçalı) | Özel kullanım gerektirir |
| Gerçek zamanlı | WebSocket, SSE | Abonelikler |
GraphQL Ne Zaman Kullanılmalı?
- Karmaşık, iç içe geçmiş veri gereksinimleri (kontrol panelleri, mobil uygulamalar).
- Farklı verilere ihtiyaç duyan birden fazla istemci türü (web, mobil, IoT).
- Hızla gelişen ön uç gereksinimleri.
REST Ne Zaman Kullanılır?
- Basit CRUD işlemleri.
- Geniş tüketici tabanına sahip genel API'ler.
- Önbelleğe alma önemlidir (GET uç noktaları için CDN).
- Dosya yüklemeleri ve ikili veriler.
API Yaşam Döngüsü Yönetimi
Sürüm Oluşturma Stratejisi
version_policy:
- v1: Initial release (stable, deprecated)
- v2: Current version (active development)
- v3: Planned (future)
deprecation:
notice_period: 6 months
communication: email, API response header
sunset_header: true # Deprecation: true
transition:
new_features: v2 only
bug fixes: v1 critical only
migrations: provide migration guide
Kullanımdan Kaldırma Başlıkları
GET /v1/users/123
Sunset: Sat, 30 Nov 2024 00:00:00 GMT
Deprecation: true
Link: </v2/users/123>; rel="successor-version"
Sonuç
İyi API tasarımı şu ilkeleri takip eder:
- Tutarlılık — Adlandırma, hata biçimleri, sayfalandırma ve kimlik doğrulama aynı kalıpları izlemelidir.
- Geliştirici deneyimi — Açık belgeler, öngörülebilir davranış, faydalı hata mesajları.
- Varsayılan olarak güvenlik — HTTPS, kimlik doğrulama, hız sınırlama, giriş doğrulama, CORS.
- Geriye dönük uyumluluk — Sürümü bilinçli olarak kullanın, kullanımdan kaldırın, son derece önemli değişiklikleri bildirin.
- Performans — Sayfalandırma, başlıkları önbelleğe alma, seyrek alanlar, sıkıştırma.
API bir üründür. Tasarımına yatırım yapın, ayrıntılı bir şekilde belgeleyin, dikkatlice sürümlendirin ve her önemli değişikliğe hak ettiği ciddiyetle yaklaşın.
Öne Çıkan Makaleler

2026’da Oluşturmaya Değer 50 Claude Skill
Claude Skills, tekrarlanan promptları yeniden kullanılabilir workflow’lara dönüştürebilir. İşte yazma, kodlama, araştırma, iş, üretkenlik, tasarım, analiz ve destek için 50 pratik Claude Skill.

Senior Engineer’lardan Öğrendiğim 6 Kodlama Pattern’i

Özel Bir Yapay Zeka Not Asistanı Kurun
Markdown notlarını özel taslakları açığa çıkarmadan aranabilir bir asistana dönüştürün.
Yorumlar
0 yorumHenüz onaylı yorum yok. Yeni yanıtlar moderasyon bekleyebilir.