Why API Design Matters
An API is the interface between systems – and between teams. Poor API design leads to:
- Confused frontend developers
- Inconsistent behavior
- Difficult maintenance
- Integration problems with third parties
Good API design, on the other hand, makes integration intuitive and reduces support effort.
The Basic Principles
1. Think Resource-Oriented
REST revolves around resources, not actions. A resource is a thing (user, product, order), not an action.
# Wrong - action-oriented
POST /createUser
GET /getUserById?id=123
POST /deleteUser
# Right - resource-oriented
POST /users
GET /users/123
DELETE /users/1232. Use HTTP Methods Correctly
| Method | Purpose | Example |
|--------|---------|---------|
| GET | Read | GET /users/123 |
| POST | Create | POST /users |
| PUT | Replace completely | PUT /users/123 |
| PATCH | Partial update | PATCH /users/123 |
| DELETE | Delete | DELETE /users/123 |
// GET - Retrieve data (no side effects!)
GET /products?category=electronics&limit=10
// POST - Create new resource
POST /orders
Body: { "productId": 123, "quantity": 2 }
// PATCH - Partial update
PATCH /users/123
Body: { "email": "new@example.com" }
// DELETE - Delete resource
DELETE /orders/4563. Meaningful URL Structure
# Plural for collections
GET /users # All users
GET /users/123 # One user
# Nested resources
GET /users/123/orders # User's orders
GET /users/123/orders/456 # A specific order
# Maximum 2-3 levels deep
GET /users/123/orders/456/items # Still OK
GET /users/123/orders/456/items/789/details # Too deep!Using HTTP Status Codes Correctly
Success (2xx)
200 OK - Successful GET, PUT, PATCH request
201 Created - Resource successfully created (POST)
204 No Content - Success without response body (DELETE)Client Errors (4xx)
400 Bad Request - Invalid request (validation error)
401 Unauthorized - Not authenticated
403 Forbidden - Authenticated but no permission
404 Not Found - Resource doesn't exist
409 Conflict - Conflict (e.g., duplicate)
422 Unprocessable - Validation failedServer Errors (5xx)
500 Internal Error - Unexpected server error
503 Service Unavailable - Server temporarily unavailableResponse Structure
Consistent Envelope
// Success
{
"data": {
"id": 123,
"name": "Max Mustermann",
"email": "max@example.com"
},
"meta": {
"timestamp": "2024-01-15T10:30:00Z"
}
}
// Error
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Validation failed",
"details": [
{ "field": "email", "message": "Invalid email format" }
]
}
}Pagination
GET /users?page=2&limit=20
{
"data": [...],
"meta": {
"page": 2,
"limit": 20,
"total": 150,
"totalPages": 8
},
"links": {
"first": "/users?page=1&limit=20",
"prev": "/users?page=1&limit=20",
"next": "/users?page=3&limit=20",
"last": "/users?page=8&limit=20"
}
}Filtering, Sorting, Search
Filtering
# Simple filters as query parameters
GET /products?category=electronics
GET /products?minPrice=100&maxPrice=500
GET /products?inStock=true
# Multiple values
GET /products?category=electronics,booksSorting
# Ascending
GET /products?sort=price
# Descending (minus prefix)
GET /products?sort=-price
# Multiple fields
GET /products?sort=-createdAt,nameSearch
# Simple search
GET /products?search=laptop
# Field-specific search
GET /products?name_contains=Pro&brand=AppleVersioning
URL Versioning (recommended)
GET /v1/users
GET /v2/usersAdvantages:
- Clearly visible
- Easy to test
- Cache-friendly
Header Versioning
GET /users
Accept: application/vnd.api+json;version=2Authentication
Bearer Token (JWT)
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...API Keys
# In header (preferred)
X-API-Key: your-api-key
# Or as query parameter (less secure)
GET /users?api_key=your-api-keyPractical Example
A complete User API:
// GET /v1/users - List all users
// Query: ?page=1&limit=20&sort=-createdAt&role=admin
{
"data": [
{ "id": 1, "name": "Max", "email": "max@example.com", "role": "admin" },
{ "id": 2, "name": "Anna", "email": "anna@example.com", "role": "admin" }
],
"meta": { "page": 1, "limit": 20, "total": 2 }
}
// GET /v1/users/1 - Single user
{
"data": {
"id": 1,
"name": "Max",
"email": "max@example.com",
"role": "admin",
"createdAt": "2024-01-01T00:00:00Z"
}
}
// POST /v1/users - Create user
// Request:
{ "name": "New", "email": "new@example.com", "password": "secret123" }
// Response (201 Created):
{
"data": { "id": 3, "name": "New", "email": "new@example.com" }
}
// PATCH /v1/users/1 - Update user
// Request:
{ "name": "Max Updated" }
// Response (200 OK):
{
"data": { "id": 1, "name": "Max Updated", "email": "max@example.com" }
}
// DELETE /v1/users/1 - Delete user
// Response: 204 No ContentChecklist for Good API Design
- [ ] Resource-oriented URLs (nouns, not verbs)
- [ ] Correct HTTP methods (GET, POST, PUT, PATCH, DELETE)
- [ ] Meaningful HTTP status codes
- [ ] Consistent response structure
- [ ] Pagination for lists
- [ ] Filtering and sorting
- [ ] Versioning
- [ ] Authentication
- [ ] Rate limiting
- [ ] Documentation (OpenAPI/Swagger)
Conclusion
Good API design isn't rocket science, but it requires discipline. The most important rules:
1. Consistency: If /users works this way, /products should work the same
2. Predictability: Developers should be able to guess how an endpoint works
3. Documentation: Even the best API needs good docs