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
Best for admin/reporting UIs where users need direct page jumps and total page count. Weaker for real-time feeds where inserts can shift results.
Cursor-Based
GET /items?cursor=abc123&limit=20
Best for timelines and infinite scroll. More stable and efficient at scale, but does not support arbitrary “jump to page N” well.
✅ Recommended: Use cursor-based for infinite scroll, offset for page numbers.
Deep dive: Pagination: Offset vs Cursor-Based
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
Header Versioning
Accept: application/vnd.api+json; version=2
Query Parameter
/api/users?version=2
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.