Appearance
ADR-010: API Versioning Strategy
Status: Accepted Date: 2026-02-08
Context
ADR-003 (API Style) identified that an API versioning strategy should be decided before Phase 1 ships. As the platform grows and clients depend on the API contract, breaking changes need a clear, predictable migration path. The team needed to choose a versioning mechanism, define what constitutes a breaking change, and establish a support window for old versions.
Decision
Versioning Mechanism: URL Path Prefix
All API endpoints are prefixed with a version segment:
/api/v1/projects/{key}/...
/api/v1/auth/register
/api/v1/invitations/{token}/acceptWhen a new version is introduced:
/api/v2/projects/{key}/... # New version
/api/v1/projects/{key}/... # Previous version (still supported)Versioning Policy: Pragmatic
A new API version is introduced only for major breaking changes:
- Removing an endpoint
- Renaming or removing a response field
- Changing the type of an existing field
- Changing the HTTP method or URL structure of an endpoint
- Altering the meaning or behavior of an existing field in an incompatible way
The following changes do not require a new version:
- Adding new endpoints
- Adding new optional fields to request or response bodies
- Adding new query parameters
- Adding new enum values (clients should handle unknown values gracefully)
- Bug fixes that correct behavior to match documentation
- Performance improvements
Minor changes are handled with deprecation notices in response headers (Deprecation and Sunset headers) to give clients time to adapt.
Support Window: One Previous Version (n-1)
At most two API versions are supported simultaneously: the current version and one previous version.
- When
v2is released,v1enters a deprecation period v1responses include aDeprecationheader with the sunset date- After the deprecation period,
v1is removed and requests return410 Gonewith a migration guide URL - The deprecation period length will be determined based on actual client usage patterns (minimum 3 months recommended)
Rationale
URL Path Prefix
- Explicit and visible -- the version is immediately obvious in URLs, logs, and documentation
- Easy to test -- can be called directly from a browser or curl without special headers
- Simple routing -- ASP.NET Core supports path-based versioning natively via
Asp.Versioning.Mvc - Client-friendly -- no need for clients to set custom headers on every request
Pragmatic Policy
- Avoids version churn from minor changes, keeping the maintenance burden low
- Additive-only changes (new fields, new endpoints) are backward-compatible by design
- Breaking changes are rare in a well-designed REST API, so versions should increment slowly
- Deprecation notices give clients visibility into upcoming removals without forcing immediate migration
n-1 Support Window
- Balances maintenance cost (two versions maximum) with client migration time
- Sufficient for a platform with a controlled client base (web frontend + potential mobile app)
- Avoids accumulating legacy versions that diverge significantly from current behavior
Implementation Notes
- Phase 1 launches as
v1. No versioning infrastructure is needed until the first breaking change - When versioning is needed, use the
Asp.Versioning.MvcNuGet package for route-based versioning - Controllers can be versioned per-endpoint (not all endpoints need to change between versions)
- The API documentation (Swagger/OpenAPI) should clearly indicate the version for each endpoint
- Version-specific controllers inherit from a shared base to minimize duplication
Alternatives Considered
- Header-based versioning (
Accept: application/vnd.kb.v1+json) -- Cleaner URLs but harder to test, less visible in logs, and requires clients to set headers on every request. May confuse developers unfamiliar with content negotiation - Query parameter versioning (
?version=1) -- Simple but clutters the query string, can conflict with other parameters, and feels non-standard for REST APIs
Consequences
- All API endpoint documentation should use the
/api/v1/prefix once versioning is implemented - The API endpoints doc and feature docs will be updated to reflect the versioned URLs when
v1is finalized - Client SDKs (if any) should default to the latest version but allow pinning to a specific version
- Monitoring should track usage by API version to inform deprecation timeline decisions