HTTP Methods

Understanding RESTful operations: GET, POST, PUT, PATCH, DELETE, and OPTIONS

Last Updated:

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
OPTIONS N/A ✅ Yes ✅ Yes ❌ No Optional

*PATCH can be made idempotent depending on implementation

GET - Retrieve Resources

GET
Safe Idempotent Cacheable

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

GET /api/v1/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

GET /api/v1/users/123
{
  "id": 123,
  "name": "John Doe",
  "email": "john@example.com",
  "created_at": "2023-01-15T10:30:00Z"
}

Get with Query Parameters

GET /api/v1/users?status=active&role=admin&page=2&limit=10
{
  "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

POST
Not Safe Not Idempotent

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

POST /api/v1/users

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

POST /api/v1/orders

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

PUT
Not Safe Idempotent

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)

PUT /api/v1/users/123

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

PATCH
Not Safe Not Idempotent*

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

PATCH /api/v1/users/123

Request Body:

{
  "email": "newemail@example.com"
}

Update Order Status

PATCH /api/v1/orders/456

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):

PATCH/api/v1/posts/42
{ "view_count": { "increment": 1 } }  // Each call adds 1 — NOT idempotent

Idempotent PATCH (set absolute value — prefer):

PATCH/api/v1/posts/42
{ "status": "published" }  // Same result every time — idempotent

Upsert: 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

PUT/api/v1/users/123/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

PUT/api/v1/config/feature-flags
// 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)

PATCH/api/v1/users/123/settings
// 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

ScenarioMethodReason
Client knows the ID, replace entire resourcePUTIdempotent, semantically correct
Client knows the ID, update partial fieldsPATCHBandwidth efficient
Server assigns the IDPOSTServer controls URI
Sync/replicate resource statePUTFull replacement ensures consistency

DELETE - Remove Resources

DELETE
Not Safe Idempotent

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

DELETE /api/v1/users/123

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

DELETE /api/v1/posts/789

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

OPTIONS
Safe Idempotent

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

OPTIONS /api/v1/users

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

HEAD

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
TRACE

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
CONNECT

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.

❌ Bad (RPC-style) POST /api/getUser?id=123
POST /api/deleteOrder?id=456
POST /api/updateUserStatus
✅ Good (REST-style) GET /api/users/123
DELETE /api/orders/456
PATCH /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.

❌ Bad GET /api/users
Body: { "filter": { "status": "active" } }
✅ Good 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.

✅ Good — Idempotency key for POST POST /api/payments
Idempotency-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.

✅ Good — Document cascade behavior 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.