A trust-first, multi-provider AI gateway. Speaks the OpenAI and Anthropic API dialects, pools multiple accounts per provider, and routes each request to the right upstream.
https://cerber.ihatebot.com · /v1 for OpenAI SDKs · /llm.md (agent guide) · /dashboard · /chatAuthorization: Bearer <KEY> or x-api-key: <KEY>.401.| Method & path | Dialect | What it does |
|---|---|---|
POST /v1/chat/completions | OpenAI | Chat for every provider incl. Claude. Supports streaming + fallback. |
POST /v1/messages | Anthropic | Native Anthropic Messages, transparent passthrough (streaming). |
POST /v1/messages/count_tokens | Anthropic | Token counting via pooled credentials. |
POST /v1/embeddings | OpenAI | Embeddings, passthrough to the provider serving the model. |
POST /v1/completions | OpenAI | Legacy text completions, passthrough. |
POST /v1/responses | OpenAI | Responses API, passthrough (streaming). |
POST /v1/images/generations | OpenAI | Image generation (e.g. grok-imagine-*, gpt-image-*). |
GET /v1/models | OpenAI | List discovered model ids per provider. |
GET /llm.md | — | Concise agent-facing usage guide (markdown). |
GET /docs | — | This reference. |
GET /healthz | — | Liveness probe. |
Embeddings/completions/responses are served only by OpenAI-compatible providers (OpenAI/Grok/ollama). A model that routes to Anthropic, or an unknown model, → 400; a provider lacking the capability → 501.
Point an OpenAI SDK at https://cerber.ihatebot.com/v1 or an Anthropic SDK at https://cerber.ihatebot.com. cerber translates OpenAI⇄Anthropic and OpenAI⇄Gemini under the hood, so you can call a Claude model through the OpenAI endpoint and get OpenAI-shaped responses, or use the native Anthropic endpoint for byte-faithful passthrough.
Just set model; cerber routes by name:
| Model prefix | Provider |
|---|---|
gpt*, o1*, o3*, o4*, chatgpt* | OpenAI |
gemini* | Gemini |
grok* | xAI (Grok) |
claude* | Anthropic |
(discovered local names) | ollama / vLLM |
Configured routing prefixes and discovered model names take precedence; an unmatched model → 400.
On /v1/chat/completions, if the model fails with a retryable error — provider 5xx, or every account rate-limited/unavailable — cerber retries the next model in a fallback chain before any bytes are sent. A 4xx client error is returned as-is, and a stream already in progress is never re-attempted.
Per-request override: header X-Cerber-Fallback: model2,model3 (each routed like any model, so it can cross providers).
No server-side chains configured on this instance; use the header.
A managed key may carry a rolling cost budget (USD, from configured model pricing) and rate limits (requests & tokens per window). On exhaustion you get:
| Status | Meaning |
|---|---|
402 | Cost budget exhausted for the window. |
429 | Request or token rate limit exceeded. |
Windows are rolling: minute / hour / day / week / month. Counters persist across restarts. Streamed responses currently count requests but not cost/tokens.
| Header | Effect |
|---|---|
Authorization: Bearer <KEY> | Client API key (or x-api-key). |
X-Cerber-Cred: oauth|key|<name> | Pin which pooled credential serves the request; omit to rotate. |
X-Cerber-Fallback: m2,m3 | Per-request fallback chain (OpenAI endpoint). |
X-Cerber-Management: <KEY> | Management key for /admin/* (if configured). |
anthropic-version, anthropic-beta | Passed through to Anthropic on the native endpoint. |
claude-haiku-4-5-20251001claude-opus-4-8claude-sonnet-5GLM-4.6-Derestricted-v5GLM-4.7Gemma-4-31B-Claude-4.6-Opus-Reasoning-DistilledGemma-4-31B-Cognitive-UnshackledGemma-4-31B-DarkIdolGemma-4-31B-FabledGemma-4-31B-GarnetGemma-4-31B-GarnetV2Gemma-4-31B-GembrainGemma-4-31B-Gembrain-uncensored-hereticGemma-4-31B-GemopusGemma-4-31B-K1-v5Gemma-4-31B-Larkspur-v0.5Gemma-4-31B-Mero-Artemis-v0.3.1Gemma-4-31B-MeroMeroGemma-4-31B-Musica-v1Gemma-4-31B-QueenGemma-4-31B-SDFT-Heretic-RPGemma-4-31B-Sphinsikus-ChronistGemma-4-31B-itMistral-Medium-3.5-128BQwen3.5-27B-AnkoQwen3.5-27B-BlueStar-DerestrictedQwen3.5-27B-BlueStar-Derestricted-LiteQwen3.5-27B-BlueStar-v2-DerestrictedQwen3.5-27B-BlueStar-v2-Derestricted-LiteQwen3.5-27B-BlueStar-v3-DerestrictedQwen3.5-27B-BlueStar-v3-Derestricted-LiteQwen3.5-27B-Claude-4.6-Opus-Reasoning-Distilled-DerestrictedQwen3.5-27B-Claude-4.6-Opus-Reasoning-Distilled-Derestricted-LiteQwen3.5-27B-Dark-Nexus-v3.0-DerestrictedQwen3.5-27B-Dark-Nexus-v3.0-Derestricted-LiteQwen3.5-27B-DerestrictedQwen3.5-27B-InfracelestialQwen3.5-27B-Marvin-DPO-V2-DerestrictedQwen3.5-27B-Marvin-DPO-V2-Derestricted-LiteQwen3.5-27B-Marvin-V2-DerestrictedQwen3.5-27B-Marvin-V2-Derestricted-LiteQwen3.5-27B-Musica-v1Qwen3.5-27B-NaNovel-DerestrictedQwen3.5-27B-NaNovel-Derestricted-LiteQwen3.5-27B-Omega-Evolution-v2.0-DerestrictedQwen3.5-27B-Omega-Evolution-v2.0-Derestricted-LiteQwen3.5-27B-Omega-Evolution-v2.2-DerestrictedQwen3.5-27B-Omega-Evolution-v2.2-Derestricted-LiteQwen3.5-27B-Omnimerge-v2-DerestrictedQwen3.5-27B-Omnimerge-v2-Derestricted-LiteQwen3.5-27B-Queen-DerestrictedQwen3.5-27B-Queen-Derestricted-LiteQwen3.5-27B-QuettaLLMs-Koreasoner-V3-DerestrictedQwen3.5-27B-QuettaLLMs-Koreasoner-V3-Derestricted-LiteQwen3.5-27B-RpRMax-v1Qwen3.5-27B-Vivid-DurianQwen3.5-27B-Writer-DerestrictedQwen3.5-27B-Writer-Derestricted-LiteQwen3.5-27B-Writer-V2-DerestrictedQwen3.5-27B-Writer-V2-Derestricted-LiteQwen3.5-27B-earica-DerestrictedQwen3.5-27B-earica-Derestricted-Liteantigravity-preview-05-2026deep-research-max-preview-04-2026deep-research-preview-04-2026deep-research-pro-preview-12-2025gemini-2.0-flashgemini-2.0-flash-001gemini-2.0-flash-litegemini-2.0-flash-lite-001gemini-2.5-computer-use-preview-10-2025gemini-2.5-flashgemini-2.5-flash-imagegemini-2.5-flash-litegemini-2.5-flash-preview-ttsgemini-2.5-progemini-2.5-pro-preview-ttsgemini-3-flash-previewgemini-3-pro-imagegemini-3-pro-image-previewgemini-3-pro-previewgemini-3.1-flash-imagegemini-3.1-flash-image-previewgemini-3.1-flash-litegemini-3.1-flash-lite-imagegemini-3.1-flash-lite-previewgemini-3.1-flash-tts-previewgemini-3.1-pro-previewgemini-3.1-pro-preview-customtoolsgemini-3.5-flashgemini-flash-latestgemini-flash-lite-latestgemini-omni-flash-previewgemini-pro-latestgemini-robotics-er-1.5-previewgemini-robotics-er-1.6-previewgemma-4-26b-a4b-itgemma-4-31b-itlyria-3-clip-previewlyria-3-pro-previewnano-banana-pro-previewgrok-4.20-0309-non-reasoninggrok-4.20-0309-reasoninggrok-4.20-multi-agent-0309grok-4.3grok-4.5grok-build-0.1grok-imagine-imagegrok-imagine-image-qualitygrok-imagine-videogrok-imagine-video-1.5Use this provider's standard model names (routed by the prefixes above).
Use this provider's standard model names (routed by the prefixes above).
⚠ No management key configured — /admin/* currently accepts any valid client key. Set access.management_key for multi-tenant deployments, otherwise a capped key could lift its own limits.
| Method & path | What it does |
|---|---|
GET /admin/stats | Usage snapshot (JSON): totals, per-credential, per-model, hourly series, total cost. |
GET /admin/requests | Recent per-request log (newest first): time, client, IP, User-Agent, provider, model, account, tokens, cost. Filters: ?model= ?provider= ?credential= ?client=; paginate with ?limit= & ?offset= (returns total). |
GET /admin/usage.csv | Usage export (CSV). |
GET /admin/accounts | Pooled credentials: state, health, usage. |
GET /admin/providers | Provider health + discovered models. |
POST /admin/accounts/{name}/enable|disable | Toggle a credential at runtime. |
GET /admin/keys | List managed client keys (redacted, with limits + window usage). |
GET /admin/keys/{name}/usage | Per-key cumulative usage: totals + cost + per-model breakdown (which models, tokens, money). |
POST /admin/keys | Mint a key; the secret is shown once. |
POST /admin/keys/{name}/enable|disable | Toggle a client key. |
DELETE /admin/keys/{name} | Delete a client key. |
POST /admin/keys/{name}/limits | Set budget/rate limits (access.Limits JSON; empty = unlimited). |
GET /metrics — Prometheus metrics (counts + credential names, no secrets).GET /dashboard — usage, accounts, total cost, per-hour chart, recent-requests table, key management.GET /admin/requests — recent per-request log (who/IP/UA/model/tokens/cost), in-memory ring (not persisted, holds IPs).GET /admin/stats & /admin/usage.csv — JSON/CSV snapshots; total_cost is the cumulative $ of all priced tokens through cerber.curl https://cerber.ihatebot.com/v1/chat/completions \
-H 'Authorization: Bearer $KEY' -H 'Content-Type: application/json' \
-d '{"model":"claude-sonnet-5","messages":[{"role":"user","content":"hi"}]}'curl https://cerber.ihatebot.com/v1/chat/completions \
-H 'Authorization: Bearer $KEY' -H 'X-Cerber-Fallback: gpt-4o,gemini-2.0-flash' \
-d '{"model":"claude-sonnet-5","messages":[{"role":"user","content":"hi"}]}'curl https://cerber.ihatebot.com/v1/messages \
-H 'Authorization: Bearer $KEY' -H 'anthropic-version: 2023-06-01' -H 'Content-Type: application/json' \
-d '{"model":"claude-sonnet-5","max_tokens":256,"messages":[{"role":"user","content":"hi"}]}'from openai import OpenAI
client = OpenAI(base_url="https://cerber.ihatebot.com/v1", api_key="$KEY")
client.chat.completions.create(model="claude-sonnet-5",
messages=[{"role":"user","content":"hi"}])cerber · github.com/tggo/cerber