Free Guide
Backend API Design Checklist
A practical checklist for designing clean, consistent, and production-ready REST APIs.
4 min read
Why a checklist?
API design decisions compound. A shortcut in naming or error handling early on creates inconsistency that spreads across every endpoint. This checklist helps you make deliberate choices before writing code.
URL Structure
- Use nouns, not verbs:
/users,/orders, not/getUsers,/createOrder - Use plural resource names:
/users/123, not/user/123 - Nest for relationships:
/users/123/orders(orders belonging to user 123) - Keep URLs lowercase with hyphens:
/order-items, not/orderItems - Limit nesting to 2 levels max:
/users/123/ordersis fine,/users/123/orders/456/items/789is too deep
GET /api/v1/users # List users
GET /api/v1/users/123 # Get user 123
POST /api/v1/users # Create user
PUT /api/v1/users/123 # Replace user 123
PATCH /api/v1/users/123 # Partial update
DELETE /api/v1/users/123 # Delete user 123
HTTP Methods
| Method | Purpose | Idempotent | Request Body |
|---|---|---|---|
| GET | Read | Yes | No |
| POST | Create | No | Yes |
| PUT | Full replace | Yes | Yes |
| PATCH | Partial update | No | Yes |
| DELETE | Remove | Yes | No |
Key rules:
- GET must never modify state
- POST is the only non-idempotent method — calling it twice creates two resources
- PUT replaces the entire resource; PATCH updates specific fields only
Status Codes
Use the right code for the right situation:
200 OK — Successful GET, PUT, PATCH, DELETE
201 Created — Successful POST (include Location header)
204 No Content — Successful DELETE with no response body
400 Bad Request — Validation failed (include field-level errors)
401 Unauthorized — Missing or invalid authentication
403 Forbidden — Authenticated but not authorized
404 Not Found — Resource doesn't exist
409 Conflict — Duplicate or state conflict
422 Unprocessable — Syntactically correct but semantically wrong
429 Too Many — Rate limit exceeded (include Retry-After)
500 Server Error — Unhandled exception (never expose stack traces)
Error Response Format
Use a consistent error format across all endpoints:
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Request validation failed",
"details": [
{
"field": "email",
"message": "Must be a valid email address"
},
{
"field": "age",
"message": "Must be at least 18"
}
]
}
}
Rules:
- Always return a machine-readable
code(not just the HTTP status) - Include
fieldin validation errors so the UI can highlight the right input - Never expose internal errors, stack traces, or database details to the client
Pagination
For list endpoints, always paginate:
GET /api/v1/users?page=2&size=20
{
"data": [...],
"pagination": {
"page": 2,
"size": 20,
"total": 156,
"totalPages": 8
}
}
- Default to
size=20if not specified - Cap maximum page size (e.g., 100)
- Include total count for UI pagination controls
- For large datasets, consider cursor-based pagination instead
Versioning
- Use URL path versioning:
/api/v1/users - Increment the major version only for breaking changes
- Keep old versions alive until all clients migrate
- Document deprecation timelines
Authentication
- Use Bearer tokens in the
Authorizationheader:Authorization: Bearer <token> - Never pass tokens in URL query strings (they appear in logs)
- Return 401 for missing/expired tokens, 403 for insufficient permissions
- Include token expiry in the response so clients can refresh proactively
Request Validation
- Validate all inputs on the server, even if the client validates too
- Return 400 with field-level errors for invalid data
- Reject unknown fields (don’t silently ignore them)
- Set maximum sizes for strings, arrays, and file uploads
- Sanitize inputs to prevent injection attacks
Response Best Practices
- Use consistent naming: camelCase or snake_case, pick one and stick to it
- Include
idin every resource response - Return the created/updated resource in POST/PUT/PATCH responses
- Use ISO 8601 for dates:
"2026-01-15T10:30:00Z" - Wrap collections in a
dataarray (not a bare array)
Rate Limiting
- Set rate limits per endpoint or per user
- Return
429 Too Many Requestswhen exceeded - Include headers:
X-RateLimit-Limit,X-RateLimit-Remaining,Retry-After - Use sliding window or token bucket algorithms
Quick Checklist
Before shipping any API endpoint, verify:
- URL uses plural nouns, lowercase, hyphens
- Correct HTTP method for the operation
- Returns appropriate status code (not always 200)
- Error responses follow consistent format
- List endpoints are paginated
- Inputs are validated server-side
- Response includes resource ID
- Dates use ISO 8601 format
- Authentication is required (unless intentionally public)
- Rate limiting is configured
- No sensitive data in URLs or logs