Deprecation Policy
This policy covers every endpoint under /api/v1/* documented as external-facing, and every request header, response header, field, error code, and webhook event in the external API.
First-party-only routes (admin UI, internal services, /api/v1/internal/*) are out of scope.
Principles
- No silent breakage. A partner running yesterday’s client against today’s production must either keep working, or have received at least one release cycle of notice.
- Deprecation is signaled in three places: the HTTP response itself, the OpenAPI document, and the changelog. A change that only appears in git history does not count as deprecated.
- Sunset dates are honored. If a
Sunsetheader promises a date, removal cannot precede it.
Versioning
- The public API is versioned by URL prefix (
/api/v1/). - Additive changes — new endpoints, new optional fields, new headers, new error codes, new event types — land inside
v1without bumping the version. - Breaking changes — removals, type narrowings, required-field additions, renamed fields, changed semantics — require either a compatible coexistence path or a new URL prefix (
/api/v2/…). v1andv2coexist during the migration window.v1endpoints carryDeprecation/Sunsetheaders pointing at their replacement.
What is a breaking change
Breaking (requires notice + version bump or coexistence path):
- Removing an endpoint, field, header, error code, scope, event name, or enum value
- Renaming any of the above
- Narrowing a type (e.g. string → enum, optional → required)
- Tightening validation to reject previously-accepted input
- Changing an HTTP status code for an existing outcome
- Changing the shape of a documented error body
- Changing the meaning of an existing field or header
Not breaking (safe to add inside v1):
- New optional request fields
- New response fields (clients must tolerate unknown fields per JSON parsing conventions)
- New optional headers
- New enum values where the schema documents extensibility
- New error codes for previously-500 outcomes
- New endpoints
- New webhook event types
Notice windows
| Change | Minimum notice | Where signaled |
|---|---|---|
| Remove or rename a public endpoint | 180 days | Deprecation + Sunset headers + changelog + docs |
| Remove or rename a response field | 180 days | Deprecation header + changelog + docs |
| Remove an error code or scope | 180 days | Changelog + docs |
| Change default pagination or page size | 90 days | Changelog + docs |
| Tighten validation | 90 days | Changelog + docs |
| Security fix that forces a change | ASAP | Changelog + security advisory |
The clock starts on the day the deprecation ships to production. Days are calendar days.
On-wire signals
Deprecated responses carry:
HTTP/1.1 200 OK
Deprecation: true
Sunset: Wed, 01 Oct 2026 00:00:00 GMT
Link: </api/v2/sites>; rel="successor-version"| Header | Purpose |
|---|---|
Deprecation: true | Signals this endpoint / field is deprecated |
Sunset: <HTTP-date> | Earliest date the endpoint may be removed |
Link: <url>; rel="successor-version" | Where to migrate (when a replacement exists) |
Clients are encouraged to surface these headers in their logs and dashboards.
In the OpenAPI document
- Deprecated endpoints and fields are marked
deprecated: true. - The endpoint description ends with: “Deprecated: use
<replacement>. Sunset YYYY-MM-DD.” - The changelog entry lives under Deprecated, followed by a Removed entry on deletion.
Removal
On the sunset date:
- The endpoint / field / header is deleted from the codebase.
- The change is noted under Removed in the changelog.
- Removed endpoints return 410 Gone with a
problem+jsonbody:
{
"type": "https://problems.eunifyer.com/gone",
"title": "Gone",
"status": 410,
"detail": "This endpoint was removed on 2026-10-01. Use /api/v2/sites instead.",
"code": "gone",
"successor": "/api/v2/sites"
}410 responses are maintained for at least 90 days after removal before the route reverts to 404.
Security exceptions
A security advisory may justify skipping the standard notice window. When that happens:
- The change ships behind a feature flag when feasible.
- A security advisory is published alongside the release.
- The changelog entry references the advisory explicitly.
No other exceptions.
Partner notification
Before a breaking change reaches production:
- Announce in the partner changelog.
- Update the OpenAPI description and
deprecatedflag. - Email known partners with active credentials at least 30 days before sunset.