Skip to content

API Versioning Policy ​

Status: Accepted Work item: AB#4334 Scope: Heritage Community Hub API (apps/api)

Purpose ​

Define how the Heritage Community Hub API evolves over time without breaking existing clients (iOS, Android, web).

Current state ​

All API routes are served under /api/v1/.... There is no v2 today. v1 is the current, stable version and remains the default for all clients.

Versioning scheme ​

  • URL-based versioning is canonical. The version segment in the URL (/api/v1/...) is the single source of truth for which contract a client is calling.
  • Header-based negotiation is optional and informational only. Clients MAY send Accept-Version: v1 for clarity in logs and traces, but the URL determines the response contract. If the header disagrees with the URL, the URL wins.
  • Version numbers are major-only (v1, v2, v3). We do not version minor or patch increments — those are handled by additive, backwards-compatible changes within the existing major version.

What counts as a breaking change ​

A change that requires a new major version (v2):

  • Removing a field from a response body
  • Renaming a field in a request or response body
  • Changing the type or shape of an existing field (e.g., stringobject, array → scalar)
  • Removing an endpoint or HTTP method
  • Changing authentication requirements on an existing endpoint (e.g., adding a new required scope or role)
  • Changing existing error codes, error response shapes, or HTTP status codes returned for the same condition
  • Making a previously optional request field required
  • Tightening validation in a way that rejects payloads previously accepted

What is NOT a breaking change ​

Additive changes that ship under the existing major version without bumping:

  • Adding a new endpoint
  • Adding a new optional field to a request body
  • Adding a new field to a response body (clients must ignore unknown fields)
  • Adding new optional query parameters
  • Adding new optional headers
  • Bug fixes that bring behavior in line with the documented contract
  • Performance improvements that do not change the contract
  • Loosening validation to accept additional valid inputs

v2 promotion path ​

When a breaking change is required:

  1. Add v2 alongside v1. New routes are mounted at /api/v2/.... v1 continues to serve its existing contract unchanged.
  2. Deprecate v1 formally. All v1 responses begin returning the Deprecation header with the sunset date in HTTP-date format:
    Deprecation: Sun, 24 Dec 2026 00:00:00 GMT
    Sunset: Sun, 24 Dec 2026 00:00:00 GMT
    Link: </api/v2/...>; rel="successor-version"
  3. Notify clients. Minimum 6 months between the Deprecation header appearing and v1 removal. Communicate via release notes and changelog (member-facing) plus direct outreach to known integrators.
  4. Monitor migration. Track v1 vs v2 request volume by route. Do not remove v1 until v2 is stable in production AND v1 traffic from active clients has stopped.
  5. Remove v1. Only after the sunset date AND zero active-client traffic. v1 URLs then return 410 Gone for one further release before the routes are deleted entirely.

Client guidance &ZeroWidthSpace;

  • Always pin to a specific major version in the URL. Never call /api/... without a version segment.
  • Treat unknown fields in responses as optional — do not fail on additive changes.
  • Watch for the Deprecation response header and plan migration well before the Sunset date.

Internal guidance for contributors &ZeroWidthSpace;

  • Default to additive. Most API changes can ship under v1 without a new version.
  • If a change feels like it might be breaking, treat it as breaking and discuss in PR review before shipping.
  • Document every new version in docs/internal/design/api-contracts.md with the diff from the previous version.
  • Never modify the contract of an existing version after it has shipped to production.

Heritage Community Hub — Internal. Access restricted via Cloudflare Access + Entra ID.