a.
mcp.altay.socialMCP & Prompt Katalogu
Rules
Öne çıkan·v1.0.0·2026-04-22

API Tasarım Kuralları

REST API tasarım kuralları — URL yapısı, HTTP method, status code, versioning, error format, pagination, idempotency, rate limit, dokümantasyon. CLAUDE.md / .cursorrules içeriği olarak kullanılır.

apiresthttpdesignrulesbackendclaude-md

İçerik

Bu içeriği projenin CLAUDE.md / AGENTS.md / .cursorrules dosyasına yapıştır.


REST API Tasarım Kuralları

URL yapısı

İsimlendirme

  • Kaynak isimleri çoğul, küçük harf, kebab-case:
    ✅ GET /users
    ✅ GET /order-items
    ❌ GET /getUsers
    ❌ GET /orderItems
    ❌ GET /User
    
  • Action verbi URL'de yasak — HTTP method verbi taşır:
    ✅ POST /users              (create)
    ✅ DELETE /users/123         (delete)
    ❌ POST /createUser
    ❌ POST /users/123/delete
    
  • İstisna: bir state transition CRUD'a uymuyorsa — sub-resource veya action:
    POST /orders/123/cancel
    POST /users/123/password-reset
    
  • Path param = resource identifier:
    GET /users/{user_id}
    GET /users/{user_id}/orders
    GET /users/{user_id}/orders/{order_id}
    
  • Nesting maksimum 2 seviye — aksi belirsizleşir. 3. seviye için flat:
    ❌ /users/1/projects/2/tasks/3/comments
    ✅ /tasks/3/comments  (task globally unique ise)
    

HTTP method

Method Ne için Idempotent? Body?
GET Listele / fetch Evet Hayır
POST Oluştur / action Hayır Evet
PUT Tam replace Evet Evet
PATCH Kısmi güncelleme Genelde evet Evet
DELETE Sil Evet Nadiren
  • GET hiçbir yan etki yaratmaz. Cache'lenir, tekrar edilebilir.
  • PUT = replace. Resource'u verdiğin body ile değiştir (full).
  • PATCH = merge. Belirtilen alanları güncelle. JSON Merge Patch ya da JSON Patch.
  • DELETE idempotent — ikinci kez çağırınca 404 değil, 204 dön (veya 404 + tutarlı).

Status code

2xx — Başarı

  • 200 OK — başarılı, body var
  • 201 Created — oluşturuldu, Location: /resource/id header
  • 202 Accepted — async, işlem başlatıldı (queue / background)
  • 204 No Content — başarılı, body yok (DELETE sonrası)

3xx — Yönlendirme

  • 301 Moved Permanently — URL değişti kalıcı
  • 302 Found / 307 Temporary — geçici redirect
  • 304 Not Modified — ETag / If-Modified-Since match

4xx — Client hatası

  • 400 Bad Request — validation hatası, malformed
  • 401 Unauthorized — authentication eksik
  • 403 Forbidden — authenticated ama yetki yok
  • 404 Not Found — resource yok
  • 405 Method Not Allowed — resource var ama method desteklenmiyor
  • 409 Conflict — state çakışması (duplicate, race)
  • 410 Gone — eskiden vardı, şimdi silindi / kalıcı kapalı
  • 422 Unprocessable Entity — syntax OK, semantic invalid (business rule)
  • 429 Too Many Requests — rate limit

5xx — Server hatası

  • 500 Internal Server Error — beklenmeyen hata
  • 502 Bad Gateway — upstream hatası
  • 503 Service Unavailable — geçici indir / maintenance
  • 504 Gateway Timeout — upstream timeout

Kullanılmayan: 200 OK başarısızlık body'siyle — yasak. Status code doğru döner.

Error response formatı

Tek format, tüm endpoint'lerde:

{
  "error": {
    "code": "order_out_of_stock",
    "message": "Requested quantity exceeds available stock",
    "details": {
      "product_id": "prod_123",
      "requested": 10,
      "available": 3
    },
    "trace_id": "req_abc123"
  }
}
  • code — machine-readable, snake_case, stable (client switch-case)
  • message — human-readable, developer için (localize etme, ayrı mekanizma)
  • details — opsiyonel, structured context
  • trace_id — log correlation

Validation hatalarında (400) her alan için:

{
  "error": {
    "code": "validation_failed",
    "fields": {
      "email": ["required", "must_be_valid_email"],
      "age": ["must_be_positive"]
    }
  }
}

Versioning

  • URL path'te major version: /v1/, /v2/ (sade, caching-friendly).
    GET /v1/users
    GET /v2/users
    
  • Breaking change → yeni major. Aynı v1 altında breaking değişiklik yasak.
  • Non-breaking eklemeler (yeni alan, yeni endpoint) mevcut version'da.
  • Deprecation: header ile (Deprecation: true, Sunset: <tarih>) + dokümantasyon.
  • En az 6 ay paralel yaşam (v1 + v2), sonra eski emekli edilir.

Request / response conventions

Naming

  • JSON field'lar snake_case (dilden bağımsız, interop friendly):
    { "user_id": "...", "created_at": "..." }
    
  • Timestamp ISO 8601 UTC: 2026-04-22T14:30:00Z.
  • ID'ler string (integer overflow, prefix'lenebilir):
    { "id": "usr_01HW3KJD..." }
    
  • Boolean alan adı: is_active, has_verified_email, değil active, verified.
  • Enum değerleri: snake_case string (tip güvenli ama esnek).

Pagination

Cursor-based (tercih):

