API Design
Principles and patterns for designing robust, scalable APIs.
REST Fundamentals
REST (Representational State Transfer) is an architectural style built on top of HTTP. A well-designed REST API maps resources to URLs and uses HTTP methods to express operations:
- GET — read a resource (idempotent)
- POST — create a new resource
- PUT — replace a resource entirely (idempotent)
- PATCH — partially update a resource
- DELETE — remove a resource (idempotent)
Resources should be nouns (/users/123), not verbs (/getUser). Use plural nouns for collections.
Status Codes
Use HTTP status codes meaningfully:
| Range | Meaning | Examples |
|---|---|---|
| 2xx | Success | 200 OK, 201 Created, 204 No Content |
| 3xx | Redirection | 301 Moved, 304 Not Modified |
| 4xx | Client error | 400 Bad Request, 401 Unauthorized, 404 Not Found, 429 Too Many Requests |
| 5xx | Server error | 500 Internal, 502 Bad Gateway, 503 Unavailable |
Pagination
For large collections, always paginate. Common approaches:
- Offset-based:
?page=2&limit=20— simple but skips are expensive on large datasets - Cursor-based:
?cursor=abc123&limit=20— more efficient, uses an opaque token pointing to the last item
Versioning Strategies
APIs evolve, and breaking changes are inevitable. Plan for versioning from day one:
- URL path:
/v1/users— most common, very explicit - Query parameter:
/users?version=1— flexible but easy to miss - Header:
Accept: application/vnd.myapi.v1+json— cleanest separation but harder to test in browsers
Rate Limiting
Protect your API with rate limiting. Include rate limit headers in responses:
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 95
X-RateLimit-Reset: 1625097600
Common algorithms: token bucket (smooth, allows bursts), sliding window (precise), and fixed window (simplest).
Authentication
- API Keys — simple, good for server-to-server. Pass in headers, not URLs.
- OAuth 2.0 — standard for delegated access. Use authorization code flow for web apps.
- JWT — self-contained tokens with claims. Verify signature server-side. Set short expiration times.
Error Responses
Return consistent, structured error bodies:
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Email is required",
"details": [
{ "field": "email", "issue": "must not be empty" }
]
}
}