HTTP Methods
Understanding RESTful operations: GET, POST, PUT, PATCH, DELETE, and OPTIONS
Overview
HTTP methods (also called verbs) define the action to be performed on a resource. Formally defined in RFC 9110 (HTTP Semantics), in RESTful APIs these methods map to CRUD operations (Create, Read, Update, Delete) and provide a standardized way to interact with resources. Each method returns appropriate HTTP status codes and should follow REST best practices.
| Method | CRUD | Idempotent | Safe | Request Body | Response Body |
|---|---|---|---|---|---|
| GET | Read | ✅ Yes | ✅ Yes | ❌ No | ✅ Yes |
| POST | Create | ❌ No | ❌ No | ✅ Yes | ✅ Yes |
| PUT | Update/Replace | ✅ Yes | ❌ No | ✅ Yes | Optional |
| PATCH | Partial Update | ❌ No* | ❌ No | ✅ Yes | ✅ Yes |
| DELETE | Delete | ✅ Yes | ❌ No | Optional | Optional |
| N/A | ✅ Yes | ✅ Yes | ❌ No | Optional |
*PATCH can be made idempotent depending on implementation
GET - Retrieve Resources
The GET method retrieves data from the server. It should never modify server state and is considered a "safe" method. GET requests can be cached, bookmarked, and remain in browser history.
When to Use GET
- Fetching a list of resources
- Retrieving a single resource by ID
- Searching or filtering resources
- Loading data for display purposes
Examples
Get All Users
{
"data": [
{"id": 1, "name": "John Doe", "email": "john@example.com"},
{"id": 2, "name": "Jane Smith", "email": "jane@example.com"}
],
"pagination": {"page": 1, "total": 50}
}
Get Single User
{
"id": 123,
"name": "John Doe",
"email": "john@example.com",
"created_at": "2023-01-15T10:30:00Z"
}
Get with Query Parameters
{
"data": [...],
"pagination": {"page": 2, "limit": 10, "total": 150}
}
Best Practices
- Never use GET for operations that modify data
- Keep URLs under 2048 characters
- Use query parameters for filtering, sorting, and pagination
- Return appropriate cache headers
POST - Create Resources
The POST method creates new resources on the server. Each POST request may result in a new resource being created, which is why it's not idempotent—calling it multiple times creates multiple resources.
When to Use POST
- Creating a new resource
- Submitting form data
- Uploading files
- Triggering complex operations that don't fit other methods
Examples
Create User
Request Body:
{
"name": "Jane Smith",
"email": "jane@example.com",
"password": "securepassword123"
}
Response (201 Created):
{
"id": 124,
"name": "Jane Smith",
"email": "jane@example.com",
"created_at": "2023-06-20T14:30:00Z"
}
Create Order
Request Body:
{
"user_id": 123,
"items": [
{"product_id": 456, "quantity": 2},
{"product_id": 789, "quantity": 1}
],
"shipping_address": "123 Main St, City, Country"
}
Best Practices
- Return 201 Created with the new resource in the response body
- Include a Location header pointing to the new resource
- Validate all input data before creating the resource
- Use idempotency keys for financial transactions
PUT - Update/Replace Resources
The PUT method replaces an entire resource with the provided data. It's idempotent, meaning multiple identical requests produce the same result. If a resource doesn't exist, PUT can create it (upsert behavior).
When to Use PUT
- Replacing an entire resource
- Updating a resource when you have all its data
- Creating a resource at a specific URL (client-determined ID)
Examples
Update User (Full Replace)
Request Body:
{
"name": "John Doe Updated",
"email": "john.updated@example.com",
"role": "admin",
"status": "active"
}
Response (200 OK):
{
"id": 123,
"name": "John Doe Updated",
"email": "john.updated@example.com",
"role": "admin",
"status": "active",
"updated_at": "2023-06-20T15:00:00Z"
}
PUT vs POST
| PUT | POST |
|---|---|
| Idempotent | Not idempotent |
| Client specifies the URI | Server determines the URI |
| Replace entire resource | Create new resource |
PATCH - Partial Updates
The PATCH method applies partial modifications to a resource. Unlike PUT, you only send the fields that need to be updated. This is more efficient for large resources where only a few fields change.
When to Use PATCH
- Updating specific fields of a resource
- When you don't have or need the entire resource
- Bandwidth optimization for large resources
Examples
Update User Email Only
Request Body:
{
"email": "newemail@example.com"
}
Update Order Status
Request Body:
{
"status": "shipped",
"tracking_number": "1Z999AA10123456784"
}
PUT vs PATCH
| PUT | PATCH |
|---|---|
| Replace entire resource | Modify specific fields |
| Must send all fields | Send only changed fields |
| Always idempotent | Can be idempotent |
Making PATCH Idempotent
PATCH is not inherently idempotent, but you can design it to be. The key is ensuring the same PATCH request applied multiple times produces the same state.
Non-idempotent PATCH (counter increment — avoid):
{ "view_count": { "increment": 1 } } // Each call adds 1 — NOT idempotentIdempotent PATCH (set absolute value — prefer):
{ "status": "published" } // Same result every time — idempotentUpsert: Create or Update with HTTP Methods
An upsert (insert + update) creates a resource if it doesn't exist, or updates it if it does — all in a single request. REST APIs implement upserts primarily with PUT, though conditional logic can be added.
Upsert with PUT (Recommended)
PUT is naturally suited for upserts when the client controls the resource ID. The server creates the resource if it doesn't exist, or replaces it if it does:
PUT Upsert — Create or Replace User Profile
Request Body:
{
"bio": "Backend engineer",
"location": "San Francisco",
"website": "https://example.com"
}Response — if created: 201 Created | if updated: 200 OK
Conditional Upsert with If-None-Match Header
// Request headers:
If-None-Match: * // Only create — fail if already exists (409 Conflict)
// OR
If-Match: "abc123" // Only update if ETag matches (optimistic locking)Upsert with PATCH (Less Common)
// Request header:
X-Upsert: true
// Body — fields to set (create if not exists, update if exists):
{
"theme": "dark",
"notifications": true
}When to Use Which Approach
| Scenario | Method | Reason |
|---|---|---|
| Client knows the ID, replace entire resource | PUT | Idempotent, semantically correct |
| Client knows the ID, update partial fields | PATCH | Bandwidth efficient |
| Server assigns the ID | POST | Server controls URI |
| Sync/replicate resource state | PUT | Full replacement ensures consistency |
DELETE - Remove Resources
The DELETE method removes a resource from the server. It's idempotent—deleting the same resource multiple times has the same effect as deleting it once (the resource no longer exists).
When to Use DELETE
- Removing a resource permanently
- Canceling orders or subscriptions
- Revoking access tokens
Examples
Delete User
Response (204 No Content or 200 OK):
// 204 No Content - empty body
// or 200 OK with confirmation:
{
"message": "User successfully deleted",
"deleted_at": "2023-06-20T16:00:00Z"
}
Delete with Soft Delete
Response (200 OK):
{
"id": 789,
"status": "deleted",
"deleted_at": "2023-06-20T16:00:00Z",
"recoverable_until": "2023-07-20T16:00:00Z"
}
Best Practices
- Return 204 No Content for successful deletion
- Return 404 if resource doesn't exist (or 204 for idempotency)
- Consider soft deletes for recoverable data
- Handle cascading deletes carefully
OPTIONS - Get Options
The OPTIONS method describes the communication options for a target resource. It's commonly used in CORS (Cross-Origin Resource Sharing) preflight requests to check what methods and headers are allowed.
When OPTIONS is Used
- CORS preflight requests
- Discovering allowed methods for a resource
- API introspection and documentation
Examples
CORS Preflight Request
Response Headers:
HTTP/1.1 204 No Content
Allow: GET, POST, PUT, DELETE, OPTIONS
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, POST, PUT, DELETE
Access-Control-Allow-Headers: Content-Type, Authorization
Access-Control-Max-Age: 86400
Additional Methods
Get Headers Only
Identical to GET but returns only headers, no body. Used to check if a resource exists or to get metadata without downloading the content.
HEAD /api/users/123
Loop-Back Test
Performs a message loop-back test to the target resource. Used for debugging but typically disabled in production for security.
TRACE /api/debug
Establish Tunnel
Establishes a tunnel to the server identified by the target resource. Used primarily for HTTPS connections through proxies.
CONNECT example.com:443
Common Mistakes with HTTP Methods
Even experienced developers make mistakes with HTTP method semantics. Here are the most common pitfalls to avoid.
Using POST for Everything (RPC-Style Anti-Pattern)
Some developers use POST for all operations, treating the API like Remote Procedure Calls. This breaks caching, idempotency guarantees, and makes the API harder to reason about.
POST /api/getUser?id=123POST /api/deleteOrder?id=456POST /api/updateUserStatus
GET /api/users/123DELETE /api/orders/456PATCH /api/users/123 { "status": "active" }
Sending GET Requests with a Body
While not forbidden by HTTP, sending a body with a GET request is strongly discouraged. Many proxies, CDNs, and HTTP clients ignore or strip GET request bodies. Use query parameters instead.
GET /api/usersBody: { "filter": { "status": "active" } }
GET /api/users?status=active
Ignoring Idempotency in Distributed Systems
In distributed systems, network failures can cause clients to retry requests. PUT and DELETE are idempotent — you can safely retry them. POST is not — retrying POST to create a user will create duplicate users. Use idempotency keys for POST operations in critical paths.
POST /api/paymentsIdempotency-Key: unique-client-generated-uuid
Using DELETE Without Considering Cascades
Deleting a resource often has side effects on related resources. A deleted user may have orders, comments, and uploaded files. Plan cascade behavior explicitly and document it. Consider soft deletes for recoverable data.
DELETE /api/users/123// Deletes user, anonymizes their orders, removes personal data// Returns 200 with summary of what was deleted
Frequently Asked Questions
What are the main HTTP methods used in REST APIs?
The main HTTP methods in REST APIs are:
- GET — Retrieve a resource (safe, idempotent)
- POST — Create a new resource
- PUT — Replace an entire resource (idempotent)
- PATCH — Partially update a resource
- DELETE — Remove a resource (idempotent)
- OPTIONS — Describe allowed operations on a resource
What is the difference between PUT and PATCH?
PUT replaces the entire resource (all fields required). PATCH applies partial changes (only send changed fields). PUT is always idempotent; PATCH may or may not be, depending on your implementation. For upsert patterns, see the Upsert section above.
Is GET idempotent?
Yes. GET is both safe (no side effects) and idempotent (same result every call). GET responses can also be cached. You should never use GET for operations that modify data on the server.
When should I use POST instead of PUT?
Use POST when the server assigns the resource ID/URL — for example, creating a new user where the server generates the user's ID. Use PUT when the client knows the exact URL and wants to create or replace the resource at that location.
What does idempotent mean in REST APIs?
An idempotent operation produces the same result no matter how many times you call it. GET, PUT, DELETE, and OPTIONS are idempotent. POST is not — calling POST twice creates two resources. Idempotency is critical in distributed systems where network failures may cause retries.
References & Further Reading
Related Topics
📊 Status Codes
Learn which HTTP status codes to return with each method.
✨ Best Practices
URL design, versioning, and API design patterns.
💻 API Examples
Real-world examples of HTTP methods in action.
⚠️ Error Handling
Handle errors gracefully for each HTTP method.
🩹 PATCH Deep Dive
Partial updates, JSON Patch format, and idempotency in detail.
🔀 OPTIONS & CORS
CORS preflight requests, headers, and browser security model.