GET /users?limit=50&cursor=eyJpZCI6InVzcl8xMjMifQ
{
  "data": [...],
  "pagination": {
    "next_cursor": "eyJpZCI6InVzcl80NTYifQ",
    "has_more": true
  }
}

Offset-based sadece küçük, stable dataset'te kabul:

GET /users?page=2&per_page=50
  • Default limit (20, 50, 100) + max limit (genelde 100-200).
  • limit ve per_page aynı anda kullanılmaz — projede biri seçilir.

Filter / sort / search

GET /orders?status=pending&created_after=2026-01-01&sort=-created_at
  • Filter query param + eşitlik. Karmaşıklaşırsa: ?status=pending,paid (comma-separated).
  • Sort -created_at = desc, created_at = asc. Multi-sort comma: sort=status,-created_at.
  • Range: created_after, created_before (net). gte:, lte: prefix'i de tercih edilebilir.
  • Search: ?q=... full-text.

Idempotency

  • POST (create) için: Idempotency-Key header (UUID).
  • Server 24-48 saat key + response cache tutar. Aynı key ile tekrar → cached response (201 + aynı body).
  • Her "hassas" POST için zorunlu yap (payment, refund, email send).
  • PUT, DELETE, GET doğaları gereği idempotent — Idempotency-Key gereksiz.

Authentication & Authorization

  • Bearer token Authorization: Bearer <jwt|opaque>.
  • 401 = auth yok/invalid. 403 = auth OK ama yetki yok. Karıştırma.
  • JWT expiration makul (< 1 saat), refresh token ayrı.
  • API key sadece server-to-server. Client (mobile/web) = OAuth token.
  • Scope-based authorization (orders:read, orders:write) basit role'den daha esnek.

Rate limiting

  • Response headers:
    X-RateLimit-Limit: 1000
    X-RateLimit-Remaining: 899
    X-RateLimit-Reset: 1700000000
    
  • 429 Too Many Requests + Retry-After header.
  • Tier'lar: anonymous < authenticated < premium.
  • Per-endpoint limit bazı endpoint'ler için (login, password reset) tighter.

CORS

  • Cross-origin kullanıma açık endpoint'te:
    Access-Control-Allow-Origin: https://app.example.com  (specific)
    Access-Control-Allow-Methods: GET, POST, PUT, DELETE
    Access-Control-Allow-Headers: Authorization, Content-Type
    Access-Control-Max-Age: 86400
    
  • * ile allow-origin sadece tamamen public, auth-free API için.

Request body size

  • Limit var (10MB gibi). Config'te tanımlı.
  • Binary upload ayrı endpoint (multipart/form-data veya presigned URL to S3).
  • Arbitrary JSON içinde binary yok — ya base64 (ayrı endpoint) ya presigned.

Dokümantasyon

  • OpenAPI 3.0+ spec kodun yanında tutulur (inline veya ayrı YAML).
  • Swagger UI / Redoc otomatik üretilir.
  • Her endpoint için: açıklama, request/response schema, örnek, error code'ları.
  • Changelog — her version bump'ta değişenler listelenir.
  • SDK / client library otomatik üretilir (OpenAPI Generator).

Güvenlik minimumu

  • HTTPS zorunlu. HTTP isteği → redirect ya da 403.
  • Input validation schema-based, her endpoint.
  • Output escape — XSS için, response'da kullanıcı content echo'lanıyorsa.
  • SQL parametreli query — concat yasak.
  • Secret log'a girmez — token, password, PII log'da görünmez.
  • CSRF cookie-based session varsa (SameSite + token).

Async / Webhooks

Long-running operation

POST /reports/generate
→ 202 Accepted
  Location: /reports/generate/status/{job_id}

GET /reports/generate/status/{job_id}
→ { "status": "pending" | "running" | "done" | "failed", "result_url": "..." }

Webhooks

  • HMAC signature body + timestamp üzerinde.
  • Retry: exponential backoff, at-least-once.
  • Idempotency-Key webhook payload'da.
  • Versioning: header ile (X-Webhook-Version: 1).

Yasak listesi (özet)

  • URL'de verb (/getUser, /createOrder)
  • 200 OK + {"success": false} body
  • id integer (stringified ID kullan)
  • Nested 3+ seviye resource
  • camelCase JSON field (dilden dile çeviride sorun)
  • PATCH ≠ PUT ayrımı belirsiz bırakmak
  • Response'da farklı error format'lar
  • Breaking change aynı version'da
  • API key URL query param'da (log'a sızar)
  • CORS * auth-required endpoint'te
  • Rate limit bilgisi yok (client tahmin edemez)
  • Dokümantasyon kodla senkron değil

Örnek iyi endpoint

POST /v1/orders:
  summary: Yeni sipariş oluştur
  headers:
    Idempotency-Key:
      required: true
      schema: { type: string, format: uuid }
    Authorization:
      required: true
  request_body:
    type: object
    required: [items]
    properties:
      items:
        type: array
        items:
          type: object
          required: [product_id, qty]
          properties:
            product_id: { type: string }
            qty: { type: integer, minimum: 1 }
  responses:
    201:
      description: Sipariş oluşturuldu
      headers:
        Location: { schema: { type: string } }
      body:
        order_id: string
        status: string
        total: number
        created_at: string (iso8601)
    400: validation_failed
    409: idempotency_replay (cached response)
    422: insufficient_stock

Commit

Conventional Commits. Endpoint eklentisi feat(api): ..., breaking change feat(api)!: + BREAKING CHANGE footer.