FastAPI Basics: Build Your First Web API
Path and Query Parameters
In this lesson you will
- Use path parameters with type conversion
- Add optional and required query parameters with defaults
- Constrain values and read the validation errors FastAPI produces
Introduction
Data reaches an API in several places. Two of the most common are the path (/books/42) and the query string (/search?q=python&limit=5). FastAPI reads both from your function's parameters, converts them to the types you declare and rejects bad input with a clear error. All outputs below come from running this code.
Path parameters
Python
@app.get("/books/{book_id}")
def get_book(book_id: int):
return {"book_id": book_id}A request to /books/42 returns {"book_id": 42}. The text 42 arrived as a string, and FastAPI converted it to an integer because of the hint.
If the value cannot be converted, for example /books/abc, FastAPI answers with status 422 (Unprocessable Content) and a JSON error:
JSON
{"detail": [{"type": "int_parsing", "loc": ["path", "book_id"],
"msg": "Input should be a valid integer, unable to parse string as an integer",
"input": "abc"}]}You wrote no error handling, yet the client gets a precise message saying where (path, book_id) and why.
Query parameters
Function parameters that are not in the path are treated as query parameters.
Python
@app.get("/search")
def search(q: str, limit: int = 10, in_stock: bool = False):
return {"q": q, "limit": limit, "in_stock": in_stock}q: strhas no default, so it is required.limit: int = 10andin_stock: bool = Falsehave defaults, so they are optional.
Results from running it:
| Request | Status | Body |
|---|---|---|
/search?q=python | 200 | {"q": "python", "limit": 10, "in_stock": false} |
/search?q=python&limit=5&in_stock=true | 200 | {"q": "python", "limit": 5, "in_stock": true} |
/search | 422 | error: query q, "Field required" |
Notice that in_stock=true became the Python value True. FastAPI accepts common forms such as true, 1, yes and on.
Quick quiz
In def search(q: str, limit: int = 10), which query parameter is required?
Constraints
Use Query and Path with Annotated to add rules such as minimum and maximum.
Python
from typing import Annotated
from fastapi import Query
@app.get("/items")
def items(limit: Annotated[int, Query(ge=1, le=100)] = 10):
return {"limit": limit}ge means greater than or equal, and le means less than or equal. A request for /items?limit=500 gets status 422 with the message "Input should be less than or equal to 100".
Other useful options include min_length, max_length, pattern for strings, and description, which appears in the docs.
Order of routes matters
FastAPI checks routes in the order you define them. If you have /books/me and /books/{book_id}, define /books/me first, or me will be treated as a book id.
Why validation at the edge matters
Rejecting bad input immediately keeps your logic simple and safer: later code can trust that limit is an integer between 1 and 100. Never trust data from the client, even after type conversion, for security-sensitive decisions such as who may see which record. Later lessons cover authentication.
Try it yourself
Add /greet/{name} with an optional query parameter shout: bool = False. If shout is true, return the name in capitals. Use /docs to test it, then try an invalid request and read the error.
Summary
- Parameters in the path template are path parameters, and other function parameters are query parameters.
- Type hints convert values, defaults make parameters optional and no default makes them required.
- Constraints with Query and Path reject bad input with detailed 422 errors, and route order matters.
Lesson complete
+20 XP
Nice work. Keep going while it is fresh.
Sources and further reading