REST API 03 ๐ HTTP Methods (GET, POST, PUT, PATCH, DELETE)
HTTP methods are the verbs of a REST API. The URI identifies the resource; the method identifies what to do with it. This separation is the core of the uniform interface constraint: the same URI can support multiple operations, and the operation is expressed by the method rather than by a verb in the path . The five methods that matter for REST are GET, POST, PUT, PATCH, and DELETE, and each has a precise contract that determines whether it is safe, idempotent, cacheable, and what status codes it should return.
The distinction between PUT and PATCH is the one that causes the most confusion. PUT replaces the entire resource with the representation in the request body. PATCH applies a partial modification. If you send only the name field in a PUT request, the other fields are set to null or their defaults; if you send only the name in a PATCH request, the other fields are unchanged . The choice between them is a design decision that depends on whether the client has the full representation or only the fields that changed.
Key point: GET retrieves and is safe and idempotent; POST creates and is neither safe nor idempotent; PUT replaces the entire resource and is idempotent but not safe; PATCH partially updates and is not guaranteed idempotent; DELETE removes and is idempotent but not safe. Safety means the method does not change server state; idempotence means repeating the request produces the same result.
Why the method contract matters
The safety problem. A safe method does not change the server’s state. GET is safe: fetching a user does not modify the user. HEAD and OPTIONS are also safe. The safety guarantee is what allows a browser to prefetch a link, a crawler to follow it, or a proxy to cache it without worrying that the request has side effects . A GET endpoint that deletes a resource when called violates this contract and breaks every assumption that caches and crawlers make.
The idempotence problem. An idempotent method produces the same result when called multiple times. PUT /users/42 with the same body twice leaves the resource in the same state as calling it once. DELETE /users/42 twice: the first call deletes the resource, the second returns 404, but the server’s state is the same as after the first call . POST /users is not idempotent: calling it twice creates two users. The idempotence guarantee is what allows a client to retry a request after a network timeout without checking whether the original request succeeded.
The cacheability problem. Only GET and HEAD are cacheable by default. A GET response can be stored by the browser, a proxy, or a CDN and reused for later requests. A POST response is not cached, because the next POST might create a different resource . The Cache-Control header can override the default, but the method’s cacheability is the starting point.
The status code problem. Each method has a set of expected status codes. GET returns 200 OK or 404 Not Found. POST returns 201 Created with a Location header pointing to the new resource, or 200 OK if the result is returned in the body. PUT returns 200 OK or 204 No Content. PATCH returns 200 OK or 204 No Content. DELETE returns 204 No Content or 200 OK . Using the wrong status code is the second most common REST API mistake after putting verbs in URIs.
a. GET: retrieve a representation
GET retrieves a representation of a resource. It is safe (does not change state), idempotent (calling it twice has the same effect as once), and cacheable (responses can be stored). It should never have a request bodyโthe HTTP specification says the semantics of a body on a GET request are undefined, and some servers and intermediaries reject it .
GET /users/42 HTTP/1.1
Host: api.example.com
Accept: application/json
HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: max-age=300
ETag: "abc123"
{
"id": 42,
"name": "Alice",
"email": "alice@example.com"
}
The Accept header tells the server what representation formats the client can handle. The Cache-Control and ETag headers are the caching contract. If the client sends a second request with If-None-Match: "abc123" and the resource has not changed, the server returns 304 Not Modified with no body.
GET on a collection returns a list. GET on an individual resource returns one representation. GET on a non-existent resource returns 404 Not Found. A GET request that returns 200 OK with an error message in the body is a violation of the contractโthe status code must reflect the outcome.
b. POST, PUT, and PATCH: the write methods
POST creates a new resource in a collection. The URI is the collection, not the individual resource, because the server assigns the identifier. The response includes the Location header with the new resource’s URI.
POST /users HTTP/1.1
Content-Type: application/json
{
"name": "Bob",
"email": "bob@example.com"
}
HTTP/1.1 201 Created
Location: /users/43
Content-Type: application/json
{
"id": 43,
"name": "Bob",
"email": "bob@example.com"
}
POST is neither safe nor idempotent. Calling it twice creates two users. This is why clients must not retry a POST blindly after a timeoutโthe original request may have succeeded, and a retry would create a duplicate. The Idempotency-Key header is one solution: the client generates a unique key, and the server treats requests with the same key as the same operation .
PUT replaces the entire resource. The URI is the individual resource, and the body contains the full representation. If the client sends only some fields, the missing fields are set to null or their defaults.
PUT /users/42 HTTP/1.1
Content-Type: application/json
{
"name": "Alice Updated",
"email": "alice.new@example.com"
}
HTTP/1.1 200 OK
Content-Type: application/json
{
"id": 42,
"name": "Alice Updated",
"email": "alice.new@example.com"
}
PUT is idempotent: sending the same body twice leaves the resource in the same state. It is not safe. If the resource does not exist, PUT can create it at the specified URI, which is why some APIs use PUT for upserts. The decision of whether PUT creates or returns 404 depends on the API’s design.
PATCH partially updates the resource. The body contains only the fields that should change. The format of the body is not standardized by HTTP; the two common formats are JSON Merge Patch (application/merge-patch+json) and JSON Patch (application/json-patch+json) .
PATCH /users/42 HTTP/1.1
Content-Type: application/merge-patch+json
{
"email": "alice.new@example.com"
}
HTTP/1.1 200 OK
Content-Type: application/json
{
"id": 42,
"name": "Alice",
"email": "alice.new@example.com"
}
JSON Merge Patch is the simpler format: the body is a partial representation, and the fields present are updated, the fields absent are unchanged. JSON Patch is more expressive: the body is an array of operations (add, remove, replace, move, copy, test), each with a path and a value. JSON Patch is not idempotent in general because the operations can depend on the current state, but it can be used idempotently if the operations are designed that way.
c. DELETE: remove a resource
DELETE removes a resource. It is idempotent: deleting the same resource twice has the same effect on the server’s state as deleting it once. The first call returns 204 No Content or 200 OK; the second returns 404 Not Found because the resource no longer exists. The server state is the same after both calls, which is why DELETE is considered idempotent despite the different status code .
DELETE /users/42 HTTP/1.1
Host: api.example.com
HTTP/1.1 204 No Content
DELETE is not safe, because it changes the server’s state. It should not have a request body in most casesโthe URI identifies the resource, and the method identifies the action. A soft delete (marking the resource as deleted without removing it) is a common pattern, but it changes the semantics: a soft-deleted resource may still be returned by GET unless the API filters it out.
The response for DELETE should be 204 No Content if there is no body to return, or 200 OK with a body if the server returns a summary of the deletion. Returning 200 OK with an empty body is technically valid but less common than 204.
Complete Example Session
The following session demonstrates all five methods against a single resource and shows the status codes and headers for each.
// ============================================
// PART 1: CREATE (POST)
// ============================================
POST /users HTTP/1.1
Content-Type: application/json
{ "name": "Alice", "email": "alice@example.com" }
HTTP/1.1 201 Created
Location: /users/42
Content-Type: application/json
{ "id": 42, "name": "Alice", "email": "alice@example.com" }
// POST creates a new resource; the server assigns the ID
// ============================================
// PART 2: RETRIEVE (GET)
// ============================================
GET /users/42 HTTP/1.1
Accept: application/json
HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: max-age=300
ETag: "v1"
{ "id": 42, "name": "Alice", "email": "alice@example.com" }
// GET is safe, idempotent, and cacheable
// ============================================
// PART 3: REPLACE (PUT)
// ============================================
PUT /users/42 HTTP/1.1
Content-Type: application/json
{ "name": "Alice Smith", "email": "alice.smith@example.com" }
HTTP/1.1 200 OK
Content-Type: application/json
{ "id": 42, "name": "Alice Smith", "email": "alice.smith@example.com" }
// PUT replaces the entire resource
// ============================================
// PART 4: PARTIAL UPDATE (PATCH)
// ============================================
PATCH /users/42 HTTP/1.1
Content-Type: application/merge-patch+json
{ "email": "alice.new@example.com" }
HTTP/1.1 200 OK
Content-Type: application/json
{ "id": 42, "name": "Alice Smith", "email": "alice.new@example.com" }
// PATCH updates only the provided field; name is unchanged
// ============================================
// PART 5: REMOVE (DELETE)
// ============================================
DELETE /users/42 HTTP/1.1
HTTP/1.1 204 No Content
// DELETE removes the resource; no body is returned
// ============================================
// PART 6: IDEMPOTENCE IN PRACTICE
// ============================================
DELETE /users/42 HTTP/1.1
HTTP/1.1 404 Not Found
// The second DELETE returns 404, but the server state
// is the same as after the first call, so DELETE is idempotent
// POST /users twice:
POST /users HTTP/1.1
{ "name": "Bob", "email": "bob@example.com" }
// โ 201 Created, Location: /users/43
POST /users HTTP/1.1
{ "name": "Bob", "email": "bob@example.com" }
// โ 201 Created, Location: /users/44
// Two resources created, so POST is not idempotent
The six parts demonstrate each method’s contract: POST creates and returns 201 with a Location header; GET retrieves and returns 200 with caching headers; PUT replaces and returns 200; PATCH partially updates and leaves other fields unchanged; DELETE removes and returns 204; and the idempotence comparison shows that DELETE twice has the same server state while POST twice creates two resources.
Quick Reference
Method Properties
| Method | Safe | Idempotent | Cacheable | Has Body |
|---|---|---|---|---|
| GET | Yes | Yes | Yes | No |
| POST | No | No | No | Yes |
| PUT | No | Yes | No | Yes |
| PATCH | No | Not guaranteed | No | Yes |
| DELETE | No | Yes | No | No |
Status Codes by Method
| Method | Success | Error |
|---|---|---|
| GET | 200 OK | 404 Not Found |
| POST | 201 Created + Location | 400 Bad Request, 409 Conflict |
| PUT | 200 OK or 204 No Content | 404 Not Found, 409 Conflict |
| PATCH | 200 OK or 204 No Content | 404 Not Found, 422 Unprocessable |
| DELETE | 204 No Content or 200 OK | 404 Not Found |
PUT vs PATCH
| Aspect | PUT | PATCH |
|---|---|---|
| Scope | Full replacement | Partial update |
| Missing fields | Set to null/default | Unchanged |
| Idempotent | Yes | Not guaranteed |
| Media type | application/json | application/merge-patch+json or application/json-patch+json |
Choosing a Method
| Goal | Method |
|---|---|
| Read a resource | GET |
| Create a new resource | POST |
| Replace a resource entirely | PUT |
| Update specific fields | PATCH |
| Remove a resource | DELETE |
Best Practices
โ Do This:
GET /users/42 # Safe, idempotent, cacheable
POST /users # Create, return 201 + Location
PUT /users/42 # Full replace, idempotent
PATCH /users/42 # Partial update with merge-patch
DELETE /users/42 # Idempotent remove, 204
โ Don’t Do This:
GET /users/42/delete # Action in URI, violates safety
POST /users/42 # Creating at an existing ID
PUT /users/42 { "name": "x" } # Partial body to PUT loses other fields
GET /users/42 with body # Body on GET is undefined
POST twice as a retry # Creates duplicates
Common Pitfalls
| Pitfall | Why It Happens | Fix |
|---|---|---|
| GET with side effects | Using GET to delete | Use DELETE |
| PUT with partial body | Confused with PATCH | Send full representation or use PATCH |
| POST retry creates duplicates | Not idempotent | Idempotency-Key header |
| Wrong status code | Returning 200 for errors | Use 4xx/5xx |
| PATCH without media type | Ambiguous format | Set Content-Type |
Real-World Examples
1. Get a resource
GET /users/42
2. List a collection
GET /users
3. Create a resource
POST /users
4. Replace a resource
PUT /users/42
5. Partial update
PATCH /users/42
6. Delete a resource
DELETE /users/42
7. Merge patch media type
Content-Type: application/merge-patch+json
8. Create response with Location
HTTP/1.1 201 Created
Location: /users/43
9. Delete response
HTTP/1.1 204 No Content
10. Idempotency key
Idempotency-Key: 9c1f-4e2a
Visual
Method Properties
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ SAFE (no state change) โ
โ GET, HEAD, OPTIONS โ
โ โ
โ IDEMPOTENT (same result if repeated) โ
โ GET, PUT, DELETE, HEAD, OPTIONS โ
โ โ
โ POST: neither safe nor idempotent โ
โ PATCH: not guaranteed idempotent โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
PUT vs PATCH
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Resource: { name: "Alice", email: "a@x" } โ
โ โ
โ PUT /users/42 โ
โ { "name": "Bob" } โ
โ โ { name: "Bob", email: null } โ
โ (email lost because PUT replaces) โ
โ โ
โ PATCH /users/42 โ
โ { "name": "Bob" } โ
โ โ { name: "Bob", email: "a@x" } โ
โ (email unchanged because PATCH merges) โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Idempotence
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ PUT /users/42 { "name": "Bob" } โ state A โ
โ PUT /users/42 { "name": "Bob" } โ state A โ
โ (same result, idempotent) โ
โ โ
โ POST /users { "name": "Bob" } โ 2 users โ
โ POST /users { "name": "Bob" } โ 3 users โ
โ (different result, not idempotent) โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Status Code Flow
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ POST โ 201 Created + Location โ
โ GET โ 200 OK (or 404) โ
โ PUT โ 200 OK (or 204) โ
โ PATCHโ 200 OK (or 204) โ
โ DELETEโ 204 No Content (or 404) โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Summary
| Item | Value |
|---|---|
| GET | Safe, idempotent, cacheable, no body |
| POST | Creates, not safe, not idempotent |
| PUT | Replaces entire resource, idempotent |
| PATCH | Partial update, not guaranteed idempotent |
| DELETE | Removes, idempotent |
| POST success | 201 Created + Location |
| DELETE success | 204 No Content |
| PUT/PATCH success | 200 OK or 204 |
| Safety | No state change |
| Idempotence | Same result if repeated |
Key takeaways:
- The method is the verb; the URI is the noun. The same URI supports multiple methods, each with a different contract. The action is never in the path .
- GET is safe, idempotent, and cacheable. It must not change server state and must not have a body. A GET with side effects breaks caches, crawlers, and prefetching .
- POST is neither safe nor idempotent. It creates a new resource, and calling it twice creates two resources. Retries require an
Idempotency-Keyor a client-side check . - PUT replaces; PATCH updates. A PUT request with a partial body nulls out the missing fields. A PATCH request with a partial body leaves the missing fields unchanged. The choice depends on whether the client has the full representation .
- DELETE is idempotent despite the status code. The first call returns 204, the second returns 404, but the server state is the same after both. This is the definition of idempotence .
- Status codes are part of the contract. POST returns 201 with Location, GET returns 200 or 404, DELETE returns 204, and errors return 4xx or 5xx. A 200 with an error body is a violation .
Remember: HTTP methods are not arbitrary labels. Each has a precise contractโsafe or not, idempotent or not, cacheable or notโand the contract determines how clients, caches, and intermediaries treat the request. GET retrieves and is safe. POST creates and is not idempotent. PUT replaces and is idempotent. PATCH partially updates and is not guaranteed idempotent. DELETE removes and is idempotent. The PUT/PATCH distinction is the one that causes the most bugs: a partial body sent to PUT silently nulls the missing fields, while the same body sent to PATCH leaves them unchanged. The status codes are not decorationโthey are how the client knows whether the request succeeded, and returning 200 for every outcome defeats the entire purpose of the protocol.
Stop using slow, ad-bloated tool sites! ๐คฎ
๐ Search “KandZ Tools” on Google to use many professional utilities for free.
KandZ.me is the ultimate minimalist hub for:
โ
Finance (Mortgage, Interest, Inflation)
โ
Tech (Base64, JSON, Dev Suite, IP)
โ
Health (BMI, BMR, TDEE)
โ
Productivity (Timer, Workspace, QR)
โก๏ธ Fast & Private
๐ No data leaves your device
๐ 100% Free
๐ Use it now: https://tools.kandz.me
๐ Bookmark itโyouโll need it later!