Skip to main content

Bring Your Own Keys (BYOK)

An org can bring its own upstream provider keys. When a model routes through the org credential, the gateway authenticates against the provider with the org's key instead of the platform credential. Clients keep using the same gateway key (yb_…) — no client change is needed.

Who can add keys​

An org admin, in the admin console: Settings → Provider keys. Every key belongs to the org that added it and is used only for that org's traffic.

Supported providers​

ProviderRegistry typebase_urlNote
OpenAIopenaihttps://api.openai.com/v1
Anthropicanthropichttps://api.anthropic.comMessages API
Z.AI (Coding Plan)zai-codinghttps://api.z.ai/api/coding/paas/v4Endpoint is pinned by the adapter; enable YABANIN_ZAI_CODING_ENABLED (see providers)
vLLMopenai-compathttp://<host>:8000/v1OpenAI-compatible server
Ollamaopenai-compathttp://<host>:11434/v1Ollama's OpenAI-compatible endpoint
Customopenai-compatany HTTPS OpenAI-compatible base_urlllama.cpp, LM Studio, gateways, …

Adding a key​

  1. Sign in to the admin console as an org admin.
  2. Go to Settings → Provider keys and click Add key.
  3. Fill in Name (e.g. prod-openai), Provider, Base URL, and the provider API key.
  4. Save. The console immediately shows only a last-4 mask; the plaintext is never displayed again.
  5. Optional: Test connection fires a guarded probe from the console to the registered base URL (rate-limited per org; the server keeps no test history).
  6. Route a request to a model of that provider — the gateway now authenticates upstream with the org key.

Ollama example​

base_url http://127.0.0.1:11434/v1, provider openai-compat. If the gateway runs in a container (quickstart compose), point at the host loopback as http://host.docker.internal:11434/v1 instead.

Credential resolution​

When a request needs an upstream credential, the gateway resolves in order:

OrderTierUsed when
1Org key (BYOK)The requesting org has an enabled key in Settings → Provider keys matching the provider and upstream base URL (the exact URL or its /v1-stripped form); newest match wins.
2Per-modelNo org key matched: the credential pinned on the model registry entry.
3GlobalNeither of the above: the platform-wide credential configured on the gateway.

Routing, budgets, lineage, and audit are identical in all three tiers; only the upstream authentication differs.

What is stored, what is visible​

  • Stored: the encrypted ciphertext (api_key_ct) and the last-4 mask — nothing else. No plaintext copy exists at rest.
  • Visible in the console and admin API: name, provider, base_url, last-4 mask. Never the key.
  • The plaintext is used in memory at request time only. It is never logged and never returned by the API after creation.
  • Org isolation (RLS): key rows are scoped to their org under row-level security. Another org cannot see or resolve them.

Troubleshooting​

  • http base_url rejected. Remote providers must use https://. Plain http:// is accepted only for loopback hosts (127.0.0.1, localhost) so local Ollama and vLLM work. On-prem deployments that register plain-http literal private-IP endpoints (vLLM, TGI) can set YABANIN_ORG_CRED_ALLOW_HTTP_PRIVATE=1 on the admin server; hostname targets stay https-only in every mode, and reserved ranges (loopback, link-local/metadata) stay forbidden at dial time. Put TLS in front of anything remote — see the DNS & TLS runbook.
  • Key does not resolve. Walk the resolution order: (1) does the org have an enabled, matching key in Settings → Provider keys — provider matches, and the base URL equals the model's upstream URL (or its /v1-stripped form)? (2) does a per-model credential on the model registry entry shadow it? (3) does the global credential exist? Fix the first tier that is wrong.
  • Another org cannot see the key. By design — RLS scopes every key row to its org. Confirm you are signed in to the org that owns the key.

Verify on the stand​

  1. make quickstart-up && make quickstart-seed — stand up; store the printed admin password and API key.
  2. Open http://127.0.0.1:8086 and sign in as admin@localhost.
  3. Settings → Provider keys → Add key: name local-ollama, provider openai-compat, base_url http://host.docker.internal:11434/v1, key ollama. The saved row shows name, base_url, and a last-4 mask — not the key.
  4. Chat through the gateway with the seeded key: curl -sS -H "Authorization: Bearer yb_…" -H "Content-Type: application/json" -d '{"model":"<ollama-backed registry model>","messages":[{"role":"user","content":"ping"}]}' http://127.0.0.1:8082/v1/chat/completions → 200, and Ollama logs the request (proof the org key authenticated upstream).
  5. Negative: try adding a key with base_url http://10.0.0.1:8000/v1 → rejected by default (plain http beyond loopback; unless the deployment sets YABANIN_ORG_CRED_ALLOW_HTTP_PRIVATE=1).
  6. Negative: sign in as a second org → Provider keys is empty (RLS).
  7. Delete the org key and repeat step 4: the request still resolves (via per-model / global tier), confirming step 4 used the org key.

Limits​

  • BYOK changes upstream authentication only. Gateway client keys (yb_…), budgets, policies, and audit are unchanged.
  • Key material cannot be exported, re-downloaded, or moved between orgs.
  • Last-4 is a display mask only — it is not proof of key validity.