0
# API Routing
1
2
The APIRouter class enables modular organization of API endpoints into logical groups with shared configuration like prefixes, tags, dependencies, and responses. Routers can be nested hierarchically and included in the main FastAPI application or other routers.
3
4
## Capabilities
5
6
### APIRouter Class
7
8
Router class for grouping related endpoints with shared configuration and hierarchical organization.
9
10
```python { .api }
11
class APIRouter:
12
def __init__(
13
self,
14
*,
15
prefix: str = "",
16
tags: Optional[List[Union[str, Enum]]] = None,
17
dependencies: Optional[Sequence[Depends]] = None,
18
default_response_class: Type[Response] = Default(JSONResponse),
19
responses: Optional[Dict[Union[int, str], Dict[str, Any]]] = None,
20
callbacks: Optional[List[BaseRoute]] = None,
21
routes: Optional[List[BaseRoute]] = None,
22
redirect_slashes: bool = True,
23
default: Optional[ASGIApp] = None,
24
dependency_overrides_provider: Optional[Any] = None,
25
route_class: Type[APIRoute] = APIRoute,
26
on_startup: Optional[Sequence[Callable]] = None,
27
on_shutdown: Optional[Sequence[Callable]] = None,
28
lifespan: Optional[Callable] = None,
29
deprecated: Optional[bool] = None,
30
include_in_schema: bool = True,
31
generate_unique_id_function: Callable[[APIRoute], str] = Default(generate_unique_id)
32
):
33
"""
34
Create an APIRouter instance.
35
36
Parameters:
37
- prefix: URL prefix for all routes in this router
38
- tags: List of tags applied to all routes in this router
39
- dependencies: List of dependencies applied to all routes in this router
40
- default_response_class: Default response class for all routes
41
- responses: Default additional responses for all routes
42
- callbacks: List of callback routes
43
- routes: List of route instances to include
44
- redirect_slashes: Automatically redirect URLs with trailing slashes
45
- default: Default ASGI app to call for unmatched routes
46
- dependency_overrides_provider: Provider for dependency overrides
47
- route_class: Class to use for API routes
48
- on_startup: Functions to run on router startup (deprecated)
49
- on_shutdown: Functions to run on router shutdown (deprecated)
50
- lifespan: Async context manager for router lifespan events
51
- deprecated: Mark all routes in this router as deprecated
52
- include_in_schema: Include all routes in OpenAPI schema
53
- generate_unique_id_function: Function to generate unique operation IDs
54
"""
55
```
56
57
### HTTP Method Decorators
58
59
Decorators for defining HTTP endpoints within the router with the same functionality as FastAPI application decorators.
60
61
```python { .api }
62
def get(
63
self,
64
path: str,
65
*,
66
response_model: Any = Default(None),
67
status_code: Optional[int] = None,
68
tags: Optional[List[Union[str, Enum]]] = None,
69
dependencies: Optional[Sequence[Depends]] = None,
70
summary: Optional[str] = None,
71
description: Optional[str] = None,
72
response_description: str = "Successful Response",
73
responses: Optional[Dict[Union[int, str], Dict[str, Any]]] = None,
74
deprecated: Optional[bool] = None,
75
operation_id: Optional[str] = None,
76
response_model_include: Optional[IncEx] = None,
77
response_model_exclude: Optional[IncEx] = None,
78
response_model_by_alias: bool = True,
79
response_model_exclude_unset: bool = False,
80
response_model_exclude_defaults: bool = False,
81
response_model_exclude_none: bool = False,
82
include_in_schema: bool = True,
83
response_class: Type[Response] = Default(JSONResponse),
84
name: Optional[str] = None,
85
callbacks: Optional[List[BaseRoute]] = None,
86
openapi_extra: Optional[Dict[str, Any]] = None,
87
generate_unique_id_function: Callable[[APIRoute], str] = Default(generate_unique_id)
88
) -> Callable[[DecoratedCallable], DecoratedCallable]:
89
"""Create a GET endpoint decorator within this router."""
90
91
def post(self, path: str, **kwargs) -> Callable:
92
"""Create a POST endpoint decorator within this router."""
93
94
def put(self, path: str, **kwargs) -> Callable:
95
"""Create a PUT endpoint decorator within this router."""
96
97
def delete(self, path: str, **kwargs) -> Callable:
98
"""Create a DELETE endpoint decorator within this router."""
99
100
def patch(self, path: str, **kwargs) -> Callable:
101
"""Create a PATCH endpoint decorator within this router."""
102
103
def options(self, path: str, **kwargs) -> Callable:
104
"""Create an OPTIONS endpoint decorator within this router."""
105
106
def head(self, path: str, **kwargs) -> Callable:
107
"""Create a HEAD endpoint decorator within this router."""
108
109
def trace(self, path: str, **kwargs) -> Callable:
110
"""Create a TRACE endpoint decorator within this router."""
111
```
112
113
### WebSocket Support
114
115
Decorator for defining WebSocket endpoints within the router.
116
117
```python { .api }
118
def websocket(
119
self,
120
path: str,
121
*,
122
name: Optional[str] = None,
123
dependencies: Optional[Sequence[Depends]] = None,
124
) -> Callable[[DecoratedCallable], DecoratedCallable]:
125
"""
126
Create a WebSocket endpoint decorator within this router.
127
128
Parameters:
129
- path: URL path for the WebSocket endpoint
130
- name: Name for the endpoint (for URL reversing)
131
- dependencies: List of dependencies for this endpoint
132
"""
133
```
134
135
### Router Inclusion
136
137
Method for including other routers within this router, enabling hierarchical router organization.
138
139
```python { .api }
140
def include_router(
141
self,
142
router: "APIRouter",
143
*,
144
prefix: str = "",
145
tags: Optional[List[Union[str, Enum]]] = None,
146
dependencies: Optional[Sequence[Depends]] = None,
147
responses: Optional[Dict[Union[int, str], Dict[str, Any]]] = None,
148
deprecated: Optional[bool] = None,
149
include_in_schema: bool = True,
150
default_response_class: Type[Response] = Default(JSONResponse),
151
callbacks: Optional[List[BaseRoute]] = None
152
) -> None:
153
"""
154
Include another APIRouter within this router.
155
156
Parameters:
157
- router: APIRouter instance to include
158
- prefix: Additional URL prefix for the included router
159
- tags: Additional tags for all routes in the included router
160
- dependencies: Additional dependencies for all routes in the included router
161
- responses: Additional responses for all routes in the included router
162
- deprecated: Mark all routes in the included router as deprecated
163
- include_in_schema: Include included router routes in OpenAPI schema
164
- default_response_class: Default response class for included router routes
165
- callbacks: Additional callbacks for all routes in the included router
166
"""
167
```
168
169
### Programmatic Route Management
170
171
Methods for adding routes programmatically instead of using decorators.
172
173
```python { .api }
174
def add_api_route(
175
self,
176
path: str,
177
endpoint: Callable,
178
*,
179
methods: Optional[Union[Set[str], List[str]]] = None,
180
name: Optional[str] = None,
181
dependencies: Optional[Sequence[Depends]] = None,
182
**kwargs: Any
183
) -> None:
184
"""
185
Add an API route programmatically to this router.
186
187
Parameters:
188
- path: URL path for the route
189
- endpoint: Function to handle the route
190
- methods: HTTP methods for the route (defaults to ["GET"])
191
- name: Name for the route
192
- dependencies: Dependencies for the route
193
"""
194
195
def add_websocket_route(
196
self,
197
path: str,
198
endpoint: Callable,
199
name: Optional[str] = None
200
) -> None:
201
"""
202
Add a WebSocket route programmatically to this router.
203
204
Parameters:
205
- path: URL path for the WebSocket route
206
- endpoint: Function to handle the WebSocket connection
207
- name: Name for the route
208
"""
209
```
210
211
### Generic Route Decorator
212
213
Generic decorator for creating routes with custom HTTP methods.
214
215
```python { .api }
216
def route(
217
self,
218
path: str,
219
methods: Optional[List[str]] = None,
220
name: Optional[str] = None,
221
include_in_schema: bool = True
222
) -> Callable:
223
"""
224
Create a generic route decorator for custom HTTP methods.
225
226
Parameters:
227
- path: URL path for the route
228
- methods: List of HTTP methods to handle
229
- name: Name for the route
230
- include_in_schema: Include route in OpenAPI schema
231
"""
232
```
233
234
### Sub-Application Mounting
235
236
Method for mounting WSGI or ASGI applications within the router.
237
238
```python { .api }
239
def mount(
240
self,
241
path: str,
242
app: ASGIApp,
243
name: Optional[str] = None
244
) -> None:
245
"""
246
Mount a sub-application at the given path within this router.
247
248
Parameters:
249
- path: Path to mount the application at
250
- app: WSGI or ASGI application to mount
251
- name: Name for the mounted application
252
"""
253
```
254
255
## Route Classes
256
257
### APIRoute
258
259
Class representing individual API routes with their configuration and metadata.
260
261
```python { .api }
262
class APIRoute:
263
def __init__(
264
self,
265
path: str,
266
endpoint: Callable,
267
*,
268
response_model: Any = Default(None),
269
status_code: Optional[int] = None,
270
tags: Optional[List[Union[str, Enum]]] = None,
271
dependencies: Optional[Sequence[Depends]] = None,
272
summary: Optional[str] = None,
273
description: Optional[str] = None,
274
response_description: str = "Successful Response",
275
responses: Optional[Dict[Union[int, str], Dict[str, Any]]] = None,
276
deprecated: Optional[bool] = None,
277
methods: Optional[Union[Set[str], List[str]]] = None,
278
operation_id: Optional[str] = None,
279
response_model_include: Optional[IncEx] = None,
280
response_model_exclude: Optional[IncEx] = None,
281
response_model_by_alias: bool = True,
282
response_model_exclude_unset: bool = False,
283
response_model_exclude_defaults: bool = False,
284
response_model_exclude_none: bool = False,
285
include_in_schema: bool = True,
286
response_class: Type[Response] = Default(JSONResponse),
287
name: Optional[str] = None,
288
callbacks: Optional[List[BaseRoute]] = None,
289
openapi_extra: Optional[Dict[str, Any]] = None,
290
generate_unique_id_function: Callable[["APIRoute"], str] = Default(generate_unique_id)
291
):
292
"""
293
Individual API route configuration.
294
295
Properties:
296
- path: URL path pattern
297
- endpoint: Handler function
298
- methods: HTTP methods handled by this route
299
- response_model: Pydantic model for response serialization
300
- status_code: Default HTTP status code
301
- tags: OpenAPI tags
302
- dependencies: Route-specific dependencies
303
- name: Route name for URL reversing
304
"""
305
```
306
307
### APIWebSocketRoute
308
309
Class representing WebSocket routes.
310
311
```python { .api }
312
class APIWebSocketRoute:
313
def __init__(
314
self,
315
path: str,
316
endpoint: Callable,
317
*,
318
name: Optional[str] = None,
319
dependencies: Optional[Sequence[Depends]] = None
320
):
321
"""
322
WebSocket route configuration.
323
324
Properties:
325
- path: URL path pattern
326
- endpoint: WebSocket handler function
327
- name: Route name for URL reversing
328
- dependencies: Route-specific dependencies
329
"""
330
```
331
332
## Usage Examples
333
334
### Basic Router Setup
335
336
```python
337
from fastapi import APIRouter, Depends
338
from pydantic import BaseModel
339
340
# Create router with shared configuration
341
router = APIRouter(
342
prefix="/items",
343
tags=["items"],
344
dependencies=[Depends(verify_auth)],
345
responses={404: {"description": "Not found"}}
346
)
347
348
class Item(BaseModel):
349
name: str
350
price: float
351
352
@router.get("/")
353
async def get_items():
354
return [{"name": "Item 1", "price": 10.5}]
355
356
@router.post("/", response_model=Item)
357
async def create_item(item: Item):
358
return item
359
360
@router.get("/{item_id}")
361
async def get_item(item_id: int):
362
return {"name": f"Item {item_id}", "price": 10.5}
363
```
364
365
### Hierarchical Router Organization
366
367
```python
368
from fastapi import FastAPI, APIRouter
369
370
# Main application
371
app = FastAPI()
372
373
# API v1 router
374
api_v1 = APIRouter(prefix="/api/v1")
375
376
# Feature-specific routers
377
users_router = APIRouter(prefix="/users", tags=["users"])
378
items_router = APIRouter(prefix="/items", tags=["items"])
379
380
@users_router.get("/")
381
async def get_users():
382
return [{"id": 1, "name": "John"}]
383
384
@users_router.get("/{user_id}")
385
async def get_user(user_id: int):
386
return {"id": user_id, "name": "John"}
387
388
@items_router.get("/")
389
async def get_items():
390
return [{"id": 1, "name": "Item 1"}]
391
392
# Include feature routers in API v1
393
api_v1.include_router(users_router)
394
api_v1.include_router(items_router)
395
396
# Include API v1 in main app
397
app.include_router(api_v1)
398
399
# Final URLs:
400
# GET /api/v1/users/
401
# GET /api/v1/users/{user_id}
402
# GET /api/v1/items/
403
```
404
405
### Router with Shared Dependencies
406
407
```python
408
from fastapi import APIRouter, Depends, HTTPException
409
410
def get_current_user(token: str = Depends(get_token)):
411
if not token:
412
raise HTTPException(status_code=401, detail="Not authenticated")
413
return {"user_id": 1, "username": "john"}
414
415
def verify_admin(user: dict = Depends(get_current_user)):
416
if not user.get("is_admin"):
417
raise HTTPException(status_code=403, detail="Not enough permissions")
418
return user
419
420
# Admin router with shared admin dependency
421
admin_router = APIRouter(
422
prefix="/admin",
423
tags=["admin"],
424
dependencies=[Depends(verify_admin)]
425
)
426
427
@admin_router.get("/users")
428
async def get_all_users():
429
# Only accessible by admin users
430
return [{"id": 1, "name": "John"}, {"id": 2, "name": "Jane"}]
431
432
@admin_router.delete("/users/{user_id}")
433
async def delete_user(user_id: int):
434
# Only accessible by admin users
435
return {"message": f"User {user_id} deleted"}
436
```
437
438
### Router with Custom Response Classes
439
440
```python
441
from fastapi import APIRouter
442
from fastapi.responses import PlainTextResponse, HTMLResponse
443
444
router = APIRouter(prefix="/content")
445
446
@router.get("/text", response_class=PlainTextResponse)
447
async def get_text():
448
return "This is plain text"
449
450
@router.get("/html", response_class=HTMLResponse)
451
async def get_html():
452
return "<html><body><h1>Hello HTML</h1></body></html>"
453
454
@router.get("/json") # Uses default JSONResponse
455
async def get_json():
456
return {"message": "This is JSON"}
457
```
458
459
### WebSocket Router
460
461
```python
462
from fastapi import APIRouter, WebSocket
463
464
ws_router = APIRouter(prefix="/ws")
465
466
@ws_router.websocket("/chat")
467
async def websocket_endpoint(websocket: WebSocket):
468
await websocket.accept()
469
try:
470
while True:
471
data = await websocket.receive_text()
472
await websocket.send_text(f"Message text was: {data}")
473
except WebSocketDisconnect:
474
print("Client disconnected")
475
```