Ada AI

Models & Routing

How Ada AI discovers models across your upstreams, picks one by priority, and fails over on 5xx — without ever silently substituting a model.

Model discovery

GET /v1/models returns the union of model IDs across the enabled upstreams belonging to your key's owner — you, or the one organization the key is scoped to. It never combines personal and org pools.

curl https://api.ada.ai/v1/models \
  -H "Authorization: Bearer sk-rc-..."
{
  "object": "list",
  "data": [
    { "id": "glm-4.7", "object": "model", "owned_by": "llm-proxy" },
    { "id": "glm-4.5", "object": "model", "owned_by": "llm-proxy" },
    { "id": "swiss-ai/Apertus-70B-Instruct-2509", "object": "model", "owned_by": "llm-proxy" },
    { "id": "Qwen/Qwen3.6-35B-A3B-FP8", "object": "model", "owned_by": "llm-proxy" },
    { "id": "moonshotai/Kimi-K2.7-Code", "object": "model", "owned_by": "llm-proxy" }
  ]
}

The owned_by field reflects the proxy, not the underlying provider, because a single model ID may be served by more than one of your upstreams.

Keeping the list fresh

Each upstream stores its own model list. After you add or change an upstream, click Sync models in the dashboard (or POST /me/upstreams/{id}/sync-models via the API) so the proxy can see which IDs are currently available. A model you request must be present on at least one enabled upstream.

How a request is routed

Given a request for model: "glm-4.7":

  1. The proxy looks up your key's owner (you, or one org).
  2. It finds every enabled upstream belonging to that owner whose synced model list contains glm-4.7.
  3. It tries them in descending priority — the upstream with the highest priority number first.
  4. If that upstream returns 5xx, the proxy fails over to the next matching upstream automatically.
  5. If every matching upstream fails, the request returns 502 (see Errors).
  6. If no upstream exposes the requested model, the request returns 400 — the proxy never silently substitutes a different model.
request: model = "glm-4.7"

  upstreams (owner = you)            synced models
  ┌──────────────────────┬───┐  ┌─────────────────────────┐
  │ Acme (priority 10)   │ ✔ │  │ glm-4.7, glm-4.5, ...   │  ← tried first
  ├──────────────────────┼───┤  ├─────────────────────────┤
  │ Backup (priority 1)  │ ✔ │  │ glm-4.7, gpt-4.1-mini   │  ← failover target
  └──────────────────────┴───┘  └─────────────────────────┘

Priority is per upstream, not per model

priority orders your upstreams. If Acme is 10 and Backup is 1, then for every model both of them serve, the proxy tries Acme first and only falls back to Backup on a 5xx. There is no per-model priority override.

Scope is fixed at mint time

A proxy key resolves against exactly one owner — personal, or one organization — chosen when the key is minted and fixed thereafter.

  • A personal key uses only your personal upstreams.
  • An org key uses only that org's upstreams — never your personal ones, and never a different org's.
  • There is no per-upstream scoping within an owner in v1. Mint separate keys to separate traffic; they share the same upstream pool.

See API keys and Organizations.

Adding an upstream

In the dashboard: UpstreamsAdd upstream. Pick a preset (which fills the base URL) or define a custom one. The fields:

FieldNotes
NameYour label.
Base URLProvider API root including the version segment (https://api.openai.com/v1). The proxy appends /chat/completions and /models.
API keyYour provider key. Encrypted at rest.
PriorityHigher is tried first. Use this for failover ordering.

After saving, Sync models populates the model IDs available on that upstream. The Models page shows the union across all your enabled upstreams.

Upstream API keys are encrypted in PostgreSQL with KEY_ENCRYPTION_KEY. Keep that key stable — losing it makes existing encrypted values unreadable.

On this page