Resource Naming Conventions
Use plural nouns for resources:
```
β
GET /users
β
GET /users/123
β
GET /users/123/orders
β GET /user
β GET /getUser
β GET /user/123
```
Use hierarchical relationships:
```
β
GET /users/123/orders # Orders for specific user
β
GET /teams/5/members # Members of specific team
β
POST /projects/10/tasks # Create task in project 10
β GET /userOrders/123 # Flat structure
β GET /orders?userId=123 # Query param for relationship
```
Use kebab-case for multi-word resources:
```
β
/shopping-carts
β
/order-items
β
/user-preferences
β /shoppingCarts (camelCase)
β /shopping_carts (snake_case)
β /ShoppingCarts (PascalCase)
```
HTTP Methods (Verbs)
| Method | Purpose | Idempotent | Safe | Example |
|--------|---------|------------|------|---------|
| GET | Retrieve resource(s) | Yes | Yes | GET /users/123 |
| POST | Create resource | No | No | POST /users |
| PUT | Replace entire resource | Yes | No | PUT /users/123 |
| PATCH | Partial update | No* | No | PATCH /users/123 |
| DELETE | Remove resource | Yes | No | DELETE /users/123 |
| HEAD | Metadata only (no body) | Yes | Yes | HEAD /users/123 |
| OPTIONS | Allowed methods | Yes | Yes | OPTIONS /users |
*PATCH can be designed to be idempotent
Status Codes
#### Success (2xx)
- 200 OK: Successful GET, PUT, PATCH, or DELETE
- 201 Created: Successful POST (include
Location header) - 202 Accepted: Request accepted, processing async
- 204 No Content: Successful DELETE or PUT with no response body
#### Client Errors (4xx)
- 400 Bad Request: Invalid request body or parameters
- 401 Unauthorized: Missing or invalid authentication
- 403 Forbidden: Authenticated but not authorized
- 404 Not Found: Resource doesn't exist
- 405 Method Not Allowed: HTTP method not supported for resource
- 409 Conflict: Resource conflict (e.g., duplicate)
- 422 Unprocessable Entity: Validation failed
- 429 Too Many Requests: Rate limit exceeded
#### Server Errors (5xx)
- 500 Internal Server Error: Generic server error
- 502 Bad Gateway: Upstream service error
- 503 Service Unavailable: Temporary unavailability
- 504 Gateway Timeout: Upstream timeout
Request/Response Formats
Request Body (POST/PUT/PATCH):
```json
POST /users
Content-Type: application/json
{
"email": "jane@example.com",
"name": "Jane Smith",
"role": "developer"
}
```
Success Response:
```json
HTTP/1.1 201 Created
Location: /users/123
Content-Type: application/json
{
"id": 123,
"email": "jane@example.com",
"name": "Jane Smith",
"role": "developer",
"created_at": "2025-10-31T10:30:00Z",
"updated_at": "2025-10-31T10:30:00Z"
}
```
Error Response (Standard Format):
```json
HTTP/1.1 422 Unprocessable Entity
Content-Type: application/json
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Request validation failed",
"details": [
{
"field": "email",
"message": "Email is already registered",
"code": "DUPLICATE_EMAIL"
},
{
"field": "name",
"message": "Name must be at least 2 characters",
"code": "NAME_TOO_SHORT"
}
],
"timestamp": "2025-10-31T10:30:00Z",
"request_id": "req_abc123"
}
}
```
Pagination
Cursor-Based Pagination (Recommended):
```
GET /users?cursor=eyJpZCI6MTIzfQ&limit=20
Response:
{
"data": [...],
"pagination": {
"next_cursor": "eyJpZCI6MTQzfQ",
"has_more": true
}
}
```
Pros: Consistent results even as data changes
Use for: Large datasets, real-time data, infinite scroll
Offset-Based Pagination:
```
GET /users?page=2&per_page=20
Response:
{
"data": [...],
"pagination": {
"page": 2,
"per_page": 20,
"total": 487,
"total_pages": 25
}
}
```
Pros: Easy to understand, supports "jump to page N"
Use for: Small datasets, admin panels, known bounds
Filtering and Sorting
Filtering:
```
GET /users?status=active&role=developer&created_after=2025-01-01
GET /products?price_min=10&price_max=100&category=electronics
```
Sorting:
```
GET /users?sort=created_at:desc
GET /users?sort=-created_at # Minus prefix for descending
GET /users?sort=name:asc,created_at:desc # Multiple fields
```
Field Selection (Partial Response):
```
GET /users?fields=id,name,email # Only specified fields
GET /users/123?exclude=password_hash # All except specified
```
API Versioning
#### Strategy 1: URI Versioning (Recommended)
```
β
/api/v1/users
β
/api/v2/users
Pros: Clear, easy to test, cache-friendly
Cons: Verbose URLs
```
#### Strategy 2: Header Versioning
```
GET /api/users
Accept: application/vnd.company.v2+json
Pros: Clean URLs
Cons: Harder to test, not visible in URL
```
#### Strategy 3: Query Parameter
```
GET /api/users?version=2
Pros: Simple
Cons: Can be forgotten, mixes with business logic params
```
Best Practice: URI versioning for public APIs, header versioning for internal services
Rate Limiting
Response Headers:
```
HTTP/1.1 200 OK
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 987
X-RateLimit-Reset: 1635724800
Response when exceeded:
HTTP/1.1 429 Too Many Requests
Retry-After: 3600
{
"error": {
"code": "RATE_LIMIT_EXCEEDED",
"message": "API rate limit exceeded",
"retry_after": 3600
}
}
```
Authentication & Authorization
Bearer Token (JWT):
```
GET /users/me
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
```
API Key:
```
GET /users
X-API-Key: sk_live_abc123...
```
Basic Auth (avoid for production):
```
GET /users
Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=
```
---