ShvIA

Docs · OpenAI-compatible API

Models

A model id names a model and where it runs. This page explains the ids, the lists that return them, and how to tell which models you can actually call.

Model ids#

The canonical id is <model>@<server>:

These ids are examples.

IdMeaning
claude-sonnet-4-6@anthropicthe model claude-sonnet-4-6, served by the provider anthropic
gpt-4o@openaithe model gpt-4o, served by the provider openai
anthropic/claude-opus-4.8@kiloa model name that contains / and ., served by the gateway kilo
qwen3:8b@my-servera model served from the operator's own hardware; the suffix is the name the operator gave the server

The model part may contain : and /. The suffix after the last @ is the server. Treat the whole id as an opaque string: copy it from a list, do not build it.

The older form model#server is still accepted on input and is never returned.

Use the full id#

If you send a name without @server, the gateway looks for a model of that name on the best available server. If it finds none, it does not return an error. It answers with another model instead: the first one that the default server lists for you.

bash
curl -s "$SHVIA_URL/v1/chat/completions" \
  -H "Authorization: Bearer $SHVIA_API_KEY" -H "Content-Type: application/json" \
  -d '{ "model": "a-model-that-does-not-exist", "messages": [{ "role": "user", "content": "hi" }] }'

The response has status 200, and its model field is the model the gateway resolved for the request, not the name you sent. On the native endpoints this applies to profile_name; the separate model and server fields are strict, and an unknown pair is answered with an error. A name with an explicit server that does not carry the model returns 404 with the code model_not_found.

When the model you ask for cannot answer#

On /v1/messages, /v1/responses, /v1/chat/completions (for models whose driver is not ollama) and POST /api/v1/agent/chat, the gateway builds a short chain: the model you asked for, then your account's default model. If the first cannot answer, for example because it is a cloud model and you have not added a key for its provider, or because its provider fails with something another model can fix (see combos for the list) before it sends any text, the default model answers instead. A model on the operator's own servers is only backed up by another model on those servers. On /v1 the call succeeds with 200, and the model field and the X-Inference-Model header still show the model you asked for: the response does not say that another model answered. agent/chat names the model that answered.

If it matters which model answers, hold the key for the cloud models you rely on (see providers and your own keys), and check that the models you call are the ones you asked for before you trust a result.

GET/v1/models#

The OpenAI-compatible list. It needs your API key and takes no parameters.

json
{
  "object": "list",
  "data": [
    { "id": "claude-sonnet-4-6@anthropic", "object": "model", "created": 1767225600, "owned_by": "shvia" }
  ]
}

owned_by is always shvia. There is no pagination, no per-model metadata, and no route to read one model by its id (/v1/models/{id}), so client.models.retrieve(...) in the OpenAI SDKs returns 404.

This list is what the gateway exposes. It is not a list of models you are allowed to use:

  • it includes cloud models even when you have not added a key for that provider;
  • it does not filter by your group's allowed models or by your quota.

Calling a listed model you cannot use does not always fail in the way you would expect: it is refused with 403 and the code permission_denied when your group or quota forbids it, and a cloud model with no provider key behind it can be answered by your default model instead, as described above.

GET/api/v1/profiles#

The native list, and the better one for "which models do I hold credentials for". It needs your API key and returns one entry per model that is visible to you. Cloud models appear only when you hold a credential for the provider.

json
{
  "profiles": [
    {
      "name": "claude-sonnet-4-6@anthropic",
      "label": "claude-sonnet-4-6",
      "model": "claude-sonnet-4-6",
      "server": "anthropic",
      "driver": "anthropic",
      "data_locality": "cloud_us",
      "efforts": ["low", "medium", "high"],
      "price_tier": "$$",
      "price": { "in": 3.0, "out": 15.0 },
      "parameter_size": null,
      "quantization": null,
      "is_default": false
    }
  ]
}

The fields worth relying on:

FieldMeaning
namethe model id to send. On the native endpoints it goes in profile_name
modelthe model name without the server
driverhow the gateway talks to the model: ollama, openai, anthropic and others. It decides which request parameters apply, see chat completions. To tell the operator's hardware from a cloud provider, use data_locality
data_localitywhere the prompt goes: on_prem stays on the operator's infrastructure; cloud_us, cloud_eu, cloud_br and cloud_cn leave it. See your data
effortsthe reasoning-effort levels the gateway advertises for the model, including discovered provider metadata when available. An empty list means no adjustable levels are advertised here; it does not by itself prove the provider rejects every explicit effort value
priceUSD per million tokens, in and out. It is null when there is no price
parameter_size, quantizationfor self-hosted models, when known

Effort handling depends on the driver. For Anthropic, a value outside the driver's effort enum is ignored. With a configured nonempty model whitelist, an unlisted valid level maps to the nearest allowed level below it, or the lowest allowed level above it if none is lower. Without such a whitelist, the driver passes a valid requested level through. Do not treat this advertised list as a universal request-validation rule for every provider.

The response also carries other fields that serve the apps (favorites, a server map, deprecated flags). Do not depend on them. The response carries Deprecation and Sunset headers that refer to some of those deprecated fields.

POST/api/v1/profiles/refresh#

Drops your cached list of cloud models and returns the same body as GET /api/v1/profiles. Call it after you add a provider key.

Which list to use#

You wantUse
a list for an OpenAI-compatible tool or SDKGET /v1/models
the models you hold credentials for, with price and localityGET /api/v1/profiles
to know whether a model accepts reasoning effortefforts in GET /api/v1/profiles