Install & Compatibility
Where this runs
tested against v7.2.0 · pip install
no network on importno background threads
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
muslpy 3.10–3.95 runs
installs and imports cleanly · install 0.0s · import 1.534s · 33.7MB
glibcpy 3.10–3.95 runs
installs and imports cleanly · install 4.4s · import 1.398s · 33MB
32MB installed
● package 32MB
Code
Verified usage
Verified import paths — ran on the pinned version, not inferred.
Cadwyn
✓ from cadwyn import Cadwyn
VersionedAPIRouter
✓ from cadwyn import VersionedAPIRouter
VersionBundle
✓ from cadwyn import VersionBundle
schema
✓ from cadwyn.structure import schema
VersionChange
✓ from cadwyn.structure import VersionChange
This quickstart demonstrates how to set up a basic FastAPI application with Cadwyn for API versioning. It defines two versions (2024-01-01 and 2023-01-01), with a version change making the `email` field optional in `UserCreateRequest` for the older version. The `Cadwyn` instance handles the generation and inclusion of versioned routers, allowing your core business logic to interact only with the latest schema.
import datetime
from fastapi import FastAPI
from pydantic import BaseModel, Field
from cadwyn import Cadwyn, VersionBundle, VersionedAPIRouter
from cadwyn.structure import VersionChange, schema
# 1. Define your schemas in the 'latest' version
class UserCreateRequest(BaseModel):
name: str
email: str
class UserResource(BaseModel):
id: int
name: str
email: str
# 2. Define your API versions
# Use ISO date strings for versions for future compatibility (v6.x+)
VERSION_2024_01_01 = datetime.date(2024, 1, 1)
VERSION_2023_01_01 = datetime.date(2023, 1, 1)
# 3. Define version changes
class ChangeEmailFieldToOptional(VersionChange):
description = 'Make email field optional in UserCreateRequest'
version = VERSION_2023_01_01
@schema(UserCreateRequest).alter
def alter_user_create_request(cls):
cls.email = Field(default=None, union_of=[cls.email, type(None)])
# 4. Create a VersionBundle
version_bundle = VersionBundle(
latest_version=VERSION_2024_01_01,
old_versions=[VERSION_2023_01_01],
version_changes=[ChangeEmailFieldToOptional],
)
# 5. Initialize Cadwyn and the versioned router
app = FastAPI()
cadwyn_app = Cadwyn(
versions=version_bundle,
api_version_header_name='x-api-version',
latest_schemas_package=__name__,
old_versions_package=__name__
)
# Use a standard FastAPI router but include it via Cadwyn
router = VersionedAPIRouter(version_bundle=version_bundle)
@router.post('/users', response_model=UserResource)
async def create_user(user: UserCreateRequest):
# Business logic always works with the latest schema
return {"id": 1, "name": user.name, "email": user.email}
@router.get('/users/{user_id}', response_model=UserResource)
async def get_user(user_id: int):
return {"id": user_id, "name": "John Doe", "email": "john.doe@example.com"}
# Cadwyn generates and includes versioned routes
cadwyn_app.generate_and_include_versioned_routers(app, router)
# To run: uvicorn your_module_name:app --reload
# Test with curl -H 'x-api-version: 2024-01-01' -X POST -H 'Content-Type: application/json' -d '{"name": "Alice", "email": "alice@example.com"}' http://localhost:8000/users
# Test with curl -H 'x-api-version: 2023-01-01' -X POST -H 'Content-Type: application/json' -d '{"name": "Bob"}' http://localhost:8000/users
cadwyn --version
Debug
Known issues
breakingCadwyn v6.0.0 removed support for FastAPI versions older than 0.128.0 and Pydantic v1. Ensure your FastAPI and Pydantic installations meet the new minimum requirements.fixUpgrade FastAPI to 0.128.0 or newer and Pydantic to v2.x (if not already using it). Ensure your project's `requires_python` is `>=3.10`.
affects: >=6.0.0
breakingPython 3.9 support was removed in Cadwyn v6.0.3. Projects using older Python versions will not be compatible with recent Cadwyn releases.fixUpgrade your Python environment to 3.10 or higher.
affects: >=6.0.3
deprecatedThe `api_version_header_name` argument in `Cadwyn` is deprecated in favor of `api_version_parameter_name`. Also, `cadwyn.Cadwyn.add_header_versioned_routers` is deprecated and likely removed in favor of `generate_and_include_versioned_routers`.fixUse `api_version_parameter_name` for configuring how Cadwyn extracts the API version. Replace `add_header_versioned_routers` with `generate_and_include_versioned_routers`.
affects: >=5.x, <=6.2.0 (deprecation); >=6.0.0 (removal of old method)
gotchaCadwyn v6.x+ stores versions as strings (preferably ISO dates) internally. While date types can still be passed to `cadwyn.Version`, string types (like 'YYYY-MM-DD') are guaranteed to be supported in the future.fixWhen defining your versions, prefer using string representations of dates (e.g., '2024-01-01') instead of `datetime.date` objects, or ensure any `datetime.date` objects are handled consistently as Cadwyn converts them internally.
affects: >=6.0.0
gotchaCadwyn aims to eliminate explicit version checks in business logic. Directly checking `api_version_var.get() >= date(...)` is discouraged and often indicates a missing or incorrectly applied version change.fixInstead of direct version checks, define appropriate `VersionChange` objects to transform schemas and routes. This keeps your business logic version-agnostic. Refer to Cadwyn's documentation on version changes for better patterns.
affects: All versions
gotchaCadwyn does not automatically edit Python import statements when generating schemas. If you import from versioned code within other versioned code, use relative imports to ensure they resolve correctly after code generation.fixUse relative imports (e.g., `from . import some_module`) for any internal module imports within your versioned schemas or routes to maintain correct references across generated versions.
affects: All versions
breakingThe method `.alter` used for defining schema version changes has been removed or significantly changed. `AlterSchemaInstructionFactory` objects no longer have an `alter` attribute, leading to an `AttributeError` when attempting to use the old syntax.fixConsult the Cadwyn documentation for the correct and current API to define `VersionChange` objects and apply schema transformations. The syntax for altering schemas has likely been updated to use different methods or decorators.
affects: >=6.0.0
Errors
Common errors & fixes
fastapi.exceptions.FastAPIError: Invalid args for response field! Hint: check that <pydantic.types.JsonValue object at 0x...> is a valid Pydantic field type.
The `pydantic.JsonValue` type, when used as a direct type annotation in request body models, requires Pydantic 2.0+ and often Python 3.12+ for full compatibility, leading to validation errors in older environments.
fixFor Python versions older than 3.12 or Pydantic versions below 2.0, use `typing.Union[dict, list, str, int, float, bool, None]` or a custom `Annotated` type instead of `JsonValue` in your Pydantic models. Alternatively, upgrade Python to 3.12+ and Pydantic to 2.0+.
RuntimeError: No matching endpoint found for migration defined for version 'YYYY-MM-DD' and path '/your/api/path'.
A migration function was defined to operate on a specific API endpoint, but Cadwyn could not find a corresponding endpoint at the specified path and version in the `VersionedAPIRouter`. This usually occurs if the endpoint was removed, renamed, or its path changed without the migration being updated accordingly.
fixVerify that the path and HTTP method used in your migration decorator (e.g., `@router.patch('/your/api/path')`) precisely match an existing endpoint in the `HeadVersion` or the target past version. If the endpoint was intentionally altered, adjust your migration to reflect these changes, potentially using `RemoveEndpoint` or `MoveEndpoint` migration types. HTTP 400 Bad Request: The requested API version 'YYYY-MM-DD' is not registered.
The client attempted to access an API version (specified via header or query parameter) that has not been explicitly defined or included in your Cadwyn application's `VersionBundle`.
fixEnsure that all supported API versions are correctly listed in the `VersionBundle` when initializing your Cadwyn application. For example: `app = Cadwyn(versions=VersionBundle(HeadVersion(), Version('2024-01-01'), Version('2023-01-01'))`. Also, verify the client is sending a valid and correctly formatted version string. Upgrade
Version history
7.2.0latest on PyPI · released Jul 29, 2026
Audit
Dependencies
fastapirequiredCadwyn is built on and extends FastAPI for API versioning functionality.
pydanticrequiredCadwyn leverages Pydantic for defining API schemas and data validation.