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
| Parameter | Type | Description |
|---|---|---|
Explicit pin | model:alias or model:N | The 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 only | The 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.
| Parameter | Type | Description |
|---|---|---|
max_price | number or object | Ceiling. 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_price | number or object | Floor, 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:
| Parameter | Type | Description |
|---|---|---|
max_price in the request | per call | Replaces the stored ceiling for this request only — wholly, not merged leg by leg. |
key + model | stored | This API key’s ceiling for this model. |
account + model | stored | Your account ceiling for this model, used by keys that set none. |
key / account default | stored | The catch-all ceiling for every model with none of its own. |
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}
]
}
}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| Parameter | Type | Description |
|---|---|---|
:codex | pool | Address this pool by name. Also accepted: :openai-codex. |
:qwencloud | pool | Address this pool by name. Also accepted: :alibaba-qwencloud. |
:zai | pool | Address this pool by name. Also accepted: :z-ai-glm-coding-plan. |
:claude-code | pool | Address this pool by name. |
:antigravity | pool | Address this pool by name. |
:grok | pool | Address this pool by name. |
:codebuddy | pool | Address this pool by name. |
:codebuddy-cn | pool | Address this pool by name. |
:clinepass | pool | Address this pool by name. |
:command-code | pool | Address this pool by name. Also accepted: :commandcode. |
:opencode | pool | Address this pool by name. Also accepted: :opencode-go. |
:mimo | pool | Address this pool by name. |
:kiro-pool | pool | Address this pool by name. |
:meta-ai | pool | Address this pool by name. |
:minimax-cn | pool | Address this pool by name. |
:qwencloud-alibaba-cn | pool | Address this pool by name. |
:marketplace | pool | Address this pool by name. Also accepted: :bare-marketplace-alias. |
:nous | pool | Address this pool by name. |
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:
| Parameter | Type | Description |
|---|---|---|
:yellow | alias | A public variant offered for many models; its price is in the catalog. |
:codex / :claude-code / … | alias | Subscription pools, listed by name in “Pool names you can pin” above. |
:pixel / :flow | alias | Media routes (images/video), not chat. |
Key settings
For auto requests (bare model) the following are set on each API key (dashboard → API keys):
| Parameter | Type | Description |
|---|---|---|
routingStrategy | string | priority (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. |
providerPriority | list | Priority of internal provider tags (human-readable names in the dashboard). Used with strategy=priority. |
disabledProviders | list | Exclude providers from auto-routing. An explicit :alias is still callable if the variant exists. |
cacheOnly | boolean | Only variants with prompt-cache support — good for a repeating prefix. |
allowedModels and limits in the table below.Routing strategy
| Parameter | Type | Description |
|---|---|---|
priority (default) | strategy | The usual default route. |
price | strategy | Pick the variant with the lowest price among those available for the model. |
latency | strategy | Pick the fastest variant by recent measurements. |
cacheOnly | boolean | Only cache-enabled variants — good for a repeating prompt prefix. |
: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 channelKey limits
For each API key you can set in the dashboard:
| Parameter | Type | Description |
|---|---|---|
allowedModels | model list | Whitelist of models this key may call. Empty — all allowed. A request for a model outside the list gets 403. |
routingStrategy / cacheOnly | override | The strategy and cache filter for this key. |
limitRub | spend limit | Spend limit for the key. |
allowedIps | IP whitelist | IP restriction (see the «Authentication» section). |
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)
| Parameter | Type | Description |
|---|---|---|
x-getvibe-route | string | The public route alias: yellow, codex, claude-code, … |
x-getvibe-model | string | The 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-id | string | History 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:yellowUsage history
In GET /v1/generations, GET /v1/usage and the dashboard each record has the fields:
| Parameter | Type | Description |
|---|---|---|
model | string | The base model name (no internal suffixes). |
route | string | null | The public :alias of the winning route. |
address_as | string | The exact value for the model field when re-pinning (like addressAs in the catalog). |
cost_detail | object | How 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. |
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.