This document describes the public HTTP APIs exposed by Conductor, including authentication, tenant scoping, core resources, operational endpoints, and proxied Virtual Model Runner APIs.
Primary audience: developers, automation engineers, and sysadmins integrating directly with Conductor.
The management API is versioned under /v1.0.
Examples in this document assume:
http://localhost:9000
So a full resource URL looks like:
http://localhost:9000/v1.0/virtualmodelrunners
- Request and response bodies use JSON unless noted otherwise.
- Enum values are serialized as strings such as
OpenAI,LeastRecentlyUsed, orFailClosed. - Successful deletes return HTTP
204 No Content. - Successful creates generally return HTTP
201 Created.
Conductor supports four practical authentication styles.
Use a credential bearer token in the Authorization header:
Authorization: Bearer cred_xxx_or_token_valueThis is the standard authentication mode for tenant users and API clients.
You can also authenticate a tenant user directly with headers:
x-tenant-id: default
x-email: admin@conductor
x-password: passwordThis is less common than bearer tokens, but it is supported by the server.
System administrator routes accept:
x-admin-email: admin@example.com
x-admin-password: secretIf admin API keys are configured in server settings, they can be sent as either:
x-admin-apikey: your-admin-api-keyor:
Authorization: Bearer your-admin-api-keyFor bearer-token-authenticated proxied Gemini requests, Conductor also checks ?key= if no bearer token is present. This is intended to support Gemini-style clients.
Conductor's route permissions are split across four levels:
| Level | Meaning |
|---|---|
Public |
No authentication required. |
Authenticated |
Any authenticated tenant user, global admin user, or system administrator. |
TenantAdmin |
A user with IsTenantAdmin=true, any global admin user, or any system administrator. |
GlobalAdmin |
A user with IsAdmin=true or any system administrator. |
AdminOnly |
Only system administrator authentication or admin API keys. |
Important distinction:
- A global admin user is a normal tenant user credential whose user record has
IsAdmin=true. - A system administrator is an
Administratoraccount authenticated with admin headers or an admin API key.
Most resources are tenant-scoped:
- users
- credentials
- model runner endpoints
- model definitions
- model configurations
- load-balancing policies
- virtual model runners
- request history
Rules:
- Normal tenant users are always scoped to their own tenant.
- Global admin users and system administrators can work across tenants.
- On create routes, cross-tenant callers should supply
TenantIdin the request body. - On read, update, delete, list, and health routes for tenant-scoped resources, cross-tenant callers can use
?tenantId=<tenant-id>.
Example:
GET /v1.0/modelrunnerendpoints/mre_123?tenantId=default
Many list endpoints accept these query parameters:
| Query parameter | Type | Notes |
|---|---|---|
maxResults |
integer | Maximum items to return. Server clamps to 1..1000. Default is 100. |
continuationToken |
string | Opaque pagination token from a previous response. |
nameFilter |
string | Partial name filter. Only available on routes whose controller supports it. |
activeFilter |
boolean | Filter active vs inactive resources. |
Typical list response shape:
{
"Data": [],
"ContinuationToken": null,
"TotalCount": 0,
"HasMore": false
}Typical response codes:
| Status | Meaning |
|---|---|
200 |
Success |
201 |
Resource created |
204 |
Delete succeeded, no body |
400 |
Validation failure or malformed request |
401 |
Authentication or authorization failure |
403 |
Authenticated caller is forbidden, including model access denials on proxied requests |
404 |
Resource not found |
409 |
Conflict, such as deleting an attached model access policy without forceDetach=true |
500 |
Unexpected server failure |
The dashboard client expects error payloads to include Message or message, but exact error bodies may vary by route.
These are the primary JSON resources used across the API.
{
"Id": "usr_xxx",
"TenantId": "default",
"FirstName": "Admin", // required
"LastName": "User", // required
"Email": "admin@conductor", // required
"Password": "password", // required in create/update payloads
"Active": true,
"IsAdmin": true,
"IsTenantAdmin": true,
"Labels": [],
"Tags": {},
"Metadata": null,
"CreatedUtc": "2026-05-18T12:00:00Z",
"LastUpdateUtc": "2026-05-18T12:00:00Z"
}{
"Id": "cred_xxx",
"TenantId": "default",
"UserId": "usr_xxx",
"Name": "Primary API Key",
"BearerToken": "token-value", // generated if omitted on create
"Active": true,
"Labels": [],
"Tags": {},
"Metadata": null,
"CreatedUtc": "2026-05-18T12:00:00Z",
"LastUpdateUtc": "2026-05-18T12:00:00Z"
}{
"Id": "mre_xxx",
"TenantId": "default",
"Name": "GPU Host A", // required
"Hostname": "gpu-a.local", // required
"Port": 11434,
"ApiKey": null,
"ApiType": "Ollama", // Ollama, OpenAI, Gemini, vLLM
"UseSsl": false,
"TimeoutMs": 60000,
"Active": true,
"HealthCheckUrl": "/",
"HealthCheckMethod": "GET",
"HealthCheckIntervalMs": 5000,
"HealthCheckTimeoutMs": 5000,
"HealthCheckExpectedStatusCode": 200,
"UnhealthyThreshold": 2,
"HealthyThreshold": 2,
"HealthCheckUseAuth": false,
"MaxParallelRequests": 4,
"Weight": 1,
"ServiceState": "Normal", // Normal, Draining, Quarantined
"RigMonitor": {
"Enabled": true,
"HostnameOverride": null,
"Port": 9990,
"UseSsl": false,
"TimeoutMs": 5000,
"CollectDuringHealthCheck": true,
"RequireReadyz": true,
"HealthAffectedByRigMonitor": false,
"MaxTelemetryAgeMs": 30000,
"CapabilitiesRefreshIntervalMs": 60000,
"TelemetryProfile": "Full", // Basic, GpuPlacement, OllamaPlacement, Full, Custom
"TelemetrySelectors": []
},
"Labels": [],
"Tags": {},
"Metadata": null,
"CreatedUtc": "2026-05-18T12:00:00Z",
"LastUpdateUtc": "2026-05-18T12:00:00Z"
}{
"Id": "egp_xxx",
"TenantId": "default",
"Name": "Primary GPU Pool", // required
"Description": "Preferred low-latency endpoints",
"Priority": 0,
"Active": true,
"TrafficWeight": 100,
"EndpointIds": ["mre_a", "mre_b"], // required; endpoints must be in the same tenant
"Labels": [],
"Tags": {},
"Metadata": null,
"CreatedUtc": "2026-06-26T12:00:00Z",
"LastUpdateUtc": "2026-06-26T12:00:00Z"
}{
"Id": "md_xxx",
"TenantId": "default",
"Name": "llama3.2:latest", // required
"SourceUrl": null,
"Family": "llama",
"ParameterSize": "8B",
"QuantizationLevel": "Q4_K_M",
"ContextWindowSize": 8192,
"SupportsEmbeddings": false,
"SupportsCompletions": true,
"Active": true,
"Labels": [],
"Tags": {},
"Metadata": null,
"CreatedUtc": "2026-05-18T12:00:00Z",
"LastUpdateUtc": "2026-05-18T12:00:00Z"
}{
"Id": "mc_xxx",
"TenantId": "default",
"Name": "Low Temperature", // required
"ContextWindowSize": 8192,
"Temperature": 0.3,
"TopP": 0.95,
"TopK": 40,
"RepeatPenalty": 1.1,
"MaxTokens": 1024,
"Model": null, // null means applies to any model
"PinnedEmbeddingsProperties": {},
"PinnedCompletionsProperties": {
"temperature": 0.3
},
"Active": true,
"Labels": [],
"Tags": {},
"Metadata": null,
"CreatedUtc": "2026-05-18T12:00:00Z",
"LastUpdateUtc": "2026-05-18T12:00:00Z"
}See LOAD_BALANCING_POLICIES.md for the full schema, supported metrics, and authoring guidance.
Minimal example:
{
"Id": "lbp_xxx",
"TenantId": "default",
"Name": "Least In-Flight",
"Description": "Prefer the least busy endpoint.",
"MaxTelemetryAgeMs": 30000,
"Filters": [],
"Ranking": [
{
"Metric": "health.inFlightRequests",
"Direction": "Ascending",
"Weight": 1.0
}
],
"FallbackMode": "UseLegacyLoadBalancingMode",
"TieBreaker": "RoundRobin",
"Active": true,
"Labels": [],
"Tags": {},
"Metadata": null,
"CreatedUtc": "2026-05-18T12:00:00Z",
"LastUpdateUtc": "2026-05-18T12:00:00Z"
}Model access policies are tenant-scoped ACL resources attached to VMRs through VirtualModelRunner.ModelAccessPolicyId.
{
"Id": "map_xxx",
"TenantId": "default",
"Name": "Production model access",
"Description": "Default deny with explicit model grants.",
"DefaultDecision": "Deny",
"Active": true,
"Rules": [
{
"Id": "mar_xxx",
"TenantId": "default",
"PolicyId": "map_xxx",
"Name": "Finance credential can use chat model",
"Priority": 100,
"Effect": "Allow",
"SubjectType": "CredentialLabel",
"SubjectSelector": { "label": "finance" },
"ResourceType": "ModelLabel",
"ResourceSelector": { "label": "chat" },
"VirtualModelRunnerId": null,
"Actions": ["Completions", "ListModels"],
"Active": true
}
],
"Labels": [],
"Tags": {},
"Metadata": null,
"CreatedUtc": "2026-06-13T12:00:00Z",
"LastUpdateUtc": "2026-06-13T12:00:00Z"
}Supported enum values:
DefaultDecision:Permit,DenyEffect:Allow,DenySubjectType:Credential,CredentialLabel,User,UserLabel,Tenant,AnyResourceType:ModelDefinition,ModelName,ModelLabel,VirtualModelRunner,AnyActions:Completions,Embeddings,ListModels,ShowModel,LoadModel,UnloadModel,ModelManagement
Selector objects support simple keys such as label, labels, value, equals, prefix, and contains.
{
"Id": "vmr_xxx",
"TenantId": "default",
"Name": "gpu-chat", // required
"Hostname": null,
"BasePath": "/v1.0/api/gpu-chat/", // required; exactly one segment after /v1.0/api/
"ApiType": "OpenAI",
"LoadBalancingMode": "RoundRobin", // RoundRobin, Random, FirstAvailable, LeastRecentlyUsed, Adaptive
"LoadBalancingPolicyId": "lbp_xxx",
"ModelAccessPolicyId": "map_xxx",
"ModelRunnerEndpointIds": ["mre_a", "mre_b"],
"AdaptiveLoadBalancing": {
"SampleCount": 2,
"ColdStartScore": 60,
"EwmaAlpha": 0.2,
"BackoffBaseMs": 30000,
"BackoffMaxMs": 300000,
"FailureThreshold": 3,
"ExcludeBackoffEndpoints": true,
"BackoffBreaksSessionAffinity": true,
"Weights": {
"Success": 35,
"Latency": 25,
"TimeToFirstToken": 15,
"Pending": 15,
"EndpointWeight": 10
}
},
"EndpointGroupIds": ["egp_primary"],
"EndpointGroups": [], // legacy inline groups; prefer EndpointGroupIds
"ModelConfigurationIds": ["mc_default"],
"ModelConfigurationMappings": {
"llama3.2:latest": "mc_default"
},
"ModelDefinitionIds": ["md_llama"],
"TimeoutMs": 300000,
"AllowEmbeddings": true,
"AllowCompletions": true,
"AllowModelManagement": false,
"StrictMode": false,
"SessionAffinityMode": "None", // None, SourceIP, ApiKey, Header
"SessionAffinityHeader": null,
"SessionTimeoutMs": 600000,
"SessionMaxEntries": 10000,
"RequestHistoryEnabled": true,
"Active": true,
"Labels": [],
"Tags": {},
"Metadata": null,
"CreatedUtc": "2026-05-18T12:00:00Z",
"LastUpdateUtc": "2026-05-18T12:00:00Z"
}{
"Id": "adm_xxx",
"Email": "admin@example.com",
"FirstName": "System",
"LastName": "Administrator",
"Active": true,
"CreatedUtc": "2026-05-18T12:00:00Z",
"LastUpdateUtc": "2026-05-18T12:00:00Z"
}Create/update administrator request bodies use:
{
"Email": "admin@example.com",
"Password": "secret",
"FirstName": "System",
"LastName": "Administrator",
"Active": true
}| Method | Path | Auth | Notes |
|---|---|---|---|
GET |
/ |
Public | Root health check, returns 200 OK. |
HEAD |
/ |
Public | Root health check without a body. |
GET |
/health |
Public | Returns a small JSON health payload. |
Example /health response:
{
"status": "healthy"
}| Method | Path | Auth | Notes |
|---|---|---|---|
POST |
/v1.0/auth/login/credential |
Public | Exchange TenantId, Email, and Password for a bearer token. |
POST |
/v1.0/auth/login/apikey |
Public | Validate a credential API key or configured admin API key. |
POST |
/v1.0/auth/login/admin |
Public | Authenticate an Administrator by email/password. |
Credential login request:
{
"TenantId": "default",
"Email": "admin@conductor",
"Password": "password"
}Credential login response:
{
"Success": true,
"BearerToken": "token-value",
"Tenant": {
"Id": "default",
"Name": "Default Tenant"
},
"User": {
"Id": "usr_xxx",
"Email": "admin@conductor",
"FirstName": "Admin",
"LastName": "User",
"IsAdmin": true,
"IsTenantAdmin": true
}
}Admin login response:
{
"Success": true,
"Administrator": {
"Id": "adm_xxx",
"Email": "admin@example.com",
"FirstName": "System",
"LastName": "Administrator"
}
}Admin API key login response:
{
"Success": true,
"IsAdmin": true,
"ApiKey": "your-admin-api-key"
}Auth level: AdminOnly
| Method | Path | Notes |
|---|---|---|
GET |
/v1.0/administrators |
List administrators. Query: maxResults, continuationToken, activeFilter. |
POST |
/v1.0/administrators |
Create administrator. |
GET |
/v1.0/administrators/{id} |
Read administrator. |
PUT |
/v1.0/administrators/{id} |
Update administrator. |
DELETE |
/v1.0/administrators/{id} |
Delete administrator. Cannot delete the currently authenticated administrator account. |
Auth:
GET /v1.0/tenants/{id}:GlobalAdmin- all other tenant routes:
AdminOnly
| Method | Path | Notes |
|---|---|---|
GET |
/v1.0/tenants |
List tenants. Query: maxResults, continuationToken, nameFilter, activeFilter. |
POST |
/v1.0/tenants |
Create tenant. |
GET |
/v1.0/tenants/{id} |
Read tenant. |
PUT |
/v1.0/tenants/{id} |
Update tenant. |
DELETE |
/v1.0/tenants/{id} |
Delete tenant and all subordinate tenant data (now including QoS profiles and traffic classes). |
POST |
/v1.0/tenants/{id}/purge |
Purge (nuke) a tenant and all of its data; returns an itemized TenantPurgeReport. System-admin only (returns 403 for tenant-scoped callers). The body must echo the id as {"ConfirmTenantId":"<id>"} (mismatch → 400); the reserved default tenant cannot be purged. |
Auth level: TenantAdmin
| Method | Path | Notes |
|---|---|---|
GET |
/v1.0/users |
List users. Query: maxResults, continuationToken, nameFilter, activeFilter, optional tenantId for cross-tenant callers. |
POST |
/v1.0/users |
Create user. Cross-tenant callers supply TenantId in the body. |
GET |
/v1.0/users/{id} |
Read user. Optional tenantId query for cross-tenant callers. |
PUT |
/v1.0/users/{id} |
Update user. Cross-tenant callers supply TenantId in the body. |
DELETE |
/v1.0/users/{id} |
Delete user. Optional tenantId query for cross-tenant callers. Also deletes associated credentials. |
Auth level: TenantAdmin
| Method | Path | Notes |
|---|---|---|
GET |
/v1.0/credentials |
List credentials. Query: maxResults, continuationToken, activeFilter, optional tenantId. |
POST |
/v1.0/credentials |
Create credential. Cross-tenant callers supply TenantId and UserId in the body. BearerToken is generated if omitted. |
GET |
/v1.0/credentials/{id} |
Read credential. Optional tenantId query. |
PUT |
/v1.0/credentials/{id} |
Update credential. Optional new BearerToken must be unique. |
DELETE |
/v1.0/credentials/{id} |
Delete credential. Optional tenantId query. |
Auth level: Authenticated
| Method | Path | Notes |
|---|---|---|
GET |
/v1.0/modelrunnerendpoints |
List endpoints. Query: maxResults, continuationToken, nameFilter, activeFilter, optional tenantId. |
POST |
/v1.0/modelrunnerendpoints |
Create endpoint. Cross-tenant callers supply TenantId in the body. |
POST |
/v1.0/modelrunnerendpoints/validate |
Validate an endpoint draft without saving it. Optional query: tenantId, existingId. |
GET |
/v1.0/modelrunnerendpoints/{id} |
Read endpoint. Optional tenantId query. |
PUT |
/v1.0/modelrunnerendpoints/{id} |
Update endpoint. Cross-tenant callers supply TenantId in the body. |
DELETE |
/v1.0/modelrunnerendpoints/{id} |
Delete endpoint. Optional tenantId query. Also removes the endpoint from referenced VMRs and endpoint groups. |
POST |
/v1.0/modelrunnerendpoints/{id}/drain |
Move the endpoint to Draining service state. Optional tenantId query. |
POST |
/v1.0/modelrunnerendpoints/{id}/resume |
Move the endpoint back to Normal service state. Optional tenantId query. |
POST |
/v1.0/modelrunnerendpoints/{id}/quarantine |
Move the endpoint to Quarantined service state. Optional tenantId query. |
POST |
/v1.0/modelrunnerendpoints/{id}/load-model |
Tenant-admin route to load or verify a model on one concrete endpoint. Optional tenantId query. |
GET |
/v1.0/modelrunnerendpoints/{id}/ollama/models |
Tenant-admin route to list local models on an Ollama endpoint. Optional tenantId query. |
POST |
/v1.0/modelrunnerendpoints/{id}/ollama/models/pull |
Tenant-admin route to pull a model onto an Ollama endpoint. Optional tenantId query. |
POST |
/v1.0/modelrunnerendpoints/{id}/ollama/models/delete |
Tenant-admin route to delete a local model from an Ollama endpoint. Optional tenantId query. |
GET |
/v1.0/modelrunnerendpoints/health |
List cached health state for all endpoints in scope. Optional tenantId query. |
GET |
/v1.0/modelrunnerendpoints/{id}/health |
Get cached health state for one endpoint. Optional tenantId query. |
GET |
/v1.0/modelrunnerendpoints/{id}/rigmonitor |
Get cached RigMonitor status for one endpoint. Optional tenantId query. |
Endpoint health response fields include:
EndpointIdEndpointNameIsHealthyLastCheckUtcLastHealthyUtcLastUnhealthyUtcFirstCheckUtcTotalUptimeMsTotalDowntimeMsUptimePercentageConsecutiveSuccessesConsecutiveFailuresInFlightRequestsMaxParallelRequestsWeightServiceStateLastErrorLastStateChangeUtcHistoryRigMonitor
Health checks are coalesced by effective request. When multiple active model runner endpoints use the same health-check method, base URL, health-check path, and auth context, Conductor sends one upstream health-check HTTP request and applies the result to each endpoint's own expected status code, thresholds, service state, and history.
RigMonitor status response fields include:
EnabledBaseUrlReadyReadyStatusReadyMessageLastReadyzUtcLastCapabilitiesUtcLastTelemetryUtcLastErrorCapabilitiesTelemetry
Capabilities is a cached summary of platform support. Telemetry contains nested System, Cpu, Memory, Network, Disk, Gpu, and Ollama sections.
Auth level: Authenticated
| Method | Path | Notes |
|---|---|---|
GET |
/v1.0/endpointgroups |
List endpoint groups. Query: maxResults, continuationToken, nameFilter, activeFilter, optional tenantId. |
POST |
/v1.0/endpointgroups |
Create endpoint group. Cross-tenant callers supply TenantId in the body. |
POST |
/v1.0/endpointgroups/validate |
Validate an endpoint group draft without saving it. Optional query: tenantId, existingId. |
GET |
/v1.0/endpointgroups/{id} |
Read endpoint group. Optional tenantId query. |
PUT |
/v1.0/endpointgroups/{id} |
Update endpoint group. Cross-tenant callers supply TenantId in the body. |
DELETE |
/v1.0/endpointgroups/{id} |
Delete endpoint group. Optional tenantId query. Also detaches the group from VMRs. |
Endpoint groups are tenant-wide reusable objects. A VMR references them through EndpointGroupIds; during save, the server expands the referenced group endpoint IDs into the VMR endpoint inventory so the route remains directly inspectable.
Auth level: TenantAdmin
These routes are available only when the target model runner endpoint has ApiType=Ollama. They call the configured endpoint directly and return upstream status details without creating request-history entries.
| Method | Path | Upstream Ollama API | Notes |
|---|---|---|---|
GET |
/v1.0/modelrunnerendpoints/{id}/ollama/models |
GET /api/tags |
Lists local models available on the endpoint. |
POST |
/v1.0/modelrunnerendpoints/{id}/ollama/models/pull |
POST /api/pull |
Pulls a model with stream=false; large downloads should use a larger TimeoutMs. |
POST |
/v1.0/modelrunnerendpoints/{id}/ollama/models/delete |
DELETE /api/delete |
Deletes a local model. Conductor uses a POST control-plane wrapper so the model name can be sent as JSON reliably. |
Pull request:
{
"Model": "gemma3:4b",
"Insecure": false,
"TimeoutMs": 1800000
}Delete request:
{
"Model": "gemma3:4b",
"TimeoutMs": 300000
}The dashboard exposes these routes from the Manage Models action on Ollama-type model runner endpoints.
Auth level: Authenticated
| Method | Path | Notes |
|---|---|---|
GET |
/v1.0/modeldefinitions |
List definitions. Query: maxResults, continuationToken, nameFilter, activeFilter, optional tenantId. |
POST |
/v1.0/modeldefinitions |
Create definition. Cross-tenant callers supply TenantId in the body. |
POST |
/v1.0/modeldefinitions/validate |
Validate a model-definition draft without saving it. Optional query: tenantId, existingId. |
GET |
/v1.0/modeldefinitions/{id} |
Read definition. Optional tenantId query. |
PUT |
/v1.0/modeldefinitions/{id} |
Update definition. Cross-tenant callers supply TenantId in the body. |
DELETE |
/v1.0/modeldefinitions/{id} |
Delete definition. Optional tenantId query. Also removes it from referenced VMRs. |
Auth level: Authenticated
| Method | Path | Notes |
|---|---|---|
GET |
/v1.0/modelconfigurations |
List configurations. Query: maxResults, continuationToken, nameFilter, activeFilter, optional tenantId. |
POST |
/v1.0/modelconfigurations |
Create configuration. Cross-tenant callers supply TenantId in the body. |
POST |
/v1.0/modelconfigurations/validate |
Validate a model-configuration draft without saving it. Optional query: tenantId, existingId. |
GET |
/v1.0/modelconfigurations/{id} |
Read configuration. Optional tenantId query. |
PUT |
/v1.0/modelconfigurations/{id} |
Update configuration. Cross-tenant callers supply TenantId in the body. |
DELETE |
/v1.0/modelconfigurations/{id} |
Delete configuration. Optional tenantId query. Also removes it from referenced VMRs. |
Auth level: Authenticated
| Method | Path | Notes |
|---|---|---|
GET |
/v1.0/loadbalancingpolicies |
List policies. Query: maxResults, continuationToken, nameFilter, activeFilter, optional tenantId. |
POST |
/v1.0/loadbalancingpolicies |
Create policy. Cross-tenant callers supply TenantId in the body. |
POST |
/v1.0/loadbalancingpolicies/validate |
Validate a load-balancing policy draft without saving it. Optional query: tenantId, existingId. |
GET |
/v1.0/loadbalancingpolicies/{id} |
Read policy. Optional tenantId query. |
PUT |
/v1.0/loadbalancingpolicies/{id} |
Update policy. Cross-tenant callers supply TenantId in the body. |
DELETE |
/v1.0/loadbalancingpolicies/{id} |
Delete policy. Optional tenantId query. Also detaches it from any VMRs that reference it. |
GET |
/v1.0/loadbalancingpolicies/metrics |
Return the live supported metric catalog used by the policy evaluator. |
The metrics response shape is:
{
"Metrics": [
{
"Id": "rig.cpu.utilizationPercent",
"Name": "CPU Utilization",
"Description": "Current host CPU utilization percentage.",
"Source": "rigmonitor",
"ValueType": "Number",
"SupportsFiltering": true,
"SupportsRanking": true,
"RecommendedDirection": "asc",
"SupportedOperators": [
"Equal",
"NotEqual",
"LessThan",
"LessThanOrEqual",
"GreaterThan",
"GreaterThanOrEqual"
]
}
]
}Auth level: Authenticated
A QoS profile classifies and queues traffic for a virtual model runner. It is an aggregate: the body
carries scalar fields (DefaultClass, IngressMode, IngressDefaultNode, TailNode, MaxTotalDepth,
MaxQueueWaitMs, RejectionStatusCode, IncludeRetryAfter, RetryAfterSeconds, Active) plus the
child collections Rules, Nodes (each with Classes), Links, and IngressRoutes. The seeded
Default (FIFO) profile (IsDefault: true) cannot be deleted.
| Method | Path | Notes |
|---|---|---|
GET |
/v1.0/qosprofiles |
List profiles. Query: maxResults, continuationToken, nameFilter, activeFilter, optional tenantId. |
POST |
/v1.0/qosprofiles |
Create profile. Cross-tenant callers supply TenantId in the body. |
POST |
/v1.0/qosprofiles/validate |
Compile-validate a profile draft without saving; returns a ResourceValidationResult. |
GET |
/v1.0/qosprofiles/classifier-catalog |
Return the available classifier sources, operators, disciplines, and the tenant's traffic classes. |
GET |
/v1.0/qosprofiles/{id} |
Read a fully-assembled profile. Optional tenantId query. |
PUT |
/v1.0/qosprofiles/{id} |
Update profile (replaces child rows). |
DELETE |
/v1.0/qosprofiles/{id} |
Delete profile. The default profile returns 400; referencing VMRs are reassigned to the tenant default. |
Auth level: Authenticated
The tenant class catalog. Fields: Name (unique per tenant), Description, Tier
(Realtime/Interactive/AgentInteractive/BatchTimebound/BatchBackground/Default), IsSystem.
| Method | Path | Notes |
|---|---|---|
GET |
/v1.0/qostrafficclasses |
List classes. Query: maxResults, continuationToken, nameFilter, optional tenantId. |
POST |
/v1.0/qostrafficclasses |
Create a traffic class. |
GET |
/v1.0/qostrafficclasses/{id} |
Read a traffic class. |
PUT |
/v1.0/qostrafficclasses/{id} |
Update a traffic class. |
DELETE |
/v1.0/qostrafficclasses/{id} |
Delete a traffic class. |
Auth level: Authenticated
Live, read-only QoS state for each virtual model runner: whether its admission scheduler is running, how much of its capacity is in use, how many requests are waiting, per-class admission statistics, and the concurrency of its endpoints. Statistics are held in memory and reset when the server restarts; history keeps one-minute buckets for the last 24 hours.
| Method | Path | Notes |
|---|---|---|
GET |
/v1.0/qosruntime |
List a QosRuntimeSnapshot for every VMR in scope. Optional tenantId query for global administrators. |
GET |
/v1.0/qosruntime/{vmrId} |
Read one VMR's QosRuntimeSnapshot. 404 when the VMR is not in scope. |
GET |
/v1.0/qosruntime/{vmrId}/history |
Time-bucketed admission history. Query: startUtc (default one hour before endUtc), endUtc (default now), interval (minute default, 5minute, 15minute, hour). Windows longer than 24 hours return 400. |
QosRuntimeSnapshot fields:
| Field | Meaning |
|---|---|
SchedulerState |
Running; Recovering (the scheduler faulted and is restarting with backoff); PassThrough (no active profile, or the profile failed to compile, so requests are admitted without queueing); Idle (no request since server start). |
SchedulerFaultCount, LastSchedulerError, LastSchedulerErrorUtc |
Scheduler faults recovered from since server start, and the most recent one. |
Capacity, InUse |
Admission capacity (the sum of the endpoints' MaxParallelRequests; 0 = unbounded) and permits held by admitted requests. |
Waiting |
Requests currently queued. |
MaxQueueWaitMs |
The profile's queue wait deadline. |
Classes |
Per traffic class: Waiting, Admitted, Rejected (queue full), TimedOut, Aborted (client disconnected while queued), EndpointSlotTimeouts, AverageWaitMs, P95WaitMs (over the last 512 admissions), MaxWaitMs, LastAdmittedUtc, LastRejectedUtc. |
Endpoints |
Per endpoint: InFlight (across every VMR that uses it), MaxParallelRequests, IsHealthy, Active. |
QosRuntimeHistory returns Buckets, one per class per interval that had activity, each with
TimestampUtc, ClassName, Admitted, Rejected, TimedOut, Aborted, EndpointSlotTimeouts,
AverageWaitMs, MaxWaitMs, and PeakWaiting.
Auth level: TenantAdmin
For a user-facing authoring guide with rollout advice and real-world policy examples, see ACCESS_POLICIES.md.
| Method | Path | Notes |
|---|---|---|
GET |
/v1.0/modelaccesspolicies |
List policies. Query: maxResults, continuationToken, nameFilter, activeFilter, optional tenantId. |
POST |
/v1.0/modelaccesspolicies |
Create a policy with optional nested rules. Cross-tenant callers supply TenantId in the body. |
POST |
/v1.0/modelaccesspolicies/validate |
Validate a policy draft and nested rules without saving it. |
GET |
/v1.0/modelaccesspolicies/{id} |
Read a policy and its rules. Optional tenantId query. |
PUT |
/v1.0/modelaccesspolicies/{id} |
Update a policy and replace its nested rules. Cross-tenant callers supply TenantId in the body. |
DELETE |
/v1.0/modelaccesspolicies/{id} |
Delete a policy. Optional tenantId query. Returns 409 Conflict if attached to any VMR unless forceDetach=true is supplied. |
POST |
/v1.0/modelaccesspolicies/{id}/evaluate |
Evaluate a supplied ModelAccessEvaluationContext against a policy. Optional tenantId query. |
GET |
/v1.0/modelaccesspolicies/effective |
Evaluate effective access using query parameters. Query: tenantId, credentialId, userId, vmrId, modelDefinitionId, modelName, action. |
Create and update validate references to credentials, users, model definitions, and VMRs in the same tenant. Evaluation returns a ModelAccessEvaluationResult with Allowed, Decision, Mode, DefaultSource, matched policy/rule metadata, ReasonCode, ReasonText, and WouldDeny.
Example evaluation request:
{
"TenantId": "default",
"CredentialId": "cred_xxx",
"UserId": "usr_xxx",
"VirtualModelRunnerId": "vmr_xxx",
"ModelAccessPolicyId": "map_xxx",
"RequestedModel": "gpt-4o-mini",
"EffectiveModel": "gpt-4o-mini",
"Action": "Completions",
"RequestType": "OpenAIChatCompletions",
"ApiType": "OpenAI"
}Example evaluation response:
{
"Allowed": true,
"Decision": "Permit",
"Mode": "Enforce",
"DefaultSource": null,
"PolicyId": "map_xxx",
"PolicyName": "Production model access",
"RuleId": "mar_xxx",
"RuleName": "Finance credential can use chat model",
"ReasonCode": "MatchedAllowRule",
"ReasonText": "Matched model access rule 'Finance credential can use chat model'.",
"WouldDeny": false
}Proxy enforcement occurs after request/model resolution and before endpoint inventory, session affinity, load balancing, and provider calls. Authentication failures return 401; authenticated model access denials return 403. In monitor mode, denied decisions are recorded as WouldDeny=true while the request continues.
List-models responses are governed by server setting ModelAccessControl.ListModelsBehavior: Filter removes denied upstream models, Synthesize returns a provider-shaped list from allowed active VMR model definitions, and RawPassThrough leaves upstream responses unchanged.
Label subject/resource rules can match a literal label by SubjectId or ResourceId, or by selectors such as { "label": "finance" } and { "labels": "finance,production" }. ModelName rules can match exact names with ResourceId, or text selectors such as { "equals": "gpt-4o-mini" }, { "prefix": "gpt-4" }, and { "contains": "70b" }.
Example policy patterns:
Default deny with a credential allow-list:
{
"TenantId": "default",
"Name": "Credential allow-list",
"DefaultDecision": "Deny",
"Rules": [
{
"Name": "Primary credential can use chat model",
"Priority": 100,
"Effect": "Allow",
"SubjectType": "Credential",
"SubjectId": "cred_xxx",
"ResourceType": "ModelDefinition",
"ResourceId": "md_chat",
"Actions": ["Completions", "ListModels"],
"Active": true
}
],
"Active": true
}Label-based access:
{
"Name": "Finance label access",
"DefaultDecision": "Deny",
"Rules": [
{
"Name": "Finance subjects can use finance models",
"Priority": 100,
"Effect": "Allow",
"SubjectType": "CredentialLabel",
"SubjectSelector": { "label": "finance" },
"ResourceType": "ModelLabel",
"ResourceSelector": { "label": "finance" },
"Actions": ["Completions", "Embeddings", "ListModels"],
"Active": true
}
]
}Embeddings-only access:
{
"Name": "Embeddings only",
"DefaultDecision": "Deny",
"Rules": [
{
"Name": "Allow embeddings model",
"Priority": 100,
"Effect": "Allow",
"SubjectType": "Any",
"ResourceType": "ModelName",
"ResourceId": "text-embedding-004",
"Actions": ["Embeddings", "ListModels"],
"Active": true
}
]
}List-model filtering uses the same ListModels action. Include ListModels in allow rules for models that should be visible when ModelAccessControl.ListModelsBehavior is Filter or Synthesize.
For monitor-mode rollout, configure ModelAccessControl.Enabled=true and ModelAccessControl.Mode=Monitor, attach the policy to selected VMRs, and inspect request history for ModelAccessWouldDeny=true before switching to Enforce.
Auth level: TenantAdmin for create, update, deactivate, and validate. Auth level: Authenticated for read, list, and effective-access evaluation.
VMR reservations are tenant-scoped time windows that block VMR admission for every identity except explicitly listed users and credentials. Outside an active reservation or admission drain window, VMR access is unchanged and continues through normal tenant, VMR, request-type, ACL, model access, routing, and endpoint checks.
For an operator and implementation guide, see MANAGING_RESERVATIONS.md.
The dashboard exposes these routes through the Reservations workspace. The table supports refresh, filtering, row-click editing, row-level JSON inspection, create/edit/deactivate workflows, validation, and effective-access evaluation for a candidate user or credential.
Tenant-scoped authenticated callers are resolved to their tenant automatically. System-admin or cross-tenant callers should include tenantId in query strings or request bodies when operating on a specific tenant; omitting tenantId on list-style routes returns cross-tenant results only for callers authorized to see them.
| Method | Path | Notes |
|---|---|---|
GET |
/v1.0/vmrreservations |
List reservations. Query: tenantId, vmrId, state, subjectType, subjectId, startsBeforeUtc, endsAfterUtc, nameFilter, activeFilter, maxResults, continuationToken. Tenant callers may omit tenantId; system admins may omit tenantId to list all tenants. |
POST |
/v1.0/vmrreservations |
Create a reservation with nested Subjects. Cross-tenant callers supply TenantId in the body. |
POST |
/v1.0/vmrreservations/validate |
Validate a reservation draft and participant list without saving it. |
GET |
/v1.0/vmrreservations/{id} |
Read a reservation and its participants. Tenant callers may omit tenantId; system admins should pass tenantId. |
PUT |
/v1.0/vmrreservations/{id} |
Update a reservation and replace its participant list. |
DELETE |
/v1.0/vmrreservations/{id} |
Soft deactivate a reservation. Tenant callers may omit tenantId; system admins should pass tenantId. |
GET |
/v1.0/virtualmodelrunners/{id}/reservations |
List reservations scoped to one VMR. Tenant callers may omit tenantId; system admins may omit tenantId to search all tenants by globally unique VMR id. |
GET |
/v1.0/virtualmodelrunners/{id}/reservation-effective |
Evaluate whether a user or credential would pass the reservation gate. Query: tenantId, userId, credentialId, atUtc. System admins should pass tenantId; tenant callers may omit it. |
Reservation request shape:
{
"TenantId": "ten_xxx",
"VirtualModelRunnerId": "vmr_xxx",
"Name": "Customer demo window",
"Description": "Reserved capacity for evaluation team",
"StartUtc": "2026-06-16T17:00:00Z",
"EndUtc": "2026-06-16T19:00:00Z",
"AdmissionDrainLeadMs": 300000,
"Active": true,
"Subjects": [
{ "SubjectType": "User", "SubjectId": "usr_xxx" },
{ "SubjectType": "Credential", "SubjectId": "cred_xxx" }
]
}During an active reservation, a credential subject admits only that credential. A user subject admits that user and credentials owned by that user when the credential owner can be resolved. Reservation allow decisions do not bypass model access policies or ACLs.
Nonparticipant requests are denied before endpoint inventory, session affinity, load balancing, and upstream provider calls. Denials return:
401 ReservationAuthenticationRequiredwhen a reserved VMR receives an unauthenticated request.403 ReservationDeniedwhen a nonparticipant calls during the active window.403 ReservationDrainDeniedwhen a nonparticipant calls during the configured admission drain window.503 ReservationConflictif multiple active reservations somehow overlap at runtime.
The server writes reservation-denial log messages with tenant, VMR, reservation id, request user, request credential, UTC window, and reason code. Request history and request analytics also persist nullable reservation dimensions: ReservationGuid, ReservationName, ReservationDecision, ReservationReasonCode, ReservationWindowStartUtc, and ReservationWindowEndUtc. Search, summary, and analytics overview routes accept reservationGuid, reservationDecision, and reservationReasonCode filters for reservation-denial investigations.
Auth level: Authenticated
| Method | Path | Notes |
|---|---|---|
GET |
/v1.0/virtualmodelrunners |
List VMRs. Query: maxResults, continuationToken, nameFilter, activeFilter, optional tenantId. |
POST |
/v1.0/virtualmodelrunners |
Create VMR. Cross-tenant callers supply TenantId in the body. BasePath must be /v1.0/api/{name}/. |
POST |
/v1.0/virtualmodelrunners/validate |
Validate a VMR draft without saving it. Optional query: tenantId, existingId. |
GET |
/v1.0/virtualmodelrunners/{id} |
Read VMR. Optional tenantId query. |
PUT |
/v1.0/virtualmodelrunners/{id} |
Update VMR. Cross-tenant callers supply TenantId in the body. BasePath must stay /v1.0/api/{name}/. |
DELETE |
/v1.0/virtualmodelrunners/{id} |
Delete VMR. Optional tenantId query. |
GET |
/v1.0/virtualmodelrunners/{id}/health |
Get aggregated health for the VMR and its endpoints. Optional tenantId query. |
GET |
/v1.0/virtualmodelrunners/{id}/effective |
Return the resolved read-only effective configuration for the VMR. Optional tenantId query. |
GET |
/v1.0/virtualmodelrunners/{id}/runtime-stats |
Return in-memory endpoint runtime stats for the VMR. Optional tenantId query. |
POST |
/v1.0/virtualmodelrunners/{id}/runtime-stats/reset |
Reset in-memory runtime stats for the VMR or one endpoint. Optional tenantId query. Body may include EndpointId. |
POST |
/v1.0/virtualmodelrunners/{id}/runtime-backoff/clear |
Clear transient runtime backoff for the VMR or one endpoint. Optional tenantId query. Body may include EndpointId. |
POST |
/v1.0/virtualmodelrunners/{id}/explain-routing |
Simulate routing for a representative request. Optional tenantId query. |
POST |
/v1.0/virtualmodelrunners/{id}/load-model |
Tenant-admin route to resolve VMR targets, then load or verify a model. Optional tenantId query. |
VMR health response fields include:
VirtualModelRunnerIdVirtualModelRunnerNameCheckedUtcOverallHealthyHealthyEndpointCountDrainingEndpointCountQuarantinedEndpointCountTotalEndpointCountActiveSessionCountEndpoints
Validation routes return a ResourceValidationResult with Errors and Warnings. The VMR effective response resolves the endpoint inventory, request permissions, session-affinity settings, attached policy metadata, model definitions, model configurations, adaptive settings, endpoint groups, and ModelConfigurationMappings that the proxy path will use. Runtime stats responses return EndpointRuntimeStatsCollection with per-endpoint pending count, completed count, success/error EWMA, latency EWMA, TTFT EWMA, last status/error, consecutive failures, transient backoff state, and recency timestamps. The VMR explain-routing response returns a RoutingDecision containing a timeline, selected endpoint, selection strategy, endpoint group, adaptive score evidence, session-affinity outcome, policy metadata, mutation summary, and per-candidate evidence.
Auth level: TenantAdmin
Model loading is a management-plane operation. It can consume GPU memory on local runners and can trigger billable upstream calls when an operator explicitly selects a hosted-provider generation or embedding probe.
Model loading calls are not proxied VMR inference requests and are not written to request history. Use the typed response, server logs, and conductor_model_load_* Prometheus metrics for audit and troubleshooting.
Routes:
| Method | Path | Notes |
|---|---|---|
POST |
/v1.0/modelrunnerendpoints/{id}/load-model |
Load or verify a model on one concrete endpoint. Direct endpoint loading is allowed even when the endpoint is inactive, so operators can warm before resuming traffic. |
POST |
/v1.0/virtualmodelrunners/{id}/load-model |
Resolve the VMR model and endpoint target set, then load or verify the model. Inactive endpoints are skipped unless IncludeInactive=true. |
Request body:
{
"Model": "gemma3:4b",
"ModelDefinitionId": null,
"ProbeKind": "Auto",
"TargetMode": "SelectedEndpoint",
"EndpointIds": [],
"InputText": "conductor warmup",
"KeepAlive": "30m",
"TimeoutMs": 300000,
"MaxRetries": 0,
"VerifyLoaded": true,
"IncludeInactive": false,
"DryRun": false
}Fields:
| Field | Notes |
|---|---|
Model |
Required for direct endpoint loading. For VMR loading it may be omitted only when exactly one active attached ModelDefinition exists. |
ModelDefinitionId |
Optional VMR selector. If supplied, Model must be empty or match the definition name. |
ProbeKind |
Auto, MetadataOnly, ChatCompletion, Completion, Embeddings, or NativeGenerate. |
TargetMode |
VMR only: SelectedEndpoint, AllEligibleEndpoints, AllConfiguredEndpoints, or SpecificEndpointIds. |
EndpointIds |
Required only when TargetMode=SpecificEndpointIds; IDs must already be attached to the VMR. |
InputText |
Tiny non-sensitive probe text. It may be sent to hosted providers for explicit generation or embedding probes. |
KeepAlive |
Ollama retention hint. Other providers report it in IgnoredFields. |
TimeoutMs |
Per-attempt upstream timeout, clamped by the server from 1,000 to 1,800,000 ms. |
MaxRetries |
Per-endpoint retry count, clamped from 0 to 3. |
VerifyLoaded |
Runs provider-specific verification after a probe, such as Ollama /api/ps or metadata list checks. |
IncludeInactive |
VMR target selection includes inactive configured endpoints when true. |
DryRun |
Returns the planned mechanism and target endpoints without sending upstream traffic. |
Response body:
{
"Success": true,
"TenantId": "default",
"TargetType": "ModelRunnerEndpoint",
"TargetId": "mre_123",
"Model": "gemma3:4b",
"ProbeKind": "Auto",
"OutcomeCode": "Loaded",
"Message": "Model load probe completed on 1 of 1 endpoint(s).",
"DurationMs": 4211,
"EndpointResults": [
{
"EndpointId": "mre_123",
"EndpointName": "gpu-host-01",
"ApiType": "Ollama",
"BaseUrl": "http://gpu-host-01:11434",
"Success": true,
"OutcomeCode": "Loaded",
"ProviderStatusCode": 200,
"Mechanism": "OllamaGenerate",
"RequestPath": "/api/generate",
"DurationMs": 4211,
"VerifiedLoaded": true,
"IgnoredFields": [],
"ErrorMessage": null
}
]
}Stable outcome codes include Loaded, AlreadyAvailable, Verified, VerifiedRemote, DryRun, Skipped, Failed, TimedOut, UnauthorizedUpstream, ModelRequired, ModelNotAttached, NoEligibleEndpoints, and UnsupportedApiType.
Provider behavior:
| Provider | Auto behavior |
Result semantics |
|---|---|---|
| Ollama | POST /api/generate with minimal output and optional keep_alive; embeddings use /api/embed. |
Loaded or AlreadyAvailable when /api/ps confirms residency. Missing models fail; Conductor does not pull models. |
| vLLM | GET /v1/models metadata verification unless an explicit probe is requested. |
Verified when the model is served. Explicit probes can warm tokenization or graph paths, but do not load arbitrary new weights. |
| OpenAI | GET /v1/models metadata verification unless an explicit probe is requested. |
VerifiedRemote; hosted OpenAI has no host-local load primitive. Explicit generation or embedding probes may be billable. |
| Gemini | GET /v1beta/models metadata verification unless an explicit probe is requested. |
VerifiedRemote; hosted Gemini has no host-local load primitive. Explicit generation or embedding probes may be billable. |
Auth level: GlobalAdmin
Both global admin users and system administrators can use these routes.
| Method | Path | Notes |
|---|---|---|
GET |
/v1.0/backup |
Export all configuration data into a BackupPackage. |
POST |
/v1.0/backup/validate |
Validate a backup package without applying it. Request body is a BackupPackage. Uses the same shared validators as create, update, and restore flows. |
POST |
/v1.0/backup/restore |
Restore from a package. Request body is a RestoreRequest. |
Backup package shape:
{
"SchemaVersion": "1.4",
"CreatedUtc": "2026-05-18T12:00:00Z",
"SourceInstance": "host-name",
"CreatedBy": "admin@example.com",
"Tenants": [],
"Users": [],
"Credentials": [],
"ModelDefinitions": [],
"ModelConfigurations": [],
"ModelRunnerEndpoints": [],
"EndpointGroups": [],
"VirtualModelRunners": [],
"VirtualModelRunnerReservations": [],
"LoadBalancingPolicies": [],
"ModelAccessPolicies": [],
"ModelAccessRules": [],
"Administrators": []
}Backups include endpoint groups, VMR reservations, and nested reservation subjects. Validation checks endpoint group endpoint membership plus reservation tenant, VMR, user, credential, subject, and overlap rules before restore; restore uses the same Skip, Overwrite, or Fail conflict mode as the other configuration entities.
Restore request shape:
{
"Package": {},
"Options": {
"ConflictResolution": "Skip", // Skip, Overwrite, Fail
"RestoreAdministrators": false,
"RestoreCredentials": true,
"TenantFilter": []
}
}Validation response shape:
{
"IsValid": true,
"Errors": [],
"Conflicts": [],
"Summary": {
"TenantCount": 0,
"UserCount": 0,
"CredentialCount": 0,
"ModelDefinitionCount": 0,
"ModelConfigurationCount": 0,
"ModelRunnerEndpointCount": 0,
"EndpointGroupCount": 0,
"VirtualModelRunnerCount": 0,
"VirtualModelRunnerReservationCount": 0,
"AdministratorCount": 0,
"LoadBalancingPolicyCount": 0,
"ModelAccessPolicyCount": 0,
"ModelAccessRuleCount": 0
}
}Restore response shape:
{
"Success": true,
"ErrorMessage": null,
"Summary": {
"Tenants": { "Created": 0, "Updated": 0, "Skipped": 0, "Failed": 0 },
"Users": { "Created": 0, "Updated": 0, "Skipped": 0, "Failed": 0 },
"Credentials": { "Created": 0, "Updated": 0, "Skipped": 0, "Failed": 0 },
"ModelDefinitions": { "Created": 0, "Updated": 0, "Skipped": 0, "Failed": 0 },
"ModelConfigurations": { "Created": 0, "Updated": 0, "Skipped": 0, "Failed": 0 },
"ModelRunnerEndpoints": { "Created": 0, "Updated": 0, "Skipped": 0, "Failed": 0 },
"EndpointGroups": { "Created": 0, "Updated": 0, "Skipped": 0, "Failed": 0 },
"VirtualModelRunners": { "Created": 0, "Updated": 0, "Skipped": 0, "Failed": 0 },
"VirtualModelRunnerReservations": { "Created": 0, "Updated": 0, "Skipped": 0, "Failed": 0 },
"Administrators": { "Created": 0, "Updated": 0, "Skipped": 0, "Failed": 0 },
"LoadBalancingPolicies": { "Created": 0, "Updated": 0, "Skipped": 0, "Failed": 0 },
"ModelAccessPolicies": { "Created": 0, "Updated": 0, "Skipped": 0, "Failed": 0 },
"ModelAccessRules": { "Created": 0, "Updated": 0, "Skipped": 0, "Failed": 0 }
},
"Warnings": []
}Auth level: Authenticated
Request history routes are registered only when request history is enabled in server settings. When it is disabled, /v1.0/requesthistory/summary, /v1.0/requesthistory/analytics/overview, and /v1.0/analytics/* aggregate routes remain available and return empty payloads.
| Method | Path | Notes |
|---|---|---|
GET |
/v1.0/requesthistory/analytics/overview |
Chart-ready aggregate analytics. Query: tenantId, range, startUtc, endUtc, bucketSeconds, limit, vmrGuid, endpointGuid, providerName, modelName, modelAccessPolicyGuid, modelAccessRuleGuid, modelAccessDecision, modelAccessWouldDeny, reservationGuid, reservationDecision, reservationReasonCode, stageKind, statusClass. |
GET |
/v1.0/requesthistory/summary |
Aggregated time buckets. Query: tenantId, vmrGuid, endpointGuid, requestorUserGuid, credentialGuid, loadBalancingPolicyGuid, modelAccessPolicyGuid, modelAccessRuleGuid, modelAccessDecision, modelAccessWouldDeny, modelName, mutationSummary, denialReasonCode, reservationGuid, reservationDecision, reservationReasonCode, sessionAffinityOutcome, statusClass, sourceIp, httpStatus, startUtc, endUtc, interval. |
GET |
/v1.0/requesthistory |
Search entries. Query: tenantId, vmrGuid, endpointGuid, requestorUserGuid, credentialGuid, loadBalancingPolicyGuid, modelAccessPolicyGuid, modelAccessRuleGuid, modelAccessDecision, modelAccessWouldDeny, modelName, mutationSummary, denialReasonCode, reservationGuid, reservationDecision, reservationReasonCode, sessionAffinityOutcome, statusClass, sourceIp, httpStatus, createdAfterUtc, createdBeforeUtc, page, pageSize. |
GET |
/v1.0/requesthistory/{id} |
Read entry metadata. Query: optional tenantId for cross-tenant callers. |
GET |
/v1.0/requesthistory/{id}/detail |
Read full request/response detail. Query: optional tenantId. |
GET |
/v1.0/requesthistory/{id}/analytics |
Read normalized analytics events for one request history entry. Query: optional tenantId. |
DELETE |
/v1.0/requesthistory/{id} |
Delete one entry. Query: optional tenantId. |
POST |
/v1.0/requesthistory/delete |
Delete selected entries by ID. Body: { "Ids": ["req_..."] }. Query: optional tenantId. |
DELETE |
/v1.0/requesthistory/bulk |
Bulk delete by filter. Query: tenantId, vmrGuid, endpointGuid, requestorUserGuid, credentialGuid, loadBalancingPolicyGuid, modelName, mutationSummary, denialReasonCode, reservationGuid, reservationDecision, reservationReasonCode, sessionAffinityOutcome, statusClass, sourceIp, httpStatus, createdAfterUtc, createdBeforeUtc. |
Summary interval values:
minute15minutehour6hourday
Search response shape:
{
"Data": [],
"Page": 1,
"PageSize": 10,
"TotalCount": 0,
"TotalPages": 0
}Selected delete response shape:
{
"DeletedCount": 2
}Summary response shape:
{
"Data": [
{
"TimestampUtc": "2026-05-18T12:00:00Z",
"SuccessCount": 120,
"FailureCount": 3,
"TotalCount": 123
}
],
"StartUtc": "2026-05-18T11:00:00Z",
"EndUtc": "2026-05-18T12:00:00Z",
"Interval": "hour",
"TotalSuccess": 120,
"TotalFailure": 3,
"StatusClassCounts": {
"2xx": 120,
"5xx": 3
},
"DenialReasonCounts": {
"AllEndpointsAtCapacity": 2,
"PolicyRejected": 1
},
"SessionAffinityOutcomeCounts": {
"Hit": 40,
"Miss": 83
},
"TotalRequests": 123
}Analytics overview response shape:
{
"StartUtc": "2026-06-05T00:00:00Z",
"EndUtc": "2026-06-06T00:00:00Z",
"BucketSeconds": 900,
"TotalRequests": 123,
"SuccessCount": 120,
"FailureCount": 3,
"AnalyticsCapturedCount": 118,
"AnalyticsCoveragePercent": 95.93,
"ReservationDeniedCount": 2,
"ReservationDenialCounts": {
"vmrr_xxx": 2
},
"AverageDurationMs": 842.4,
"P50DurationMs": 600,
"P95DurationMs": 1900,
"P99DurationMs": 3200,
"TotalTokens": 456789,
"AverageTokensPerSecond": 42.5,
"TimeSeries": [],
"StageBreakdown": [],
"EndpointSummaries": [],
"SlowestRequests": []
}Analytics stage events use stable StageKind values such as routing, capacity_wait, upstream_headers, first_token_wait, generation, completion, provider_load, provider_prompt_eval, and provider_generation. Provider-native timings are best-effort and missing values are returned as null, not zero.
Request history entry fields include:
IdTenantGuidVirtualModelRunnerGuidVirtualModelRunnerNameRequestorUserGuidRequestorUserEmailCredentialGuidCredentialNameLoadBalancingPolicyGuidLoadBalancingPolicyNameModelAccessPolicyGuidModelAccessPolicyNameModelAccessRuleGuidModelAccessRuleNameModelAccessDecisionModelAccessWouldDenyModelEndpointGuidModelEndpointNameModelEndpointUrlModelDefinitionGuidModelDefinitionNameModelConfigurationGuidRequestedModelEffectiveModelRequestTypeRoutingOutcomeCodeDenialReasonCodeDenialReasonReservationGuidReservationNameReservationDecisionReservationReasonCodeReservationWindowStartUtcReservationWindowEndUtcSessionAffinityOutcomeMutationSummaryExplanationSummaryRequestBodyRetainedRequestBodyRedactedRequestHeadersRedactedResponseBodyRetainedResponseBodyRedactedResponseHeadersRedactedRequestorSourceIpHttpMethodHttpUrlRequestBodyLengthResponseBodyLengthHttpStatusFirstTokenTimeMsResponseTimeMsTraceIdProviderRequestIdProviderNamePromptTokensCompletionTokensTotalTokensTokensPerSecondOverallTokensPerSecondGenerationAnalyticsCapturedAnalyticsVersionDominantStageKindDominantStageDurationMsAnalyticsFailureCodeObjectKeyRequestTransferTypeResponseTransferTypeCreatedUtcCompletedUtc
Detail responses extend the entry with:
RequestHeadersRequestBodyRequestBodyTruncatedResponseHeadersResponseBodyResponseBodyTruncatedRoutingDecision
If request or response bodies have aged past BodyRetentionDays, detail records remain readable but the body content is scrubbed while the searchable routing and latency metadata stays available until MetadataRetentionDays expires.
Auth level: TenantAdmin or SystemAdmin
The Analytics workspace API is the dashboard-oriented reporting surface for TTFT, token usage, estimate-only cost, user/model/endpoint breakdowns, and failed-request-type counts. It is separate from /v1.0/requesthistory/analytics/*, which exposes trace-linked per-request timing stages. See ADR 0002 for the accepted first-release design.
System administrators can query globally or pass tenantId to restrict results to one tenant. Tenant administrators and other tenant-scoped callers are forced into their authenticated tenant scope even if they pass a different tenantId. First-release analytics data is bounded to the last 30 days.
| Method | Path | Notes |
|---|---|---|
GET |
/v1.0/analytics/catalog |
Supported metrics, dimensions, named ranges, granularities, retention, and unavailable future export formats. |
POST |
/v1.0/analytics/query |
General analytics query. Body: AnalyticsQueryRequest. |
GET |
/v1.0/analytics/reports |
List saved reports. Query: tenantId, maxResults, continuationToken, nameFilter, ownerUserId. |
POST |
/v1.0/analytics/reports |
Create saved report. Body: AnalyticsSavedReport. |
GET |
/v1.0/analytics/reports/{id} |
Read saved report. Query: optional tenantId for system administrators. |
PUT |
/v1.0/analytics/reports/{id} |
Update saved report. Body: AnalyticsSavedReport. |
DELETE |
/v1.0/analytics/reports/{id} |
Delete saved report. Query: optional tenantId for system administrators. |
GET |
/v1.0/analytics/summary |
Convenience summary query. |
GET |
/v1.0/analytics/timeseries |
Convenience time-series query. |
GET |
/v1.0/analytics/ttft |
TTFT-focused query; defaults to grouping by user. |
GET |
/v1.0/analytics/tokens |
Token-usage query; defaults to grouping by effective model. |
GET |
/v1.0/analytics/costs |
Estimate-only cost query; defaults to grouping by user. |
GET |
/v1.0/analytics/users |
User-oriented usage query. |
GET |
/v1.0/analytics/access |
Access/reliability query for success, failure, denied, and rate-limited counts. |
Analytics routes resolve to RequestTypeEnum.ReadAnalytics. System administrators can query global scope and may filter to a tenant with tenantId. Tenant administrators and tenant users granted analytics.read are forced into their authenticated tenant scope. Grant first-release dedicated Analytics access by adding the analytics.read user label, or by setting a user tag such as analytics.read=true or permissions=analytics.read.
GET query parameters:
| Parameter | Type | Notes |
|---|---|---|
tenantId |
string | Optional tenant filter for system administrators only. |
range |
string | lastHour, lastDay, lastWeek, lastMonth, or custom. Default lastDay. |
startUtc |
string | Custom start timestamp, UTC ISO 8601. Used with endUtc; clamped to the 30-day retained window. |
endUtc |
string | Custom end timestamp, UTC ISO 8601. |
bucketSeconds |
integer | Bucket size. Common values: 60, 900, 3600, 21600, 86400. |
timezone |
string | Display timezone hint. Aggregation remains UTC in the first release. |
limit |
integer | Maximum raw request-history rows to scan. Server caps the value. |
tokenUnitCost |
decimal | Optional per-token unit cost used for estimate-only cost. GET parsing ignores invalid or negative values; POST query validation rejects negative values. |
costCurrency |
string | Optional display label such as USD, EUR, or estimate. |
groupBy |
string | One dimension: TenantId, RequestedModel, EffectiveModel, ModelDefinitionId, ModelRunnerEndpointId, VirtualModelRunnerId, RequestorUserId, CredentialId, ProviderName, ReservationGuid, ReservationName, ReservationDecision, or ReservationReasonCode. |
vmrGuid |
string | Filter by Virtual Model Runner ID. CSV values are accepted. |
endpointGuid |
string | Filter by model runner endpoint ID. CSV values are accepted. |
modelName |
string | Filter by requested, effective, or model-definition name. CSV values are accepted. |
requestorUserGuid / userId |
string | Filter by user ID. CSV values are accepted. |
credentialGuid / credentialId |
string | Filter by credential ID. CSV values are accepted. |
providerName |
string | Filter by provider family/name. CSV values are accepted. |
reservationGuid / reservationId |
string | Filter by VMR reservation ID. CSV values are accepted. |
reservationDecision |
string | Filter by reservation gate decision, such as Allowed, Denied, NoReservation, or Conflict. CSV values are accepted. |
reservationReasonCode |
string | Filter by reservation reason, such as ReservationDenied, ReservationDrainDenied, ReservationAuthenticationRequired, or ReservationConflict. CSV values are accepted. |
statusClass |
string | Filter by HTTP status class such as 2xx, 4xx, or 5xx. CSV values are accepted. |
stageKind |
string | Filter by normalized dominant stage kind where request analytics capture is available, such as routing, first_token_wait, generation, completion, or denial. |
modelAccessWouldDeny |
boolean | Filter model-access monitor-mode would-deny rows. |
successfulCompletionsOnly |
boolean | Usage-style metrics use successful completions by default. |
AnalyticsQueryRequest shape:
{
"TenantId": "tenant_123",
"Range": "lastDay",
"StartUtc": null,
"EndUtc": null,
"BucketSeconds": 3600,
"Timezone": "UTC",
"TokenUnitCost": 0.00001,
"CostCurrency": "USD",
"Metrics": [
"latency.ttft.avg",
"tokens.total",
"cost.estimated"
],
"GroupBy": [
"RequestorUserId"
],
"Filters": {
"VirtualModelRunnerIds": [
"vmr_123"
],
"ModelRunnerEndpointIds": [],
"ModelNames": [],
"RequestorUserIds": [],
"CredentialIds": [],
"ProviderNames": [],
"ReservationIds": [],
"ReservationDecisions": [],
"ReservationReasonCodes": [],
"StatusClasses": [],
"StageKinds": [],
"ModelAccessWouldDeny": null,
"SuccessfulCompletionsOnly": true
},
"Limit": 10000,
"ContinuationToken": null
}AnalyticsQueryResult shape:
{
"TenantId": "tenant_123",
"IsGlobalScope": false,
"StartUtc": "2026-06-13T00:00:00Z",
"EndUtc": "2026-06-14T00:00:00Z",
"BucketSeconds": 3600,
"RetentionDays": 30,
"TotalRequests": 120,
"SuccessfulCompletionCount": 118,
"FailedRequestCount": 2,
"DeniedRequestCount": 1,
"ReservationDeniedCount": 1,
"ReservationDenialCounts": {
"vmrr_123": 1
},
"RateLimitedRequestCount": 1,
"AverageTimeToFirstTokenMs": 214.5,
"P50TimeToFirstTokenMs": 180,
"P95TimeToFirstTokenMs": 490,
"P99TimeToFirstTokenMs": 850,
"PromptTokens": 240000,
"CompletionTokens": 62000,
"TotalTokens": 302000,
"CachedTokens": null,
"MultimodalTokens": null,
"UnknownTokenUsageCount": 3,
"TokenUnitCost": 0.00001,
"CostCurrency": "USD",
"EstimatedCost": 3.02,
"TimeSeries": [
{
"TimestampUtc": "2026-06-13T12:00:00Z",
"RequestCount": 20,
"SuccessfulCompletionCount": 19,
"FailedRequestCount": 1,
"DeniedRequestCount": 0,
"RateLimitedRequestCount": 1,
"AverageTimeToFirstTokenMs": 230.0,
"PromptTokens": 42000,
"CompletionTokens": 12000,
"TotalTokens": 54000,
"CachedTokens": null,
"MultimodalTokens": null,
"UnknownTokenUsageCount": 0,
"EstimatedCost": 0.54
}
],
"Groups": [
{
"Dimension": "RequestorUserId",
"Value": "usr_123",
"Label": "operator@example.com",
"RequestCount": 20,
"SuccessfulCompletionCount": 19,
"FailedRequestCount": 1,
"DeniedRequestCount": 0,
"RateLimitedRequestCount": 1,
"AverageTimeToFirstTokenMs": 230.0,
"P95TimeToFirstTokenMs": 490,
"TotalTokens": 54000,
"UnknownTokenUsageCount": 0,
"TimeToFirstTokenCoveragePercent": 100.0,
"EstimatedCost": 0.54,
"LastSeenUtc": "2026-06-13T12:57:00Z"
}
]
}Cost is estimate-only: Conductor multiplies successful reported token usage by the caller-supplied tokenUnitCost. It does not model provider price books, cached-token discounts, multimodal pricing, account credits, taxes, currency conversion, or provider invoice rounding. Missing provider usage is reported through UnknownTokenUsageCount, not treated as zero. Cached and multimodal token fields are nullable until provider parsers persist those categories. Grouped summaries include failure, denial, rate-limit, unknown-token, TTFT coverage, and last-seen fields so dashboards can answer user and credential breakdown questions without separate request-history reads.
AnalyticsSavedReport shape:
{
"Id": "asr_123",
"TenantId": "tenant_123",
"OwnerUserId": "usr_123",
"Name": "Daily user cost",
"Description": "Estimate user token cost over the last day.",
"Scope": "Tenant",
"Query": {
"Range": "lastDay",
"BucketSeconds": 3600,
"TokenUnitCost": 0.00001,
"CostCurrency": "USD",
"GroupBy": [
"RequestorUserId"
],
"Filters": {
"RequestorUserIds": [
"usr_123"
],
"SuccessfulCompletionsOnly": true
},
"Limit": 10000
},
"DisplayState": {
"workspace": "Analytics",
"chart": "VolumeAndTtft"
},
"Labels": [
"analytics"
],
"Tags": {
"range": "lastDay"
},
"CreatedUtc": "2026-06-14T10:00:00Z",
"LastUpdateUtc": "2026-06-14T10:00:00Z"
}Saved reports can be global (TenantId null, system-admin scope) or tenant-scoped. Tenant administrators cannot create or load reports outside their authenticated tenant. Saved reports store query and display-state definitions only; they do not schedule execution or snapshot historical results.
Export endpoints are not included in the first route slice. The catalog returns export formats as unavailable until those APIs are implemented.
Auth level: Authenticated
| Method | Path | Notes |
|---|---|---|
GET |
/v1.0/observability/metrics |
Prometheus text exposition for low-cardinality operational metrics. |
GET |
/v1.0/observability/metrics/summary |
JSON snapshot of counters and latency summaries grouped overall and by VMR. |
The export includes counters and histograms such as conductor_requests_total, conductor_denials_total, conductor_policy_fallbacks_total, conductor_session_affinity_total, conductor_saturation_denials_total, conductor_telemetry_freshness_failures_total, conductor_route_decision_duration_ms, conductor_total_duration_ms, and conductor_first_token_time_ms.
These are not fixed management routes. They are mounted dynamically under each VMR's BasePath.
If a VMR has:
/v1.0/api/my-vmr/
then the proxy surface begins there.
Available when the VMR ApiType is OpenAI.
Typical proxied routes:
POST /v1.0/api/{vmr}/v1/chat/completionsPOST /v1.0/api/{vmr}/v1/completionsGET /v1.0/api/{vmr}/v1/modelsPOST /v1.0/api/{vmr}/v1/embeddings
Available when the VMR ApiType is vLLM.
Conductor uses the OpenAI-compatible surface:
POST /v1.0/api/{vmr}/v1/chat/completionsPOST /v1.0/api/{vmr}/v1/completionsGET /v1.0/api/{vmr}/v1/modelsPOST /v1.0/api/{vmr}/v1/embeddings
Available when the VMR ApiType is Gemini.
Typical proxied routes:
POST /v1.0/api/{vmr}/v1beta/models/{model}:generateContentPOST /v1.0/api/{vmr}/v1beta/models/{model}:streamGenerateContentPOST /v1.0/api/{vmr}/v1beta/models/{model}:embedContentGET /v1.0/api/{vmr}/v1beta/models
Available when the VMR ApiType is Ollama.
Typical proxied routes:
POST /v1.0/api/{vmr}/api/generatePOST /v1.0/api/{vmr}/api/chatGET /v1.0/api/{vmr}/api/tagsPOST /v1.0/api/{vmr}/api/embedPOST /v1.0/api/{vmr}/api/embeddingsPOST /v1.0/api/{vmr}/api/pullDELETE /v1.0/api/{vmr}/api/deleteGET /v1.0/api/{vmr}/api/psPOST /v1.0/api/{vmr}/api/show
These VMR fields affect proxied behavior:
| Field | Meaning |
|---|---|
LoadBalancingMode |
Built-in selection mode used directly or as a policy fallback. Supported values: RoundRobin, Random, FirstAvailable, LeastRecentlyUsed, Adaptive. |
LoadBalancingPolicyId |
Optional advanced policy attachment. |
AdaptiveLoadBalancing |
Optional adaptive scoring settings used when LoadBalancingMode is Adaptive. |
EndpointGroupIds |
Optional reusable endpoint group attachments evaluated before the final selection strategy. |
EndpointGroups |
Legacy inline priority or traffic-split endpoint groups retained for compatibility. Prefer EndpointGroupIds. |
AllowEmbeddings |
If false, embedding routes are rejected. |
AllowCompletions |
If false, completion/chat routes are rejected. |
AllowModelManagement |
If false, model management routes such as list/pull/delete are rejected. |
StrictMode |
If true, only attached ModelDefinitions are accepted. |
SessionAffinityMode |
Enables sticky routing by source IP, API key, or a custom header. |
TimeoutMs |
Maximum proxy wait time per request. |
GET or HEAD on a VMR's base URL (/v1.0/api/{vmr}/ or /v1.0/api/{vmr}) is a health probe. It needs
no authentication, never enters a QoS queue, does not count against any endpoint's MaxParallelRequests,
and never reaches a model runner. It returns 204 when at least one of the VMR's endpoints is active, in
the Normal service state, and passing its health checks, and 503 otherwise (with a JSON error body for
GET). Point monitors and health checkers at this URL instead of at /v1/models or /api/tags.
Every proxied request is admitted through the VMR's QoS profile (the tenant's Default (FIFO) profile
unless another is linked):
- When every endpoint is at
MaxParallelRequests, the request queues in its traffic class instead of being rejected immediately. It is released in the profile's scheduling order as capacity frees. - An admitted request that finds its endpoint busy (for example, because another VMR shares the
endpoint) waits for a free slot until the profile's
MaxQueueWaitMsdeadline, measured from arrival. - A request that is not admitted gets the profile's
RejectionStatusCode(default429) withRetry-After:QosRejectedwhen the queue is full,QosTimedOutwhen it waited pastMaxQueueWaitMs, andEndpointAtCapacitywhen no endpoint slot freed before the deadline. These outcomes are recorded in request history with the denial reason and aQosAdmissiontimeline stage.
curl -X POST http://localhost:9000/v1.0/tenants \
-H "Content-Type: application/json" \
-H "x-admin-email: admin@example.com" \
-H "x-admin-password: secret" \
-d '{"Name":"Production"}'curl -X POST http://localhost:9000/v1.0/auth/login/credential \
-H "Content-Type: application/json" \
-d '{"TenantId":"default","Email":"admin@conductor","Password":"password"}'curl -X POST http://localhost:9000/v1.0/loadbalancingpolicies \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_TOKEN" \
-d '{
"Name":"Least In-Flight",
"Filters":[],
"Ranking":[
{
"Metric":"health.inFlightRequests",
"Direction":"Ascending",
"Weight":1.0
}
],
"FallbackMode":"UseLegacyLoadBalancingMode",
"TieBreaker":"RoundRobin",
"Active":true
}'curl -X POST http://localhost:9000/v1.0/api/my-vmr/v1/chat/completions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_TOKEN" \
-d '{
"model":"llama3.2:latest",
"messages":[
{"role":"user","content":"Hello"}
]
}'curl -X POST "http://localhost:9000/v1.0/modelrunnerendpoints/mre_123/load-model?tenantId=default" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_TOKEN" \
-d '{
"Model":"gemma3:4b",
"ProbeKind":"Auto",
"KeepAlive":"30m",
"VerifyLoaded":true
}'curl -X POST "http://localhost:9000/v1.0/virtualmodelrunners/vmr_123/load-model?tenantId=default" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_TOKEN" \
-d '{
"Model":"gemma3:4b",
"TargetMode":"SelectedEndpoint",
"ProbeKind":"Auto",
"VerifyLoaded":true
}'
{ "Id": "default", // server-generated unless explicitly provided "Name": "Default Tenant", // required "Active": true, "Labels": ["production"], "Tags": { "region": "us-west" }, "Metadata": { "owner": "ops" }, "CreatedUtc": "2026-05-18T12:00:00Z", "LastUpdateUtc": "2026-05-18T12:00:00Z" }