You name the parameter in the path with braces, declare it in the function signature with a type hint, and add constraints with Path().
from fastapi import FastAPI, Path
app = FastAPI()
@app.get("/items/{item_id}")
def get_item(
item_id: int = Path(..., gt=0, description="The ID of the item")
):
return {"item_id": item_id}
@app.get("/users/{user_id}/items/{item_id}")
def get_user_item(user_id: int, item_id: int):
return {"user_id": user_id, "item_id": item_id}
FastAPI converts the path segment to the declared type, so item_id arrives as an int, not a string. A value like /items/foo fails the conversion and gets a validation error before your code runs.
Path() adds numeric constraints such as gt for greater than and le for less than or equal. It also takes a description that appears in the docs. Here gt=0 rejects zero and negative IDs.
A route can hold several path parameters, as the second function shows. Routes are matched in declaration order, so /users/me must come before /users/{user_id}.
To allow only a fixed set of values, type the parameter with a class that subclasses str and Enum. Newer code often writes the gt=0 constraint as Annotated[int, Path(gt=0)].
This answer doesn't lend itself to a diagram - it reads best . No credits were charged.
Why there's no diagram: “”
The interactive diagram is below the answer - jump to diagram ↓ · Below it, the related concept . Jump to it ↓
The diagram below the answer is the concept . Jump to it ↓