FastAPI Easy Versioning
A library for building versioned APIs with FastAPI. Each API version is a separate FastAPI sub-application mounted under a common application. The library automatically inherits endpoints from older versions into newer ones and rebuilds each version's OpenAPI schema, so every version's /docs always shows its complete, current set of endpoints.
Features
- Endpoint inheritance between versions: declare an endpoint once and it is available in all subsequent versions.
- Precise availability range control with the
untilparameter. - Redefining an endpoint in a newer version shadows the inherited one — both at runtime and in the OpenAPI schema.
- HTTP and WebSocket endpoints are supported.
- Versioning metadata (
origin,until) is readable right inside the endpoint. - Several independent versioned APIs within one application.
- The only runtime dependency is
fastapi(versions from 0.95 up to the latest are supported).
Installation
pip install fastapi-easy-versioning
Quick Start
Versioning is built from two pieces that only work together:
VersioningMiddleware— added to the application that mounts the versions;versioning()— a dependency factory that marks an endpoint as versioned.
from fastapi import FastAPI, Depends
from fastapi_easy_versioning import VersioningMiddleware, versioning
app = FastAPI()
app_v1 = FastAPI(api_version=1)
app_v2 = FastAPI(api_version=2)
app.mount("/v1", app_v1)
app.mount("/v2", app_v2)
app.add_middleware(VersioningMiddleware)
@app_v1.get('/only-v1', dependencies=[Depends(versioning(until=1))])
def only_v1() -> str:
return "Available only in version v1"
@app_v1.get('/all-versions', dependencies=[Depends(versioning())])
def all_versions() -> str:
return "Available in all versions starting from v1"
@app_v2.get('/from-v2', dependencies=[Depends(versioning())])
def from_v2() -> str:
return "Available starting from v2 and in all future versions"
graph TD
A[Availability by version]
A --> B[v1]
A --> C[v2]
B --> B1["/only-v1 ✓"]
B --> B2["/all-versions ✓"]
B --> B3["/from-v2 ✗"]
C --> C1["/only-v1 ✗"]
C --> C2["/all-versions ✓"]
C --> C3["/from-v2 ✓"]
style B1 fill:#90EE90
style B2 fill:#90EE90
style B3 fill:#FFB6C1
style C1 fill:#FFB6C1
style C2 fill:#90EE90
style C3 fill:#90EE90
The result:
/v1/only-v1responds while/v2/only-v1returns 404 — the endpoint is limited byuntil=1./v1/all-versionsand/v2/all-versionsboth respond — the endpoint is declared inv1and inherited intov2./v2/from-v2responds while/v1/from-v2returns 404 — the endpoint only appeared inv2./v1/docsand/v2/docsshow exactly the endpoints available in the corresponding version.
How It Works
- Each version is a
FastAPI(api_version=N)sub-application mounted under a common application:app.mount("/v1", app_v1).api_versionmust be an integer. - On its first ASGI event (server startup or the first request)
VersioningMiddlewarebuilds the inheritance once: it copies the marked endpoints from older versions into newer ones and rebuilds each version's OpenAPI schema. - Only endpoints with the
versioning()dependency are inherited. An endpoint without it stays only in the version where it is declared. - Every inheriting version receives its own copy of the route — changes in one version do not affect the others.
Documentation Sections
- The
versioningdependency — ways to mark endpoints,untilsemantics, reading metadata inside the endpoint. - Middleware — where to add it, how inheritance works, OpenAPI, adding routes at runtime, FastAPI version compatibility.
- Examples: simple versioning, multiple independent APIs.