Skip to content

Status Codes & Errors

How an API reports outcomes is part of its contract. Two things make that contract trustworthy: the status code (the part clients branch on) and a consistent error body (the part humans and code read to recover).

flowchart TD
  Q{Did the request succeed?} -->|Yes| S[2xx]
  Q -->|No, caller's fault| C[4xx: fix the request]
  Q -->|No, our fault| E[5xx: retry may help]
  C --> C1[400 / 401 / 403 / 404 / 409 / 422]
  E --> E1[500 / 503]
First decide the family, then the specific code

The single most important rule: never wrap a failure in a 200. A response that says 200 OK but carries { "error": "..." } defeats every client, cache, and monitoring tool that trusts the status line.

  • Choosing status codes — the common ones and how to pick between close calls.
  • Error format (problem+json) — one consistent shape for every error.
  • Validation errors — reporting bad input field by field.
  • Error handling in TypeScript — turning thrown errors into clean responses.
A 5xx status code signals what?
Why is returning 200 with an error body a problem?