Handbooks / REST API Design / Chapter 1
HTTP Methods and Status Codes
7 pages · ~5 min✓ Reviewed
Start here. Next up: Resource Design.
The Request-Response Mental Model
1. The Exchange
- Requestmethod + URL + headers + body?
- Responsestatus line + headers + body?
| Part | Tells you |
|---|---|
| Method | what to do |
| URL | to which resource |
| Status code | how it went |
2. Nouns in URLs, Verbs as Methods
- Resources are nouns:
/users/42 - Methods are the verbs: GET, POST, PUT, PATCH, DELETE
| Avoid | Use |
|---|---|
GET /getUser?id=42 | GET /users/42 |
POST /deleteUser | DELETE /users/42 |
3. Stateless and Self-Contained
- HTTP is stateless: the server keeps no memory between requests
- Each request is self-contained
- Auth and context travel in headers:
Authorization,Cookie
Method semantics are a contract
Clients, caches and proxies rely on them for retrying and caching. Break them (a GET that deletes data) and you get real bugs.
GET, POST, PUT, PATCH and DELETE Semantics
1. The five verbs
| Method | URL | Body | Success |
|---|---|---|---|
| GET | /users/42 | none | 200 |
| POST | /users | new resource | 201 |
| PUT | /users/42 | full copy | 200 or 204 |
| PATCH | /users/42 | changed fields | 200 |
| DELETE | /users/42 | none | 204 or 200 |
2. Read, create, replace
- GET has no body semantics: parameters go in the query string
- POST to the collection: the server picks the ID
- Reply
201 Createdwith aLocationheader - PUT sends the full body to a known URL
- Omitted fields are reset or removed
- PUT creates the resource if missing
http
POST /users {"name":"Asha"}
201 Created
Location: /users/433. Patch and delete
- PATCH changes only the sent fields
PATCH /users/42 {"email":"a@b.com"}keeps the name- DELETE returns
204 No Content(or200with a body) - Deleting again ends in the same state
PUT vs PATCH
PUT replaces the whole resource, so a missing field is lost. PATCH sends only the change.
Safe and Idempotent Methods
1. Two Definitions
- Safe = does not change server state
- GET, HEAD, OPTIONS: crawlers and prefetchers may call them freely
- Idempotent = N identical requests leave the same state as one
2. Who Is What
| Method | Safe | Idempotent |
|---|---|---|
| GET, HEAD, OPTIONS | yes | yes |
| PUT | no | yes |
| DELETE | no | yes |
| POST | no | no |
| PATCH | no | not guaranteed |
- Safe ⊂ idempotent: every safe method is idempotent
- PUT and DELETE: idempotent, not safe
DELETE /users/42twice: same end state, user gone
3. Retrying After a Timeout
GET, PUT, DELETEPOST
- Retrying a payment POST needs an Idempotency-Key header
bash
curl -X POST https://api.x.com/payments \ -H 'Idempotency-Key: 7c1e-42' \ -d '{"amount":500}'
Same key, one charge
A retry with the same key returns the first result, so no duplicate payment.
Status Code Classes and the Common Codes
1. The Five Classes
| Class | Meaning | Next step |
|---|---|---|
| 1xx | Informational | Interim reply |
| 2xx | Success | Done |
| 3xx | Redirection | Follow it or use cache |
| 4xx | Client error | Fix the request |
| 5xx | Server error | Retry may work |
2. Success and Redirects
| Code | Meaning |
|---|---|
| 200 | OK |
| 201 | Created, with Location |
| 204 | No Content, empty body |
| 301 | Permanent redirect |
| 302 / 307 | Temporary redirect; 307 keeps the method |
| 304 | Not Modified, use the cache copy |
3. Client Errors (4xx)
- 400 bad input
- 401 not authenticated
- 403 authenticated, but forbidden
- 404 not found
- 409 conflict
- 422 validation failed
- 429 rate limited
4. Server Errors (5xx)
- 500 unhandled server error
- 502 bad gateway: upstream sent a bad response
- 503 unavailable or overloaded; may send
Retry-After - 504 gateway timeout
401 vs 403
401 = who are you? 403 = I know you, still no.
Headers That Matter and Common Mistakes
1. Headers and Their Failures
| Header | Job | Failure |
|---|---|---|
Content-Type | body you send, e.g. application/json | 415 |
Accept | format you want back | 406 |
Authorization: Bearer <token> | credentials on every request | 401 + WWW-Authenticate |
Location | new or redirected resource | none |
Retry-After | how long to wait | after 429 / 503 |
2. Caching and Locking
Cache-Control: max-age reuses, no-store never cachesETag+If-None-Match: unchanged gives 304If-Matchon PUT = optimistic locking; conflict gives 412
- Server sends ETag
- Client sends If-None-Match
- 304, no body
http
PUT /users/42 If-Match: "v7"
412 if the ETag has changed
3. Common Mistakes
- 200 with an error body
- GET that changes data
- POST for everything
- 500 for bad client input
401 vs 403
401 = not authenticated. 403 = authenticated but forbidden.
HTTP Methods and Status Codes Cheat Sheet
1. Methods
| Method | Use | Safe | Idempotent | OK code |
|---|---|---|---|---|
GET | read | yes | yes | 200 |
POST | create / action | no | no | 201 |
PUT | replace | no | yes | 200 / 204 |
PATCH | partial update | no | not guaranteed | 200 |
DELETE | remove | no | yes | 204 |
2. Codes and Headers
- 4xx client: 400 bad request, 401 who are you, 403 not allowed, 404 missing
- 409 conflict, 422 invalid, 429 slow down
- 5xx server: 500 server bug, 502/504 upstream, 503 overloaded
Content-Typebody sent,Acceptformat wanted,AuthorizationcredentialsCache-Control,ETag/If-None-Matchfor 304 cachingLocationnew resource,Retry-Afterwait after 429 / 503
3. curl
bash
curl -i https://api.x.com/users/42 curl -X POST -H 'Content-Type: application/json' \ -d '{"name":"a"}' https://api.x.com/users
GET, then POST
401 vs 403
401 = not logged in. 403 = logged in, not allowed.
Check yourself
A client times out on PUT /users/42 with a full body, then retries it. Can this create a bad state?
- No: PUT is idempotent, so the second send leaves the same state.
- Same retry on POST /orders could create a duplicate.
POST /payments times out and the client auto-retries. What can go wrong, and what fixes it?
- POST is not idempotent, so the customer may be charged twice.
- Send an
Idempotency-Keyheader so the server ignores the repeat.
A logged-in user without admin rights calls an admin endpoint and gets 401. What is the bug?
- 401 means not authenticated; this user is known but not allowed.
- The correct code is 403 Forbidden