Skip to main content

FastAPI Operation Parameters

When building APIs, you often need to receive information from the client to provide customized responses. In FastAPI, these inputs are called "operation parameters" and they form a crucial part of creating flexible, powerful API endpoints.

Introduction to Operation Parameters

Operation parameters allow your API endpoints to receive data from the client through various methods. FastAPI provides a rich way of defining these parameters with built-in validation, documentation, and type conversions.

There are several types of operation parameters in FastAPI:

  • Path parameters
  • Query parameters
  • Request body parameters
  • Header parameters
  • Cookie parameters
  • Form data
  • File uploads

In this guide, we'll focus on the most common ones: path parameters, query parameters, and how to properly define and validate them.

Path Parameters

Path parameters are parts of the URL path that are variable and can be captured by the application. They're defined within curly braces {} in the path specification.

Basic Path Parameters

python
from fastapi import FastAPI

app = FastAPI()

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

When a request comes to /items/42, FastAPI will:

  1. Match the URL to the path operation pattern /items/{item_id}
  2. Parse 42 from the URL path
  3. Validate it against the int type annotation
  4. Call the function with item_id=42
  5. Return the response {"item_id": 42}

If we try to access /items/foo, FastAPI will return an error because foo cannot be converted to an integer.

Path Parameter Validation

We can add more validation constraints to path parameters using Pydantic's Field function:

python
from fastapi import FastAPI, Path

app = FastAPI()

@app.get("/items/{item_id}")
async def read_item(
item_id: int = Path(..., title="The ID of the item", ge=1)
):
return {"item_id": item_id}

Here, ge=1 ensures that item_id must be greater than or equal to 1. If someone tries to access /items/0, they'll get a validation error.

Query Parameters

Query parameters are the key-value pairs that appear after the ? in a URL. Unlike path parameters, they're optional by default.

Basic Query Parameters

python
from fastapi import FastAPI

app = FastAPI()

@app.get("/items/")
async def read_items(skip: int = 0, limit: int = 10):
return {"skip": skip, "limit": limit}

In this example:

  • If we access /items/?skip=20&limit=30, we'll get {"skip": 20, "limit": 30}
  • If we access /items/ (without parameters), we'll get {"skip": 0, "limit": 10}

Optional vs. Required Query Parameters

By default, query parameters are optional. To make them required, don't provide a default value:

python
from fastapi import FastAPI

app = FastAPI()

@app.get("/items/")
async def read_items(q: str):
return {"q": q}

Now, a request to /items/ without the q parameter will result in an error.

Query Parameter Validation

Similar to path parameters, we can add validation to query parameters:

python
from fastapi import FastAPI, Query

app = FastAPI()

@app.get("/items/")
async def read_items(
q: str = Query(
None,
min_length=3,
max_length=50,
title="Query string",
description="Query string for the items to search"
)
):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results

This adds validation rules and documentation for the q parameter:

  • It must be at least 3 characters long
  • It must be at most 50 characters long
  • It's optional (default is None)

Multiple Parameters

You can combine different types of parameters in a single endpoint:

python
from fastapi import FastAPI, Path, Query

app = FastAPI()

@app.get("/items/{item_id}")
async def read_item(
item_id: int = Path(..., title="The ID of the item", ge=1),
q: str = Query(None, max_length=50),
short: bool = False
):
item = {"item_id": item_id}
if q:
item.update({"q": q})
if not short:
item.update(
{"description": "This is an amazing item that has a long description"}
)
return item

This endpoint:

  1. Takes a required path parameter item_id that must be at least 1
  2. Takes an optional query parameter q with a maximum length of 50
  3. Takes an optional boolean query parameter short

Real-world Example: Product Filtering API

Let's create a more practical example of a product filtering API:

python
from fastapi import FastAPI, Query, Path
from enum import Enum
from typing import Optional, List

app = FastAPI()

class SortOrder(str, Enum):
asc = "asc"
desc = "desc"

class Category(str, Enum):
electronics = "electronics"
clothing = "clothing"
books = "books"
home = "home"

# Sample product database
products = [
{"id": 1, "name": "Laptop", "price": 999.99, "category": "electronics"},
{"id": 2, "name": "T-shirt", "price": 19.99, "category": "clothing"},
{"id": 3, "name": "Python Cookbook", "price": 39.99, "category": "books"},
{"id": 4, "name": "Coffee Maker", "price": 89.99, "category": "home"},
{"id": 5, "name": "Smartphone", "price": 699.99, "category": "electronics"},
]

@app.get("/products/")
async def get_products(
category: Optional[Category] = None,
min_price: float = Query(None, ge=0),
max_price: float = Query(None, ge=0),
sort_by: str = Query("id", regex="^(id|name|price)$"),
sort_order: SortOrder = SortOrder.asc,
skip: int = Query(0, ge=0),
limit: int = Query(10, ge=1, le=100),
):
filtered_products = products.copy()

# Apply category filter
if category:
filtered_products = [p for p in filtered_products if p["category"] == category]

# Apply price filters
if min_price is not None:
filtered_products = [p for p in filtered_products if p["price"] >= min_price]
if max_price is not None:
filtered_products = [p for p in filtered_products if p["price"] <= max_price]

# Apply sorting
filtered_products.sort(
key=lambda x: x[sort_by],
reverse=(sort_order == SortOrder.desc)
)

# Apply pagination
paginated_products = filtered_products[skip:skip + limit]

return {
"total": len(filtered_products),
"skip": skip,
"limit": limit,
"products": paginated_products
}

@app.get("/products/{product_id}")
async def get_product(
product_id: int = Path(..., ge=1, title="The ID of the product to fetch")
):
for product in products:
if product["id"] == product_id:
return product
return {"error": "Product not found"}

This API showcases:

  1. Enum parameters for predefined options
  2. Numeric validation for price ranges
  3. Regex validation for sort fields
  4. Pagination using skip/limit
  5. Required path parameters with validation
  6. Optional query parameters with defaults

Advanced Parameter Features

Default Values and Ellipsis

When defining parameters, you'll often see either default values or ...:

python
# Optional parameter with default value
q: str = "default"

# Required parameter (ellipsis tells FastAPI this parameter is required)
q: str = ...
# or using Query
q: str = Query(...)

Declaring Metadata

You can add metadata to your parameters to enhance API documentation:

python
@app.get("/items/")
async def read_items(
q: str = Query(
None,
title="Query string",
description="Query string for the items to search",
deprecated=True # Mark as deprecated in the docs
)
):
return {"q": q}

List/Array Parameters

To receive multiple values for the same query parameter:

python
from typing import List

@app.get("/items/")
async def read_items(q: List[str] = Query(None)):
return {"q": q}

Example requests:

  • /items/?q=foo&q=bar{"q": ["foo", "bar"]}

Summary

FastAPI's operation parameters provide a powerful way to:

  1. Capture data from client requests through paths, queries, and more
  2. Automatically validate this data based on type annotations
  3. Add constraints to ensure data quality and security
  4. Generate interactive documentation for your API

By understanding how to properly define and use operation parameters, you can create APIs that are both flexible for clients and robust against invalid input.

Additional Resources

Exercises

  1. Create an API endpoint that accepts a user ID as a path parameter and returns information about that user.
  2. Create a search endpoint that filters a list of items based on multiple query parameters (name, category, price range).
  3. Modify the product filtering API to support additional filtering criteria like name search with partial matching.
  4. Create an API endpoint that accepts a list of IDs as a query parameter and returns all items with matching IDs.


If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)