REST API Design
REST (Representational State Transfer) is an architectural style for designing web APIs that leverages HTTP's built-in semantics.
Resource-Oriented Design
In REST, every entity is a resource identified by a URL:
GET /api/users → list all users
GET /api/users/42 → get user 42
POST /api/users → create a new user
PUT /api/users/42 → replace user 42
PATCH /api/users/42 → modify user 42
DELETE /api/users/42 → delete user 42Resources can be nested:
GET /api/users/42/posts → get all posts by user 42
POST /api/users/42/posts → create a post by user 42HTTP Methods and Idempotence
| Method | Idempotent? | Safe? | Purpose |
|---|---|---|---|
| GET | ✅ Yes | ✅ Yes | Retrieve a resource |
| POST | ❌ No | ❌ No | Create a resource or trigger a process |
| PUT | ✅ Yes | ❌ No | Replace a resource entirely |
| PATCH | ❌ No | ❌ No | Update part of a resource |
| DELETE | ✅ Yes | ❌ No | Delete a resource |
| HEAD | ✅ Yes | ✅ Yes | Same as GET but without the body |
| OPTIONS | ✅ Yes | ✅ Yes | List allowed methods |
An idempotent operation means applying it multiple times has the same effect as applying it once.
Status Codes
| Code | Meaning | When to use |
|---|---|---|
| 200 | OK | Successful GET, PUT, PATCH, or DELETE |
| 201 | Created | Successful POST that creates a resource |
| 204 | No Content | Successful request with no body to return |
| 400 | Bad Request | Malformed request, validation error |
| 401 | Unauthorized | Missing or invalid authentication |
| 403 | Forbidden | Authenticated but not allowed |
| 404 | Not Found | Resource doesn't exist |
| 409 | Conflict | Resource already exists, or version conflict |
| 429 | Too Many Requests | Rate limited |
| 500 | Internal Server Error | Unexpected server error |
Error Response Format
Always return structured error responses:
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Invalid email address",
"details": {
"field": "email",
"value": "not-an-email"
}
}
}Versioning
Never change a deployed API without versioning. Common approaches:
- URL versioning:
/api/v1/users,/api/v2/users - Header versioning:
Accept: application/vnd.myapi.v1+json - Query parameter:
/api/users?version=1
URL versioning is the simplest and most commonly used approach.