Skills DirectorySkills Directory
SkillsLearnSecurityCategoriesDocsBlogPro
Sign InSubmit Skill
Skills Directory

Security-tested agent skills for Claude, coding agents, and AI workflows.

Directory

  • Browse Skills
  • All Skills A–Z
  • Claude Skills
  • Claude Code Skills
  • Agent Skills
  • Categories
  • Authors
  • Submit a Skill

Learn

  • Learn Hub
  • Install Claude Skills
  • Write SKILL.md
  • Skills vs MCP
  • Directories Compared

Security

  • Security
  • Methodology
  • Secure Claude Skills
  • Security Badges
  • Chrome Extension
  • Skill Manager

Company

  • About
  • Community
  • Blog
  • API Docs
  • Advertise

2026 Skills Directory. All rights reserved.

ProTermsPrivacyRefunds
Back to skills

Api Design

ASecurity

REST API tasarım kalıpları; kaynak isimlendirme, durum kodları, sayfalama, filtreleme, hata yanıtları, versiyonlama ve üretim API'leri için hız sınırlama içerir.

2 stars
0 votes
0 copies
1 views
Added 9/19/2026
developmenttypescriptpythongosqlnextjsdjangogitapi

Works with

cursorapi

Security Analysis

A100/100

Scanned 9/19/2026

$npx -y skills add ibragimov-oasis/oasis-languages-jp --skill api-design --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Api Design?

Add the live security badge to your README — it updates automatically with every re-scan.

