Console
API reference

List models

The model catalog.

GET/v1/models

GET /v1/models lists every model id RouterPlus can serve on your key, one row per id. GET /v1/models/<id> returns one row of that list. SDK models.list() and models.retrieve() calls resolve to these endpoints, so both answer in two shapes:

RequestResponse shape
No anthropic-version headerOpenAI
anthropic-version header present (any value)Anthropic

The Anthropic SDK sends anthropic-version on every request, so each SDK gets its own shape with no configuration.

Send your key as Authorization: Bearer $TM_API_KEY or as x-api-key: $TM_API_KEY. A missing or invalid key is a 401 with error_type: "auth" (see Errors).

List models: OpenAI shape (default)

bash
curl -s https://dev2-api.routerplus.com/v1/models \
  -H "Authorization: Bearer $TM_API_KEY"
json
{
  "object": "list",
  "data": [
    { "id": "claude-haiku-4-5", "object": "model", "created": 1756900000, "owned_by": "anthropic",
      "context_length": 200000,
      "architecture": { "input_modalities": ["text", "image", "file"], "output_modalities": ["text"] } },
    { "id": "gpt-image-1", "object": "model", "created": 1756900000, "owned_by": "openai",
      "architecture": { "input_modalities": ["text"], "output_modalities": ["image"] } },
    { "id": "typesafe/jev-1.13", "object": "model", "created": 1756900000, "owned_by": "typesafe",
      "architecture": { "input_modalities": ["text"], "output_modalities": ["decisions"] } }
  ]
}
FieldTypeMeaning
idstringThe exact string for the model field of your request.
object"model"Constant.
createdintegerUnix seconds. See the note under Anthropic shape.
owned_bystringThe provider id of the first deployment routing would try for this model. routerplus for a dedicated endpoint.
context_lengthintegerChat models only. The largest context window, in tokens, among the routes of your key for this model. Absent when no route declares a window.
architecture.input_modalitiesarrayWhat a message to the model may carry: "text", plus each of "image", "file", "audio" and "video" that a route of this key takes. A chat request with a part that no route takes is a 400 (see Wire compatibility). Image and decision models take ["text"]. A route on your own provider key declares no inputs, so it adds none here. RouterPlus sends it every part as you sent it.
architecture.output_modalitiesarray["text"], ["image"], ["video"], ["decisions"], ["embeddings"], ["transcription"] or ["audio"]. A transcription model takes ["audio"] and a speech model takes ["text"].

OpenAI SDKs ignore context_length and architecture. Clients that size their context window or pick a route by modality read them.

What the list contains

  • A key bound to your own provider connection lists the models of that connection.
  • A key under a routing policy lists the models of the policy.
  • Your organization's active dedicated endpoints (<your-namespace>/<name>) are listed with owned_by routerplus, on the base URL they are served from.
  • Deployed endpoints from Optimize (tm/<name>-v<n>) are not listed.
  • The OpenAI shape lists the rp- name of each Claude model (rp-sonnet-5-5 for claude-sonnet-5-5) right after its model. That row has the same owned_by, context_length and architecture, and a canonical_slug that names the model. Model pickers that read this list, such as Cursor's, show these names. See Claude names for Cursor. The Anthropic shape does not list them.

Filtering

bash
curl -s "https://demo-api.routerplus.com/v1/models?output_modalities=image" \
  -H "Authorization: Bearer $TM_API_KEY"

output_modalities takes a comma-separated list of these values:

ValueModels for
textChat
imageImage generation
videoVideo generation
decisionsPOST /v1/decisions
embeddingsPOST /v1/embeddings
transcriptionPOST /v1/audio/transcriptions
audioPOST /v1/audio/speech
  • The list is a filter. ?output_modalities=text,image,video,decisions,embeddings,transcription,audio is the same as no filter.
  • A kind with no model in the catalog gives an empty list.
  • Any other value is a 400 invalid_request ("invalid output_modalities filter").
  • The Anthropic shape lists chat models only. The Anthropic Messages API has no route for image or decision models.

A provider query parameter takes the same JSON object as the request-level provider routing controls, for example {"only":["openai"]}. The response lists the models those controls let through. See Routing policies.

Anthropic shape

bash
curl -s https://dev2-api.routerplus.com/v1/models \
  -H "x-api-key: $TM_API_KEY" \
  -H "anthropic-version: 2023-06-01"
