A number that says how it went
An HTTP status code is a three-digit number a server puts at the top of every response to say how the request went. It tells a program, before it reads anything else, whether to carry on or to stop.
You will learn the five groups of codes, pick the right one, and write an error message a developer can act on.
By the end of this lesson
Note
I can choose the right status code and report an error clearly.
Key words
| Word | What it means | Example |
|---|---|---|
| Status code | a three-digit number saying how a request went | 201 |
| Success | a code starting with 2: the request worked | 200 |
| Client error | a code starting with 4: the request was wrong | 404 |
| Server error | a code starting with 5: the server failed | 500 |
| Error body | the part of the response that explains what went wrong |
The cells students fill in are left blank in this preview.
The first digit gives the group
Codes come in five groups. The first digit says who is responsible.
2xx means it worked. 4xx means the client sent something wrong, so the client must change the request. 5xx means the server failed, so the same request may work later. 3xx means look elsewhere, and 1xx is rare.
Worked example: the five groups
| Group | Meaning | Who acts | Example |
|---|---|---|---|
| 1xx | Information, carry on | Nobody | 100 Continue |
| 2xx | It worked | Nobody | 200 OK |
| 3xx | Go to another address | The client follows it | 301 Moved Permanently |
| 4xx | The request was wrong | The client fixes it | 404 Not Found |
| 5xx | The server failed | The server owner fixes it | 500 Internal Server Error |
The cells students fill in are left blank in this preview.
See the success codes first
Run the next two commands to make a books table. Then each Run prints only the status code of one request.
Give psql the password
export PGPASSWORD=shopShown here, not run. Create a free account to press Run and type it into your own lab’s terminal.
Make the books table
psql -h db -U shop -c "drop table if exists books; create table books (id serial primary key, title text not null, year int not null, available boolean not null default true); insert into books (title, year, available) values ('Maps of the Sea', 1998, true), ('Rivers of Europe', 2004, false), ('Night Trains', 2011, true); notify pgrst, 'reload schema'"Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.
Read the books
curl -s -o /dev/null -w "%{http_code}\n" "http://api:3000/books"Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.
Add a book
curl -s -o /dev/null -w "%{http_code}\n" -X POST -H "Content-Type: application/json" -d '{"title":"Tide Tables","year":2019}' "http://api:3000/books"Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.
Delete book 3
curl -s -o /dev/null -w "%{http_code}\n" -X DELETE "http://api:3000/books?id=eq.3"Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.
Pick the 4xx code that fits
A vague error wastes the developer's time. Pick the most exact code.
400 means the request is malformed. 401 means the caller has not proved who they are. 403 means they are known and not allowed. 404 means there is nothing at that address. 409 means the request clashes with the current state, such as a duplicate. 429 means too many requests.
Worked example: which code for which problem
| Problem | Code |
|---|---|
| The JSON body is broken | 400 |
| No key or token was sent | 401 |
| A valid user may not delete this | 403 |
| Book 999 does not exist | 404 |
| A book with this id is already there | 409 |
| Too many requests this minute | 429 |
The cells students fill in are left blank in this preview.
Send a book with no title
curl -s -o /dev/null -w "%{http_code}\n" -X POST -H "Content-Type: application/json" -d '{"year":2019}' "http://api:3000/books"Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.
Ask for a table that is not there
curl -s -o /dev/null -w "%{http_code}\n" "http://api:3000/nothing"Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.
Add a book with a used id
curl -s -o /dev/null -w "%{http_code}\n" -X POST -H "Content-Type: application/json" -d '{"id":1,"title":"Copy","year":2000}' "http://api:3000/books"Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.
A common mistake
Warning
Many people think an API can answer 200 every time and put the error in the body. Then every client must open every body to learn whether it worked, and tools that watch for failures see none. Use the status code for how it went and the body for why.
A good error body says what and where
The code is for programs. The error body is for the developer. Give every error the same shape.
Say what went wrong, which field it was about, and how to fix it. Never include a stack trace, a file path or a password. Those help an attacker and nobody else.
An error body worth sending (our own design)
HTTP/1.1 400 Bad Request
Content-Type: application/json
{
"error": "invalid_book",
"message": "year must be a whole number",
"field": "year"
}
# This is the lesson's own example, not the lab's output.
# The code says 400. The body says why, and where.Read the lab's own error body
curl -s -w "\n" -X POST -H "Content-Type: application/json" -d '{"title":"Tide Tables","year":"soon"}' "http://api:3000/books"Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.