Theme
Language

Transparent routing and flight breakdown

The transparent GetVibe router: explicit route via :alias or auto-route by key strategy. Public aliases, failover, reveal/debug headers x-getvibe-route and route/address_as fields in history.

GetVibe is a transparent router: you either explicitly pick a public variant via the :alias suffix, or leave the model name without a suffix — then the gateway picks the route according to your account/key strategy and, on failures, switches to another available variant. Only public route identifiers are used in responses and history.

Two modes: pin or auto

ParameterTypeDescription
Explicit pinmodel:alias or model:NThe request always goes through the chosen variant. Cross-variant failover is off: on 429/5xx the error is returned as-is (a retry on the same variant is allowed).
Auto (bare model)model name onlyThe gateway picks the variant per account or key settings. On 429/5xx and empty 200 it tries other variants of the same model, with cost and input constraints.
"model": "claude-opus-4.8"          // auto — key strategy
"model": "claude-opus-4.8:yellow"   // pin — :yellow only, no switching to other channels
"model": "claude-opus-4.8:2"        // pin — catalog variant #2 (legacy :N syntax)

Price bounds: max_price and min_price

Each model is served by several channels at different prices — a ladder. These two request-body parameters say which rungs of that ladder may serve you. Both are USD per 1M tokens, the same unit and the same numbers the Models page prints. They are compared against our price — what you are charged — never against a wholesale number you cannot see.

ParameterTypeDescription
max_pricenumber or objectCeiling. A number bounds BOTH legs; an object bounds them separately: {"input": 0.5, "output": 2}. An omitted leg is unbounded. Inclusive: a bound equal to a published price admits that channel.
min_pricenumber or objectFloor, same shape. Refuses channels priced BELOW it — for callers who would rather not be served by the deepest discount on the book. It can only make a request cost more, never less.
{
  "model": "deepseek-v4-flash-0731",
  "messages": [{"role": "user", "content": "hi"}],
  "max_price": 0.02,
  "min_price": {"input": 0.001}
}

Both legs must fit, input and output — never an average of the two. A channel that is cheap on input and expensive on output does not satisfy a single-number bound.

A standing ceiling, set once in the cabinet

A ceiling does not have to be repeated on every call. The dashboard stores one per API key and per model, plus a default that covers every model you have not set explicitly, and the API reads it on every request. A request that carries max_price uses that value instead for that one call; a request that carries none uses your stored ceiling. Precedence, most specific first:

ParameterTypeDescription
max_price in the requestper callReplaces the stored ceiling for this request only — wholly, not merged leg by leg.
key + modelstoredThis API key’s ceiling for this model.
account + modelstoredYour account ceiling for this model, used by keys that set none.
key / account defaultstoredThe catch-all ceiling for every model with none of its own.
The ceiling and the channel filter are two different controls and they compose. Channel order and exclusions decide which channels may serve you; the ceiling decides which price rung inside them may fill the request. Set either, both or neither. A channel filter alone cannot bound your price: one channel can offer the same model at many prices at once, so excluding channels never caps what the cheapest one ends up charging.

Where to read the prices you are bounding

GET /api/catalog publishes a channels array for every model: one entry per channel a request can land on, cheapest first, each with the address you can pin it by, its inputUsd / outputUsd price per 1M tokens and whether it is the default. Those are the exact numbers max_price and min_price are compared against, and the exact numbers you are billed at — one list, not three.

curl -s https://getvibeapi.com/api/catalog   | jq '.[] | select(.apiModel=="z-ai/glm-5.3") | .channels'

What you are billed

You are billed for the channel that actually served the request, plus our fixed markup — not for the ceiling you set, and never more than it. If you cap at a price and the request fills on a cheaper rung, you pay the cheaper one. The ladder on the model page shows a range, and the “from” figure is the cheapest rung that exists — it is a real price you could be charged, not a promise that this request will land there. Set max_price when you need a guaranteed upper bound.

When nothing fits

