# HTTP Methods and Their Guarantees — API Design and Versioning

Source: https://www.geekswithgeeks.com/en/api-design/pr-http-methods

> Use GET, POST, PUT, PATCH and DELETE according to their safety and idempotency semantics.

## Safe and idempotent

**Safe** methods do not change server state (`GET`, `HEAD`, `OPTIONS`), so clients, caches and crawlers may call them freely. **Idempotent** methods give the same end state when repeated (`GET`, `PUT`, `DELETE`, and by design `HEAD`/`OPTIONS`), which makes retries safe after a timeout. `POST` is neither: repeating it may create a second resource. `PUT` **replaces** a whole resource at a known URL; `PATCH` applies a **partial** change; `DELETE` removes a resource (deleting something already gone should still be fine). Never use `GET` for state changes, since links, prefetchers and caches will trigger them.

## Method guarantees at a glance

Use this table when deciding which method fits an operation.

```text
Method   Safe  Idempotent  Typical use
GET      yes   yes         read a resource or a collection
HEAD     yes   yes         headers only (check existence, size, ETag)
PUT      no    yes         replace a resource at a known URL
PATCH    no    no*         partial update (*can be made idempotent)
DELETE   no    yes         remove a resource
POST     no    no          create, or run an action
```

## JSON Merge Patch for PATCH, run

I ran this plain-Python example. JSON Merge Patch (RFC 7396) is a simple partial-update format: keys in the patch replace or are added, nested objects merge, and a `null` value deletes the key. Arrays are replaced whole. Here `pin` is removed, `state` added and `tags` replaced.

```python
import hmac, hashlib, json, time, bisect

def merge_patch(target, patch):
    if not isinstance(patch, dict): return patch
    result = dict(target) if isinstance(target, dict) else {}
    for k, v in patch.items():
        if v is None: result.pop(k, None)
        else: result[k] = merge_patch(result.get(k), v)
    return result
doc = {"name": "Asha", "address": {"city": "Pune", "pin": "411001"}, "tags": ["a"]}
print(merge_patch(doc, {"address": {"pin": None, "state": "MH"}, "tags": ["x", "y"], "name": "Asha R"}))

```

Output:

```
{'name': 'Asha R', 'address': {'city': 'Pune', 'state': 'MH'}, 'tags': ['x', 'y']}
```

**Quiz:** Which method is idempotent and replaces a whole resource?

- [ ] OPTIONS
- [ ] POST
- [ ] GET
- [x] PUT

*Answer:* PUT. PUT sets the resource to the given representation, so repeating it leaves the same state.
