awesome-everything RU
↑ Back to the climb

APIs

Status codes: reading HTTP exchanges

Crux Read real HTTP exchanges — status line, headers, and body together — and pick what the response actually says and the highest-leverage fix.
Your altitude — climbing toward senior
ZeroJuniorMiddleSenior
You are at senior altitude — in orbit
◷ 14 min

Status codes are diagnosed on the wire, in the raw exchange. Read each request/response pair — line, headers, body — and decide what it really says and what a senior would change first.

Goal

Practise the on-the-wire reading loop: spot when the status and the body disagree, when a header is missing, and when the code attributes fault to the wrong side — then name the fix.

Exchange 1 — the 200 that is really a failure

POST /v1/payments HTTP/1.1
Content-Type: application/json

{ "amount": 4200, "currency": "usd" }

HTTP/1.1 200 OK
Content-Type: application/json

{ "ok": false, "error": "upstream_timeout", "code": "GATEWAY_DOWN" }
Quiz

The upstream timed out, yet the status line is 200. What is the consequence and the fix?

Exchange 2 — 401 vs 403

DELETE /tenants/acme/users/77 HTTP/1.1
Authorization: Bearer eyJhbGc...   # valid, non-expired token for user in tenant 'globex'

HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer

{ "error": "you may not delete users in another tenant" }
Quiz

The token is valid; the caller simply lacks permission for another tenant. What is wrong with this response, and what should it be?

Exchange 3 — 503 without Retry-After, and a hot retry loop

GET /catalog/items?page=3 HTTP/1.1

HTTP/1.1 503 Service Unavailable
Content-Type: application/json

{ "error": "overloaded, shedding load" }

# client behaviour: immediately re-issues the GET in a tight loop, no delay
Quiz

The server is shedding load with 503 but sent no Retry-After, and the client retries instantly. What are the two fixes — one per side?

Exchange 4 — conditional update and 412

PUT /docs/42 HTTP/1.1
If-Match: "v7"
Content-Type: application/json

{ "title": "Q3 plan", "body": "..." }

HTTP/1.1 412 Precondition Failed

# the stored ETag is now "v9" — someone else saved twice since the client last read
Quiz

The conditional PUT returns 412 because the ETag moved from v7 to v9. What does this tell the client, and what should it do?

Recap

On the wire, read the status line, headers, and body as one unit. A 200 with an error body lies to every machine that branches on status — return the real 5xx. 401 vs 403 turns on authentication vs authorization, and getting it wrong loops the client. A 503 should carry Retry-After, and a client without one must back off with jitter rather than hammer. A 412 is optimistic concurrency working — refetch, reconcile against the new ETag, and retry the conditional write rather than forcing the overwrite.

Continue the climb ↑Status codes: ship an honest API
shortcuts expand
search
K
prev piece
k
next piece
j
cycle tier
t
this menu
?
sources2
expand
  1. 01
  2. 02

Trademarks belong to their respective owners. Editorial reference only.