Path parameters

FastAPI · Essentials · 8 min

Resource URLs such as /users/42 are the backbone of REST APIs, and typed parameters make them safe to use.

Put a name in braces in the path and give the function a parameter with the same name: @app.get("/items/{item_id}") with def read_item(item_id: int). FastAPI extracts that URL segment, and the type hint decides what happens next:

  • For /items/42, the string "42" is converted, so item_id is the int 42.
  • For /items/abc, conversion fails and the client gets a 422 response whose JSON body says which parameter was wrong and why. Your function never runs.

This is the central FastAPI idea: the type hint is documentation, parsing and validation in one. int, float, str, bool, UUID, date and datetime all work out of the box.

When only a fixed set of values is valid, use an Enum that also subclasses str. FastAPI validates against the members, the docs show a dropdown, and your function receives the enum member, so compare with Color.red or read .value.

Path parameters are always required: a URL either has the segment or it matches a different route. A segment can't contain /, unless you use the path converter, {file_path:path}, which matches the rest of the URL including slashes.

Two practical notes. First, route order: with /users/me and /users/{user_id}, declare /users/me first or me is captured as a user id. Second, Pydantic's default conversion is lenient where it's unambiguous ("007" becomes 7) but strict about losing information: "3.5" is rejected for an int rather than truncated.

Example

from enum import Enum
from fastapi import FastAPI
from fastapi.testclient import TestClient

class Color(str, Enum):
    red = "red"
    green = "green"

app = FastAPI()

@app.get("/items/{item_id}")
def read_item(item_id: int):
    return {"item_id": item_id, "type": type(item_id).__name__}

@app.get("/colors/{color}")
def read_color(color: Color):
    return {"color": color.value, "is_red": color is Color.red}

@app.get("/files/{file_path:path}")
def read_file(file_path: str):
    return {"path": file_path}

c = TestClient(app)
print(c.get("/items/42").json())         # {'item_id': 42, 'type': 'int'}
print(c.get("/items/abc").status_code)   # 422
print(c.get("/colors/blue").status_code) # 422: not an enum member
print(c.get("/files/docs/a.txt").json()) # {'path': 'docs/a.txt'}

Remember

  • {name} in the path + a parameter with the same name = path parameter
  • The type hint converts the value; invalid input gets a 422 before your code runs
  • Use a str Enum to restrict a parameter to fixed values
  • {name:path} captures the rest of the URL including slashes

Watch out for

  • Declaring /users/{user_id} before /users/me, so 'me' never reaches its own route.

Check yourself

  1. With def read_item(item_id: int), what does GET /items/007 pass as item_id?
  2. What does GET /items/3.5 return for item_id: int?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: fastapi.tiangolo.com/tutorial/path-params/