Skip to content

Sub-applications

FasterAPI's include_router lets you split your API across multiple files and routers, each mounted under a shared prefix.

Basic router

# items/router.py
from FasterAPI import FasterRouter, HTTPException
import msgspec

router = FasterRouter()

_items: dict[int, dict] = {}


class Item(msgspec.Struct):
    name: str
    price: float


@router.get("/", tags=["items"])
async def list_items():
    return list(_items.values())


@router.post("/", status_code=201, tags=["items"])
async def create_item(item: Item):
    new_id = len(_items) + 1
    _items[new_id] = {"id": new_id, **msgspec.structs.asdict(item)}
    return _items[new_id]


@router.get("/{item_id}", tags=["items"])
async def get_item(item_id: int):
    if item_id not in _items:
        raise HTTPException(status_code=404, detail="Not found")
    return _items[item_id]
# main.py
from FasterAPI import Faster
from items.router import router as items_router
from users.router import router as users_router

app = Faster(title="Multi-router API")

app.include_router(items_router, prefix="/items")
app.include_router(users_router, prefix="/users", tags=["users"])

Router with prefix and tags

All routes registered through the router inherit the prefix and tags passed to include_router:

# The router's @router.get("/") becomes GET /items/
# @router.get("/{item_id}") becomes GET /items/{item_id}
app.include_router(items_router, prefix="/items", tags=["items"])

Multiple versions

from v1.router import router as v1_router
from v2.router import router as v2_router

app.include_router(v1_router, prefix="/v1")
app.include_router(v2_router, prefix="/v2")

Nested routers

# admin/users.py
admin_users_router = FasterRouter()

# admin/__init__.py
from FasterAPI import FasterRouter
from .users import admin_users_router

admin_router = FasterRouter()
# Include nested router — FasterRouter.include_router mirrors app.include_router

Currently FasterRouter does not expose include_router directly; nest via app.include_router with different prefixes:

app.include_router(admin_users_router, prefix="/admin/users", tags=["admin"])
app.include_router(admin_settings_router, prefix="/admin/settings", tags=["admin"])
myproject/
├── main.py               # create Faster() app, include_router calls
├── dependencies.py       # shared Depends() callables
├── models.py             # shared msgspec.Struct definitions
├── items/
│   ├── __init__.py
│   ├── router.py         # FasterRouter with /items routes
│   └── models.py
├── users/
│   ├── __init__.py
│   ├── router.py
│   └── models.py
└── auth/
    ├── __init__.py
    └── router.py

See Bigger Applications for a fully-worked example.

ASGI sub-applications

Mount a completely separate ASGI app (e.g. another FasterAPI instance or a third-party ASGI app) by routing a prefix manually:

admin_app = Faster(title="Admin API", docs_url="/docs")

# Dispatch /admin/* to admin_app
@app.get("/admin/{rest_of_path:path}")
async def admin_proxy(rest_of_path: str, request: Request):
    # adjust scope and dispatch
    ...

For full ASGI mounting, wrap at the ASGI level outside FasterAPI using a helper like a2wsgi or write a custom router.

Next steps