Skip to content
This page is a translation of the authoritative Chinese source and may lag behind.View the original

Access key and key group fields

GateLLM has two kinds of "users"; be sure to distinguish them:

  • Console user (ConsoleUser): the admin account that logs into the console, with the role admin or monitor (normal_user is not a console login role). UI operations are in Console user management.
  • Access key (AccessKey): the credential a caller presents when calling the API (the key inside Bearer <key>). This chapter covers its fields.

The two are fully independent: console users govern "who can enter the console", access keys govern "who can call the API".

Access keys and key groups (Access Keys)

Entry: Console → Access keys. This page has three tabs: Access Keys, Key groups, and Access rules (Header ACL, fields in Header ACL rule fields).

Relation

text
Console user ──created_by──→ access key ──group──→ key group ──┬→ models[]         (which models it can call)
                                                               ├→ load_balancers[] (which load balancers it can call)
                                                               └→ mcp_tool_acl     (which MCP tools it can call)
  • An access key belongs to one or more key groups (the groups field, multi-select in the form; with multiple groups, each dimension takes the union and cost quota takes the widest — see "Cost quota").
  • A key group's permissions split into three mutually independent dimensions — models, load balancers, MCP tools — each with its own "all" switch, none implying the others:
    • Model list decides which models are accessible: empty = no model access; ["*"] = all models; specific model names = only those listed (exact match on model name, not alias).
    • Load balancer list decides which load balancers are accessible: empty = no load balancer access; ["*"] = all load balancers; specific names = only those listed (exact match on load balancer name, not alias).
    • Checking "all models" does not grant load-balancer permission, and vice versa — the two dimensions are checked separately.
    • A load balancer is an authorization unit: once a load balancer is granted, the gateway no longer validates the members (entries) configured inside that load balancer one-by-one against the "model list" — keys in that group can reach every member of that load balancer, even if the "model list" is empty or doesn't include those models. Putting a sensitive or expensive model into a load balancer's members effectively opens it to all keys holding that load balancer's permission; to strictly limit a key to a single model, configure it as an ordinary model and add it to the "model list" instead of putting it inside an authorized load balancer.
  • A key with no group = no access to any model or load balancer.

Managing access keys

OperationHowDescription
Create"Access Keys" tab → NewFill name, generate or manually enter the API key, select groups, enable
View full key"Copy" button in the listCalls /access-keys/{name}/api-key to fetch the full value (the list only shows a mask)
RotateEdit → "Rotate" to the right of the API keyAfter confirming, a new value replaces the old, which becomes invalid immediately; the new key is shown only once in the success dialog — copy it immediately (other attributes unchanged)
RevokeEdit → uncheck "Enabled"Marked revoked, no longer effective, record retained
DeleteList → DeleteFully removed (prefer "Revoke" to preserve audit)

Access-key fields

FieldDescriptionDefault
NameKey identifier, for management and audit; read-only on edit(required)
API keyThe credential the client actually presents; the list shows a mask (first/last 4 chars, e.g. sk-a***xxxx)auto-generated by clicking "Generate"
GroupThe owning key group (multi-select, can belong to multiple groups; with multiple groups, model/LB/MCP permissions take the union), determines model/MCP permissionno group (= no access to any model)
TagsFree-form organization tags, multiple allowed; used for console filtering and search (the search box also matches tags), pure annotation with no permission effect. Select from historical tags or type a new oneempty
AnonymousWhen checked, this key is the anonymous fallback (see below), and the API key field is emptiedfalse
EnabledUnchecking revokes ittrue
Created byWhich console user created itthe currently logged-in console user
acl_default_actionallow / deny, the per-key fallback action when no rule matchesunset (falls back to the group, then to global Allow)
Model mapping (model_mappings)from → to rewrite rules specific to this key, can carry when request-header conditions for branching; higher priority than the owning key group's rules. Mapping targets must pass the egress gate (looked up in the corresponding list by real kind: ordinary models in models, load balancers in load_balancers), and source names must be in the corresponding list (the entry gate looks up real names by kind, and falls back to union for fictional names). See Configure identity model mappingempty (no mapping)
Monthly quota (monthly_quota)This key's monthly (UTC natural month) cost cap (USD amount). Empty = inherit lower level; a value must be > 0. See "Cost quota" belowempty (inherit lower level)
Daily quota (daily_quota)This key's daily (UTC natural day) cost cap (USD amount). Same semantics as monthly, judged independentlyempty (inherit lower level)

