4xx: The Problem Is on Your Side
One request works. Vera asks Tandem for the station at Old Market, with her key in the header, and gets the object back: capacity 24, nine bikes free. That single working request is the control specimen for this entire page, because now it gets broken on purpose — five different ways, each with its own three digits and its own fix that takes about thirty seconds.
Picture the counter at a city office, and the slips they hand back. Your form is illegible, so nothing can be read from it. You have no identity document at all. You have one, but it is for a different department. There is no such office at this address. Or the form is perfectly legible and says your date of birth is tomorrow. Five refusals, five different queues to fix them in — and being able to tell them apart on sight is most of what "good with APIs" means in practice.
| Status | What it means | The thirty-second fix |
|---|---|---|
200 | read, allowed, answered | nothing — this is the control |
400 | could not read what you sent | fix the shape: quotes, commas, encoding |
401 | who are you? | send the key in the Authorization header |
403 | you, specifically, may not | email Jonas — this one is paperwork |
404 | nothing lives at this address | compare your path with the docs, character by character |
422 | read it, refused the values | fix the field the message names |
The Request That Works
Start from success, so every break has something to be measured against. Vera's key rides in the Authorization header exactly as Chapter 5 established, the path names one station by its code, and the answer is a 200 with the station object inside it.
curl -i -H "Authorization: Bearer tnd_live_..." \
https://api.tandem.example/v1/stations/st_014
HTTP/1.1 200 OK
Content-Type: application/json
{"id": "st_014", "name": "Old Market", "capacity": 24, "free_bikes": 9}
Keep that shape in mind. Everything below changes exactly one thing about it, and every change earns a different number.
400 and 422: the Request Itself Is Wrong
These two are a pair, and the difference between them is the difference between illegible and impossible. A 400 means the server could not read what arrived: a body with a missing quotation mark, a bracket that never closes, a query string mangled by an unencoded space. The request never got as far as meaning anything.
A 422 means the opposite kind of failure. The server read your request perfectly and understood every part of it, then refused the contents. Vera asks for a page of stations and writes the word "nine" where a count belongs; the request is flawless as a piece of text and nonsense as an instruction. The status is 422, and the message names the field: the limit has to be a whole number.
Both are fixed the same way — read the message, correct the thing it names, resend once. The reason the two exist separately is that they point at different halves of your work: one at how the request was assembled, one at what you asked for.
401: Who Are You?
Take the key out of a rides request and Tandem stops recognizing anyone. The status is 401, and the honest translation is not "you are not allowed" but "you have not said who you are." An anonymous caller asking about public stations is fine; an anonymous caller asking about rides is not, because rides sit behind the door Chapter 5 opened.
The other common cause is a credential that used to work: a token past its expiry, which is why "it worked yesterday" is the most-reported symptom in support inboxes everywhere. Either way the fix is one header — the whole of Chapter 5, compressed into a single line you already know how to write.
# 401 - no key at all, on an endpoint that requires one curl -i https://api.tandem.example/v1/rides/rd_7c29 # 403 - a read-only key asking to cancel a reservation curl -i -X DELETE -H "Authorization: Bearer tnd_live_..." \ https://api.tandem.example/v1/reservations/res_9d04 # 404 - one character wrong in the path curl -i -H "Authorization: Bearer tnd_live_..." \ https://api.tandem.example/v1/station/st_014 # 422 - a word where a number belongs curl -i -H "Authorization: Bearer tnd_live_..." \ "https://api.tandem.example/v1/stations?limit=nine"
403: You, Specifically, May Not
A 403 is the one beginners lose afternoons to, because it looks like a 401 and behaves nothing like one. Here Tandem knows exactly who is calling. Vera's key is valid, her account is in good standing, and the answer is still no — because the key was issued read-only, and she has just asked to cancel a reservation.
The distinction pays cash. A 401 is fixed by typing: add the header, resend, done. A 403 cannot be fixed by typing at all. It is fixed by paperwork — an email to Jonas asking for the write permission to be added to her key. Recognizing which of the two you are holding saves you from retyping the same request harder for an hour, which is a thing everybody does exactly once.
404: Nothing Lives Here
A 404 has four common causes and they are worth separating. The first and by far the most frequent is a typo in the path — Vera writes /station/st_014 without the s, and there is no such collection at Tandem. The second is sending the documentation's placeholder as literal text: the reference page writes {id} to mean "your value goes here", and copying the braces along produces a tidy 404. The third is the honest case: the path is perfect and the station genuinely does not exist, perhaps because it was decommissioned last spring. And the fourth is subtler: some APIs answer 404 instead of 403 for things you are not allowed to see, so that the 404 itself does not confirm the thing exists.
All of them arrive as the same three digits, and the endpoint line in the documentation resolves which one you have in under a minute. Notice also what a 404 is not: it is not the API being down. The API answered you. Something has to be running to say "nothing lives here".
The Family Habit
Every 4xx gets the same four-beat treatment. Stop. Read the body, because it names the problem. Fix your side. Resend once. That is the routine, and it works whether the status is one of the five above or something rarer you meet years from now.
The one thing you never do is loop. A 4xx is deterministic: the identical request will earn the identical refusal, on the first attempt and the sixtieth. Retrying a refusal is not persistence, it is a very slow way of asking the same question. The one you will actually meet that rewards waiting rather than editing is 429, the one that means you are asking too often — it gets its own page in the next chapter, at Riverport's Friday rush hour. (A handful of rarer 4xx codes, 408 for instance, also clear on their own.) Every other member of the family wants a change, not a repeat.
- "401 and 403 are two names for access denied." Not identified versus identified but not permitted. One is fixed with a header you type yourself; the other with a permission request to the provider. Different fixes, so the distinction is worth real money.
- "A 404 means the API is down." The API answered, which is the opposite of down. This address has nothing at it, overwhelmingly because of a path typo, and it is the fastest of the five to fix.
- "Retrying might work — the internet is flaky." Flakiness lives in the 5xx family and in timeouts. A 4xx is a considered decision about your request, so the same request gets the same answer every time. Change something, or stop.
- "400 and 422 are interchangeable in practice." They point at different halves of your work: one says the request could not be read at all, the other says it was read fine and its values were rejected. The message field tells you which repair you are doing.
- These five statuses are the daily weather of working with APIs. Sorting them on sight, without looking anything up, is the bulk of what people mean when they call someone good with APIs.
- One setup broken five ways gives you a permanent test bench. Any unfamiliar error you meet later can be slotted next to one of these five and handled the same way.
Knowledge Check
What separates a 400 from a 422?
- A 400 blames your request and a 422 blames the server that received it
- A 400 could not be read at all; a 422 was read and its values refused
- A 400 means the key is missing and a 422 means the key has expired
- A 400 is permanent while a 422 clears on its own after a short wait
Vera's key is valid, and her attempt to cancel a reservation answers 403. What does that tell her?
- Tandem could not work out who was calling, so it refused the request
- She was recognized, and her key's scope does not cover writes
- The reservations endpoint is at a different address than the one she used
- She has sent more requests this minute than her key is allowed
Which is the most common cause of a 404 in everyday API work?
- The provider's servers are down and cannot serve any addresses right now
- A typo in the path you sent, such as a missing letter or a stray plural
- Your key was left out, so the server refuses to reveal the address
- A parameter carrying a word where the docs expect a number
Why is retrying a 4xx a waste of time?
- Because repeated failures make the provider suspend your key permanently
- Because the identical request earns the identical refusal, attempt after attempt
- Because every retry costs the provider more than the original request did
- Because a 4xx response takes far longer to arrive on the second attempt
You got correct