Skip to main content

Versioning & Changelog Policy

Fyndow's backend is a headless API: every capability lives behind an HTTP contract under /api/v1, and all of Fyndow's own apps — web, mobile, admin — are clients of that contract through a single typed SDK. Because that contract is the product's structural backbone (see The Headless-First Thesis), how it is versioned and how changes to it are communicated are first-class concerns. This chapter states the versioning policy, how breaking changes are handled, and where the changelog lives.

URL-based API versioning

Fyndow versions its API in the URL path. Every route is mounted under a single global prefix:

/api/v1/<resource>

This prefix is set once when the backend starts and is the canonical version seam. The SDK's base URL points at this prefix — for example https://api.example.com/api/v1 — so the version a client speaks is explicit and visible in every request.

PropertyValue
Versioning styleURL path prefix
Current versionv1
Prefix/api/v1/
Where it's setWhen the backend starts
How clients pin itSDK base URL includes the version

URL versioning was chosen for the same reason the rest of the platform favours explicitness: the version a caller depends on is impossible to miss. There is no header negotiation, no implicit "latest," and no ambiguity about which contract a given request targets.

What counts as a breaking change

A change is breaking if a correct, existing client could stop working because of it. The dividing line matters because breaking and non-breaking changes are handled differently.

Breaking (requires a new version):

  • Removing or renaming an endpoint, field, or query parameter.
  • Changing the type or units of a field (for example, a value that was dollars becoming cents, or a string becoming an enum).
  • Making a previously optional request field required.
  • Changing the meaning of an existing status, enum value, or default.
  • Tightening validation so input that used to be accepted is now rejected.

Non-breaking (ships within the current version):

  • Adding a new endpoint.
  • Adding a new optional request field.
  • Adding a new field to a response (clients should ignore unknown fields).
  • Adding a new enum value where the consumer already handles an "unknown/other" case.
  • Relaxing validation to accept more input than before.

:::tip Additive by default The platform's standard response envelope and consistent module boundaries make additive change cheap: new fields and endpoints can land without disturbing existing callers. The bar for cutting a new major version is therefore high — it is reserved for changes that genuinely cannot be made additively. :::

How breaking changes are handled

When a change cannot be made additively, it ships as a new version prefix rather than mutating the existing one:

The policy is:

  1. A breaking change becomes /api/v2/. The new contract is served under a new prefix; the old prefix is left intact.
  2. /api/v1/ keeps serving existing integrations through a deprecation window, so callers are never broken the moment a new version ships.
  3. The typed SDK pins a version. Because the SDK carries the version in its base URL, upgrading to a new major version is an explicit, deliberate act — bumping the SDK and base URL — not something that happens silently underneath a running client.
  4. Deprecated versions are announced before sunset, with the changelog as the record of what changed and what to migrate to.

Within a single version, the contract evolves additively only — new optional fields and new endpoints, never silent semantic changes to existing ones.

A worked example of the discipline

The reason this policy is taken seriously is visible in the platform's own history. The internal teams have repeatedly caught and fixed exactly the class of change that would be breaking on a public contract — for instance, tool payloads that sent dollars where a service expected cents, or an availability payload whose shape did not match what the scheduling service stored (which silently wiped availability). On an internal contract those are bugs caught in review; on a public /api/v1 they would be breaking changes demanding a version bump and a migration note. This is precisely why units, field shapes, and defaults are treated as part of the contract, not implementation details.

Where the changelog lives

A formal, published API changelog is forward-looking work tied to making the API a public developer surface. Today, the authoritative record of how the contract has changed lives in the engineering sources rather than a customer-facing page:

  • The typed SDK's method signatures are the canonical description of the current surface — adding or changing a method there is the most direct signal of a contract change.
  • Version control history and the project's phase/status tracking record when modules and endpoints were added or reshaped.
  • The schema migration history records the database-level changes that back the contract.

A public, human-readable changelog — "what changed in this release, and what you must do about it" — is part of the same body of work as the public API itself (API keys, scopes, per-key rate limits). The prerequisites for that move, including the security audit that must precede any external exposure, are described in The Public API.

:::note TODO A published, customer-facing API changelog does not exist yet. When the public developer API ships, this section should point at that changelog and define its cadence (per-release vs. rolling), its format (added / changed / deprecated / removed), and the length of the deprecation window between a version's sunset announcement and its removal. :::

Summary

  • Fyndow versions its API in the URL path (/api/v1), set once at bootstrap and pinned by the SDK's base URL.
  • Within a version, changes are additive only; breaking changes ship under a new prefix (/api/v2) while the old one continues to serve during a deprecation window.
  • Units, field shapes, defaults, and validation strictness are part of the contract — changing them is breaking.
  • A published changelog is forward-looking; today the canonical record is the SDK surface, git history, and migrations. See The Public API for the broader public-surface roadmap.