The request is refused: HTTP 422 with "type": "price_bound_no_lane", quoting the cheapest and dearest channel prices for that model and the full channels list, so you can pick a bound from the numbers instead of guessing at one. lowest_passing_usd_per_million is the smallest bound that admits a channel right now — one channel’s own pair, so sending it passes (the two cheapest legs may come from different channels). The same field appears when the exchange itself refused your bound: then it is the next price level that still has supply, and it is never lower than the bound you sent. When your bound was not the limit — our own purchase ceiling for the channel was, and the offers under it were busy or drained — the answer is instead HTTP 503 "type": "no_seller_available" with Retry-After and no suggested price: raising max_price would not help, retrying shortly might. The cheapest rung often holds a single offer that is busy, so for reliable fills set the bound at or above the model’s priceTypical, where most supply sits. We never quietly serve a dearer channel, and we never substitute another model. A malformed value — a string, a zero, a negative, an unknown field — is 400 invalid_request_error, never silently ignored.

{
  "error": {
    "message": "No channel of model "deepseek-v4-flash-0731" is priced within your max_price $0.0001 in / $0.0001 out...",
    "type": "price_bound_no_lane",
    "code": 422,
    "param": "max_price",
    "cheapest_usd_per_million": {"input": 0.0065, "output": 0.013},
    "dearest_usd_per_million": {"input": 0.0528, "output": 0.1584},
    "lowest_passing_usd_per_million": {"input": 0.0205, "output": 0.0613},
    "channels": [
      {"address": "deepseek/deepseek-v4-flash-0731:codebuddy-cn", "label": "codebuddy-cn", "inputUsd": 0.0205, "outputUsd": 0.0613, "isDefault": true},
      {"address": "deepseek/deepseek-v4-flash-0731:qwencloud", "label": "qwencloud", "inputUsd": 0.0378, "outputUsd": 0.1132, "isDefault": false}
    ]
  }
}
Price bounds apply to a bare model and to an explicit pin alike. On a pin that is itself outside the bound you get the same 422 naming the pin — the pin is never moved to another channel for you.

Pool names you can pin

Channels served from a vendor subscription pool are addressable by name. Write the name after a colon, exactly like any other alias:

"model": "gpt-6.1-sol:codex"         // pin a subscription pool
"model": "claude-opus-5.5:claude-code"  // pin the Claude Code pool
Addressable pools
ParameterTypeDescription
:codexpoolAddress this pool by name. Also accepted: :openai-codex.
:qwencloudpoolAddress this pool by name. Also accepted: :alibaba-qwencloud.
:zaipoolAddress this pool by name. Also accepted: :z-ai-glm-coding-plan.
:claude-codepoolAddress this pool by name.
:antigravitypoolAddress this pool by name.
:grokpoolAddress this pool by name.
:codebuddypoolAddress this pool by name.
:codebuddy-cnpoolAddress this pool by name.
:clinepasspoolAddress this pool by name.
:command-codepoolAddress this pool by name. Also accepted: :commandcode.
:opencodepoolAddress this pool by name. Also accepted: :opencode-go.
:mimopoolAddress this pool by name.
:kiro-poolpoolAddress this pool by name.
:meta-aipoolAddress this pool by name.
:minimax-cnpoolAddress this pool by name.
:qwencloud-alibaba-cnpoolAddress this pool by name.
:marketplacepoolAddress this pool by name. Also accepted: :bare-marketplace-alias.
:nouspoolAddress this pool by name.
These readable names are the only spellings this deployment advertises. An older short letter form still resolves during the migration window and is announced on every response (x-pv-deprecated-alias / x-pv-use-instead), but it is never shown here and new integrations should use the name. Each pool is one channel with its own price ladder; an older band spelling ending in a digit (:claude-code-2) still resolves to that pool.

Public aliases (:alias)

The suffix after the colon is a public route identifier, not an upstream name. The full list for a specific model is in the catalog (Models, the «In API» column). Main aliases:

ParameterTypeDescription
:yellowaliasA public variant offered for many models; its price is in the catalog.
:codex / :claude-code / …aliasSubscription pools, listed by name in “Pool names you can pin” above.
:pixel / :flowaliasMedia routes (images/video), not chat.
More about the variants of one model — in the section Models → Providers. If the suffix is unavailable for a model, the request returns 400.

Key settings

For auto requests (bare model) the following are set on each API key (dashboard → API keys):

ParameterTypeDescription
routingStrategystringpriority (default) — the order of providerPriority, otherwise the first variant in the catalog; price — the cheapest for us variant; latency — the fastest by recent measurements; default — rigidly the first eligible variant.
providerPrioritylistPriority of internal provider tags (human-readable names in the dashboard). Used with strategy=priority.
disabledProviderslistExclude providers from auto-routing. An explicit :alias is still callable if the variant exists.
cacheOnlybooleanOnly variants with prompt-cache support — good for a repeating prefix.
Settings apply only to requests without an explicit suffix. An empty key field means the default. See also allowedModels and limits in the table below.

