| name | rest-api-guidelines |
| description | REST API design guidelines including URL structure, HTTP methods, status codes, request/response formats, and client implementation. Auto-loaded when working with API code. |
| category | guideline |
| user-invocable | false |
API Design Guidelines
Core Principles
- Consistency - Same patterns everywhere
- Predictability - Clients know what to expect
- Discoverability - APIs are self-documenting
- Resilience - Graceful degradation, proper error handling
REST API Design
URL Structure
# Collection resources (plural nouns)
GET /api/users # List users
POST /api/users # Create user
GET /api/users/:id # Get user
PUT /api/users/:id # Replace user
PATCH /api/users/:id # Update user
DELETE /api/users/:id # Delete user
# Nested resources (relationships)
GET /api/users/:id/orders # User's orders
POST /api/users/:id/orders # Create order for user
# Actions (when CRUD doesn't fit)
POST /api/users/:id/activate
POST /api/orders/:id/cancel
Naming Conventions
/api/users
/api/products
/api/order-items
/api/user-profiles
GET /api/users
DELETE /api/users/1
HTTP Methods
| Method | Purpose | Idempotent | Safe |
|---|
| GET | Read resource | Yes | Yes |
| POST | Create resource | No | No |
| PUT | Replace resource | Yes | No |
| PATCH | Partial update | Yes | No |
| DELETE | Remove resource | Yes | No |
Status Codes
200 OK
201 Created
204 No Content
400 Bad Request
401 Unauthorized
403 Forbidden
404 Not Found
409 Conflict
422 Unprocessable
500 Internal Error
502 Bad Gateway
503 Unavailable
504 Gateway Timeout
Request/Response Format
Request Structure
GET /api/users?status=active&page=1&limit=20&sort=-createdAt
POST /api/users
Content-Type: application/json
{
"name": "John Doe",
"email": "john@example.com",
"role": "admin"
}
Response Structure
{
"data": {
"id": "user-123",
"name": "John Doe",
"email": "john@example.com",
"createdAt": "2024-01-15T10:30:00Z"
}
}
{
"data": [
{ "id": "user-1", "name": "Alice" },
{ "id": "user-2", "name": "Bob" }
],
"pagination": {
"page": 1,
"limit": 20,
"total": 150,
"totalPages": 8
}
}
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Invalid input data",
"details": [
{ "field": "email", "message": "Invalid email format" },
{ "field": "age", "message": "Must be at least 18" }
]
}
}
Type Definitions
interface ApiResponse<T> {
data: T;
meta?: {
requestId: string;
timestamp: string;
};
}
interface PaginatedResponse<T> {
data: T[];
pagination: {
page: number;
limit: number;
total: number;
totalPages: number;
};
}
interface ApiError {
error: {
code: string;
message: string;
details?: Array<{
field?: string;
message: string;
}>;
};
}
Known Gotchas
Content-Type Matters
fetch('/api/users', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data)
});
Empty Responses
if (response.status === 204) {
return null;
}
return response.json();
Trailing Slashes
Be consistent - pick one and stick to it:
/api/users // Preferred
/api/users/ // Alternative (configure redirects)
Date Formats
Always use ISO 8601 in UTC:
{
"createdAt": "2024-01-15T10:30:00Z"
}
Additional References