Security grade badge for Api Design
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/ibragimov-oasis-api-design-oasis-languages-jp/badge)](https://www.skillsdirectory.com/skills/ibragimov-oasis-api-design-oasis-languages-jp)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
Files
SKILL.md
---
name: api-design
description: REST API tasarım kalıpları; kaynak isimlendirme, durum kodları, sayfalama, filtreleme, hata yanıtları, versiyonlama ve üretim API'leri için hız sınırlama içerir.
origin: ECC
tags:
  - domain/skills
  - artifact/skill
  - source/skills-everything-cc
---

# API Tasarım Kalıpları

Tutarlı, geliştirici dostu REST API'leri tasarlamak için konvansiyonlar ve en iyi uygulamalar.

## Ne Zaman Aktifleştirmeli

- Yeni API endpoint'leri tasarlarken
- Mevcut API sözleşmelerini incelerken
- Sayfalama, filtreleme veya sıralama eklerken
- API'ler için hata işleme uygularken
- API versiyonlama stratejisi planlarken
- Halka açık veya iş ortağı odaklı API'ler oluştururken

## Kaynak Tasarımı

### URL Yapısı

```
# Kaynaklar isim, çoğul, küçük harf, kebab-case
GET    /api/v1/users
GET    /api/v1/users/:id
POST   /api/v1/users
PUT    /api/v1/users/:id
PATCH  /api/v1/users/:id
DELETE /api/v1/users/:id

# İlişkiler için alt kaynaklar
GET    /api/v1/users/:id/orders
POST   /api/v1/users/:id/orders

# CRUD'a uymayan aksiyonlar (fiilleri dikkatli kullanın)
POST   /api/v1/orders/:id/cancel
POST   /api/v1/auth/login
POST   /api/v1/auth/refresh
```

### İsimlendirme Kuralları

```
# İYİ
/api/v1/team-members          # çok sözcüklü kaynaklar için kebab-case
/api/v1/orders?status=active  # filtreleme için query parametreleri
/api/v1/users/123/orders      # sahiplik için iç içe kaynaklar

# KÖTÜ
/api/v1/getUsers              # URL'de fiil
/api/v1/user                  # tekil (çoğul kullanın)
/api/v1/team_members          # URL'lerde snake_case
/api/v1/users/123/getOrders   # iç içe kaynaklarda fiil
```

## HTTP Metodları ve Durum Kodları

### Metod Semantiği

| Metod | Idempotent | Güvenli | Kullanım Amacı |
|--------|-----------|------|---------|
| GET | Evet | Evet | Kaynakları getir |
| POST | Hayır | Hayır | Kaynak oluştur, aksiyonları tetikle |
| PUT | Evet | Hayır | Kaynağın tam değişimi |
| PATCH | Hayır* | Hayır | Kaynağın kısmi güncellemesi |
| DELETE | Evet | Hayır | Kaynağı kaldır |

*PATCH uygun implementasyonla idempotent yapılabilir

### Durum Kodu Referansı

```
# Başarı
200 OK                    — GET, PUT, PATCH (yanıt body'si ile)
201 Created               — POST (Location header ekleyin)
204 No Content            — DELETE, PUT (yanıt body'si yok)

# İstemci Hataları
400 Bad Request           — Validasyon hatası, hatalı JSON
401 Unauthorized          — Eksik veya geçersiz kimlik doğrulama
403 Forbidden             — Kimlik doğrulandı ama yetkilendirilmedi
404 Not Found             — Kaynak mevcut değil
409 Conflict              — Tekrar kayıt, durum çakışması
422 Unprocessable Entity  — Semantik olarak geçersiz (geçerli JSON, kötü veri)
429 Too Many Requests     — Hız limiti aşıldı

# Sunucu Hataları
500 Internal Server Error — Beklenmeyen hata (detayları açığa çıkarmayın)
502 Bad Gateway           — Upstream servis başarısız
503 Service Unavailable   — Geçici aşırı yük, Retry-After ekleyin
```

### Yaygın Hatalar

```
# KÖTÜ: Her şey için 200
{ "status": 200, "success": false, "error": "Not found" }

# İYİ: HTTP durum kodlarını semantik olarak kullanın
HTTP/1.1 404 Not Found
{ "error": { "code": "not_found", "message": "User not found" } }

# KÖTÜ: Validasyon hataları için 500
# İYİ: Alan düzeyinde detaylarla 400 veya 422

# KÖTÜ: Oluşturulan kaynaklar için 200
# İYİ: Location header ile 201
HTTP/1.1 201 Created
Location: /api/v1/users/abc-123
```

## Yanıt Formatı

### Başarı Yanıtı

```json
{
  "data": {
    "id": "abc-123",
    "email": "alice@example.com",
    "name": "Alice",
    "created_at": "2025-01-15T10:30:00Z"
  }
}
```

### Koleksiyon Yanıtı (Sayfalama ile)

```json
{
  "data": [
    { "id": "abc-123", "name": "Alice" },
    { "id": "def-456", "name": "Bob" }
  ],
  "meta": {
    "total": 142,
    "page": 1,
    "per_page": 20,
    "total_pages": 8
  },
  "links": {
    "self": "/api/v1/users?page=1&per_page=20",
    "next": "/api/v1/users?page=2&per_page=20",
    "last": "/api/v1/users?page=8&per_page=20"
  }
}
```

### Hata Yanıtı

```json
{
  "error": {
    "code": "validation_error",
    "message": "Request validation failed",
    "details": [
      {
        "field": "email",
        "message": "Must be a valid email address",
        "code": "invalid_format"
      },
      {
        "field": "age",
        "message": "Must be between 0 and 150",
        "code": "out_of_range"
      }
    ]
  }
}
```

### Yanıt Zarfı Varyantları

```typescript
// Seçenek A: Data sarmalayıcılı zarf (halka açık API'ler için önerilir)
interface ApiResponse<T> {
  data: T;
  meta?: PaginationMeta;
  links?: PaginationLinks;
}

interface ApiError {
  error: {
    code: string;
    message: string;
    details?: FieldError[];
  };
}

// Seçenek B: Düz yanıt (daha basit, dahili API'ler için yaygın)
// Başarı: kaynağı doğrudan döndür
// Hata: hata nesnesini döndür
// HTTP durum koduyla ayırt et
```

## Sayfalama

### Offset-Tabanlı (Basit)

```
GET /api/v1/users?page=2&per_page=20

# Implementasyon
SELECT * FROM users
ORDER BY created_at DESC
LIMIT 20 OFFSET 20;
```

**Artıları:** Uygulaması kolay, "N sayfasına git" destekler
**Eksileri:** Büyük offset'lerde yavaş (OFFSET 100000), eş zamanlı eklemelerde tutarsız

### Cursor-Tabanlı (Ölçeklenebilir)

```
GET /api/v1/users?cursor=eyJpZCI6MTIzfQ&limit=20

# Implementasyon
SELECT * FROM users
WHERE id > :cursor_id
ORDER BY id ASC
LIMIT 21;  -- has_next belirlemek için bir fazla getir
```

```json
{
  "data": [...],
  "meta": {
    "has_next": true,
    "next_cursor": "eyJpZCI6MTQzfQ"
  }
}
```

**Artıları:** Pozisyondan bağımsız tutarlı performans, eş zamanlı eklemelerde kararlı
**Eksileri:** Rastgele sayfaya atlayamaz, cursor opak

### Hangisi Ne Zaman Kullanılmalı

| Kullanım Senaryosu | Sayfalama Tipi |
|----------|----------------|
| Admin panelleri, küçük veri setleri (<10K) | Offset |
| Sonsuz kaydırma, akışlar, büyük veri setleri | Cursor |
| Halka açık API'ler | Cursor (varsayılan) ile offset (opsiyonel) |
| Arama sonuçları | Offset (kullanıcılar sayfa numarası bekler) |

## Filtreleme, Sıralama ve Arama

### Filtreleme

```
# Basit eşitlik
GET /api/v1/orders?status=active&customer_id=abc-123

# Karşılaştırma operatörleri (köşeli parantez notasyonu kullanın)
GET /api/v1/products?price[gte]=10&price[lte]=100
GET /api/v1/orders?created_at[after]=2025-01-01

# Çoklu değerler (virgülle ayrılmış)
GET /api/v1/products?category=electronics,clothing

# İç içe alanlar (nokta notasyonu)
GET /api/v1/orders?customer.country=US
```

### Sıralama

```
# Tek alan (azalan için - öneki)
GET /api/v1/products?sort=-created_at

# Çoklu alanlar (virgülle ayrılmış)
GET /api/v1/products?sort=-featured,price,-created_at
```

### Tam Metin Arama

```
# Arama query parametresi
GET /api/v1/products?q=wireless+headphones

# Alana özel arama
GET /api/v1/users?email=alice
```

### Seyrek Fieldset'ler

```
# Sadece belirtilen alanları döndür (payload'ı azaltır)
GET /api/v1/users?fields=id,name,email
GET /api/v1/orders?fields=id,total,status&include=customer.name
```

## Kimlik Doğrulama ve Yetkilendirme

### Token-Tabanlı Auth

```
# Authorization header'da Bearer token
GET /api/v1/users
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...

# API key (sunucudan sunucuya)
GET /api/v1/data
X-API-Key: sk_live_abc123
```

### Yetkilendirme Kalıpları

```typescript
// Kaynak seviyesi: sahipliği kontrol et
app.get("/api/v1/orders/:id", async (req, res) => {
  const order = await Order.findById(req.params.id);
  if (!order) return res.status(404).json({ error: { code: "not_found" } });
  if (order.userId !== req.user.id) return res.status(403).json({ error: { code: "forbidden" } });
  return res.json({ data: order });
});

// Rol-tabanlı: yetkileri kontrol et
app.delete("/api/v1/users/:id", requireRole("admin"), async (req, res) => {
  await User.delete(req.params.id);
  return res.status(204).send();
});
```

## Hız Sınırlama

### Header'lar

```
HTTP/1.1 200 OK
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 95
X-RateLimit-Reset: 1640000000

# Aşıldığında
HTTP/1.1 429 Too Many Requests
Retry-After: 60
{
  "error": {
    "code": "rate_limit_exceeded",
    "message": "Rate limit exceeded. Try again in 60 seconds."
  }
}
```

### Hız Limit Katmanları

| Katman | Limit | Pencere | Kullanım Senaryosu |
|------|-------|--------|----------|
| Anonim | 30/dk | IP Başına | Halka açık endpoint'ler |
| Kimlik Doğrulanmış | 100/dk | Kullanıcı Başına | Standart API erişimi |
| Premium | 1000/dk | API key Başına | Ücretli API planları |
| Dahili | 10000/dk | Servis Başına | Servisten servise |

## Versiyonlama

### URL Yolu Versiyonlama (Önerilen)

```
/api/v1/users
/api/v2/users
```

**Artıları:** Açık, yönlendirmesi kolay, cache'lenebilir
**Eksileri:** Versiyonlar arası URL değişir

### Header Versiyonlama

```
GET /api/users
Accept: application/vnd.myapp.v2+json
```

**Artıları:** Temiz URL'ler
**Eksileri:** Test etmesi zor, unutulması kolay

### Versiyonlama Stratejisi

```
1. /api/v1/ ile başlayın — ihtiyaç duyana kadar versiyonlamayın
2. En fazla 2 aktif versiyon koruyun (mevcut + önceki)
3. Kullanımdan kaldırma zaman çizelgesi:
   - Kullanımdan kaldırmayı duyurun (halka açık API'ler için 6 ay önceden)
   - Sunset header ekleyin: Sunset: Sat, 01 Jan 2026 00:00:00 GMT
   - Sunset tarihinden sonra 410 Gone döndürün
4. Breaking olmayan değişiklikler yeni versiyon gerektirmez:
   - Yanıtlara yeni alanlar eklemek
   - Yeni opsiyonel query parametreleri eklemek
   - Yeni endpoint'ler eklemek
5. Breaking değişiklikler yeni versiyon gerektirir:
   - Alanları kaldırmak veya yeniden adlandırmak
   - Alan tiplerini değiştirmek
   - URL yapısını değiştirmek
   - Kimlik doğrulama metodunu değiştirmek
```

## Implementasyon Kalıpları

### TypeScript (Next.js API Route)

```typescript
import { z } from "zod";
import { NextRequest, NextResponse } from "next/server";

const createUserSchema = z.object({
  email: z.string().email(),
  name: z.string().min(1).max(100),
});

export async function POST(req: NextRequest) {
  const body = await req.json();
  const parsed = createUserSchema.safeParse(body);

  if (!parsed.success) {
    return NextResponse.json({
      error: {
        code: "validation_error",
        message: "Request validation failed",
        details: parsed.error.issues.map(i => ({
          field: i.path.join("."),
          message: i.message,
          code: i.code,
        })),
      },
    }, { status: 422 });
  }

  const user = await createUser(parsed.data);

  return NextResponse.json(
    { data: user },
    {
      status: 201,
      headers: { Location: `/api/v1/users/${user.id}` },
    },
  );
}
```

### Python (Django REST Framework)

```python
from rest_framework import serializers, viewsets, status
from rest_framework.response import Response

class CreateUserSerializer(serializers.Serializer):
    email = serializers.EmailField()
    name = serializers.CharField(max_length=100)

class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ["id", "email", "name", "created_at"]

class UserViewSet(viewsets.ModelViewSet):
    serializer_class = UserSerializer
    permission_classes = [IsAuthenticated]

    def get_serializer_class(self):
        if self.action == "create":
            return CreateUserSerializer
        return UserSerializer

    def create(self, request):
        serializer = CreateUserSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        user = UserService.create(**serializer.validated_data)
        return Response(
            {"data": UserSerializer(user).data},
            status=status.HTTP_201_CREATED,
            headers={"Location": f"/api/v1/users/{user.id}"},
        )
```

### Go (net/http)

```go
func (h *UserHandler) CreateUser(w http.ResponseWriter, r *http.Request) {
    var req CreateUserRequest
    if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
        writeError(w, http.StatusBadRequest, "invalid_json", "Invalid request body")
        return
    }

    if err := req.Validate(); err != nil {
        writeError(w, http.StatusUnprocessableEntity, "validation_error", err.Error())
        return
    }

    user, err := h.service.Create(r.Context(), req)
    if err != nil {
        switch {
        case errors.Is(err, domain.ErrEmailTaken):
            writeError(w, http.StatusConflict, "email_taken", "Email already registered")
        default:
            writeError(w, http.StatusInternalServerError, "internal_error", "Internal error")
        }
        return
    }

    w.Header().Set("Location", fmt.Sprintf("/api/v1/users/%s", user.ID))
    writeJSON(w, http.StatusCreated, map[string]any{"data": user})
}
```

## API Tasarım Kontrol Listesi

Yeni bir endpoint yayınlamadan önce:

- [ ] Kaynak URL isimlendirme konvansiyonlarını takip ediyor (çoğul, kebab-case, fiil yok)
- [ ] Doğru HTTP metodu kullanılıyor (okumalar için GET, oluşturmalar için POST, vb.)
- [ ] Uygun durum kodları döndürülüyor (her şey için 200 değil)
- [ ] Girdi şema ile validasyona tabi tutuluyor (Zod, Pydantic, Bean Validation)
- [ ] Hata yanıtları kodlar ve mesajlarla standart formatı takip ediyor
- [ ] Liste endpoint'leri için sayfalama uygulanmış (cursor veya offset)
- [ ] Kimlik doğrulama gerekli (veya açıkça halka açık işaretlenmiş)
- [ ] Yetkilendirme kontrol ediliyor (kullanıcı sadece kendi kaynaklarına erişebilir)
- [ ] Hız sınırlama yapılandırılmış
- [ ] Yanıt dahili detayları sızdırmıyor (stack trace'ler, SQL hataları)
- [ ] Mevcut endpoint'lerle tutarlı isimlendirme (camelCase vs snake_case)
- [ ] Dokümante edilmiş (OpenAPI/Swagger spec güncellenmiş)

## 🔗 Связи

- [[MOC - Skills]] — Skills library
- [[skills/skills-everything-cc]] — Category: skills-everything-cc

Attribution

ibragimov-oasisibragimov-oasis
View sourceSee grades on GitHubMore from ibragimov-oasis →
SSkills DirectorySkills Directory

Ship a skill? Prove it's safe.

Free 120-pattern security scan, letter grade, and an embeddable README badge.

Submit a skill

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments (0)

No comments yet. Be the first to comment!

SSkills DirectorySkills Directory

Ship a skill? Prove it's safe.

Free 120-pattern security scan, letter grade, and an embeddable README badge.

Submit a skill

Related Skills

Clean Code

Pragmatic coding standards - concise, direct, no over-engineering, no unnecessary comments

304955 votes

Browser Extension Developer

Use this skill when developing or maintaining browser extension code in the `browser/` directory, including Chrome/Firefox/Edge compatibility, content scripts, background scripts, or i18n updates.

285172 votes

Seo Optimizer

SEO optimization with keyword analysis, readability assessment, technical validation, content quality. Use for search rankings, blog posts, content audits, or encountering keyword density, readability scores, meta tags, schema markup errors.

2222 votes

Google Official Seo Guide

Official Google SEO guide covering search optimization, best practices, Search Console, crawling, indexing, and improving website search visibility based on official Google documentation

1862 votes

Tanstack Start

Build a full-stack TanStack Start app on Cloudflare Workers from scratch — SSR, file-based routing, server functions, D1+Drizzle, better-auth, Tailwind v4+shadcn/ui. Use whenever the user mentions TanStack Start, asks to scaffold a full-stack Cloudflare app with SSR, wants an SSR dashboard, or asks for a React 19 + Cloudflare Workers app with file-based routing and server functions — even if they don't name TanStack Start specifically. No template repo — Claude generates every file fresh per ...

10341 votes
View all in development →