Skip to main content

LLM Settings API

Manage the current user's LLM provider configuration for LENS AI. Two kinds of provider exist: Seal AI (seal_ai, the platform-managed private provider — no API key, subject to plan entitlement and token quota) and Bring-Your-Own-Key (BYOK) providers, where keys are stored per-user (not per-site) and reused across every site the user can access. LENS AI uses these settings to call Seal AI, 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) plus seal_ai (the platform-managed provider, listed first whenever the platform key is configured). Each entry carries the display metadata used by the settings UI.

Response:

{
"providers": [
{
"id": "seal_ai",
"name": "Seal AI (Private, EU)",
"description": "SealMetrics private AI. Processed entirely in the EU, no prompt retention, your data never trains third-party models. No API key needed.",
"requires_api_key": false,
"requires_plan_upgrade": false,
"default_models": {
"simple": "gpt-oss-120b",
"complex": "gpt-oss-120b",
"critical": "gpt-oss-120b"
},
"documentation_url": null
},
{
"id": "anthropic",
"name": "Anthropic (Claude)",
"description": "Claude models from Anthropic. Requires API key.",
"requires_api_key": true,
"requires_plan_upgrade": false,
"default_models": {
"simple": "claude-3-5-haiku-20241022",
"complex": "claude-sonnet-4-20250514",
"critical": "claude-opus-4-20250514"
},
"documentation_url": "https://docs.anthropic.com/"
}
],
"default_provider": "anthropic"
}

requires_plan_upgrade is true on seal_ai when the user's plan does not include Seal AI (it drives the upgrade badge in the settings UI). Each provider exposes three default models — one per rule-complexity tier (simple / complex / critical) — which you can override per-config with the fields below.


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",
"model_simple": null,
"model_complex": "claude-sonnet-4-20250514",
"model_critical": null,
"deepseek_base_url": null,
"is_enabled": true,
"is_default": true,
"created_at": "2025-01-05T10:00:00Z",
"updated_at": "2025-01-05T10:00:00Z"
}
]
}

model_simple / model_complex / model_critical are per-tier overrides — null means the provider's default model for that tier is used. The stored API key is never returned.


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
providerenumYesseal_ai, anthropic, openai, deepseek_cloud, gemini, or deepseek_local
api_keystringCond.10–200 chars. Required for anthropic, openai, deepseek_cloud, gemini; not needed for seal_ai / deepseek_local
model_simplestringNoModel override for the simple rule tier
model_complexstringNoModel override for the complex rule tier
model_criticalstringNoModel override for the critical rule tier
deepseek_base_urlstringNoCustom DeepSeek endpoint (Cloud or self-hosted)
is_enabledbooleanNoWhether this configuration is active (default true)

To mark a config as the user's default, use the /set-default endpoint — is_default is not accepted in this body. Validation errors return 400/422.

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.