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.