Management API reference

Every operation on the administration and management API.

Administrative control plane: keys, users, orgs, budgets, guardrails, credentials, compliance. Requires an attested administrator identity — see Authentication & Scoping.

Generated from the OpenAPI specification. A continuous-integration check enforces the specification against the running router in both directions — an undocumented route fails the build, and so does a documented route that no longer exists. This reference therefore cannot silently drift from the implementation.

122 operations across 21 groups.

A note on free-form responses

Some operations document their body as a free-form object (additionalProperties: true). That is deliberate, not an omission, and it means one of two things:

  • Provider passthrough. The gateway forwards the upstream provider’s payload verbatim. Restating the provider’s schema here would create a second source of truth that drifts from theirs. Use the provider’s own documentation for those shapes.
  • Application-defined JSON. The value comes from a JSONB column the application does not structurally constrain.

Where a shape is pinned, this reference names the schema and lists its fields. So ChatCompletionRequest — model*: string, … is a contract; “free-form object” is an honest admission that it is not.

Contents

key

POST /key/block

Soft-block a key (blocked keys 401 on /v1/* but remain queryable)

Request body (required): key: string, key_id: string

ResponseMeaning
200Blocked. — blocked: boolean
401Missing or invalid bearer token.
404Resource not found.
5XXUnexpected server-side failure.

POST /key/delete

Delete one or more API keys

Request body (required): key: string, key_id: string, keys: array, key_aliases: array

ResponseMeaning
200Deleted. — deleted_keys: array
400Malformed body or invalid parameters.
401Missing or invalid bearer token.
5XXUnexpected server-side failure.

POST /key/generate

Generate a new API key

Request body (required): key_name: string, key_alias: string, user_id: string, team_id: string, max_budget: number|null, models: array, rpm_limit: integer|null, tpm_limit: integer|null … +3

ResponseMeaning
201Key created; plaintext key returned only at this time. — key*: string, key_id: string, key_name: string
400Malformed body or invalid parameters.
401Missing or invalid bearer token.
5XXUnexpected server-side failure.

GET /key/info

Look up a single API key by token or id

ParameterInRequiredType
keyquerynostring
key_idquerynostring
ResponseMeaning
200Key row. — APIKeytoken*: string, id: string, key_name: string, key_alias: string
401Missing or invalid bearer token.
404Resource not found.
5XXUnexpected server-side failure.

GET /key/list

List API keys

ParameterInRequiredType
user_idquerynostring
team_idquerynostring
organization_idquerynostring
searchquerynostring
pagequerynointeger
page_sizequerynointeger
ResponseMeaning
200Paginated list of keys. — data: array, total: integer
401Missing or invalid bearer token.
5XXUnexpected server-side failure.

POST /key/unblock

Reverse a soft-block on a key

Request body (required): key: string, key_id: string

ResponseMeaning
200Unblocked. — unblocked: boolean
401Missing or invalid bearer token.
404Resource not found.
5XXUnexpected server-side failure.

POST /key/update

Update an existing API key

Request body (required): key*: string, key_name: string, key_alias: string, max_budget: number|null, models: array, rpm_limit: integer|null, tpm_limit: integer|null, expires: string|null … +2

ResponseMeaning
200Updated. — updated: boolean
400Malformed body or invalid parameters.
401Missing or invalid bearer token.
404Resource not found.
5XXUnexpected server-side failure.

POST /key/{key}/regenerate

Regenerate (rotate) a key’s token in place

ParameterInRequiredType
keypathyesstring
ResponseMeaning
200New plaintext key returned (rotation completed). — key*: string, key_id: string
401Missing or invalid bearer token.
404Resource not found.
5XXUnexpected server-side failure.

user

POST /user/delete

Delete a user (soft-delete; spend history preserved)

Request body (required): user_id*: string

ResponseMeaning
200Deleted. — deleted: boolean
401Missing or invalid bearer token.
404Resource not found.
5XXUnexpected server-side failure.

GET /user/info

Get a single user by id or email

ParameterInRequiredType
user_idquerynostring
user_emailquerynostring
ResponseMeaning
200User row. — Useruser_id: string, user_email: string, user_role*: string, name: string, organization_id: string, team_id: string
401Missing or invalid bearer token.
404Resource not found.
5XXUnexpected server-side failure.

GET /user/list

List users

ParameterInRequiredType
pagequerynointeger
page_sizequerynointeger
user_rolequerynostring
ResponseMeaning
200Paginated user list. — data: array
401Missing or invalid bearer token.
5XXUnexpected server-side failure.

POST /user/new

Create a new user

Request body (required): user_email: string, user_role: string, name*: string

ResponseMeaning
201User created. — id: string, user_email: string
400Malformed body or invalid parameters.
401Missing or invalid bearer token.
5XXUnexpected server-side failure.

POST /user/update

Update a user’s role or profile

Request body (required): user_id*: string, user_role: string|null

ResponseMeaning
200Updated. — updated: boolean
400Malformed body or invalid parameters.
401Missing or invalid bearer token.
404Resource not found.
5XXUnexpected server-side failure.

team

POST /team/block

Soft-block a team

Request body (required): team_id*: string

ResponseMeaning
200Blocked. — blocked: boolean
401Missing or invalid bearer token.
404Resource not found.
5XXUnexpected server-side failure.

POST /team/delete

Delete a team

Request body (required): team_id*: string

ResponseMeaning
200Deleted. — deleted: boolean
401Missing or invalid bearer token.
404Resource not found.
5XXUnexpected server-side failure.

GET /team/info

Get a single team

41-13: response enriched additively (id, alias, name, org_id, org_name, member_count, max_budget, total_spend, current_spend, status, created_at) alongside team_id/team_alias/spend.

ParameterInRequiredType
team_idqueryyesstring
ResponseMeaning
200Team row. — object
401Missing or invalid bearer token.
404Resource not found.
5XXUnexpected server-side failure.

GET /team/list

List teams

41-13: rows enriched additively (see /team/info) alongside the pre-existing team_id/team_alias/spend/blocked.

ParameterInRequiredType
organization_idquerynostring
ResponseMeaning
200Team list. — data: array
401Missing or invalid bearer token.
5XXUnexpected server-side failure.

POST /team/member_add

Add a user to a team

Request body (required): team_id: string, user_id: string, role: string

ResponseMeaning
200Added. — added: boolean
401Missing or invalid bearer token.
404Resource not found.
5XXUnexpected server-side failure.

POST /team/member_delete

Remove a user from a team

Request body (required): team_id: string, user_id: string

ResponseMeaning
200Removed. — removed: boolean
401Missing or invalid bearer token.
404Resource not found.
5XXUnexpected server-side failure.

POST /team/new

Create a team

Request body (required): team_alias*: string, organization_id: string, max_budget: number|null, rpm_limit: integer|null, tpm_limit: integer|null, models: array

ResponseMeaning
201Team created. — team_id: string
400Malformed body or invalid parameters.
401Missing or invalid bearer token.
5XXUnexpected server-side failure.

POST /team/unblock

Reverse a soft-block on a team

Request body (required): team_id*: string

ResponseMeaning
200Unblocked. — unblocked: boolean
401Missing or invalid bearer token.
404Resource not found.
5XXUnexpected server-side failure.

POST /team/update

Update a team

Request body (required): team_id*: string, team_alias: string, max_budget: number|null

ResponseMeaning
200Updated. — updated: boolean
401Missing or invalid bearer token.
404Resource not found.
5XXUnexpected server-side failure.

organization

POST /management/organizations/{id}/apply_tier

Apply a tier’s resolved limits to an organization (idempotent)

Resolves the tier (by external_id) from the plan_tiers catalog, merges any per-subscription override, and applies the effective limits to the organization’s budget/api-key rows idempotently. NULL-soft: an unsynced external_id applies the override only and never zeroes an existing budget. Control-plane principals only (tenant principal → 403). Org id comes from the path; any body id is inert.

ParameterInRequiredType
idpathyesstring

Request body (required): external_id*: string, override: object

ResponseMeaning
200Applied; returns the effective limits written to the org. — object
400Malformed body or invalid parameters.
401Missing or invalid bearer token.
403Authenticated but not authorized — e.g. a non-admin caller
404Resource not found.
5XXUnexpected server-side failure.

POST /organization/delete

Delete an organization

Request body (required): organization_id*: string

ResponseMeaning
200Deleted. — deleted: boolean
401Missing or invalid bearer token.
404Resource not found.
5XXUnexpected server-side failure.

GET /organization/info

Get a single organization

41-13: response enriched additively (alias, name, metadata, member_count, team_count, total_spend, created_at) alongside id/organization_alias/spend.

ParameterInRequiredType
organization_idqueryyesstring
ResponseMeaning
200Organization row. — object
401Missing or invalid bearer token.
404Resource not found.
5XXUnexpected server-side failure.

GET /organization/list

List organizations

41-13: rows enriched additively (alias, name, member_count, team_count, total_spend, created_at) alongside id/organization_alias/spend.

ResponseMeaning
200Organization list. — data: array
401Missing or invalid bearer token.
5XXUnexpected server-side failure.

POST /organization/member_add

Add a user to an organization

Request body (required): organization_id: string, user_id: string, role: string

ResponseMeaning
200Added. — added: boolean
401Missing or invalid bearer token.
404Resource not found.
5XXUnexpected server-side failure.

POST /organization/member_delete

Remove a user from an organization

Request body (required): organization_id: string, user_id: string

ResponseMeaning
200Removed. — removed: boolean
401Missing or invalid bearer token.
404Resource not found.
5XXUnexpected server-side failure.

POST /organization/new

Create an organization

Request body (required): organization_alias*: string, max_budget: number|null, models: array

ResponseMeaning
201Organization created. — organization_id: string
400Malformed body or invalid parameters.
401Missing or invalid bearer token.
5XXUnexpected server-side failure.

POST /organization/update

Update an organization

41-13: this route now performs a REAL scoped UPDATE (it was a no-op that only audited intent). organization_alias + metadata are persisted via COALESCE (omitted field = column untouched), behind the unchanged own-org gateOrgWriteScope gate.

Request body (required): organization_id*: string, organization_alias: string, metadata: object, max_budget: number|null

ResponseMeaning
200Updated. — updated: boolean
401Missing or invalid bearer token.
404Resource not found.
5XXUnexpected server-side failure.

customer

POST /customer/delete

Delete a customer

Request body (required): customer_id*: string, id: string, end_user_id: string

ResponseMeaning
200Deleted. — deleted: boolean
401Missing or invalid bearer token.
404Resource not found.
5XXUnexpected server-side failure.

GET /customer/list

List customers

41-15: rows enriched additively (external_user_id + alias — dashboard-parity duplicates of the spec-locked end_user_id / end_user_name, which keep their exact names and derivations — plus default_model, allowed_model_region) alongside the pre-existing id/spend/blocked/created_at.

ResponseMeaning
200Customer list. — data: array
401Missing or invalid bearer token.
5XXUnexpected server-side failure.

POST /customer/new

Create a customer

Request body (required): user_id*: string, alias: string, max_budget: number|null, models: array, end_user_id: string, end_user_name: string

ResponseMeaning
201Customer created. — customer_id: string
400Malformed body or invalid parameters.
401Missing or invalid bearer token.
5XXUnexpected server-side failure.

POST /customer/update

Update a customer

41-15: the handler targets by the additive id (row UUID) or by the historical end_user_id (external user id) — both through the same scope gate. end_user_name/blocked persist via COALESCE.

Request body (required): customer_id*: string, max_budget: number|null, id: string, end_user_id: string, end_user_name: string, blocked: boolean

ResponseMeaning
200Updated. — updated: boolean
401Missing or invalid bearer token.
404Resource not found.
5XXUnexpected server-side failure.

budget

POST /budget/delete

Delete a budget tier

Request body (required): budget_id*: string

ResponseMeaning
200Deleted. — deleted: boolean
401Missing or invalid bearer token.
404Resource not found.
5XXUnexpected server-side failure.

GET /budget/info

Get a single budget tier

ParameterInRequiredType
budget_idqueryyesstring
ResponseMeaning
200Budget tier row. — object
401Missing or invalid bearer token.
404Resource not found.
5XXUnexpected server-side failure.

GET /budget/list

List budget tiers

41-14: rows enriched additively (name — blank rendered as “unnamed”, duration + budget_duration, soft_budget, rpm_limit, tpm_limit, reset_at, created_at, current_spend) alongside the pre-existing id/max_budget.

ResponseMeaning
200Budget list. — data: array
401Missing or invalid bearer token.
5XXUnexpected server-side failure.

POST /budget/new

Create a budget tier

41-14: request gains name + soft_budget (additive); budget_duration/rpm_limit/tpm_limit are now persisted (previously accepted but dropped).

Request body (required): budget_id*: string, max_budget: number, budget_duration: string, tpm_limit: integer|null, rpm_limit: integer|null, name: string, soft_budget: number|null

ResponseMeaning
201Budget tier created. — budget_id: string
400Malformed body or invalid parameters.
401Missing or invalid bearer token.
5XXUnexpected server-side failure.

POST /budget/update

Update a budget tier

41-14: this route now performs a REAL scoped UPDATE (it was a no-op that only audited intent) — COALESCE semantics, so an omitted field leaves the column untouched. Response shape unchanged.

Request body (required): budget_id*: string, max_budget: number, budget_duration: string, name: string, soft_budget: number|null, rpm_limit: integer|null, tpm_limit: integer|null

ResponseMeaning
200Updated. — updated: boolean
401Missing or invalid bearer token.
404Resource not found.
5XXUnexpected server-side failure.

model

POST /model/delete

Remove a model from the registry

Request body (required): model_id*: string

ResponseMeaning
200Deleted. — deleted: boolean
401Missing or invalid bearer token.
404Resource not found.
5XXUnexpected server-side failure.

GET /model/info

Get a registered model

41-16: response enriched additively (id, name, created_at) alongside the pre-existing model_name/model_info/aosentry_params. Reads stay open to all admin tiers (global fleet catalog).

ParameterInRequiredType
model_idquerynostring
model_namequerynostring
ResponseMeaning
200Model row. — object
401Missing or invalid bearer token.
404Resource not found.
5XXUnexpected server-side failure.

GET /model/list

List registered models

41-16: rows enriched additively (id, name, provider, health, response_time_ms, last_checked_at, lifecycle, is_self_hosted, created_at — dashboard-parity health/lifecycle join fields) alongside the pre-existing model_name/model_info. Reads stay open to all admin tiers and unfiltered (global fleet catalog); writes remain Instance-only (41-08).

ResponseMeaning
200Model list. — data: array
401Missing or invalid bearer token.
5XXUnexpected server-side failure.

POST /model/new

Add a model to the registry

Request body (required): model_name*: string, litellm_params: object, model_info: object

ResponseMeaning
201Model registered. — model_id: string
400Malformed body or invalid parameters.
401Missing or invalid bearer token.
5XXUnexpected server-side failure.

POST /model/update

Update a model registry entry

Request body (required): model_id*: string, model_name: string, litellm_params: object

ResponseMeaning
200Updated. — updated: boolean
401Missing or invalid bearer token.
404Resource not found.
5XXUnexpected server-side failure.

credential

POST /credential/delete

Delete a stored credential

41-16: gains additive id (row UUID) targeting, dual-keyed with the handler’s historical credential_name arm.

Request body (required): credential_id*: string, id: string, credential_name: string

ResponseMeaning
200Deleted. — deleted: boolean
401Missing or invalid bearer token.
404Resource not found.
5XXUnexpected server-side failure.

GET /credential/list

List stored credentials (credential_info string values are redacted)

41-16: rows enriched additively (id, created_by, created_at, updated_at) alongside the pre-existing credential_name/credential_info; credential_info masking tightened from api_key-only to ALL string values (admin-family parity — deliberate security tightening, field names unchanged). Instance-only, like every /credential/* verb (41-08).

ResponseMeaning
200Credential list. EVERY string value inside credential_info is — data: array
401Missing or invalid bearer token.
5XXUnexpected server-side failure.

POST /credential/new

Store a provider credential

Request body (required): credential_name: string, credential_info: object

ResponseMeaning
201Credential stored. — credential_id: string
400Malformed body or invalid parameters.
401Missing or invalid bearer token.
5XXUnexpected server-side failure.

GET /credential/provider-presets

List known provider defaults for the “Add Credential” form

Returns the provider preset catalog (name, api_base, custom_llm_provider, api_key_header) with detected stamped per entry — whether a matching key is present in the gateway’s environment. NEVER returns key material; only the boolean. Instance-only, like every /credential/* verb.

ResponseMeaning
200Provider presets. No key values are ever included. — data: array
401Missing or invalid bearer token.
5XXUnexpected server-side failure.

POST /credential/provision-from-env

Create a provider credential from a key already in the gateway env

Reads the provider’s key from the gateway’s OWN environment, stores it as a credential and fires the autopopulate sync — the raw key never reaches the browser. DEV-ONLY: returns 404 when Environment=production, because production credentials come from the secret store. Instance-only.

Request body (required): provider*: string

ResponseMeaning
201Credential stored from the environment key. — object
400Malformed body or invalid parameters.
401Missing or invalid bearer token.
404Unknown provider key, or the endpoint is disabled because the gateway
5XXUnexpected server-side failure.

POST /credential/update

Update a stored credential

41-16: gains additive id (row UUID) targeting, dual-keyed with the handler’s historical credential_name arm — only the id arm can rename (credential_name becomes a write value); unknown id → 404. All /credential/* verbs are Instance-only (41-08).

Request body (required): credential_id*: string, id: string, credential_name: string, credential_values: string, credential_info: object

ResponseMeaning
200Updated. — updated: boolean
401Missing or invalid bearer token.
404Resource not found.
5XXUnexpected server-side failure.

guardrail

POST /guardrail/check

Evaluate a guardrail against an input payload (dry-run)

Request body (required): guardrail_id: string, input: string

ResponseMeaning
200Evaluation result. — passed: boolean, details: object
400Malformed body or invalid parameters.
401Missing or invalid bearer token.
5XXUnexpected server-side failure.

POST /guardrail/delete

Delete a guardrail

Request body (required): guardrail_id*: string

ResponseMeaning
200Deleted. — deleted: boolean
401Missing or invalid bearer token.
404Resource not found.
5XXUnexpected server-side failure.

GET /guardrail/list

List guardrails

41-14: rows enriched additively (name — duplicate of guardrail_name for parsers keyed on name, aosentry_params, guardrail_info) alongside the pre-existing id/guardrail_name/guardrail_type/enabled/created_at.

ResponseMeaning
200Guardrail list. — data: array
401Missing or invalid bearer token.
5XXUnexpected server-side failure.

GET /guardrail/logs

List guardrail evaluation logs

41-14: rows enriched additively (confidence, stage — execution_stage with “pre” default, original_content, modified_content, created_at) alongside the pre-existing id/request_id/guardrail_name/status/duration_ms; status stays the raw column.

ParameterInRequiredType
guardrail_idquerynostring
pagequerynointeger
page_sizequerynointeger
ResponseMeaning
200Log entries. — data: array
401Missing or invalid bearer token.
5XXUnexpected server-side failure.

GET /guardrail/logs/stats

Aggregated guardrail-log statistics

ResponseMeaning
200Stats. — object
401Missing or invalid bearer token.
5XXUnexpected server-side failure.

POST /guardrail/new

Create a guardrail

41-14: an empty guardrail_type is inferred from the name / aosentry_params shape (admin-family inferGuardrailType parity); an operator-supplied type passes through unchanged.

Request body (required): guardrail_name: string, guardrail_type: string, mode*: string, config: object

ResponseMeaning
201Guardrail created. — guardrail_id: string
400Malformed body or invalid parameters.
401Missing or invalid bearer token.
5XXUnexpected server-side failure.

POST /guardrail/update

Update a guardrail

41-14 (docs catch-up): guardrail_name / guardrail_type / aosentry_params / enabled were already accepted and persisted by the handler; documented here because the dashboard’s enable/disable toggle converges onto {guardrail_id, enabled}. Writes are scope-gated (foreign-org / NULL-org targets → 403).

Request body (required): guardrail_id*: string, mode: string, config: object, guardrail_name: string, guardrail_type: string, aosentry_params: object, enabled: boolean

ResponseMeaning
200Updated. — updated: boolean
401Missing or invalid bearer token.
404Resource not found.
5XXUnexpected server-side failure.

callback

POST /callback/delete

Remove a registered callback

Request body (required): callback_id*: string

ResponseMeaning
200Removed. — deleted: boolean
401Missing or invalid bearer token.
404Resource not found.
5XXUnexpected server-side failure.

GET /callback/list

List registered callbacks

ResponseMeaning
200Callback list. — data: array
401Missing or invalid bearer token.
5XXUnexpected server-side failure.

POST /callback/new

Register a webhook callback

Request body (required): url: string, events: array, secret: string

ResponseMeaning
201Callback registered. — callback_id: string
400Malformed body or invalid parameters.
401Missing or invalid bearer token.
5XXUnexpected server-side failure.

config

GET /config/list

List runtime config entries

ResponseMeaning
200Config map. — object
401Missing or invalid bearer token.
5XXUnexpected server-side failure.

POST /config/update

Update one or more runtime config entries

Request body (required): object

ResponseMeaning
200Updated. — updated: boolean
401Missing or invalid bearer token.
5XXUnexpected server-side failure.

dataset

GET /management/dataset/list

List datasets

Lists every dataset asset in the attested tenant’s namespace. Tenant isolation is structural — the namespace path IS the boundary (SC6).

ResponseMeaning
200Dataset list (tenant-scoped). — data: array
401Missing or invalid bearer token.
403Authenticated but not authorized — e.g. a non-admin caller
5XXUnexpected server-side failure.

POST /management/dataset/new

Create a dataset

Validates the content against the dataset JSON Schema (C-02; required name/storage_format/table_ref) and persists it as a catalog asset (asset_type=‘dataset’) in the attested tenant’s namespace. table_ref.snapshot_ids carries the Iceberg reproducibility pin (SC2).

Request body (required): name: string, content: object

ResponseMeaning
201Dataset created. — asset_id: string, version: integer
400Malformed body or invalid parameters.
401Missing or invalid bearer token.
403Authenticated but not authorized — e.g. a non-admin caller
5XXUnexpected server-side failure.

POST /management/dataset/{id}/items

Append items to a dataset

Appends jsonl-style test-case items into the dataset asset’s provenance.items array and re-validates the merged content against the dataset schema before persisting via AIAssetStore.Update (which bumps the version + content-hash atomically).

ParameterInRequiredType
idpathyesstring

Request body (required): items*: array

ResponseMeaning
200Items appended. — appended: integer
400Malformed body or invalid parameters.
401Missing or invalid bearer token.
403Authenticated but not authorized — e.g. a non-admin caller
404Resource not found.
5XXUnexpected server-side failure.

POST /management/dataset/{id}/sample_from_production

Sample production traffic into a dataset

Reads a bounded, tenant-filtered sample of production spend_logs rows (metadata.tenant_id = the attested tenant) and appends them as dataset items. sample_size is capped server-side; the tenant binding is the attested principal exclusively (no tenant_id wire field), so a cross-tenant sample is structurally impossible.

ParameterInRequiredType
idpathyesstring

Request body (required): sample_size*: integer

ResponseMeaning
200Sampled rows appended. — sampled: integer
400Malformed body or invalid parameters.
401Missing or invalid bearer token.
403Authenticated but not authorized — e.g. a non-admin caller
404Resource not found.
5XXUnexpected server-side failure.

developer

GET /developer/v1/audit

Audit entries involving the calling developer

Returns audit_logs rows where either the developer was the actor (changed_by = ‘api-key:’ — the attested actor string) OR the resource is one of the developer’s api_keys (table_name=‘api_keys’ AND object_id IN developer’s keys by aoid_credential_id). Newest first. Cross-developer leak is prevented by the IN subquery restricting object_id to keys owned by the calling developer.

ParameterInRequiredType
pagequerynointeger
page_sizequerynointeger
ResponseMeaning
200Paginated audit entries. — data: array, page: integer, page_size: integer
400Malformed body or invalid parameters.
401Missing or invalid bearer token.
5XXUnexpected server-side failure.

GET /developer/v1/keys

List the developer’s own active keys

Returns the calling developer’s active (non-discarded) API keys. The raw token column is NEVER included — only the id and public metadata. Pagination via standard limit/offset query params.

ParameterInRequiredType
limitquerynointeger
offsetquerynointeger
ResponseMeaning
200List of keys (raw token NEVER included). — data: array
401Missing or invalid bearer token.
5XXUnexpected server-side failure.

POST /developer/v1/keys

Mint a self-service API key

Create a new API key bound to the calling developer’s attested credential (aoid_credential_id). Security invariants enforced server-side:

  1. aoid_credential_id is sourced from the attested context (request-body user_id / team_id / organization_id are dropped — never trusted).
  2. team_id and organization_id are zeroed.
  3. max_budget is clamped to (developer ceiling - allocated). Exceeding the remaining grant returns 400.
  4. models[] defaults to the developer’s own allowlist when omitted (NEVER empty for a restricted developer, because empty in api_keys = “all models” — bypass key blocked).
  5. models[] is intersected with the developer’s allowlist — a developer cannot grant a model outside their own grant set. Per-developer key cap (default 10, override via env DEVELOPER_MAX_KEYS_PER_USER) enforced before INSERT.

Audit row recorded with changed_by=“api-key:” via the attested actor string.

Request body (required): key_name: string, key_alias: string, max_budget: number|null, models: array, rpm_limit: integer|null, tpm_limit: integer|null, expires: string|null

ResponseMeaning
201Key minted. Plaintext key returned only at this time. — id: string, key: string, key_alias: string
400Validation error. Includes:
401Missing or invalid bearer token.
5XXUnexpected server-side failure.

DELETE /developer/v1/keys/{id}

Revoke one of the developer’s keys (soft-delete)

Sets discarded_at = now() on the key. Same ownership filter as GET: 404 (not 403) is returned for foreign or non-existent keys. Audit row recorded with changed_by=“developer:”.

ResponseMeaning
204Key revoked.
401Missing or invalid bearer token.
404Key not found OR not owned by the calling developer (same
5XXUnexpected server-side failure.

GET /developer/v1/keys/{id}

Retrieve one of the developer’s keys

Returns the key’s public metadata. 404 is returned BOTH when the key genuinely does not exist AND when it exists but is not owned by the calling developer — distinguishing the two would leak key existence (RESEARCH Pitfall: no enumeration via 403-vs- 404 split). The raw token is never included in the response.

ResponseMeaning
200Key details (raw token NEVER included). — id: string, key_name: string, key_alias: string, max_budget: number
401Missing or invalid bearer token.
404Key not found OR not owned by the calling developer. The
5XXUnexpected server-side failure.

GET /developer/v1/models/available

List models the developer can grant on minted keys

Returns the proxy_models registry INTERSECTED with the developer’s users.models[] allowlist. When the developer is unrestricted (users.models[] is empty), the full registry is returned. When restricted, only models in the developer’s grant set appear — out-of-allowlist models are SILENTLY ABSENT (no error, no enumeration leak).

This endpoint preserves the 404-on-unauthorized-model property (SC2) for the developer surface: a model NOT in the developer’s grant set is not discoverable through this list endpoint.

ResponseMeaning
200Grantable model list. — object: string, data: array
401Missing or invalid bearer token.
5XXUnexpected server-side failure.

GET /developer/v1/spend

Total spend + request count for the calling developer’s keys

Returns the calling developer’s total_spend + total_requests over the date window. Scoped by aoid_credential_id (the attested self-scope derived from the AOID-signed context). A developer NEVER sees another developer’s totals. Discarded keys’ historic spend IS included (the developer spent that money; the key was just revoked afterward).

ParameterInRequiredType
start_datequerynostring
end_datequerynostring
ResponseMeaning
200Developer-scoped spend summary. — total_spend: number, total_requests: integer, start_date: string, end_date: string
400Malformed body or invalid parameters.
401Missing or invalid bearer token.
5XXUnexpected server-side failure.

GET /developer/v1/spend/logs

Paginated spend_logs for the calling developer’s keys

Returns spend_logs rows for keys owned by the calling developer, ordered by start_time DESC (newest first). page is 0-indexed.

ParameterInRequiredType
pagequerynointeger
page_sizequerynointeger
ResponseMeaning
200Paginated spend_logs (newest first). — data: array, page: integer, page_size: integer
400Malformed body or invalid parameters.
401Missing or invalid bearer token.
5XXUnexpected server-side failure.

GET /developer/v1/usage

Per-key spend breakdown for the calling developer

Returns one row per api_key owned by the calling developer with request count + spend in the window. Sorted by spend DESC. Empty key aliases are preserved as-is — the portal handles display.

ParameterInRequiredType
start_datequerynostring
end_datequerynostring
ResponseMeaning
200Per-key breakdown. — data: array
400Malformed body or invalid parameters.
401Missing or invalid bearer token.
5XXUnexpected server-side failure.

eval_job

GET /management/eval_job/list

List eval jobs (tenant-scoped)

Returns a paginated list of eval_jobs rows for the caller’s tenant, ordered newest-first (created_at DESC). Enforces the tenant isolation matrix from Obj 16 TRD 16-10 (mirrors ListRuns):

  • Plain tenant admin: sees only own-tenant rows. ?tenant= → 403.
  • master_key class OR cross_tenant_admin entitlement: may pass ?tenant= override (audited as eval_job.tenant_override).

aggregate_score and verdict are omitted when no eval_results exist yet for a job (no fake zeros). For per-job scores and verdict use GET /management/eval_job/{id}/results.

ParameterInRequiredType
limitquerynointeger
offsetquerynointeger
statusquerynostring
tenantquerynostring
ResponseMeaning
200Eval job list page. — jobs: array, total: integer
400Malformed body or invalid parameters.
401Missing or invalid bearer token.
403Authenticated but not authorized — e.g. a non-admin caller
5XXUnexpected server-side failure.

POST /management/eval_job/new

Launch an eval pipeline run

Opens ONE pgx.Tx, INSERTs pipeline_runs + eval_jobs in the same tx, emits the pipeline.run.start provenance entry (A-04 outbox), and ExecuteWorkflow’s EvalRunWorkflow on TaskQueueEval with EVERY reproducibility input PINNED at run start (SC2): the suite version defaults to the catalog head when omitted, temperature is pinned to 0, and the reproducibility seed flows through unchanged. A Temporal failure rolls the whole tx back — no orphan run row. The tenant comes from the attested principal exclusively (SC6); there is no tenant_id wire field.

Request body (required): eval_suite_id*: string, eval_suite_version: integer, model_asset_id: string, model_version: string, judge_model_version: string, dataset_snapshot_ids: array, reproducibility_seed: integer

ResponseMeaning
201Eval job created; Temporal run started. — eval_job_id: string, pipeline_run_id: string, status: string
400Malformed body or invalid parameters.
401Missing or invalid bearer token.
403Authenticated but not authorized — e.g. a non-admin caller
5XXUnexpected server-side failure.

GET /management/eval_job/{id}

Get one eval job

Reads eval_jobs + pipeline_runs from Postgres (never Temporal visibility — anti-pattern). The wrong-tenant gate (SC6) 404s a job owned by a different tenant — never leaks its existence.

ParameterInRequiredType
idpathyesstring
ResponseMeaning
200Eval job snapshot. — eval_job_id: string, tenant_id: string, eval_suite_id: string, eval_suite_version: integer, pipeline_run_id: string, status: string, pipeline_run_status: string, reproducibility_seed: integer
401Missing or invalid bearer token.
403Authenticated but not authorized — e.g. a non-admin caller
404Resource not found.
5XXUnexpected server-side failure.

GET /management/eval_job/{id}/results

Get eval-job scores + verdict

Returns the eval_scores rows + the latest eval_results verdict bound to THIS job (job_id guard). A missing verdict on a still-running job is NOT an error — the verdict field is simply absent. Same wrong-tenant gate (SC6) as GET /eval_job/{id}.

ParameterInRequiredType
idpathyesstring
ResponseMeaning
200Scores + verdict. — eval_job_id: string, scores: array, verdict: string, aggregate_score: number, result: object
401Missing or invalid bearer token.
403Authenticated but not authorized — e.g. a non-admin caller
404Resource not found.
5XXUnexpected server-side failure.

eval_suite

POST /management/eval_suite/new

Create an eval suite

Validates the content against the eval_suite JSON Schema (C-02; required name/eval_type/test_cases) and persists it as a catalog asset (asset_type=‘eval_suite’) in the attested tenant’s namespace. Versioning + content-hash come from the catalog store. Returns the catalog asset_id and the just-assigned version.

Request body (required): name: string, content: object

ResponseMeaning
201Eval suite created. — asset_id: string, version: integer
400Malformed body or invalid parameters.
401Missing or invalid bearer token.
403Authenticated but not authorized — e.g. a non-admin caller
5XXUnexpected server-side failure.

GET /management/eval_suite/{id}/versions

List eval suite versions

Surfaces the append-only version history for an eval_suite asset from the shipped AIAssetVersionStore. A job pins a specific suite version (SC2) by reading from here.

ParameterInRequiredType
idpathyesstring
ResponseMeaning
200Version history (newest-first). — data: array
401Missing or invalid bearer token.
403Authenticated but not authorized — e.g. a non-admin caller
404Resource not found.
5XXUnexpected server-side failure.

openapi

GET /openapi/{filename}

Serve an embedded OpenAPI YAML file

Returns the bytes of one of the embedded OpenAPI YAML files (management.yaml, _components.yaml; v1.yaml after TRD 02). Public route — no authentication required. The contract has no secrets in it.

ParameterInRequiredType
filenamepathyesstring
ResponseMeaning
200The embedded YAML file.
404Resource not found.
5XXUnexpected server-side failure.

pipeline

GET /management/pipelines/definitions

List pipeline definitions

ResponseMeaning
200Definition list. — data: array
401Missing or invalid bearer token.
5XXUnexpected server-side failure.

POST /management/pipelines/definitions

Register a pipeline definition

Compiles the DSL via dsl.Compile, validates the content against the pipeline_definition JSON Schema (C-02; 13-value operator enum), and persists as a catalog asset under (aocore, pipelines). Returns the catalog asset_id, the just-assigned version, and the Temporal workflow type name (pipeline_<assetID-first-8>_v<version>).

Request body (required): name: string, dsl_source: string

ResponseMeaning
201Definition registered. — asset_id: string, version: integer, workflow_type: string
400Malformed body or invalid parameters.
401Missing or invalid bearer token.
5XXUnexpected server-side failure.

GET /management/pipelines/definitions/{id}

Get one pipeline definition

ParameterInRequiredType
idpathyesstring
ResponseMeaning
200Definition. — asset_id: string, name: string, current_version: integer, content_hash: string, content: object, created_at: string, updated_at: string
404Resource not found.
5XXUnexpected server-side failure.

GET /management/pipelines/hitl/pending

List pending human-in-the-loop reviews

Returns the pipeline_runs rows in status=‘awaiting_review’ scoped to the caller’s tenant — the HITL reviewer inbox (G-07). Cross-tenant via ?tenant=other is master-key/admin-only and audit-logged; non-admin callers receive 403 forbidden.

The reviewer-role filter is a documented C-04 RBAC stub: every authenticated caller currently sees ALL pending reviews for the (effective) tenant. step_id / step_name / reviewer_role project as empty strings until the parked-step descriptor lands with C-04.

ParameterInRequiredType
tenantquerynostring
ResponseMeaning
200Pending HITL review list. — data: array
401Missing or invalid bearer token.
403Authenticated but not authorized — e.g. a non-admin caller
5XXUnexpected server-side failure.

GET /management/pipelines/runs

List pipeline runs

Returns pipeline_runs rows filtered to the caller’s tenant (per attested context). Cross-tenant via ?tenant=other is master-key/admin-only and audit-logged; non-admin callers receive 403 forbidden.

ParameterInRequiredType
tenantquerynostring
statusquerynostring
definition_idquerynostring
limitquerynointeger
offsetquerynointeger
ResponseMeaning
200Run list. — data: array
401Missing or invalid bearer token.
403Authenticated but not authorized — e.g. a non-admin caller
5XXUnexpected server-side failure.

POST /management/pipelines/runs

Start a pipeline run

Resolves the Temporal namespace + task queue from the attested principal via temporal.ResolveNamespace. Opens a pgx.Tx, INSERTs the pipeline_runs row, emits the pipeline.run.start audit chain entry (F-01 wire format) IN THE SAME tx, calls temporal.Client.ExecuteWorkflow, and commits. Wrong-tenant smuggling is structurally impossible — the request body has no tenant_id field.

Request body (required): definition_id*: string, definition_version: string, initial_inputs: object

ResponseMeaning
202Run accepted. — run_id: string, temporal_workflow_id: string, temporal_namespace: string, status: string
400Malformed body or invalid parameters.
401Missing or invalid bearer token.
404Resource not found.
503Service dependency unavailable — e.g. Temporal workflow engine not
5XXUnexpected server-side failure.

GET /management/pipelines/runs/{id}

Get one pipeline run

ParameterInRequiredType
idpathyesstring
ResponseMeaning
200Run. — object
404Resource not found.
5XXUnexpected server-side failure.

POST /management/pipelines/runs/{id}/cancel

Cancel a pipeline run (graceful)

Sends Temporal CancelWorkflow. Activities observe workflow.IsCanceled and clean up; subsequent activities are not scheduled. Compare with /terminate which is destructive.

ParameterInRequiredType
idpathyesstring
ResponseMeaning
200Cancel accepted.
403Authenticated but not authorized — e.g. a non-admin caller
404Resource not found.
503Service dependency unavailable — e.g. Temporal workflow engine not
5XXUnexpected server-side failure.

GET /management/pipelines/runs/{id}/history

Paginated Temporal workflow history events

G-12 replaces the G-04 stub with real paginated Temporal history. Returns events in the Flutter wire shape consumed by G-05 EventHistoryView and G-06 projectStepsFromHistory. Pagination is offset-based: ?limit (default 100, max 1000) + ?next_page_token (opaque stringified offset). Final page omits next_page_token. When Temporal is not configured, returns 503 temporal_not_configured.

ParameterInRequiredType
idpathyesstring
limitquerynointeger
next_page_tokenquerynostring
ResponseMeaning
200Paginated Temporal workflow history events. — data: array, next_page_token: string
401Missing or invalid bearer token.
404Resource not found.
503Service dependency unavailable — e.g. Temporal workflow engine not
5XXUnexpected server-side failure.

POST /management/pipelines/runs/{id}/signal

Send a signal to a pipeline run

Forwards a Temporal signal (e.g. human_review_decision with payload {approved: bool, reason: string} for the human_review operator).

ParameterInRequiredType
idpathyesstring

Request body (required): signal_name*: string, payload: object

ResponseMeaning
200Signal delivered.
400Malformed body or invalid parameters.
403Authenticated but not authorized — e.g. a non-admin caller
404Resource not found.
503Service dependency unavailable — e.g. Temporal workflow engine not
5XXUnexpected server-side failure.

GET /management/pipelines/runs/{id}/stream

SSE live updates for a pipeline run

Server-Sent Events stream. Polls Temporal every 2 seconds and emits one of three event types: state-change (status transition), heartbeat (no change), terminal (final status; stream closes). Latency budget: 2.3s p99 from state change to client render (G-RESEARCH Domain 5).

ParameterInRequiredType
idpathyesstring
ResponseMeaning
200SSE stream (text/event-stream).
404Resource not found.
5XXUnexpected server-side failure.

POST /management/pipelines/runs/{id}/terminate

Terminate a pipeline run (destructive)

Sends Temporal TerminateWorkflow. Activities are NOT given a graceful shutdown signal; the workflow halts immediately. Use /cancel for graceful shutdown.

ParameterInRequiredType
idpathyesstring

Request body (optional): reason: string

ResponseMeaning
200Terminate accepted.
403Authenticated but not authorized — e.g. a non-admin caller
404Resource not found.
503Service dependency unavailable — e.g. Temporal workflow engine not
5XXUnexpected server-side failure.

schema

GET /management/schema

Return the management API JSON schema descriptor

Self-describing endpoint that returns a machine-readable summary of the management API surface. Independent of the OpenAPI spec served at /openapi/management.yaml — see go/internal/api/management/schema.go.

ResponseMeaning
200Schema descriptor. — object
401Missing or invalid bearer token.
5XXUnexpected server-side failure.

tag

POST /tag/delete

Delete a tag

Request body (required): tag_id*: string, id: string, name: string

ResponseMeaning
200Deleted. — deleted: boolean
401Missing or invalid bearer token.
404Resource not found.
5XXUnexpected server-side failure.

GET /tag/list

List tags

41-15: rows enriched additively (id — the UI row identity and update/delete mutation key) alongside the pre-existing name/color/description.

ResponseMeaning
200Tag list. — data: array
401Missing or invalid bearer token.
5XXUnexpected server-side failure.

POST /tag/new

Create a tag

Request body (required): tag_name*: string, description: string, name: string, color: string

ResponseMeaning
201Tag created. — tag_id: string
400Malformed body or invalid parameters.
401Missing or invalid bearer token.
5XXUnexpected server-side failure.

POST /tag/update

Update a tag

41-15: promoted from a recorded no-op to a REAL scoped UPDATE. The handler targets by the additive id (row UUID — required for rename, which cannot address the row it renames by name) or by the unique name; name/color/description persist via COALESCE (omit to leave unchanged). Both arms ride the same scope gate.

Request body (required): tag_id*: string, tag_name: string, description: string, id: string, name: string, color: string

ResponseMeaning
200Updated. — updated: boolean
401Missing or invalid bearer token.
404Resource not found.
5XXUnexpected server-side failure.

tier

POST /management/tiers

Upsert a plan-tier catalog row (control-plane sync target)

Idempotent upsert of a tier into the global plan_tiers catalog, matched on external_id (= eden-biz plan_key). First push inserts (201); re-push updates in place (200). Control-plane principals only; a tenant principal is rejected (403).

Request body (required): external_id*: string, slug: string, max_budget: number|null, soft_budget: number|null, rpm_limit: integer|null, tpm_limit: integer|null, models: array

ResponseMeaning
200Tier updated in place (existing external_id). — object
201Tier created (new external_id). — object
400Malformed body or invalid parameters.
401Missing or invalid bearer token.
403Authenticated but not authorized — e.g. a non-admin caller
5XXUnexpected server-side failure.

v1

POST /management/v1/agent/chat

Attested chat completion (agent LLM step)

OpenAI-compatible chat+tools completion authenticated by the ATTESTED Principal (no API key). Mounted under AttestedAdminMiddleware. Accepts the OpenAI chat shape (messages + tools) and reuses the same LLM proxy as /v1/chat/completions: resolves model→provider→credential, runs guardrails, calls the upstream provider, and returns the assistant message + tool_calls + usage. Used by the agent loop worker so the LLM step runs as the attested operator identity rather than a service API key. Streaming is not supported on this path.

Request body (required): model: string, messages: array, tools: array, tool_choice: any

ResponseMeaning
200Chat completion response (OpenAI shape). — id: string, object: string, model: string, choices: array, usage: object
400Malformed body or invalid parameters.
401Missing or invalid bearer token.
403Authenticated but not authorized — e.g. a non-admin caller
404Resource not found.
5XXUnexpected server-side failure.

GET /management/v1/billing-export/usage

Versioned cursor-paginated billing-data export (v1 pull seam)

Stable versioned pull API serving daily per-org usage/spend aggregates to EXTERNAL billing systems. AOCore produces billing-usable data; external systems price and invoice (locked decision 3).

CONTRACT STABILITY RULES (see docs/billing/billing-export-seam.md):

  • version field is always “v1”; v2 would use /billing-export/v2/usage.
  • Records for a closed UTC day are immutable (aggregate over spend_logs).
  • Field evolution is additive-only: new fields may appear; existing fields are never removed or renamed without a path-level version bump.
  • Cursor is opaque (base64 of internal position); callers must NOT parse or construct cursor values.
  • Complete-or-loud: any tenant schema error returns 500 naming the tenant (billing data must be complete or explicitly broken — never silently partial, unlike orgs/usage).
  • v1 is PULL (stateless, replayable, external biller controls cadence). Push (scheduled exporter/webhook) is the designed additive extension (see seam doc); it is NOT built in v1.

Ordering: (period_start ASC, org ASC) — deterministic and stable. Auth: AttestedAdminMiddleware.

ParameterInRequiredType
cursorquerynostring
limitquerynointeger
ResponseMeaning
200Page of daily per-org usage records. — version: string, records: array, next_cursor: string
400Malformed body or invalid parameters.
401Missing or invalid bearer token.
403Authenticated but not authorized — e.g. a non-admin caller
500Unexpected server-side failure.
5XXUnexpected server-side failure.

DELETE /management/v1/catalog/tags

Clear a catalog tag

Request body (required): ns: string, key: string, target*: object

ResponseMeaning
200Tag cleared.
400Malformed body or invalid parameters.
401Missing or invalid bearer token.
5XXUnexpected server-side failure.

GET /management/v1/catalog/tags

List catalog tags

ResponseMeaning
200Tag list. — data: array
401Missing or invalid bearer token.
5XXUnexpected server-side failure.

POST /management/v1/catalog/tags

Apply a catalog tag

Request body (required): ns: string, key: string, value: string, target: object

ResponseMeaning
200Tag applied.
400Malformed body or invalid parameters.
401Missing or invalid bearer token.
5XXUnexpected server-side failure.

GET /management/v1/catalog/vector-tables

List vector tables

Paginated, ACL-filtered list of vector tables.

ParameterInRequiredType
cursorquerynostring
limitquerynointeger
searchquerynostring
ResponseMeaning
200Vector table list page. — items: array, next_cursor: string
401Missing or invalid bearer token.
5XXUnexpected server-side failure.

GET /management/v1/catalog/vector-tables/{id}

Get vector table detail

Full vector table detail including schema + vector columns. ACL-enforced.

ParameterInRequiredType
idpathyesstring
ResponseMeaning
200Vector table detail. — object
400Malformed body or invalid parameters.
401Missing or invalid bearer token.
403Authenticated but not authorized — e.g. a non-admin caller
404Resource not found.
5XXUnexpected server-side failure.

GET /management/v1/catalog/vector-tables/{id}/index-status/{jobId}

Poll vector index rebuild status

ParameterInRequiredType
idpathyesstring
jobIdpathyesstring
ResponseMeaning
200Index job status. — status: string, progress_pct: number
400Malformed body or invalid parameters.
401Missing or invalid bearer token.
403Authenticated but not authorized — e.g. a non-admin caller
404Resource not found.
5XXUnexpected server-side failure.

POST /management/v1/catalog/vector-tables/{id}/rebuild-index/{column}

Rebuild a vector column index

Triggers an async IVF_HNSW_SQ index rebuild for the column. Returns a job id.

ParameterInRequiredType
idpathyesstring
columnpathyesstring
ResponseMeaning
202Rebuild accepted. — job_id: string
400Malformed body or invalid parameters.
401Missing or invalid bearer token.
403Authenticated but not authorized — e.g. a non-admin caller
404Resource not found.
5XXUnexpected server-side failure.

GET /management/v1/groups/

List all groups

ResponseMeaning
200The list of groups. — data: array
401Missing or invalid bearer token.
403Authenticated but not authorized — e.g. a non-admin caller
5XXUnexpected server-side failure.

POST /management/v1/groups/

Create a group

Creates a new group (catalog_principal_roles row) plus a dedicated companion catalog role so per-group permissions can be granted. A name collision returns 409.

Request body (required): name*: string, catalog: string

ResponseMeaning
201Group created. — group: object
400Malformed body or invalid parameters.
401Missing or invalid bearer token.
403Authenticated but not authorized — e.g. a non-admin caller
409A group with this name already exists.
5XXUnexpected server-side failure.

DELETE /management/v1/groups/{id}

Delete a group

ResponseMeaning
200Group deleted. — object
401Missing or invalid bearer token.
403Authenticated but not authorized — e.g. a non-admin caller
404Resource not found.
5XXUnexpected server-side failure.

GET /management/v1/groups/{id}

Get a group by id

ResponseMeaning
200The group. — group: object
401Missing or invalid bearer token.
403Authenticated but not authorized — e.g. a non-admin caller
404Resource not found.
5XXUnexpected server-side failure.

GET /management/v1/groups/{id}/members

List a group’s members

ResponseMeaning
200The member principal (actor) strings. — data: array
401Missing or invalid bearer token.
403Authenticated but not authorized — e.g. a non-admin caller
5XXUnexpected server-side failure.

POST /management/v1/groups/{id}/members

Add a member to a group

Request body (required): principal_id*: string

ResponseMeaning
200Member added (idempotent). — object
400Malformed body or invalid parameters.
401Missing or invalid bearer token.
403Authenticated but not authorized — e.g. a non-admin caller
5XXUnexpected server-side failure.

POST /management/v1/groups/{id}/members/remove

Remove a member from a group

Request body (required): principal_id*: string

ResponseMeaning
200Member removed (idempotent). — object
400Malformed body or invalid parameters.
401Missing or invalid bearer token.
403Authenticated but not authorized — e.g. a non-admin caller
5XXUnexpected server-side failure.

POST /management/v1/groups/{id}/permissions

Grant a permission to a group

Grants an AssetPrivilege to the group (applied to the group’s catalog role). object_type/object_id/tenant default to ai_asset / “” / “”.

Request body (required): privilege*: string, object_type: string, object_id: string, tenant: string

ResponseMeaning
200Permission granted (idempotent). — object
400Malformed body or invalid parameters.
401Missing or invalid bearer token.
403Authenticated but not authorized — e.g. a non-admin caller
404Resource not found.
5XXUnexpected server-side failure.

POST /management/v1/groups/{id}/permissions/remove

Revoke a permission from a group

Request body (required): privilege*: string, object_type: string, object_id: string, tenant: string

ResponseMeaning
200Permission revoked (idempotent). — object
400Malformed body or invalid parameters.
401Missing or invalid bearer token.
403Authenticated but not authorized — e.g. a non-admin caller
404Resource not found.
5XXUnexpected server-side failure.

GET /management/v1/orgs/usage

Per-org usage aggregates (quota dashboard data source)

Returns per-org (tenant-slug) request/token/spend aggregates over a rolling time window. Fans out over all tenant schemas + public via ForEachTenantSchema. Continue-on-error: one broken tenant schema does NOT 500 the response — instead “partial”: true is set and the broken schema is skipped. This is the data source for the TRD 7-08 Flutter quota dashboard.

Wire contract (frozen — 7-08 codes against this verbatim):

  • window accepts 7d|30d|90d, default 30d.
  • orgs sorted ascending by slug.
  • org="" rows (public/legacy scope) included only when non-zero AND tenant mode is active.
  • partial=true signals at least one tenant schema was unavailable.

Auth: AttestedAdminMiddleware (attested admin identity required). No billing semantics — raw usage + recorded spend_usd from spend_logs.

ParameterInRequiredType
windowquerynostring
ResponseMeaning
200Per-org usage aggregates for the window. — window: object, orgs: array, partial*: boolean
400Malformed body or invalid parameters.
401Missing or invalid bearer token.
403Authenticated but not authorized — e.g. a non-admin caller
5XXUnexpected server-side failure.

GET /management/v1/tenants

List provisioned tenant slugs

Returns the sorted list of tenant slugs this instance is provisioned for (cfg.TenantSlugs / AOCORE_TENANT_SLUGS, Obj 18 TRD 18-04 contract). When no slugs are configured (multi-tenancy dormant) returns an empty array with dormant=true. Internal multi-org framing only — no reseller or downstream-tenant concepts (7-CONTEXT.md locked decisions 1-2). Consumed by the admin shell org switcher (7-10). Supersedes the G-07 NamespaceSwitcher hardcoded stub as the real tenant-discovery source.

ResponseMeaning
200Tenant slug list. — tenants: array, dormant: boolean
401Missing or invalid bearer token.
403Authenticated but not authorized — e.g. a non-admin caller
5XXUnexpected server-side failure.

POST /management/v1/trino/query

Execute a READ-ONLY Trino query

Runs a SELECT-class statement against Trino and returns columns + rows. READ-ONLY enforced server-side (LOCKED decision 5): any non-SELECT statement (INSERT/UPDATE/DELETE/MERGE/CREATE/DROP/ALTER/TRUNCATE/GRANT/ SET/CALL, multi-statement, or EXPLAIN ANALYZE of a write) is rejected with 403 and error.code trino_read_only BEFORE reaching Trino — defense in depth above the UI gate. Writes belong in pipelines where they carry provenance. Per-identity rate-limited; results capped (413 with Retry-With-Pagination on overflow). Returns 503 when Trino is not configured.

Request body (required): sql*: string, args: array

ResponseMeaning
200Query results. — columns: array, rows: array, stats*: object
400Malformed body or invalid parameters.
401Missing or invalid bearer token.
403Read-only violation (error.code trino_read_only) — a non-SELECT
413Result exceeds the row cap; retry with pagination.
429Per-identity rate limit exceeded.
503Service dependency unavailable — e.g. Temporal workflow engine not
5XXUnexpected server-side failure.

GET /management/v1/trino/query/history

List the caller’s read-only query history

Returns the calling identity’s own Trino workbench query history (Objective 7 TRD 7-01), newest first, capped at 100 rows. Scope is implicit and unforgeable: the actor is taken from the resolved attested principal, never from a query parameter, so no cross-actor access path exists. Reads Postgres (not Trino), so it functions even when the Trino coordinator is unconfigured.

ResponseMeaning
200The caller’s query history (newest first, max 100). — queries*: array
401Missing or invalid bearer token.
403Authenticated but not authorized — e.g. a non-admin caller
5XXUnexpected server-side failure.