Authentication & keys
Every gateway request (except GET /health) authenticates with a Relay API key using the ApiKey scheme.
Authorization: Bearer app_live_xxxxxxxxxxxxxxxxxxxxxxxx
#Issuing keys
Create keys in the control panel under API Keys. The full key is shown once at creation — copy it then. Keys belong to the workspace you have selected, which is how usage, budgets and cost attribution are grouped; it is stamped server-side and never typed in.
Manage keys via the control-plane API too: POST /api/ApiKeys/search, POST /api/ApiKeys, PUT /api/ApiKeys/{id}, POST /api/ApiKeys/{id}/revoke, DELETE /api/ApiKeys/{id}.
#What a key controls
Everything below is settable at creation and editable afterwards:
| Setting | Effect | Empty / unset means |
|---|---|---|
| Name | Identifies the key in the panel and in cost attribution. | — (required) |
| Scopes | Capabilities the key may exercise: chat.completions, embeddings, models.read, workflows.run. | Every scope allowed. |
| Model allow-list | Models the key may call. A request for anything else returns 403 model_not_allowed. | Any enabled model. |
| Rate limit | Requests per minute for this key. | No per-key limit. |
| Expiry | The key stops working after this date (end of day). | Never expires. |
An empty scope list or allow-list means unrestricted, not nothing — so adding a new scope to the gateway never retroactively locks out existing keys.
#Editing a key
A key's details can be changed at any time; the secret cannot. Editing changes the name, scopes, allow-list, rate limit and expiry, and leaves the key its holder is using working exactly as before.
There is deliberately no way to rotate a key in place. Repointing an existing key at a new secret would either break every caller silently or, worse, leave two secrets believed to be one. Rotation is revoke + issue a new key, which leaves an audit trail that an edit would not.
Nor is the key retrievable. Only a SHA-256 hash is stored, so after creation the panel can show the identifiable prefix (app_live_xxxxxxxx…) and nothing more — not because it is being withheld, but because the rest was never kept.
#Budgets
A workspace has one spend ceiling, optionally divided into per-member allocations. When workspace spend reaches a hard-stop cap, the router rejects further requests with 402 before anything is sent upstream. Spend is recomputed periodically from telemetry (Gateway:BudgetRefreshMinutes), so the stop engages within that window rather than instantly. See Budgets & spend limits.
#Control-panel authentication
The control panel is a separate app that authenticates admins with Microsoft Entra (cookie auth) — not API keys. The api/* control-plane endpoints require a signed-in admin session; the public /v1/* API requires an API key. Keep the two mental models separate:
Gateway API (/v1/*) | Control panel (api/*) | |
|---|---|---|
| Who | Applications | Admins / team owners |
| Auth | API key (Bearer) | Entra sign-in (cookie) |
#Good practice
- One key per app or environment, so you can revoke narrowly.
- Set a model allow-list on keys that only need a specific model.
- Put every app's key behind the team that should own its cost.