HTTP Methods & Status Codes Deep Dive
Understanding HTTP Methods in Depth
HTTP methods (also called verbs) are the backbone of REST API communication. Each method has specific semantics, safety properties, and idempotency characteristics that determine how it should be used. Let's explore each method in detail.
GET - Retrieve Resources
The GET method retrieves data from the server. It's the most commonly used HTTP method and should ONLY be used for reading data, never for modifying it.
Characteristics:
- Safe: Doesn't change server state
- Idempotent: Making the same request multiple times produces the same result
- Cacheable: Responses can be cached by browsers and CDNs
- Has Body: No request body (data passed in URL)
Common Use Cases:
// Get all users
GET /api/users
Response: 200 OK
[
{"id": 1, "name": "Alice"},
{"id": 2, "name": "Bob"}
]
// Get single user
GET /api/users/123
Response: 200 OK
{"id": 123, "name": "Alice", "email": "alice@example.com"}
// Get with query parameters (filtering, sorting, pagination)
GET /api/users?role=admin&sort=name&page=1&limit=20
Response: 200 OK
{
"data": [...],
"pagination": {
"current_page": 1,
"total_pages": 5,
"total_items": 100
}
}
// Get nested resources
GET /api/users/123/posts
Response: 200 OK
[
{"id": 1, "title": "My First Post"},
{"id": 2, "title": "Another Post"}
]
POST - Create Resources
POST is used to create new resources on the server. It sends data in the request body and typically returns the created resource with a 201 status code.
Characteristics:
- Not Safe: Changes server state
- Not Idempotent: Multiple identical requests create multiple resources
- Not Cacheable: By default (can be made cacheable with proper headers)
- Has Body: Yes - data sent in request body
Creating Resources:
POST /api/users
Content-Type: application/json
{
"name": "Charlie",
"email": "charlie@example.com",
"role": "user"
}
Response: 201 Created
Location: /api/users/456
{
"id": 456,
"name": "Charlie",
"email": "charlie@example.com",
"role": "user",
"created_at": "2026-02-14T10:30:00Z"
}
POST for Complex Operations:
POST can also be used for operations that don't fit the standard CRUD model:
// Search with complex criteria (too complex for GET query params)
POST /api/users/search
{
"filters": {
"age_range": [18, 65],
"countries": ["US", "UK", "CA"],
"interests": ["tech", "sports"]
}
}
// Process an action
POST /api/orders/123/ship
{
"tracking_number": "ABC123",
"carrier": "FedEx"
}
// Batch operations
POST /api/users/batch-create
{
"users": [
{"name": "User1", "email": "user1@example.com"},
{"name": "User2", "email": "user2@example.com"}
]
}
PUT - Replace Entire Resource
PUT replaces an entire resource with the provided data. If the resource doesn't exist, some APIs create it (though this is optional).
Characteristics:
- Not Safe: Changes server state
- Idempotent: Multiple identical requests produce the same result
- Not Cacheable: By default
- Has Body: Yes - complete resource representation
Full Resource Updates:
PUT /api/users/123
Content-Type: application/json
{
"name": "Alice Updated",
"email": "alice.new@example.com",
"role": "admin",
"bio": "Software Developer"
}
Response: 200 OK
{
"id": 123,
"name": "Alice Updated",
"email": "alice.new@example.com",
"role": "admin",
"bio": "Software Developer",
"updated_at": "2026-02-14T11:00:00Z"
}
PATCH - Partial Updates
PATCH updates only specific fields of a resource without replacing the entire resource.
Characteristics:
- Not Safe: Changes server state
- Not Idempotent: Technically (though often implemented as idempotent)
- Not Cacheable: By default
- Has Body: Yes - only fields to update
Partial Updates:
PATCH /api/users/123
Content-Type: application/json
{
"email": "alice.newest@example.com"
}
Response: 200 OK
{
"id": 123,
"name": "Alice Updated", // unchanged
"email": "alice.newest@example.com", // updated
"role": "admin", // unchanged
"bio": "Software Developer", // unchanged
"updated_at": "2026-02-14T11:15:00Z"
}
PUT vs. PATCH: When to Use Each
| Scenario | Use | Reason |
|---|---|---|
| Update user profile (all fields) | PUT | Replacing entire resource |
| Change user email only | PATCH | Updating single field |
| Update product details form | PUT | Form has all fields |
| Toggle user active status | PATCH | Single boolean flip |
DELETE - Remove Resources
DELETE removes a resource from the server permanently.
Characteristics:
- Not Safe: Changes server state
- Idempotent: Deleting the same resource multiple times has the same effect
- Not Cacheable: By default
- Has Body: Usually no (though technically allowed)
Deletion Patterns:
// Delete single resource
DELETE /api/users/123
Response: 204 No Content
// Empty body
// Or with confirmation data
Response: 200 OK
{
"message": "User deleted successfully",
"deleted_at": "2026-02-14T11:30:00Z"
}
// Soft delete (mark as deleted, don't remove)
DELETE /api/users/123
Response: 200 OK
{
"id": 123,
"deleted": true,
"deleted_at": "2026-02-14T11:30:00Z"
}
// Delete nested resource
DELETE /api/users/123/posts/456
Response: 204 No Content
HEAD - Get Headers Only
HEAD is identical to GET but returns only headers without the response body. Useful for checking if a resource exists or getting metadata.
HEAD /api/users/123
Response: 200 OK
Content-Type: application/json
Content-Length: 256
Last-Modified: Wed, 14 Feb 2026 11:00:00 GMT
ETag: "abc123"
// No body returned
// Use cases:
// - Check if resource exists (200 vs 404)
// - Get resource size before downloading
// - Check if resource was modified (ETag, Last-Modified)
// - Verify authentication without downloading data
OPTIONS - Discover Allowed Methods
OPTIONS returns the HTTP methods that the server supports for a specific endpoint. Also used for CORS preflight requests.
OPTIONS /api/users/123
Response: 200 OK
Allow: GET, PUT, PATCH, DELETE, HEAD, OPTIONS
Access-Control-Allow-Methods: GET, PUT, PATCH, DELETE
Access-Control-Allow-Origin: https://example.com
Access-Control-Allow-Headers: Content-Type, Authorization
// CORS preflight example
OPTIONS /api/users
Origin: https://frontend.example.com
Response: 200 OK
Access-Control-Allow-Origin: https://frontend.example.com
Access-Control-Allow-Methods: GET, POST
Access-Control-Allow-Headers: Content-Type
Access-Control-Max-Age: 86400
HTTP Status Codes: Complete Reference
Status codes communicate the result of an HTTP request. Choosing the right code helps clients handle responses appropriately.
1xx - Informational Responses
These indicate that the request was received and is being processed. Rarely used in REST APIs.
| Code | Meaning | Use Case |
|---|---|---|
| 100 | Continue | Client should continue with request |
| 101 | Switching Protocols | Switching to WebSocket, HTTP/2 |
2xx - Success Responses
The request was successfully received, understood, and accepted.
| Code | Meaning | When to Use |
|---|---|---|
| 200 | OK | GET, PUT, PATCH successful |
| 201 | Created | POST created new resource |
| 202 | Accepted | Request accepted, processing async |
| 204 | No Content | DELETE successful, no data to return |
| 206 | Partial Content | Range request (pagination, streaming) |
// 200 OK - Standard success
GET /api/users/123
Response: 200 OK
{"id": 123, "name": "Alice"}
// 201 Created - New resource
POST /api/users
Response: 201 Created
Location: /api/users/456
{"id": 456, "name": "Bob"}
// 202 Accepted - Async processing
POST /api/reports/generate
Response: 202 Accepted
{"job_id": "abc123", "status": "processing"}
// 204 No Content - Success, no data
DELETE /api/users/123
Response: 204 No Content
3xx - Redirection Responses
Further action is needed to complete the request.
| Code | Meaning | Use Case |
|---|---|---|
| 301 | Moved Permanently | Resource permanently at new URL |
| 302 | Found | Temporary redirect |
| 304 | Not Modified | Cached version still valid |
| 307 | Temporary Redirect | Temporary, keep same method |
| 308 | Permanent Redirect | Permanent, keep same method |
4xx - Client Error Responses
The request contains bad syntax or cannot be fulfilled. These are the most important codes for API developers.
| Code | Meaning | When to Use |
|---|---|---|
| 400 | Bad Request | Malformed request, invalid JSON |
| 401 | Unauthorized | Missing or invalid authentication |
| 403 | Forbidden | Authenticated but lacks permission |
| 404 | Not Found | Resource doesn't exist |
| 405 | Method Not Allowed | HTTP method not supported |
| 409 | Conflict | Resource conflict (duplicate email) |
| 422 | Unprocessable Entity | Validation failed |
| 429 | Too Many Requests | Rate limit exceeded |
Detailed 4xx Examples:
// 400 Bad Request - Malformed JSON
POST /api/users
{name: "Bob"} // Missing quotes around key
Response: 400 Bad Request
{
"error": "Invalid JSON syntax"
}
// 401 Unauthorized - No authentication
GET /api/users/123
Response: 401 Unauthorized
{
"error": "Authentication required",
"message": "Please provide a valid access token"
}
// 403 Forbidden - Insufficient permissions
DELETE /api/users/456
Response: 403 Forbidden
{
"error": "Insufficient permissions",
"message": "You don't have permission to delete users"
}
// 404 Not Found - Resource doesn't exist
GET /api/users/99999
Response: 404 Not Found
{
"error": "User not found",
"message": "No user exists with ID 99999"
}
// 409 Conflict - Duplicate resource
POST /api/users
{"email": "existing@example.com"}
Response: 409 Conflict
{
"error": "Email already exists",
"message": "A user with this email already exists"
}
// 422 Unprocessable Entity - Validation failed
POST /api/users
{"name": "A", "email": "invalid-email"}
Response: 422 Unprocessable Entity
{
"error": "Validation failed",
"errors": {
"name": ["Name must be at least 3 characters"],
"email": ["Email must be a valid email address"]
}
}
// 429 Too Many Requests - Rate limit
GET /api/users
Response: 429 Too Many Requests
Retry-After: 60
{
"error": "Rate limit exceeded",
"message": "Try again in 60 seconds"
}
5xx - Server Error Responses
The server failed to fulfill a valid request.
| Code | Meaning | When It Occurs |
|---|---|---|
| 500 | Internal Server Error | Generic server error |
| 502 | Bad Gateway | Invalid response from upstream |
| 503 | Service Unavailable | Server overloaded or maintenance |
| 504 | Gateway Timeout | Upstream server didn't respond |
For each scenario, choose the correct HTTP method and expected status code:
- User updates their profile picture: Method: _____ Status: _____
- User logs in with email/password: Method: _____ Status: _____
- User checks if a username is available: Method: _____ Status: _____
- Admin soft-deletes a user account: Method: _____ Status: _____
- User tries to access admin panel without permission: Method: _____ Status: _____
Answers: 1) PATCH, 200 2) POST, 200 3) HEAD or GET, 200/404 4) DELETE, 200 5) GET, 403
Key Takeaways
- GET is for reading, never modifying - it's safe and idempotent
- POST creates resources and returns 201 with Location header
- PUT replaces entire resources, PATCH updates specific fields
- DELETE removes resources, returning 204 or 200
- Use HEAD to check existence without downloading data
- Always return appropriate status codes - they matter for clients
- 4xx errors are client's fault, 5xx errors are server's fault
- Include helpful error messages in response bodies