Skip to content
docs/modelsModels

Models

List every model, its category, its status and the price it is published at.

GET /v1/models is the whole catalogue, every model, its category, its status and every axis it bills against. It answers anonymously and is cached, so a model picker or a pricing page can read it straight from a browser. There is no companion route naming the upstreams behind a model: which host serves a request is not part of what the model is.

GET/v1/modelsAvailable

Every model with its category, status, published price and per-token rates.

AUTHENTICATION
Bearer token, Authorization header
REQUIRED SCOPE
public

What a model row carries

FIELDTYPEMEANING
idstringWhat you put in model. The primary alias where one is set, otherwise the canonical slug.
canonical_slugstringThe stable vendor/model slug. Equal to id unless id is an alias.
namestringDisplay name, for a human. GPT-4o mini.
descriptionstringOne line on what the model is for.
categoryenumtext, image, video, audio, embedding or rerank. Decides which route serves it.
statusenumavailable, coming_soon or deprecated.
unitstringThe billing unit in words, per 1M tokens, per 5s clip, 720p.
pricenumber, nullHeadline price in that unit. Null while a model is coming_soon.
reference_pricenumber, nullThe same unit at the vendor's own list price.
context_lengthinteger, nullLargest context this model accepts. Null where the idea does not apply.
createdintegerUnix seconds the model joined the catalogue.
architectureobjectModalities in and out, tokeniser, instruct type.
pricingobjectEvery metered axis, as strings.
supported_parametersstring[]Request fields the model honours.

Frozen, then additive

The first six fields (id, category, status, unit, price and reference_price) are frozen, and every change since has been an addition. That is the only kind of change a published catalogue may make: a field appears, an existing one does not change meaning and does not go away. Read the fields you need by name and ignore the rest, and nothing added next month can break you.

Rates are strings, the headline price is a number

The rates inside pricing come back as JSON strings. A per-token rate is around 0.0000005; a client that parses a million of them as float64 and adds them up drifts away from the invoice, and internally the value is a decimal backed by a numeric column, so emitting a number would mean converting it to a double on the way out. Parse rates with a decimal library, not parseFloat. price and reference_price stay numbers: they are a headline for a human to read, not an input to billing arithmetic.

The pricing object

AXISMETERED ON
promptEach input token.
completionEach output token.
cached_promptEach input token served from the upstream prompt cache.
internal_reasoningEach reasoning token, where they are billed apart from completion.
requestA flat charge per call, on top of any metered axis.
imageEach generated image.
image_inputEach image supplied as input.
video_secondEach second of generated video.
audio_secondEach second of generated or transcribed audio.
web_searchEach built-in web-search call.

Null on an axis means the model is not metered on it. That is a different claim from the string 0, which means metered and free. A text model has a null image rate, a promotional model has a zero one, and a client that treats the two the same bills the wrong thing the first time one becomes the other.

architecture

architecture.modality is the summary (text->text, text->image), and the arrays under it are the precise version: input_modalities is what you may send, output_modalities is what comes back. tokenizer names the tokeniser the context length is counted in, and instruct_type names the prompt template that models needing one expect; both are null where the vendor has published neither. Check input_modalities before sending an image inside a message, rather than finding out from a 400.

supported_parameters

supported_parameters lists the request fields this model honours. Tools, temperature, response_format and the rest. Read it before you send one: a parameter that is not on the list may be ignored rather than refused, so a request carrying tools can come back as a plain completion. Checking the list at render time is cheaper than discovering it in a response you have already paid for.

The three statuses

STATUSPRICEWHAT A REQUEST DOES
availableSetRouted and billed normally.
coming_soonNull409 model_unavailable. Announced, listed, not yet servable.
deprecatedSetStill served and still billed. It will stop being. Move off it.

Nothing is priced automatically. A model discovered on an upstream catalogue arrives as coming_soon with a null price and stays there until somebody sets one, which is why an unpriced model is refused rather than served for nothing: a 200 that charged nothing cannot be billed for afterwards. deprecated exists so that retiring a model is distinguishable from deleting one, without it, a model on its way out looks exactly like a model that never existed.

Aliases

gpt-4o and openai/gpt-4o are the same model. The alias is resolved in the same query as the slug, so the short form costs the same single round trip as the long one and neither is a redirect. The response, the charge and the record on GET /v1/generation are identical. Store canonical_slug rather than id: canonical_slug is stable, while the id published for a model changes if its primary alias changes.

Narrower reads

Four routes answer a smaller question than the full catalogue, and each is cheaper to parse than filtering it yourself. GET /v1/models/count is the number of servable models. GET /v1/embeddings/models, /v1/images/models and /v1/videos/models are the catalogue narrowed to one modality, each carrying a total_count beside its data. GET /v1/model/{author}/{slug} is one model. Note the singular model, which is the spelling this route has and the plural one does not.

GET/v1/models/countAvailable

How many models are servable right now.

AUTHENTICATION
Bearer token, Authorization header
REQUIRED SCOPE
public

GET/v1/model/{author}/{slug}Available

One model by slug. Singular 'model'. OpenRouter's spelling for this route.

AUTHENTICATION
Bearer token, Authorization header
REQUIRED SCOPE
public

GET/v1/embeddings/modelsAvailable

The catalogue narrowed to embedding models, with a total count.

AUTHENTICATION
Bearer token, Authorization header
REQUIRED SCOPE
public

GET /v1/models/user exists and answers, but it returns the same set as GET /v1/models: model access here is not scoped per key, so there is no narrower list for it to give. It is published so that a client written against a gateway that does scope access gets a catalogue rather than a 404.

Reading the catalogue

cURLTwo catalogue reads, no key
# Every text model callable today, cheapest first. The catalogue
# route takes no query parameters. Narrow it client-side, or use one
# of the modality routes above.
curl -s https://api.routehook.ai/v1/models \
  | jq '[.data[] | select(.category == "text" and .status == "available")]
        | sort_by(.price)
        | .[] | {id, price, unit}'

# One model in full, including every axis it bills against.
curl -s https://api.routehook.ai/v1/model/openai/gpt-4o-mini \
  | jq '.data | {id, name, context_length, pricing, supported_parameters}'