Versioning

The promise

  • /api/v1/* is stable for ≥18 months from v1.0 ship date.
  • Breaking changes go in a new major version (/api/v2/*) only. We don't break v1 mid-flight.
  • Non-breaking changes (new fields, new optional params, new endpoints) ship in /api/v1/* at any time without notice.
  • When /api/v2/* ships, /api/v1/* continues serving for ≥6 months alongside it.

Sunset semantics

When we deprecate /api/v1/*:

  1. 60 days before sunset: the v1 → v2 migration guide is published on this docs site.

  2. 30 days before sunset: every /api/v1/* response carries Deprecation: true, Sunset: <date>, and Link: <v2-path>; rel="successor-version" per RFC 8594/api/v1/* still serves normally; the headers are advance notice.

  3. Sync-tier customers: personal Slack heads-up 30+ days before sunset.

  4. On sunset day: /api/v1/* auto-migrates.

    • A cluster-first keeper route returns 308 Permanent Redirect to its /api/v2/* equivalent. 308 preserves the method and the query string, so a conforming client follows the redirect and keeps working without a code change.
    • A demoted surface (the standalone masters/* and bandcamp/* top-level — in v2 release/master and Bandcamp data are dimensions of the artist dossier, not first-class resources) returns 410 Gone with a Link to its successor and a JSON body explaining where the data moved.

    The cutover is feature-flagged and announced; until it's flipped, /api/v1/* serves unchanged. (This reverses an earlier draft of this page that promised no auto-redirect — for the v2 cut we chose method-preserving 308s so existing integrations migrate without breaking.)

What counts as a breaking change

| Change | Major bump? | |---|---| | Add a new endpoint | No | | Add a new optional query/body param | No | | Add a new field to a response | No | | Remove a field from a response | YES | | Rename a field | YES | | Change a field's type (e.g. string → number) | YES | | Tighten a validation rule (rejects what was previously accepted) | YES | | Change error code mapping (e.g. 400 → 422 for the same input) | YES | | Change rate-limit values | No (but we'll announce) | | Add a new error code | No | | Change authentication scheme | YES |

What's reserved for v2

Speculative — not actually planned:

  • GraphQL surface (alongside REST, not replacing it)
  • Bulk dumps (currently explicitly out of scope per TOS)
  • Webhooks for usage events (customer-initiated push notifications)

If you have feedback on v2 direction, the public issue tracker on github.com/hosaka-fm/crate is the right place.

What we DON'T promise

  • 99.99% uptime SLA (v1.0). We publish actuals via /api/v1/health + aim for ≥99.5%.
  • Real-time data freshness beyond the existing freshness.ridden_lag_s / freshness.mirror_lag_s signals (typically under 2 minutes, but bursty under producer load).
  • Specific p50/p95/p99 response-time SLOs. We publish actuals; if you need contractual SLAs, that's a Sync-tier conversation.
  • Backwards compatibility for clients of the public consumer surface (the /crate page) that aren't authenticated API customers.
  • SDK clients. We've deliberately not pre-built language SDKs; build against the OpenAPI spec. If a customer requests one, we'll ship it.

Why this matters

API customers integrate crate into paid client deliverables (sync agencies), production music apps (developers), and internal tooling (small teams). A surprise breaking change kills trust. The versioning contract on this page is what makes crate a trust-worthy substrate to build on — versioned, opinionated, sunset-honored.

Built right, an API is a quiet trust contract. This page is the trust contract.