Methods & The Status Code Zoo
GET, POST, PUT, PATCH, DELETE. 200s through 500s. When to return what.
HTTP has seven core methods and about thirty status codes you'll see in real life. Most developers can name GET, POST, and 404and call it a day. That's not enough. The methods carry promises ("safe", "idempotent") that proxies and clients rely on. The codes form a small grammar that good APIs speak fluently. Let's learn the whole vocabulary.
The seven methods
A method is a verb. The URL is the noun. GET /users/42 means "fetch user 42." Here are all seven you need to know:
- GET - read a resource. Should never change server state.
- HEAD - same as GET but the server only returns headers, no body. Used to check if a resource exists, its size, or its last-modified date without downloading it.
- POST - create a new resource, or trigger a side effect. Not idempotent: calling it twice creates two things.
- PUT - replace a resource entirely at a known URL. Idempotent.
- PATCH - partial update. Send only the fields that change. Idempotency depends on the payload format.
- DELETE- remove a resource. Idempotent (deleting an already-deleted thing is still "deleted").
- OPTIONS - ask the server which methods are allowed. Browsers use this for CORS preflight (covered in the cookies/CORS lesson).
Idempotent= doing it N times has the same effect as doing it once. GET, HEAD, OPTIONS, PUT, DELETE are idempotent. POST is not. PATCH usually isn't.
PUT vs POST vs PATCH - the question that won't die
The shortest correct rule:
- POST when the server decides the new URL.
POST /articlesreturns the article with a new id. - PUTwhen the client knows the URL and wants to replace what's there.
PUT /articles/42replaces it. - PATCH when the client knows the URL and only wants to change a few fields.
PATCH /articles/42with{ title: 'New title' }.
# Create - server assigns the id
POST /articles
{"title": "Hello"}
# 201 Created, Location: /articles/42
# Replace
PUT /articles/42
{"title": "Hello v2", "body": "..."}
# Partial update
PATCH /articles/42
{"title": "Hello v3"}The status code zoo
Status codes are grouped by their first digit. Learn the families first, then the specific codes.
- 1xx - informational (you can ignore for now).
- 2xx - success.
- 3xx - redirection.
- 4xx - you, the client, did something wrong.
- 5xx - the server did something wrong.
2xx - it worked
- 200 OK - generic success with a body. The default.
- 201 Created - POST or PUT created a new resource. Should include a
Locationheader with the new URL. - 204 No Content- success but the response has no body. Common after a DELETE or a PATCH where you don't want to ship data back.
- 206 Partial Content - response to a range request, used for video seeking and resumable downloads.
3xx - go look somewhere else
- 301 Moved Permanently - this URL has a new permanent home. Browsers and search engines cache this aggressively.
- 302 Found- temporary redirect. Don't cache it. Historically vague about whether the method should change on redirect, which is why 307 and 308 exist.
- 303 See Other- after a POST, redirect to a GET. The classic "Post/Redirect/Get" pattern that prevents duplicate form submissions.
- 304 Not Modified- "your cached copy is still good." Returned from conditional GETs (covered in the next lesson).
- 307 Temporary Redirect - like 302 but the method is preserved. POST stays a POST.
- 308 Permanent Redirect - like 301 but the method is preserved.
4xx - the client messed up
- 400 Bad Request- malformed input. JSON didn't parse, a required field was missing.
- 401 Unauthorized- you didn't prove who you are. Misnamed: this really means "unauthenticated."
- 403 Forbidden- we know who you are, you just can't do this.
- 404 Not Found- the resource doesn't exist here. Don't use this for "you don't have access" unless you want to hide existence.
- 405 Method Not Allowed- the URL exists but doesn't support this method.
POST /users/42on a read-only endpoint. - 409 Conflict - your request collides with current state. Double-creating a thing with a unique key. Editing a stale version.
- 410 Gone- like 404 but stronger: this used to exist and we deliberately removed it. Don't come back.
- 422 Unprocessable Content- the request was syntactically valid (JSON parsed fine) but the semantics are off (email field wasn't an email). Most APIs use this for validation errors.
- 429 Too Many Requests - rate-limited. Should include a
Retry-Afterheader.
403= "I know exactly who you are, and you can't." Returned when an authenticated user lacks permission. Sending the request again won't help. Log in as someone else.
5xx - the server messed up
- 500 Internal Server Error- generic "something blew up." The default when an unhandled exception escapes.
- 502 Bad Gateway- a proxy or load balancer couldn't reach the upstream server, or got a malformed response.
- 503 Service Unavailable - server is temporarily overloaded or in maintenance. Should include a
Retry-Afterheader. - 504 Gateway Timeout- a proxy reached the upstream but it didn't respond in time.
418 - the teapot
418 I'm a teapotis from a 1998 April Fool's RFC about brewing coffee. It is not a real status code. Some APIs ship it as an Easter egg. Google's servers return 418 for /teapot. Try not to use it in production. Probably.
Which code should I return? A decision tree
- Did the request even reach your handler?
- No, the route doesn't exist → 404.
- Yes, but the method is wrong → 405.
- Is the user authenticated?
- No credentials / bad credentials → 401.
- Is the user allowed to do this?
- No → 403.
- Is the input syntactically valid?
- JSON didn't parse, missing required field → 400.
- Is the input semantically valid?
- Email field isn't an email → 422.
- Does it conflict with current state?
- Duplicate unique key, stale version → 409.
- Is the user being too noisy?
- Over rate limit → 429.
- Did everything work?
- Created something new → 201.
- Did something but won't return a body → 204.
- Returning data → 200.
- Did your code blow up?
- Unhandled exception → 500.
- Upstream timed out → 504.
- Down for maintenance → 503.
200 OK with { error: '...' } in the body. This breaks every monitoring tool, every cache, and every well-written client. Use real status codes.Quiz
Which methods are idempotent?
Recap
- Seven methods. Safe = no state change. Idempotent = same end state on retry.
- POST creates, PUT replaces, PATCH partially updates, DELETE removes, OPTIONS asks what's allowed.
- 2xx = success, 3xx = redirect, 4xx = client error, 5xx = server error.
- 401 = who are you? 403= you can't do that. They are not synonyms.
- Use the decision tree. Don't return 200 with an error body.
- 418 is a joke. Don't use it.