No history yet

Path Parameters

Dynamic URL Paths

Many APIs need to handle dynamic data. Instead of creating a separate URL for every single user or product, you can create a single path that accepts a variable. These variables in the URL are called path parameters.

For instance, if you have an endpoint to fetch user data, you don't want to write separate functions for /users/1, /users/2, and so on. Instead, you can create a single endpoint like /users/{user_id}, where user_id is a path parameter that can change.

from fastapi import FastAPI

app = FastAPI()

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

In this example, {item_id} in the path decorator corresponds directly to the item_id argument in the read_item function. FastAPI handles the connection automatically.

Automatic Validation

Notice the type hint item_id: int. This isn't just for documentation. FastAPI uses this information to perform data conversion and validation. When a request comes in for /items/5, FastAPI converts the string "5" into the integer 5 before passing it to your function.

What happens if a user tries to visit /items/foo? Since "foo" cannot be converted to an integer, FastAPI automatically intercepts the request and returns a helpful JSON error message, telling the client that the input is invalid. This built-in validation saves you from writing a lot of boilerplate error-handling code.

Using Python type hints is the key to FastAPI's automatic data validation. It ensures the data your function receives is exactly the type you expect.

You can use any standard Python type, like str, float, bool, and more. If you don't specify a type, it will be treated as a string.

Ordering and Specificity

The order of your path operations matters. FastAPI checks paths in the order they are defined. A request will be handled by the first matching path it finds.

Consider these two paths:

# This path is for a specific, logged-in user
@app.get("/users/me")
async def read_current_user():
    return {"user_id": "the current user"}

# This path is for fetching any user by their ID
@app.get("/users/{user_id}")
async def read_user(user_id: str):
    return {"user_id": user_id}

If you defined the /users/{user_id} path before /users/me, a request to /users/me would never reach the read_current_user function. FastAPI would match /users/{user_id} first and interpret "me" as the value for user_id.

Always place fixed, non-variable paths before dynamic paths that might otherwise match the same URL structure.

You can also have multiple path parameters in a single URL. Just define them in both the path decorator and the function signature. Make sure your function arguments match the names used in the path string.

@app.get("/users/{user_id}/items/{item_id}")
async def read_user_item(user_id: int, item_id: str):
    return {"owner": user_id, "item": item_id}

Here, FastAPI correctly routes requests like /users/10/items/abc and passes 10 as an integer and "abc" as a string to the function.

Quiz Questions 1/5

What is the primary purpose of a path parameter in a web API?

Quiz Questions 2/5

Consider the following FastAPI code:

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

What is the server's response when a client sends a GET request to /items/banana?

That's how you can create dynamic and robust API endpoints using path parameters in FastAPI.