Unlock Your Python Backend Career: Build 30 Projects in 30 Days. Join now for just $54

HTTP Status Codes for Clear API Responses

by Jane Nkwor

.

Updated Fri Jun 27 2025

.
HTTP Status Codes for Clear API Responses

Learn how to use HTTP status codes effectively in your FastAPI projects for clear, consistent API responses.

Introduction

APIs (Application Programming Interfaces) are essential for software, enabling communication between clients and servers. Most web APIs, especially RESTful APIs, operate over the HTTP protocol, which defines how data is transmitted across the internet. HTTP not only facilitates data exchange but also includes status codes, which tell clients what happened on the server. The HTTP status codes are three-digit codes that summarize the result of a request.

Whether you're building a backend with FastAPI or consuming an external service, understanding and using the right HTTP status codes helps ensure clear communication, better debugging, and a professional API interface.

HTTP Methods in APIs

HTTP methods define the type of operation a client wants to perform on a resource. Pairing them with the correct status codes improves clarity.

Method

Use Case

Example

GET

Retrieve data

GET /books

POST

Create new data

POST /books

PUT

Replace a resource entirely

PUT /books/1

PATCH

Partially update a resource

PATCH /books/1

DELETE

Delete a resource

DELETE /books/1

Common HTTP Status Codes

Here are some commonly used HTTP status codes in API development:

  • 200 OK – Request Successful

  • 201 Created – A resource was successfully created

  • 204 No Content – Success, but no data returned

  • 400 Bad Request – Validation errors (Client sent invalid input)

  • 401 Unauthorized – Authentication failure(Missing or invalid credentials)

  • 403 Forbidden – Access denied (Not allowed)

  • 404 Not Found – Resource not found

  • 409 Conflict – Resource state conflict

  • 422 Unprocessable Entity – Validation failed (common with Pydantic)

  • 500 Internal Server Error – Server crashed or encountered an unexpected error

Using HTTPException for Custom Errors

FastAPI allows you to raise exceptions with specific status codes using HTTPException :

from fastapi import FastAPI, HTTPException

app = FastAPI()

@app.get("/books/{book_id}")
async def read_book(book_id: int):
	# Simulate checking a database for the book
    if book_id != 1:
    # Raise a 404 if the book is not found
        raise HTTPException(status_code=404, detail="Book not found")
    return {"book_id": book_id, "title": "The Hobbit"}

In this example, when a client requests a specific book, the server checks if it exists (in this case, only book with ID 1 exists). If it doesn’t, we raise a 404 Not Found, letting the client know the resource doesn’t exist. This is clearer than returning a generic 200 OK with a confusing response.

Handling Validation Errors (422)

FastAPI uses Pydantic for input validation. If the input doesn't meet the model’s expected structure or data types, FastAPI automatically returns a 422 status code. This helps you avoid manually checking data types in every route.

from pydantic import BaseModel

class Book(BaseModel):
    title: str # Title must be a string
    pages: int # Pages must be an integer
@app.post("/books")
def create_book(book: Book):
    return book

Try sending invalid input like:

{"title": "Book", "pages": "not-a-number"}

FastAPI will respond with a 422: Unprocessable entity error.

Returning Custom Status Codes

To customize the status code in a response, use the status_code parameter:

from fastapi import status

@app.post("/books", status_code=status.HTTP_201_CREATED)
def add_book(book: Book):
    return {"message": "Book created successfully"}

Using 201 Created tells the client that a new resource was successfully created, which is more specific than 200 OK.

Custom Exception Handlers

By default, FastAPI will return a standard error structure when input validation fails. But in some cases (e.g., when building an API for a frontend app), you may want to customize the error response to fit your frontend’s expected structure.

You can define a handler for RequestValidationError, returning a structured JSON with a human-readable message ("Validation failed") and additional details.

from fastapi import FastAPI, Request
from fastapi.responses import JSONResponse
from fastapi.exceptions import RequestValidationError
from pydantic import BaseModel

app = FastAPI()

# Custom Exception Handler
@app.exception_handler(RequestValidationError)
async def validation_exception_handler(request: Request, exc: RequestValidationError):
    return JSONResponse(
        status_code=422,
        content={
            "message": "Validation failed",
            "errors": exc.errors(),
            "body": exc.body,
        },
    )

# Pydantic Model
class Book(BaseModel):
    title: str
    pages: int

# Route expecting valid input
@app.post("/books")
async def create_book(book: Book):
    return {"message": "Book created", "book": book}

How it works

When a client sends an invalid request,

{
"title": "Purple Hibiscus",
"pages": "not-a-number"
}

FastAPI will:

  • Detect the invalid pages value (should be an int)

  • Trigger RequestValidationError

  • Use your custom validation_exception_handler to return a structured error.

Example of Custom Response

{
  "message": "Validation failed",
  "errors": [
    {
      "type": "int_parsing",
      "loc": [
        "body",
        "pages"
      ],
      "msg": "Input should be a valid integer, unable to parse string as an integer",
      "input": "A string"
    }
  ],
  "body": {
    "title": "string",
    "pages": "A string"
  }
}

Using status Module for Clean Code

Avoid hardcoding status codes. Use the fastapi.status module for improved readability. FastAPI provides a built-in status module that contains named constants for all standard HTTP status codes. Instead of writing "magic numbers" like 404 or 403 directly in your code, you can use readable constants like:

status.HTTP_404_NOT_FOUND
status.HTTP_403_FORBIDDEN
status.HTTP_201_CREATED
from fastapi import status

raise HTTPException(
		status_code=status.HTTP_403_FORBIDDEN, 
		detail="Access denied"
		)

FAQ: HTTP Status Codes in FastAPI

Q: What status code should I return when data is created?

A: Use 201 Created to indicate that a resource was successfully created.

Q: What does 422 Unprocessable Entity mean?

A: It means the input was syntactically valid but semantically incorrect—often used when validation fails.

Q: How do I raise a 404 error in FastAPI?

A: Use raise HTTPException(status_code=404, detail="Not found").

Q: What’s the difference between 401 and 403?

A: 401 Unauthorized means no or invalid credentials; 403 Forbidden means valid credentials but no permission.

Conclusion

Using the right HTTP status codes in your API makes your application more predictable, user-friendly, and easier to debug. FastAPI makes it easy to handle errors the right way:

  • Use standard status codes consistently.

  • Prefer descriptive errors over vague responses.

  • Add custom error handlers for better control.

  • Use the status module to avoid magic numbers.

For production-ready APIs, also consider logging, monitoring, and documenting your error responses consistently.

TL;DR

  • Use HTTPException to raise clear, standard errors.

  • Customize responses with status_code, detail, or exception handlers.

  • Let Pydantic and FastAPI handle validation automatically (422).

References

Whenever you're ready

There are 4 ways we can help you become a great backend engineer:

The MB Platform

Join 1000+ backend engineers learning backend engineering. Build real-world backend projects, learn from expert-vetted courses and roadmaps, track your learnings and set schedules, and solve backend engineering tasks, exercises, and challenges.

The MB Academy

The “MB Academy” is a 6-month intensive Advanced Backend Engineering BootCamp to produce great backend engineers.

Join Backend Weekly

If you like post like this, you will absolutely enjoy our exclusive weekly newsletter, Sharing exclusive backend engineering resources to help you become a great Backend Engineer.

Get Backend Jobs

Find over 2,000+ Tailored International Remote Backend Jobs or Reach 50,000+ backend engineers on the #1 Backend Engineering Job Board

Backend Tips, Every week

Backend Tips, Every week