Skip to main content

LLM Settings API

Manage the current user's Bring-Your-Own-Key (BYOK) LLM provider configuration. Keys are stored per-user (not per-site) and reused across every site the user can access. LENS AI uses these keys to call OpenAI, Anthropic, Gemini, or DeepSeek Cloud on the user's behalf.

Base path: /users/me/llm-settings

Required scope: read for listing, write for create/update/delete/test/set-default.

Keys are never returned

Stored API keys are never echoed back. Responses include api_key_configured (boolean) and api_key_last_4 (last 4 chars) only.


List Providers

GET /users/me/llm-settings/providers

No auth scope required beyond a valid session. Returns the BYOK-capable providers (anthropic, openai, deepseek_cloud, gemini) along with display metadata used by the settings UI.

Response:

{
"providers": [
{
"id": "anthropic",
"name": "Anthropic",
"default_model": "claude-sonnet-4-5",
"requires_api_key": true
}
],
"default_provider": "anthropic"
}

List My LLM Configs

GET /users/me/llm-settings

Required scope: read

Response:

{
"configs": [
{
"id": 12,
"provider": "anthropic",
"api_key_configured": true,
"api_key_last_4": "abcd",
"is_default": true,
"model": "claude-sonnet-4-5",
"base_url": null,
"created_at": "2025-01-05T10:00:00Z",
"updated_at": "2025-01-05T10:00:00Z"
}
]
}

Create or Update Config

POST /users/me/llm-settings

Required scope: write. Returns 201 Created.

There is at most one config per provider per user; calling POST again for the same provider updates the existing row.

Request Body:

FieldTypeRequiredDescription
providerenumYesanthropic, openai, deepseek_cloud, gemini, or deepseek_local
api_keystringCond.Required for every provider except deepseek_local
modelstringNoOverride the provider's default model
base_urlstringNoCustom endpoint (useful for OpenAI-compatible gateways)
is_defaultbooleanNoWhen true, marks this as the user's default provider

Validation errors return 400.

Response: LLMSettingsResponse (same shape as list items).


Update Config

PATCH /users/me/llm-settings/{config_id}

Required scope: write

Partial update. Cannot change provider (delete + recreate instead) or is_default (use the /set-default endpoint).

Returns 404 if the config doesn't belong to the caller, 400 on validation errors.


Delete Config

DELETE /users/me/llm-settings/{config_id}

Required scope: write. Returns 204 No Content, or 404 if the config doesn't exist for the caller.


Set Default Provider

POST /users/me/llm-settings/{config_id}/set-default

Required scope: write

Marks the given config as the default; clears the flag on any other config for the same user.

Response: Updated LLMSettingsResponse.


Test Connection

POST /users/me/llm-settings/test

Required scope: write

Validate a provider configuration without saving it. Pass api_key to test a fresh key, or omit it to test the currently saved key for that provider.

Request Body:

FieldTypeRequiredDescription
providerenumYesProvider to test
api_keystringNoOverride the stored key for this test
base_urlstringNoOverride the stored base URL

Response:

{
"success": true,
"provider": "anthropic",
"message": "Connection OK",
"latency_ms": 420,
"model_available": "claude-sonnet-4-5"
}

Returns 404 with error_code: "provider_not_configured" when no key is stored and none is passed in the body.