API Design

Designing frontend-friendly APIs: pagination, error handling, versioning, and type safety.

Quick Navigation: Pagination Error Handling Versioning Type Safety

Pagination Strategies

Offset-Based (Page Numbers)

GET /items?page=2&limit=20

Pros

  • ✓ Simple to implement
  • ✓ Jump to any page
  • ✓ Shows total count

Cons

  • ✗ Slow on large datasets (OFFSET)
  • ✗ Inconsistent with real-time data
  • ✗ Items can be skipped/duplicated

Cursor-Based

GET /items?cursor=abc123&limit=20

Pros

  • ✓ Fast on large datasets
  • ✓ Consistent with real-time data
  • ✓ No duplicate/missing items

Cons

  • ✗ Can't jump to arbitrary page
  • ✗ More complex implementation
  • ✗ No total count

Recommended: Use cursor-based for infinite scroll, offset for page numbers.

Error Response Design

Good Error Response Structure

{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Invalid email format",
    "details": [
      {
        "field": "email",
        "message": "Must be a valid email address"
      }
    ]
  }
}

HTTP Status Codes

  • 2xx - Success (200 OK, 201 Created, 204 No Content)
  • 4xx - Client errors (400 Bad Request, 401 Unauthorized, 404 Not Found)
  • 5xx - Server errors (500 Internal, 503 Service Unavailable)

Frontend Error Handling

  • 400: Show validation errors inline
  • 401: Redirect to login
  • 403: Show "access denied" message
  • 404: Show not found page
  • 429: Rate limited, show retry message
  • 500: Generic error, offer retry

API Versioning

URL Path Versioning

/api/v1/users, /api/v2/users

Pros: Explicit, easy to understand, cacheable
Cons: URL clutter, multiple endpoints to maintain

Header Versioning

Accept: application/vnd.api+json; version=2

Pros: Clean URLs, follows REST
Cons: Harder to test, less visible

Query Parameter

/api/users?version=2

Pros: Easy to add, optional
Cons: Pollutes query string, caching issues

Type Safety

OpenAPI / Swagger

Define API schema, generate TypeScript types.

Pros

  • ✓ Language agnostic
  • ✓ Auto-generated documentation
  • ✓ Client SDK generation

Cons

  • ✗ Can drift from implementation
  • ✗ Verbose schema files

tRPC

End-to-end TypeScript type safety without code generation.

Pros

  • ✓ No code generation needed
  • ✓ Types always in sync
  • ✓ Great DX

Cons

  • ✗ TypeScript only
  • ✗ Monorepo works best
  • ✗ Not REST (RPC)

GraphQL

Strong typing from schema, excellent tooling.

Pros

  • ✓ Schema is the contract
  • ✓ Excellent code generation
  • ✓ Self-documenting

Cons

  • ✗ Steeper learning curve
  • ✗ Overhead for simple APIs

Best Practices

  • 1.Use cursor pagination for infinite scroll, offset for page numbers.
  • 2.Return meaningful errors with error codes, messages, and field details.
  • 3.Version from day one. Easier than adding later.
  • 4.Generate types from schema. Don't manually sync types.
  • 5.Consider tRPC for full-stack TypeScript projects.