As your FastAPI application for serving machine learning models grows, managing all your API endpoints within a single Python file (like main.py) quickly becomes difficult. Code becomes harder to navigate, maintain, and debug. Different logical parts of your API, such as prediction endpoints, status checks, or model management routes, get tangled together.
FastAPI provides a clean solution for this: APIRouter. Think of an APIRouter as a mini FastAPI application. It allows you to group related path operations (endpoints) together, typically in separate Python modules, and then connect them back to your main FastAPI application instance. This modular approach is fundamental for building larger, well-structured services.
An APIRouter works much like the main FastAPI application object. You can define path operations (using decorators like @router.get, @router.post, etc.) on an APIRouter instance just as you would on an app instance.
Let's see how to use it. Imagine you want to separate your model prediction endpoints into their own module.
First, create a new file, for example, routers/predictions.py. Inside this file, you import APIRouter and create an instance:
# routers/predictions.py
from fastapi import APIRouter
from pydantic import BaseModel
# Define your input/output Pydantic models if needed
class PredictionInput(BaseModel):
feature1: float
feature2: str
# ... other features
class PredictionOutput(BaseModel):
prediction: float
probability: float | None = None
# Create the router instance
router = APIRouter()
# Define path operations on the router instance
@router.post("/make", response_model=PredictionOutput)
async def make_prediction(data: PredictionInput):
"""
Accepts input data and returns a model prediction.
(Actual model loading and inference logic would go here)
"""
# Placeholder for model inference logic
prediction_value = 1.0 # Replace with actual model.predict(...)
probability_value = 0.85 # Replace if your model provides probabilities
# Here you would typically:
# 1. Preprocess input data (data.dict())
# 2. Get prediction from your loaded ML model
# 3. Postprocess the result if necessary
# 4. Return the structured output
return PredictionOutput(prediction=prediction_value, probability=probability_value)
@router.get("/info")
async def get_model_info():
"""
Returns basic information about the prediction model.
"""
return {"model_name": "ExamplePredictor", "version": "1.0"}
# You can add more prediction-related endpoints here...
Notice that we use @router.post and @router.get instead of @app.post and @app.get. The function signatures and Pydantic model usage remain exactly the same.
Now, you need to tell your main FastAPI application about this router. In your main.py (or wherever your main FastAPI instance is defined), you import the router object and use the app.include_router() method.
# main.py
from fastapi import FastAPI
from routers import predictions # Import the module containing your router
# Create the main FastAPI application instance
app = FastAPI(
title="ML Model Prediction Service",
description="API for serving predictions from an ML model.",
version="0.1.0"
)
# Include the predictions router
app.include_router(predictions.router)
@app.get("/")
async def read_root():
```python
return {"message": "Prediction API!"}
With this setup, the endpoints defined in `routers/predictions.py` (`/make` and `/info`) are now part of your main application. FastAPI handles the routing internally. When a request comes in for `/make` or `/info`, it will be directed to the corresponding function within the `predictions` router.
### Organizing URLs with Prefixes and Tags
The `include_router` method offers useful parameters for better organization, especially for API documentation and URL structure.
* **`prefix`**: Adds a path prefix to all routes defined in the router. This is excellent for grouping endpoints under a common path segment.
* **`tags`**: Assigns tags to all routes in the router. These tags are used to group operations in the automatic API documentation (like Swagger UI).
Let's modify our `main.py` to use these:
```python
# main.py (updated)
from fastapi import FastAPI
from routers import predictions
app = FastAPI(
title="ML Model Prediction Service",
description="API for serving predictions from an ML model.",
version="0.1.0"
)
# Include the predictions router with a prefix and tags
app.include_router(
predictions.router,
prefix="/predict", # All routes in predictions.router now start with /predict
tags=["Predictions"] # Group these endpoints under 'Predictions' in docs
)
@app.get("/")
async def read_root():
```python
return {"message": "Prediction API!"}
Now, the endpoint previously accessed at `/make` will be available at `/predict/make`, and `/info` will be at `/predict/info`. In your interactive API documentation (usually found at `/docs`), you'll see these endpoints neatly grouped under the "Predictions" tag.
```graphviz
digraph G {
rankdir=LR;
graph [bgcolor=transparent, fontname="Arial"];
node [shape=box, style="rounded,filled", fontname="Arial", fontsize=10, color="#495057", fillcolor="#e9ecef", fontcolor="#495057"];
edge [color="#adb5bd", fontname="Arial", fontsize=9];
subgraph cluster_main {
label = "main.py";
style="filled,rounded";
color="#dee2e6";
bgcolor="#f8f9fa";
main_app [label="app = FastAPI()"];
include_call [label="app.include_router(\n predictions.router,\n prefix='/predict',\n tags=['Predictions']\n)", shape=invhouse];
main_app -> include_call [label=" configures "];
}
subgraph cluster_router {
label = "routers/predictions.py";
style="filled,rounded";
color="#dee2e6";
bgcolor="#f8f9fa";
router_instance [label="router = APIRouter()"];
predict_endpoint [label="@router.post('/make')", shape=ellipse, fillcolor="#a5d8ff"];
info_endpoint [label="@router.get('/info')", shape=ellipse, fillcolor="#a5d8ff"];
router_instance -> predict_endpoint;
router_instance -> info_endpoint;
}
include_call -> router_instance [label=" includes "];
}
Diagram showing the main application including the prediction router module. The
include_routercall specifies a/predictprefix and assigns the 'Predictions' tag.
Using APIRouter is a significant step towards building maintainable and scalable FastAPI applications. It allows you to:
/api/v1/predict/...).As your ML API grows, adopting routers early will save considerable effort in the long run, forming the backbone of a well-organized project structure.
Was this section helpful?
APIRouter for modular application design.APIRouter, specifically for deploying machine learning models and data science solutions.APIRouter helps implement for well-organized API services.© 2026 ApX Machine LearningEngineered with