
## Model lifecycle

A model in the Vibecode catalog is in one of three states. The state determines whether the call is served by the requested model and which signals arrive in the response headers. The rules are common to all model calls — chat, embeddings and speech recognition.

| State | What happens on a call | Response headers |
|-----------|--------------------------|------------------|
| `ACTIVE` | Standard service, no signals to the client | — |
| `DEPRECATED` | The request is served by the requested model, and deprecation signals arrive in the headers | `Deprecation: true`, `Sunset: <disable date>` if one is assigned, `Link: </v1/models/<successor>>; rel="successor-version"` and `X-Model-Replacement: <successor id>` if a successor is assigned |
| `DISABLED` | The request is **transparently** redirected to the successor model. `response.model` contains the model that actually served it | `X-Model-Fallback: <requested modelId>`, `X-Model-Replacement: <actual modelId>`, `X-Model-Fallback-Reason: model_disabled` |

## What the client should do

- **`Deprecation: true`** — flag the model's usage in your logs. If a `Link: rel=successor-version` is present, plan the migration. Until the `Sunset` date the model works; after it the model will be disabled.
- **`X-Model-Replacement` without `X-Model-Fallback`** — this is the recommended successor model for future requests. You can switch immediately.
- **`X-Model-Fallback` present** — the model is already disabled, and the response came from the successor. Its identifier is in `response.model`. Update `model` in your code to this identifier or keep the old one: the redirect will keep working.

If no successor is configured for a disabled model, the call returns `503 model_unavailable`. This is the only case where the redirect for the `DISABLED` state does not fire.

## Signal in the model catalog

In [`GET /v1/models`](./list.md) models in the `DEPRECATED` state remain — the client sees that they still work. Models in the `DISABLED` state are hidden from the catalog, but a direct request by their `modelId` still goes through the redirect to the successor.

You can check the state of a specific model via [`GET /v1/models/:modelId`](./get.md): for a retired model the response gains a `replaced_by` field with the successor's identifier, and `pricing` shows the successor's price — the one the call is actually billed at.

## Known specifics

**The headers follow the standards.** `Deprecation`, `Sunset` and `Link` follow [`RFC 8594`](https://datatracker.ietf.org/doc/html/rfc8594) and [`RFC 8288`](https://datatracker.ietf.org/doc/html/rfc8288), so they are recognized by standard HTTP clients without extra code.

**The redirect does not change the request's price.** The call is billed at the price of the model that actually served it. For a disabled model this is the successor's price, not its own.

## See also

- [List models](./list.md)
- [Get model](./get.md)
- [Create chat completion](/docs/ai/chat/completions)
- [AI Router](/docs/ai)