json
{
  "data": [
    { "type": "model", "id": "claude-haiku-4-5", "display_name": "claude-haiku-4-5", "created_at": "2026-09-03T12:00:00.000Z" }
  ],
  "has_more": false,
  "first_id": "claude-haiku-4-5",
  "last_id": "gpt-4o-mini"
}

has_more is always false. The full list arrives in one response, with no pagination.

Note

created and created_at are the time the gateway process loaded its catalog. They are not the release date of the model, so do not build logic on them. For prices and retention policy, use the public /api/models.json, documented in Models & catalog.

Retrieve one model

GET /v1/models/<id> returns the row that GET /v1/models gives your key for that id, in the same shape rules. An id with a slash, such as typesafe/jev-1.13, works as it is or URL-encoded.

bash
curl -s https://dev2-api.routerplus.com/v1/models/claude-haiku-4-5 \
  -H "Authorization: Bearer $TM_API_KEY"
json
{ "id": "claude-haiku-4-5", "object": "model", "created": 1756900000, "owned_by": "anthropic",
  "context_length": 200000,
  "architecture": { "input_modalities": ["text", "image", "file"], "output_modalities": ["text"] } }

With anthropic-version, the answer is one Anthropic row, for example {"type": "model", "id": "claude-haiku-4-5", "display_name": "claude-haiku-4-5", "created_at": "2026-09-03T12:00:00.000Z"}.

An id that the list does not give your key is a 404 model_unavailable, with the same body as in Unknown models. In the Anthropic shape, this includes every model that is not a chat model.

GET /v1/models/<id>/endpoints is a separate route. It lists each provider of one model with its price, data policy, status and measurements. See Provider routing.

SDK usage

python
import os
from openai import OpenAI

client = OpenAI(base_url="https://demo-api.routerplus.com/v1", api_key=os.environ["TM_API_KEY"])
for m in client.models.list():
    print(m.id, m.owned_by)
python
import os
import anthropic

# The SDK sends anthropic-version itself, so this gets the Anthropic shape.
client = anthropic.Anthropic(base_url="https://demo-api.routerplus.com", api_key=os.environ["TM_API_KEY"])
for m in client.models.list():
    print(m.id)
typescript
import OpenAI from "openai";

const client = new OpenAI({ baseURL: "https://demo-api.routerplus.com/v1", apiKey: process.env.TM_API_KEY });
for await (const m of client.models.list()) {
  console.log(m.id, m.owned_by);
}

Unknown models on completion calls

A completion request (/v1/chat/completions or /v1/messages) for an id that is not in this list fails with a 404. The error echoes the string you sent. RouterPlus contacts no provider and bills nothing. One exception: a dated pin of a listed model (claude-haiku-4-5-20251001, gpt-4o-2024-08-06, -latest) routes as its family. See Models & catalog.

OpenAI surface:

json
{
  "error": {
    "code": "model_unavailable",
    "message": "model \"gpt-5o\" is not in the catalog; GET /v1/models lists what this key can serve",
    "type": "invalid_request_error",
    "metadata": { "error_type": "model_unavailable" }
  },
  "request_id": "6f3c…"
}

Anthropic surface:

json
{
  "type": "error",
  "error": {
    "type": "not_found_error",
    "message": "model \"gpt-5o\" is not in the catalog; GET /v1/models lists what this key can serve",
    "error_type": "model_unavailable"
  },
  "request_id": "6f3c…"
}

Both carry the x-tm-error-code: model_unavailable header and x-request-id.

Warning

RouterPlus does no fuzzy matching and never falls back to a similar model. A typo in the model id is a 404. Every unknown id gets the same 404, so the error does not reveal which ids exist.

Errors

Statuserror_typeMeaning
404model_unavailableThe id is not in the catalog. Fix the id.
503gateway_errorThe id is in the catalog, but every deployment serving it is cooling down after failures. Comes with retry-after: 5 and x-tm-limit-kind: health. Retry the request.
400model_not_pricedBilled key, and the ledger has no price row for this model. RouterPlus does not serve a model it cannot meter.
400invalid_requestA listed image model sent to a chat route. The message names POST /v1/images/generations. A chat model sent to the images route gets the same 400, pointing at the chat routes. See POST /v1/images/generations.

Errors has the full list.

For agents: /docs/api-models.md and /llms.txt