RESTful API Design Patterns for Production
APIs are contracts. Once published, they're difficult to change without breaking clients. Here are patterns that help you get the design right from the start.
Resource Naming
Use nouns, not verbs. Resources are things, not actions:
# Good
GET /api/v1/orders
GET /api/v1/orders/123
POST /api/v1/orders
# Bad
GET /api/v1/getOrders
POST /api/v1/createOrder
Versioning Strategy
Always version your APIs from day one:
# URL versioning (most common)
/api/v1/orders
/api/v2/orders
# Header versioning (cleaner URLs)
Accept: application/vnd.company.v1+json
I prefer URL versioning for its discoverability, even if it's less "pure."
Consistent Response Format
Define a standard envelope for all responses:
{
"data": { ... },
"meta": {
"page": 1,
"per_page": 20,
"total": 150
},
"links": {
"self": "/api/v1/orders?page=1",
"next": "/api/v1/orders?page=2"
}
}
Error Handling
Errors should be informative and actionable:
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Request validation failed",
"details": [
{
"field": "email",
"message": "must be a valid email address"
}
]
}
}
Filtering and Pagination
Use query parameters consistently:
# Filtering
GET /api/v1/orders?status=pending&customer_id=123
# Sorting
GET /api/v1/orders?sort=-created_at,status
# Pagination (cursor-based for large datasets)
GET /api/v1/orders?cursor=eyJpZCI6MTAwfQ==
Rate Limiting Headers
Always communicate rate limits in response headers:
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 998
X-RateLimit-Reset: 1704067200
Idempotency
Support idempotency keys for critical operations:
POST /api/v1/payments
Idempotency-Key: abc-123-unique-key
# Same key returns same result without re-processing
These patterns aren't revolutionary, but applying them consistently separates amateur APIs from professional ones.