For the complete documentation index, see llms.txt. This page is also available as Markdown.

Model Deprecations

GET https://api.aimlapi.com/v1/models/deprecations

GET /v1/models/deprecations lists the models that are retiring, have already been withdrawn, or were folded into another model — with the date it happened and the id to move to. No API key is required for this request. You can also open the feed directly in a browser.

It exists to answer the one question GET /v1/models structurally cannot. A model missing from the catalogue may have been withdrawn, may have been folded into another id that still works, or may never have existed — and the catalogue returns the same "not here" for all three. Treating them alike is how a model-sync job ends up disabling models that are still serving.

https://api.aimlapi.com/models/deprecations and https://api.aimlapi.com/api/v1/models/deprecations serve exactly the same data, as does deprecated in place of deprecations on any of the three. /v1/models/deprecations is the canonical path and the one to use in new integrations.

Get the deprecation feed

Returns the deprecation entries matching the given filters, newest first.

get
Query parameters
statusstringOptional

Keep only entries in these states: deprecated, superseded or withdrawn. Values are case-insensitive and may be comma-separated (?status=superseded,withdrawn) or repeated (?status=superseded&status=withdrawn). Unknown values are ignored rather than rejected — a parameter holding no recognised value filters nothing and returns the whole feed.

Example: withdrawn
sincestringOptional

Keep only entries whose deprecated_at or shutdown_at falls on or after this date. Plain YYYY-MM-DD, no time part. Entries carrying neither date are dropped, because there is nothing to compare against. A malformed value is ignored rather than rejected, so a broken poll returns the whole feed instead of a 400.

Example: 2026-08-01
Responses
200

The deprecation feed, newest first.

application/json
objectstringRequired

Always list.

Example: list
generated_atstringRequired

When this response was built, in UTC. It moves on every call and is deliberately excluded from the ETag.

Example: 2026-08-24T13:59:21.643Z
get/v1/models/deprecations
curl -L \
  --url 'https://api.aimlapi.com/v1/models/deprecations?status=withdrawn&since=2026-08-01'
{
  "object": "list",
  "generated_at": "2026-08-24T13:59:21.643Z",
  "data": [
    {
      "id": "openai/gpt-5-codex",
      "aliases": [
        "gpt-5-codex"
      ],
      "status": "withdrawn",
      "deprecated_at": "2026-07-30",
      "shutdown_at": "2026-07-30",
      "replaced_by": "deepgram/aura-2",
      "reason": "provider_delisted"
    }
  ]
}

The three states

status is the field to branch on, and the difference between the three is what your integration should do next.

status

Does the id still work?

What to do

deprecated

Yes — still serving, retirement announced

Plan the migration before shutdown_at. Nothing breaks today.

superseded

Yes — folded into another model, still resolves

Nothing is broken. Switch to replaced_by when convenient.

withdrawn

No — requests return 404

Switch to replaced_by, or pick a replacement from the catalogue.

A deprecated model is read from its live model card, so it announces its own sunset while it still works. Once a real retirement date is set, it is dropped from GET /v1/models — but it keeps serving, and GET /model/{id} still returns its card with the sunset dates attached. The other two states come from a durable record instead: a withdrawn model has no card left to read.

Response shape

Dates are plain YYYY-MM-DD. deprecated_at is the date the provider announced the retirement, or the date we learned of it when they gave no notice; shutdown_at is the date it stopped, or will stop, serving. reason is provider_delisted, consolidated or unknown — and null on an entry read from a live model card.

Entries are ordered newest-first by the most recent date they carry, then by id. A model published under several endpoint types appears once: the sunset belongs to the model, not to the route.

Filtering

Both filters are optional, and both fail open: an unrecognised value is ignored rather than rejected. This is a discovery surface, and a typo in a polling job should not turn every poll into a 400.

  • status — case-insensitive, comma-separated (?status=superseded,withdrawn) or repeated (?status=superseded&status=withdrawn). A parameter holding no recognised value filters nothing and returns the whole feed.

  • since — plain YYYY-MM-DD, no time part. Keeps entries whose deprecated_at or shutdown_at falls on or after that date. Entries carrying neither date are dropped, because there is nothing to compare against.

Polling and caching

Responses carry a weak ETag and Cache-Control: public, max-age=300. Send the tag back as If-None-Match and you get 304 Not Modified with an empty body when nothing changed:

The tag is computed over data only. generated_at changes on every call, so including it would make every poll a cache miss — the tag moves only when the feed's contents actually move. Polling daily is plenty; the payload is small and changes rarely.

Keeping an integration in sync

The feed and the catalogue answer different halves of the same question, so read both. The catalogue says what you can use today; the feed explains anything the catalogue no longer lists.

The last branch is the one worth keeping separate. A name in neither list was never a model id here, which is a different problem from a model that went away — and it is the case a catalogue-only check silently reports as a deprecation.

Looking for a replacement by hand rather than in code? All Model IDs lists the current catalogue alongside its deprecated models section.

Last updated

Was this helpful?