Status codes in practice

Reading · 6 min · Module 2, lesson 3 of 526 min left in this module

Module 2 · APIsLesson 3 of 5

Goal: Choose the right status code for success, bad input, not found, auth and server errors.

Key idea

When you write an API, the status code is part of the contract. A client decides what to do from the code before it reads the body, so the code has to say who needs to act: nobody (2xx), the client (4xx) or you (5xx).

Lesson 1.6.2 covers what the families mean. This lesson is about picking one.

Success: 200, 201 or 204

  • 200 OK: it worked, and here's the result. The default for a GET, and for an update that returns the changed thing.
  • 201 Created: a POST made something new. Return the new thing, id included, so the client doesn't have to ask again.
  • 204 No Content: it worked and there's nothing to say, typical after a DELETE. A 204 has no body.

Bad input: 400, 415 or 422

The request reached you and it's wrong. Say why in the body, in words the client can act on:

  • 400 Bad Request: the general answer. A required field is missing, or the JSON doesn't parse.
  • 415 Unsupported Media Type: the body isn't in a format you accept, for example no Content-Type: application/json.
  • 422 Unprocessable Content: some APIs use this when the JSON parses but a value breaks a rule, like a due date in the past. Pick one of 400 or 422 for that and use it everywhere.

Not found: 404

404 Not Found: nothing at that path, including a real path with an id that doesn't exist, like /notes/99 when there's no note 99. Don't answer 200 with an empty body: the client would think it got a note.

Auth: 401 or 403

  • 401 Unauthorized: who are you? The token is missing, expired or wrong. Logging in again can fix it.
  • 403 Forbidden: I know who you are, and you can't do this. Logging in again won't help.

Server errors: 500 or 503

  • 500 Internal Server Error: your code failed. Log the details and send the client a plain message, never the stack trace or the database error.
  • 503 Service Unavailable: you can't take requests right now, for example while a database you depend on is down. The client can try again later.

Check yourself

A signed-in user asks to delete another user's note. Which code?
POST /notes succeeds and creates note 12. What's the best response?