Skip to content

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-Secret request 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):

{ "ok": true, "provider": "anthropic", "pool_depth": 5 }

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):

{ "provider": "anthropic", "pool_depth": 5 }

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:

{ "ok": true, "event": "session_expired" }

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):

{ "ok": true, "provider": "anthropic", "failover_active": false }

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.