Skip to content

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}/accept

When 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 v2 is released, v1 enters a deprecation period
  • v1 responses include a Deprecation header with the sunset date
  • After the deprecation period, v1 is removed and requests return 410 Gone with 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.Mvc NuGet 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 v1 is 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