Deprecations
Declare deprecations and sunset dates on a route and have them reach your editor, OpenAPI, Swift, Kotlin, and the Deprecation and Sunset response headers.
Routes
| Declaration | Type |
|---|---|
deprecated | boolean | string | { message?, date?, link? } |
sunset | string | { date, link? } |
Dates are ISO 8601, a date alone meaning midnight UTC. On the wire, Deprecation is Unix seconds and Sunset an HTTP date.
Set deprecated on the route, either true, a migration message, or the object form with a date and a documentation link:
With a date, every response from the route announces it:
true or a message alone sends no header. The date may sit in the future, announcing a deprecation before it takes effect.
Sunset
A route scheduled for removal declares when. The object form adds a link to the retirement policy:
Every response from the route then announces it:
sunset stands on its own, a route can sunset without being deprecated. defineConfig rejects a sunset or deprecated.date that does not parse as ISO 8601.
Fields
| Declaration | Type |
|---|---|
.meta({ deprecated: ... }) | boolean | string |
Fields declare it in their Zod metadata:
What each output emits
- OpenAPI marks the operation and the field's schema with
deprecated: true(the spec has no message field), and documents theDeprecation,Sunset, andLinkheaders on every response of a route that sends them. - The TypeScript client emits
@deprecated use `email_address` insteadon the method and on the field, which strikes them through in your editor whether or not the extension is installed. - Swift emits
@available(*, deprecated, message: "use `email_address` instead"), so the message reaches autocomplete and compiler warnings. - Kotlin emits
@Deprecated("use `email_address` instead"), reaching the same places. - The headers themselves are sent by the server, so every client sees them at runtime.