Routing strategy

ParameterTypeDescription
priority (default)strategyThe usual default route.
pricestrategyPick the variant with the lowest price among those available for the model.
latencystrategyPick the fastest variant by recent measurements.
cacheOnlybooleanOnly cache-enabled variants — good for a repeating prompt prefix.
The strategy applies only to default requests. If you explicitly set a variant with a suffix (e.g. :yellow) it is always respected and routing does not override it. Configured per key in dashboard → API keys.

Explicit provider selection

Add a provider alias after a colon — it is respected regardless of the routing strategy. The full list of aliases and examples — in the section Models → Providers.

"model": "claude-opus-4.8"        // auto — key strategy
"model": "claude-opus-4.8:yellow"     // explicitly pin the :yellow channel
"model": "claude-opus-4.8:kiro-pool"  // explicitly pin the :kiro-pool channel

Key limits

For each API key you can set in the dashboard:

ParameterTypeDescription
allowedModelsmodel listWhitelist of models this key may call. Empty — all allowed. A request for a model outside the list gets 403.
routingStrategy / cacheOnlyoverrideThe strategy and cache filter for this key.
limitRubspend limitSpend limit for the key.
allowedIpsIP whitelistIP restriction (see the «Authentication» section).
This is handy for handing keys to teams and integrations: one key — only cheap models, another — with a spend limit, a third — with its own strategy. All configured in the dashboard.

Failover (auto only)

With a bare model the gateway may switch to another public variant of the same model if the current one returned 429, 5xx or an empty 200 with no content. Constraints:

  • Requests with images/PDF are not switched to another provider (vision compatibility).
  • Failover does not go to a significantly pricier variant (except strategy=price).
  • There is an upper bound on the number of attempts per client request.
  • With pin (:alias) cross-provider failover is off — you get the error of the chosen route.

Retrying with exponential backoff on 429 is described in Errors and limits.

Flight breakdown — which route served the request

For trusted reveal/debug clients, after the request completes (including auto) headers are available showing which public variant actually ran. Normal clients are not given this data.

Response headers for trusted reveal/debug clients (chat / messages / responses)

ParameterTypeDescription
x-getvibe-routestringThe public route alias: yellow, codex, claude-code, …
x-getvibe-modelstringThe model value for re-pinning: base or base:alias (e.g. gpt-6.1-sol:yellow). With an explicit pin it matches your choice.
x-pv-generation-idstringHistory record id (non-stream). See Balance and history.
curl -sD - https://getvibeapi.com/v1/chat/completions \
  -H "Authorization: Bearer $GETVIBE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model":"gpt-6.1-sol","messages":[{"role":"user","content":"ping"}],"max_tokens":8}' \
  -o /dev/null | grep -i getvibe

# x-getvibe-route: yellow
# x-getvibe-model: gpt-6.1-sol:yellow

Usage history

In GET /v1/generations, GET /v1/usage and the dashboard each record has the fields:

ParameterTypeDescription
modelstringThe base model name (no internal suffixes).
routestring | nullThe public :alias of the winning route.
address_asstringThe exact value for the model field when re-pinning (like addressAs in the catalog).
cost_detailobjectHow the charge was computed: token lines with their rate per 1M (lines), surcharges (adjustments) and the total. A marketplace channel bills the price tier (ladder rung) whose seller filled the request, so when that differs from the list rate, rateBasis is "tier", the lines are shown at that tier’s rate and add up to the charge, and tier names the rate. realisedRate {input, output} is the price per 1M the request was actually billed at — find it on the model’s price ladder (/api/model-ladder) to see which rung filled; minimumCharge is true (and realisedRate null) when the request was billed the per-request minimum instead. Send max_price to cap the rung.
In the response body of OpenAI-compatible endpoints upstream brands, internal suffixes in model and cost_usd remain hidden (except clients with a reveal exception). Flight breakdown is only in headers and history, without breaking SDKs.

Limitations

GetVibe does not provide a «raw» waterfall listing upstream providers in the request body. Control is via public :alias, key strategy and auto-failover within the model catalog. There is no separate «ignore providers» API or routing ZDR flags.

GetVibe routing — :alias, auto-route, failover, flight breakdown | GetVibe API