# API Versioning — Derived Rules > Derives from `domains/api/first-principles.md` P5 (Versioning) and P10 (Stability). ## The Default: No Breaking Changes - A breaking change is a new version. There is no "minor" breaking change. - Breaking changes: removing a field, changing a field type, changing a field's semantics, changing required vs optional, changing error codes. - Non-breaking changes: adding a field, adding an endpoint, adding an optional parameter, loosening validation. ## Version Policies ### URL Versioning (`/v1/users`) - Simple, visible, cacheable. - Breaking changes bump the major version: `/v1` → `/v2`. - Old versions are supported in parallel during the deprecation window. ### Header Versioning (`Accept: application/vnd.atelier.v1+json`) - Invisible in the URL; harder to test. - Useful when the URL must stay stable (e.g., public webhooks). ### Semantic Versioning (for libraries/SDKs) - Major: breaking. Minor: additive. Patch: fix. - Follow semver strictly. A "minor" that breaks is a lie. ## Deprecation Cycle (P5 Reversibility) 1. **Announce**: mark the field/endpoint `@deprecated` with a sunset date. 2. **Support**: keep the old version working until the sunset date. 3. **Monitor**: track usage of the deprecated surface. 4. **Retire**: when usage drops below threshold (or sunset passes), remove. 5. **Never** remove without announcing. The cost of a silent break is paid by every consumer. ## Sunset Headers (P9 Error Transparency) - Deprecated endpoints return `Sunset: ` header. - Deprecated endpoints return `Deprecation: ` header. - A consumer who reads headers knows when to migrate. ## Versioning vs Compatibility - Versioning is the mechanism. Compatibility is the property. - Backward compatibility: old consumers work with the new version. - Forward compatibility: new consumers work with the old version (harder, rarer, usually not worth it). - Aim for backward compatibility. Forward compatibility is for protocols, not APIs. ## What Violates Versioning | Violation | Principle | |-----------|-----------| | Removing a field without deprecation | P5, P10 | | Changing a field's type in a "minor" release | P1, P5 | | No sunset header on a deprecated endpoint | P9 | | Two versions with divergent semantics for the same field | P1 |