Fuente canónica. Cambios en el versionado de API se documentan aquí.
API Versioning System¶
Overview¶
This document describes the API versioning strategy implemented in the SaaS Courier backend.
Versioning Strategy¶
The API supports multiple versions coexisting simultaneously:
- /api/v1/* - Version 1 (default)
- /api/v2/* - Version 2 (with enhanced features)
Version Detection¶
Versions are detected from the URL path:
# From path (default behavior)
GET /api/v1/shipments # Uses v1
GET /api/v2/shipments # Uses v2
# From header (optional)
API-Version: v2
Implementation¶
Core Versioning Module¶
Located at core/versioning.py:
from core.versioning import APIVersion, resolve_version, get_api_version
# Detect version from request
@router.get("/shipments")
async def get_shipments(request: Request):
version = resolve_version(request)
# version is APIVersion.V1 or APIVersion.V2
Versioned DTOs¶
V1 and V2 DTOs are defined separately:
# V1 - modules/shipments/application/dtos.py
class ShipmentResponseDTO:
id: str
tenant_id: str
tracking_id: str
# ... basic fields
# V2 - modules/shipments/application/dtos_v2.py
class ShipmentResponseV2DTO(ShipmentResponseDTO):
tenant_name: str = "Unknown" # NEW: Expanded info
version: str = "v2" # NEW: Version marker
available_capacity: float # NEW: Computed field
Versioning Helper Functions¶
Located at modules/shipments/application/versioning.py:
from core.versioning import APIVersion
from modules.shipments.application.versioning import shipment_to_dto
@router.get("/shipments")
async def get_shipments(request: Request):
version = resolve_version(request)
shipment = await repo.get_by_id(id)
return shipment_to_dto(shipment, version, tenant_name="My Tenant")
Adding New Versions¶
1. Create Version-Specific DTOs¶
Create modules/<module>/application/dtos_v{N}.py:
from pydantic import BaseModel
class MyResponseV3DTO(BaseModel):
# New fields for v3
new_field: str
@classmethod
def from_v2(cls, v2_dto: "MyResponseV2DTO") -> "MyResponseV3DTO":
# Conversion logic
return cls(...)
2. Register Version in Factory¶
Update modules/<module>/application/versioning.py:
def my_entity_to_dto(entity, version: APIVersion):
if version == APIVersion.V3:
return MyResponseV3DTO(...)
elif version == APIVersion.V2:
return MyResponseV2DTO(...)
return MyResponseV1DTO(...)
3. Update Supported Versions¶
Edit core/versioning.py:
class APIVersion(Enum):
V1 = "v1"
V2 = "v2"
V3 = "v3" # Add new version
SUPPORTED_VERSIONS = [APIVersion.V1, APIVersion.V2, APIVersion.V3]
Testing¶
Run versioning tests:
Best Practices¶
- Backwards Compatibility: V1 endpoints must continue working unchanged
- Additive Changes: New fields in V2 should have defaults
- No Breaking Changes: Existing clients using V1 should not break
- Deprecation Notice: When deprecating versions, add
X-API-Deprecatedheader
Migration Guide¶
When making breaking changes:
- Create new DTOs with version suffix
- Add new version to
APIVersionenum - Update
resolve_version()if needed - Document changes in this file
- Add migration tests
- Communicate deprecation to API consumers
Ver también: API Contract · ADR-001