Every API deprecation is a promise-breaking exercise with someone else's production system on the other end. The technical part — removing an endpoint or field — is trivial. The actual work is giving consumers enough warning, signal, and migration support that removing it doesn't take down integrations you don't control and often can't even see.
Signal deprecation in the response, not just the changelog
RFC 8594 defines a Sunset HTTP response header carrying the date after which a resource will stop being available, and it's increasingly paired with the (still-draft but widely implemented) Deprecation header to signal "this is deprecated now" separately from "this stops working on this date." Putting both directly in the API response means a consumer's own monitoring or logging can catch the signal automatically, instead of relying on someone reading a changelog that may never reach the engineer who wrote the integration two years ago.
HTTP/1.1 200 OK
Deprecation: @1719849600
Sunset: Sat, 01 Nov 2026 00:00:00 GMT
Link: ; rel="deprecation"
Content-Type: application/json
{"order_id": "ORD-1029", "status": "shipped"}
Your versioning strategy decides how painful deprecation is
APIs versioned in the URL path (/v1/orders, /v2/orders) make deprecation explicit and easy to route, but force consumers to migrate an entire surface at once. Header-based versioning (Accept: application/vnd.example.v2+json) or field-level evolution (adding new fields, never repurposing old ones, and deprecating individual fields rather than whole endpoints) let you retire small pieces independently, which is gentler but requires more disciplined per-field deprecation tracking. Stripe's approach — a versioned API where each account is pinned to the version active when the account was created, with explicit opt-in upgrades — is the reference example of minimizing forced-migration blast radius.
Adding a new optional field, a new endpoint, or a new enum value is backward compatible and shouldn't trigger a version increment or deprecation notice — as long as consumers are documented to ignore unknown fields. Reserve version bumps for actual breaking changes: removing a field, changing a type, or altering existing behavior.
Measure actual usage before committing to a sunset date
Announcing a sunset date without first checking real traffic to the deprecated endpoint is how deprecations turn into incidents. Instrument the deprecated path specifically — request counts by API key or client ID — and use that data both to set a realistic timeline and to reach out directly to the highest-volume consumers before the public announcement goes out. A consumer hearing about a breaking change from your outreach team, rather than from a broken integration, is the difference between a manageable migration and a support fire.
A consumer that hasn't responded to deprecation emails by the sunset date isn't necessarily fine with it — they may have missed the email, or the integration may be unmonitored legacy code still processing real transactions. Where the blast radius justifies it, keep serving the deprecated version with a warning for high-volume unmigrated clients rather than hard-cutting on the announced date.
A defensible deprecation timeline
There's no universal standard duration, but a pattern that holds up across most B2B APIs: announce with the Deprecation header immediately, publish a migration guide with the announcement (not weeks later), give a minimum of 6-12 months before the Sunset date for anything with meaningful external usage, and send direct reminders at fixed intervals (announcement, halfway point, 30 days out, 7 days out) rather than a single notice at the start.
| Phase | Action |
|---|---|
| Announcement | Deprecation header live, migration guide published |
| Mid-window | Direct outreach to highest-volume unmigrated consumers |
| 30 days before sunset | Escalate to email/account manager for remaining traffic |
| Sunset date | Sunset header honored, old version returns 410 Gone or is removed |
Wrapping up
Deprecation strategy is mostly a communication and measurement problem wearing a technical costume. Signal it in the response headers so tooling can catch it automatically, measure real usage before locking in a sunset date, and reach out directly to whoever's still generating traffic rather than assuming a changelog entry was enough.
Independent software engineer in Nairobi specialising in Acumatica customisations, Laravel backends, and tax fiscalisation integrations across East and Southern Africa.