5759c1862e
M0-M7 已完成:核心网关(身份/RBAC/TOTP/OIDC/SAML/Provider/配额/路由/内容策略/审计/定价)+ 资源市场(MCP/Skills/数字员工)。 含 22 个 PostgreSQL 迁移、管理端/门户端前端源码、OpenAPI 契约、部署 compose。 Co-Authored-By: Claude <noreply@anthropic.com>
1628 lines
68 KiB
YAML
1628 lines
68 KiB
YAML
openapi: 3.1.0
|
|
info:
|
|
title: AI Gateway Runtime API
|
|
version: 0.10.0
|
|
description: Go rewrite contract. OpenAI-compatible payloads remain intentionally open.
|
|
servers:
|
|
- url: /
|
|
paths:
|
|
/healthz:
|
|
get:
|
|
operationId: getHealth
|
|
responses:
|
|
"200":
|
|
description: Process is alive
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/Health"
|
|
/readyz:
|
|
get:
|
|
operationId: getReadiness
|
|
responses:
|
|
"200":
|
|
description: Required dependencies are ready
|
|
"503":
|
|
description: A required dependency is unavailable
|
|
/metrics:
|
|
get:
|
|
operationId: getMetrics
|
|
responses:
|
|
"200": { description: Prometheus text metrics for runtime, audit, bootstrap and shadow traffic }
|
|
/api/v1/admin/login:
|
|
post:
|
|
operationId: loginAdmin
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema: { $ref: "#/components/schemas/LoginRequest" }
|
|
responses:
|
|
"200": { description: Opaque Redis-backed session token }
|
|
"401": { description: Invalid credentials }
|
|
"429": { description: Account locked }
|
|
/api/v1/admin/whoami:
|
|
get:
|
|
operationId: getAdminIdentity
|
|
security: [{ bearerAuth: [] }]
|
|
responses:
|
|
"200": { description: Active administrator identity and role }
|
|
"401": { description: Invalid or expired session }
|
|
/api/v1/admin/password:
|
|
post:
|
|
operationId: changeAdminPassword
|
|
security: [{ bearerAuth: [] }]
|
|
responses:
|
|
"200": { description: Administrator password changed after current-password verification }
|
|
"401": { description: Current password invalid }
|
|
/api/v1/admin/system-info:
|
|
get:
|
|
operationId: getSystemInfo
|
|
security: [{ bearerAuth: [] }]
|
|
responses: { "200": { description: Version, runtime, uptime and enabled resource counts } }
|
|
/api/v1/admin/monitoring/overview:
|
|
get:
|
|
operationId: getMonitoringOverview
|
|
security: [{ bearerAuth: [] }]
|
|
responses: { "200": { description: PostgreSQL-backed 24-hour request, token, cost and latency summary } }
|
|
/api/v1/admin/reload:
|
|
post:
|
|
operationId: reloadRuntimeSnapshots
|
|
security: [{ bearerAuth: [] }]
|
|
responses: { "200": { description: Provider, content-policy and pricing snapshots reloaded } }
|
|
/api/v1/admin/fact-check/settings:
|
|
get:
|
|
operationId: getFactCheckSettings
|
|
security: [{ bearerAuth: [] }]
|
|
responses: { "200": { description: Fact-check Provider reference, model and timeout without duplicated credentials } }
|
|
put:
|
|
operationId: updateFactCheckSettings
|
|
security: [{ bearerAuth: [] }]
|
|
responses: { "200": { description: Fact-check settings updated } }
|
|
/api/v1/admin/fact-check/policies:
|
|
get:
|
|
operationId: listFactCheckPolicies
|
|
security: [{ bearerAuth: [] }]
|
|
responses: { "200": { description: Scoped fact-check policies } }
|
|
post:
|
|
operationId: createFactCheckPolicy
|
|
security: [{ bearerAuth: [] }]
|
|
responses: { "200": { description: Validated fact-check policy created } }
|
|
/api/v1/admin/fact-check/policies/{policy_id}:
|
|
put:
|
|
operationId: updateFactCheckPolicy
|
|
security: [{ bearerAuth: [] }]
|
|
parameters: [{ name: policy_id, in: path, required: true, schema: { type: string, format: uuid } }]
|
|
responses: { "200": { description: Fact-check policy revision updated } }
|
|
delete:
|
|
operationId: deleteFactCheckPolicy
|
|
security: [{ bearerAuth: [] }]
|
|
parameters: [{ name: policy_id, in: path, required: true, schema: { type: string, format: uuid } }]
|
|
responses: { "200": { description: Fact-check policy deleted } }
|
|
/api/v1/admin/fact-check/events:
|
|
get:
|
|
operationId: listFactCheckEvents
|
|
security: [{ bearerAuth: [] }]
|
|
responses: { "200": { description: Bounded fact-check event summaries } }
|
|
/api/v1/admin/fact-check/events/{event_id}:
|
|
get:
|
|
operationId: getFactCheckEvent
|
|
security: [{ bearerAuth: [] }]
|
|
parameters: [{ name: event_id, in: path, required: true, schema: { type: string, format: uuid } }]
|
|
responses: { "200": { description: Fact-check claims and evidence detail } }
|
|
/api/v1/admin/login/totp:
|
|
post:
|
|
operationId: completeAdminTOTPLogin
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema: { $ref: "#/components/schemas/TOTPLoginRequest" }
|
|
responses:
|
|
"200": { description: TOTP challenge completed and session issued }
|
|
"401": { description: Invalid, reused, or consumed factor }
|
|
/api/v1/admin/totp/status:
|
|
get:
|
|
operationId: getAdminTOTPStatus
|
|
security: [{ bearerAuth: [] }]
|
|
responses:
|
|
"200": { description: TOTP enrollment status }
|
|
/api/v1/admin/totp/setup:
|
|
post:
|
|
operationId: setupAdminTOTP
|
|
security: [{ bearerAuth: [] }]
|
|
responses:
|
|
"200": { description: New secret and otpauth provisioning URI }
|
|
/api/v1/admin/totp/confirm:
|
|
post:
|
|
operationId: confirmAdminTOTP
|
|
security: [{ bearerAuth: [] }]
|
|
responses:
|
|
"200": { description: Enrollment confirmed; backup codes returned once }
|
|
/api/v1/admin/totp/disable:
|
|
post:
|
|
operationId: disableAdminTOTP
|
|
security: [{ bearerAuth: [] }]
|
|
responses:
|
|
"200": { description: TOTP disabled after password and factor verification }
|
|
/api/v1/admin/totp/backup-codes/regenerate:
|
|
post:
|
|
operationId: regenerateAdminTOTPBackupCodes
|
|
security: [{ bearerAuth: [] }]
|
|
responses:
|
|
"200": { description: Previous backup codes revoked and replacements returned once }
|
|
/api/v1/admin/logout:
|
|
post:
|
|
operationId: logoutAdmin
|
|
security: [{ bearerAuth: [] }]
|
|
responses:
|
|
"200": { description: Session revoked }
|
|
/api/v1/admin/menus:
|
|
get:
|
|
operationId: getAdminMenus
|
|
security: [{ bearerAuth: [] }]
|
|
responses:
|
|
"200": { description: Art Design Pro route tree for the active role }
|
|
/api/v1/admin/identities/admins:
|
|
get:
|
|
operationId: listAdministrators
|
|
security: [{ bearerAuth: [] }]
|
|
responses:
|
|
"200": { description: Administrator accounts with direct and effective permissions }
|
|
"403": { description: identity:manage permission required }
|
|
post:
|
|
operationId: createAdministrator
|
|
security: [{ bearerAuth: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema: { $ref: "#/components/schemas/IdentityInput" }
|
|
responses:
|
|
"200": { description: Administrator created and outbox event committed }
|
|
"409": { description: Login already exists }
|
|
/api/v1/admin/identities/admins/{identity_id}:
|
|
put:
|
|
operationId: updateAdministrator
|
|
security: [{ bearerAuth: [] }]
|
|
parameters:
|
|
- $ref: "#/components/parameters/IdentityID"
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema: { $ref: "#/components/schemas/IdentityInput" }
|
|
responses:
|
|
"200": { description: Account and permissions updated immediately }
|
|
"409": { description: Self-disable, self-role change, or duplicate login }
|
|
/api/v1/admin/identities/portal-users:
|
|
get:
|
|
operationId: listPortalUsers
|
|
security: [{ bearerAuth: [] }]
|
|
responses:
|
|
"200": { description: Portal accounts with direct and effective permissions }
|
|
post:
|
|
operationId: createPortalUser
|
|
security: [{ bearerAuth: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema: { $ref: "#/components/schemas/IdentityInput" }
|
|
responses:
|
|
"200": { description: Local portal account created }
|
|
/api/v1/admin/identities/portal-users/{identity_id}:
|
|
put:
|
|
operationId: updatePortalUser
|
|
security: [{ bearerAuth: [] }]
|
|
parameters:
|
|
- $ref: "#/components/parameters/IdentityID"
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema: { $ref: "#/components/schemas/IdentityInput" }
|
|
responses:
|
|
"200": { description: Portal account updated }
|
|
/api/v1/admin/departments:
|
|
get:
|
|
operationId: listDepartments
|
|
security: [{ bearerAuth: [] }]
|
|
responses:
|
|
"200": { description: Flat department catalog with parent names and active user counts }
|
|
post:
|
|
operationId: createDepartment
|
|
security: [{ bearerAuth: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema: { $ref: "#/components/schemas/DepartmentInput" }
|
|
responses:
|
|
"200": { description: Department created with outbox event }
|
|
"409": { description: Duplicate code or invalid hierarchy }
|
|
/api/v1/admin/departments/{department_id}:
|
|
put:
|
|
operationId: updateDepartment
|
|
security: [{ bearerAuth: [] }]
|
|
parameters:
|
|
- name: department_id
|
|
in: path
|
|
required: true
|
|
schema: { type: string, format: uuid }
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema: { $ref: "#/components/schemas/DepartmentInput" }
|
|
responses:
|
|
"200": { description: Department updated with hierarchy validation }
|
|
"409": { description: Cycle or active users/children prevent the update }
|
|
/api/v1/admin/identity-providers:
|
|
get:
|
|
operationId: listIdentityProviders
|
|
security: [{ bearerAuth: [] }]
|
|
responses:
|
|
"200": { description: OIDC providers without client secret material }
|
|
post:
|
|
operationId: createIdentityProvider
|
|
security: [{ bearerAuth: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema: { $ref: "#/components/schemas/OIDCProviderInput" }
|
|
responses:
|
|
"200": { description: Encrypted OIDC provider configuration created }
|
|
/api/v1/admin/identity-providers/{provider_id}:
|
|
put:
|
|
operationId: updateIdentityProvider
|
|
security: [{ bearerAuth: [] }]
|
|
parameters:
|
|
- $ref: "#/components/parameters/ProviderID"
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema: { $ref: "#/components/schemas/OIDCProviderInput" }
|
|
responses:
|
|
"200": { description: OIDC provider updated; omitted secret remains unchanged }
|
|
/api/v1/admin/saml-providers:
|
|
get:
|
|
operationId: listSAMLProviders
|
|
security: [{ bearerAuth: [] }]
|
|
responses:
|
|
"200": { description: SAML identity provider configurations }
|
|
post:
|
|
operationId: createSAMLProvider
|
|
security: [{ bearerAuth: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema: { $ref: "#/components/schemas/SAMLProviderInput" }
|
|
responses:
|
|
"200": { description: SAML provider created after metadata and signing certificate validation }
|
|
/api/v1/admin/saml-providers/{provider_id}:
|
|
put:
|
|
operationId: updateSAMLProvider
|
|
security: [{ bearerAuth: [] }]
|
|
parameters:
|
|
- $ref: "#/components/parameters/ProviderID"
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema: { $ref: "#/components/schemas/SAMLProviderInput" }
|
|
responses:
|
|
"200": { description: SAML provider updated and revision incremented }
|
|
/api/v1/admin/providers:
|
|
get:
|
|
operationId: listProviders
|
|
security: [{ bearerAuth: [] }]
|
|
responses:
|
|
"200": { description: Providers with masked credentials }
|
|
post:
|
|
operationId: createProvider
|
|
security: [{ bearerAuth: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema: { $ref: "#/components/schemas/ProviderInput" }
|
|
responses:
|
|
"200": { description: Provider created and outbox event committed }
|
|
"403": { description: Superadmin role required }
|
|
/api/v1/admin/api-keys:
|
|
get:
|
|
operationId: listAPIKeys
|
|
security: [{ bearerAuth: [] }]
|
|
responses:
|
|
"200": { description: API keys without secret material }
|
|
"403": { description: Superadmin role required }
|
|
post:
|
|
operationId: createAPIKey
|
|
security: [{ bearerAuth: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema: { $ref: "#/components/schemas/APIKeyInput" }
|
|
responses:
|
|
"200": { description: API key secret returned exactly once }
|
|
/api/v1/admin/api-keys/{api_key_id}:
|
|
delete:
|
|
operationId: revokeAPIKey
|
|
security: [{ bearerAuth: [] }]
|
|
parameters:
|
|
- name: api_key_id
|
|
in: path
|
|
required: true
|
|
schema: { type: string, format: uuid }
|
|
responses:
|
|
"200": { description: Key revoked and shared cache invalidated }
|
|
"404": { description: Key not found or already revoked }
|
|
/api/v1/admin/api-keys/{api_key_id}/limits:
|
|
put:
|
|
operationId: updateAPIKeyLimits
|
|
security: [{ bearerAuth: [] }]
|
|
parameters:
|
|
- name: api_key_id
|
|
in: path
|
|
required: true
|
|
schema: { type: string, format: uuid }
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema: { $ref: "#/components/schemas/APIKeyLimitsInput" }
|
|
responses:
|
|
"200": { description: Request and token limits updated; authentication cache invalidated }
|
|
"404": { description: Key not found or already revoked }
|
|
/api/v1/admin/model-routes:
|
|
get:
|
|
operationId: listModelRoutes
|
|
security: [{ bearerAuth: [] }]
|
|
responses:
|
|
"200": { description: Model alias and weighted route rules }
|
|
post:
|
|
operationId: createModelRoute
|
|
security: [{ bearerAuth: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema: { $ref: "#/components/schemas/ModelRouteInput" }
|
|
responses:
|
|
"200": { description: Route committed, snapshot refreshed, and peers notified }
|
|
"409": { description: Duplicate route }
|
|
/api/v1/admin/model-routes/{model_route_id}:
|
|
put:
|
|
operationId: updateModelRoute
|
|
security: [{ bearerAuth: [] }]
|
|
parameters:
|
|
- $ref: "#/components/parameters/ModelRouteID"
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema: { $ref: "#/components/schemas/ModelRouteInput" }
|
|
responses:
|
|
"200": { description: Route updated and active snapshots refreshed }
|
|
"404": { description: Route not found }
|
|
delete:
|
|
operationId: deleteModelRoute
|
|
security: [{ bearerAuth: [] }]
|
|
parameters:
|
|
- $ref: "#/components/parameters/ModelRouteID"
|
|
responses:
|
|
"200": { description: Route deleted and active snapshots refreshed }
|
|
"404": { description: Route not found }
|
|
/api/v1/admin/audit-events:
|
|
get:
|
|
operationId: listAuditEvents
|
|
security: [{ bearerAuth: [] }]
|
|
parameters:
|
|
- { name: from, in: query, schema: { type: string, format: date-time } }
|
|
- { name: to, in: query, schema: { type: string, format: date-time } }
|
|
- { name: before, in: query, schema: { type: string, format: date-time } }
|
|
- { name: api_key_id, in: query, schema: { type: string, format: uuid } }
|
|
- { name: provider, in: query, schema: { type: string } }
|
|
- { name: model, in: query, schema: { type: string } }
|
|
- { name: status, in: query, schema: { type: integer, minimum: 100, maximum: 599 } }
|
|
- { name: limit, in: query, schema: { type: integer, minimum: 1, maximum: 200, default: 50 } }
|
|
responses:
|
|
"200": { description: Cursor-paginated gateway audit events }
|
|
"403": { description: audit:read permission required }
|
|
/api/v1/admin/usage/daily:
|
|
get:
|
|
operationId: listDailyUsage
|
|
security: [{ bearerAuth: [] }]
|
|
parameters:
|
|
- { name: from, in: query, schema: { type: string, format: date } }
|
|
- { name: to, in: query, schema: { type: string, format: date } }
|
|
- { name: api_key_id, in: query, schema: { type: string, format: uuid } }
|
|
- { name: provider, in: query, schema: { type: string } }
|
|
- { name: model, in: query, schema: { type: string } }
|
|
responses:
|
|
"200": { description: Daily request, failure, and token aggregates }
|
|
"403": { description: usage:read permission required }
|
|
/api/v1/admin/outbox-events:
|
|
get:
|
|
operationId: listOutboxEvents
|
|
security: [{ bearerAuth: [] }]
|
|
parameters:
|
|
- { name: status, in: query, schema: { type: string, enum: [pending, dead, processed] } }
|
|
- { name: type, in: query, schema: { type: string } }
|
|
- { name: limit, in: query, schema: { type: integer, minimum: 1, maximum: 500, default: 100 } }
|
|
responses:
|
|
"200": { description: Pending, dead-lettered, or processed transactional outbox events }
|
|
"403": { description: outbox:read permission required }
|
|
/api/v1/admin/outbox-events/{event_id}/retry:
|
|
post:
|
|
operationId: retryOutboxEvent
|
|
security: [{ bearerAuth: [] }]
|
|
parameters:
|
|
- name: event_id
|
|
in: path
|
|
required: true
|
|
schema: { type: string, format: uuid }
|
|
responses:
|
|
"200": { description: Pending or dead-lettered event made immediately claimable }
|
|
"403": { description: outbox:manage permission required }
|
|
"404": { description: Unprocessed event not found }
|
|
/api/v1/admin/content-policies:
|
|
get:
|
|
operationId: listContentPolicies
|
|
security: [{ bearerAuth: [] }]
|
|
responses:
|
|
"200": { description: Ordered content policy definitions }
|
|
"403": { description: content_policy:read permission required }
|
|
post:
|
|
operationId: createContentPolicy
|
|
security: [{ bearerAuth: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema: { $ref: "#/components/schemas/ContentPolicyInput" }
|
|
responses:
|
|
"200": { description: Policy committed, compiled, and activated locally }
|
|
"400": { description: Invalid RE2 rule or policy scope }
|
|
/api/v1/admin/content-policies/{policy_id}:
|
|
put:
|
|
operationId: updateContentPolicy
|
|
security: [{ bearerAuth: [] }]
|
|
parameters: [{ name: policy_id, in: path, required: true, schema: { type: string, format: uuid } }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema: { $ref: "#/components/schemas/ContentPolicyInput" }
|
|
responses:
|
|
"200": { description: Policy revision updated and snapshot reloaded }
|
|
"404": { description: Policy not found }
|
|
delete:
|
|
operationId: deleteContentPolicy
|
|
security: [{ bearerAuth: [] }]
|
|
parameters: [{ name: policy_id, in: path, required: true, schema: { type: string, format: uuid } }]
|
|
responses:
|
|
"200": { description: Policy deleted and snapshot reloaded }
|
|
/api/v1/admin/model-prices:
|
|
get:
|
|
operationId: listModelPrices
|
|
security: [{ bearerAuth: [] }]
|
|
responses:
|
|
"200": { description: Versioned model price definitions }
|
|
"403": { description: pricing:read permission required }
|
|
post:
|
|
operationId: createModelPrice
|
|
security: [{ bearerAuth: [] }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema: { $ref: "#/components/schemas/ModelPriceInput" }
|
|
responses:
|
|
"200": { description: Price version created and runtime snapshot reloaded }
|
|
/api/v1/admin/model-prices/{price_id}:
|
|
put:
|
|
operationId: updateModelPrice
|
|
security: [{ bearerAuth: [] }]
|
|
parameters: [{ name: price_id, in: path, required: true, schema: { type: string, format: uuid } }]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema: { $ref: "#/components/schemas/ModelPriceInput" }
|
|
responses:
|
|
"200": { description: Price revision updated and runtime snapshot reloaded }
|
|
delete:
|
|
operationId: deleteModelPrice
|
|
security: [{ bearerAuth: [] }]
|
|
parameters: [{ name: price_id, in: path, required: true, schema: { type: string, format: uuid } }]
|
|
responses:
|
|
"200": { description: Price version deleted }
|
|
/api/v1/admin/prompts:
|
|
get:
|
|
operationId: listPrompts
|
|
security: [{ bearerAuth: [] }]
|
|
responses: { "200": { description: Prompt templates and active immutable versions } }
|
|
post:
|
|
operationId: createPrompt
|
|
security: [{ bearerAuth: [] }]
|
|
requestBody: { required: true, content: { application/json: { schema: { $ref: "#/components/schemas/PromptInput" } } } }
|
|
responses: { "200": { description: Template and initial immutable version created } }
|
|
/api/v1/admin/prompts/{prompt_id}:
|
|
get:
|
|
operationId: getPrompt
|
|
security: [{ bearerAuth: [] }]
|
|
parameters: [{ name: prompt_id, in: path, required: true, schema: { type: string, format: uuid } }]
|
|
responses: { "200": { description: Prompt metadata and current immutable version } }
|
|
put:
|
|
operationId: updatePromptMetadata
|
|
security: [{ bearerAuth: [] }]
|
|
parameters: [{ name: prompt_id, in: path, required: true, schema: { type: string, format: uuid } }]
|
|
requestBody: { required: true, content: { application/json: { schema: { $ref: "#/components/schemas/PromptInput" } } } }
|
|
responses: { "200": { description: Prompt metadata updated without mutating version content } }
|
|
delete:
|
|
operationId: deletePrompt
|
|
security: [{ bearerAuth: [] }]
|
|
parameters: [{ name: prompt_id, in: path, required: true, schema: { type: string, format: uuid } }]
|
|
responses: { "200": { description: Prompt and versions deleted } }
|
|
/api/v1/admin/prompts/{prompt_id}/versions:
|
|
get:
|
|
operationId: listPromptVersions
|
|
security: [{ bearerAuth: [] }]
|
|
parameters: [{ name: prompt_id, in: path, required: true, schema: { type: string, format: uuid } }]
|
|
responses: { "200": { description: Immutable Prompt version history } }
|
|
post:
|
|
operationId: createPromptVersion
|
|
security: [{ bearerAuth: [] }]
|
|
parameters: [{ name: prompt_id, in: path, required: true, schema: { type: string, format: uuid } }]
|
|
responses: { "200": { description: New immutable version created and optionally activated } }
|
|
/api/v1/admin/prompts/{prompt_id}/versions/{version}/activate:
|
|
post:
|
|
operationId: activatePromptVersion
|
|
security: [{ bearerAuth: [] }]
|
|
parameters:
|
|
- { name: prompt_id, in: path, required: true, schema: { type: string, format: uuid } }
|
|
- { name: version, in: path, required: true, schema: { type: integer, minimum: 1 } }
|
|
responses: { "200": { description: Historical immutable version made current } }
|
|
/api/v1/admin/prompts/{prompt_id}/render:
|
|
post:
|
|
operationId: previewPrompt
|
|
security: [{ bearerAuth: [] }]
|
|
parameters: [{ name: prompt_id, in: path, required: true, schema: { type: string, format: uuid } }]
|
|
responses: { "200": { description: Current Prompt rendered for control-plane preview } }
|
|
/api/v1/admin/prompt-categories:
|
|
get:
|
|
operationId: listPromptCategories
|
|
security: [{ bearerAuth: [] }]
|
|
responses: { "200": { description: Prompt categories with template counts } }
|
|
post:
|
|
operationId: createPromptCategory
|
|
security: [{ bearerAuth: [] }]
|
|
responses: { "200": { description: Prompt category created } }
|
|
/api/v1/admin/prompt-categories/{category_id}:
|
|
delete:
|
|
operationId: deletePromptCategory
|
|
security: [{ bearerAuth: [] }]
|
|
parameters: [{ name: category_id, in: path, required: true, schema: { type: string, format: uuid } }]
|
|
responses: { "200": { description: Category removed and templates made uncategorized } }
|
|
/api/v1/admin/knowledge-bases:
|
|
get:
|
|
operationId: listKnowledgeBases
|
|
security: [{ bearerAuth: [] }]
|
|
responses: { "200": { description: PostgreSQL-backed knowledge bases } }
|
|
post:
|
|
operationId: createKnowledgeBase
|
|
security: [{ bearerAuth: [] }]
|
|
requestBody: { required: true, content: { application/json: { schema: { $ref: "#/components/schemas/KnowledgeBaseInput" } } } }
|
|
responses: { "200": { description: Knowledge base created } }
|
|
/api/v1/admin/knowledge-bases/{knowledge_base_id}:
|
|
put:
|
|
operationId: updateKnowledgeBase
|
|
security: [{ bearerAuth: [] }]
|
|
parameters: [{ name: knowledge_base_id, in: path, required: true, schema: { type: string, format: uuid } }]
|
|
requestBody: { required: true, content: { application/json: { schema: { $ref: "#/components/schemas/KnowledgeBaseInput" } } } }
|
|
responses: { "200": { description: Knowledge base updated } }
|
|
delete:
|
|
operationId: deleteKnowledgeBase
|
|
security: [{ bearerAuth: [] }]
|
|
parameters: [{ name: knowledge_base_id, in: path, required: true, schema: { type: string, format: uuid } }]
|
|
responses: { "200": { description: Unreferenced knowledge base deleted } }
|
|
/api/v1/admin/knowledge-bases/{knowledge_base_id}/documents:
|
|
get:
|
|
operationId: listKnowledgeDocuments
|
|
security: [{ bearerAuth: [] }]
|
|
parameters: [{ name: knowledge_base_id, in: path, required: true, schema: { type: string, format: uuid } }]
|
|
responses: { "200": { description: Bounded extracted-text documents } }
|
|
post:
|
|
operationId: addKnowledgeDocument
|
|
security: [{ bearerAuth: [] }]
|
|
parameters: [{ name: knowledge_base_id, in: path, required: true, schema: { type: string, format: uuid } }]
|
|
responses: { "200": { description: Document stored in PostgreSQL and synchronously chunked } }
|
|
/api/v1/admin/knowledge-bases/{knowledge_base_id}/documents/{document_id}:
|
|
delete:
|
|
operationId: deleteKnowledgeDocument
|
|
security: [{ bearerAuth: [] }]
|
|
parameters:
|
|
- { name: knowledge_base_id, in: path, required: true, schema: { type: string, format: uuid } }
|
|
- { name: document_id, in: path, required: true, schema: { type: string, format: uuid } }
|
|
responses: { "200": { description: Document and chunks deleted } }
|
|
/api/v1/admin/knowledge-bases/{knowledge_base_id}/documents/{document_id}/reprocess:
|
|
post:
|
|
operationId: reprocessKnowledgeDocument
|
|
security: [{ bearerAuth: [] }]
|
|
parameters:
|
|
- { name: knowledge_base_id, in: path, required: true, schema: { type: string, format: uuid } }
|
|
- { name: document_id, in: path, required: true, schema: { type: string, format: uuid } }
|
|
responses: { "200": { description: Stored bounded text re-chunked transactionally } }
|
|
/api/v1/admin/knowledge-bases/{knowledge_base_id}/search:
|
|
post:
|
|
operationId: testKnowledgeSearch
|
|
security: [{ bearerAuth: [] }]
|
|
parameters: [{ name: knowledge_base_id, in: path, required: true, schema: { type: string, format: uuid } }]
|
|
responses: { "200": { description: Retriever test results } }
|
|
/api/v1/admin/tools:
|
|
get:
|
|
operationId: listTools
|
|
security: [{ bearerAuth: [] }]
|
|
responses: { "200": { description: HTTP tool definitions without decrypted secret headers } }
|
|
post:
|
|
operationId: createTool
|
|
security: [{ bearerAuth: [] }]
|
|
requestBody: { required: true, content: { application/json: { schema: { $ref: "#/components/schemas/ToolInput" } } } }
|
|
responses: { "200": { description: SSRF-validated tool with encrypted headers created } }
|
|
/api/v1/admin/tools/{tool_id}:
|
|
put:
|
|
operationId: updateTool
|
|
security: [{ bearerAuth: [] }]
|
|
parameters: [{ name: tool_id, in: path, required: true, schema: { type: string, format: uuid } }]
|
|
requestBody: { required: true, content: { application/json: { schema: { $ref: "#/components/schemas/ToolInput" } } } }
|
|
responses: { "200": { description: Tool revision updated } }
|
|
delete:
|
|
operationId: deleteTool
|
|
security: [{ bearerAuth: [] }]
|
|
parameters: [{ name: tool_id, in: path, required: true, schema: { type: string, format: uuid } }]
|
|
responses: { "200": { description: Unreferenced tool deleted } }
|
|
/api/v1/admin/tools/{tool_id}/test:
|
|
post:
|
|
operationId: testTool
|
|
security: [{ bearerAuth: [] }]
|
|
parameters: [{ name: tool_id, in: path, required: true, schema: { type: string, format: uuid } }]
|
|
responses: { "200": { description: Bounded SSRF-safe administrative tool test } }
|
|
/api/v1/admin/applications:
|
|
get:
|
|
operationId: listApplications
|
|
security: [{ bearerAuth: [] }]
|
|
responses: { "200": { description: Application drafts and current published versions } }
|
|
post:
|
|
operationId: createApplication
|
|
security: [{ bearerAuth: [] }]
|
|
requestBody: { required: true, content: { application/json: { schema: { $ref: "#/components/schemas/ApplicationInput" } } } }
|
|
responses: { "200": { description: Application draft created } }
|
|
/api/v1/admin/applications/catalog:
|
|
get:
|
|
operationId: getApplicationCompositionCatalog
|
|
security: [{ bearerAuth: [] }]
|
|
responses: { "200": { description: Prompt, knowledge and tool assets available for composition } }
|
|
/api/v1/admin/applications/asset-dependencies:
|
|
get:
|
|
operationId: getApplicationAssetDependencies
|
|
security: [{ bearerAuth: [] }]
|
|
parameters:
|
|
- { name: asset_type, in: query, required: true, schema: { type: string, enum: [prompt, knowledge, tool] } }
|
|
- { name: asset_id, in: query, required: true, schema: { type: string, format: uuid } }
|
|
responses: { "200": { description: Draft and published application references to an asset } }
|
|
/api/v1/admin/applications/{application_id}/publish:
|
|
post:
|
|
operationId: publishApplication
|
|
security: [{ bearerAuth: [] }]
|
|
parameters: [{ name: application_id, in: path, required: true, schema: { type: string, format: uuid } }]
|
|
responses: { "200": { description: Validated immutable application composition published } }
|
|
/api/v1/admin/applications/{application_id}:
|
|
get:
|
|
operationId: getApplication
|
|
security: [{ bearerAuth: [] }]
|
|
parameters: [{ name: application_id, in: path, required: true, schema: { type: string, format: uuid } }]
|
|
responses: { "200": { description: Application composition and immutable version history } }
|
|
put:
|
|
operationId: updateApplication
|
|
security: [{ bearerAuth: [] }]
|
|
parameters: [{ name: application_id, in: path, required: true, schema: { type: string, format: uuid } }]
|
|
requestBody: { required: true, content: { application/json: { schema: { $ref: "#/components/schemas/ApplicationInput" } } } }
|
|
responses: { "200": { description: Application draft updated } }
|
|
delete:
|
|
operationId: deleteApplication
|
|
security: [{ bearerAuth: [] }]
|
|
parameters: [{ name: application_id, in: path, required: true, schema: { type: string, format: uuid } }]
|
|
responses: { "200": { description: Application and its versions deleted } }
|
|
/api/v1/admin/applications/{application_id}/rollback/{version}:
|
|
post:
|
|
operationId: rollbackApplication
|
|
security: [{ bearerAuth: [] }]
|
|
parameters:
|
|
- { name: application_id, in: path, required: true, schema: { type: string, format: uuid } }
|
|
- { name: version, in: path, required: true, schema: { type: integer, minimum: 1 } }
|
|
responses: { "200": { description: Historical composition copied into a new immutable published version } }
|
|
/api/v1/admin/applications/{application_id}/versions:
|
|
get:
|
|
operationId: listApplicationVersions
|
|
security: [{ bearerAuth: [] }]
|
|
parameters: [{ name: application_id, in: path, required: true, schema: { type: string, format: uuid } }]
|
|
responses: { "200": { description: Immutable application publication history } }
|
|
/api/v1/admin/applications/{application_id}/runs:
|
|
get:
|
|
operationId: listApplicationRuns
|
|
security: [{ bearerAuth: [] }]
|
|
parameters: [{ name: application_id, in: path, required: true, schema: { type: string, format: uuid } }]
|
|
responses: { "200": { description: Recent application orchestration runs } }
|
|
/api/v1/admin/notification-channels:
|
|
get:
|
|
operationId: listNotificationChannels
|
|
security: [{ bearerAuth: [] }]
|
|
responses: { "200": { description: Webhook subscriptions without decrypted signing secrets } }
|
|
post:
|
|
operationId: createNotificationChannel
|
|
security: [{ bearerAuth: [] }]
|
|
requestBody: { required: true, content: { application/json: { schema: { $ref: "#/components/schemas/NotificationChannelInput" } } } }
|
|
responses: { "200": { description: Signed Webhook subscription created } }
|
|
/api/v1/admin/notification-deliveries:
|
|
get:
|
|
operationId: listNotificationDeliveries
|
|
security: [{ bearerAuth: [] }]
|
|
responses: { "200": { description: Durable Webhook delivery history } }
|
|
/api/v1/admin/notification-channels/{channel_id}:
|
|
put:
|
|
operationId: updateNotificationChannel
|
|
security: [{ bearerAuth: [] }]
|
|
parameters: [{ name: channel_id, in: path, required: true, schema: { type: string, format: uuid } }]
|
|
requestBody: { required: true, content: { application/json: { schema: { $ref: "#/components/schemas/NotificationChannelInput" } } } }
|
|
responses: { "200": { description: Notification channel updated } }
|
|
delete:
|
|
operationId: deleteNotificationChannel
|
|
security: [{ bearerAuth: [] }]
|
|
parameters: [{ name: channel_id, in: path, required: true, schema: { type: string, format: uuid } }]
|
|
responses: { "200": { description: Notification channel and deliveries deleted } }
|
|
/api/v1/admin/notification-deliveries/{delivery_id}/retry:
|
|
post:
|
|
operationId: retryNotificationDelivery
|
|
security: [{ bearerAuth: [] }]
|
|
parameters: [{ name: delivery_id, in: path, required: true, schema: { type: string, format: uuid } }]
|
|
responses: { "200": { description: Failed delivery attempted immediately } }
|
|
/v1/prompts:
|
|
get:
|
|
operationId: listRuntimePrompts
|
|
security: [{ apiKeyAuth: [] }]
|
|
responses: { "200": { description: Visible enabled Prompt definitions without template bodies } }
|
|
/v1/prompts/{prompt_name}/render:
|
|
post:
|
|
operationId: renderPrompt
|
|
security: [{ apiKeyAuth: [] }]
|
|
parameters: [{ name: prompt_name, in: path, required: true, schema: { type: string } }]
|
|
responses: { "200": { description: Active template rendered after required-variable validation } }
|
|
/v1/knowledge/{knowledge_base_id}/search:
|
|
post:
|
|
operationId: searchKnowledge
|
|
security: [{ apiKeyAuth: [] }]
|
|
parameters: [{ name: knowledge_base_id, in: path, required: true, schema: { type: string, format: uuid } }]
|
|
responses: { "200": { description: Department-scoped Retriever results } }
|
|
/v1/knowledge/search:
|
|
post:
|
|
operationId: searchKnowledgeLegacyShape
|
|
security: [{ apiKeyAuth: [] }]
|
|
responses: { "200": { description: Knowledge search with knowledge_base_id in the JSON body } }
|
|
/v1/tools:
|
|
get:
|
|
operationId: listRuntimeTools
|
|
security: [{ apiKeyAuth: [] }]
|
|
responses: { "200": { description: Department-scoped tool schemas without encrypted headers } }
|
|
/v1/tools/{tool_code}/invoke:
|
|
post:
|
|
operationId: invokeTool
|
|
security: [{ apiKeyAuth: [] }]
|
|
parameters: [{ name: tool_code, in: path, required: true, schema: { type: string } }]
|
|
responses: { "200": { description: Schema-validated, SSRF-safe bounded HTTP tool result } }
|
|
/v1/applications/{application_code}/chat/completions:
|
|
post:
|
|
operationId: runApplication
|
|
security: [{ apiKeyAuth: [] }]
|
|
parameters: [{ name: application_code, in: path, required: true, schema: { type: string } }]
|
|
responses: { "200": { description: Prompt, retrieval and bounded tool loop executed through the governed gateway } }
|
|
/api/v1/admin/providers/{provider_id}:
|
|
put:
|
|
operationId: updateProvider
|
|
security: [{ bearerAuth: [] }]
|
|
parameters:
|
|
- name: provider_id
|
|
in: path
|
|
required: true
|
|
schema: { type: string, format: uuid }
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema: { $ref: "#/components/schemas/ProviderInput" }
|
|
responses:
|
|
"200": { description: Provider updated and revision incremented }
|
|
"404": { description: Provider not found }
|
|
/api/v1/admin/providers/{provider_id}/test:
|
|
post:
|
|
operationId: testProviderConnection
|
|
security: [{ bearerAuth: [] }]
|
|
parameters:
|
|
- $ref: "#/components/parameters/ProviderID"
|
|
responses:
|
|
"200":
|
|
description: Bounded connectivity test against the upstream models endpoint
|
|
content:
|
|
application/json:
|
|
schema: { $ref: "#/components/schemas/ProviderConnectionResult" }
|
|
"404": { description: Provider not found }
|
|
"502": { description: Upstream network request failed }
|
|
/api/v1/admin/providers/{provider_id}/models:
|
|
get:
|
|
operationId: listProviderModels
|
|
security: [{ bearerAuth: [] }]
|
|
parameters:
|
|
- $ref: "#/components/parameters/ProviderID"
|
|
responses:
|
|
"200":
|
|
description: Current and historical provider model catalog
|
|
"404": { description: Provider not found }
|
|
/api/v1/admin/providers/{provider_id}/models/sync:
|
|
post:
|
|
operationId: syncProviderModels
|
|
security: [{ bearerAuth: [] }]
|
|
parameters:
|
|
- $ref: "#/components/parameters/ProviderID"
|
|
responses:
|
|
"200":
|
|
description: Model catalog transactionally synchronized and outbox event committed
|
|
content:
|
|
application/json:
|
|
schema: { $ref: "#/components/schemas/ModelSyncResult" }
|
|
"404": { description: Provider not found }
|
|
"502": { description: Upstream response failed validation }
|
|
/api/v1/admin/providers/credentials/rotate:
|
|
post:
|
|
operationId: rotateProviderCredentials
|
|
description: Re-encrypt every Provider credential not already using the active KEK version.
|
|
security: [{ bearerAuth: [] }]
|
|
responses:
|
|
"200":
|
|
description: All required credential updates and outbox events committed atomically
|
|
content:
|
|
application/json:
|
|
schema: { $ref: "#/components/schemas/CredentialRotationResult" }
|
|
/api/v1/portal/login:
|
|
post:
|
|
operationId: loginPortal
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema: { $ref: "#/components/schemas/LoginRequest" }
|
|
responses:
|
|
"200": { description: Opaque Redis-backed portal session token }
|
|
"401": { description: Invalid credentials }
|
|
/api/v1/portal/sso/providers:
|
|
get:
|
|
operationId: listPublicSSOProviders
|
|
responses:
|
|
"200": { description: Enabled OIDC and SAML providers safe for login-page display }
|
|
/api/v1/portal/sso/{provider_code}/start:
|
|
get:
|
|
operationId: startSSOLogin
|
|
parameters:
|
|
- name: provider_code
|
|
in: path
|
|
required: true
|
|
schema: { type: string }
|
|
responses:
|
|
"302": { description: Redirect to the OIDC authorization endpoint or SAML Redirect-binding SSO endpoint }
|
|
/api/v1/portal/sso/{provider_code}/callback:
|
|
get:
|
|
operationId: completeOIDCLogin
|
|
parameters:
|
|
- name: provider_code
|
|
in: path
|
|
required: true
|
|
schema: { type: string }
|
|
responses:
|
|
"302": { description: Verified identity redirects with a one-minute single-use exchange code }
|
|
"401": { description: State or ID Token validation failed }
|
|
post:
|
|
operationId: completeSAMLLogin
|
|
parameters:
|
|
- name: provider_code
|
|
in: path
|
|
required: true
|
|
schema: { type: string }
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/x-www-form-urlencoded:
|
|
schema:
|
|
type: object
|
|
required: [SAMLResponse, RelayState]
|
|
properties:
|
|
SAMLResponse: { type: string, format: byte }
|
|
RelayState: { type: string }
|
|
responses:
|
|
"302": { description: Signed assertion accepted and browser redirected with a single-use exchange code }
|
|
"401": { description: Signature, request correlation, assertion, or replay validation failed }
|
|
/api/v1/portal/sso/{provider_code}/metadata:
|
|
get:
|
|
operationId: getSAMLServiceProviderMetadata
|
|
parameters:
|
|
- name: provider_code
|
|
in: path
|
|
required: true
|
|
schema: { type: string }
|
|
responses:
|
|
"200": { description: SAML Service Provider metadata XML }
|
|
"404": { description: SAML provider not found }
|
|
/api/v1/portal/sso/exchange:
|
|
post:
|
|
operationId: exchangeOIDCCode
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required: [code]
|
|
properties:
|
|
code: { type: string }
|
|
responses:
|
|
"200": { description: Redis-backed portal session token }
|
|
"401": { description: Exchange code invalid, expired, or already consumed }
|
|
/api/v1/portal/me:
|
|
get:
|
|
operationId: getPortalIdentity
|
|
security: [{ bearerAuth: [] }]
|
|
responses:
|
|
"200": { description: Active portal identity }
|
|
/api/v1/portal/login/totp:
|
|
post:
|
|
operationId: completePortalTOTPLogin
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema: { $ref: "#/components/schemas/TOTPLoginRequest" }
|
|
responses:
|
|
"200": { description: TOTP challenge completed and session issued }
|
|
"401": { description: Invalid, reused, or consumed factor }
|
|
/api/v1/portal/totp/status:
|
|
get:
|
|
operationId: getPortalTOTPStatus
|
|
security: [{ bearerAuth: [] }]
|
|
responses:
|
|
"200": { description: TOTP enrollment status }
|
|
/api/v1/portal/totp/setup:
|
|
post:
|
|
operationId: setupPortalTOTP
|
|
security: [{ bearerAuth: [] }]
|
|
responses:
|
|
"200": { description: New secret and otpauth provisioning URI }
|
|
/api/v1/portal/totp/confirm:
|
|
post:
|
|
operationId: confirmPortalTOTP
|
|
security: [{ bearerAuth: [] }]
|
|
responses:
|
|
"200": { description: Enrollment confirmed; backup codes returned once }
|
|
/api/v1/portal/totp/disable:
|
|
post:
|
|
operationId: disablePortalTOTP
|
|
security: [{ bearerAuth: [] }]
|
|
responses:
|
|
"200": { description: TOTP disabled after password and factor verification }
|
|
/api/v1/portal/totp/backup-codes/regenerate:
|
|
post:
|
|
operationId: regeneratePortalTOTPBackupCodes
|
|
security: [{ bearerAuth: [] }]
|
|
responses:
|
|
"200": { description: Previous backup codes revoked and replacements returned once }
|
|
/api/v1/portal/logout:
|
|
post:
|
|
operationId: logoutPortal
|
|
security: [{ bearerAuth: [] }]
|
|
responses:
|
|
"200": { description: Session revoked }
|
|
/api/v1/portal/menus:
|
|
get:
|
|
operationId: getPortalMenus
|
|
security: [{ bearerAuth: [] }]
|
|
responses:
|
|
"200": { description: Art Design Pro portal route tree }
|
|
/api/v1/portal/password:
|
|
post:
|
|
operationId: changePortalPassword
|
|
security: [{ bearerAuth: [] }]
|
|
responses: { "200": { description: Local password changed after current-password verification } }
|
|
/api/v1/portal/applications:
|
|
get:
|
|
operationId: listPortalApplications
|
|
security: [{ bearerAuth: [] }]
|
|
responses: { "200": { description: Published applications visible to the portal user's department } }
|
|
/api/v1/portal/catalog:
|
|
get:
|
|
operationId: getPortalCatalog
|
|
security: [{ bearerAuth: [] }]
|
|
responses: { "200": { description: Department-scoped application and AI asset catalog } }
|
|
/api/v1/portal/knowledge:
|
|
get:
|
|
operationId: listPortalKnowledge
|
|
security: [{ bearerAuth: [] }]
|
|
responses: { "200": { description: Enabled visible knowledge bases } }
|
|
/api/v1/portal/tools:
|
|
get:
|
|
operationId: listPortalTools
|
|
security: [{ bearerAuth: [] }]
|
|
responses: { "200": { description: Enabled visible tool metadata without endpoint or secret headers } }
|
|
/api/v1/portal/prompts:
|
|
get:
|
|
operationId: listPortalPrompts
|
|
security: [{ bearerAuth: [] }]
|
|
responses: { "200": { description: Enabled visible prompts with favorite state } }
|
|
/api/v1/portal/prompts/{prompt_id}:
|
|
get:
|
|
operationId: getPortalPrompt
|
|
security: [{ bearerAuth: [] }]
|
|
parameters: [{ name: prompt_id, in: path, required: true, schema: { type: string, format: uuid } }]
|
|
responses: { "200": { description: Visible prompt and current immutable content } }
|
|
/api/v1/portal/prompts/{prompt_id}/favorite:
|
|
post:
|
|
operationId: favoritePortalPrompt
|
|
security: [{ bearerAuth: [] }]
|
|
parameters: [{ name: prompt_id, in: path, required: true, schema: { type: string, format: uuid } }]
|
|
responses: { "200": { description: Prompt added to favorites idempotently } }
|
|
delete:
|
|
operationId: unfavoritePortalPrompt
|
|
security: [{ bearerAuth: [] }]
|
|
parameters: [{ name: prompt_id, in: path, required: true, schema: { type: string, format: uuid } }]
|
|
responses: { "200": { description: Prompt removed from favorites idempotently } }
|
|
/api/v1/portal/model-requests/available:
|
|
get:
|
|
operationId: listPortalAvailableModels
|
|
security: [{ bearerAuth: [] }]
|
|
responses: { "200": { description: Enabled provider model catalog } }
|
|
/api/v1/portal/model-requests:
|
|
get:
|
|
operationId: listPortalModelRequests
|
|
security: [{ bearerAuth: [] }]
|
|
responses: { "200": { description: Current user's model access requests } }
|
|
post:
|
|
operationId: createPortalModelRequest
|
|
security: [{ bearerAuth: [] }]
|
|
responses: { "200": { description: Pending model access request created with outbox event } }
|
|
/api/v1/portal/logs:
|
|
get:
|
|
operationId: listPortalAuditEvents
|
|
security: [{ bearerAuth: [] }]
|
|
responses: { "200": { description: Bounded audit events owned through portal API keys } }
|
|
/api/v1/portal/logs/{audit_event_id}:
|
|
get:
|
|
operationId: getPortalAuditEvent
|
|
security: [{ bearerAuth: [] }]
|
|
parameters: [{ name: audit_event_id, in: path, required: true, schema: { type: string, format: uuid } }]
|
|
responses: { "200": { description: Owned audit event with bounded previews } }
|
|
/api/v1/portal/stats:
|
|
get:
|
|
operationId: getPortalStats
|
|
security: [{ bearerAuth: [] }]
|
|
responses: { "200": { description: Personal requests, tokens, cost and latency aggregate } }
|
|
/api/v1/portal/cost:
|
|
get:
|
|
operationId: getPortalCost
|
|
security: [{ bearerAuth: [] }]
|
|
responses: { "200": { description: Personal month-to-date cost in integer microunits } }
|
|
/api/v1/portal/docs-info:
|
|
get:
|
|
operationId: getPortalIntegrationDocs
|
|
security: [{ bearerAuth: [] }]
|
|
responses: { "200": { description: Safe runtime protocol and authentication overview } }
|
|
/api/v1/portal/apps/{application_code}/chat:
|
|
post:
|
|
operationId: runPortalApplicationCompatibilityChat
|
|
security: [{ bearerAuth: [] }]
|
|
parameters: [{ name: application_code, in: path, required: true, schema: { type: string } }]
|
|
responses: { "200": { description: Single user message executed with a server-held encrypted application credential } }
|
|
/api/v1/portal/apps/{application_code}/conversations:
|
|
post:
|
|
operationId: createPortalApplicationConversation
|
|
security: [{ bearerAuth: [] }]
|
|
parameters: [{ name: application_code, in: path, required: true, schema: { type: string } }]
|
|
responses: { "200": { description: Server-managed conversation created } }
|
|
/api/v1/portal/apps/{application_code}/conversations/{conversation_id}:
|
|
get:
|
|
operationId: getPortalApplicationConversation
|
|
security: [{ bearerAuth: [] }]
|
|
parameters:
|
|
- { name: application_code, in: path, required: true, schema: { type: string } }
|
|
- { name: conversation_id, in: path, required: true, schema: { type: string, format: uuid } }
|
|
responses: { "200": { description: Ownership-checked conversation with verified immutable hash chain } }
|
|
/api/v1/portal/apps/{application_code}/conversations/{conversation_id}/messages:
|
|
post:
|
|
operationId: appendPortalApplicationConversationMessage
|
|
security: [{ bearerAuth: [] }]
|
|
parameters:
|
|
- { name: application_code, in: path, required: true, schema: { type: string } }
|
|
- { name: conversation_id, in: path, required: true, schema: { type: string, format: uuid } }
|
|
responses: { "200": { description: Leased serial message execution with verified server-side history } }
|
|
/api/v1/admin/models:
|
|
get:
|
|
operationId: listAdministrativeModels
|
|
security: [{ bearerAuth: [] }]
|
|
responses: { "200": { description: Enabled provider model catalog } }
|
|
/api/v1/admin/model-requests:
|
|
get:
|
|
operationId: listAdministrativeModelRequests
|
|
security: [{ bearerAuth: [] }]
|
|
responses: { "200": { description: Portal model access requests by status } }
|
|
/api/v1/admin/model-requests/{request_id}/approve:
|
|
post:
|
|
operationId: approveModelRequest
|
|
security: [{ bearerAuth: [] }]
|
|
parameters: [{ name: request_id, in: path, required: true, schema: { type: string, format: uuid } }]
|
|
responses: { "200": { description: Pending request approved transactionally } }
|
|
/api/v1/admin/model-requests/{request_id}/reject:
|
|
post:
|
|
operationId: rejectModelRequest
|
|
security: [{ bearerAuth: [] }]
|
|
parameters: [{ name: request_id, in: path, required: true, schema: { type: string, format: uuid } }]
|
|
responses: { "200": { description: Pending request rejected transactionally } }
|
|
/v1/models:
|
|
get:
|
|
operationId: listModels
|
|
security: [{ bearerAuth: [] }]
|
|
parameters:
|
|
- $ref: "#/components/parameters/GatewayProvider"
|
|
responses:
|
|
"200": { description: OpenAI-compatible model list }
|
|
"429": { description: Per-minute, monthly request, or monthly token quota exceeded }
|
|
"503": { description: Authentication, admission control, or provider configuration unavailable }
|
|
/v1/chat/completions:
|
|
post:
|
|
operationId: createChatCompletion
|
|
security: [{ bearerAuth: [] }]
|
|
parameters:
|
|
- $ref: "#/components/parameters/GatewayProvider"
|
|
- $ref: "#/components/parameters/IdempotencyKey"
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema: { type: object, additionalProperties: true }
|
|
responses:
|
|
"200": { description: JSON response or SSE stream }
|
|
"429": { description: Per-minute, monthly request, or monthly token quota exceeded }
|
|
"503": { description: Authentication, admission control, or provider configuration unavailable }
|
|
/v1/responses:
|
|
post:
|
|
operationId: createResponse
|
|
security: [{ bearerAuth: [] }]
|
|
parameters:
|
|
- $ref: "#/components/parameters/GatewayProvider"
|
|
- $ref: "#/components/parameters/IdempotencyKey"
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema: { type: object, additionalProperties: true }
|
|
responses:
|
|
"200": { description: JSON response or SSE stream }
|
|
"429": { description: Per-minute, monthly request, or monthly token quota exceeded }
|
|
"503": { description: Authentication, admission control, or provider configuration unavailable }
|
|
/v1/embeddings:
|
|
post:
|
|
operationId: createEmbedding
|
|
security: [{ bearerAuth: [] }]
|
|
parameters:
|
|
- $ref: "#/components/parameters/GatewayProvider"
|
|
- $ref: "#/components/parameters/IdempotencyKey"
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema: { type: object, additionalProperties: true }
|
|
responses:
|
|
"200": { description: OpenAI-compatible embedding response }
|
|
"429": { description: Per-minute, monthly request, or monthly token quota exceeded }
|
|
"503": { description: Authentication, admission control, or provider configuration unavailable }
|
|
/v1/messages:
|
|
post:
|
|
operationId: createAnthropicMessage
|
|
security: [{ bearerAuth: [] }]
|
|
parameters:
|
|
- $ref: "#/components/parameters/GatewayProvider"
|
|
- $ref: "#/components/parameters/IdempotencyKey"
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema: { type: object, additionalProperties: true }
|
|
responses:
|
|
"200": { description: Anthropic-compatible response or SSE stream }
|
|
"429": { description: Per-minute, monthly request, or monthly token quota exceeded }
|
|
"503": { description: Authentication, admission control, or provider configuration unavailable }
|
|
components:
|
|
parameters:
|
|
ModelRouteID:
|
|
name: model_route_id
|
|
in: path
|
|
required: true
|
|
schema: { type: string, format: uuid }
|
|
IdempotencyKey:
|
|
name: Idempotency-Key
|
|
in: header
|
|
required: false
|
|
description: Enables bounded retries for replayable POST requests. Reusing a key is the caller's idempotency contract.
|
|
schema: { type: string, minLength: 1, maxLength: 255 }
|
|
IdentityID:
|
|
name: identity_id
|
|
in: path
|
|
required: true
|
|
schema: { type: string, format: uuid }
|
|
ProviderID:
|
|
name: provider_id
|
|
in: path
|
|
required: true
|
|
schema: { type: string, format: uuid }
|
|
GatewayProvider:
|
|
name: X-Gateway-Provider
|
|
in: header
|
|
required: false
|
|
description: Enabled database Provider code. Omit to use the current default snapshot entry.
|
|
schema: { type: string }
|
|
securitySchemes:
|
|
bearerAuth:
|
|
type: http
|
|
scheme: bearer
|
|
apiKeyAuth:
|
|
type: http
|
|
scheme: bearer
|
|
description: Gateway API Key with gateway:invoke scope; X-Gateway-API-Key is also accepted.
|
|
schemas:
|
|
Health:
|
|
type: object
|
|
required: [status, version]
|
|
properties:
|
|
status: { type: string, const: ok }
|
|
version: { type: string }
|
|
LoginRequest:
|
|
type: object
|
|
required: [userName, password]
|
|
properties:
|
|
userName: { type: string, minLength: 1, maxLength: 128 }
|
|
password: { type: string, minLength: 1, maxLength: 1024 }
|
|
TOTPLoginRequest:
|
|
type: object
|
|
required: [temp_token]
|
|
properties:
|
|
temp_token: { type: string, minLength: 1 }
|
|
code: { type: string, pattern: "^[0-9]{6}$" }
|
|
backup_code: { type: string, pattern: "^[A-Za-z2-9]{4}-?[A-Za-z2-9]{4}$" }
|
|
anyOf:
|
|
- required: [code]
|
|
- required: [backup_code]
|
|
ProviderInput:
|
|
type: object
|
|
required: [code, adapter, base_url, capabilities, config, enabled]
|
|
properties:
|
|
code:
|
|
type: string
|
|
pattern: "^[a-z][a-z0-9_-]{1,63}$"
|
|
adapter:
|
|
type: string
|
|
enum: [openai-compatible]
|
|
base_url: { type: string, format: uri }
|
|
api_key:
|
|
type: string
|
|
description: Omit during update to retain the existing encrypted credential.
|
|
capabilities:
|
|
type: array
|
|
items: { type: string }
|
|
config: { type: object, additionalProperties: true }
|
|
enabled: { type: boolean }
|
|
IdentityInput:
|
|
type: object
|
|
required: [login, display_name, role, permissions, active]
|
|
properties:
|
|
login: { type: string, minLength: 2, maxLength: 128 }
|
|
display_name: { type: string, maxLength: 64 }
|
|
role: { type: string, enum: [superadmin, operator, auditor, member] }
|
|
password:
|
|
type: string
|
|
minLength: 12
|
|
maxLength: 1024
|
|
description: Required on create; omit on update to retain the current password.
|
|
permissions:
|
|
type: array
|
|
uniqueItems: true
|
|
items:
|
|
type: string
|
|
pattern: "^[a-z][a-z0-9_.:-]{2,127}$|^\\*$"
|
|
active: { type: boolean }
|
|
department_id:
|
|
type: [string, "null"]
|
|
format: uuid
|
|
description: Portal accounts may bind to an active department.
|
|
DepartmentInput:
|
|
type: object
|
|
required: [code, name, description, active]
|
|
properties:
|
|
code: { type: string, pattern: "^[a-z][a-z0-9_-]{1,63}$" }
|
|
name: { type: string, minLength: 1, maxLength: 128 }
|
|
description: { type: string, maxLength: 1024 }
|
|
parent_id: { type: [string, "null"], format: uuid }
|
|
active: { type: boolean }
|
|
OIDCProviderInput:
|
|
type: object
|
|
required:
|
|
[code, display_name, issuer_url, client_id, redirect_uri, portal_return_url, scopes, auto_provision, enabled]
|
|
properties:
|
|
code: { type: string, pattern: "^[a-z][a-z0-9_-]{1,63}$" }
|
|
display_name: { type: string, minLength: 1, maxLength: 128 }
|
|
issuer_url: { type: string, format: uri }
|
|
client_id: { type: string, minLength: 1 }
|
|
client_secret:
|
|
type: string
|
|
description: Required on create and omitted on update to retain the encrypted value.
|
|
redirect_uri: { type: string, format: uri }
|
|
portal_return_url: { type: string, format: uri }
|
|
scopes:
|
|
type: array
|
|
contains: { const: openid }
|
|
items: { type: string }
|
|
auto_provision: { type: boolean }
|
|
default_department_id: { type: [string, "null"], format: uuid }
|
|
enabled: { type: boolean }
|
|
SAMLProviderInput:
|
|
type: object
|
|
required:
|
|
[code, display_name, metadata_url, sp_entity_id, acs_url, portal_return_url, email_attribute, name_attribute, auto_provision, enabled]
|
|
properties:
|
|
code: { type: string, pattern: "^[a-z][a-z0-9_-]{1,63}$" }
|
|
display_name: { type: string, minLength: 1, maxLength: 128 }
|
|
metadata_url: { type: string, format: uri }
|
|
sp_entity_id:
|
|
type: string
|
|
minLength: 1
|
|
maxLength: 512
|
|
description: Absolute URI used as the SAML audience.
|
|
acs_url:
|
|
type: string
|
|
format: uri
|
|
description: Must end with /api/v1/portal/sso/{code}/callback.
|
|
portal_return_url: { type: string, format: uri }
|
|
email_attribute: { type: string, maxLength: 256 }
|
|
name_attribute: { type: string, maxLength: 256 }
|
|
auto_provision: { type: boolean }
|
|
default_department_id: { type: [string, "null"], format: uuid }
|
|
enabled: { type: boolean }
|
|
ProviderConnectionResult:
|
|
type: object
|
|
required: [connected, latency_ms, message]
|
|
properties:
|
|
connected: { type: boolean }
|
|
status_code: { type: integer }
|
|
latency_ms: { type: integer, format: int64, minimum: 0 }
|
|
message: { type: string }
|
|
ProviderModel:
|
|
type: object
|
|
required:
|
|
[id, provider_id, provider_model_id, metadata, enabled, discovered_at, last_seen_at]
|
|
properties:
|
|
id: { type: string, format: uuid }
|
|
provider_id: { type: string, format: uuid }
|
|
provider_model_id: { type: string, minLength: 1, maxLength: 512 }
|
|
owned_by: { type: string }
|
|
metadata: { type: object, additionalProperties: true }
|
|
enabled: { type: boolean }
|
|
discovered_at: { type: string, format: date-time }
|
|
last_seen_at: { type: string, format: date-time }
|
|
ModelSyncResult:
|
|
type: object
|
|
required: [discovered, active, disabled, synced_at]
|
|
properties:
|
|
discovered: { type: integer, minimum: 0 }
|
|
active: { type: integer, minimum: 0 }
|
|
disabled: { type: integer, minimum: 0 }
|
|
synced_at: { type: string, format: date-time }
|
|
CredentialRotationResult:
|
|
type: object
|
|
required: [active_version, loaded_versions, rotated, skipped]
|
|
properties:
|
|
active_version: { type: integer, minimum: 1 }
|
|
loaded_versions:
|
|
type: array
|
|
items: { type: integer, minimum: 1 }
|
|
rotated: { type: integer, minimum: 0 }
|
|
skipped: { type: integer, minimum: 0 }
|
|
APIKeyInput:
|
|
type: object
|
|
required: [name, scopes, requests_per_minute, monthly_request_quota, monthly_token_quota]
|
|
properties:
|
|
name: { type: string, minLength: 1, maxLength: 128 }
|
|
scopes:
|
|
type: array
|
|
minItems: 1
|
|
items: { type: string, enum: [gateway:invoke, "*"] }
|
|
requests_per_minute:
|
|
type: integer
|
|
minimum: 0
|
|
maximum: 1000000
|
|
description: Per-API-key UTC minute request limit; zero means unlimited.
|
|
monthly_request_quota:
|
|
type: integer
|
|
format: int64
|
|
minimum: 0
|
|
maximum: 1000000000000
|
|
description: Accepted requests per UTC calendar month; zero means unlimited.
|
|
monthly_token_quota:
|
|
type: integer
|
|
format: int64
|
|
minimum: 0
|
|
maximum: 1000000000000000
|
|
description: Input plus output tokens per UTC calendar month; zero means unlimited.
|
|
expires_at: { type: [string, "null"], format: date-time }
|
|
APIKeyLimitsInput:
|
|
type: object
|
|
required: [requests_per_minute, monthly_request_quota, monthly_token_quota]
|
|
properties:
|
|
requests_per_minute: { type: integer, minimum: 0, maximum: 1000000 }
|
|
monthly_request_quota: { type: integer, format: int64, minimum: 0, maximum: 1000000000000 }
|
|
monthly_token_quota: { type: integer, format: int64, minimum: 0, maximum: 1000000000000000 }
|
|
ModelRouteInput:
|
|
type: object
|
|
required: [name, source_model, target_model, provider_id, weight, priority, conditions, enabled]
|
|
properties:
|
|
name: { type: string, minLength: 1, maxLength: 128 }
|
|
source_model: { type: string, minLength: 1, maxLength: 512 }
|
|
target_model: { type: string, minLength: 1, maxLength: 512 }
|
|
provider_id: { type: string, format: uuid }
|
|
weight: { type: integer, minimum: 1, maximum: 10000 }
|
|
priority: { type: integer, minimum: -100000, maximum: 100000 }
|
|
enabled: { type: boolean }
|
|
conditions:
|
|
type: object
|
|
additionalProperties: true
|
|
properties:
|
|
endpoints:
|
|
type: array
|
|
items: { type: string, enum: [/v1/chat/completions, /v1/responses, /v1/embeddings, /v1/messages] }
|
|
api_key_ids:
|
|
type: array
|
|
items: { type: string, format: uuid }
|
|
tenant_ids:
|
|
type: array
|
|
items: { type: string, format: uuid }
|
|
ContentPolicyInput:
|
|
type: object
|
|
required: [name, description, action, priority, paths, models, api_key_ids, rules, enabled]
|
|
properties:
|
|
name: { type: string, minLength: 1, maxLength: 128 }
|
|
description: { type: string, maxLength: 1000 }
|
|
action: { type: string, enum: [audit, block, redact] }
|
|
priority: { type: integer, minimum: -100000, maximum: 100000 }
|
|
paths: { type: array, items: { type: string } }
|
|
models: { type: array, items: { type: string } }
|
|
api_key_ids: { type: array, items: { type: string, format: uuid } }
|
|
enabled: { type: boolean }
|
|
rules:
|
|
type: array
|
|
minItems: 1
|
|
maxItems: 20
|
|
items:
|
|
type: object
|
|
required: [name, pattern, replacement]
|
|
properties:
|
|
name: { type: string, minLength: 1 }
|
|
pattern: { type: string, minLength: 1, maxLength: 512, description: Go RE2 expression }
|
|
replacement: { type: string }
|
|
ModelPriceInput:
|
|
type: object
|
|
required: [provider_code, model_pattern, input_microunits_per_million, output_microunits_per_million, currency, effective_from, enabled]
|
|
properties:
|
|
provider_code: { type: string, pattern: "^[a-z][a-z0-9_-]{1,63}$" }
|
|
model_pattern: { type: string, description: Exact model name or a prefix ending in one asterisk }
|
|
input_microunits_per_million: { type: integer, format: int64, minimum: 0 }
|
|
output_microunits_per_million: { type: integer, format: int64, minimum: 0 }
|
|
currency: { type: string, minLength: 3, maxLength: 3, default: USD }
|
|
effective_from: { type: string, format: date-time }
|
|
effective_to: { type: [string, "null"], format: date-time }
|
|
enabled: { type: boolean }
|
|
PromptVariable:
|
|
type: object
|
|
required: [name, required]
|
|
properties:
|
|
name: { type: string, pattern: "^[A-Za-z_][A-Za-z0-9_]*$" }
|
|
label: { type: string, maxLength: 128 }
|
|
default: { type: string, maxLength: 10000 }
|
|
required: { type: boolean }
|
|
PromptInput:
|
|
type: object
|
|
required: [name, description, tags, department_ids, enabled]
|
|
properties:
|
|
name: { type: string, minLength: 1, maxLength: 128 }
|
|
description: { type: string, maxLength: 4000 }
|
|
category_id: { type: [string, "null"], format: uuid }
|
|
tags: { type: array, maxItems: 30, items: { type: string } }
|
|
department_ids: { type: array, maxItems: 100, items: { type: string, format: uuid } }
|
|
enabled: { type: boolean }
|
|
content: { type: string, maxLength: 100000, description: Required only when creating the initial version. }
|
|
variables: { type: array, maxItems: 100, items: { $ref: "#/components/schemas/PromptVariable" } }
|
|
change_note: { type: string }
|
|
KnowledgeBaseInput:
|
|
type: object
|
|
required: [name, description, retrieval_mode, chunk_size, chunk_overlap, department_ids, enabled]
|
|
properties:
|
|
name: { type: string, minLength: 1, maxLength: 128 }
|
|
description: { type: string, maxLength: 4000 }
|
|
retrieval_mode: { type: string, enum: [postgres_fts] }
|
|
chunk_size: { type: integer, minimum: 200, maximum: 8000 }
|
|
chunk_overlap: { type: integer, minimum: 0 }
|
|
department_ids: { type: array, maxItems: 100, items: { type: string, format: uuid } }
|
|
enabled: { type: boolean }
|
|
ToolInput:
|
|
type: object
|
|
required: [code, name, description, endpoint_url, http_method, input_schema, timeout_seconds, department_ids, enabled]
|
|
properties:
|
|
code: { type: string, pattern: "^[a-z][a-z0-9_-]{1,63}$" }
|
|
name: { type: string, minLength: 1, maxLength: 128 }
|
|
description: { type: string, maxLength: 4000 }
|
|
endpoint_url: { type: string, format: uri }
|
|
http_method: { type: string, enum: [GET, POST, PUT, PATCH, DELETE] }
|
|
headers:
|
|
type: object
|
|
writeOnly: true
|
|
additionalProperties: { type: string }
|
|
description: Omit during update to preserve the existing KEK-encrypted headers.
|
|
input_schema: { type: object, additionalProperties: true }
|
|
timeout_seconds: { type: integer, minimum: 1, maximum: 120 }
|
|
department_ids: { type: array, maxItems: 100, items: { type: string, format: uuid } }
|
|
enabled: { type: boolean }
|
|
ApplicationConfig:
|
|
type: object
|
|
required: [model, knowledge_base_ids, tool_ids, retrieval_top_k, temperature, max_tool_rounds]
|
|
properties:
|
|
model: { type: string, maxLength: 255 }
|
|
prompt_template_id: { type: string, format: uuid }
|
|
knowledge_base_ids: { type: array, maxItems: 20, items: { type: string, format: uuid } }
|
|
tool_ids: { type: array, maxItems: 20, items: { type: string, format: uuid } }
|
|
retrieval_top_k: { type: integer, minimum: 1, maximum: 20 }
|
|
temperature: { type: number, minimum: 0, maximum: 2 }
|
|
max_tool_rounds: { type: integer, minimum: 0, maximum: 8 }
|
|
ApplicationInput:
|
|
type: object
|
|
required: [code, name, description, status, department_ids, draft_config]
|
|
properties:
|
|
code: { type: string, pattern: "^[a-z][a-z0-9_-]{2,63}$" }
|
|
name: { type: string, minLength: 1, maxLength: 128 }
|
|
description: { type: string, maxLength: 4000 }
|
|
status: { type: string, enum: [draft, active, suspended, retired] }
|
|
department_ids: { type: array, maxItems: 100, items: { type: string, format: uuid } }
|
|
draft_config: { $ref: "#/components/schemas/ApplicationConfig" }
|
|
NotificationChannelInput:
|
|
type: object
|
|
required: [name, webhook_url, event_patterns, enabled]
|
|
properties:
|
|
name: { type: string, minLength: 1, maxLength: 128 }
|
|
webhook_url: { type: string, format: uri }
|
|
signing_secret:
|
|
type: string
|
|
writeOnly: true
|
|
maxLength: 4096
|
|
description: Omit during update to preserve the existing KEK-encrypted signing secret.
|
|
event_patterns:
|
|
type: array
|
|
minItems: 1
|
|
maxItems: 100
|
|
items: { type: string, description: Exact event type or a prefix ending in one asterisk. }
|
|
enabled: { type: boolean }
|