Skip to content

API stability and versioning policy

Fredrik Dettner edited this page Jun 20, 2026 · 1 revision

API Stability and Versioning Policy

Audience: Sedis engineers changing anything under /v2/.... This document is the enforceable contract behind the promise in the developer's guide that "every v2 field name is a permanent contract." Read it before opening a PR that touches a v2 controller, DTO, route, query parameter, header, error shape, rate limit, or the OpenAPI document.

The core rule: v2.x is additive-only

The Partner API v2 surface is additive-only. Partners encode our field names, routes, and behaviors into their integrations; once shipped, those are permanent contract decisions.

  • Non-breaking changes ship freely as /v2 point releases.
  • Breaking changes are NOT allowed under /v2. They require a new /v3/... URL prefix and a parallel run alongside /v2 (exactly as /v2 runs in parallel with v1 today — see Migrating from v1).

When in doubt, treat the change as breaking and escalate to a /v3 design discussion. It is always safe to be conservative here.

NON-breaking — ship freely in v2.x point releases

The following are non-breaking. A PR doing only these can merge under /v2:

  • New endpoints (new URL paths).
  • New OPTIONAL fields on responses (additive serialization — old clients ignore unknown fields).
  • New OPTIONAL query parameters with safe defaults (existing clients see no behavior change).
  • New OPTIONAL header support.
  • New enum values added at the END of an enum (verify: if a partner uses exhaustive switch logic this can surprise them; document the new value as additive via OpenAPI).
  • More permissive rate limits per tier (looser is non-breaking).

BREAKING — require a /v3/... prefix + parallel-run with /v2/...

The following are breaking. A PR doing any of these cannot target /v2 — it is rejected pending a v3 design discussion:

  • Renaming or removing a response field.
  • Changing a response field's type (e.g. string → number).
  • Changing default behavior of an existing endpoint.
  • Adding a REQUIRED parameter to an existing endpoint.
  • Narrowing rate limits below an existing partner's observed usage.
  • Changing the error contract (response shape for 4xx/5xx).
  • Changing the auth scheme on existing endpoints.
  • Removing or renaming an endpoint.
  • Changing pagination defaults or max page size DOWNWARD (upward is safe).
  • Changing the Idempotency-Key semantics (TTL, key scope).

Per-PR checklist (every /v2 PR answers this)

Copy this into the PR description and answer it. A PR touching /v2 cannot merge without it.

### Partner API v2 stability check
- [ ] Does this PR touch a /v2 endpoint, DTO, route, query param, header,
      error shape, rate limit, or the v2 OpenAPI document?
      (If NO — skip the rest.)
- [ ] Is this change BREAKING per docs/partnerapi-v2/CONTRIBUTING.md?
      - [ ] NO  → additive-only; proceeded under /v2. List the additive change(s):
                  ____________________________________________________
      - [ ] YES → STOP. This requires /v3 + parallel-run. Do NOT merge under /v2.
                  Open a v3 design discussion and link it here: ______________
- [ ] OpenAPI info.version updated if the API contract changed? (see below)
- [ ] Developer's guide updated IN THIS PR if the change is partner-visible?
      (see "Maintenance contract" below)
- [ ] Changelog entry added to docs/partnerapi-v2/15-changelog.md?
- [ ] v1 wire snapshot suite still green (v1 must stay byte-identical)?

If the breaking box is checked, the reviewer rejects the PR for /v2. The change is re-scoped to /v3 (a new URL prefix that runs in parallel with /v2), or dropped.

OpenAPI info.version is independent of GitVersion

There are two version numbers and they move independently:

Version What it tracks When it bumps
GitVersion deployable tag (e.g. v2.11.4) The Sedis application/container release Freely, on every deploy — patch by default; see CLAUDE.md "Versioning (GitVersion)". A deploy bump does not imply any API change.
OpenAPI info.version (e.g. 2.0.0) The Partner API v2 contract Only when the API contract changes. Additive v2.x changes bump the minor/patch of info.version; a breaking change is /v3 (a new document), never a 2.x→3.x flip of the same /v2 document.

Consequences for contributors:

  • A routine deploy that bumps GitVersion from v2.11.3 → v2.11.4 and changes nothing in /v2 does not touch info.version.
  • An additive /v2 change (new optional field/endpoint/param) bumps info.version (e.g. 2.0.0 → 2.1.0) and adds a changelog entry — but the GitVersion tag bumps on its own separate schedule.
  • The offline PDF filename matches info.version (Sedis-PartnerAPI_v2.0.0.pdf), not the GitVersion tag. Regenerate it when info.version bumps (see below).
  • docs(...) / planning-only commits use +semver: none per CLAUDE.md; an additive feat(...) on /v2 follows the normal GitVersion marker rules and separately bumps info.version.

Maintenance contract: docs ship in the SAME PR

The developer's guide (docs/partnerapi-v2/) and this policy are part of the contract, not afterthoughts.

  • Any partner-visible /v2 change updates the relevant guide section in the same PR as the code change — never as a follow-up "docs sweep."
  • A new or changed endpoint/field/param/error/header updates both the guide section and the changelog (15-changelog.md) in that PR.
  • The PDF is a generated artifact (never hand-edited). Regenerate it from the markdown when info.version bumps and commit the regenerated file — see the regeneration command documented in the 62-10 plan summary (Sedis.DevTools "Generate Partner API v2 Guide PDF" tool). The markdown is the single source of truth; the PDF must never drift from it.

v1 must stay byte-identical

None of the above relaxes the v1 guarantee. v1 is frozen and snapshot-guarded — the v1 wire-snapshot CI gate fails on any byte drift. A /v2 (or /v3) PR must never touch v1 wire output.

Clone this wiki locally