Admin Endpoints¶
The admin API manages the gateway runtime, control-plane configuration, and operator workflows.
These endpoints back the Admin UI, but you can also use them directly for automation.
Quick Success Path¶
Caller policies accept output_tpm_limit on key and team create/update endpoints, organization create/update endpoints, and runtime-user updates (PUT /ui/api/users/{user_id}). Reads and lists return the stored value. Use a strict integer from 1 through 2,147,483,647, or null. Omitted updates preserve the policy; null clears it. Self-service key creation cannot exceed a configured team output limit. See Output TPM requirements.
Teams and keys also accept nullable model_output_tpm_limit maps on create/update. Use exact callable IDs with positive integer values, at most 64 entries and 256 UTF-8 bytes per ID. Omit to preserve; null or {} clears the map. Reads and lists return it. Parent limits still apply independently.
Tier model-policy create, patch, clone, and bulk-limit operations accept nullable output_tpm_limit. Activation includes the value in its immutable policy revision. In enforce mode, each assigned organization gets its own counter for that model. Tier output policies require fail-closed Redis and tier snapshot behavior. The organization preview returns the effective model limit and its tier source. The simulator returns an empty-minute completion projection separately from admission.
Most operators use the admin API in this order:
- Log in with the master key or an authenticated admin session
- Create a model deployment
- Grant the callable targets an organization, team, or key should see
- Create a virtual API key
- Adjust settings, guardrails, or route groups as needed
- Inspect spend, audit history, or batch activity
Authentication¶
Admin endpoints require either:
- a master key in
Authorization: Bearer ... - or an authenticated session cookie from the
/auth/*login flow
Some endpoints require specific admin permissions, so a valid session does not automatically mean full access.
If the account has MFA enabled, session-authenticated admin access requires an MFA-verified session.
Auth and Account Lifecycle¶
These endpoints back browser login, invitation acceptance, password recovery, MFA, and SSO.
| Method | Endpoint | Purpose |
|---|---|---|
POST |
/auth/internal/login |
Email/password login for admin sessions |
POST |
/auth/internal/logout |
End the current admin session |
GET |
/auth/me |
Inspect the current session |
POST |
/auth/internal/change-password |
Change password for the current session |
POST |
/auth/internal/forgot-password |
Request a password reset link |
GET |
/auth/internal/reset-password/{token} |
Validate a reset token |
POST |
/auth/internal/reset-password |
Complete a password reset |
GET |
/auth/invitations/{token} |
Validate an invitation token |
POST |
/auth/invitations/accept |
Accept an invitation |
POST |
/auth/mfa/enroll/start |
Start MFA enrollment |
POST |
/auth/mfa/enroll/confirm |
Confirm MFA enrollment |
POST |
/auth/mfa/verify |
Verify the current session for MFA-enabled accounts |
GET |
/auth/sso-config |
Inspect whether SSO is enabled |
GET |
/auth/login |
Start the SSO login flow |
GET |
/auth/callback |
Complete the SSO callback |
Governance Notes¶
- Callable-target and MCP runtime checks are enforced from in-memory snapshots, not per-request database reads.
- In multi-instance deployments, admin writes publish governance invalidation events so other instances reload their local snapshots asynchronously.
- Callable-target access groups are authorization groups. They grant callable targets such as model names or route-group keys; they do not change deployment routing.
- MCP binding and tool-policy listing endpoints return enabled rows by default. Platform admins can opt in to disabled rows with
include_disabled=true.
Runtime Configuration¶
Asset List Controls¶
These list endpoints accept search, limit, offset, sort_by, and sort_direction.
Use asc or desc for the direction. The server applies access checks and filters before sorting and pagination.
Equal values use a stable asset key as the final sort key. Missing values appear last.
| Endpoint | Allowed sort_by values |
|---|---|
/ui/api/models |
name, mode, provider, health, created_by, updated_at, visibility |
/ui/api/route-groups |
name, routing, members, health, created_by, updated_at, visibility |
/ui/api/prompt-registry/templates |
name, versions, labels, bindings, created_by, updated_at, visibility |
The UI requests sort_by=updated_at&sort_direction=desc initially.
If you omit sort_by, the existing API order applies.
List items include created_by_user_id, created_by_kind, created_by_email, created_at, updated_at, and visibility.
The creator ID is the stored account ID for all roles, including platform administrators.
created_by_kind tells how the creator authenticated:
| Value | Meaning |
|---|---|
account |
A signed-in account. The creator ID is null if the account was deleted. |
master_key |
The master key. The creator ID is null. |
system |
DeltaLLM, for example configuration seeding. |
unknown |
The item was created before DeltaLLM recorded the creator kind. |
created_by_email is the creator account email address. The API returns it only to platform administrators and to the creator. For other callers, the value is null.
sort_by=created_by sorts by the creator email address. Items without an email address appear last.
Old records can have null creator IDs or timestamps.
Model list items include health_status: healthy, unhealthy, or unknown.
The healthy field is null when health data is unavailable. Cooldowns make a deployment unavailable.
Group list items also include degraded, paused, and empty states, with enabled and available member counts.
For health sorting, ascending order puts unhealthy and degraded items first.
Unknown groups have a null available member count.
Models¶
| Method | Endpoint | Purpose |
|---|---|---|
GET |
/ui/api/models |
List deployments |
GET |
/ui/api/models/{deployment_id} |
Get one deployment |
POST |
/ui/api/models |
Create a deployment |
PUT |
/ui/api/models/{deployment_id} |
Update a deployment |
DELETE |
/ui/api/models/{deployment_id} |
Delete a deployment |
GET |
/ui/api/provider-presets |
List provider presets for the UI |
POST |
/ui/api/provider-models/discover |
Discover provider model suggestions for the UI |
Model create and update payloads accept custom upstream auth-header overrides inside deltallm_params for these OpenAI-compatible providers:
openaiopenroutergroqtogetherfireworksdeepinfraperplexityvllmlmstudioollama
Relevant fields:
deltallm_params.auth_header_namedeltallm_params.auth_header_format
auth_header_format must contain the exact {api_key} placeholder, and reserved header names such as Content-Type are rejected. If a deployment uses named_credential_id and also carries overlapping local connection fields, the named credential values win.
List, detail, create, and update responses continue to redact secrets such as api_key.
With custom upstream authentication, connection_summary can include the effective auth_header_name and a short custom_auth_label.
Examples are X-API-Key and Authorization (Token).
It never includes the rendered header value.
Model create and update payloads also accept these metadata fields:
model_info.mode: runtime workload type, such aschat,embedding,image_generation,audio_speech,audio_transcription, orrerankmodel_info.access_groups: authorization groups attached to the public callable targetmodel_info.tags: routing tags for deployment selection; not authorization
model_info.access_groups must be an array of valid group keys. Keys are normalized to lowercase, must start with a letter or digit, and may contain lowercase letters, digits, ., _, or -. Access groups expand to the public model_name, not to a single deployment. When several deployments share the same model_name, keep their access groups identical so group expansion remains deterministic.
Successful model create, update, and delete responses include a warnings array.
A durable database change remains successful if its immediate local routing refresh fails.
In this condition, the response includes a post-commit warning. Background revision reconciliation repairs the replica.
Read the deployment again before you retry the mutation.
Example inline model create payload:
{
"model_name": "support-vllm",
"deltallm_params": {
"provider": "vllm",
"model": "vllm/meta-llama/Llama-3.1-8B-Instruct",
"api_key": "gateway-key",
"api_base": "https://vllm.example/v1",
"auth_header_name": "X-API-Key",
"auth_header_format": "{api_key}"
},
"model_info": {
"mode": "chat",
"access_groups": ["support", "beta"],
"tags": ["low-latency"]
}
}
POST /ui/api/provider-models/discover accepts the same connection fields, including auth_header_name and auth_header_format, so the UI can probe OpenAI-compatible gateways before saving a deployment.
Organization Tiers¶
Tier administration requires platform-admin permission.
| Method | Endpoint | Purpose |
|---|---|---|
GET, POST |
/ui/api/tiers |
List or create tiers |
GET, PATCH, DELETE |
/ui/api/tiers/{tier_id} |
Read, update, or delete a tier |
POST |
/ui/api/tiers/bootstrap |
Atomically create a tier and its first draft |
GET, POST |
/ui/api/tiers/{tier_id}/versions |
List versions or create a draft version |
GET |
/ui/api/tiers/{tier_id}/versions/{tier_version_id} |
Read a version and its policies |
POST |
/ui/api/tiers/{tier_id}/versions/{tier_version_id}/clone |
Clone a version into a draft |
GET, POST |
/ui/api/tiers/{tier_id}/versions/{tier_version_id}/model-policies |
List or create model policies |
PATCH, DELETE |
/ui/api/tiers/{tier_id}/versions/{tier_version_id}/model-policies/{policy_id} |
Update or delete a model policy |
POST |
/ui/api/tiers/{tier_id}/versions/{tier_version_id}/model-policies/bulk-limits |
Update request limits in bulk |
GET, POST |
/ui/api/tiers/{tier_id}/versions/{tier_version_id}/capacity-pools |
List or create capacity pools |
PATCH, DELETE |
/ui/api/tiers/{tier_id}/versions/{tier_version_id}/capacity-pools/{pool_id} |
Update or delete a capacity pool |
GET |
/ui/api/tiers/{tier_id}/versions/{tier_version_id}/activation-preview |
Preview activation impact and concurrency guards |
POST |
/ui/api/tiers/{tier_id}/versions/{tier_version_id}/activate |
Activate a draft using revision and active-version guards |
POST |
/ui/api/tiers/{tier_id}/versions/{tier_version_id}/archive |
Archive a version |
GET, POST |
/ui/api/organizations/{organization_id}/tier-assignments |
List or create assignments |
PATCH, DELETE |
/ui/api/organizations/{organization_id}/tier-assignments/{assignment_id} |
Update or remove an assignment |
GET |
/ui/api/organizations/{organization_id}/tier-policy-preview |
Preview the effective compiled policy |
POST |
/ui/api/organizations/{organization_id}/tier-policy/simulate |
Simulate model access, pricing, and limits |
GET |
/ui/api/tier-capacity/dashboard |
Inspect live pool utilization and limit hits |
POST, DELETE |
/ui/api/tier-capacity/boosts |
Apply or clear an audited temporary weight boost |
See Admin UI: Tiers for the policy model and Organization Tiers Rollout for activation and operations.
Named Credentials¶
| Method | Endpoint | Purpose |
|---|---|---|
GET |
/ui/api/named-credentials |
List named credentials with usage counts |
GET |
/ui/api/named-credentials/{credential_id} |
Get one named credential and linked deployments |
POST |
/ui/api/named-credentials |
Create a named credential |
PUT |
/ui/api/named-credentials/{credential_id} |
Update a named credential |
DELETE |
/ui/api/named-credentials/{credential_id} |
Delete a named credential when not linked |
GET |
/ui/api/named-credentials/inline-report |
Report repeated inline credential groups |
POST |
/ui/api/named-credentials/convert-inline-group |
Convert repeated inline credentials into a shared named credential |
Named credentials are the reusable provider connection objects that model deployments can reference through named_credential_id.
Use them when you want to:
- rotate one provider key and have multiple deployments pick it up
- reduce duplicated inline secrets in model payloads
- centralize shared connection settings such as
api_key,api_base,api_version, or Bedrock fields
For the same OpenAI-compatible providers listed above, named-credential connection_config also supports:
auth_header_nameauth_header_format
Read responses always redact secret-bearing fields. Updating an in-use named credential triggers a runtime reload so linked deployments pick up the new connection settings. If that post-commit refresh fails, the mutation still succeeds and returns a warnings entry while durable revision polling reconciles the runtime. The raw secret value is never readable back out of the admin API.
For full UI and curl examples, see Admin UI: Named Credentials.
Route Groups¶
Use the route_group_id UUID returned by list/create responses to address an individual group.
The key is a runtime model name and may contain /, %, spaces, Unicode, ?, or #.
It is preserved exactly in response bodies, prompt bindings, and inference requests.
To resolve a known key, send it as the URL-encoded group_key query parameter to
GET /ui/api/route-groups/resolve/by-key; the response contains route_group_id and group_key.
The existing /ui/api/route-groups/{group_key} routes and their subresources remain
compatibility endpoints for single-segment names. URL-encoding a slash is insufficient on
those endpoints because servers decode paths before routing. New integrations should use
the ID endpoints below. Unknown or deleted IDs return 404 and cannot select a new group
created with the same key. IDs are never interpreted as keys.
Keep the legacy identifier during a staged rollout when older clients still depend on it.
| Method | Endpoint | Purpose |
|---|---|---|
GET |
/ui/api/route-groups |
List route groups |
GET |
/ui/api/route-groups/by-id/{route_group_id} |
Get one route group |
POST |
/ui/api/route-groups |
Create a route group |
PUT |
/ui/api/route-groups/by-id/{route_group_id} |
Update a route group |
DELETE |
/ui/api/route-groups/by-id/{route_group_id} |
Delete a route group |
GET |
/ui/api/route-groups/by-id/{route_group_id}/members |
List group members |
POST |
/ui/api/route-groups/by-id/{route_group_id}/members |
Add a member |
DELETE |
/ui/api/route-groups/by-id/{route_group_id}/members/{deployment_id} |
Remove a member |
Member weight and priority accept integers or null. Integer strings remain accepted
for compatibility. Boolean values are rejected with 400 before any member is changed.
An enabled route group owns a colliding callable key even when it has no enabled members. Deleting the group preserves callable-target bindings when a same-named model deployment exists; otherwise the group and its callable-target bindings are removed transactionally.
Callable Target Governance¶
Callable targets are the public runtime names that callers can use, including both model names and route-group keys.
| Method | Endpoint | Purpose |
|---|---|---|
GET |
/ui/api/callable-targets |
List callable targets from the live catalog |
GET |
/ui/api/callable-targets/{callable_key} |
Get one callable target with current bindings |
GET |
/ui/api/callable-target-access-groups |
List access groups from the live catalog and existing bindings |
GET |
/ui/api/callable-target-access-group-bindings |
List access-group bindings |
POST |
/ui/api/callable-target-access-group-bindings |
Create or update an access-group binding |
DELETE |
/ui/api/callable-target-access-group-bindings/{binding_id} |
Delete an access-group binding |
GET |
/ui/api/callable-target-bindings |
List callable-target bindings |
POST |
/ui/api/callable-target-bindings |
Create or update a binding |
DELETE |
/ui/api/callable-target-bindings/{binding_id} |
Delete a binding |
GET |
/ui/api/callable-target-scope-policies |
List scope policies such as inherit or restrict |
POST |
/ui/api/callable-target-scope-policies |
Create or update a scope policy |
DELETE |
/ui/api/callable-target-scope-policies/{policy_id} |
Delete a scope policy |
GET |
/ui/api/callable-target-migration/report |
Report rollout and migration readiness |
POST |
/ui/api/callable-target-migration/backfill |
Backfill explicit bindings from legacy data |
GET /ui/api/callable-target-access-groups accepts search, include_members, limit, and offset. Groups can appear because current callable targets are labelled with model_info.access_groups or because a binding already references the group. This supports planned future grants before a group has current members.
Access-group binding upserts use this payload:
{
"group_key": "support",
"scope_type": "organization",
"scope_id": "org_acme",
"enabled": true,
"metadata": {
"reason": "support tenant baseline"
}
}
scope_type supports organization, team, api_key, and user. Binding writes trigger governance snapshot reloads and emit ADMIN_CALLABLE_TARGET_ACCESS_GROUP_BINDING_UPSERT or ADMIN_CALLABLE_TARGET_ACCESS_GROUP_BINDING_DELETE audit events.
Route Group Policy¶
| Method | Endpoint | Purpose |
|---|---|---|
GET |
/ui/api/route-groups/by-id/{route_group_id}/policy |
Read current policy |
GET |
/ui/api/route-groups/by-id/{route_group_id}/policies |
Read policy history |
POST |
/ui/api/route-groups/by-id/{route_group_id}/policy/validate |
Validate a policy payload |
POST |
/ui/api/route-groups/by-id/{route_group_id}/policy/draft |
Save a draft policy |
DELETE |
/ui/api/route-groups/by-id/{route_group_id}/policy/draft |
Discard the draft policy |
POST |
/ui/api/route-groups/by-id/{route_group_id}/policy/publish |
Publish a policy |
POST |
/ui/api/route-groups/by-id/{route_group_id}/policy/rollback |
Roll back to an earlier policy |
POST |
/ui/api/route-groups/by-id/{route_group_id}/policy/simulate |
Simulate routing behavior |
PUT |
/ui/api/route-groups/{group_key}/policy |
Deprecated compatibility endpoint for direct publication |
Use POST /ui/api/route-groups/by-id/{route_group_id}/policy/publish for new integrations. A non-empty body
publishes that document; an omitted or empty body publishes the latest draft. The legacy PUT
endpoint always treats its body as an explicit document and returns a Link header identifying the
POST successor.
Publish and rollback record the account that does the operation in published_by. The master key
has no account, so its publications show admin_api. Policy reads also return
published_by_email. Only platform admins and the publishing account see this value. For other
callers, it is null.
DELETE .../policy/draft deletes the draft and returns discarded_version. The published policy
and live routing do not change. If the group has no draft, the endpoint returns 404.
strategy is the canonical policy routing field. Legacy mode: "weighted" and
mode: "fallback" inputs remain accepted with deprecation warnings and normalize to weighted and
priority-based-routing, respectively.
The optional context policy block is accepted only when the route group's workload mode is
chat or embedding. Validation, draft, publication, rollback, and simulation reject it for image,
audio, and rerank groups.
Omitting context from a policy write preserves the stored context block for forward compatibility.
Send "context": null to explicitly disable context routing; the deletion marker is applied during
the write and is not retained in the published document. Context token settings accept exact
non-negative integers (or their decimal string form) and reject fractional values.
Policy simulation accepts a bounded scenario (1–5000 iterations):
{
"iterations": 100,
"input_tokens": 9000,
"requested_output_tokens": 1000,
"policy": {
"strategy": "priority-based-routing",
"context": {
"mode": "eligible-only",
"unknown_capacity": "allow",
"safety_margin_tokens": 256
},
"members": [
{"deployment_id": "primary", "priority": 0},
{"deployment_id": "standby", "priority": 1}
],
"retry": {"max_attempts": 1, "retryable_error_classes": ["timeout"]}
},
"metadata": {"tags": ["vip"]},
"outcomes": [
{"deployment_id": "primary", "outcome": "timeout"}
]
}
input_tokens defaults to 0.
An omitted or null requested_output_tokens uses the context policy's deployment or default output allowance.
Supported assumed outcomes are success, timeout, rate_limit, and unavailable.
Omitted deployments default to success.
The response includes these results:
- Initial
selections. served_deploymentsandterminal_outcomes.- Total retry and fallback counts.
- Eligibility
reason_counts. - A bounded
sample_attemptstrace.
basis is live_state_dry_run.
The server pins one runtime generation and takes a snapshot of routing state before the simulation.
It calls no provider. It does not change live routing state.
When present, policy is the full client-owned policy document, not a partial update.
Omitted fields have these effects:
membersinherits the group's enabled membership.retryandtimeoutsclear published overrides.strategyuses the route group's configured strategy.
ID-addressed simulation verifies that the requested group still exists in its database snapshot. If the group was deleted before that snapshot, it returns 404, including when another group has since been created with the same key.
prompt_ref must name a prompt template that the caller can read. If the caller cannot read
the template, the response is the same 400 prompt_ref could not be resolved that an unknown
template gets. This prevents a caller from finding the prompt keys of other tenants.
A default_prompt value sent inside route group metadata gets the same access check as the
top-level default_prompt field. An unchanged value is kept without a new check.
Prompt Registry¶
| Method | Endpoint | Purpose |
|---|---|---|
GET |
/ui/api/prompt-registry/templates |
List prompt templates |
GET |
/ui/api/prompt-registry/templates/{template_key} |
Get one template with versions, labels, and bindings |
POST |
/ui/api/prompt-registry/templates |
Create a template |
PUT |
/ui/api/prompt-registry/templates/{template_key} |
Update a template |
DELETE |
/ui/api/prompt-registry/templates/{template_key} |
Delete a template |
POST |
/ui/api/prompt-registry/templates/{template_key}/versions |
Create a version |
POST |
/ui/api/prompt-registry/templates/{template_key}/versions/{version}/publish |
Publish a version |
GET |
/ui/api/prompt-registry/templates/{template_key}/labels |
List labels |
POST |
/ui/api/prompt-registry/templates/{template_key}/labels |
Create or move a label |
DELETE |
/ui/api/prompt-registry/templates/{template_key}/labels/{label} |
Delete a label |
GET |
/ui/api/prompt-registry/bindings |
List bindings |
POST |
/ui/api/prompt-registry/bindings |
Create a binding |
DELETE |
/ui/api/prompt-registry/bindings/{binding_id} |
Delete a binding |
POST |
/ui/api/prompt-registry/render |
Preview prompt rendering |
POST |
/ui/api/prompt-registry/preview-resolution |
Preview prompt resolution |
Settings and Routing Config¶
| Method | Endpoint | Purpose |
|---|---|---|
GET |
/ui/api/branding |
Read the public, non-secret Theme projection (no authentication required) |
PUT |
/ui/api/branding |
Update the installation Theme (platform admin only) |
GET |
/ui/api/branding/assets/{logo_mark\|logo_full\|favicon} |
Read a versioned public branding asset from the replica-local cache |
PUT |
/ui/api/branding/assets/{logo_mark\|logo_full\|favicon} |
Upload and persist a branding asset BLOB (platform admin only) |
DELETE |
/ui/api/branding/assets/{logo_mark\|logo_full\|favicon} |
Remove a branding asset BLOB (platform admin only) |
GET |
/ui/api/routing |
Read routing config |
PUT |
/ui/api/routing |
Update routing config |
GET |
/ui/api/settings |
Read gateway settings |
PUT |
/ui/api/settings |
Update gateway settings |
MCP Management¶
| Method | Endpoint | Purpose |
|---|---|---|
GET |
/ui/api/mcp-servers |
List MCP servers |
POST |
/ui/api/mcp-servers |
Create an MCP server |
GET |
/ui/api/mcp-servers/{server_id} |
Get one server with visible tools, bindings, and policies |
GET |
/ui/api/mcp-servers/{server_id}/operations |
Server-level usage and approval summary |
PATCH |
/ui/api/mcp-servers/{server_id} |
Update an MCP server |
DELETE |
/ui/api/mcp-servers/{server_id} |
Delete an MCP server |
POST |
/ui/api/mcp-servers/{server_id}/refresh-capabilities |
Refresh upstream tool capabilities |
POST |
/ui/api/mcp-servers/{server_id}/health-check |
Run an upstream health check |
GET |
/ui/api/mcp-bindings |
List MCP bindings |
POST |
/ui/api/mcp-bindings |
Create or update an MCP binding |
DELETE |
/ui/api/mcp-bindings/{binding_id} |
Delete an MCP binding |
GET |
/ui/api/mcp-scope-policies |
List MCP scope policies |
POST |
/ui/api/mcp-scope-policies |
Create or update an MCP scope policy |
DELETE |
/ui/api/mcp-scope-policies/{policy_id} |
Delete an MCP scope policy |
GET |
/ui/api/mcp-tool-policies |
List MCP tool policies |
POST |
/ui/api/mcp-tool-policies |
Create or update an MCP tool policy |
DELETE |
/ui/api/mcp-tool-policies/{policy_id} |
Delete an MCP tool policy |
GET |
/ui/api/mcp-approval-requests |
List approval requests |
POST |
/ui/api/mcp-approval-requests/{approval_request_id}/decision |
Approve or reject a pending request |
GET |
/ui/api/mcp-migration/report |
Report MCP rollout readiness by organization |
POST |
/ui/api/mcp-migration/backfill |
Backfill explicit org ceilings and child scope policies for MCP |
Access and Identity¶
API Keys¶
| Method | Endpoint | Purpose |
|---|---|---|
GET |
/ui/api/keys |
List keys |
POST |
/ui/api/keys |
Create a key |
PUT |
/ui/api/keys/{token_hash} |
Update a key |
GET |
/ui/api/keys/{token_hash}/asset-visibility |
Preview effective callable-target visibility for a key |
GET |
/ui/api/keys/{token_hash}/asset-access |
Read scoped callable-target access config for a key |
PUT |
/ui/api/keys/{token_hash}/asset-access |
Update scoped callable-target access config for a key |
POST |
/ui/api/keys/{token_hash}/regenerate |
Regenerate a key |
POST |
/ui/api/keys/{token_hash}/revoke |
Revoke a key |
DELETE |
/ui/api/keys/{token_hash} |
Delete a key |
GET /ui/api/keys and PUT /ui/api/keys/{token_hash} return last_used_at for each key. The value is an ISO 8601 UTC time, or null when no use is recorded. The gateway writes this value in batches about once per minute, so the value can be up to one minute old.
Service Accounts¶
| Method | Endpoint | Purpose |
|---|---|---|
GET |
/ui/api/service-accounts |
List service accounts |
POST |
/ui/api/service-accounts |
Create a service account |
Teams¶
| Method | Endpoint | Purpose |
|---|---|---|
GET |
/ui/api/teams |
List teams |
GET |
/ui/api/teams/{team_id} |
Get one team |
GET |
/ui/api/teams/{team_id}/asset-visibility |
Preview effective callable-target visibility for a team |
GET |
/ui/api/teams/{team_id}/asset-access |
Read scoped callable-target access config for a team |
PUT |
/ui/api/teams/{team_id}/asset-access |
Update scoped callable-target access config for a team |
POST |
/ui/api/teams |
Create a team |
PUT |
/ui/api/teams/{team_id} |
Update a team |
DELETE |
/ui/api/teams/{team_id} |
Delete a team |
GET |
/ui/api/teams/{team_id}/members |
List team members |
GET |
/ui/api/teams/{team_id}/member-candidates |
List addable team members |
POST |
/ui/api/teams/{team_id}/members |
Add a member |
DELETE |
/ui/api/teams/{team_id}/members/{user_id} |
Remove a member |
Organizations¶
| Method | Endpoint | Purpose |
|---|---|---|
GET |
/ui/api/organizations |
List organizations |
GET |
/ui/api/organizations/{organization_id} |
Get one organization |
GET |
/ui/api/organizations/{organization_id}/asset-visibility |
Preview effective callable-target visibility for an organization |
GET |
/ui/api/organizations/{organization_id}/asset-access |
Read scoped callable-target access config for an organization |
PUT |
/ui/api/organizations/{organization_id}/asset-access |
Update scoped callable-target access config for an organization |
POST |
/ui/api/organizations |
Create an organization |
PUT |
/ui/api/organizations/{organization_id} |
Update an organization |
GET |
/ui/api/organizations/{organization_id}/members |
List organization members |
GET |
/ui/api/organizations/{organization_id}/member-candidates |
List addable organization members |
POST |
/ui/api/organizations/{organization_id}/members |
Add a member |
DELETE |
/ui/api/organizations/{organization_id}/members/{membership_id} |
Remove a member |
GET |
/ui/api/organizations/{organization_id}/teams |
List teams in the organization |
When you remove a person from a team or an organization, DeltaLLM deletes the API keys that the
person owns in that team, or in all teams of that organization. The cached key entries are
invalidated, and each key gets an ADMIN_KEY_AUTO_REVOKE_MEMBERSHIP_REMOVED audit event. The
response includes revoked_keys, the number of deleted keys. This applies to these endpoints:
DELETE /ui/api/teams/{team_id}/members/{user_id}DELETE /ui/api/organizations/{organization_id}/members/{membership_id}DELETE /ui/api/rbac/team-memberships/{membership_id}DELETE /ui/api/rbac/organization-memberships/{membership_id}DELETE /ui/api/rbac/accounts/{account_id}, which deletes all keys that the account owns
Keys that other people or service accounts own stay active.
Each item returned by GET /ui/api/organizations includes non-null member_count and
team_count aggregates. member_count counts direct rows in
deltallm_organizationmembership; the aggregate is limited to organizations visible to the
authenticated principal.
RBAC¶
| Method | Endpoint | Purpose |
|---|---|---|
GET |
/ui/api/rbac/accounts |
List platform accounts |
GET |
/ui/api/principals |
List assignable principals |
GET |
/ui/api/users/{user_id}/asset-visibility |
Preview effective callable-target visibility for a runtime user |
GET |
/ui/api/users/{user_id}/asset-access |
Read scoped callable-target access config for a runtime user |
PUT |
/ui/api/users/{user_id}/asset-access |
Update scoped callable-target access config for a runtime user |
POST |
/ui/api/rbac/accounts |
Create a platform account |
DELETE |
/ui/api/rbac/accounts/{account_id} |
Delete a platform account |
GET |
/ui/api/rbac/organization-memberships |
List org memberships |
POST |
/ui/api/rbac/organization-memberships |
Create org membership |
DELETE |
/ui/api/rbac/organization-memberships/{membership_id} |
Delete org membership |
GET |
/ui/api/rbac/team-memberships |
List team memberships |
POST |
/ui/api/rbac/team-memberships |
Create team membership |
DELETE |
/ui/api/rbac/team-memberships/{membership_id} |
Delete team membership |
Scoped Asset Access Payloads¶
Asset-access endpoints for organizations, teams, API keys, and runtime users use the same response shape:
mode:grantfor organizations, orinherit/restrictfor teams, keys, and usersselected_callable_keys: direct model names or route-group keys selected for the scopeselected_access_group_keys: access groups selected for the scopeselectable_targets: callable targets that can be selected from the parent access universeselectable_access_groups: access groups that can be selected from the parent access universeeffective_targets: callable targets visible after inheritance, direct bindings, and access-group expansionsummary: selected, selectable, effective, and access-group counts
Update payloads accept direct targets and access groups:
{
"mode": "restrict",
"selected_callable_keys": ["gpt-4o-mini"],
"selected_access_group_keys": ["support"]
}
For organization updates, omit mode or set it to grant. For teams, keys, and users, inherit requires empty selected_callable_keys and selected_access_group_keys; use restrict only when narrowing access below the parent scope.
Query parameters:
| Endpoint kind | Parameters |
|---|---|
GET .../asset-visibility |
include_access_groups, access_group_search, access_group_limit, access_group_offset |
GET .../asset-access |
include_targets, access_group_search, access_group_limit, access_group_offset |
Asset-access writes emit the matching scope audit action, such as ADMIN_ORGANIZATION_ASSET_ACCESS_UPDATE, ADMIN_TEAM_ASSET_ACCESS_UPDATE, or ADMIN_KEY_ASSET_ACCESS_UPDATE.
Invitations¶
| Method | Endpoint | Purpose |
|---|---|---|
GET |
/ui/api/invitations |
List invitations visible to the caller |
POST |
/ui/api/invitations |
Create an invitation |
POST |
/ui/api/invitations/{invitation_id}/resend |
Resend an invitation |
POST |
/ui/api/invitations/{invitation_id}/cancel |
Cancel an invitation |
Safety and Operations¶
Guardrails¶
| Method | Endpoint | Purpose |
|---|---|---|
GET |
/ui/api/guardrails |
List global guardrail configuration |
PUT |
/ui/api/guardrails |
Update global guardrail configuration |
GET |
/ui/api/guardrails/scope/{scope}/{entity_id} |
Read scoped assignment |
PUT |
/ui/api/guardrails/scope/{scope}/{entity_id} |
Update scoped assignment |
DELETE |
/ui/api/guardrails/scope/{scope}/{entity_id} |
Remove scoped assignment |
Spend¶
| Method | Endpoint | Purpose |
|---|---|---|
GET |
/ui/api/spend/summary |
Platform or scoped spend summary |
GET |
/ui/api/spend/report |
Spend report and optional request logs |
Supported report parameters include:
group_by=model|provider|day|api_key|organization|team|userview=organization|team|selffor accounts with multiple reporting viewsstart_dateend_dateinterval=day|week|monthfor time seriesscope_type=organization|team|userwith exactly one ofscope_id=<id>orscope_unassigned=truefor a model drill-downlimitandoffsetfor grouped reports
Grouped rows return a nullable group_key and an explicit is_unassigned boolean. Clients must use is_unassigned rather than reserving a string identifier; a real model or tenant identifier such as __unassigned__ remains an ordinary assigned value.
For view=self, the report accepts only group_by=organization|team in addition to the common day, model, and provider groupings. A model drill-down may use only scope_type=organization|team. Both the grouping and drill-down retain the authenticated account's owner predicate and active membership boundary, so they partition personal usage without exposing another account's traffic. User/API-key groupings and request logs remain unavailable to self-only accounts.
Usage explorer¶
These routes feed the Overview of the Usage page. They accept the same view, start_date, and end_date parameters as /ui/api/spend/report.
| Method | Endpoint | Purpose |
|---|---|---|
GET |
/ui/api/spend/explorer/summary |
Totals for the period and for the period of the same length before it |
GET |
/ui/api/spend/explorer/series |
Time series split by model, provider, or team |
GET |
/ui/api/spend/explorer/breakdown |
One page of grouped rows with the previous-period spend |
Filter parameters (all three routes):
model,provider,organization,team,user,api_key: one exact value for each dimension.unassigned=<dimension>: select the rows that have no value for that dimension. You can repeat this parameter. Do not send a value andunassignedfor the same dimension.
The team and self views accept only the dimensions in capabilities.allowed_dimensions, plus model and provider.
Another dimension gets HTTP 403. A bad filter gets HTTP 422.
Series parameters: interval=day|week|month, split_by=model|provider|team, and max_groups (1 to 8).
The response contains groups (ranked, is_other last) and buckets.
Breakdown parameters: group_by=model|provider|organization|team|user|api_key, sort_by=spend|tokens|requests,
search (part of the name or ID), limit (1 to 100), and offset. The response contains data, scope_spend
(the total spend of the filtered scope), and pagination.
Live reports¶
These routes feed the Dashboard. They always use the last 24 hours (UTC) and accept only view.
| Method | Endpoint | Purpose |
|---|---|---|
GET |
/ui/api/spend/live/hourly |
48 hourly buckets and the number of active keys in the last 24 hours |
GET |
/ui/api/spend/live/daily |
Daily totals from the first day of last month until yesterday |
GET |
/ui/api/spend/live/providers |
Requests, failures, top failing model, and top error for each provider |
GET |
/ui/api/spend/live/top |
The API key, the model, and the team with the most requests in the last hour |
GET |
/ui/api/spend/live/budgets |
Organizations, teams, and keys that used 80% or more of their budget |
The gateway keeps live results in the reporting cache for 60 seconds and daily results for 15 minutes.
Send Cache-Control: no-cache to load new data.
Request logs¶
| Method | Endpoint | Purpose |
|---|---|---|
GET |
/ui/api/logs |
Request logs for the platform and organization views |
Parameters:
since: ISO 8601 timestamp. The first row to include. A timestamp without an offset is UTC. When you also sendstart_date, the later value applies.start_dateandend_date: dates in UTC.model,provider,organization_id,team_id,user_id,api_key: exact values.unassigned=<dimension>: rows without a value for that dimension (model,provider,organization,team,user, orapi_key).status:successorerror.cache_hit:trueorfalse.request_id: one exact request ID. The search reads only the selected window.pagination_mode=cursorwithcursorandlimit(1 to 500), orpagination_mode=offsetwithlimitandoffset.
All these report routes use the spend-reporting capacity gate. When the gate is full or a query takes too long,
they return HTTP 503 with Retry-After.
Workspace request logs¶
| Method | Endpoint | Purpose |
|---|---|---|
GET |
/ui/api/workspace/logs |
List the request logs of the session's workspace |
GET |
/ui/api/workspace/logs/{log_id} |
Read one request log of the session's workspace |
These routes accept only an external customer session (external_customer_v1) that has spend.read.self. They also require general_settings.spend_reporting_v2_enabled. Operator sessions and the master key get HTTP 403, because they have no workspace.
The scope is fixed. The organization and the team come from the session binding. After a team switch, the scope is the selected team. The routes refuse organization_id, team_id, user_id, and view with HTTP 422. The detail route returns HTTP 404 for a row of another workspace and for a missing row.
List parameters:
startandend: ISO 8601 timestamps.startis inclusive andendis exclusive. A timestamp without an offset is UTC. The default window is the last 24 hours.model: exact model name.api_key: the key hash thatGET /ui/api/keysreturns intoken.status:successorerror.cursor: thepagination.next_cursorvalue of the previous page. Rows are newest first.limit: 1 to 100. The default is 50.
Each row contains only these fields: id, request_id, start_time, end_time, latency_ms, call_type, model, api_key, status, http_status_code, error_type, prompt_tokens, completion_tokens, prompt_tokens_cached, completion_tokens_cached, spend, and cache_hit. spend is the amount that the gateway charged to the workspace budget. api_key is null when the row has no stored key hash, for example for a jwt:<user or email> or master_key credential label. The routes never return request or response bodies, metadata, api_base, cache keys, end users, owners, tags, or provider error text.
The list response also contains pagination (limit, count, has_more, next_cursor) and the resolved start and end. Both routes use the spend-reporting capacity gate. When the gate is full, they return HTTP 503 with Retry-After.
Batches¶
| Method | Endpoint | Purpose |
|---|---|---|
GET |
/ui/api/batches/summary |
Batch counts by status |
GET |
/ui/api/batches |
List batches |
GET |
/ui/api/batches/facets |
Models and teams that have batches, for the list filters |
GET |
/ui/api/batches/{batch_id} |
Get one batch with items and redacted webhook delivery state |
GET |
/ui/api/batches/{batch_id}/errors |
Failed lines in groups by safe error message |
GET |
/ui/api/batches/{batch_id}/webhook-deliveries |
Inspect redacted delivery state, including after batch metadata cleanup |
POST |
/ui/api/batches/{batch_id}/cancel |
Cancel a batch |
POST |
/ui/api/batches/{batch_id}/webhook-deliveries/{event_id}/replay |
Reschedule a failed webhook delivery while preserving its event ID and body |
The read routes (summary, list, detail, items, costs, and webhook inspection) apply the same scope:
- A platform administrator sees all batches.
key.readin an organization or team shows all batches in that scope.- Every other organization or team membership shows only the batches that the account created, as
recorded in
created_by_owner_account_idwhen the batch was created. The batch must also be in one of the account's current organizations or teams.
GET /ui/api/batches and GET /ui/api/batches/summary accept these filters. Each filter makes
the result smaller. It never shows batches outside the caller's scope.
| Parameter | Value |
|---|---|
search |
Part of a batch ID or a model name |
status |
One status or a comma-separated list, for example in_progress,finalizing. Unknown values are ignored. The summary does not accept it. |
model |
The model name, exact match |
endpoint |
/v1/embeddings or /v1/chat/completions. Other values return 400. |
team_id |
The team that created the batch |
created_after |
An ISO 8601 time. A time without a time zone is UTC. |
The summary returns total, queued, in_progress, finalizing, completed, failed,
cancelled, and expired. in_progress includes the finalizing batches, as before.
GET /ui/api/batches/facets accepts created_after. It returns models and teams, each a list of
value, label, and count, most used first, at most 50 of each.
GET /ui/api/batches/{batch_id} accepts these item parameters:
| Parameter | Value |
|---|---|
items_limit |
1 to 500, default 50 |
items_offset or after_line_number |
The page of lines. after_line_number is faster for later pages. |
item_status |
pending, in_progress, completed, failed, or cancelled. Other values return 400. |
custom_id |
One custom ID, exact match |
The detail response also contains input_file_id, output_file_id, and error_file_id.
GET /ui/api/batches/{batch_id}/errors returns at most 20 groups of failed lines. Each group has
message, retry_category, code, and count. The message is a safe message from the retry
category. The response never contains the error text from the provider.
A batch outside this scope returns 403. The list response also contains view. The value is
own when the caller sees only its own batches, and operator in all other cases.
GET /ui/api/batches/feature-status is available to every signed-in operator account.
The write routes (cancel, retry finalization, requeue stale, mark failed, and webhook replay) still
require key.update in the batch's scope.
Webhook inspection requires the existing scoped batch read permission. Replay requires scoped batch update permission and returns 409 unless the delivery is still failed. The standalone delivery endpoint and replay remain scoped through ownership retained on the outbox row after batch metadata cleanup. These responses never include the destination URL, signing secret, encrypted configuration, headers, payload, ownership identifiers, or caller metadata.
Audit¶
| Method | Endpoint | Purpose |
|---|---|---|
GET |
/ui/api/audit/events |
List audit events, newest first |
GET |
/ui/api/audit/events/{event_id} |
Fetch one audit event |
GET |
/ui/api/audit/events/{event_id}/payloads |
Fetch the stored request and response bodies of one event |
GET |
/ui/api/audit/events/{event_id}/related |
Events of the same request, recent events on the same resource, and recent sign-ins of the same actor |
GET |
/ui/api/audit/actions |
Every known action with its category (no database read) |
GET |
/ui/api/audit/organizations |
Organizations whose audit log the caller can read, for filters |
GET |
/ui/api/audit/timeline |
Timeline by request or correlation |
GET |
/ui/api/audit/export |
Export events as JSONL or CSV |
GET /ui/api/audit/events filters:
category:admin,auth,api,mcp,spend, orsystem, read from the action prefix. An unknown value returns422.action,status,organization_id,request_id,correlation_id,resource_type,resource_id, andipmatch exactly.actormatches an account ID, an email (case-insensitive), an API key hash, or an API key name.actor_idandactor_typematch those columns.searchmatches an event ID, request ID, or resource ID.sinceanduntiltake timestamps;start_dateandend_datetake whole days.
Paging: with count=false or a cursor, the response has pagination.next_cursor and has_more and runs no count query.
Pass next_cursor back as cursor for the next older page. Without them, offset paging with an exact total still works.
enrich=true adds a labels object to each event with the actor's email or key name, the key's team, and the organization and resource names.
An email shows only to platform admins, to the account itself, and to callers who can read the audit log of an organization the account belongs to.
GET /ui/api/audit/events/{event_id} takes include_payloads=false to return payload_summary (count, redacted, kinds) instead of the bodies, and context=true to add the actor's current role, the API key's team, owner, and state, and the resource's current state.
Audit read access is limited to the roles that hold audit.read.
Email Operations¶
| Method | Endpoint | Purpose |
|---|---|---|
GET |
/ui/api/email/outbox/summary |
Operator summary of outbox status and recent email records |
POST |
/ui/api/email/test |
Queue a test email and verify delivery is possible |
GET |
/ui/api/email/suppressions |
List suppressed email recipients |
DELETE |
/ui/api/email/suppressions/{email_address} |
Remove a suppressed recipient |
POST |
/webhooks/email/resend |
Ingest Resend delivery feedback and suppression events |
Session and Login Endpoints¶
| Method | Endpoint | Purpose |
|---|---|---|
POST |
/auth/internal/login |
Log in with email and password |
POST |
/auth/internal/logout |
Log out and clear the session |
GET |
/auth/me |
Inspect current session state |
POST |
/auth/internal/change-password |
Change password |
POST |
/auth/mfa/enroll/start |
Start MFA enrollment |
POST |
/auth/mfa/enroll/confirm |
Confirm MFA enrollment |
GET |
/auth/sso-config |
Read SSO configuration |
GET |
/auth/login |
Start SSO login |
GET |
/auth/callback |
Complete SSO login |