Skip to course content
Free FastAPI backend course

FastAPI for AI Backend Development

Unit 03.01: Status codes the client can act on

The status code is what a client can act on without parsing anything.

Eleven codes, and which are worth retrying

Each code with what the client should do next.

The code lists them and extracts the retryable ones.

CODES = [
    (200, "OK",                    "the request succeeded"),
    (201, "Created",               "and a resource now exists; include its location"),
    (204, "No Content",            "succeeded, deliberately no body"),
    (400, "Bad Request",           "malformed; do not retry unchanged"),
    (401, "Unauthorized",          "no valid credentials; authenticate"),
    (403, "Forbidden",             "authenticated, not allowed; do not retry"),
    (404, "Not Found",             "no such resource"),
    (422, "Unprocessable Entity",  "well-formed, failed validation"),
    (429, "Too Many Requests",     "slow down; Retry-After says how long"),
    (500, "Internal Server Error", "our fault; retry may work"),
    (503, "Service Unavailable",   "temporarily down; retry with backoff"),
]
print(f"{'code':>5} {'name':22} what the client should do")
for code, name, action in CODES:
    print(f"{code:>5} {name:22} {action}")

retryable = [c for c, _, a in CODES if "retry" in a and "do not" not in a]
print(f"\nworth retrying: {retryable}")
print("A client cannot decide any of this from a 200 with an error in the body.")

422 against 400 is the distinction most often collapsed: 400 means the request was malformed, 422 means it parsed and failed validation. A client can present the second to a user and can only log the first.

A client cannot decide any of this from a 200 with an error inside the body - which is what an API returns when nobody thought about status codes.

The mistake this prevents

The mistake is returning 200 with {"success": false}. Every intermediary - proxies, retry libraries, monitoring - treats it as a success, so your error rate reads as zero while callers fail.

Takeaway

Use the status code to tell the client what to do. A 200 carrying an error makes your failures invisible to every layer between you and the caller.