AI Providers
Catalog, workspace provider configs, and live credential tests.
Endpoints under /api/v1/ai-providers. Authenticate with Authorization: Bearer. Any valid key scope is accepted. Missing/invalid token: 401 { "error": "Valid bearer API key is required" }. Bodies are { error } / { providers } / { provider } / { result } — not the usage contract envelope.
Session twins exist at /api/ai-providers (cookie session + workspaceId query/body).
Endpoints
| Method | Path | Description |
|---|---|---|
| GET | /api/v1/ai-providers | List workspace configs |
| POST | /api/v1/ai-providers | Create a config (201) |
| GET | /api/v1/ai-providers/{id} | Get one config |
| PATCH | /api/v1/ai-providers/{id} | Update config |
| GET | /api/v1/ai-providers/catalog | Static BYOK catalog |
| POST | /api/v1/ai-providers/test | Live connection test |
List and create
GET returns { providers[] } with id, workspaceId, provider, displayName, defaultModel, credentialName, baseUrl, apiVersion, disabledModels, status, updatedAt.
POST body:
| Field | Notes |
|---|---|
provider | Required. One of openai, anthropic, google, azure, openrouter, deepseek, mistral, groq, perplexity, together, fireworks, xai, cohere, custom |
defaultModel | Required, trimmed |
credentialName | Required, trimmed |
baseUrl | Optional (v1 does not validate scheme) |
apiVersion | Optional (Azure) |
disabledModels | Optional string array |
Invalid provider: 400 listing allowed values. Missing model/credential: 400 "Default model and credential name are required."
Get and patch
Unknown id: 404 "AI provider not found." PATCH accepts the same optional fields as create except provider. Empty strings on model/credential are ignored (trim() then omitted).
Catalog
GET /api/v1/ai-providers/catalog → { providers } from listByokProviderCatalog() (includes Ollama/vLLM as custom with discovery flags). No live discovery on v1.
Session catalog may add warnings and discovered local models.
Test
{
"provider": "openai",
"model": "gpt-4o-mini",
"credentialName": "OPENAI_API_KEY",
"apiKey": "",
"baseUrl": "",
"apiVersion": ""
}
Inline apiKey wins; otherwise the named workspace credential is decrypted. Missing credential name lookup: 400. Missing provider: 400. Result HTTP 200 if result.ok, else 400 { result }.
