*API Design

September 15, 2025

Principles

  • Explicit contracts (OpenAPI/Protobuf). Minimize breaking changes.
  • Errors: consistent codes and schemas; correlation IDs.
  • Pagination: cursor > offset; HATEOAS optional.
  • Idempotency: keys for sensitive operations.

Versioning

  • URI: /v1/v2 (simple but coarse).
  • Header: Accept: application/vnd.company.v2+json (finer control).
  • GraphQL: additive evolution; deprecate before removal.

Error model

{
  "error": {
    "code": "INVALID_INPUT",
    "message": "email is required",
    "correlationId": "c-123"
  }
}

Pagination (cursor)

# language-http
GET /users?limit=50&cursor=eyJpZCI6IjEyMyIsImNyZWF0ZWRBdCI6IjIwMjUtMDktMTUiLjk5OSJ9
-- language-sql
SELECT * FROM users
WHERE (created_at, id) < ($createdAt, $id)
ORDER BY created_at DESC, id DESC
LIMIT 50;

Idempotency example

# language-http
POST /orders
Idempotency-Key: 2b0f...

Contract first

# language-yaml
openapi: 3.1.0
info: { title: Users API, version: 1.0.0 }
paths:
  /users/{id}:
    get:
      parameters:
        - { name: id, in: path, required: true, schema: { type: string } }
      responses:
        '200': { description: OK }

Consistency and naming

  • Nouns for resources, verbs for actions; kebab‑case paths, lower_snake_case fields or follow platform norms.
  • Avoid mixing plurals/singular; prefer /users/{id}/posts over custom verbs.

Security

  • OAuth2 scopes, mTLS where needed, rate limits per client.

Observability

  • Correlation IDs (traceparent), structured logs, SLOs per endpoint.

Analogy

An API is your product’s contract. Clarity and stability build trust; surprises and inconsistency break it.

FAQ

  • Do I need HATEOAS? Not for most APIs; links can help discoverability but keep it simple.
  • Offset pagination OK? For small lists yes; use cursors for large/real‑time lists.