The confusing part of this 404 is that the model usually does exist — in Anthropic's docs, in a blog post, in last quarter's code. What it does not exist in is the list your API key is allowed to address today.
The error
{
"type": "error",
"error": {
"type": "not_found_error",
"message": "model: claude-3-5-sonnet"
}
}Causes and fixes at a glance
| Cause | Fix |
|---|---|
| A retired dated snapshot | Snapshots are deprecated on a published schedule and then stop resolving. Move to a current one. |
| An alias that never existed | `claude-3-5-sonnet` is a family, not a callable id. Anthropic ids carry a version or a date suffix. |
| The model is real but not enabled for your account | Newest models can be gated by tier. The 404 is indistinguishable from a typo — check the models endpoint, not the docs. |
| An OpenAI model name on an Anthropic endpoint | `gpt-4o` at api.anthropic.com is a missing model, not a routing error. Use a gateway if you want one endpoint for both. |
Ask the API, not the documentation
Docs describe the catalogue; the models endpoint describes your catalogue. When those disagree, the endpoint is right. Anything absent from this list will 404 no matter how current it looks elsewhere.
curl -s https://api.anthropic.com/v1/models \
-H "x-api-key: $ANTHROPIC_API_KEY" \
-H "anthropic-version: 2023-06-01" \
| grep '"id"'Pin deliberately, upgrade deliberately
Hard-coding a dated snapshot buys reproducibility and a future 404 on a date you did not choose. Reading the model id from configuration means the fix is a deploy-time value, not a code change — and the same switch is what lets you fail over when a model is busy rather than missing.
import os
# One place to change when a snapshot retires.
MODEL = os.environ.get("LLM_MODEL", "claude-sonnet-4-6")
resp = client.chat.completions.create(
model=MODEL,
messages=[{"role": "user", "content": "ping"}],
)Tell 404 apart from 400 and 403
404 means the name resolved to nothing. A 400 means the name was fine but the request was not (bad parameter, malformed content). A 403 means the model exists and you may not use it. Only 404 is fixed by changing the model string.
If you’re calling through Kunavo
Kunavo's catalogue is the list its /v1/models endpoint returns, and every id in it is callable on any funded key — there is no per-account model gating, so the "real but not enabled for you" cause above does not arise. Because the same endpoint serves Claude, Gemini and GPT-family names, an OpenAI id is not a wrong-endpoint mistake either; it just routes. Retirements still happen upstream, and when a model is withdrawn its id is redirected or documented rather than left to 404 silently. Current ids and their per-token rates are in the Claude API price list.
FAQ
Is 404 ever a temporary error?
No. Unlike 429, 500 and 529, retrying a 404 with the same model string can only fail again. Change the string or stop.
How do I know when a snapshot retires?
Anthropic publishes deprecation dates for dated snapshots. If you pin snapshots, that schedule is a calendar item; if you read the id from config, it is a one-line change.
Why does my colleague's key work with the same name?
Model availability can differ by account tier. Compare the two /v1/models responses — that difference is the answer.
Related guides
- model_not_found / 404 — model naming across Claude, Gemini and gateways
- Claude API 401 authentication_error / invalid x-api-key — every cause
- Claude API 529 overloaded_error — what it is and how to ride it out
More error semantics live in the error reference; getting a key takes a minute via sign up and the authentication docs.