Files
asepharyana-hub-guide/skills/api-design/SKILL.md
T
asepharyana d324c1b3c0 fix: add MANDATORY prefix to all 8 core skill descriptions
- Add MANDATORY — always active to engineering-principles, testing,
  error-handling, security, git-workflow, api-design
- Update hook output with explicit EXTREMELY_IMPORTANT instruction
- Skills now explicitly state they apply to every session
2026-07-26 12:00:04 +07:00

4.9 KiB

name, description
name description
api-design MANDATORY — always active. Best practices for API design — REST, GraphQL, RPC conventions, versioning, status codes, pagination, error responses, and documentation. Use when designing new endpoints, reviewing API contracts. Detects from code context and project files — not dependent on specific language keywords."

API Design

REST Conventions

URL Structure

POST   /resources          # Create
GET    /resources          # List (with query params for filtering/pagination)
GET    /resources/:id     # Read one
PUT    /resources/:id     # Full replace
PATCH  /resources/:id     # Partial update
DELETE /resources/:id     # Delete
GET    /resources/:id/related  # Nested resource
  • Plural nouns, not verbs: /users not /getUsers
  • Kebab-case for multi-word: /order-items not /orderItems
  • No file extensions: /users not /users.json
  • Version in URL or Accept header: /v1/users or Accept: application/vnd.api.v1+json

Response Format

// Success
HTTP 200
{ "data": { "id": "1", "name": "Alice", "email": "alice@example.com" } }

// List with pagination
HTTP 200
{
  "data": [ ... ],
  "meta": { "total": 100, "page": 1, "per_page": 20 },
  "links": { "self": "?page=1", "next": "?page=2", "prev": null }
}

// Error
HTTP 422
{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Email is required",
    "details": [{ "field": "email", "issue": "required" }]
  }
}

Status Codes — Use Precisely

Code When
200 Success (GET, PUT, PATCH)
201 Created (POST)
204 No Content (DELETE success)
301 Moved permanently (redirect)
400 Bad request (malformed input)
401 Unauthenticated (missing/invalid credentials)
403 Forbidden (authenticated but not authorized)
404 Not found
409 Conflict (duplicate, version mismatch)
422 Unprocessable entity (validation failure)
429 Too many requests (rate limit)
500 Internal server error (unhandled, doesn't fit above)
502/503 Upstream / service unavailable

Never return 200 with an error body. Never return 500 for validation errors.

Pagination

// Cursor-based (preferred for live data)
GET /items?cursor=abc123&limit=20
Response: { data: [], meta: { next_cursor: "xyz789", has_more: true } }

// Page-based (fine for stable datasets)
GET /items?page=1&per_page=20
Response: { data: [], meta: { total: 100, page: 1, per_page: 20 } }

Filtering, Sorting, Fields

GET /items?filter[status]=active&filter[created_at]=2024-01-01..2024-12-31
GET /items?sort=-created_at,name       // -prefix = descending
GET /items?fields=id,name,status       // sparse fieldset (performance)

GraphQL

  • Schema-first — design the schema before implementing resolvers.
  • N+1 problem — use DataLoader for batch loading.
  • Expose a single endpoint — no per-resource URLs.
  • Mutations return the mutated object — always include the affected type.
  • Paginate connections — use the Relay Connection spec (edges { node }).

API Versioning

  • URL versioning (/v1/users) — simplest, most explicit.
  • Header versioning (Accept: application/vnd.api.v2+json) — cleaner URL.
  • Never remove fields — deprecate first, remove in next major version.
  • Document breaking changes — changelog, migration guide, sunset header (Sunset: Sat, 1 Nov 2025 00:00:00 GMT).

API Documentation

  • OpenAPI 3.x for REST APIs. Generate from code (Hono Zod OpenAPI, FastAPI).
  • Include in docs: endpoint, method, params, request body schema, response schema, error codes, auth requirement, example requests/responses.
  • Keep a changelog — versioned alongside the API spec.

Other API Styles

gRPC

  • Use for internal service-to-service communication.
  • Proto3, HTTP/2, streaming support.
  • Better than REST for high-throughput, low-latency internal APIs.

RPC-style (tRPC, Elysia Eden)

  • No URL routing — direct function calls from client.
  • Type-safe end-to-end. Preferred for full-stack TypeScript.
  • Trade-off: couples client and server types.

Idempotency

  • PUT and DELETE are idempotent — same request multiple times = same result.
  • POST is not idempotent — provide Idempotency-Key header for payment-like operations.
  • PATCH can be idempotent if you send the full delta (not increments).

API Anti-patterns

  • Leaking internal implementation — exposing DB fields, raw SQL, internal IDs
  • Inconsistent error format — sometimes {error}, sometimes {message}, sometimes {errors}[]
  • Over-fetching/n+1 — returning more data than needed, making N+1 queries
  • No rate limit info — no Retry-After, no X-RateLimit-* headers
  • Version in body/api?version=2, version field in JSON body
  • 200 for errorsHTTP 200 {"error": "not found"} should be HTTP 404