Connect or replace the fallback AI provider
const url = 'https://beta-api.plune.ai/v1/settings/ai/fallback';const options = { method: 'PUT', headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'}, body: '{"provider":"openrouter","apiKey":"sk-example-not-a-real-key","model":"gpt-5","acceptedDisclaimer":true}'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request PUT \ --url https://beta-api.plune.ai/v1/settings/ai/fallback \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data '{ "provider": "openrouter", "apiKey": "sk-example-not-a-real-key", "model": "gpt-5", "acceptedDisclaimer": true }'#829 (ADR 0052): owner only. An optional second provider with its own key; the code goes to it only when the primary fails. The primary must be connected first (409). The fallback cannot be the same as the primary: the same provider, address and model (400). A custom address goes through the same guard as the primary’s (https, public address) before anything is saved. The key is write-only.
Authorizations
Section titled “Authorizations ”Request Body required
Section titled “Request Body required ”#829 (ADR 0052): PUT /v1/settings/ai/fallback - the same fields as AiSettingsConnect without language (the primary’s language governs). customAddress is required exactly when provider is custom.
object
ADR-0004 — the three ways to connect a provider on this feature; each later addition is its own task.
Same rules as AiSettingsConnect.customAddress.
Write-only - never returned by any read (AC-12).
Same rules as AiSettingsConnect.model.
The fallback’s own acknowledgement: the code goes to this provider only when the primary fails; the owner answers for its terms of data handling.
Examples
a second hosted provider
{ "provider": "openrouter", "apiKey": "sk-example-not-a-real-key", "model": "gpt-5", "acceptedDisclaimer": true}Responses
Section titled “ Responses ”Connected - the owner view, with the fallback slot
What an owner reads — AiSettingsStatus plus AC-05/AC-09/AC-15. Never includes the credentials themselves (AC-12).
object
Whether a provider has ever been connected (an ai_settings row exists).
Present exactly when configured is true.
Present exactly when configured is true.
#829: the fallback slot - provider and model only (AC-05). Present when one is set.
object
ADR-0004 — the three ways to connect a provider on this feature; each later addition is its own task.
#829: the owner’s view of the fallback slot; present when one is set.
object
ADR-0004 — the three ways to connect a provider on this feature; each later addition is its own task.
Present when provider is custom.
userId of the owner who last connected or replaced the fallback’s credentials.
The fallback’s own most recent provider issue, apart from the primary’s: a primary that fell back stays in the primary’s.
Present when provider is custom.
#1286: the owner’s monthly limit in USD; null = none. At 80% usage.cap.state is warning, at 100% new draft requests are refused.
Draft language, default en (AC-05) — a project setting, not the reader’s interface language.
Present exactly when configured is true (AC-05, AC-12 — “коли й ким”, never the value).
userId of the owner who last connected or replaced credentials.
AC-09 — the most recent provider issue, if any; null otherwise. Never aborted-shaped: a timeout is not a provider failure.
Present exactly when configured is true.
object
Calendar month, UTC.
object
#829: how many of the attempts above the fallback made, so an owner sees it really works (ADR 0052 §3).
object
Sum of costUsd over calls whose model had a known price at call time.
Count of calls whose tokens the provider reported but whose model has no price — “ціна невідома” — never folded into knownUsd as zero (SAD §8 rule 6). A call that reported no tokens (a timeout, a rejected key) has nothing to price and is counted in calls, not here.
#1286: the same two numbers split by who asked. agent is a model acting for a person (a bearer token with X-Plune-Session, an agent actor in the audit log); human is everyone else. The halves add up to the totals.
object
object
object
#1286: where the month stands against the owner’s limit (AiSettingsFull.monthlyCapUsd); absent when no limit is set. warning from 80% of it, spent at 100%. Only calls with a known price count.
object
GET, owner only (#896): the model the platform recommends for each provider it lists — none for custom, whose owner names the model. The connect form offers it first; always a model with a known price (AC-15).
object
GET, owner only (#898): the models the connect form lets the owner choose from for each provider the platform lists — the ones it has a price for, the recommended first, each with that price. None for custom. A model that is not listed is still allowed (model is free text): the list is a help, not a gate.
object
One model the connect form lists (#898): the id as a provider writes it and what the platform’s own price table charges for it, per million tokens (AC-15).
object
USD for a million input tokens.
USD for a million output tokens.
One model the connect form lists (#898): the id as a provider writes it and what the platform’s own price table charges for it, per million tokens (AC-15).
object
USD for a million input tokens.
USD for a million output tokens.
Example
{ "provider": "anthropic", "fallback": { "provider": "anthropic", "lastIssueKind": "key_rejected" }, "lastIssueKind": "key_rejected", "usage": { "cap": { "state": "ok" } }, "models": { "anthropic": [ { "id": "claude-sonnet-5-5", "inputUsdPerMillion": 2, "outputUsdPerMillion": 10 } ], "openrouter": [ { "id": "claude-sonnet-5-5", "inputUsdPerMillion": 2, "outputUsdPerMillion": 10 } ] }}Invalid body, a rejected address, or the same as the primary
object
Examples
{ "error": "validation failed — acceptedDisclaimer: must be true"}{ "error": "address rejected — must be an https address"}{ "error": "The fallback cannot be the same as the primary: the same provider, address and model"}No / invalid token or session
A member or a reader asked
object
Example
{ "error": "project owner only"}The primary is not connected yet - PUT /v1/settings/ai first
object
Example
{ "error": "AI is not connected yet — connect a provider first"}Rate-limited: the per-route throttle, or the per-minute request limit of the plan an API token counts by (#1442; the body names the plan, #2092). Retry-After carries the seconds until the window rolls over.
object
Example generated
{ "error": "example"}Headers
Section titled “Headers ”Seconds until the window rolls over
No server encryption key; nothing is saved
object
Example
{ "error": "AI platform not configured — contact your operator"}