APIs for AIFastAPI 0.141 · httpx2 2.13 · Python 3.10+
0%
1
Curious builder0 XP earned · 300 to level 2
0 daysFinish a lesson to begin
Badge collection0 of 6 unlocked
19 small wins to finish your pathNext lesson

HTTPException and response models

Lesson 5 ended with a crash for a ticket that does not exist. An API should say not found, with a 404, and should never send fields the caller has no business seeing.

Exampletickets.py
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel

app = FastAPI()
TICKETS = {1: {"id": 1, "customer": "Asha", "text": "I was charged twice", "notes": "VIP"}}


class TicketOut(BaseModel):
    id: int
    customer: str
    text: str


@app.get("/tickets/{ticket_id}", response_model=TicketOut)
def get_ticket(ticket_id: int):
    if ticket_id not in TICKETS:
        raise HTTPException(status_code=404, detail="ticket not found")
    return TICKETS[ticket_id]

raise HTTPException(status_code=404, ...) stops the function and sends that status with detail as the body. It is the raise from the Python course, and FastAPI turns it into a response instead of a crash.

response_model=TicketOut passes whatever the function returns through TicketOut before sending it. The stored ticket has a private notes field; the model does not, so it is left out.

Example
from fastapi.testclient import TestClient
from tickets import app

client = TestClient(app)
for ticket_id in (1, 9):
    response = client.get(f"/tickets/{ticket_id}")
    print(response.status_code, response.json())

The 404 is now a decision your code made, with a message a client can show. And VIP never left the service.

Choosing the status code

A POST that creates something should answer 201, created. Pass it in the decorator: @app.post("/tickets", status_code=201). The status code is part of what your API promises, so clients can check it without reading the body.

The API describes itself

Example
schema = app.openapi()
print(list(schema["paths"]))
print(list(schema["paths"]["/tickets/{ticket_id}"]["get"]["responses"]))

FastAPI builds an OpenAPI description of every endpoint from your code: paths, parameters, models and responses. 422 is listed because a path parameter can fail validation. Lesson 8 shows the page it generates from this.

Try it yourself
  • Remove response_model=TicketOut and fetch ticket 1 again.
  • Raise HTTPException(status_code=403, detail="not your ticket") for ticket 1.
  • Add status_code=201 to a POST endpoint from lesson 6 and check the status.

You understood something today that you didn't yesterday.