Endpoints
Management API reference. All routes are under /v1, take and return JSON,
and require Authorization: Bearer <console token> unless marked public.
The last column is the permission needed (any one of them, when several are
listed).
Health and installation
| Method |
Path |
Purpose |
Auth |
GET |
/health |
Liveness. {"status":"ok"} with no I/O. |
public |
GET |
/install/status |
{"state":"installed"\|"not_installed"\|"partial","version":N\|null} |
public |
POST |
/install |
Install the schema when not_installed. 409 once installed, 500 on partial. |
public |
GET |
/diagnostics |
Build version, schema state vs. expected, observability status. Never fails, even with the database down. |
any user |
// GET /v1/diagnostics
{
"version": "3.1.0",
"db_schema": { "state": "installed", "version": 3, "expected": 3 },
"observability": { "enabled": true, "type": "http", "format": "ndjson" }
}
Users
| Method |
Path |
Purpose |
Permission |
POST |
/users/login |
{email,password} → user + token |
public |
POST |
/users/logout |
Rotates the token |
any user |
GET |
/users/me |
Current user, without secrets |
any user |
PATCH |
/users/password |
{current_password,new_password} for oneself |
any user |
GET |
/users?search&is_active&page&limit |
List |
core:read |
GET |
/users/:id |
One user |
core:read |
POST |
/users |
{email,password,name} |
core:create |
PATCH |
/users/:id |
{name} |
core:update |
PATCH |
/users/:id/activate, /users/:id/deactivate |
Toggle; deactivating rotates the token |
core:update |
PATCH |
/users/:id/regenerate/password |
{new_password} set by an admin; rotates the token |
core:manage |
DELETE |
/users/:id |
Delete |
core:delete |
GET |
/users/:userId/roles |
Roles of a user |
core:read |
POST |
/users/:userId/roles |
{role_id} |
core:update |
DELETE |
/users/:userId/roles/:userRoleId |
Remove assignment |
core:update |
Roles and permissions
| Method |
Path |
Purpose |
Permission |
GET |
/roles, /roles/:id |
List; detail includes permissions |
core:read |
POST |
/roles |
Create |
core:create |
PATCH |
/roles/:id |
Rename / describe |
core:update |
PATCH |
/roles/:roleId/permissions |
{permission_ids:[…]} replaces the set |
core:update |
DELETE |
/roles/:id |
Delete (system roles refuse) |
core:delete |
GET |
/permissions?module |
Catalogue of permissions |
core:read |
Providers
| Method |
Path |
Purpose |
Permission |
GET |
/llm/providers, /llm/providers/:id |
List / detail. Credentials never returned; api_key_masked holds the last 4 characters. |
llm:read |
POST |
/llm/providers/test |
Validate credentials without saving |
llm:test |
POST |
/llm/providers |
Create; connectivity is verified before saving |
llm:create |
PATCH |
/llm/providers/:id |
{name,description} |
llm:update |
PATCH |
/llm/providers/:id/activate, /deactivate |
Toggle; inactive providers refuse runtime traffic (provider_inactive) |
llm:update |
DELETE |
/llm/providers/:id |
Delete; 409 while it has models |
llm:delete |
GET |
/llm/providers/:id/files |
Files stored at the provider |
llm:read |
DELETE |
/llm/providers/:id/files/:fileId |
Delete a provider file |
llm:delete |
Provider types and their fields:
type |
Required |
Optional |
openai |
api_key |
|
azure-openai |
api_key, base_url, api_version |
|
google-aistudio |
api_key |
|
google-enterprise (Vertex AI) |
region |
project_id (else taken from the service-account JSON or the GCP metadata server), credentials (service-account JSON, raw or base64; without it the core uses the environment's GCP identity), bucket_uri (gs://…, for Files) |
Models
| Method |
Path |
Purpose |
Permission |
GET |
/llm/models?provider_id&is_active&search |
List |
llm:read |
GET |
/llm/models/:id |
Detail |
llm:read |
GET |
/llm/models/:id/stats?from&to&group_by |
Usage of one model |
llm:read |
GET |
/llm/providers/:providerId/models/deployed |
Models already registered for a provider |
llm:read |
GET |
/llm/providers/:providerId/models/from-provider?publisher |
Models the provider offers |
llm:read |
POST |
/llm/providers/:providerId/models |
Register a model (name, prices per 1M tokens, flags) |
llm:create |
POST |
/llm/providers/:providerId/models/:modelId/test |
Send a test generation |
llm:test |
POST |
/llm/models/:idModel/replace/:idNewModel?dry_run |
Swap one model for another across apps |
llm:update |
PATCH |
/llm/models/:id |
Edit prices, flags, rate-limit fields |
llm:update |
DELETE |
/llm/models/:id |
Delete |
llm:delete |
GET |
/llm/models/:modelId/scopes, …/scopes/:scopeId/usages |
Where a model is allowed |
llm:read |
POST |
/llm/models/:modelId/scopes |
{scope_type,scope_id} |
llm:update |
DELETE |
/llm/models/:modelId/scopes/:scopeId |
Remove a scope |
llm:update |
Proxy apps
| Method |
Path |
Purpose |
Permission |
GET |
/proxy-apps, /proxy-apps/:id |
List / detail |
rm:read |
GET |
/proxy-apps/:proxyAppId/allowed-models |
Effective model list |
rm:read |
GET |
/proxy-apps/:id/stats?from&to&group_by |
Usage of one app |
rm:read |
GET |
/proxy-apps/cache, /proxy-apps/:id/cache |
Cache contents |
rm:read |
POST |
/proxy-apps |
Create (status draft) |
rm:create |
PATCH |
/proxy-apps/:id |
{name,description,budget_limit,budget_period,rate_limit_rpm,rate_limit_tpm,policies} |
rm:update |
PATCH |
/proxy-apps/:id/publish |
→ ready (needs a default model) |
rm:update |
PATCH |
/proxy-apps/:id/deactivate |
→ inactive |
rm:update |
PATCH |
/proxy-apps/:id/default-models |
Set default model |
rm:update |
PATCH |
/proxy-apps/:id/allowed-models |
{model_ids:[…]} |
rm:update |
DELETE |
/proxy-apps/:id |
Delete |
rm:delete |
DELETE |
/proxy-apps/:id/cache, /proxy-apps/:id/cache/expired |
Clear cache for one app |
rm:delete |
DELETE |
/proxy-apps/cache/expired |
Clear expired cache entries globally (cron-friendly) |
rm:delete |
API keys
| Method |
Path |
Purpose |
Permission |
GET |
/rm/api-keys?scope_type&proxy_app_id&rm_project_id |
List (hash and suffix only) |
rm:read |
GET |
/rm/api-keys/:id |
Detail |
rm:read |
POST |
/rm/api-keys |
{name,scope_type:"proxy_app",proxy_app_id,expires_at?} → returns key once |
rm:create |
PATCH |
/rm/api-keys/:id |
{name,is_active,expires_at} |
rm:update |
DELETE |
/rm/api-keys/:id |
Delete |
rm:delete |
Statistics
| Method |
Path |
Purpose |
Permission |
GET |
/stats/proxy?from&to&group_by&id_proxy_app&id_model |
Aggregates from stats.proxy_daily |
observability:read |
from and to are YYYY-MM-DD, required, at most 366 days apart.
group_by takes up to two of day, model, app separated by a comma.
Response: { "range": {…}, "totals": {…}, "rows": […] } with requests,
tokens and cost. Latency and error counters in this table are not populated
in this version; use traces for those.
Observability
| Method |
Path |
Purpose |
Permission |
GET |
/observability/traces?trace_id&proxy_app_id&status&from&to&limit |
Query traces (PostgreSQL destination only; 409 otherwise) |
observability:read |
Parameters and paging: PostgreSQL destination.
Projects and endpoints (preview)
/rm/projects and /rm/endpoints offer CRUD for a prompt-management feature
whose runtime is not yet available. API keys with scope_type: rm_project
can be created but have nothing to call. Expect these routes to change.
Runtime API
The provider gateways under /proxy-apps/:proxyAppId/{openai,gemini,vertex}
are documented in Proxy apps & gateways.