Files
ai-gateway-go/api/openapi/gateway.yaml
T
superidou 9501751792 0.10.1: 安全与业务逻辑加固、新品牌与部署加固
三轮审查修复(60+ 项),相对远端 main(b536672)的关键变更:
- 安全: 数据面 SSRF 拨号防护(防 DNS rebinding)/上游凭据剥离/登录防枚举
  与锁定态统一/可信代理(X-Forwarded-For)限流加固/会话版本失效机制/
  撤销即时传播/弱密钥拒绝启动/脱敏字节级重写(保签名契约)
- 业务逻辑: 裸 body 上传 panic/bootstrap 审计管线卡死/定价通配符优先级/
  全局工具可见性/调度器停机补跑/TOTP 挑战令牌消费顺序/熔断探针语义/
  >4MB 响应 token 计量/管理员重置密码作废会话 等
- 前端: 新 logo(语枢 AI 网关主题)/Provider 凭据异常警示/删除入口/
  后端错误消息透传/localStorage 敏感数据收敛
- 部署: CREDENTIAL_MASTER_KEY 持久化与弱值拒绝/Provider DELETE 接口/
  nginx 安全头/worker 内存限制
- 新增迁移 000029(key_hash 索引)/000030(usage_daily 币种维度)
2026-08-13 10:50:51 +08:00

