Skip to content

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:

  1. Log in with the master key or an authenticated admin session
  2. Create a model deployment
  3. Grant the callable targets an organization, team, or key should see
  4. Create a virtual API key
  5. Adjust settings, guardrails, or route groups as needed
  6. 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:

  • openai
  • openrouter
  • groq
  • together
  • fireworks
  • deepinfra
  • perplexity
  • vllm
  • lmstudio
  • ollama

Relevant fields:

  • deltallm_params.auth_header_name
  • deltallm_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 as chat, embedding, image_generation, audio_speech, audio_transcription, or rerank
  • model_info.access_groups: authorization groups attached to the public callable target
  • model_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_name
  • auth_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_deployments and terminal_outcomes.
  • Total retry and fallback counts.
  • Eligibility reason_counts.
  • A bounded sample_attempts trace.

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:

  • members inherits the group's enabled membership.
  • retry and timeouts clear published overrides.
  • strategy uses 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: grant for organizations, or inherit / restrict for teams, keys, and users
  • selected_callable_keys: direct model names or route-group keys selected for the scope
  • selected_access_group_keys: access groups selected for the scope
  • selectable_targets: callable targets that can be selected from the parent access universe
  • selectable_access_groups: access groups that can be selected from the parent access universe
  • effective_targets: callable targets visible after inheritance, direct bindings, and access-group expansion
  • summary: 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|user
  • view=organization|team|self for accounts with multiple reporting views
  • start_date
  • end_date
  • interval=day|week|month for time series
  • scope_type=organization|team|user with exactly one of scope_id=<id> or scope_unassigned=true for a model drill-down
  • limit and offset for 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 and unassigned for 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 send start_date, the later value applies.
  • start_date and end_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, or api_key).
  • status: success or error.
  • cache_hit: true or false.
  • request_id: one exact request ID. The search reads only the selected window.
  • pagination_mode=cursor with cursor and limit (1 to 500), or pagination_mode=offset with limit and offset.

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:

  • start and end: ISO 8601 timestamps. start is inclusive and end is 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 that GET /ui/api/keys returns in token.
  • status: success or error.
  • cursor: the pagination.next_cursor value 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.read in 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_id when 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, or system, read from the action prefix. An unknown value returns 422.
  • action, status, organization_id, request_id, correlation_id, resource_type, resource_id, and ip match exactly.
  • actor matches an account ID, an email (case-insensitive), an API key hash, or an API key name. actor_id and actor_type match those columns.
  • search matches an event ID, request ID, or resource ID.
  • since and until take timestamps; start_date and end_date take 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