Module 04 / Project 02 — CRUD API¶
Home: README
Learn Your Way¶
| Read | Build | Watch | Test | Review | Visualize | Try |
|---|---|---|---|---|---|---|
| — | This project | — | — | Flashcards | — | — |
Focus¶
GET/POST/PUT/DELETE endpoints, Pydantic models for request validation, proper HTTP status codes.
Why this project exists¶
Most web APIs revolve around four operations: Create, Read, Update, Delete (CRUD). This project builds a todo list API that demonstrates all four. You will learn how Pydantic models validate incoming data automatically, how to return the right HTTP status codes, and how to structure an API that follows REST conventions.
Run¶
Then open http://127.0.0.1:8000/docs to test every endpoint interactively.
Press Ctrl+C to stop the server.
Expected output¶
Using the /docs interface or curl:
# Create a todo
curl -X POST http://127.0.0.1:8000/todos -H "Content-Type: application/json" -d '{"title": "Learn FastAPI"}'
# Returns: {"id": 1, "title": "Learn FastAPI", "completed": false} (status 201)
# List all todos
curl http://127.0.0.1:8000/todos
# Returns: [{"id": 1, "title": "Learn FastAPI", "completed": false}]
# Update a todo
curl -X PUT http://127.0.0.1:8000/todos/1 -H "Content-Type: application/json" -d '{"title": "Learn FastAPI", "completed": true}'
# Returns: {"id": 1, "title": "Learn FastAPI", "completed": true}
# Delete a todo
curl -X DELETE http://127.0.0.1:8000/todos/1
# Returns: (empty, status 204)
Alter it¶
- Add a
descriptionfield (optional string) to the todo model. Make sure it appears in create, update, and response models. - Add a
GET /todos?completed=truequery parameter that filters the list to only completed or only incomplete todos. - Add a
PATCH /todos/{todo_id}endpoint that allows partial updates (only the fields you send get changed).
Break it¶
- Send a POST request with an empty body (no JSON). What error does FastAPI return?
- Send a POST request where
titleis an integer instead of a string. Does Pydantic accept it? Why? - Try to GET, PUT, or DELETE a todo with an ID that does not exist. What happens?
Fix it¶
- The empty body error (422) is correct — Pydantic requires the
titlefield. No fix needed; understand why validation matters. - Pydantic coerces the integer to a string by default. If you want strict validation, use
StrictStrfrom pydantic. Try it and see how the behavior changes. - The 404 response for missing IDs is already handled. If it is not, add a check that raises
HTTPException(status_code=404, detail="Todo not found").
Explain it¶
- What is the difference between
TodoCreate(the request model) andTodoResponse(the response model)? Why use separate models? - Why does the POST endpoint return status code 201 instead of 200?
- Why does the DELETE endpoint return status code 204 with no body?
- How does Pydantic validation work? Where do you define what fields are required vs. optional?
Mastery check¶
You can move on when you can:
- create all four CRUD endpoints from memory,
- explain why separate request and response Pydantic models are a good practice,
- intentionally trigger a 422 validation error and explain the response body,
- describe what status codes 200, 201, 204, 404, and 422 mean.
Related Concepts¶
Next¶
Continue to 03-database-backed.