REST Fundamentals
REST (Representational State Transfer) is an architectural style for designing networked applications using HTTP protocols.
REST Constraints
- Client-Server: Separation of concerns between UI and data storage
- Stateless: Each request contains all information needed
- Cacheable: Responses can be cached for performance
- Uniform Interface: Standardized way to interact with resources
- Layered System: Client doesn't know if it's connected directly to server
- Code on Demand (optional): Server can send executable code
Resources
Everything in REST is a resource. Resources are identified by URIs (Uniform Resource Identifiers).
URL Structure
https://api.example.com/v1/users/123/orders?status=pending
Protocol: https
Domain: api.example.com
Version: v1
Resource: users
Resource ID: 123
Sub-resource: orders
Query parameter: status=pending
HTTP Methods
| Method | Purpose | Idempotent | Safe | Request Body |
|---|---|---|---|---|
| GET | Retrieve resource | ✅ Yes | ✅ Yes | ❌ No |
| POST | Create resource | ❌ No | ❌ No | ✅ Yes |
| PUT | Replace resource | ✅ Yes | ❌ No | ✅ Yes |
| PATCH | Partial update | ❌ No* | ❌ No | ✅ Yes |
| DELETE | Remove resource | ✅ Yes | ❌ No | ❌ No |
Idempotent: Same request repeated multiple times produces same result.
Safe: Method doesn't modify the resource.
Safe: Method doesn't modify the resource.
CRUD Operations Mapping
REST Endpoints
GET /users → Get all users (Read)
GET /users/123 → Get user 123 (Read)
POST /users → Create new user (Create)
PUT /users/123 → Replace user 123 (Update)
PATCH /users/123 → Update user 123 partially (Update)
DELETE /users/123 → Delete user 123 (Delete)
HTTP Status Codes
2xx - Success
| Code | Name | Use Case |
|---|---|---|
200 | OK | Successful GET, PUT, PATCH |
201 | Created | Successful POST (resource created) |
204 | No Content | Successful DELETE (no body) |
3xx - Redirection
| Code | Name | Use Case |
|---|---|---|
301 | Moved Permanently | Resource moved to new URL |
304 | Not Modified | Cached version is still valid |
4xx - Client Errors
| Code | Name | Use Case |
|---|---|---|
400 | Bad Request | Invalid request syntax/data |
401 | Unauthorized | Authentication required |
403 | Forbidden | Authenticated but not authorized |
404 | Not Found | Resource doesn't exist |
405 | Method Not Allowed | HTTP method not supported |
409 | Conflict | Resource conflict (duplicate) |
422 | Unprocessable Entity | Validation errors |
429 | Too Many Requests | Rate limit exceeded |
5xx - Server Errors
| Code | Name | Use Case |
|---|---|---|
500 | Internal Server Error | Generic server error |
502 | Bad Gateway | Invalid response from upstream |
503 | Service Unavailable | Server temporarily down |
504 | Gateway Timeout | Upstream server timeout |
API Design Best Practices
URL Naming Conventions
Good vs Bad
# Good ✅
GET /users
GET /users/123
GET /users/123/orders
GET /orders?user_id=123
# Bad ❌
GET /getUsers
GET /getUserById/123
GET /user/orders/getOrders
POST /createUser
Pagination
JSON
// Request
GET /users?page=2&limit=10
// Response
{
"data": [...],
"pagination": {
"current_page": 2,
"per_page": 10,
"total_pages": 5,
"total_count": 48,
"links": {
"first": "/users?page=1&limit=10",
"prev": "/users?page=1&limit=10",
"next": "/users?page=3&limit=10",
"last": "/users?page=5&limit=10"
}
}
}
Error Response Format
JSON
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Request validation failed",
"details": [
{
"field": "email",
"message": "Invalid email format"
},
{
"field": "age",
"message": "Must be a positive number"
}
]
}
}
Filtering & Sorting
URL
# Filtering
GET /users?status=active&role=admin
GET /orders?created_after=2024-01-01
# Sorting
GET /users?sort=name # Ascending
GET /users?sort=-created_at # Descending
GET /users?sort=role,-name # Multiple
# Field selection
GET /users?fields=id,name,email
Authentication
API Key
HTTP Header
X-API-Key: your-api-key-here
# Or in query string (less secure)
GET /users?api_key=your-api-key-here
Bearer Token (JWT)
HTTP Header
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
OAuth 2.0 Flow
- User clicks "Login with Google"
- Redirect to authorization server
- User authenticates and consents
- Redirect back with authorization code
- Exchange code for access token
- Use token to access API
OAuth Token Request
POST /oauth/token
Content-Type: application/x-www-form-urlencoded
grant_type=authorization_code
&code=AUTH_CODE
&client_id=YOUR_CLIENT_ID
&client_secret=YOUR_CLIENT_SECRET
&redirect_uri=YOUR_REDIRECT_URI
API Examples
JavaScript (Fetch)
JavaScript
// GET request
const response = await fetch('/api/users');
const users = await response.json();
// POST request
const newUser = await fetch('/api/users', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer YOUR_TOKEN'
},
body: JSON.stringify({
name: 'John Doe',
email: 'john@example.com'
})
});
// Error handling
try {
const response = await fetch('/api/users/123');
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
} catch (error) {
console.error('API Error:', error);
}
Python (Requests)
Python
import requests
# GET request
response = requests.get('https://api.example.com/users')
users = response.json()
# POST request
response = requests.post(
'https://api.example.com/users',
json={'name': 'John', 'email': 'john@example.com'},
headers={'Authorization': 'Bearer YOUR_TOKEN'}
)
# Error handling
response = requests.get('https://api.example.com/users/123')
response.raise_for_status() # Raises exception for 4xx/5xx
Best Practices:
• Version your API (/v1/users)
• Use HTTPS always
• Implement rate limiting
• Document with OpenAPI/Swagger
• Use proper HTTP status codes
• Keep responses consistent
• Version your API (/v1/users)
• Use HTTPS always
• Implement rate limiting
• Document with OpenAPI/Swagger
• Use proper HTTP status codes
• Keep responses consistent