Gateway
Name a config once and send requests through it: which model answers, what to fall back to, how often to retry, whether to answer from cache, and how fast a key may go. Make one and try it under Gateway in the console.
Send requests through one
Name it in the x-klinn-gateway header, or make it a key's default under Gateway → Keys in the console. The header wins over a key's default. A model of default, or none, means the gateway's default model.
curl https://api.klinn.dev/v1/chat/completions \
-H "Authorization: Bearer $KLINN_API_KEY" \
-H "x-klinn-gateway: support-bot" \
-H "Content-Type: application/json" \
-d '{ "model": "default", "messages": [{ "role": "user", "content": "Hello" }] }'It works the same on chat, messages and decisions calls. Each gateway belongs to one account; another account's names do not resolve.
Make one under Gateway in the console, from code with the Management API (/api/v1/gateways, and PATCH /api/v1/keys/{id} for a key's default), or by asking an agent connected over MCP.
Two kinds
A chat gateway (kind: "chat", the default) routes the requests your code sends: they name their model, or default, and the rules below do the rest. A decision gateway (kind: "decision") is your own classifier: its default model is a decision model and it saves the questions, so a call to POST https://api.klinn.dev/v1/systemone sends only { "state": "…" } and gets the answers back; the same routing rules apply, guardrail rules do not. The config, the three-line call and the console's per-question answer counts are on Decisions.
What a gateway sets
Routing. Single: the request's model, or the one model you pin. Fallback: models tried in order; when one answers with a status code you list (by default 429, 500, 502, 503 and 504), the next one answers. Load balance: each request goes to one model, by weight. A streamed answer falls back only before its first token. Within each model we still choose and fall over between providers as usual.
Retries and timeouts. Up to 5 retries a model, after 1, 2 and 4 seconds, or when the model's Retry-After says. A timeout bounds how long an answer may take to start.
Overrides. Per model: max_tokens, temperature, top_p and seed replace what the request sent.
Response cache. The exact same request gets the kept answer, for free, for the time you set (up to 24 hours). Answers are kept in memory, per account, and a restart empties them. Send x-klinn-cache: refresh for a new answer.
Limits. Requests a minute per key, and the models allowed through it (ids, or patterns with *).
What comes back
Answers carry x-klinn-gateway, x-klinn-target (the model that answered) and, with a cache, x-klinn-cache (hit, miss or refresh). Each answer is billed at its model's price. A try that failed before an answer is not billed, and a cache hit is free. Logs show each request's gateway, the model that answered, its fallbacks and retries, and cache hits.
gateway_not_found. A model the gateway does not allow is a 403 model_not_allowed, never answered by another model. Past its rate limit, a 429 with Retry-After.