Access keys are viewed and managed by admin in the console (normal_user doesn't log into the console; it only holds/uses an API key). After a console user is deleted, the keys it created have created_by cleared and become legacy keys (visible only to admin).

Managing key groups

OperationHowDescription
Create"Key groups" tab → NewFill name, select models, select load balancers, configure MCP tool ACL
EditList → EditFour sub-tabs: Models / Load balancers / MCP / Model mappings
DeleteList → DeleteIf keys reference this group, change their group first

Key-group fields

FieldDescriptionDefault
NameGroup identifier(required)
ModelsThe accessible model list; displayed grouped by upstream, "All Models" = * select-all. Independent of the load-balancer dimensionempty (no permission)
Load balancersThe accessible load balancer list; "All Load Balancers" = * select-all. "All Models" does not include load balancers, which must be checked separately hereempty (no permission)
MCPallowed_tools / denied_tools / allowed_tags, controlling which MCP tools are callable (see MCP configuration)empty
acl_default_actionallow / deny, the per-group fallback action when no rule matchesunset (falls back to global Allow)
Model mapping (model_mappings)from → to rewrite rules shared by this key group (can carry when request-header conditions), applied to all keys in the group; lower priority than the key's own rules, higher than passthrough. Mapping targets must pass the egress gate (looked up in the corresponding list by real kind), and source names must be in the corresponding list (entry gate looks up real names by kind, falls back to union for fictional names). See Configure identity model mappingempty (no mapping)
Monthly quota (monthly_quota)The monthly (UTC natural month) cost cap (USD amount) each key in the group inherits. Not a shared ledger — it's a per-key cap for each key in the group. Empty = this group doesn't participate in folding (not treated as infinite); a value must be > 0empty (doesn't participate in folding)
Daily quota (daily_quota)The daily (UTC natural day) cost cap each key in the group inherits. Same semantics as monthly, judged independentlyempty (doesn't participate in folding)

Anonymous access keys

Set an access key's "Anonymous" = true (globally only one can exist):

  • When a client request carries no Authorization / x-api-key / x-goog-api-key header, it matches this anonymous key.
  • The anonymous key still needs a group to gain model access; otherwise it can "enter but call nothing".
  • Requests with an invalid key also fall to the anonymous branch (equivalent to no key).

Cost quota

The cost quota limits each access key's monetary consumption. Quotas are uniformly enforced in USD — a system-level single exchange-rate source FxCache (exposed via the /fx-rates API, with three-level fallback: operator config override > Frankfurter ECB online > static fallback table) converts each currency's spend into USD and accumulates. There are three config layers, all in the Console Access keys page and the Billing → Quota tab:

  • per-key: fill monthly / daily caps in the access key form's "Cost quota" area.
  • per-group: fill in the key group form — semantics are "the cap each key in the group inherits", not a shared ledger for the group.
  • global default: edit monthly_limit / daily_limit in the Billing → Quota tab, applying to keys that have no self-set limit.

Three-layer priority

Each period resolves the effective limit independently:

per-key || max(caps of member groups that set a limit, groups without a limit don't participate) || global default
  • Monthly and daily are two independent periods, each taking its own value and judging independently; hitting either rejects the key's subsequent requests (429).
  • Group-limit semantics = the per-key cap each key in the group inherits (not a shared ledger). A key in multiple groups where several groups set limits takes the widest (max) — e.g. team-a=$100, team-b=$500, a key in both groups → effective $500.
  • Member groups without a limit don't participate in folding (not treated as infinite) — otherwise a limited key could become infinite just by joining an unlimited group.
  • All member groups unset → falls back to the global default; global also unset → unlimited for that period.
  • All three layers unset → fully unlimited.

Value and period boundaries

  • Values: empty / null = inherit the lower level (key→group→global), not "this window is unlimited"; a value must be > 0 (0 and negatives are rejected on write, with frontend sync validation). To express "a window is unlimited", set a limit at a higher level and leave this level empty — or accept the trade-off that three layers can't express "one window unlimited while other windows limited".
  • Period boundaries: UTC natural month (resets on the 1st at 00:00 UTC) and UTC natural day (resets at 00:00 UTC each day). Consistent with statistics/billing.
  • The limit dimension is USD amount: record_cost looks up FxCache by pricing.currency, converts to USD micro-units, and accumulates inflight; refresh_once reads cost_breakdown (per-currency) and sums each multiplied by its exchange rate. The frontend billing page's ≈USD and quota enforcement share the same backend exchange-rate source. Excel export still shows per-currency columns (no cross-currency summing, unchanged).

429 and soft limits

  • Hitting any period returns 429, error type quota_exceeded, with the message indicating whether it's the monthly or daily window, the limit and used amount, and the reset time.
  • Only the daily window carries a Retry-After header (≤86400s); monthly can reach ~31 days, which is meaningless to clients and may be mis-handled, so the message already includes the reset time and no such header is sent.
  • Soft limits: usage = the TTL-cached DB period total spend (USD; refresh_once reads cost_breakdown per-currency and sums each multiplied by its rate) + the in-process inflight accumulation (USD, record_cost sync-converted), refreshed about every 30s (daily) / 5min (monthly); a minute-level overrun window is accepted. In multi-instance (PG mode), the DB snapshot is shared while inflight is per-instance local, so cross-instance overrun is also slight — all within the soft-limit semantics. ECB daily-frequency rates; models of the same currency convert at the day's rate all day; on a missing rate, fail-safe under-counts (skips accumulating that request, doesn't falsely reject).

Notes

  • Anonymous key: anonymous traffic is already merged into a single "anonymous" bucket in statistics, and all anonymous traffic shares one quota (the global default applies to anonymous).
  • Renaming a key: usage aggregates by name, so after renaming a key its old usage can't be associated with the new name (consistent with existing statistics semantics).
  • count_tokens exemption: not billed, not judged for quota.
  • Model try-me (tryme): doesn't enter the admission-check seam; consumption is recorded in the SystemDiagnostics fake bucket and never counts toward any real key's quota.
  • Unpriced models (no pricing): cost 0, doesn't consume quota (consistent with billing).

Relation to load balancers

The load balancer is an authorization dimension in the key group independent of models: the key group's load_balancers list must include the load balancer's name (or "*") for a key to call through the LB. The models dimension only governs ordinary models; "all models" does not additionally grant load balancers:

json
{
  "name": "full-access",
  "models": ["*"],
  "load_balancers": ["gpt-4o-ha"]
}

Console → Access keys → Key groups → Edit → the "Load balancers" sub-tab to check the corresponding LB. See Load-balancing fields.

FAQ

Q: The client gets 403 model_access_denied, but the key is right. The key's key group "Model" list doesn't include the requested model. Go to "Key groups", add that model, or change it to *. Calling a load balancer and getting 403 is the same — the load balancer is an independent dimension; check the group's "Load balancers" list ("All Models" does not additionally grant load balancers).

Q: How do I restrict a key to only a few models? Create a new key group whose model list only contains those, and point the key's group at it.

Q: The access-key list only shows sk-a***xxxx — how do I get the full value? Click that row's "Copy" button; it calls an API to fetch the full key and copy it to the clipboard. Anonymous keys don't support fetching the full value.

Q: Who can view/manage access keys in the console? Access keys are viewed and managed by admin in the console. normal_user doesn't log into the console — it only holds/uses an API key (the credential presented when calling the API).

Q: I want open, login-free access for internal services. Configure an anonymous access key (anonymous=true) and give it a permission-restricted key group. Note: anonymous means anyone who can reach the gateway can use it — only for trusted internal networks.

Q: How do an access key's acl_default_action and a key group's acl_default_action work? They are the fallback action when no Header ACL rule matches. See Header ACL rule fields.

Next: Header ACL rule fields for the full Header ACL rule field table; Configure Header ACL access rules for steps and common examples; Upstream and model fields for model configuration; Load-balancing fields for the LB–key-group relation; Configure identity model mapping for the steps and operational contract of rewriting model names by key / group.