A well-designed API is a joy to use. A poorly designed one? It’s a source of endless frustration, bugs, and wasted developer hours. Here are the most common API design mistakes I’ve encountered—and how to avoid them.
Mistake 1: Inconsistent Naming Conventions
Nothing frustrates developers more than an API that can’t decide on a naming convention.
# The nightmare API
GET /getUsers
GET /fetch-products
GET /Order_history
POST /createNewUser
POST /add_productThe fix: Pick a convention and stick to it religiously.
# Consistent REST API
GET /users
GET /products
GET /orders
POST /users
POST /productsUse:
- Plural nouns for resources (
/users, not/user) - Kebab-case for multi-word resources (
/user-profiles) - HTTP verbs for actions, not URL verbs
Mistake 2: Ignoring HTTP Status Codes
Returning 200 OK for everything, including errors, is a cardinal sin.
// Bad - Returns 200 with error in body
{
"success": false,
"error": "User not found"
}
// Good - Returns 404 with helpful message
// HTTP 404 Not Found
{
"error": {
"code": "USER_NOT_FOUND",
"message": "No user exists with ID 12345"
}
}Use status codes semantically:
- 2xx - Success
- 4xx - Client errors (bad request, unauthorized, not found)
- 5xx - Server errors
Mistake 3: Poor Error Messages
Generic error messages waste everyone’s time.
// Bad
{ "error": "Invalid request" }
// Good
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Request validation failed",
"details": [
{
"field": "email",
"issue": "Must be a valid email address",
"received": "not-an-email"
}
]
}
}Good error messages include:
- A machine-readable error code
- A human-readable message
- Details about what went wrong
- Hints about how to fix it
Mistake 4: Not Versioning Your API
APIs evolve. Breaking changes without versioning break your consumers’ applications.
# Version in URL (most common)
GET /v1/users
GET /v2/users
# Version in header (cleaner URLs)
GET /users
Accept: application/vnd.myapi.v1+jsonStart with v1 from day one. It costs nothing and saves future pain.
Mistake 5: Returning Too Much (or Too Little) Data
Over-fetching wastes bandwidth; under-fetching forces multiple requests.
// Over-fetching - returns everything
GET /users/123
{
"id": 123,
"name": "John",
"email": "[email protected]",
"password_hash": "...", // Security issue!
"internal_notes": "...",
"created_at": "...",
"updated_at": "...",
// ... 50 more fields
}
// Better - return sensible defaults with field selection
GET /users/123?fields=id,name,email
{
"id": 123,
"name": "John",
"email": "[email protected]"
}Consider:
- Field selection for customizing responses
- Pagination for collections
- Expansion for related resources (
?expand=orders)
Mistake 6: Ignoring Pagination
Returning 10,000 records in one response is never okay.
// Good pagination response
{
"data": [...],
"pagination": {
"page": 1,
"per_page": 20,
"total_pages": 50,
"total_items": 1000
},
"links": {
"self": "/users?page=1",
"next": "/users?page=2",
"last": "/users?page=50"
}
}Pagination strategies:
- Offset-based - Simple but can skip items if data changes
- Cursor-based - More reliable for real-time data
- Keyset - Best for large datasets
Mistake 7: No Rate Limiting
Without rate limiting, one misbehaving client can bring down your entire API.
HTTP/1.1 200 OK
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 999
X-RateLimit-Reset: 1640995200
HTTP/1.1 429 Too Many Requests
Retry-After: 60
{
"error": {
"code": "RATE_LIMITED",
"message": "Rate limit exceeded. Try again in 60 seconds."
}
}Rate limiting protects:
- Your infrastructure from abuse
- Fair usage across all clients
- Your API from accidental infinite loops
Bonus: Document Everything
The best-designed API is useless if no one knows how to use it.
Use OpenAPI/Swagger to:
- Generate interactive documentation
- Enable client SDK generation
- Validate requests and responses
- Keep docs in sync with code
Conclusion
Great API design is about empathy for the developers who will use your API. Every decision should make their lives easier, not harder.
Remember:
- Consistency is king
- Errors are features, not afterthoughts
- Plan for change from the start
- When in doubt, follow REST conventions
Your API is a product. Treat it like one.
What API design patterns have you found most valuable? What mistakes would you add to this list?