1984 lines
85 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/traces:
get:
operationId: listLLMTraces
security: [{ bearerAuth: [] }]
parameters:
- { name: from, in: query, schema: { type: string, format: date-time } }
- { name: to, in: query, schema: { type: string, format: date-time } }
- { name: trace_type, in: query, schema: { type: string, enum: [application, digital_employee] } }
- { name: target_code, in: query, schema: { type: string } }
- { name: request_id, in: query, schema: { type: string } }
- { name: status, in: query, schema: { type: string, enum: [running, success, error] } }
- { name: limit, in: query, schema: { type: integer, minimum: 1, maximum: 200, default: 50 } }
responses:
"200": { description: Metadata-only LLM Trace summaries }
"403": { description: trace:read permission required }
/api/v1/admin/traces/{trace_id}:
get:
operationId: getLLMTrace
security: [{ bearerAuth: [] }]
parameters: [{ name: trace_id, in: path, required: true, schema: { type: string, format: uuid } }]
responses:
"200":
description: Trace detail with ordered model, retrieval, and tool spans
content:
application/json:
schema: { $ref: "#/components/schemas/LLMTrace" }
"403": { description: trace:read permission required }
"404": { description: Trace not found }
/api/v1/admin/agent-sessions:
get:
operationId: listAgentSessions
security: [{ bearerAuth: [] }]
parameters:
- { name: from, in: query, schema: { type: string, format: date-time } }
- { name: to, in: query, schema: { type: string, format: date-time } }
- { name: trace_type, in: query, schema: { type: string, enum: [application, digital_employee] } }
- { name: target_code, in: query, schema: { type: string, maxLength: 128 } }
- { name: session_id, in: query, schema: { type: string, maxLength: 512 } }
- { name: limit, in: query, schema: { type: integer, minimum: 1, maximum: 200, default: 50 } }
responses:
"200":
description: Metadata-only application and digital-employee session aggregates
content:
application/json:
schema:
type: object
required: [code, data]
properties:
code: { type: integer }
data:
type: object
required: [items]
properties:
items: { type: array, items: { $ref: "#/components/schemas/AgentSession" } }
"403": { description: trace:read permission required }
/api/v1/admin/agent-nodes:
get:
operationId: listAgentNodes
security: [{ bearerAuth: [] }]
responses:
"200":
description: Registered agent nodes with derived heartbeat status
content:
application/json:
schema: { type: array, items: { $ref: "#/components/schemas/AgentNode" } }
"403": { description: agent_node:read permission required }
post:
operationId: createAgentNode
security: [{ bearerAuth: [] }]
requestBody:
required: true
content:
application/json:
schema: { $ref: "#/components/schemas/AgentNodeInput" }
responses:
"200": { description: Node metadata and one-time registration token }
"403": { description: agent_node:manage permission required }
"409": { description: Node code already exists }
/api/v1/admin/agent-nodes/route-preview:
post:
operationId: previewAgentNodeRoute
security: [{ bearerAuth: [] }]
requestBody:
required: true
content:
application/json:
schema: { $ref: "#/components/schemas/AgentNodeRoutePreviewInput" }
responses:
"200":
description: Read-only online candidate list and stable-hash selection; no remote task is dispatched
content:
application/json:
schema: { $ref: "#/components/schemas/AgentNodeRoutePreview" }
"400": { description: Invalid pool, request key or capability constraints }
"403": { description: agent_node:read permission required }
/api/v1/admin/agent-nodes/{node_id}:
put:
operationId: updateAgentNode
security: [{ bearerAuth: [] }]
parameters: [{ name: node_id, in: path, required: true, schema: { type: string, format: uuid } }]
requestBody:
required: true
content:
application/json:
schema: { $ref: "#/components/schemas/AgentNodeInput" }
responses:
"200": { description: Updated node metadata }
"403": { description: agent_node:manage permission required }
"404": { description: Node not found }
delete:
operationId: deleteAgentNode
security: [{ bearerAuth: [] }]
parameters: [{ name: node_id, in: path, required: true, schema: { type: string, format: uuid } }]
responses:
"200": { description: Node removed and its token invalidated }
"403": { description: agent_node:manage permission required }
"404": { description: Node not found }
/api/v1/admin/agent-nodes/{node_id}/rotate-token:
post:
operationId: rotateAgentNodeToken
security: [{ bearerAuth: [] }]
parameters: [{ name: node_id, in: path, required: true, schema: { type: string, format: uuid } }]
responses:
"200": { description: New one-time registration token; previous token is immediately invalid }
"403": { description: agent_node:manage permission required }
"404": { description: Node not found }
/api/v1/agent/nodes/{code}/heartbeat:
post:
operationId: heartbeatAgentNode
security: [{ agentTokenAuth: [] }]
parameters: [{ name: code, in: path, required: true, schema: { type: string, pattern: "^[a-z0-9][a-z0-9._-]{0,127}$" } }]
requestBody:
required: true
content:
application/json:
schema: { $ref: "#/components/schemas/AgentNodeHeartbeat" }
responses:
"200": { description: Heartbeat accepted and derived online status returned }
"401": { description: Invalid or disabled node token }
/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/scheduled-tasks:
get:
operationId: listScheduledTasks
security: [{ bearerAuth: [] }]
responses: { "200": { description: Scheduled task definitions with next and last execution state } }
post:
operationId: createScheduledTask
security: [{ bearerAuth: [] }]
requestBody:
required: true
content:
application/json:
schema: { $ref: "#/components/schemas/ScheduledTaskInput" }
responses: { "200": { description: Task created with KEK-encrypted execution credential } }
/api/v1/admin/scheduled-tasks/{task_id}:
get:
operationId: getScheduledTask
security: [{ bearerAuth: [] }]
parameters: [{ name: task_id, in: path, required: true, schema: { type: string, format: uuid } }]
responses: { "200": { description: Task detail without plaintext credentials } }
put:
operationId: updateScheduledTask
security: [{ bearerAuth: [] }]
parameters: [{ name: task_id, in: path, required: true, schema: { type: string, format: uuid } }]
requestBody:
required: true
content:
application/json:
schema: { $ref: "#/components/schemas/ScheduledTaskInput" }
responses: { "200": { description: Task updated and next execution recomputed } }
delete:
operationId: deleteScheduledTask
security: [{ bearerAuth: [] }]
parameters: [{ name: task_id, in: path, required: true, schema: { type: string, format: uuid } }]
responses: { "200": { description: Task and execution history deleted } }
/api/v1/admin/scheduled-tasks/{task_id}/start:
post:
operationId: startScheduledTask
security: [{ bearerAuth: [] }]
parameters: [{ name: task_id, in: path, required: true, schema: { type: string, format: uuid } }]
responses: { "200": { description: Task enabled and next execution computed } }
/api/v1/admin/scheduled-tasks/{task_id}/pause:
post:
operationId: pauseScheduledTask
security: [{ bearerAuth: [] }]
parameters: [{ name: task_id, in: path, required: true, schema: { type: string, format: uuid } }]
responses: { "200": { description: Task paused without deleting history } }
/api/v1/admin/scheduled-tasks/{task_id}/run:
post:
operationId: runScheduledTaskNow
security: [{ bearerAuth: [] }]
parameters: [{ name: task_id, in: path, required: true, schema: { type: string, format: uuid } }]
responses: { "200": { description: Manual execution durably queued } }
/api/v1/admin/scheduled-tasks/{task_id}/runs:
get:
operationId: listScheduledTaskRuns
security: [{ bearerAuth: [] }]
parameters: [{ name: task_id, in: path, required: true, schema: { type: string, format: uuid } }]
responses: { "200": { description: Execution history with status, response and error } }
/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.
agentTokenAuth:
type: apiKey
in: header
name: X-Agent-Token
description: One-time-issued node registration token used for heartbeats.
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 }
ScheduledTaskInput:
type: object
required: [code, name, description, cron_expression, timezone, target_type, target_code, prompt, variables, skill_ids, mcp_server_ids, conversation_id, 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 }
cron_expression: { type: string, maxLength: 128, description: Standard five-field cron expression. }
timezone: { type: string, maxLength: 128, example: Asia/Shanghai }
target_type: { type: string, enum: [application, digital_employee] }
target_code: { type: string, maxLength: 64 }
prompt: { type: string, minLength: 1, maxLength: 100000 }
variables: { type: object, additionalProperties: true }
skill_ids: { type: array, maxItems: 100, items: { type: string, format: uuid } }
mcp_server_ids: { type: array, maxItems: 100, items: { type: string, format: uuid } }
conversation_id: { type: string, maxLength: 128 }
notification_channel_id: { type: [string, "null"], format: uuid }
api_key:
type: string
writeOnly: true
maxLength: 512
description: Required on create; omit on update to retain the encrypted credential.
enabled: { type: boolean }
LLMTraceSpan:
type: object
required: [id, trace_id, span_type, name, status, started_at, input_tokens, output_tokens, round, error, metadata]
properties:
id: { type: string, format: uuid }
trace_id: { type: string, format: uuid }
parent_id: { type: string, format: uuid }
span_type: { type: string, enum: [model, tool, retrieval] }
name: { type: string }
status: { type: string, enum: [running, success, error] }
started_at: { type: string, format: date-time }
finished_at: { type: string, format: date-time }
latency_ms: { type: integer, minimum: 0 }
provider_code: { type: string }
model: { type: string }
input_tokens: { type: integer, minimum: 0 }
output_tokens: { type: integer, minimum: 0 }
round: { type: integer, minimum: 0 }
error: { type: string }
metadata: { type: object, additionalProperties: true }
LLMTrace:
type: object
required: [id, request_id, trace_type, target_code, conversation_id, status, started_at, retrieval_count, model_call_count, tool_call_count, error, metadata]
properties:
id: { type: string, format: uuid }
request_id: { type: string }
api_key_id: { type: string, format: uuid }
tenant_id: { type: string, format: uuid }
trace_type: { type: string, enum: [application, digital_employee] }
target_id: { type: string, format: uuid }
target_code: { type: string }
conversation_id: { type: string }
status: { type: string, enum: [running, success, error] }
started_at: { type: string, format: date-time }
finished_at: { type: string, format: date-time }
latency_ms: { type: integer, minimum: 0 }
retrieval_count: { type: integer, minimum: 0 }
model_call_count: { type: integer, minimum: 0 }
tool_call_count: { type: integer, minimum: 0 }
error: { type: string }
metadata: { type: object, additionalProperties: true }
spans: { type: array, items: { $ref: "#/components/schemas/LLMTraceSpan" } }
AgentSession:
type: object
required: [id, trace_type, target_code, trace_count, latest_trace_id, latest_status, started_at, updated_at, retrieval_count, model_call_count, tool_call_count]
properties:
id: { type: string, description: Session key; request-derived for stateless calls }
trace_type: { type: string, enum: [application, digital_employee] }
target_code: { type: string }
trace_count: { type: integer, minimum: 1 }
latest_trace_id: { type: string, format: uuid }
latest_status: { type: string, enum: [running, success, error] }
started_at: { type: string, format: date-time }
updated_at: { type: string, format: date-time }
retrieval_count: { type: integer, minimum: 0 }
model_call_count: { type: integer, minimum: 0 }
tool_call_count: { type: integer, minimum: 0 }
AgentNodeInput:
type: object
required: [name, description, endpoint, node_type, pool_type, pool_code, enabled]
properties:
code: { type: string, pattern: "^[a-z0-9][a-z0-9._-]{0,127}$" }
name: { type: string, minLength: 1, maxLength: 128 }
description: { type: string, maxLength: 4000 }
endpoint: { type: string, maxLength: 512 }
node_type: { type: string, enum: [worker, gateway, executor] }
pool_type: { type: string, enum: [public, private] }
pool_code: { type: string, minLength: 1, maxLength: 64 }
enabled: { type: boolean }
AgentNodeRoutePreviewInput:
type: object
required: [pool_type, pool_code, request_key]
properties:
pool_type: { type: string, enum: [public, private] }
pool_code: { type: string, minLength: 1, maxLength: 64 }
required_capabilities: { type: array, maxItems: 32, items: { type: string, maxLength: 128 } }
request_key: { type: string, minLength: 1, maxLength: 512 }
AgentNodeHeartbeat:
type: object
required: [version, capabilities, metadata, error]
properties:
version: { type: string, maxLength: 128 }
capabilities: { type: object, additionalProperties: true }
metadata: { type: object, additionalProperties: true }
error: { type: string, maxLength: 4000 }
AgentNode:
type: object
required: [id, code, name, description, endpoint, node_type, pool_type, pool_code, enabled, status, token_prefix, version, capabilities, metadata, last_error, created_at, updated_at]
properties:
id: { type: string, format: uuid }
code: { type: string }
name: { type: string }
description: { type: string }
endpoint: { type: string }
node_type: { type: string, enum: [worker, gateway, executor] }
pool_type: { type: string, enum: [public, private] }
pool_code: { type: string }
enabled: { type: boolean }
status: { type: string, enum: [pending, online, offline, disabled] }
token_prefix: { type: string }
version: { type: string }
capabilities: { type: object, additionalProperties: true }
metadata: { type: object, additionalProperties: true }
last_heartbeat_at: { type: string, format: date-time }
last_heartbeat_ip: { type: string }
last_error: { type: string }
created_at: { type: string, format: date-time }
updated_at: { type: string, format: date-time }
AgentNodeTokenResponse:
type: object
required: [node, token, warning]
properties:
node: { $ref: "#/components/schemas/AgentNode" }
token: { type: string, writeOnly: true }
warning: { type: string }
AgentNodeRoutePreview:
type: object
required: [pool_type, pool_code, required_capabilities, request_key, selection_policy, reason, selected, candidates]
properties:
pool_type: { type: string, enum: [public, private] }
pool_code: { type: string }
required_capabilities: { type: array, items: { type: string } }
request_key: { type: string }
selection_policy: { type: string, example: stable-hash(request_key,node_id) }
reason: { type: string, enum: [selected_online_node, no_online_node, no_capable_node] }
selected:
anyOf:
- { $ref: "#/components/schemas/AgentNode" }
- { type: 'null' }
candidates: { type: array, items: { $ref: "#/components/schemas/AgentNode" } }