Routing & Versioning

Vorte extends FastAPI routing with versioned endpoints, deprecation headers, and flexible versioning strategies. The VorteAPIRouter is a drop-in replacement for APIRouter that adds these features.

VorteAPIRouter

list_users.py
python
Copied!
1from vorte.routing import VorteAPIRouter
2
3router = VorteAPIRouter(prefix="/api")
4
5@router.get("/users")
6async def list_users():
7 return {"users": []}
8
9@router.post("/users")
10async def create_user(payload: CreateUserPayload):
11 return {"id": 1, "name": payload.name}

Versioned Routes

Attach a version to any route. Vorte automatically routes requests to the correct handler based on the versioning strategy you configure.

list_users_v1.py
python
Copied!
1from vorte.routing import VorteAPIRouter
2
3router = VorteAPIRouter(prefix="/api")
4
5@router.get("/users", version=1)
6async def list_users_v1():
7 return {"users": [], "format": "legacy"}
8
9@router.get("/users", version=2)
10async def list_users_v2():
11 return {
12 "data": [],
13 "meta": {"total": 0, "page": 1},
14 "format": "standardized",
15 }
16
17@router.get("/users", version=3)
18async def list_users_v3():
19 return {
20 "data": [],
21 "meta": {"total": 0, "page": 1, "per_page": 20},
22 "links": {"self": "/api/users", "next": None},
23 }

Versioning Strategies

Vorte supports multiple strategies for determining which version of a route to serve. Configure the strategy at the application level or override it per-router.

URL-Based Versioning

The version is embedded in the URL path. This is the default strategy and the most common approach for public APIs.

example.py
python
Copied!
1from vorte import Vorte
2
3app = Vorte(
4 auto_load=True,
5 config={
6 "routing": {
7 "versioning_strategy": "url",
8 "default_version": 1,
9 }
10 },
11)
12
13# Routes resolve as:
14# GET /v1/users -> list_users_v1()
15# GET /v2/users -> list_users_v2()
16# GET /v3/users -> list_users_v3()

Header-Based Versioning

The client specifies the desired version through a custom header. This keeps URLs stable across versions.

example.py
python
Copied!
1app = Vorte(
2 auto_load=True,
3 config={
4 "routing": {
5 "versioning_strategy": "header",
6 "version_header": "X-API-Version",
7 "default_version": 2,
8 }
9 },
10)
11
12# Client request:
13# GET /api/users
14# Header: X-API-Version: 3
15# -> list_users_v3()

Content Negotiation Versioning

example.py
python
Copied!
1app = Vorte(
2 auto_load=True,
3 config={
4 "routing": {
5 "versioning_strategy": "accept",
6 "default_version": 1,
7 }
8 },
9)
10
11# Client request:
12# GET /api/users
13# Accept: application/vnd.vorte.v2+json
14# -> list_users_v2()

Deprecation Headers

Mark routes as deprecated to notify consumers. Vorte automatically addsDeprecation and Sunset headers to responses.

list_users_legacy.py
python
Copied!
1from vorte.routing import VorteAPIRouter
2
3router = VorteAPIRouter(prefix="/api")
4
5@router.get(
6 "/users/legacy",
7 version=1,
8 deprecated=True,
9 sunset="2026-06-01",
10 deprecation_message="Use /v2/users instead",
11)
12async def list_users_legacy():
13 return {"users": []}

The response will include the following headers:

example.py
python
Copied!
1Deprecation: true
2Sunset: Mon, 01 Jun 2026 00:00:00 GMT
3Link: </v2/users>; rel="successor-version"
4X-Deprecation-Notice: Use /v2/users instead

Route Groups

Organize routes into groups with shared middleware, prefixes, and dependencies.

public_status.py
python
Copied!
1from vorte.routing import VorteAPIRouter
2from vorte.auth import require_auth
3
4router = VorteAPIRouter()
5
6public = router.group(prefix="/public")
7private = router.group(
8 prefix="/admin",
9 dependencies=[Depends(require_auth)],
10 tags=["admin"],
11)
12
13@public.get("/status")
14async def public_status():
15 return {"status": "ok"}
16
17@private.get("/metrics")
18async def admin_metrics():
19 return {"requests": 12000, "errors": 3}

Route Middleware

log_request.py
python
Copied!
1from vorte.routing import VorteAPIRouter
2
3router = VorteAPIRouter()
4
5@router.middleware("request")
6async def log_request(request, call_next):
7 start = time.time()
8 response = await call_next(request)
9 duration = time.time() - start
10 response.headers["X-Response-Time"] = f"{duration:.3f}s"
11 return response
12
13@router.middleware("response")
14async def add_correlation_id(request, response):
15 response.headers["X-Request-ID"] = request.state.request_id
16 return response

Default Version Fallback

When a request does not specify a version, Vorte falls back to the configured default. If no handler matches the default version, it returns a 404.

example.py
python
Copied!
1app = Vorte(
2 auto_load=True,
3 config={
4 "routing": {
5 "versioning_strategy": "url",
6 "default_version": 2,
7 "strict_versioning": False,
8 }
9 },
10)
11
12# GET /users -> falls back to v2 handler
13# GET /v2/users -> explicit v2 handler
14# GET /v4/users -> 404 (no v4 handler exists)
Stay in the loop

Get Vorte release notes, module guides, and developer deep-dives. No spam — unsubscribe anytime.