Save Provider
Override the provider of one kind for this workspace (e.g. a self-hosted OpenAI-compatible model: `{"provider": "openai_compatible", "base_url": "http://vllm:8000/v1", "model": "qwen3-32b"}`). The API key is stored encrypted and never returned; omit it to keep the stored one. Base URLs must be public unless the server allows private URLs. Changing the embedding provider re-embeds this workspace's knowledge base in the background.
API key access
admin scope with an API key (ro_pat_...). A signed-in session uses the caller's role./api/v1/settings/providers/{kind}Access token from /api/v1/auth/login, or an API key (ro_pat_..., RO-176) from /api/v1/workspaces/current/api-keys: the key implies its workspace and needs the route's scope. MCP connectors (/api/v1/mcp only) may use an OAuth access token (ro_oat_..., RO-284).
In: header
Path Parameters
A kind of provider a workspace can override.
"llm" | "embedding" | "search" | "stt" | "tts" | "voice_llm" | "dialer" | "enrichment" | "mail"Header Parameters
Id of the workspace to act on (must be a member).
1 <= length <= 32The API base, e.g. http://vllm.internal:8000/v1 (LiveKit: wss://...).
length <= 2048length <= 200Non-secret settings: model_fast, model_deep, structured_output (llm),
language, protocol (reachout, vosk, openai_realtime or vllm_realtime) and sample_rate (8000-48000 Hz) (stt;
the last two for streaming_ws), voice, language (tts), languages (stt and tts,
RO-250: a JSON map of per-language routes as a string, e.g.
{"hi": {"provider": "streaming_ws", "base_url": "ws://asr:9000/v1", "model": "..."}}),
sip_trunk_id, agent_name, from_number (dialer: the workspace's E.164 caller id).
Empty Object
Write-only.
length <= 4000Write-only (LiveKit).
length <= 4000RO-262 (stt, tts), write-only: a key per language route, {"te": "<key>"}, for a route
in options.languages that switches to another provider needing its own key (e.g. te
-> sarvam). Absent keeps the stored keys; null or "" removes one. A key is bound to
its route's provider: a route that changes provider or is removed loses it.
Empty Object
int640 <= value <= 1000000int640 <= value <= 1000000Response Body
curl -X PUT "http://localhost:8000/api/v1/settings/providers/llm" \ -H "X-Workspace-Id: string" \ -H "Content-Type: application/json" \ -d '{ "provider": "openai_compatible" }'{
"kind": "llm",
"label": "string",
"description": "string",
"source": "workspace",
"providers": [
{
"name": "openai_compatible",
"label": "string",
"base_url": "required",
"model": "required",
"api_key": "required",
"api_secret": true,
"default_base_url": "string",
"default_model": "string"
}
],
"option_names": [
"string"
],
"default": {
"provider": "string",
"model": "string"
},
"override": {}
}{
"detail": [
{
"loc": [
"string"
],
"msg": "string",
"type": "string",
"input": null,
"ctx": {}
}
]
}List Providers
Every provider kind (language model, embeddings, web search, speech to text, text to speech, voice agent model, telephony, enrichment): the providers it can use, the server's env default and this workspace's override. Resolution: workspace override, else the env default. Credentials are never returned (`credentials_configured`). Owners and admins.
Test Provider
One tiny call to the provider with a strict timeout (`PROVIDERS_TEST_TIMEOUT_SECONDS`, 10 s): a 1-token completion, a one-word embedding, a 1-result search, a model or voice list, a LiveKit room list, or (a `streaming_ws` speech-to-text server) a WebSocket handshake with the protocol's start and stop messages, expecting a JSON reply or a clean close (RO-256). Without a body the saved override is tested (and its last result recorded); with a body those values are tested (a missing `api_key` uses the stored one for the same provider). Answers 200 with `ok: false` when the provider fails.