{"library":"cadwyn","title":"Cadwyn: Production-Ready FastAPI API Versioning","description":"Cadwyn is a Python library that provides production-ready, Stripe-like API versioning for FastAPI applications. It allows developers to maintain only the latest version of their API implementation, automatically generating older versions and handling backward compatibility. This approach encapsulates version changes in independent modules, simplifying business logic. The current version is 6.2.0, with an active development and release cadence.","status":"active","version":"6.2.0","language":"en","source_language":"en","source_url":"https://github.com/zmievsa/cadwyn","tags":["api","api-versioning","fastapi","pydantic","code-generation","stripe","versioning","python"],"install":[{"cmd":"pip install cadwyn","lang":"bash","label":"Install Cadwyn"}],"dependencies":[{"reason":"Cadwyn is built on and extends FastAPI for API versioning functionality.","package":"fastapi","optional":false},{"reason":"Cadwyn leverages Pydantic for defining API schemas and data validation.","package":"pydantic","optional":false}],"imports":[{"symbol":"Cadwyn","correct":"from cadwyn import Cadwyn"},{"symbol":"VersionedAPIRouter","correct":"from cadwyn import VersionedAPIRouter"},{"symbol":"VersionBundle","correct":"from cadwyn import VersionBundle"},{"symbol":"schema","correct":"from cadwyn.structure import schema"},{"symbol":"VersionChange","correct":"from cadwyn.structure import VersionChange"}],"quickstart":{"code":"import datetime\nfrom fastapi import FastAPI\nfrom pydantic import BaseModel, Field\nfrom cadwyn import Cadwyn, VersionBundle, VersionedAPIRouter\nfrom cadwyn.structure import VersionChange, schema\n\n# 1. Define your schemas in the 'latest' version\nclass UserCreateRequest(BaseModel):\n    name: str\n    email: str\n\nclass UserResource(BaseModel):\n    id: int\n    name: str\n    email: str\n\n# 2. Define your API versions\n# Use ISO date strings for versions for future compatibility (v6.x+)\nVERSION_2024_01_01 = datetime.date(2024, 1, 1)\nVERSION_2023_01_01 = datetime.date(2023, 1, 1)\n\n# 3. Define version changes\nclass ChangeEmailFieldToOptional(VersionChange):\n    description = 'Make email field optional in UserCreateRequest'\n    version = VERSION_2023_01_01\n\n    @schema(UserCreateRequest).alter\n    def alter_user_create_request(cls):\n        cls.email = Field(default=None, union_of=[cls.email, type(None)])\n\n# 4. Create a VersionBundle\nversion_bundle = VersionBundle(\n    latest_version=VERSION_2024_01_01,\n    old_versions=[VERSION_2023_01_01],\n    version_changes=[ChangeEmailFieldToOptional],\n)\n\n# 5. Initialize Cadwyn and the versioned router\napp = FastAPI()\ncadwyn_app = Cadwyn(\n    versions=version_bundle,\n    api_version_header_name='x-api-version',\n    latest_schemas_package=__name__,\n    old_versions_package=__name__\n)\n\n# Use a standard FastAPI router but include it via Cadwyn\nrouter = VersionedAPIRouter(version_bundle=version_bundle)\n\n@router.post('/users', response_model=UserResource)\nasync def create_user(user: UserCreateRequest):\n    # Business logic always works with the latest schema\n    return {\"id\": 1, \"name\": user.name, \"email\": user.email}\n\n@router.get('/users/{user_id}', response_model=UserResource)\nasync def get_user(user_id: int):\n    return {\"id\": user_id, \"name\": \"John Doe\", \"email\": \"john.doe@example.com\"}\n\n# Cadwyn generates and includes versioned routes\ncadwyn_app.generate_and_include_versioned_routers(app, router)\n\n# To run: uvicorn your_module_name:app --reload\n# 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\n# Test with curl -H 'x-api-version: 2023-01-01' -X POST -H 'Content-Type: application/json' -d '{\"name\": \"Bob\"}' http://localhost:8000/users","lang":"python","description":"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."},"warnings":[{"fix":"Upgrade 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`.","message":"Cadwyn 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.","severity":"breaking","affected_versions":">=6.0.0"},{"fix":"Upgrade your Python environment to 3.10 or higher.","message":"Python 3.9 support was removed in Cadwyn v6.0.3. Projects using older Python versions will not be compatible with recent Cadwyn releases.","severity":"breaking","affected_versions":">=6.0.3"},{"fix":"Use `api_version_parameter_name` for configuring how Cadwyn extracts the API version. Replace `add_header_versioned_routers` with `generate_and_include_versioned_routers`.","message":"The `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`.","severity":"deprecated","affected_versions":">=5.x, <=6.2.0 (deprecation); >=6.0.0 (removal of old method)"},{"fix":"When 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.","message":"Cadwyn 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.","severity":"gotcha","affected_versions":">=6.0.0"},{"fix":"Instead 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.","message":"Cadwyn 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.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Use 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.","message":"Cadwyn 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.","severity":"gotcha","affected_versions":"All versions"}],"env_vars":null,"last_verified":"2026-04-06T00:00:00.000Z","next_check":"2026-07-05T00:00:00.000Z"}