REST API Design Rules Reference
Core Principles
1. Resources, Not Actions
REST APIs should focus on resources (nouns) rather than actions (verbs). The HTTP methods provide the actions.
✅ Good:
GET /users # Get all users
GET /users/123 # Get user 123
POST /users # Create new user
PUT /users/123 # Update user 123
DELETE /users/123 # Delete user 123
❌ Bad:
POST /getUsers
POST /createUser
POST /updateUser/123
POST /deleteUser/123
2. Hierarchical Resource Structure
Use hierarchical URLs to represent resource relationships:
/users/123/orders/456/items/789
But avoid excessive nesting (max 3-4 levels):
❌ Too deep: /companies/123/departments/456/teams/789/members/012/tasks/345
✅ Better: /tasks/345?member=012&team=789
Resource Naming Conventions
URLs Should Use Kebab-Case
✅ Good:
/user-profiles
/order-items
/shipping-addresses
❌ Bad:
/userProfiles
/user_profiles
/orderItems
Collections vs Individual Resources
Collection: /users
Individual: /users/123
Sub-resource: /users/123/orders
Pluralization Rules
- Use plural nouns for collections:
/users,/orders - Use singular nouns for single resources:
/user-profile,/current-session - Be consistent throughout your API
HTTP Methods Usage
GET - Safe and Idempotent
- Purpose: Retrieve data
- Safe: No side effects
- Idempotent: Multiple calls return same result
- Request Body: Should not have one
- Cacheable: Yes
GET /users/123
GET /users?status=active&limit=10
POST - Not Idempotent
- Purpose: Create resources, non-idempotent operations
- Safe: No
- Idempotent: No
- Request Body: Usually required
- Cacheable: Generally no
POST /users # Create new user
POST /users/123/activate # Activate user (action)
PUT - Idempotent
- Purpose: Create or completely replace a resource
- Safe: No
- Idempotent: Yes
- Request Body: Required (complete resource)
- Cacheable: No
PUT /users/123 # Replace entire user resource
PATCH - Partial Update
- Purpose: Partially update a resource
- Safe: No
- Idempotent: Not necessarily
- Request Body: Required (partial resource)
- Cacheable: No
PATCH /users/123 # Update only specified fields
DELETE - Idempotent
- Purpose: Remove a resource
- Safe: No
- Idempotent: Yes (same result if called multiple times)
- Request Body: Usually not needed
- Cacheable: No
DELETE /users/123
Status Codes
Success Codes (2xx)
- 200 OK: Standard success response
- 201 Created: Resource created successfully (POST)
- 202 Accepted: Request accepted for processing (async)
- 204 No Content: Success with no response body (DELETE, PUT)
Redirection Codes (3xx)
- 301 Moved Permanently: Resource permanently moved
- 302 Found: Temporary redirect
- 304 Not Modified: Use cached version
Client Error Codes (4xx)
- 400 Bad Request: Invalid request syntax or data
- 401 Unauthorized: Authentication required
- 403 Forbidden: Access denied (user authenticated but not authorized)
- 404 Not Found: Resource not found
- 405 Method Not Allowed: HTTP method not supported
- 409 Conflict: Resource conflict (duplicates, version mismatch)
- 422 Unprocessable Entity: Valid syntax but semantic errors
- 429 Too Many Requests: Rate limit exceeded
Server Error Codes (5xx)
- 500 Internal Server Error: Unexpected server error
- 502 Bad Gateway: Invalid response from upstream server
- 503 Service Unavailable: Server temporarily unavailable
- 504 Gateway Timeout: Upstream server timeout
URL Design Patterns
Query Parameters for Filtering
GET /users?status=active
GET /users?role=admin&department=engineering
GET /orders?created_after=2024-01-01&status=pending
Pagination Parameters
# Offset-based
GET /users?offset=20&limit=10
# Cursor-based
GET /users?cursor=eyJpZCI6MTIzfQ&limit=10
# Page-based
GET /users?page=3&page_size=10
Sorting Parameters
GET /users?sort=created_at # Ascending
GET /users?sort=-created_at # Descending (prefix with -)
GET /users?sort=last_name,first_name # Multiple fields
Field Selection
GET /users?fields=id,name,email
GET /users/123?include=orders,profile
GET /users/123?exclude=internal_notes
Search Parameters
GET /users?q=john
GET /products?search=laptop&category=electronics
Response Format Standards
Consistent Response Structure
{
"data": {
"id": 123,
"name": "John Doe",
"email": "john@example.com"
},
"meta": {
"timestamp": "2024-02-16T13:00:00Z",
"version": "1.0"
}
}
Collection Responses
{
"data": [
{"id": 1, "name": "Item 1"},
{"id": 2, "name": "Item 2"}
],
"pagination": {
"total": 150,
"page": 1,
"pageSize": 10,
"totalPages": 15,
"hasNext": true,
"hasPrev": false
},
"meta": {
"timestamp": "2024-02-16T13:00:00Z"
}
}
Error Response Format
{
"error": {
"code": "VALIDATION_ERROR",
"message": "The request contains invalid parameters",
"details": [
{
"field": "email",
"code": "INVALID_FORMAT",
"message": "Email address is not valid"
}
],
"requestId": "req-123456",
"timestamp": "2024-02-16T13:00:00Z"
}
}
Field Naming Conventions
Use camelCase for JSON Fields
✅ Good:
{
"firstName": "John",
"lastName": "Doe",
"createdAt": "2024-02-16T13:00:00Z",
"isActive": true
}
❌ Bad:
{
"first_name": "John",
"LastName": "Doe",
"created-at": "2024-02-16T13:00:00Z"
}
Boolean Fields
Use positive, clear names with "is", "has", "can", or "should" prefixes:
✅ Good:
{
"isActive": true,
"hasPermission": false,
"canEdit": true,
"shouldNotify": false
}
❌ Bad:
{
"active": true,
"disabled": false, // Double negative
"permission": false // Unclear meaning
}
Date/Time Fields
- Use ISO 8601 format:
2024-02-16T13:00:00Z - Include timezone information
- Use consistent field naming:
{
"createdAt": "2024-02-16T13:00:00Z",
"updatedAt": "2024-02-16T13:30:00Z",
"deletedAt": null,
"publishedAt": "2024-02-16T14:00:00Z"
}
Content Negotiation
Accept Headers
Accept: application/json
Accept: application/xml
Accept: application/json; version=1
Content-Type Headers
Content-Type: application/json
Content-Type: application/json; charset=utf-8
Content-Type: multipart/form-data
Versioning via Headers
Accept: application/vnd.myapi.v1+json
API-Version: 1.0
Caching Guidelines
Cache-Control Headers
Cache-Control: public, max-age=3600 # Cache for 1 hour
Cache-Control: private, max-age=0 # Don't cache
Cache-Control: no-cache, must-revalidate # Always validate
ETags for Conditional Requests
HTTP/1.1 200 OK
ETag: "123456789"
Last-Modified: Wed, 21 Oct 2015 07:28:00 GMT
# Client subsequent request:
If-None-Match: "123456789"
If-Modified-Since: Wed, 21 Oct 2015 07:28:00 GMT
Security Headers
Authentication
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Authorization: Basic dXNlcjpwYXNzd29yZA==
Authorization: Api-Key abc123def456
CORS Headers
Access-Control-Allow-Origin: https://example.com
Access-Control-Allow-Methods: GET, POST, PUT, DELETE
Access-Control-Allow-Headers: Content-Type, Authorization
Rate Limiting
Rate Limit Headers
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 999
X-RateLimit-Reset: 1640995200
X-RateLimit-Window: 3600
Rate Limit Exceeded Response
HTTP/1.1 429 Too Many Requests
Retry-After: 3600
{
"error": {
"code": "RATE_LIMIT_EXCEEDED",
"message": "API rate limit exceeded",
"details": {
"limit": 1000,
"window": "1 hour",
"retryAfter": 3600
}
}
}
Hypermedia (HATEOAS)
Links in Responses
{
"id": 123,
"name": "John Doe",
"email": "john@example.com",
"_links": {
"self": {
"href": "/users/123"
},
"orders": {
"href": "/users/123/orders"
},
"edit": {
"href": "/users/123",
"method": "PUT"
},
"delete": {
"href": "/users/123",
"method": "DELETE"
}
}
}
Link Relations
- self: Link to the resource itself
- edit: Link to edit the resource
- delete: Link to delete the resource
- related: Link to related resources
- next/prev: Pagination links
Common Anti-Patterns to Avoid
1. Verbs in URLs
❌ Bad: /api/getUser/123
✅ Good: GET /api/users/123
2. Inconsistent Naming
❌ Bad: /user-profiles and /userAddresses
✅ Good: /user-profiles and /user-addresses
3. Deep Nesting
❌ Bad: /companies/123/departments/456/teams/789/members/012
✅ Good: /team-members/012?team=789
4. Ignoring HTTP Status Codes
❌ Bad: Always return 200 with error info in body
✅ Good: Use appropriate status codes (404, 400, 500, etc.)
5. Exposing Internal Structure
❌ Bad: /api/database_table_users
✅ Good: /api/users
6. No Versioning Strategy
❌ Bad: Breaking changes without version management
✅ Good: /api/v1/users or Accept: application/vnd.api+json;version=1
7. Inconsistent Error Responses
❌ Bad: Different error formats for different endpoints
✅ Good: Standardized error response structure
Best Practices Summary
- Use nouns for resources, not verbs
- Leverage HTTP methods correctly
- Maintain consistent naming conventions
- Implement proper error handling
- Use appropriate HTTP status codes
- Design for cacheability
- Implement security from the start
- Plan for versioning
- Provide comprehensive documentation
- Follow HATEOAS principles when applicable