Skip to content

Multiple APIs Versioning Example

The English documentation has been automatically translated. If you notice any grammatical or semantic errors, please help improve it by contributing corrections on GitHub, or refer to the original Russian documentation.

The example is available on GitHub.

To run it locally, clone the repository and execute the following command:

git clone https://github.com/feodor-ra/fastapi-easy-versioning.git
uvx --python=3.13 --from="fastapi[standard]" --with="fastapi-easy-versioning" fastapi dev fastapi-easy-versioning/examples/multiple_versioning.py

The example contains the following code:

from fastapi import Depends, FastAPI, middleware
from fastapi_easy_versioning import (
    VersioningMiddleware,
    versioning,
)

app = FastAPI()

public_app = FastAPI(middleware=[middleware.Middleware(VersioningMiddleware)])
public_v1 = FastAPI(api_version=1)
public_v2 = FastAPI(api_version=2)

private_app = FastAPI(middleware=[middleware.Middleware(VersioningMiddleware)])
private_v1 = FastAPI(api_version=1)
private_v2 = FastAPI(api_version=2)

app.mount("/api/public", public_app)
public_app.mount("/v1", public_v1)
public_app.mount("/v2", public_v2)

app.mount("/api/private", private_app)
private_app.mount("/v1", private_v1)
private_app.mount("/v2", private_v2)


@private_v1.get("/endpoint", dependencies=[Depends(versioning(until=1))])
def private_endpoint() -> str:
    return "I'm v1 private endpoint"


@private_v1.get("/another-endpoint", dependencies=[Depends(versioning())])
def private_another_endpoint() -> str:
    return "I'm v1 private another endpoint"


@private_v2.get("/endpoint", dependencies=[Depends(versioning())])
def private_endpoint_v2() -> str:
    return "I'm v2 private endpoint"


@public_v1.get("/endpoint", dependencies=[Depends(versioning(until=1))])
def public_endpoint() -> str:
    return "I'm v1 public endpoint"


@public_v1.get("/another-endpoint", dependencies=[Depends(versioning())])
def public_another_endpoint() -> str:
    return "I'm v1 public another endpoint"


@public_v2.get("/endpoint", dependencies=[Depends(versioning())])
def public_endpoint_v2() -> str:
    return "I'm v2 public endpoint"

This code creates two independent versioned APIs: public and private. Each has two versions (v1 and v2). Swagger documentation for them is available at:

The resulting structure is as follows:

  • In the public API:
  • /endpoint is available only in version v1 (with until=1 restriction)
  • /another-endpoint is available in all versions (starting from v1)
  • in v2, a new /endpoint is added, which overrides the version from v1

  • In the private API:

  • /endpoint is available only in version v1 (with until=1 restriction)
  • /another-endpoint is available in all versions (starting from v1)
  • in v2, a new /endpoint is added, which overrides the version from v1

Both APIs operate independently thanks to the use of separate VersioningMiddleware instances.

graph TD
    A[Endpoint Availability] --> B[Public API]
    A --> C[Private API]

    B --> B1[v1<br/>api_version=1]
    B --> B2[v2<br/>api_version=2]

    C --> C1[v1<br/>api_version=1]
    C --> C2[v2<br/>api_version=2]

    B1 --> B11["/endpoint ✓<br/>(until=1)"]
    B1 --> B12["/another-endpoint ✓"]

    B2 --> B21["/endpoint ✓<br/>(from v2)"]
    B2 --> B22["/another-endpoint ✓"]

    C1 --> C11["/endpoint ✓<br/>(until=1)"]
    C1 --> C12["/another-endpoint ✓"]

    C2 --> C21["/endpoint ✓<br/>(from v2)"]
    C2 --> C22["/another-endpoint ✓"]

    style B11 fill:#90EE90
    style B12 fill:#90EE90
    style B21 fill:#90EE90
    style B22 fill:#90EE90

    style C11 fill:#90EE90
    style C12 fill:#90EE90
    style C21 fill:#90EE90
    style C22 fill:#90EE90

    classDef available fill:#90EE90,stroke:#333;
    classDef notAvailable fill:#FFB6C1,stroke:#333;