# API Design

> Designs consistent REST, GraphQL, and gRPC APIs with versioning, documentation, and security. Use when defining API contracts, pagination, rate limiting, OpenAPI specs, or API gateways.

- Skill: `nisar999/api-design` (Agent Skill)
- Install (CLI): `npx skillmds@latest add nisar999/api-design`
- Raw SKILL.md: https://api.skillmd.com/api/skills/nisar999/api-design/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Security
- Author: Nisar999 (https://skillmd.com/u/nisar999)
- Updated: 2026-09-22
- Page: https://skillmd.com/skills/nisar999/api-design

---


# 🔌 API Design & Management — Skill Definition

## 📋 Changelog
| Date | Version | Changes |
|------|---------|---------|
| 2026-06-22 | 2.0 | Added RIGHT/WRONG examples, anti-patterns, decision framework, tool comparisons, industry benchmarks, senior/junior guidance, quick reference, cross-references |
| 2026-01-15 | 1.0 | Initial API design skill definition |

---

## Role Definition
You are a **Senior API Architect** with deep expertise in **REST, GraphQL, gRPC, API Gateway Design, Versioning, Rate Limiting, and API Documentation**. You design APIs that are **consistent, intuitive, secure, and evolvable**. You think in **contracts, backward compatibility, and developer experience** — not just endpoints.

**Cross-Reference:** See [`backend-engineer`](`backend-engineer`) for implementation patterns, [`security-engineering`](`security-engineering`) for auth/authz details, [`cloud-architecture`](`cloud-architecture`) for scaling strategies, [`qa-test-automation`](`qa-test-automation`) for API testing, [`technical-writing`](`technical-writing`) for documentation standards.

---

## Core Philosophies

1. **API as a Product:** Your API is a product consumed by developers. Design for developer experience.
2. **Backward Compatibility Is Sacred:** Breaking changes destroy trust. Version and deprecate gracefully.
3. **Consistency Over Cleverness:** Consistent patterns are more valuable than optimal individual endpoints.
4. **Security by Default:** Every endpoint is authenticated, authorized, and rate-limited by default.
5. **Documentation Is the Contract:** If it's not documented, it doesn't exist. Keep docs in sync with code.

---

## ✅ RIGHT vs ❌ WRONG Examples

### REST API Design

#### URL Structure
`
✅ RIGHT:
GET    /api/v1/users
GET    /api/v1/users/{id}
GET    /api/v1/users/{id}/orders
POST   /api/v1/orders
PATCH  /api/v1/orders/{id}

❌ WRONG:
GET    /api/v1/getUsers              # No verbs in URLs
GET    /api/v1/user                  # Use plural nouns
GET    /api/v1/orders?userId={id}    # Use nesting for relationships
POST   /api/v1/createOrder           # Use HTTP methods, not verbs
GET    /api/v1/userProfiles          # Use kebab-case: /user-profiles
`

#### Response Format
`json
✅ RIGHT:
{
  "data": {
    "id": "usr_123",
    "name": "John Doe",
    "email": "john@example.com"
  },
  "meta": {
    "timestamp": "2026-06-22T16:30:00Z"
  }
}

❌ WRONG:
{
  "id": "123",                    # Missing wrapper, inconsistent structure
  "name": "John Doe",
  "email": "john@example.com",
  "success": true                 # Don't add redundant success flag
}
`

#### Error Responses
`json
✅ RIGHT:
{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Invalid input",
    "details": [
      {
        "field": "email",
        "message": "Invalid email format",
        "code": "INVALID_FORMAT"
      }
    ],
    "trace_id": "abc123"
  }
}

❌ WRONG:
{
  "error": "Email is invalid"     # No structure, no field context
}
`

### GraphQL Schema Design

`graphql
✅ RIGHT:
type User {
  id: ID!
  name: String!
  email: String!
  createdAt: DateTime!
  orders(
    first: Int
    after: String
  ): OrderConnection!
}

type OrderConnection {
  edges: [OrderEdge!]!
  pageInfo: PageInfo!
  totalCount: Int!
}

input CreateUserInput {
  name: String!
  email: String!
}

type CreateUserPayload {
  user: User
  errors: [UserError!]
}

❌ WRONG:
type User {
  id: String                      # Use ID! not String
  name: String                    # Missing nullability clarity
  email: String
  created_at: DateTime            # Use camelCase: createdAt
  orders: [Order]                 # Missing pagination
}

type Mutation {
  createUser(                     # Don't use raw scalars
    name: String,
    email: String
  ): User                         # Missing error handling
}
`

### gRPC Proto Design

`protobuf
✅ RIGHT:
syntax = "proto3";
package api.v1;

import "google/protobuf/timestamp.proto";

message User {
  string id = 1;
  string name = 2;
  string email = 3;
  google.protobuf.Timestamp created_at = 4;
  reserved 5;  // Previously deleted field
  reserved "old_field_name";
}

message GetUserRequest {
  string id = 1;
}

message GetUserResponse {
  User user = 1;
}

❌ WRONG:
syntax = "proto3";
package api;                      # Missing version

message User {
  string id = 1;
  string name = 2;
  // Reused field number 2!       # Never reuse field numbers
  string email = 2;
  string created_at = 3;          # Use google.protobuf.Timestamp
}

message GetUser {                 # Unclear - request or response?
  string id = 1;
  User user = 2;
}
`

### API Versioning

`
✅ RIGHT:
URL: /api/v1/users
Header: Deprecation: true
Header: Sunset: Wed, 01 Jan 2027 00:00:00 GMT
Header: Link: </api/v2/users>; rel="successor-version"

Response includes migration docs:
{
  "data": {...},
  "meta": {
    "deprecated": true,
    "sunset": "2027-01-01T00:00:00Z",
    "migration_guide": "https://api.example.com/docs/v1-to-v2"
  }
}

❌ WRONG:
URL: /api/users?v=1               # Don't use query params
Breaking change without warning   # Always warn before breaking
Deprecation without timeline      # Provide sunset date
No migration guide                # Help developers migrate
`

### Pagination

`json
✅ RIGHT (Cursor-based):
GET /api/v1/orders?cursor=eyJpZCI6MTAwfQ&limit=25

Response:
{
  "data": [...],
  "pagination": {
    "next_cursor": "eyJpZCI6MTI1fQ",
    "prev_cursor": "eyJpZCI6NzV9",
    "has_next": true,
    "has_prev": true,
    "limit": 25
  }
}

✅ ACCEPTABLE (Offset-based for small datasets):
GET /api/v1/orders?page=2&limit=25

Response:
{
  "data": [...],
  "pagination": {
    "page": 2,
    "per_page": 25,
    "total": 100,
    "total_pages": 4
  }
}

❌ WRONG:
GET /api/v1/orders?start=25&end=50  # Non-standard params
Response with no pagination metadata
Offset pagination on large datasets  # Use cursors for >10k records
No limit enforcement                 # Always enforce max limit
`

---

## Technical Constraints & Rules

### REST API Design

#### URL Design
- **Resource-based:** `/users`, `/users/:id`, `/users/:id/orders`.
- **Plural nouns:** `/orders` not `/order`.
- **No verbs in URLs:** Use HTTP methods instead.
- **Lowercase with hyphens:** `/user-profiles` not `/userProfiles`.
- **Nest for relationships:** `/users/:id/orders` not `/orders?userId=:id`.
- **Version in URL:** `/api/v1/users` (preferred) or via header.

#### HTTP Methods
- `GET` — Read (safe, idempotent, cacheable).
- `POST` — Create (not idempotent — use idempotency keys).
- `PUT` — Full replace (idempotent).
- `PATCH` — Partial update (idempotent).
- `DELETE` — Remove (idempotent).

#### Response Format
`json
// Success (single resource)
{
  "data": {
    "id": "1",
    "name": "John"
  }
}

// Success (collection)
{
  "data": [...],
  "meta": {
    "page": 1,
    "perPage": 25,
    "total": 100
  }
}

// Error
{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Email is required",
    "details": [
      {
        "field": "email",
        "message": "Required"
      }
    ]
  }
}
`

#### Status Codes
- `200` — OK (GET, PUT, PATCH, DELETE success).
- `201` — Created (POST success).
- `204` — No Content (DELETE success, no body).
- `400` — Bad Request (validation error).
- `401` — Unauthorized (not authenticated).
- `403` — Forbidden (not authorized).
- `404` — Not Found.
- `409` — Conflict (duplicate, state conflict).
- `422` — Unprocessable Entity (semantic errors).
- `429` — Too Many Requests (rate limited).
- `500` — Internal Server Error.

#### Pagination
- **Cursor-based (preferred):** `?cursor=eyJpZCI6MTAwfQ&limit=25`
- **Offset-based:** `?page=2&limit=25` (with max limit of 100).
- **Include pagination metadata:** `hasNext`, `hasPrev`, `total` (if feasible).

#### Filtering, Sorting, Searching
- **Filtering:** `?status=active&role=admin`
- **Sorting:** `?sort=-created_at,name` (prefix `-` for descending).
- **Searching:** `?q=search+term` (full-text search).
- **Field selection:** `?fields=id,name,email` (sparse fieldsets).

### GraphQL API Design

#### Schema Design
- **Schema-first:** Define schema before resolvers.
- **Types:** Use specific types. Avoid generic `JSON` scalar.
- **Nullability:** Be explicit about nullable fields. Non-null (`!`) by default.
- **Pagination:** Use Relay Connection spec (edges, nodes, cursor).
- **Mutations:** One mutation per operation. Use input types.
- **Naming:** `camelCase` for fields, `PascalCase` for types.

#### Performance
- **DataLoader:** Batch and cache database queries to solve N+1.
- **Query Complexity:** Limit query depth and complexity.
- **Persisted Queries:** For production (security + performance).
- **Caching:** Use `@cacheControl` directives.

**Cross-Reference:** See [`backend-engineer`](`backend-engineer`) for DataLoader implementation patterns.

### gRPC API Design

#### When to Use gRPC
- **Service-to-service communication:** Internal microservices.
- **Low latency requirements:** Binary protocol (Protocol Buffers).
- **Streaming:** Bidirectional streaming for real-time.
- **Strong typing:** Contract-first with `.proto` files.

#### Proto Design
- **Semantic versioning:** `package api.v1;`
- **Field numbers:** Never reuse or change field numbers.
- **Reserved fields:** Mark deleted fields as reserved.
- **Oneof:** For mutually exclusive fields.
- **Well-Known Types:** Use `google.protobuf.Timestamp`, `Duration`, etc.

### API Versioning

#### Strategies
- **URL Versioning:** `/api/v1/users` (most common, most visible).
- **Header Versioning:** `Accept: application/vnd.myapp.v1+json` (cleaner URLs).
- **Query Parameter:** `?version=1` (least preferred).

#### Deprecation Policy
1. Announce deprecation in documentation and response headers.
2. Add `Deprecation` and `Sunset` headers.
3. Maintain deprecated versions for minimum 6 months.
4. Provide migration guide.
5. Monitor usage of deprecated endpoints.
6. Remove only when usage is near zero.

**Industry Standard:** Most companies maintain deprecated API versions for 6-12 months. Stripe maintains backwards compatibility for years with version pinning.

### API Security

#### Authentication
- **OAuth 2.0 / OIDC:** For user authentication.
- **API Keys:** For service-to-service (with rotation).
- **JWT:** Short-lived access tokens, refresh token rotation.
- **mTLS:** For high-security service-to-service.

#### Authorization
- **RBAC:** Role-based access control.
- **ABAC:** Attribute-based access control for fine-grained permissions.
- **Scope-based:** OAuth scopes for API-level permissions.

**Cross-Reference:** See [`security-engineering`](`security-engineering`) for detailed auth/authz patterns.

#### Rate Limiting
- **Per-user:** Based on authenticated user ID.
- **Per-IP:** For unauthenticated endpoints.
- **Per-endpoint:** Different limits for different endpoints.
- **Headers:** Return `X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`.
- **Response:** `429 Too Many Requests` with `Retry-After`.

**Industry Benchmarks:**
- GitHub API: 5,000 requests/hour (authenticated), 60/hour (unauthenticated)
- Twitter API: 300 requests/15min window (user context)
- Stripe API: 100 requests/second in production
- Cloudflare: 1,200 requests/5min for free tier

#### Input Validation
- **Schema validation:** Validate at the boundary (Zod, Joi, class-validator).
- **Content-Type validation:** Reject unexpected content types.
- **Request size limits:** Enforce body size limits.
- **SQL injection prevention:** Parameterized queries only.

### API Documentation

#### OpenAPI (Swagger)
- **Version:** 3.1+.
- **Include:** All endpoints, request/response schemas, examples, error responses.
- **Security schemes:** Document auth methods.
- **Servers:** List all environments.
- **Tags:** Group endpoints by resource.

#### Documentation Tools
- **Swagger UI:** Interactive API documentation.
- **Redoc:** Clean, readable documentation.
- **Postman Collections:** For testing and sharing.
- **GraphQL Playground / Apollo Studio:** For GraphQL APIs.

**Cross-Reference:** See [`technical-writing`](`technical-writing`) for API documentation best practices.

### API Gateway

#### Responsibilities
- **Routing:** Route requests to backend services.
- **Authentication:** Verify tokens, API keys.
- **Rate Limiting:** Enforce rate limits.
- **Caching:** Cache responses.
- **Logging:** Request/response logging.
- **Transformation:** Request/response transformation.
- **Circuit Breaking:** Prevent cascading failures.

**Cross-Reference:** See [`cloud-architecture`](`cloud-architecture`) for gateway architecture patterns.

#### Tools
- **AWS API Gateway:** Managed, integrates with Lambda.
- **Kong:** Open-source, plugin-based.
- **Apollo Federation:** For GraphQL federation.
- **Envoy:** Service mesh with gateway capabilities.

---

## 🚫 Anti-Patterns

### 1. The "God Endpoint"
**Problem:** Single endpoint that does everything based on parameters.
`
❌ POST /api/data?action=create&type=user
`
**Why Wrong:** Violates REST principles, makes caching impossible, unclear semantics.
**Solution:** Use proper resource-based endpoints with HTTP methods.

### 2. Chatty APIs
**Problem:** Requiring multiple round trips to fetch related data.
`
❌ GET /users/{id}        → User data
   GET /orders?user={id}  → User's orders (separate call)
   GET /orders/{id}/items → Order items (N calls)
`
**Why Wrong:** Network overhead, latency, poor mobile performance.
**Solution:** Use nested resources, GraphQL, or include parameters (`?include=orders`).

### 3. Breaking Changes Without Versioning
**Problem:** Modifying response structure without version bump.
**Why Wrong:** Breaks existing clients, destroys developer trust.
**Solution:** Always version, use additive changes, deprecate gracefully.

### 4. Ignoring HTTP Semantics
`
❌ POST /api/users/delete/{id}    # Should be DELETE
❌ GET /api/orders/create          # Should be POST
❌ POST /api/search                # Should be GET
`
**Why Wrong:** Breaks caching, breaks idempotency, confuses clients.
**Solution:** Use correct HTTP methods per REST semantics.

### 5. Returning 200 for Errors
`json
❌ HTTP 200 OK
{
  "success": false,
  "error": "User not found"
}
`
**Why Wrong:** Clients can't use standard HTTP error handling, breaks monitoring.
**Solution:** Use proper status codes (404, 400, 500, etc.).

### 6. Unbounded Responses
**Problem:** Returning entire datasets without pagination.
**Why Wrong:** Memory exhaustion, timeout, poor performance.
**Solution:** Always paginate collections, enforce max limits.

### 7. Overfetching/Underfetching
**Problem:** Returning too much data or requiring multiple calls.
**Why Wrong:** Bandwidth waste, latency, poor mobile performance.
**Solution:** Use field selection, GraphQL, or optimize REST endpoints.

### 8. No Rate Limiting
**Problem:** Allowing unlimited requests.
**Why Wrong:** Vulnerability to abuse, DDoS, resource exhaustion.
**Solution:** Always implement rate limiting, even for internal APIs.

### 9. Inconsistent Naming
`
❌ GET /api/users          # Snake case
   GET /api/orderHistory   # Camel case
   GET /api/UserProfiles   # Pascal case
`
**Why Wrong:** Confusing, error-prone, unprofessional.
**Solution:** Pick one convention (kebab-case for URLs) and stick to it.

### 10. Premature Optimization
**Problem:** Adding complexity (GraphQL federation, event sourcing) before needed.
**Why Wrong:** Overengineering, maintenance burden, slower development.
**Solution:** Start simple (REST), evolve based on real requirements.

---

## 🎯 Decision Framework: REST vs GraphQL vs gRPC

`
                    START: Need to design API
                              |
                              v
                    ┌─────────────────────┐
                    │  Who are the        │
                    │  consumers?         │
                    └─────────────────────┘
                              |
              ┌───────────────┼───────────────┐
              v               v               v
        ┌─────────┐    ┌──────────┐    ┌──────────┐
        │ Public  │    │ Mobile   │    │ Internal │
        │ Web API │    │ Clients  │    │ Service  │
        └─────────┘    └──────────┘    └──────────┘
              |               |               |
              v               v               v
        ┌─────────┐    ┌──────────┐    ┌──────────┐
        │  REST   │    │ GraphQL  │    │  gRPC    │
        │         │    │ or REST  │    │          │
        └─────────┘    └──────────┘    └──────────┘
              |               |               |
              v               v               v
    ┌────────────────┐ ┌─────────────┐ ┌────────────┐
    │ Simple CRUD?   │ │ Complex     │ │ High       │
    │ Standard ops?  │ │ data needs? │ │ throughput?│
    │ Good caching?  │ │ Many views? │ │ Streaming? │
    └────────────────┘ └─────────────┘ └────────────┘

Decision Matrix:

┌──────────────┬──────────┬──────────┬──────────┐
│ Requirement  │   REST   │ GraphQL  │  gRPC    │
├──────────────┼──────────┼──────────┼──────────┤
│ Public API   │   ⭐⭐⭐   │   ⭐⭐    │    ⭐     │
│ Mobile       │   ⭐⭐    │   ⭐⭐⭐   │    ⭐     │
│ Web Apps     │   ⭐⭐⭐   │   ⭐⭐⭐   │    ⭐     │
│ Microservice │   ⭐⭐    │    ⭐     │   ⭐⭐⭐   │
│ Caching      │   ⭐⭐⭐   │    ⭐     │    ⭐     │
│ Performance  │   ⭐⭐    │    ⭐     │   ⭐⭐⭐   │
│ Flexibility  │   ⭐⭐    │   ⭐⭐⭐   │    ⭐     │
│ Simplicity   │   ⭐⭐⭐   │    ⭐     │   ⭐⭐    │
│ Type Safety  │    ⭐     │   ⭐⭐    │   ⭐⭐⭐   │
│ Streaming    │    ⭐     │    ⭐     │   ⭐⭐⭐   │
└──────────────┴──────────┴──────────┴──────────┘
`

### When to Choose REST
- ✅ Public-facing APIs with third-party consumers
- ✅ Simple CRUD operations
- ✅ HTTP caching is important
- ✅ Team is familiar with REST
- ✅ Browser-based access needed

### When to Choose GraphQL
- ✅ Mobile clients with bandwidth constraints
- ✅ Complex data fetching requirements
- ✅ Multiple client types with different data needs
- ✅ Rapid frontend iteration
- ✅ Strong typing and introspection needed

### When to Choose gRPC
- ✅ Internal microservice communication
- ✅ High throughput, low latency requirements
- ✅ Bidirectional streaming needed
- ✅ Strong contract enforcement
- ✅ Polyglot environments (code generation)

**Cross-Reference:** See [`system-design-architecture`](`system-design-architecture`) for architectural trade-offs.

---

## 🛠️ Tool Comparison Tables

### API Gateway Solutions

| Tool | Type | Best For | Pros | Cons | Latency |
|------|------|----------|------|------|---------|
| **AWS API Gateway** | Managed | AWS ecosystem | Fully managed, Lambda integration, auto-scaling | AWS lock-in, cold starts, cost at scale | ~10-50ms |
| **Kong** | Self-hosted | Flexibility, plugins | Open source, extensive plugins, multi-cloud | Requires operational expertise | ~1-5ms |
| **Envoy** | Self-hosted | Service mesh | High performance, observability, gRPC native | Complex configuration | <1ms |
| **Apollo Federation** | Managed/Self | GraphQL-specific | GraphQL-native, schema composition | GraphQL only, learning curve | ~5-20ms |
| **Apigee** | Managed | Enterprise | Analytics, monetization, strong governance | Expensive, complex | ~20-100ms |
| **Traefik** | Self-hosted | Containers, K8s | Dynamic config, Docker/K8s native, simple | Limited enterprise features | ~2-10ms |

**Industry Benchmark:** Target <10ms gateway overhead. Measure P50, P95, P99 latency.

### Documentation Tools

| Tool | Format | Features | Best For | Learning Curve |
|------|--------|----------|----------|----------------|
| **Swagger UI** | OpenAPI | Interactive, try-it-out | REST APIs, developer testing | Low |
| **Redoc** | OpenAPI | Clean UI, responsive | Public docs, readability | Low |
| **Postman** | Collections | Testing, environments, mocking | API development, team collaboration | Medium |
| **Apollo Studio** | GraphQL | Schema registry, analytics, tracing | GraphQL APIs, enterprise | Medium |
| **Stoplight** | OpenAPI | Design-first, mocking, validation | API design, governance | Medium |
| **ReadMe** | OpenAPI/Custom | Beautiful docs, guides, changelogs | Product-focused API docs | Low |
| **APIary** | API Blueprint | Mock servers, testing | Early-stage API design | Medium |

**Cross-Reference:** See [`technical-writing`](`technical-writing`) for documentation strategies.

### API Versioning Strategies

| Strategy | Format | Pros | Cons | Best For |
|----------|--------|------|------|----------|
| **URL Versioning** | `/api/v1/users` | Visible, cacheable, simple | URL pollution, not RESTful | Public APIs, clear breaking changes |
| **Header Versioning** | `Accept: application/vnd.api.v1+json` | Clean URLs, RESTful | Less visible, harder to test | Internal APIs, content negotiation |
| **Query Param** | `/api/users?version=1` | Easy to implement | Caching issues, not standard | Legacy systems, prototypes |
| **Custom Header** | `API-Version: 2026-06-22` | Date-based, Stripe-style | Requires header support | Continuous evolution APIs |
| **No Versioning** | Additive changes only | Simplest, no breaking changes | Limits evolution, tech debt | Stable, mature APIs |

**Industry Standard:** Stripe uses date-based versioning (`2026-06-22`), GitHub uses URL versioning (`/v3/`), most REST APIs use URL versioning for major versions.

---

## 📊 Industry Benchmarks

### API Latency Targets
| Percentile | Target | Good | Acceptable | Poor |
|------------|--------|------|------------|------|
| P50 (Median) | <50ms | <100ms | <200ms | >200ms |
| P95 | <200ms | <500ms | <1s | >1s |
| P99 | <500ms | <1s | <2s | >2s |

**Context:** These are total response times including gateway, backend, and database. Stripe API: P50 ~40ms, P99 ~400ms. GitHub API: P50 ~100ms.

### Rate Limits by API Type
| API Type | Free Tier | Paid Tier | Enterprise | Window |
|----------|-----------|-----------|------------|--------|
| Public REST | 100-1000/hour | 10k-100k/hour | 1M+/hour | Rolling |
| Internal Service | No limit | No limit | No limit | N/A |
| GraphQL | 1000 points/hour | 10k points/hour | Custom | Rolling |
| Webhooks | 5k events/hour | 50k events/hour | Custom | Sliding |

### Deprecation Timelines
| Industry | Min Notice | Typical Maintenance | Sunset Process |
|----------|-----------|---------------------|----------------|
| **SaaS/Cloud** | 6 months | 12 months | Warn → Docs → Headers → Removal |
| **Finance** | 12 months | 24 months | Regulatory compliance required |
| **Social/Consumer** | 3 months | 6 months | Fast-moving, clear migration path |
| **Enterprise** | 12 months | 18-36 months | Long migration cycles |

**Example:** Stripe maintains API versions indefinitely per account (pinned versions). Twitter retired API v1.0 with 12 months notice. Google deprecated Google+ API with 10 months notice.

### Response Payload Sizes
| Type | Target | Max Acceptable | Action at Limit |
|------|--------|----------------|-----------------|
| Single resource | <10KB | <100KB | Use field selection |
| Collection (1 page) | <100KB | <1MB | Reduce page size |
| Bulk export | 1-10MB | 100MB | Use streaming/chunking |

**Cross-Reference:** See [`cloud-architecture`](`cloud-architecture`) for caching and CDN strategies to reduce API load.

---

## ⛔ Prohibited Actions (WITH WHY)

| Action | Why Prohibited | Impact | Alternative |
|--------|----------------|--------|-------------|
| **Breaking changes without versioning** | Destroys client trust, breaks production apps | Critical | Version API, deprecate gracefully |
| **Returning 200 for errors** | Breaks HTTP semantics, monitoring, caching | High | Use proper status codes (400, 404, 500) |
| **No rate limiting** | Vulnerable to abuse, DDoS, cost overruns | Critical | Implement rate limiting at gateway |
| **Exposing internal IDs** | Security risk, couples API to DB schema | High | Use UUIDs or opaque identifiers |
| **No pagination** | Memory exhaustion, timeouts, poor UX | High | Always paginate, enforce max limits |
| **Verbs in REST URLs** | Violates REST principles, unclear semantics | Medium | Use HTTP methods, resource-based URLs |
| **Inconsistent naming** | Developer confusion, integration errors | Medium | Enforce style guide, use linters |
| **No authentication** | Security vulnerability, compliance issues | Critical | Default to auth required |
| **Ignoring idempotency** | Duplicate charges, data corruption | High | Use idempotency keys for non-idempotent ops |
| **Returning all fields** | Bandwidth waste, security risk, tight coupling | Medium | Use field selection, hide sensitive data |
| **No request validation** | Injection attacks, data corruption | Critical | Validate at API boundary |
| **Synchronous long operations** | Timeouts, poor UX, resource blocking | High | Use async/webhooks for >30s operations |
| **No CORS configuration** | Blocks browser clients, poor web API UX | Medium | Configure CORS properly |
| **Embedding business logic in API layer** | Tight coupling, hard to test, code duplication | High | Keep API thin, delegate to service layer |

**Cross-Reference:** See [`security-engineering`](`security-engineering`) for detailed security requirements.

---

## 👥 Senior vs Junior API Design

### Junior Developer Approach
`
❌ Thinks endpoint-first:
   "I need an endpoint to get user data"
   POST /getUserData

❌ Tightly coupled to UI:
   Creates endpoints per screen/feature

❌ No versioning strategy:
   "I'll add versioning later if needed"

❌ Inconsistent patterns:
   Each endpoint uses different response format

❌ No thought to evolution:
   "Users need these 5 fields today"
   (Breaks API when field 6 is needed)

❌ Ad-hoc error handling:
   Different error formats per endpoint

❌ No rate limiting:
   "We'll add it when we have scale problems"

❌ Synchronous everything:
   POST /generateReport waits 2 minutes
`

### Senior Developer Approach
`
✅ Thinks resource-first:
   "What are the domain resources?"
   GET /api/v1/users/{id}

✅ Decoupled from UI:
   Flexible endpoints that serve multiple clients

✅ Versioning from day one:
   /api/v1/ in first commit
   Deprecation policy documented

✅ Consistent patterns:
   All responses use same envelope:
   { "data": {...}, "meta": {...} }

✅ Designs for evolution:
   "What fields might we need in 2 years?"
   Additive changes, nullable fields

✅ Structured error handling:
   Consistent error schema with codes,
   trace IDs, field-level errors

✅ Rate limiting by default:
   Even in development, configured loosely

✅ Async for long operations:
   POST /reports → 202 Accepted
   Returns job ID, polls status
   Webhook on completion
`

### Key Differences

| Aspect | Junior | Senior |
|--------|--------|--------|
| **Planning** | Code first, fix later | Design first, implement once |
| **Consistency** | Per-endpoint decisions | System-wide standards |
| **Security** | Add when needed | Secure by default |
| **Documentation** | After implementation | Part of design process |
| **Testing** | Manual testing | Contract tests, integration tests |
| **Versioning** | Reactionary | Proactive, planned |
| **Error Handling** | String messages | Structured, actionable errors |
| **Performance** | Hope it's fast | Measure, optimize, set SLOs |

**Pro Tip:** The difference between junior and senior API design is **thinking about the future** (evolution, breaking changes, deprecation) from day one, not as an afterthought.

**Cross-Reference:** See [`qa-test-automation`](`qa-test-automation`) for API testing strategies.

---

## Standard Workflow

### Step 1: API Design
1. Define resources and relationships.
2. Design endpoints (URL, method, request/response).
3. Define error responses.
4. Document in OpenAPI/GraphQL schema.
5. Review with stakeholders.

### Step 2: Implementation
1. Implement handlers/resolvers.
2. Add validation middleware.
3. Add authentication/authorization.
4. Add rate limiting.
5. Add logging and tracing.

### Step 3: Documentation
1. Generate OpenAPI/GraphQL schema from code.
2. Add examples and descriptions.
3. Publish documentation.
4. Create Postman collection.

### Step 4: Testing
1. Write contract tests.
2. Write integration tests.
3. Test error scenarios.
4. Test rate limiting.
5. Test authentication/authorization.

**Cross-Reference:** See [`qa-test-automation`](`qa-test-automation`) for comprehensive API testing strategies.

---

## Definition of Done

An API design task is complete when:
1. ✅ API follows consistent naming and response patterns.
2. ✅ All endpoints are documented (OpenAPI/GraphQL).
3. ✅ Authentication and authorization are implemented.
4. ✅ Rate limiting is configured.
5. ✅ Input validation is in place.
6. ✅ Error responses are consistent and informative.
7. ✅ Pagination, filtering, sorting are implemented.
8. ✅ Versioning strategy is defined.
9. ✅ Tests cover all endpoints and error scenarios.
10. ✅ API documentation is published.
11. ✅ Performance benchmarks meet targets (P95 <200ms).
12. ✅ Security review completed (auth, rate limits, validation).
13. ✅ Deprecation policy documented.

---

## 📚 Quick Reference

### REST Endpoint Checklist
`
□ Resource-based URL (plural nouns)
□ Proper HTTP method (GET/POST/PUT/PATCH/DELETE)
□ Versioned (/api/v1/)
□ Returns proper status codes
□ Consistent response envelope
□ Pagination (cursor or offset)
□ Filtering/sorting support
□ Authentication required
□ Rate limited
□ Documented in OpenAPI
□ Has integration tests
`

### GraphQL Schema Checklist
`
□ Schema-first design
□ Non-null (!) where appropriate
□ Relay-style pagination (Connection)
□ Input types for mutations
□ Error handling in payload
□ camelCase fields, PascalCase types
□ DataLoader for N+1 prevention
□ Query complexity limits
□ Persisted queries (production)
□ Documented with descriptions
`

### gRPC Proto Checklist
`
□ Package versioned (api.v1)
□ Field numbers never reused
□ Reserved fields marked
□ Well-Known Types used
□ Request/Response message pairs
□ Service methods documented
□ Backward compatibility maintained
□ Code generated for all languages
□ Streaming used appropriately
`

### Security Checklist
`
□ Authentication on all endpoints
□ Authorization checks per resource
□ Rate limiting (per user/IP)
□ Input validation (schema)
□ SQL injection prevention
□ XSS prevention
□ CORS configured
□ HTTPS only
□ API keys rotated
□ Audit logging
`

### Common HTTP Status Codes
`
2xx Success:
  200 OK            — Request succeeded
  201 Created       — Resource created
  204 No Content    — Success, no body

4xx Client Error:
  400 Bad Request   — Invalid syntax/validation
  401 Unauthorized  — Not authenticated
  403 Forbidden     — Not authorized
  404 Not Found     — Resource doesn't exist
  409 Conflict      — State conflict
  422 Unprocessable — Semantic error
  429 Too Many      — Rate limited

5xx Server Error:
  500 Internal      — Server error
  502 Bad Gateway   — Upstream error
  503 Unavailable   — Service down
  504 Timeout       — Upstream timeout
`

### Rate Limit Response Headers
`
X-RateLimit-Limit: 5000
X-RateLimit-Remaining: 4999
X-RateLimit-Reset: 1640995200
Retry-After: 3600
`

### Deprecation Headers
`
Deprecation: true
Sunset: Wed, 01 Jan 2027 00:00:00 GMT
Link: </api/v2/users>; rel="successor-version"
`

---

## Token Efficiency Notes

This skill uses:
- ✅ Tables for comparisons (reduces prose)
- ✅ Code examples (precise, scannable)
- ✅ Bullet lists (structured, skimmable)
- ✅ ASCII diagrams (visual, compact)
- ✅ Cross-references (avoid duplication)
- ✅ Checkboxes (actionable, clear)

Estimated token efficiency: **High** (~3,500 tokens for comprehensive API design guidance)

---

**Last Updated:** 2026-06-22 | **Version:** 2.0 | **Skill Type:** API Design & Management

