Provider key pool API
Self-serve tenants share a single pooled provider credential. If that key is blocked or revoked (for example after a policy enforcement action against one end-user), Myra AI Workspace automatically rotates to a pre-provisioned standby key so self-serve traffic keeps flowing, and alerts operators. This API is how those standby keys are added to the pool.
Standby keys cannot be created programmatically at the provider — they are created once in the provider's console and then submitted here. A human, or the unattended console-automation bot, submits each key through this endpoint.
Authentication
The key-pool endpoints below accept either of two credentials:
- a platform-admin session (the normal operator path); or
- a shared bot secret — the unattended console-automation bot sends the
X-AIG-KeyPool-Bot-Secretrequest header, matched constant-time against a shared secret configured by your operator. When that secret is not configured the header path can never authenticate (fail closed), so the endpoints reduce to platform-admin-only.
A request that presents neither is rejected with 401/403.
Adding a standby key
POST /admin/v1/system/anthropic-key-pool
Auth: platform-admin session or the bot secret (see above).
The endpoint performs a live validation call with the submitted key before storing it. A key that does not validate is rejected and never stored, so the pool only ever holds usable keys. The key is stored encrypted at rest.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
key |
string | yes | The raw provider inference key to add as a standby. |
provider |
string | no | Defaults to anthropic. Only anthropic is accepted in this version. |
key_id |
string | no | The provider-side key identifier, used later to deactivate the key when it is rotated out. |
Accepted input and what is rejected
The request body is validated at the trust boundary (fail closed):
| Condition | Result |
|---|---|
key missing, empty, or not a string |
400 — nothing stored, no validation call made |
key longer than 512 characters |
400 — nothing stored |
key_id present but not a string |
400 — nothing stored |
provider not anthropic |
400 — nothing stored |
key fails the live validation call |
400 — nothing stored |
| caller has neither a platform-admin session nor a valid bot secret | 401/403 — nothing stored, no validation call made |
Response
On success (200):
pool_depth is the number of standby keys now available for rotation.
Reading the pool depth
GET /admin/v1/system/anthropic-key-pool
Auth: platform-admin session or the bot secret.
Returns the current number of standby keys. The unattended bot calls this first so it can top the pool up to a target and cheaply do nothing when it is already full. No secret is ever returned — only the count.
| Query param | Type | Required | Description |
|---|---|---|---|
provider |
string | no | Defaults to anthropic. Only anthropic is accepted; anything else is 400. |
On success (200):
Key-pool bot alerts
POST /admin/v1/system/key-pool-bot-alert
Auth: platform-admin session or the bot secret.
The unattended console-automation bot calls this to page a human through the
platform notifier when it hits a state only a human can resolve — an expired
console session or a changed console UI (the irreducible re-bootstrap step). The
caller sends only a fixed event; the server composes all human-facing alert
text, so a caller can never inject arbitrary alert content.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
event |
string | yes | One of session_expired, ui_changed, run_failed. |
detail |
string | no | Short, non-secret context appended to the server body. Max 256 characters. |
Accepted input and what is rejected
| Condition | Result |
|---|---|
| body missing | 400 — no alert fired |
event missing or not a string |
400 — no alert fired |
event not in the allowlist |
400 — no alert fired |
detail present but not a string, or longer than 256 characters |
400 — no alert fired |
| caller has neither a platform-admin session nor a valid bot secret | 401/403 — no alert fired |
On success (200) the alert is fanned out through the platform notifier and the
endpoint returns:
What happens on rotation
When a blocked-key event is detected on the self-serve shared credential, the gateway activates the next standby key, deactivates the blocked key at the provider, and decrements the pool. Operators are alerted on every rotation, when the pool runs low, and — critically — when the pool is exhausted or the whole provider organisation appears suspended, in which case self-serve traffic fails over to a cross-vendor fallback model until an operator restores the primary.
How self-serve requests read the pooled key
Self-serve tenants never hold their own per-gateway provider secret. On every self-serve request whose model resolves to the pooled provider, the gateway reads the active pooled key — the same credential rotation writes and hot-swaps — rather than a per-gateway secret. This read is a pure configuration lookup on the request path; it never retries or alters the response. Rotation writing a new key is picked up automatically within the key-cache window, with no request-path code change. A caller-supplied key-alias header is ignored on this pooled path, so a self-serve user cannot point the read at a different key.
Cross-vendor failover routing
While the pool is exhausted or the organisation is suspended, the failover flag
is set and self-serve traffic for the affected tier is routed to that tier's
required, named cross-vendor fallback model — the plan's fallback in plan-config — (a same-capability model from a
different vendor, already in the catalog). The requested model is validated
against the tenant's plan first; the fallback substitution is a platform decision
and is not re-checked against the plan allowlist. If a tier has no fallback
configured while failover is engaged, the request fails closed with a
configuration error rather than being routed to the dead primary.
Switching back to the primary is deliberately manual — a human confirms the provider organisation is actually restored (not merely responding again) and the standby pool is topped up. Topping up the pool does not by itself clear the failover flag.
Clearing failover (manual revert)
POST /admin/v1/system/anthropic-failover
Required role: platform admin.
| Field | Type | Required | Description |
|---|---|---|---|
active |
boolean | yes | Must be the literal false. Only clearing is exposed. |
provider |
string | no | Defaults to anthropic. Only anthropic is accepted. |
The request body is validated at the trust boundary (fail closed):
| Condition | Result |
|---|---|
| body missing | 400 — nothing changed |
active absent, not a boolean, or true |
400 — the flag is never set by hand (that is the engine's job) |
provider not anthropic |
400 — nothing changed |
| caller is not a platform admin | 401/403 — nothing changed |
| the underlying write fails | 500 |
On success (200):
Configuration
Self-serve pooled-key routing is wired by your operator as part of the deployment: which internal gateway holds the pooled key, the key alias that rotation writes and the request path reads (default self-serve), and the shared secret the unattended console-automation bot presents (in the X-AIG-KeyPool-Bot-Secret header) to authenticate the key-pool endpoints. Until the pooled gateway is configured, self-serve pooled routing stays inert; without the bot secret the bot path is disabled and the endpoints become platform-admin-only. The failover flag is cached on the request path for a short window (about 15 seconds by default); setting or manually clearing it takes effect immediately regardless.