Skip to main content

Path Operation Registration

When you define an endpoint in FastAPI, you are registering a "path operation." This registration process links a URL path and an HTTP method (like GET or POST) to a specific function in your code. FastAPI provides several ways to do this, ranging from high-level decorators to programmatic methods for dynamic route generation.

Decorator-based Registration

The most common way to register a path operation is using decorators on a FastAPI instance. These decorators correspond to HTTP verbs and are implemented as methods on the FastAPI class in fastapi/applications.py.

from fastapi import FastAPI

app = FastAPI()

@app.get("/items/")
def read_items():
return [{"name": "Empanada"}, {"name": "Arepa"}]

When you use @app.get("/items/"), FastAPI internally delegates this call to its underlying APIRouter instance. The FastAPI class defines methods for all standard HTTP verbs:

  • @app.get()
  • @app.post()
  • @app.put()
  • @app.delete()
  • @app.patch()
  • @app.options()
  • @app.head()
  • @app.trace()

Each of these decorators accepts a path and a variety of configuration parameters that control both the runtime behavior (like status codes) and the generated OpenAPI schema (like tags and summaries).

Programmatic Registration with add_api_route

If you need to register routes dynamically—for example, if you are generating endpoints based on a configuration file or a database—you can use the add_api_route() method. This is the underlying mechanism that the decorators use.

You can find examples of this in tests/test_extra_routes.py:

from fastapi import FastAPI

app = FastAPI()

def get_not_decorated(item_id: str):
return {"item_id": item_id}

# Registering the route without a decorator
app.add_api_route("/items-not-decorated/{item_id}", get_not_decorated)

The add_api_route method requires the path and the endpoint (the function to call). It also accepts the same keyword arguments as the decorators, such as methods (a list of HTTP methods like ["GET", "POST"]), response_model, and status_code.

Generic Route Registration with api_route

For scenarios where a single function should handle multiple HTTP methods, or when the method is determined by a variable, use the @app.api_route() decorator.

@app.api_route("/items/{item_id}", methods=["GET", "POST"])
def handle_item(item_id: str):
return {"item_id": item_id}

This decorator is useful when you want to group logic for different methods within a single endpoint function while still benefiting from FastAPI's automatic validation and documentation.

Path Operation Configuration

Registration methods allow you to configure how the endpoint behaves and how it appears in the interactive documentation (Swagger UI).

Status Codes and Responses

You can define the default success status code using the status_code parameter. This is useful for POST requests that should return 201 Created.

@app.post("/items/", status_code=201)
def create_item(name: str):
return {"name": name}

Metadata for Documentation

Parameters like tags, summary, and description are used by FastAPI to organize and describe your API in the OpenAPI schema.

@app.get("/users/", tags=["users"], summary="Retrieve all users")
def read_users():
"""
This description will be extracted from the docstring
if the 'description' parameter is not provided.
"""
return [{"username": "johndoe"}]

If you don't provide a description argument, FastAPI automatically extracts it from the function's docstring, as seen in the implementation of FastAPI.get in fastapi/applications.py.

Internal Architecture

The FastAPI class inherits from Starlette's Starlette application but overrides the routing logic to use fastapi.routing.APIRouter.

When you instantiate FastAPI, it creates a self.router attribute:

# From fastapi/applications.py
self.router: routing.APIRouter = routing.APIRouter(
# ... configuration ...
)

Every registration method on the app instance (like app.get or app.add_api_route) is a proxy that calls the corresponding method on self.router. This architecture allows FastAPI to maintain a clean separation between the application-level configuration (like OpenAPI metadata) and the core routing logic.

Redirect Slashes

By default, FastAPI (via the router) handles trailing slashes automatically. If you register /items/ and a client requests /items, FastAPI will redirect them to /items/ with a 307 status code. This behavior is controlled by the redirect_slashes parameter in the FastAPI constructor.

app = FastAPI(redirect_slashes=False)

Strict Content-Type

FastAPI implements strict checking for the Content-Type header via the strict_content_type parameter. When enabled (the default), requests with a body that lack a Content-Type header will not be parsed as JSON, which helps prevent certain types of CSRF attacks.