Models
A model is identified by an author/model id (the same scheme OpenRouter uses). The catalog
aggregates every model offered by active providers. You pick the model, and provider
routing decides which provider fulfills it.
Model ids
You can pass either form as the model field in a request body:
| Form | Example | Notes |
|---|---|---|
author/model | openai/gpt-4o | Recommended. The segment before the first / is the model author. |
| bare model | gpt-4o | Accepted; resolved against the catalog. |
The author/model id refers to the model author (e.g. openai, anthropic), not to
the provider fulfilling the request. Providers are addressed separately through the
provider object.
Dot and hyphen forms
Some models write their version number with a dot upstream and a hyphen in the provider-native id. Onlist publishes one form as the public id and accepts the other as an alias, so both resolve to the same model:
| Where it appears | Example |
|---|---|
Public id: id, model page URL, sitemap | anthropic/claude-opus-4.8 |
Alias, also accepted in the model field | anthropic/claude-opus-4-8 |
canonical_slug in GET /v1/models | anthropic/claude-opus-4-8 |
This matches OpenRouter, which publishes the same models under the dot form. Requesting
the hyphen form works and is not deprecated; a model page opened at the hyphen URL
redirects to the published one. If you persist model ids, persist canonical_slug: it
does not move when the published form does.
Listing models
GET /v1/models returns the catalog in the OpenAI/OpenRouter list shape. It is public,
no authentication required, and is cached for about 60 seconds. There is one entry per
(author, model) aggregated across active, ready listings.
curl https://onlist.io/v1/modelsA response looks like this:
{
"object": "list",
"data": [
{
"id": "anthropic/claude-opus-4.8",
"name": "Anthropic: Claude Opus 4.8",
"owned_by": "anthropic",
"canonical_slug": "anthropic/claude-opus-4-8",
"created": 1780680536,
"context_length": 1000000,
"pricing": { "prompt": "0.0000030000", "completion": "0.0000150000" },
"supported_parameters": ["tools", "reasoning", "structured_outputs"]
}
]
}
A few honest details about the fields:
pricing.prompt/pricing.completionare USD-per-token decimal strings (so"0.0000030000"is $3.00 per million prompt tokens).pricing.overridesappears when the priced provider charges more for long prompts, in OpenRouter's shape:[{ "min_prompt_tokens": 200000, "prompt": "...", "completion": "..." }]. A request whose full prompt is longer thanmin_prompt_tokensis billed entirely at that entry's prices;pricing.prompt/pricing.completionstay the base (lowest) prices.nameis the human-readable display label (Anthropic: Claude Opus 4.8), not a copy ofid.canonical_slugis the provider-native form of the id. It stays put whenidis published under an alias form, so it is the safer value to store.createdis the listing'screated_at(when a provider listed the model on Onlist), not the model's release date, a deliberate divergence from OpenRouter.- The response carries an
X-Onlist-Catalog-Version: 1header pinning the catalog shape.
Anthropic shape
A request that carries the anthropic-version header gets the catalog in the Anthropic
Models API shape instead, the same switch OpenRouter makes. This is what the Anthropic
SDK's models.list() and Claude Code's gateway model discovery
(CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY=1) receive:
{
"data": [
{
"id": "anthropic/openai/gpt-5.6-sol[1m]",
"type": "model",
"display_name": "OpenAI: GPT-5.6 Sol",
"created_at": "2026-09-22T16:32:12Z",
"max_input_tokens": 1050000,
"max_tokens": 128000,
"capabilities": null
}
],
"has_more": false,
"first_id": "anthropic/openai/gpt-5.6-sol[1m]",
"last_id": "anthropic/openai/gpt-5.6-sol[1m]"
}
- Every id sits under
anthropic/, because Claude Code drops models whose id mentions neitherclaudenoranthropic. Models with a context window of one million tokens or more end in[1m], which Claude Code reads as the window size. - Claude models use the hyphen form (
anthropic/claude-opus-5-5) rather than the dotted public id, because Claude Code misreads the dotted form as an older model. - Every id in this list is accepted as-is in the
modelfield, with or without[1m]. - Models that cannot output text are left out.
limit,after_idandbefore_idpage the list as in the Anthropic API; withoutlimitthe whole list comes back.
Listing models for a key
GET /v1/models/user returns the same list narrowed to what one API key can actually
call. It is the authenticated sibling of GET /v1/models: identical entry shape, the same
X-Onlist-Catalog-Version: 1 header, projected from the same 60-second catalog snapshot.
Send the API key you already use for inference:
curl https://onlist.io/v1/models/user \
-H "Authorization: Bearer YOUR_ONLIST_TOKEN"A missing, unknown or revoked key returns 401. The endpoint is rate limited per
credential, 60 requests per minute and 500 per day per account. When nothing survives the
filters the body is {"object": "list", "data": []} — never null. A management key is
accepted as well, but it stands for the whole account, which carries no model or provider
restriction, so it gets the full catalog back.
Three filters run, in this order:
- Model access list. If the key carries a model allowlist (“Only allow selected models” in the key drawer), only the models on it are listed.
- Denied providers. A model drops out when every listing behind it belongs to a provider the key's routing policy denies.
- Allowed providers. If the key's routing policy sets a provider allowlist, only models with at least one allowed provider selling them are listed. This holds even when the key also has "fall back to every provider once the allowlist is exhausted" turned on, which is the default: the list expresses your intent, while the fallback is a runtime safety net for a request already in flight.
zdr and data_collection are per-request parameters rather than key settings, so they
never narrow this list. See Provider routing.
This endpoint is for programs holding one specific key — typically the model picker of an
IDE agent such as OpenCode or Cline — so the dropdown offers only models that key can
really call, instead of surfacing a 403 after the user picks one. If you just pointed
base_url at Onlist for ordinary chat calls, you do not need it: keep using the public
GET /v1/models, which stays the full catalog and never shrinks because of a key.
The onlist/auto default
onlist/auto (and the OpenRouter alias openrouter/auto) resolve to one static
platform-default model. They do not inspect your prompt and pick the best model
per request. These sentinels are request-side routing values; they never appear in the
GET /v1/models data[]. Sending an auto sentinel to an endpoint that doesn't support
it returns 422.
Model variant suffixes
A : suffix on a model id means one of two things, and Onlist reads them the way
OpenRouter does. Only the last : segment is inspected.
Routing shortcuts never change which model you get. They are stripped from the id and
only reorder the eligible providers, or, for :online, turn on web search. Without a suffix
you get the default Smart order:
like OpenRouter's default, traffic is drawn in proportion to the inverse square of each
provider's delivered price, adjusted for reliability and speed. See
Default routing (Smart).
| Suffix | Effect |
|---|---|
:floor | Lowest effective price first (same as provider.sort: "price"). |
:nitro | Fastest first by measured speed over the last 7 days, combining time to first token and throughput (same as provider.sort: "throughput"). |
:exacto | Honored as the default ordering, which is already a composite quality score. No warning. |
:online | Turns on web search for the request, the same as plugins: [{"id": "web"}]: one search before the model answers. Chat Completions only; on other endpoints it is dropped with a warning. To let the model decide when and how often to search, declare the openrouter:web_search tool instead. |
# Route to the cheapest provider for this model
curl https://onlist.io/v1/chat/completions \
-H "Authorization: Bearer YOUR_ONLIST_TOKEN" \
-H "Content-Type: application/json" \
-d '{"model": "openai/gpt-4o:floor", "messages": [{"role": "user", "content": "hi"}]}'
Static variants are separate models, not options. Every other suffix, including
:free, :batch, :thinking and anything Onlist does not recognize, stays in the model id
and is routed to its own listing: deepseek/deepseek-v4:thinking and
deepseek/deepseek-v4 are two different products.
If no provider sells that exact id, the request returns 404 no_listing_for_model.
Onlist does not quietly drop the suffix and serve you the base model. There are no
:free listings on Onlist today, so those ids have nothing behind them. Full table and
the rules for combining the two kinds:
Provider routing.
Next steps
- Provider routing: Choose which provider fulfills a model: only, sort, allow, max_price.
- Streaming: Stream responses over Server-Sent Events.
- Web search: What
:online, thewebplugin and theopenrouter:web_searchtool do, and what they cost. - Usage & cost: Token usage, and where cost actually lives.
- OpenAPI spec: Full request and response schemas, including GET /v1/models and GET /v1/models/user (YAML download).