diff --git a/Cargo.lock b/Cargo.lock index c3d7ca8d3..82a05b5ad 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -10842,6 +10842,7 @@ dependencies = [ "hex", "http-body-util", "ipnet", + "libc", "mockall", "octocrab", "rand 0.10.2", @@ -12102,6 +12103,7 @@ dependencies = [ "tracing", "url", "utoipa", + "zip 8.6.0", ] [[package]] diff --git a/apps/temps-cli/openapi.json b/apps/temps-cli/openapi.json index cdee0a7d5..713698cf4 100644 --- a/apps/temps-cli/openapi.json +++ b/apps/temps-cli/openapi.json @@ -1,91206 +1 @@ -{ - "openapi": "3.1.0", - "info": { - "title": "Temps", - "description": "An API for managing projects, deployments, and infrastructure resources", - "contact": { - "name": "Temps Support", - "url": "https://temps.sh" - }, - "version": "1.0.0" - }, - "servers": [ - { - "url": "/api", - "description": "Base path for all API endpoints" - } - ], - "paths": { - "/.well-known/temps.json": { - "get": { - "tags": [ - "Platform" - ], - "summary": "Get platform information", - "operationId": "get_platform_info", - "responses": { - "200": { - "description": "Successfully retrieved platform information", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/PlatformInfo" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/0/organizations/{org_slug}/chunk-upload/": { - "get": { - "tags": [ - "sentry-compat" - ], - "summary": "Chunk upload options (stub for sentry-cli compatibility).", - "description": "sentry-cli checks this endpoint to determine if chunk-based upload is supported.\nWe return a response indicating that chunk upload is NOT supported, which forces\nsentry-cli to fall back to the standard file-by-file upload.", - "operationId": "chunk_upload_options", - "parameters": [ - { - "name": "org_slug", - "in": "path", - "description": "Organization slug (ignored)", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Chunk upload options", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SentryChunkUploadResponse" - } - } - } - } - } - } - }, - "/0/organizations/{org_slug}/releases/": { - "post": { - "tags": [ - "sentry-compat" - ], - "summary": "Create a release (stub for sentry-cli compatibility).", - "description": "sentry-cli calls this before uploading files. Since Temps implicitly creates\nreleases when source maps are uploaded, this is a no-op that returns the\nexpected response format.", - "operationId": "create_release", - "parameters": [ - { - "name": "org_slug", - "in": "path", - "description": "Organization slug (ignored in single-tenant mode)", - "required": true, - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SentryCreateReleaseRequest" - } - } - }, - "required": true - }, - "responses": { - "201": { - "description": "Release created", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SentryReleaseResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - } - } - } - }, - "/0/projects/{org_slug}/{project_slug}/releases/": { - "post": { - "tags": [ - "sentry-compat" - ], - "summary": "Create a release for a specific project (stub for sentry-cli compatibility).", - "description": "sentry-cli calls this endpoint (instead of /organizations/.../releases/) when\nboth SENTRY_ORG and SENTRY_PROJECT env vars are set. Behaves identically to\nthe organizations endpoint but validates the project slug.", - "operationId": "create_project_release", - "parameters": [ - { - "name": "org_slug", - "in": "path", - "description": "Organization slug (ignored in single-tenant mode)", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "project_slug", - "in": "path", - "description": "Project slug or numeric ID", - "required": true, - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SentryCreateReleaseRequest" - } - } - }, - "required": true - }, - "responses": { - "201": { - "description": "Release created", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SentryReleaseResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "404": { - "description": "Project not found" - } - } - } - }, - "/0/projects/{org_slug}/{project_slug}/releases/{version}/": { - "put": { - "tags": [ - "sentry-compat" - ], - "summary": "Finalize a release (stub for sentry-cli compatibility).", - "description": "sentry-cli calls `releases finalize` after uploading source maps. This sets\nthe dateReleased on the release. Since Temps stores source maps independently\nof releases, this is a no-op that returns the expected response.", - "operationId": "finalize_project_release", - "parameters": [ - { - "name": "org_slug", - "in": "path", - "description": "Organization slug (ignored)", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "project_slug", - "in": "path", - "description": "Project slug or numeric ID", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "version", - "in": "path", - "description": "Release version to finalize", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Release finalized", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SentryReleaseResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "404": { - "description": "Project not found" - } - } - } - }, - "/0/projects/{org_slug}/{project_slug}/releases/{version}/files/": { - "get": { - "tags": [ - "sentry-compat" - ], - "summary": "List files for a release.", - "description": "Returns all source maps stored for a specific release in sentry-cli compatible format.", - "operationId": "list_release_files", - "parameters": [ - { - "name": "org_slug", - "in": "path", - "description": "Organization slug (ignored)", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "project_slug", - "in": "path", - "description": "Project slug or numeric ID", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "version", - "in": "path", - "description": "Release version", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "List of release files", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/SentryReleaseFileResponse" - } - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "404": { - "description": "Project not found" - } - } - }, - "post": { - "tags": [ - "sentry-compat" - ], - "summary": "Upload a source map file for a release.", - "description": "Accepts the same multipart format as the Sentry release files API.\nThe `name` field should be the URL path of the file (e.g., `~/dist/bundle.js.map`).\n\nThe route has a 50 MiB body limit applied at the router level (Fix #4).\nA per-field size check provides an additional defense-in-depth layer.", - "operationId": "upload_release_file", - "parameters": [ - { - "name": "org_slug", - "in": "path", - "description": "Organization slug (ignored)", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "project_slug", - "in": "path", - "description": "Project slug or numeric ID", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "version", - "in": "path", - "description": "Release version", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "201": { - "description": "File uploaded", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SentryReleaseFileResponse" - } - } - } - }, - "400": { - "description": "Bad request" - }, - "401": { - "description": "Unauthorized" - }, - "404": { - "description": "Project not found" - }, - "413": { - "description": "Source map file exceeds the 50 MiB per-field limit" - } - } - } - }, - "/_temps/event": { - "post": { - "tags": [ - "Metrics" - ], - "summary": "Record analytics event", - "operationId": "record_event_metrics", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/EventMetricsPayload" - } - } - }, - "required": true - }, - "responses": { - "204": { - "description": "Event recorded successfully" - }, - "400": { - "description": "Bad request" - }, - "500": { - "description": "Internal server error" - } - } - } - }, - "/_temps/session-replay/events": { - "post": { - "tags": [ - "Analytics" - ], - "summary": "Add events to existing session replay", - "operationId": "add_session_replay_events", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SessionReplayEventsRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Events added successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AddEventsResponse" - } - } - } - }, - "400": { - "description": "Bad request", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - }, - "404": { - "description": "Session not found", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - } - } - } - }, - "/_temps/session-replay/init": { - "post": { - "tags": [ - "Analytics" - ], - "summary": "Initialize session replay with metadata", - "operationId": "init_session_replay", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SessionReplayInitRequest" - } - } - }, - "required": true - }, - "responses": { - "201": { - "description": "Session initialized successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SessionReplayInitResponse" - } - } - } - }, - "400": { - "description": "Bad request", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - } - } - } - }, - "/_temps/speed": { - "post": { - "tags": [ - "Performance" - ], - "summary": "Record performance metrics from client", - "operationId": "record_speed_metrics", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SpeedMetricsPayload" - } - } - }, - "required": true - }, - "responses": { - "204": { - "description": "Metrics recorded successfully" - }, - "400": { - "description": "Bad request", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - }, - "404": { - "description": "Host not found in route table", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - } - } - } - }, - "/_temps/speed/update": { - "post": { - "tags": [ - "Performance" - ], - "summary": "Update late performance metrics", - "operationId": "update_speed_metrics", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdateSpeedMetricsPayload" - } - } - }, - "required": true - }, - "responses": { - "204": { - "description": "Metrics updated successfully" - }, - "400": { - "description": "Bad request", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - }, - "404": { - "description": "Host not found or metrics not found", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - } - } - } - }, - "/admin/gate-settings": { - "get": { - "tags": [ - "AdminGate" - ], - "operationId": "get_admin_gate", - "responses": { - "200": { - "description": "Current admin gate config", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AdminGateResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "patch": { - "tags": [ - "AdminGate" - ], - "operationId": "patch_admin_gate", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdateAdminGateRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Updated admin gate config", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AdminGateResponse" - } - } - } - }, - "400": { - "description": "Invalid IP/CIDR/host" - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "409": { - "description": "Env-overridden or would lock out caller" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/admin/oidc/providers": { - "get": { - "tags": [ - "Authentication" - ], - "operationId": "list_oidc_providers", - "responses": { - "200": { - "description": "OIDC providers", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/OidcProviderResponse" - } - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "post": { - "tags": [ - "Authentication" - ], - "operationId": "create_oidc_provider", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateOidcProviderRequest" - } - } - }, - "required": true - }, - "responses": { - "201": { - "description": "OIDC provider created", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/OidcProviderResponse" - } - } - } - }, - "409": { - "description": "Another OIDC provider already uses that name" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/admin/oidc/providers/{provider_id}": { - "delete": { - "tags": [ - "Authentication" - ], - "operationId": "delete_oidc_provider", - "parameters": [ - { - "name": "provider_id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "204": { - "description": "OIDC provider deleted" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "patch": { - "tags": [ - "Authentication" - ], - "operationId": "update_oidc_provider", - "parameters": [ - { - "name": "provider_id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdateOidcProviderRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "OIDC provider updated", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/OidcProviderResponse" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/admin/oidc/providers/{provider_id}/role-mappings": { - "get": { - "tags": [ - "Authentication" - ], - "operationId": "list_oidc_role_mappings", - "parameters": [ - { - "name": "provider_id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "OIDC role mappings", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/OidcRoleMappingResponse" - } - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "post": { - "tags": [ - "Authentication" - ], - "operationId": "create_oidc_role_mapping", - "parameters": [ - { - "name": "provider_id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateOidcRoleMappingRequest" - } - } - }, - "required": true - }, - "responses": { - "201": { - "description": "Role mapping created", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/OidcRoleMappingResponse" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/admin/oidc/providers/{provider_id}/test": { - "post": { - "tags": [ - "Authentication" - ], - "operationId": "test_oidc_provider", - "parameters": [ - { - "name": "provider_id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Connection test result", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/OidcTestConnectionResponse" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/admin/oidc/providers/{provider_id}/users": { - "get": { - "tags": [ - "Authentication" - ], - "operationId": "list_oidc_provider_users", - "parameters": [ - { - "name": "provider_id", - "in": "path", - "description": "OIDC provider ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Users authenticated via this OIDC provider", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/OidcProviderUserResponse" - } - } - } - } - }, - "404": { - "description": "Provider not found" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/admin/oidc/role-mappings/{mapping_id}": { - "delete": { - "tags": [ - "Authentication" - ], - "operationId": "delete_oidc_role_mapping", - "parameters": [ - { - "name": "mapping_id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "204": { - "description": "Role mapping deleted" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/agents/webhook/{webhook_id}": { - "post": { - "tags": [ - "Agents" - ], - "summary": "Public webhook endpoint. Authenticated via `X-Webhook-Token` header.", - "description": "`POST /api/agents/webhook/{webhook_id}`\nHeader: `X-Webhook-Token: `\n\nThe `webhook_id` in the URL is a short non-secret identifier (safe to log).\nThe actual credential is the secret token in the header.\n\nAccepts any JSON body, which is passed as `user_context` to the agent run.", - "operationId": "webhook_trigger", - "parameters": [ - { - "name": "webhook_id", - "in": "path", - "description": "Webhook ID (non-secret)", - "required": true, - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/WebhookTriggerRequest" - } - } - }, - "required": true - }, - "responses": { - "202": { - "description": "Agent run created", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/WebhookTriggerResponse" - } - } - } - }, - "401": { - "description": "Missing or invalid X-Webhook-Token header" - }, - "404": { - "description": "Invalid webhook ID" - }, - "422": { - "description": "Agent disabled" - } - } - } - }, - "/ai/conversations": { - "get": { - "tags": [ - "AI Chat" - ], - "summary": "List every active conversation across all projects, most-recently-active\nfirst, annotated with project name/slug. Powers the unified \"all chats\"\nswitcher in the AI assistant dock.", - "operationId": "list_all_conversations", - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/GlobalConversationResponse" - } - } - } - } - }, - "401": { - "description": "" - }, - "403": { - "description": "" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/ai/pricing": { - "get": { - "tags": [ - "AI Gateway Pricing" - ], - "operationId": "get_pricing", - "responses": { - "200": { - "description": "Model pricing information", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/PricingResponse" - } - } - } - }, - "401": { - "description": "Unauthorized", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "403": { - "description": "Insufficient permissions", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/ai/providers": { - "get": { - "tags": [ - "AI Gateway Admin" - ], - "operationId": "list_provider_keys", - "responses": { - "200": { - "description": "List of provider keys", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ProviderKeyResponse" - } - } - } - } - }, - "401": { - "description": "Unauthorized", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "403": { - "description": "Insufficient permissions", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "post": { - "tags": [ - "AI Gateway Admin" - ], - "operationId": "create_provider_key", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateProviderKeyRequest" - } - } - }, - "required": true - }, - "responses": { - "201": { - "description": "Provider key created", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProviderKeyResponse" - } - } - } - }, - "400": { - "description": "Validation error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "401": { - "description": "Unauthorized", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "403": { - "description": "Insufficient permissions", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/ai/providers/test": { - "post": { - "tags": [ - "AI Gateway Admin" - ], - "operationId": "test_provider_key_inline", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/TestProviderKeyRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Test result", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/TestProviderKeyResponse" - } - } - } - }, - "400": { - "description": "Validation error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "401": { - "description": "Unauthorized", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "403": { - "description": "Insufficient permissions", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/ai/providers/{id}": { - "delete": { - "tags": [ - "AI Gateway Admin" - ], - "operationId": "delete_provider_key", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "204": { - "description": "Provider key deleted" - }, - "401": { - "description": "Unauthorized", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "403": { - "description": "Insufficient permissions", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "404": { - "description": "Not found", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "patch": { - "tags": [ - "AI Gateway Admin" - ], - "operationId": "update_provider_key", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdateProviderKeyRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Provider key updated", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProviderKeyResponse" - } - } - } - }, - "400": { - "description": "Validation error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "401": { - "description": "Unauthorized", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "403": { - "description": "Insufficient permissions", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "404": { - "description": "Not found", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/ai/providers/{id}/test": { - "post": { - "tags": [ - "AI Gateway Admin" - ], - "operationId": "test_provider_key_by_id", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Test result", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/TestProviderKeyResponse" - } - } - } - }, - "401": { - "description": "Unauthorized", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "403": { - "description": "Insufficient permissions", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "404": { - "description": "Provider key not found", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/ai/usage/by-provider": { - "get": { - "tags": [ - "AI Gateway Usage" - ], - "operationId": "get_usage_by_provider", - "parameters": [ - { - "name": "from", - "in": "query", - "description": "ISO 8601 start time (defaults to 24h ago)", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "to", - "in": "query", - "description": "ISO 8601 end time (defaults to now)", - "required": false, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Usage broken down by provider", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ProviderUsage" - } - } - } - } - }, - "400": { - "description": "Invalid query parameters", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "401": { - "description": "Unauthorized", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "403": { - "description": "Insufficient permissions", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/ai/usage/conversations": { - "get": { - "tags": [ - "AI Gateway Usage" - ], - "operationId": "get_conversations", - "parameters": [ - { - "name": "from", - "in": "query", - "description": "ISO 8601 start time (defaults to 24h ago)", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "to", - "in": "query", - "description": "ISO 8601 end time (defaults to now)", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "limit", - "in": "query", - "description": "Max results (defaults to 50, max 100)", - "required": false, - "schema": { - "type": "integer", - "format": "int64", - "minimum": 0 - } - }, - { - "name": "user_id", - "in": "query", - "description": "Filter by user ID", - "required": false, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "tags", - "in": "query", - "description": "Filter by tags (comma-separated)", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "model", - "in": "query", - "description": "Filter by model name", - "required": false, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Conversation summaries", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ConversationSummary" - } - } - } - } - }, - "400": { - "description": "Invalid query parameters", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "401": { - "description": "Unauthorized", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "403": { - "description": "Insufficient permissions", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/ai/usage/conversations/{conversation_id}": { - "get": { - "tags": [ - "AI Gateway Usage" - ], - "operationId": "get_conversation_detail", - "parameters": [ - { - "name": "conversation_id", - "in": "path", - "description": "Conversation ID", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "limit", - "in": "query", - "description": "Max results (defaults to 100)", - "required": false, - "schema": { - "type": "integer", - "format": "int64", - "minimum": 0 - } - } - ], - "responses": { - "200": { - "description": "Invocations within a conversation", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/UsageLogEntry" - } - } - } - } - }, - "401": { - "description": "Unauthorized", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "403": { - "description": "Insufficient permissions", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/ai/usage/recent": { - "get": { - "tags": [ - "AI Gateway Usage" - ], - "operationId": "get_usage_recent", - "parameters": [ - { - "name": "limit", - "in": "query", - "description": "Page size (defaults to 20, max 50)", - "required": false, - "schema": { - "type": "integer", - "format": "int64", - "minimum": 0 - } - }, - { - "name": "offset", - "in": "query", - "description": "Number of results to skip for pagination (defaults to 0)", - "required": false, - "schema": { - "type": "integer", - "format": "int64", - "minimum": 0 - } - }, - { - "name": "provider", - "in": "query", - "description": "Filter by provider name", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "model", - "in": "query", - "description": "Filter by model name", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "status", - "in": "query", - "description": "Filter by HTTP status code (exact match)", - "required": false, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "cost_gte", - "in": "query", - "description": "Cost greater-than-or-equal, in microcents", - "required": false, - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "cost_gt", - "in": "query", - "description": "Cost strictly greater-than, in microcents", - "required": false, - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "cost_lte", - "in": "query", - "description": "Cost less-than-or-equal, in microcents", - "required": false, - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "cost_lt", - "in": "query", - "description": "Cost strictly less-than, in microcents", - "required": false, - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "tokens_gte", - "in": "query", - "description": "Total tokens greater-than-or-equal", - "required": false, - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "tokens_gt", - "in": "query", - "description": "Total tokens strictly greater-than", - "required": false, - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "tokens_lte", - "in": "query", - "description": "Total tokens less-than-or-equal", - "required": false, - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "tokens_lt", - "in": "query", - "description": "Total tokens strictly less-than", - "required": false, - "schema": { - "type": "integer", - "format": "int64" - } - } - ], - "responses": { - "200": { - "description": "Page of recent usage log entries", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UsageLogPage" - } - } - } - }, - "401": { - "description": "Unauthorized", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "403": { - "description": "Insufficient permissions", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/ai/usage/summary": { - "get": { - "tags": [ - "AI Gateway Usage" - ], - "operationId": "get_usage_summary", - "parameters": [ - { - "name": "from", - "in": "query", - "description": "ISO 8601 start time (defaults to 24h ago)", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "to", - "in": "query", - "description": "ISO 8601 end time (defaults to now)", - "required": false, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Usage summary for the time range", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UsageSummary" - } - } - } - }, - "400": { - "description": "Invalid query parameters", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "401": { - "description": "Unauthorized", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "403": { - "description": "Insufficient permissions", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/ai/usage/timeseries": { - "get": { - "tags": [ - "AI Gateway Usage" - ], - "operationId": "get_usage_timeseries", - "parameters": [ - { - "name": "from", - "in": "query", - "description": "ISO 8601 start time (defaults to 24h ago)", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "to", - "in": "query", - "description": "ISO 8601 end time (defaults to now)", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "bucket", - "in": "query", - "description": "Bucket size: hour, day, week (defaults to day)", - "required": false, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Time-series usage data", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/TimeseriesBucket" - } - } - } - } - }, - "400": { - "description": "Invalid query parameters", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "401": { - "description": "Unauthorized", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "403": { - "description": "Insufficient permissions", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/ai/usage/top-models": { - "get": { - "tags": [ - "AI Gateway Usage" - ], - "operationId": "get_usage_top_models", - "parameters": [ - { - "name": "from", - "in": "query", - "description": "ISO 8601 start time (defaults to 24h ago)", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "to", - "in": "query", - "description": "ISO 8601 end time (defaults to now)", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "limit", - "in": "query", - "description": "Max results (defaults to 10)", - "required": false, - "schema": { - "type": "integer", - "format": "int64", - "minimum": 0 - } - } - ], - "responses": { - "200": { - "description": "Top models by request count", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ModelUsage" - } - } - } - } - }, - "400": { - "description": "Invalid query parameters", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "401": { - "description": "Unauthorized", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "403": { - "description": "Insufficient permissions", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/ai/v1/chat/completions": { - "post": { - "tags": [ - "AI Gateway" - ], - "operationId": "chat_completions", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ChatCompletionRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Chat completion response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ChatCompletionResponse" - } - } - } - }, - "400": { - "description": "Invalid request", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/OpenAiErrorResponse" - } - } - } - }, - "401": { - "description": "Unauthorized", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/OpenAiErrorResponse" - } - } - } - }, - "404": { - "description": "Model not found", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/OpenAiErrorResponse" - } - } - } - }, - "500": { - "description": "Internal error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/OpenAiErrorResponse" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/ai/v1/embeddings": { - "post": { - "tags": [ - "AI Gateway" - ], - "operationId": "embeddings", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/EmbeddingRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Embedding response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/EmbeddingResponse" - } - } - } - }, - "400": { - "description": "Invalid request", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/OpenAiErrorResponse" - } - } - } - }, - "401": { - "description": "Unauthorized", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/OpenAiErrorResponse" - } - } - } - }, - "404": { - "description": "Model not found", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/OpenAiErrorResponse" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/ai/v1/models": { - "get": { - "tags": [ - "AI Gateway" - ], - "operationId": "list_models", - "responses": { - "200": { - "description": "List of available models", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ModelListResponse" - } - } - } - }, - "401": { - "description": "Unauthorized", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/OpenAiErrorResponse" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/analytics/active-visitors": { - "get": { - "tags": [ - "Analytics" - ], - "summary": "Get detailed active visitors", - "operationId": "get_analytics_active_visitors", - "parameters": [ - { - "name": "project_id", - "in": "query", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "environment_id", - "in": "query", - "description": "Environment ID (optional)", - "required": false, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "deployment_id", - "in": "query", - "description": "Deployment ID (optional)", - "required": false, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "window_minutes", - "in": "query", - "description": "Time window in minutes for active visitors (default: 5)", - "required": false, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Successfully retrieved active visitors", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ActiveVisitorsResponse" - } - } - } - }, - "400": { - "description": "Invalid parameters or project not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/analytics/event-detail": { - "get": { - "tags": [ - "Analytics" - ], - "summary": "Get detailed analytics for a specific event", - "operationId": "get_event_detail", - "parameters": [ - { - "name": "event_name", - "in": "query", - "description": "Event name to get details for", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "project_id", - "in": "query", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "environment_id", - "in": "query", - "description": "Environment ID (optional)", - "required": false, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "start_date", - "in": "query", - "description": "Start date (ISO 8601)", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "end_date", - "in": "query", - "description": "End date (ISO 8601)", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "bucket_interval", - "in": "query", - "description": "Bucket interval: hour, day, week, month (default: auto)", - "required": false, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Successfully retrieved event details", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/EventDetailResponse" - } - } - } - }, - "400": { - "description": "Invalid parameters" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/analytics/event-entries": { - "get": { - "tags": [ - "Analytics" - ], - "summary": "Get paginated list of raw occurrences of a specific event, including custom JSON properties", - "operationId": "get_event_entries", - "parameters": [ - { - "name": "event_name", - "in": "query", - "description": "Event name to list occurrences for", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "project_id", - "in": "query", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "environment_id", - "in": "query", - "description": "Environment ID (optional)", - "required": false, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "start_date", - "in": "query", - "description": "Start date (ISO 8601)", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "end_date", - "in": "query", - "description": "End date (ISO 8601)", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "page", - "in": "query", - "description": "Page number (1-based, default: 1)", - "required": false, - "schema": { - "type": "integer", - "format": "int64", - "minimum": 0 - } - }, - { - "name": "per_page", - "in": "query", - "description": "Items per page (default: 20, max: 100)", - "required": false, - "schema": { - "type": "integer", - "format": "int64", - "minimum": 0 - } - } - ], - "responses": { - "200": { - "description": "Successfully retrieved event entries", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/EventEntriesResponse" - } - } - } - }, - "400": { - "description": "Invalid parameters" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/analytics/event-visitors": { - "get": { - "tags": [ - "Analytics" - ], - "summary": "Get paginated list of visitors who triggered a specific event", - "operationId": "get_event_visitors", - "parameters": [ - { - "name": "event_name", - "in": "query", - "description": "Event name to list visitors for", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "project_id", - "in": "query", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "environment_id", - "in": "query", - "description": "Environment ID (optional)", - "required": false, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "start_date", - "in": "query", - "description": "Start date (ISO 8601)", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "end_date", - "in": "query", - "description": "End date (ISO 8601)", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "page", - "in": "query", - "description": "Page number (1-based, default: 1)", - "required": false, - "schema": { - "type": "integer", - "format": "int64", - "minimum": 0 - } - }, - { - "name": "per_page", - "in": "query", - "description": "Items per page (default: 20, max: 100)", - "required": false, - "schema": { - "type": "integer", - "format": "int64", - "minimum": 0 - } - } - ], - "responses": { - "200": { - "description": "Successfully retrieved event visitors", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/EventVisitorsResponse" - } - } - } - }, - "400": { - "description": "Invalid parameters" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/analytics/events": { - "get": { - "tags": [ - "Analytics" - ], - "operationId": "get_analytics_events_count", - "parameters": [ - { - "name": "start_date", - "in": "query", - "description": "Start date in format YYYY-MM-DD HH:MM:SS", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "end_date", - "in": "query", - "description": "End date in format YYYY-MM-DD HH:MM:SS", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "project_id", - "in": "query", - "description": "Project ID or slug", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "limit", - "in": "query", - "description": "Maximum number of results to return", - "required": false, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "environment_id", - "in": "query", - "description": "Environment ID (optional)", - "required": false, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "custom_events_only", - "in": "query", - "description": "Only return custom events, excluding system events like page_view, page_leave, heartbeat (default: true)", - "required": false, - "schema": { - "type": "boolean" - } - }, - { - "name": "breakdown", - "in": "query", - "description": "Breakdown by geography: 'country', 'region', or 'city' (optional)", - "required": false, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Successfully retrieved event counts", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/EventCount" - } - } - } - } - }, - "400": { - "description": "Invalid date format, missing required parameters, or project not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/analytics/general-stats": { - "get": { - "tags": [ - "Analytics" - ], - "summary": "Get general statistics across all projects for a time frame", - "operationId": "get_general_stats", - "parameters": [ - { - "name": "start_date", - "in": "query", - "description": "Start date in format YYYY-MM-DD HH:MM:SS", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "end_date", - "in": "query", - "description": "End date in format YYYY-MM-DD HH:MM:SS", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "project_ids", - "in": "query", - "description": "Optional: Filter by specific project IDs (comma-separated)", - "required": false, - "schema": { - "type": "array", - "items": { - "type": "integer", - "format": "int32" - } - } - }, - { - "name": "environment_id", - "in": "query", - "description": "Environment ID (optional)", - "required": false, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "include_project_breakdown", - "in": "query", - "description": "Whether to include per-project breakdown (default: false)", - "required": false, - "schema": { - "type": "boolean" - } - } - ], - "responses": { - "200": { - "description": "Successfully retrieved general statistics", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/GeneralStatsResponse" - } - } - } - }, - "400": { - "description": "Invalid date format or parameters" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/analytics/has-events": { - "get": { - "tags": [ - "Analytics" - ], - "operationId": "check_analytics_has_events", - "parameters": [ - { - "name": "project_id", - "in": "query", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "environment_id", - "in": "query", - "description": "Environment ID (optional)", - "required": false, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Analytics events existence check", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HasAnalyticsEventsResponse" - } - } - } - }, - "400": { - "description": "Bad request" - }, - "401": { - "description": "Unauthorized" - }, - "404": { - "description": "Project not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/analytics/live-visitors": { - "get": { - "tags": [ - "Analytics" - ], - "summary": "Get list of currently live visitors from visitor table", - "operationId": "get_live_visitors_list", - "parameters": [ - { - "name": "project_id", - "in": "query", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "environment_id", - "in": "query", - "description": "Environment ID (optional)", - "required": false, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "window_minutes", - "in": "query", - "description": "Time window in minutes for live visitors (default: 5)", - "required": false, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Successfully retrieved live visitors list", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LiveVisitorsListResponse" - } - } - } - }, - "400": { - "description": "Invalid parameters or project not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/analytics/page-flow": { - "get": { - "tags": [ - "Analytics" - ], - "summary": "Get page flow analytics: entry pages, exit pages, drop-off points, and page transitions", - "operationId": "get_page_flow", - "parameters": [ - { - "name": "project_id", - "in": "query", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "environment_id", - "in": "query", - "description": "Environment ID (optional)", - "required": false, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "start_date", - "in": "query", - "description": "Start date in ISO 8601 format", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "end_date", - "in": "query", - "description": "End date in ISO 8601 format", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "limit", - "in": "query", - "description": "Max entry/exit pages to return (default: 20, max: 100)", - "required": false, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "transitions_limit", - "in": "query", - "description": "Max page transitions to return (default: 50, max: 200)", - "required": false, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "min_views_for_dropoff", - "in": "query", - "description": "Minimum views for drop-off analysis (default: 5)", - "required": false, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Successfully retrieved page flow analytics", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/PageFlowResponse" - } - } - } - }, - "400": { - "description": "Invalid parameters" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/analytics/page-hourly-sessions": { - "get": { - "tags": [ - "Analytics" - ], - "operationId": "get_page_hourly_sessions", - "parameters": [ - { - "name": "page_path", - "in": "query", - "description": "The page path to get sessions for", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "project_id", - "in": "query", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "environment_id", - "in": "query", - "description": "Environment ID (optional)", - "required": false, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "start_time", - "in": "query", - "description": "Start time in format YYYY-MM-DD HH:MM:SS", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "end_time", - "in": "query", - "description": "End time in format YYYY-MM-DD HH:MM:SS", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "bucket_interval", - "in": "query", - "description": "Bucket interval: 'hour', 'day', 'week', or 'month' (default: auto-determined based on range)", - "required": false, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Successfully retrieved page sessions with time buckets", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/PageHourlySessionsResponse" - } - } - } - }, - "400": { - "description": "Invalid parameters or project not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/analytics/page-path-detail": { - "get": { - "tags": [ - "Analytics" - ], - "summary": "Get detailed analytics for a specific page path\nReturns visitors, page views, activity over time, geographic distribution, and referrers", - "operationId": "get_page_path_detail", - "parameters": [ - { - "name": "page_path", - "in": "query", - "description": "The page path to get details for (URL-encoded)", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "project_id", - "in": "query", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "environment_id", - "in": "query", - "description": "Environment ID (optional)", - "required": false, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "start_date", - "in": "query", - "description": "Start date in ISO 8601 format", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "end_date", - "in": "query", - "description": "End date in ISO 8601 format", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "bucket_interval", - "in": "query", - "description": "Bucket interval for time series: 'hour', 'day', 'week', 'month' (default: auto based on date range)", - "required": false, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Successfully retrieved page path detail analytics", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/PagePathDetailResponse" - } - } - } - }, - "400": { - "description": "Invalid parameters or project not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/analytics/page-path-visitors": { - "get": { - "tags": [ - "Analytics" - ], - "summary": "Get individual visitor sessions for a specific page path", - "operationId": "get_page_path_visitors", - "parameters": [ - { - "name": "page_path", - "in": "query", - "description": "The page path to get visitors for (URL-encoded)", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "project_id", - "in": "query", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "environment_id", - "in": "query", - "description": "Environment ID (optional)", - "required": false, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "start_date", - "in": "query", - "description": "Start date in ISO 8601 format", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "end_date", - "in": "query", - "description": "End date in ISO 8601 format", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "page", - "in": "query", - "description": "Page number (1-based, default: 1)", - "required": false, - "schema": { - "type": "integer", - "format": "int64", - "minimum": 0 - } - }, - { - "name": "per_page", - "in": "query", - "description": "Items per page (default: 50, max: 100)", - "required": false, - "schema": { - "type": "integer", - "format": "int64", - "minimum": 0 - } - } - ], - "responses": { - "200": { - "description": "Successfully retrieved page path visitors", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/PagePathVisitorsResponse" - } - } - } - }, - "400": { - "description": "Invalid parameters" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/analytics/page-paths": { - "get": { - "tags": [ - "Analytics" - ], - "operationId": "get_page_paths", - "parameters": [ - { - "name": "project_id", - "in": "query", - "description": "Project ID or slug", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "environment_id", - "in": "query", - "description": "Environment ID (optional)", - "required": false, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "start_date", - "in": "query", - "description": "Start date in format YYYY-MM-DD HH:MM:SS (optional)", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "end_date", - "in": "query", - "description": "End date in format YYYY-MM-DD HH:MM:SS (optional)", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "limit", - "in": "query", - "description": "Maximum number of page paths to return (default: 100, max: 1000)", - "required": false, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Successfully retrieved page paths", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/PagePathsResponse" - } - } - } - }, - "400": { - "description": "Invalid parameters or project not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/analytics/page-paths-sparklines": { - "get": { - "tags": [ - "Analytics" - ], - "operationId": "get_page_paths_sparklines", - "parameters": [ - { - "name": "project_id", - "in": "query", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "environment_id", - "in": "query", - "description": "Environment ID (optional)", - "required": false, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "start_time", - "in": "query", - "description": "Start time in ISO 8601 format", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "end_time", - "in": "query", - "description": "End time in ISO 8601 format", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "page_paths", - "in": "query", - "description": "Comma-separated list of page paths", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Sparkline data for all requested page paths", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/PagePathsSparklineResponse" - } - } - } - }, - "400": { - "description": "Invalid parameters" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/analytics/recent-activity": { - "get": { - "tags": [ - "Analytics" - ], - "summary": "Get recent activity events for real-time activity feed", - "operationId": "get_recent_activity", - "parameters": [ - { - "name": "project_id", - "in": "query", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "environment_id", - "in": "query", - "description": "Environment ID (optional)", - "required": false, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "since_id", - "in": "query", - "description": "Return events with ID greater than this (cursor-based polling)", - "required": false, - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "limit", - "in": "query", - "description": "Max events to return (default: 50, max: 100)", - "required": false, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Successfully retrieved recent activity events", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/RecentActivityResponse" - } - } - } - }, - "400": { - "description": "Invalid parameters" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/analytics/sessions/{session_id}": { - "get": { - "tags": [ - "Analytics" - ], - "summary": "Get detailed information about a specific session including events and request logs", - "operationId": "get_session_details", - "parameters": [ - { - "name": "session_id", - "in": "path", - "description": "Session ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "project_id", - "in": "query", - "description": "Project ID or slug", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "environment_id", - "in": "query", - "description": "Environment ID (optional)", - "required": false, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Successfully retrieved session details", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SessionDetails" - } - } - } - }, - "400": { - "description": "Invalid parameters or project not found" - }, - "404": { - "description": "Session not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/analytics/sessions/{session_id}/events": { - "get": { - "tags": [ - "Analytics" - ], - "operationId": "get_analytics_session_events", - "parameters": [ - { - "name": "session_id", - "in": "path", - "description": "Session ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "project_id", - "in": "query", - "description": "Project ID or slug", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "environment_id", - "in": "query", - "description": "Environment ID (optional)", - "required": false, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "start_date", - "in": "query", - "description": "Start date in format YYYY-MM-DD HH:MM:SS", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "end_date", - "in": "query", - "description": "End date in format YYYY-MM-DD HH:MM:SS", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "limit", - "in": "query", - "description": "Number of results to return (default: 100)", - "required": false, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "offset", - "in": "query", - "description": "Number of results to skip (default: 0)", - "required": false, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Successfully retrieved session events", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SessionEventsResponse" - } - } - } - }, - "400": { - "description": "Invalid parameters or project not found" - }, - "404": { - "description": "Session not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/analytics/sessions/{session_id}/logs": { - "get": { - "tags": [ - "Analytics" - ], - "operationId": "get_session_logs", - "parameters": [ - { - "name": "session_id", - "in": "path", - "description": "Session ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "project_id", - "in": "query", - "description": "Project ID or slug", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "environment_id", - "in": "query", - "description": "Environment ID (optional)", - "required": false, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "start_date", - "in": "query", - "description": "Start date in format YYYY-MM-DD HH:MM:SS", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "end_date", - "in": "query", - "description": "End date in format YYYY-MM-DD HH:MM:SS", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "limit", - "in": "query", - "description": "Number of results to return (default: 100)", - "required": false, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "offset", - "in": "query", - "description": "Number of results to skip (default: 0)", - "required": false, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Successfully retrieved session logs", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SessionLogsResponse" - } - } - } - }, - "400": { - "description": "Invalid parameters or project not found" - }, - "404": { - "description": "Session not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/analytics/visitor-facets": { - "get": { - "tags": [ - "Analytics" - ], - "summary": "Get filter dropdown contents for the visitors page. Returns the top\nvalues per dimension with distinct visitor counts so the UI can render\n\"Country \u2014 1,234 visitors\" rows. Each dimension is computed against the\nsegment minus its own filter, so a selected value never collapses its\nown dropdown.", - "operationId": "get_visitor_facets", - "parameters": [ - { - "name": "start_date", - "in": "query", - "description": "Start date in format YYYY-MM-DD HH:MM:SS", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "end_date", - "in": "query", - "description": "End date in format YYYY-MM-DD HH:MM:SS", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "project_id", - "in": "query", - "description": "Project ID or slug", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "environment_id", - "in": "query", - "description": "Environment ID (optional)", - "required": false, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "include_crawlers", - "in": "query", - "description": "Include crawlers (default: false)", - "required": false, - "schema": { - "type": "boolean" - } - }, - { - "name": "has_activity_only", - "in": "query", - "description": "Hide ghost visitors (default: true)", - "required": false, - "schema": { - "type": "boolean" - } - }, - { - "name": "per_facet_limit", - "in": "query", - "description": "Top N values per dimension (default: 50, max: 200)", - "required": false, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "filter_country", - "in": "query", - "description": "Geolocation country", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "filter_region", - "in": "query", - "description": "Geolocation region", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "filter_city", - "in": "query", - "description": "Geolocation city", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "filter_channel", - "in": "query", - "description": "First-touch channel", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "filter_referrer", - "in": "query", - "description": "First-touch referrer hostname (use 'Direct' for null)", - "required": false, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Top values per dimension", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/VisitorFacets" - } - } - } - }, - "400": { - "description": "Invalid date format or project not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/analytics/visitors": { - "get": { - "tags": [ - "Analytics" - ], - "summary": "Get list of visitors with summary information", - "operationId": "get_visitors", - "parameters": [ - { - "name": "start_date", - "in": "query", - "description": "Start date in format YYYY-MM-DD HH:MM:SS", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "end_date", - "in": "query", - "description": "End date in format YYYY-MM-DD HH:MM:SS", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "project_id", - "in": "query", - "description": "Project ID or slug", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "environment_id", - "in": "query", - "description": "Environment ID (optional)", - "required": false, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "include_crawlers", - "in": "query", - "description": "Include crawlers (default: false)", - "required": false, - "schema": { - "type": "boolean" - } - }, - { - "name": "limit", - "in": "query", - "description": "Maximum number of visitors to return (default: 50)", - "required": false, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "offset", - "in": "query", - "description": "Number of visitors to skip (default: 0)", - "required": false, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "has_activity_only", - "in": "query", - "description": "Filter to only include visitors with recorded activity (events/sessions). When true, excludes ghost visitors (default: true)", - "required": false, - "schema": { - "type": "boolean" - } - }, - { - "name": "filter_country", - "in": "query", - "description": "Geolocation country", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "filter_region", - "in": "query", - "description": "Geolocation region", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "filter_city", - "in": "query", - "description": "Geolocation city", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "filter_channel", - "in": "query", - "description": "First-touch channel", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "filter_referrer", - "in": "query", - "description": "First-touch referrer hostname (use 'Direct' for null)", - "required": false, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Successfully retrieved visitors", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/VisitorsResponse" - } - } - } - }, - "400": { - "description": "Invalid date format, missing required parameters, or project not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/analytics/visitors/guid/{visitor_id}": { - "get": { - "tags": [ - "Analytics" - ], - "summary": "Get visitor by GUID with geolocation data", - "operationId": "get_visitor_by_guid", - "parameters": [ - { - "name": "visitor_id", - "in": "path", - "description": "Visitor GUID (supports enc_ prefix for encrypted IDs)", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "project_id", - "in": "query", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "environment_id", - "in": "query", - "description": "Environment ID (optional)", - "required": false, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Successfully retrieved visitor with geolocation", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/VisitorWithGeolocation" - } - } - } - }, - "400": { - "description": "Invalid parameters or project not found" - }, - "404": { - "description": "Visitor not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/analytics/visitors/id/{id}": { - "get": { - "tags": [ - "Analytics" - ], - "summary": "Get visitor by numeric ID with geolocation data", - "operationId": "get_visitor_by_id", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "Visitor numeric ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "project_id", - "in": "query", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "environment_id", - "in": "query", - "description": "Environment ID (optional)", - "required": false, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Successfully retrieved visitor with geolocation", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/VisitorWithGeolocation" - } - } - } - }, - "400": { - "description": "Invalid parameters or project not found" - }, - "404": { - "description": "Visitor not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/analytics/visitors/{visitor_id}": { - "get": { - "tags": [ - "Analytics" - ], - "summary": "Get detailed information about a specific visitor by numeric ID", - "operationId": "get_visitor_details", - "parameters": [ - { - "name": "visitor_id", - "in": "path", - "description": "Visitor numeric ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "project_id", - "in": "query", - "description": "Project ID or slug", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "environment_id", - "in": "query", - "description": "Environment ID (optional)", - "required": false, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Successfully retrieved visitor details", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/VisitorDetails" - } - } - } - }, - "400": { - "description": "Invalid parameters or project not found" - }, - "404": { - "description": "Visitor not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/analytics/visitors/{visitor_id}/enrich": { - "put": { - "tags": [ - "Analytics" - ], - "operationId": "enrich_visitor", - "parameters": [ - { - "name": "visitor_id", - "in": "path", - "description": "Visitor ID - can be numeric ID, GUID, or encrypted GUID (enc_xxx)", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "project_id", - "in": "query", - "description": "Project ID or slug", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/EnrichVisitorRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Successfully enriched visitor data", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/EnrichVisitorResponse" - } - } - } - }, - "400": { - "description": "Invalid parameters or project not found" - }, - "404": { - "description": "Visitor not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/analytics/visitors/{visitor_id}/info": { - "get": { - "tags": [ - "Analytics" - ], - "summary": "Get visitor record from database", - "operationId": "get_visitor_info", - "parameters": [ - { - "name": "visitor_id", - "in": "path", - "description": "Visitor numeric ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "project_id", - "in": "query", - "description": "Project ID or slug", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Successfully retrieved visitor info", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/VisitorRecord" - } - } - } - }, - "400": { - "description": "Invalid parameters or project not found" - }, - "404": { - "description": "Visitor not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/analytics/visitors/{visitor_id}/journey": { - "get": { - "tags": [ - "Analytics" - ], - "summary": "Get the complete visitor journey: all events across all sessions, grouped by session", - "operationId": "get_visitor_journey", - "parameters": [ - { - "name": "visitor_id", - "in": "path", - "description": "Visitor numeric ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "project_id", - "in": "query", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "limit_sessions", - "in": "query", - "description": "Maximum number of sessions to return (default: 50)", - "required": false, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Successfully retrieved visitor journey", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/VisitorJourneyResponse" - } - } - } - }, - "400": { - "description": "Invalid parameters" - }, - "404": { - "description": "Visitor not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/analytics/visitors/{visitor_id}/sessions": { - "get": { - "tags": [ - "Analytics" - ], - "summary": "Get all sessions for a specific visitor by numeric ID", - "operationId": "get_analytics_visitor_sessions", - "parameters": [ - { - "name": "visitor_id", - "in": "path", - "description": "Visitor numeric ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "project_id", - "in": "query", - "description": "Project ID or slug", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "environment_id", - "in": "query", - "description": "Environment ID (optional)", - "required": false, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "limit", - "in": "query", - "description": "Maximum number of sessions to return (default: 100)", - "required": false, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Successfully retrieved visitor sessions", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/VisitorSessionsResponse" - } - } - } - }, - "400": { - "description": "Invalid parameters or project not found" - }, - "404": { - "description": "Visitor not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/analytics/visitors/{visitor_id}/stats": { - "get": { - "tags": [ - "Analytics" - ], - "summary": "Get visitor statistics", - "operationId": "get_visitor_stats", - "parameters": [ - { - "name": "visitor_id", - "in": "path", - "description": "Visitor numeric ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "project_id", - "in": "query", - "description": "Project ID or slug", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Successfully retrieved visitor statistics", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/VisitorStats" - } - } - } - }, - "400": { - "description": "Invalid parameters or project not found" - }, - "404": { - "description": "Visitor not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/api-keys": { - "get": { - "tags": [ - "API Keys" - ], - "operationId": "list_api_keys", - "parameters": [ - { - "name": "page", - "in": "query", - "description": "Page number (default: 1)", - "required": false, - "schema": { - "type": "integer", - "format": "int64", - "minimum": 0 - } - }, - { - "name": "page_size", - "in": "query", - "description": "Items per page (default: 20)", - "required": false, - "schema": { - "type": "integer", - "format": "int64", - "minimum": 0 - } - } - ], - "responses": { - "200": { - "description": "API keys retrieved successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ApiKeyListResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Forbidden" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "post": { - "tags": [ - "API Keys" - ], - "operationId": "create_api_key", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateApiKeyRequest" - } - } - }, - "required": true - }, - "responses": { - "201": { - "description": "API key created successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateApiKeyResponse" - } - } - } - }, - "400": { - "description": "Bad request" - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Forbidden" - }, - "409": { - "description": "Conflict - API key name already exists" - }, - "428": { - "description": "Recent MFA verification required" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/api-keys/permissions": { - "get": { - "tags": [ - "API Keys" - ], - "operationId": "get_api_key_permissions", - "responses": { - "200": { - "description": "Available permissions and roles retrieved successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AvailablePermissions" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/api-keys/{id}": { - "get": { - "tags": [ - "API Keys" - ], - "operationId": "get_api_key", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "API key ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "API key retrieved successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ApiKeyResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Forbidden" - }, - "404": { - "description": "Not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "put": { - "tags": [ - "API Keys" - ], - "operationId": "update_api_key", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "API key ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdateApiKeyRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "API key updated successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ApiKeyResponse" - } - } - } - }, - "400": { - "description": "Bad request" - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Forbidden" - }, - "404": { - "description": "Not found" - }, - "409": { - "description": "Conflict - API key name already exists" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "delete": { - "tags": [ - "API Keys" - ], - "operationId": "delete_api_key", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "API key ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "204": { - "description": "API key deleted successfully" - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Forbidden" - }, - "404": { - "description": "Not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/api-keys/{id}/activate": { - "post": { - "tags": [ - "API Keys" - ], - "operationId": "activate_api_key", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "API key ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "API key activated successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ApiKeyResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Forbidden" - }, - "404": { - "description": "Not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/api-keys/{id}/deactivate": { - "post": { - "tags": [ - "API Keys" - ], - "operationId": "deactivate_api_key", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "API key ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "API key deactivated successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ApiKeyResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Forbidden" - }, - "404": { - "description": "Not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/api-keys/{id}/rotate": { - "post": { - "tags": [ - "API Keys" - ], - "operationId": "rotate_api_key", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "API key ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "API key rotated successfully; the response contains the new plaintext secret, shown only once", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateApiKeyResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Forbidden" - }, - "404": { - "description": "Not found" - }, - "428": { - "description": "Recent MFA verification required" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/auth/cli/device/approve": { - "post": { - "tags": [ - "Authentication" - ], - "operationId": "cli_device_approve", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CliDeviceApproveRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Session approved; CLI can now claim the API key", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CliDeviceApproveResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Browser session required" - }, - "404": { - "description": "Unknown user_code" - }, - "409": { - "description": "Already resolved" - }, - "410": { - "description": "Session expired" - }, - "428": { - "description": "Recent MFA verification required" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "session_token": [] - } - ] - } - }, - "/auth/cli/device/deny": { - "post": { - "tags": [ - "Authentication" - ], - "operationId": "cli_device_deny", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CliDeviceApproveRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Session denied", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CliDeviceApproveResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "404": { - "description": "Unknown user_code" - }, - "409": { - "description": "Already resolved" - }, - "410": { - "description": "Session expired" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "session_token": [] - } - ] - } - }, - "/auth/cli/device/lookup": { - "get": { - "tags": [ - "Authentication" - ], - "operationId": "cli_device_lookup", - "parameters": [ - { - "name": "user_code", - "in": "query", - "description": "`user_code` as displayed in the CLI / pasted into the URL.", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Device session metadata", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CliDeviceLookupResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "404": { - "description": "Unknown user_code" - }, - "410": { - "description": "Device session expired" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "session_token": [] - } - ] - } - }, - "/auth/cli/device/poll": { - "post": { - "tags": [ - "Authentication" - ], - "operationId": "cli_device_poll", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CliDevicePollRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Poll result; check `status` field", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CliDevicePollResponse" - } - } - } - }, - "404": { - "description": "Unknown device_code" - }, - "500": { - "description": "Internal server error" - } - } - } - }, - "/auth/cli/device/start": { - "post": { - "tags": [ - "Authentication" - ], - "operationId": "cli_device_start", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CliDeviceStartRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Device session created", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CliDeviceStartResponse" - } - } - } - }, - "500": { - "description": "Internal server error" - } - } - } - }, - "/auth/cli/logout": { - "post": { - "tags": [ - "Authentication" - ], - "operationId": "cli_logout", - "responses": { - "204": { - "description": "API key revoked" - }, - "401": { - "description": "Not authenticated" - }, - "403": { - "description": "Endpoint requires API key authentication" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/auth/email-status": { - "get": { - "tags": [ - "Authentication" - ], - "operationId": "email_status", - "responses": { - "200": { - "description": "Email configuration status", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/EmailStatusResponse" - } - } - } - }, - "500": { - "description": "Internal server error" - } - } - } - }, - "/auth/login": { - "post": { - "tags": [ - "Authentication" - ], - "operationId": "login", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LoginRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Login successful, session cookie set", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AuthResponse" - } - } - } - }, - "401": { - "description": "Invalid credentials, or the account's role requires MFA enrollment that has not been completed" - }, - "500": { - "description": "Internal server error" - } - } - } - }, - "/auth/oidc/callback": { - "get": { - "tags": [ - "Authentication" - ], - "operationId": "oidc_callback", - "parameters": [ - { - "name": "code", - "in": "query", - "required": false, - "schema": { - "type": [ - "string", - "null" - ] - } - }, - { - "name": "state", - "in": "query", - "required": false, - "schema": { - "type": [ - "string", - "null" - ] - } - }, - { - "name": "error", - "in": "query", - "required": false, - "schema": { - "type": [ - "string", - "null" - ] - } - }, - { - "name": "error_description", - "in": "query", - "required": false, - "schema": { - "type": [ - "string", - "null" - ] - } - } - ], - "responses": { - "302": { - "description": "Redirect to app with session cookie or login error" - } - } - } - }, - "/auth/oidc/login/{slug}": { - "get": { - "tags": [ - "Authentication" - ], - "operationId": "start_oidc_login_by_slug", - "parameters": [ - { - "name": "slug", - "in": "path", - "description": "OIDC provider slug (from /email-status or /auth/oidc/providers)", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "return_to", - "in": "query", - "required": false, - "schema": { - "type": [ - "string", - "null" - ] - } - } - ], - "responses": { - "302": { - "description": "Redirect to IdP authorize URL" - }, - "404": { - "description": "Provider not found" - }, - "503": { - "description": "OIDC provider unreachable" - } - } - } - }, - "/auth/oidc/providers": { - "get": { - "tags": [ - "Authentication" - ], - "operationId": "list_public_providers", - "responses": { - "200": { - "description": "Enabled OIDC providers for login page", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/OidcProvidersListResponse" - } - } - } - } - } - } - }, - "/auth/password-reset/request": { - "post": { - "tags": [ - "Authentication" - ], - "operationId": "request_password_reset", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/EmailRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Reset email sent if account exists", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AuthResponse" - } - } - } - }, - "503": { - "description": "Email service not configured" - } - } - } - }, - "/auth/password-reset/verify": { - "post": { - "tags": [ - "Authentication" - ], - "operationId": "reset_password", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ResetPasswordRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Password reset successful", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AuthResponse" - } - } - } - }, - "400": { - "description": "Invalid or expired token" - }, - "500": { - "description": "Internal server error" - } - } - } - }, - "/auth/step-up": { - "post": { - "tags": [ - "Authentication" - ], - "operationId": "verify_step_up", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/VerifyStepUpRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Session elevated for sensitive actions", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/StepUpResponse" - } - } - } - }, - "400": { - "description": "Verification code is empty" - }, - "401": { - "description": "Invalid code or expired session" - }, - "403": { - "description": "Browser session required" - }, - "428": { - "description": "MFA setup required" - }, - "429": { - "description": "Too many verification attempts" - }, - "500": { - "description": "Verification infrastructure failed" - } - }, - "security": [ - { - "session_token": [] - } - ] - } - }, - "/auth/verify-email": { - "get": { - "tags": [ - "Authentication" - ], - "operationId": "verify_email", - "parameters": [ - { - "name": "token", - "in": "query", - "description": "Email verification token", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Email verified successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AuthResponse" - } - } - } - }, - "400": { - "description": "Invalid or expired token" - }, - "500": { - "description": "Internal server error" - } - } - } - }, - "/auth/verify-mfa": { - "post": { - "tags": [ - "Authentication" - ], - "operationId": "verify_mfa_challenge", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/MfaVerificationRequest" - } - } - }, - "required": true - }, - "responses": { - "204": { - "description": "MFA verification successful" - }, - "400": { - "description": "Invalid request" - }, - "401": { - "description": "Invalid MFA code" - }, - "500": { - "description": "Internal server error" - } - } - } - }, - "/backups/alerts": { - "get": { - "tags": [ - "Backups" - ], - "summary": "List open backup alerts.", - "description": "Returns all alerts that have not yet been resolved, ordered by `opened_at`\ndescending (newest first). The UI renders these as a banner above the\nBackups page content. Alerts are auto-opened by the watcher and\nauto-resolved when the triggering condition clears.\n\n**Schedule overdue** \u2014 the backup scheduler did not enqueue a job within\nthe expected window (1 hour past `next_run`). Usually means the scheduler\ntask is dead or wedged.\n\n**Job stalled** \u2014 a `backup_jobs` row has been in `state='pending'` for\nmore than 1 hour. The runner never claimed the job. Usually means the\nrunner task is dead or the runner concurrency cap is too low.", - "operationId": "list_backup_alerts", - "responses": { - "200": { - "description": "List of open backup alerts", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/BackupAlertListResponse" - } - } - } - }, - "401": { - "description": "Unauthorized", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/backups/cleanup": { - "post": { - "tags": [ - "Backups" - ], - "summary": "Preview or run retention using each selected schedule's configured retention days.", - "operationId": "cleanup_expired_backups", - "parameters": [ - { - "name": "dry_run", - "in": "query", - "description": "Return the backups selected by retention without deleting anything.", - "required": false, - "schema": { - "type": "boolean" - } - }, - { - "name": "schedule_id", - "in": "query", - "description": "Limit cleanup to one backup schedule.", - "required": false, - "schema": { - "type": [ - "integer", - "null" - ], - "format": "int32" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CleanupExpiredBackupsRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Retention cleanup completed", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/RetentionCleanupReport" - } - } - } - }, - "400": { - "description": "Missing or invalid preview candidate list", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "401": { - "description": "Unauthorized", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "403": { - "description": "Insufficient permissions", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "404": { - "description": "Schedule or backup not found", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "409": { - "description": "Cleanup preview is stale", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "500": { - "description": "Cleanup could not be started", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/backups/external-services/{id}/run": { - "post": { - "tags": [ - "Backups" - ], - "summary": "Run a backup for an external service manually.", - "description": "Enqueues the backup for asynchronous execution via the `BackupRunner`\n(ADR-014). Returns `202 Accepted` immediately: pending parent and child\nrows are inserted, and a `backup_jobs` row is enqueued for the resolved\nengine. Poll `GET /backups/{id}` to observe `pending \u2192 running \u2192 completed`.", - "operationId": "run_external_service_backup", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/RunExternalServiceBackupRequest" - } - } - }, - "required": true - }, - "responses": { - "202": { - "description": "Backup enqueued for async execution", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ExternalServiceBackupResponse" - } - } - } - }, - "400": { - "description": "Invalid request", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "404": { - "description": "External service or S3 source not found", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/backups/external-services/{service_id}/backups": { - "get": { - "tags": [ - "Backups" - ], - "summary": "List all backups for a specific external service (DB-only, no S3 scan).", - "description": "Returns a paginated list of backups that belong to this service.\nCompletes in <100 ms regardless of S3 endpoint latency because it\nnever touches S3.", - "operationId": "list_external_service_backups", - "parameters": [ - { - "name": "service_id", - "in": "path", - "description": "External service ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "page", - "in": "query", - "description": "Page number (1-based). Defaults to 1.", - "required": false, - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "page_size", - "in": "query", - "description": "Items per page. Defaults to 20, max 100.", - "required": false, - "schema": { - "type": "integer", - "format": "int64" - } - } - ], - "responses": { - "200": { - "description": "Paginated list of backups for this service", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ServiceBackupListResponse" - } - } - } - }, - "401": { - "description": "Unauthorized", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/backups/external-services/{service_id}/schedules": { - "get": { - "tags": [ - "Backups" - ], - "summary": "List the schedules that target a specific external service. Useful for\nthe service detail page (\"which schedules back this DB up?\").", - "operationId": "list_service_schedules", - "parameters": [ - { - "name": "service_id", - "in": "path", - "description": "External service ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Schedules backing up this service", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/BackupScheduleResponse" - } - } - } - } - }, - "401": { - "description": "Unauthorized", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "403": { - "description": "Insufficient permissions", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "404": { - "description": "Service not found", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/backups/s3-sources": { - "get": { - "tags": [ - "Backups" - ], - "summary": "List all S3 sources", - "operationId": "list_s3_sources", - "responses": { - "200": { - "description": "List of S3 sources", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/S3SourceResponse" - } - } - } - } - }, - "401": { - "description": "Unauthorized", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "post": { - "tags": [ - "Backups" - ], - "summary": "Create a new S3 source", - "operationId": "create_s3_source", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateS3SourceRequest" - } - } - }, - "required": true - }, - "responses": { - "201": { - "description": "S3 source created", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/S3SourceResponse" - } - } - } - }, - "400": { - "description": "Invalid request", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "401": { - "description": "Unauthorized", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/backups/s3-sources/test": { - "post": { - "tags": [ - "Backups" - ], - "summary": "Test S3 connectivity against a prospective source configuration (before creating it).\nThe credentials are NOT persisted. Useful for validating the form in the UI.", - "operationId": "test_s3_connection_preview", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateS3SourceRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Connection test result", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/S3ConnectionTestResponse" - } - } - } - }, - "400": { - "description": "Invalid request", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "401": { - "description": "Unauthorized", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/backups/s3-sources/{id}": { - "get": { - "tags": [ - "Backups" - ], - "summary": "Get an S3 source by ID", - "operationId": "get_s3_source", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "S3 source details", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/S3SourceResponse" - } - } - } - }, - "404": { - "description": "S3 source not found", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "delete": { - "tags": [ - "Backups" - ], - "summary": "Delete an S3 source", - "operationId": "delete_s3_source", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "204": { - "description": "S3 source deleted" - }, - "404": { - "description": "S3 source not found", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "patch": { - "tags": [ - "Backups" - ], - "summary": "Update an S3 source", - "operationId": "update_s3_source", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdateS3SourceRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "S3 source updated", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/S3SourceResponse" - } - } - } - }, - "404": { - "description": "S3 source not found", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/backups/s3-sources/{id}/backups": { - "get": { - "tags": [ - "Backups" - ], - "summary": "List all backups in an S3 source", - "operationId": "list_source_backups", - "parameters": [ - { - "name": "include_s3_scan", - "in": "query", - "description": "When `true`, scan the S3 bucket for backups not tracked in the\nlocal database (useful after disaster-recovery from another Temps\ninstance). Defaults to `false` \u2014 the fast DB-only path.", - "required": false, - "schema": { - "type": "boolean" - } - }, - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "List of all backups in the source", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SourceBackupIndexResponse" - } - } - } - }, - "401": { - "description": "Unauthorized", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "404": { - "description": "S3 source not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/backups/s3-sources/{id}/run": { - "post": { - "tags": [ - "Backups" - ], - "summary": "Run a backup immediately for an S3 source.", - "description": "Enqueues the backup for asynchronous execution via the `BackupRunner`\n(ADR-014). Returns `202 Accepted` immediately: a `backups` row is inserted\nwith `state='pending'` and a `backup_jobs` row is enqueued for the\n`ControlPlaneEngine`. Poll `GET /backups/{id}` to observe\n`pending \u2192 running \u2192 completed`.", - "operationId": "run_backup_for_source", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/RunBackupRequest" - } - } - }, - "required": true - }, - "responses": { - "202": { - "description": "Backup enqueued for async execution", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/BackupResponse" - } - } - } - }, - "400": { - "description": "Invalid request", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "404": { - "description": "S3 source not found", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/backups/s3-sources/{id}/set-default": { - "post": { - "tags": [ - "Backups" - ], - "summary": "Mark an S3 source as the default. All new backups/schedules/services that do not\nexplicitly reference a source will use the default. Returns the updated source.", - "operationId": "set_default_s3_source", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "S3 source marked as default", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/S3SourceResponse" - } - } - } - }, - "401": { - "description": "Unauthorized", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "404": { - "description": "S3 source not found", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/backups/s3-sources/{id}/test": { - "post": { - "tags": [ - "Backups" - ], - "summary": "Test connectivity to an existing S3 source using its stored credentials.", - "operationId": "test_s3_source_connection", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Connection test result", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/S3ConnectionTestResponse" - } - } - } - }, - "401": { - "description": "Unauthorized", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "404": { - "description": "S3 source not found", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/backups/schedule-runs/{id}/cancel": { - "post": { - "tags": [ - "Backups" - ], - "summary": "Cancel every non-terminal child backup belonging to a schedule run.", - "description": "Loops over `state IN ('pending','running')` children and flips each via\nthe same path as the per-backup cancel endpoint. The parent\n`schedule_runs.finished_at` is stamped automatically once no live\nchildren remain. Idempotent: cancelling a run with no live children is\na 200 with `cancelled = 0`.", - "operationId": "cancel_schedule_run", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int64" - } - } - ], - "responses": { - "200": { - "description": "Cancel processed (idempotent)", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CancelBackupResponse" - } - } - } - }, - "401": { - "description": "Unauthorized", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "403": { - "description": "Insufficient permissions", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "404": { - "description": "Schedule run not found", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/backups/schedule-runs/{id}/jobs": { - "get": { - "tags": [ - "Backups" - ], - "summary": "List the individual backup jobs for a single scheduler run.", - "description": "Returns each child `backups` row joined with its external service name and\nthe most-recent `backup_jobs` engine key. Used by the schedule detail\naccordion to show per-job detail on row expand.\n\n`page_size` defaults to 50 and is capped at 200.", - "operationId": "list_schedule_run_jobs", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int64" - } - } - ], - "responses": { - "200": { - "description": "Jobs for this scheduler run", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ScheduleRunJobEntry" - } - } - } - } - }, - "401": { - "description": "Unauthorized", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "403": { - "description": "Insufficient permissions", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/backups/schedules": { - "get": { - "tags": [ - "Backups" - ], - "summary": "List all backup schedules", - "operationId": "list_backup_schedules", - "responses": { - "200": { - "description": "List of backup schedules", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/BackupScheduleResponse" - } - } - } - } - }, - "401": { - "description": "Unauthorized", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "post": { - "tags": [ - "Backups" - ], - "summary": "Create a new backup schedule", - "operationId": "create_backup_schedule", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateBackupScheduleRequest" - } - } - }, - "required": true - }, - "responses": { - "201": { - "description": "Backup schedule created", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/BackupScheduleResponse" - } - } - } - }, - "401": { - "description": "Unauthorized", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/backups/schedules/{id}": { - "get": { - "tags": [ - "Backups" - ], - "summary": "Get a backup schedule by ID", - "operationId": "get_backup_schedule", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Backup schedule details", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/BackupScheduleResponse" - } - } - } - }, - "404": { - "description": "Backup schedule not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "delete": { - "tags": [ - "Backups" - ], - "summary": "Delete a backup schedule", - "operationId": "delete_backup_schedule", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "204": { - "description": "Backup schedule deleted" - }, - "404": { - "description": "Backup schedule not found", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "patch": { - "tags": [ - "Backups" - ], - "summary": "Update a backup schedule (partial update).", - "description": "All request fields are optional; only fields that are present in the\nJSON body are updated. Absent fields leave the corresponding column\nunchanged. If `schedule_expression` is changed, `next_run` is\nrecomputed automatically.", - "operationId": "update_backup_schedule", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdateBackupScheduleRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Schedule updated", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/BackupScheduleResponse" - } - } - } - }, - "400": { - "description": "Validation error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "401": { - "description": "Unauthorized", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "404": { - "description": "Schedule not found", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/backups/schedules/{id}/backups": { - "get": { - "tags": [ - "Backups" - ], - "summary": "List backups for a schedule", - "operationId": "list_backups_for_schedule", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "List of backups for the schedule", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/BackupResponse" - } - } - } - } - }, - "404": { - "description": "Backup schedule not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/backups/schedules/{id}/disable": { - "patch": { - "tags": [ - "Backups" - ], - "summary": "Disable a backup schedule", - "operationId": "disable_backup_schedule", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Backup schedule disabled", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/BackupScheduleResponse" - } - } - } - }, - "404": { - "description": "Backup schedule not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/backups/schedules/{id}/enable": { - "patch": { - "tags": [ - "Backups" - ], - "summary": "Enable a backup schedule", - "operationId": "enable_backup_schedule", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Backup schedule enabled", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/BackupScheduleResponse" - } - } - } - }, - "404": { - "description": "Backup schedule not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/backups/schedules/{id}/run": { - "post": { - "tags": [ - "Backups" - ], - "summary": "Immediately fan-out a run for the given schedule (Run Now).", - "description": "Creates one `schedule_runs` row, one control-plane backup job, and one\nbackup job per supported external service \u2014 all in a single transaction.\nReturns `202 Accepted` with a [`ScheduleRunResponse`] containing the new\n`schedule_run_id` and the list of enqueued jobs. Returns `409 Conflict` if\na run for this schedule is already in flight or if the schedule is disabled.", - "operationId": "run_schedule_now", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "202": { - "description": "Fan-out run enqueued for async execution", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ScheduleRunResponse" - } - } - } - }, - "401": { - "description": "Unauthorized", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "403": { - "description": "Insufficient permissions", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "404": { - "description": "Schedule not found", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "409": { - "description": "Run already in flight or schedule disabled", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/backups/schedules/{id}/runs": { - "get": { - "tags": [ - "Backups" - ], - "summary": "Paginated run history for a backup schedule (one row per scheduler tick).", - "description": "Returns one [`ScheduleRunSummary`] per scheduler tick, with child backup\ncounts aggregated in a single SQL round-trip. Legacy `backups` rows (pre-\nfan-out) are surfaced as synthetic single-job runs so history does not\ndisappear. Ordered by `started_at DESC` (newest first).\n\nUse `GET /backups/schedule-runs/{run_id}/jobs` to drill into a single run.", - "operationId": "list_schedule_runs", - "parameters": [ - { - "name": "page", - "in": "query", - "description": "Page number (1-based, defaults to 1, clamped to 1 if < 1).", - "required": false, - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "page_size", - "in": "query", - "description": "Items per page (defaults to 20, clamped to 100 if > 100).", - "required": false, - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Paginated run history for the schedule", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ScheduleRunSummaryList" - } - } - } - }, - "401": { - "description": "Unauthorized", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "403": { - "description": "Insufficient permissions", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "404": { - "description": "Schedule not found", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/backups/schedules/{id}/services": { - "get": { - "tags": [ - "Backups" - ], - "summary": "List the external services attached to a backup schedule.", - "operationId": "list_schedule_services", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "Schedule ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Services attached to this schedule", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ExternalServiceSummary" - } - } - } - } - }, - "401": { - "description": "Unauthorized", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "403": { - "description": "Insufficient permissions", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "404": { - "description": "Schedule not found", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "post": { - "tags": [ - "Backups" - ], - "summary": "Attach one or more external services to a backup schedule. Idempotent \u2014\nservices that are already attached are silently skipped (`ON CONFLICT\nDO NOTHING`). Returns the count of newly inserted rows + the total\nmembership after the operation.", - "operationId": "attach_schedule_services", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "Schedule ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AttachScheduleServicesRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Services attached", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AttachScheduleServicesResponse" - } - } - } - }, - "400": { - "description": "Validation error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "401": { - "description": "Unauthorized", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "403": { - "description": "Insufficient permissions", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "404": { - "description": "Schedule not found", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/backups/schedules/{id}/services/{service_id}": { - "delete": { - "tags": [ - "Backups" - ], - "summary": "Detach a single external service from a backup schedule. Idempotent \u2014\nreturns `204` whether or not a row was actually removed.", - "operationId": "detach_schedule_service", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "Schedule ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "service_id", - "in": "path", - "description": "External service ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "204": { - "description": "Service detached (or was not attached)" - }, - "401": { - "description": "Unauthorized", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "403": { - "description": "Insufficient permissions", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/backups/{id}": { - "get": { - "tags": [ - "Backups" - ], - "summary": "Get a backup by ID", - "operationId": "get_backup", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Backup details", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/BackupResponse" - } - } - } - }, - "401": { - "description": "Unauthorized", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "404": { - "description": "Backup not found", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "delete": { - "tags": [ - "Backups" - ], - "summary": "Permanently delete one terminal backup from object storage and the database.", - "operationId": "delete_backup", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "Backup UUID", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "204": { - "description": "Backup deleted" - }, - "400": { - "description": "Backup artifact cannot be safely attributed", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "401": { - "description": "Unauthorized", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "403": { - "description": "Insufficient permissions", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "404": { - "description": "Backup not found", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "409": { - "description": "Backup is running, referenced, or lacks safe artifact identity", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "500": { - "description": "Object storage or database error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/backups/{id}/cancel": { - "post": { - "tags": [ - "Backups" - ], - "summary": "Cancel a single in-flight backup.", - "description": "Flips the parent `backups` row + its latest `backup_jobs` row to\n`failed` with reason `\"cancelled by user \"`. The in-process\n`CancellationToken` is observed on the next heartbeat tick (\u22645s), so the\nengine exits cleanly and rollback reaps the sidecar. Idempotent: cancelling\nan already-terminal backup is a 200 with `cancelled = 0`.", - "operationId": "cancel_backup", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Cancel processed (idempotent)", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CancelBackupResponse" - } - } - } - }, - "401": { - "description": "Unauthorized", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "403": { - "description": "Insufficient permissions", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "404": { - "description": "Backup not found", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/backups/{id}/children": { - "get": { - "tags": [ - "Backups" - ], - "summary": "List the external-service child backups that belong to a parent backup.", - "description": "Each entry in `children` corresponds to one `external_service_backups` row,\njoined with `external_services` so the caller receives the service name and\ntype without a second request.\n\nReturns an empty `{ \"children\": [] }` \u2014 **not 404** \u2014 when the parent\nbackup exists but has no children (e.g. control-plane backups).\nReturns 404 when the parent backup itself does not exist.", - "operationId": "list_backup_children", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "Integer row id of the parent backup", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Child backup list (may be empty)", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ChildBackupListResponse" - } - } - } - }, - "401": { - "description": "Unauthorized", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "403": { - "description": "Insufficient permissions", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "404": { - "description": "Parent backup not found", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/blob": { - "get": { - "tags": [ - "Blob" - ], - "summary": "List blobs", - "operationId": "blob_list", - "parameters": [ - { - "name": "limit", - "in": "query", - "description": "Maximum number of items to return", - "required": false, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "prefix", - "in": "query", - "description": "Prefix to filter by", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "cursor", - "in": "query", - "description": "Continuation token for pagination", - "required": false, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "List of blobs", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ListBlobsResponse" - } - } - } - }, - "401": { - "description": "Unauthorized", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "post": { - "tags": [ - "Blob" - ], - "summary": "Upload a blob", - "operationId": "blob_put", - "requestBody": { - "description": "Binary blob data", - "content": { - "application/octet-stream": { - "schema": { - "type": "string" - } - } - }, - "required": true - }, - "responses": { - "201": { - "description": "Blob uploaded successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/BlobResponse" - } - } - } - }, - "400": { - "description": "Invalid request", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "401": { - "description": "Unauthorized", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "delete": { - "tags": [ - "Blob" - ], - "summary": "Delete blobs", - "operationId": "blob_delete", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/DeleteBlobRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Blobs deleted successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/DeleteBlobResponse" - } - } - } - }, - "401": { - "description": "Unauthorized", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/blob/copy": { - "post": { - "tags": [ - "Blob" - ], - "summary": "Copy a blob to a new location", - "operationId": "blob_copy", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CopyBlobRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Blob copied successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/BlobResponse" - } - } - } - }, - "400": { - "description": "Invalid request", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "401": { - "description": "Unauthorized", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "404": { - "description": "Source blob not found", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/blob/disable": { - "delete": { - "tags": [ - "Blob Management" - ], - "summary": "Disable Blob service", - "operationId": "blob_disable", - "responses": { - "200": { - "description": "Blob service disabled", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/DisableBlobResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "404": { - "description": "Blob service not enabled" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/blob/enable": { - "post": { - "tags": [ - "Blob Management" - ], - "summary": "Enable Blob service", - "operationId": "blob_enable", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/EnableBlobRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Blob service enabled", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/EnableBlobResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/blob/status": { - "get": { - "tags": [ - "Blob Management" - ], - "summary": "Get Blob service status", - "operationId": "blob_status", - "responses": { - "200": { - "description": "Blob service status", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/BlobStatusResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/blob/update": { - "patch": { - "tags": [ - "Blob Management" - ], - "summary": "Update Blob service configuration", - "operationId": "blob_update", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdateBlobRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Blob service updated", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdateBlobResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "404": { - "description": "Blob service not enabled" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/blob/{project_id}/{path}": { - "get": { - "tags": [ - "Blob" - ], - "summary": "Download a blob", - "operationId": "blob_download", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "path", - "in": "path", - "description": "Blob path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Blob content" - }, - "404": { - "description": "Blob not found", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "head": { - "tags": [ - "Blob" - ], - "summary": "Get blob metadata", - "operationId": "blob_head", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "path", - "in": "path", - "description": "Blob path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Blob metadata in headers" - }, - "404": { - "description": "Blob not found", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/dashboard/projects-analytics": { - "get": { - "tags": [ - "Events" - ], - "summary": "Get dashboard analytics for multiple projects in a single batch request", - "description": "Returns unique visitor counts and hourly sparkline data for all requested projects\nusing only 2 SQL queries instead of 2\u00d7N per-project queries.", - "operationId": "get_dashboard_projects_analytics", - "parameters": [ - { - "name": "project_ids", - "in": "query", - "description": "Comma-separated list of project IDs", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "start_date", - "in": "query", - "description": "Start date for filtering", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "end_date", - "in": "query", - "description": "End date for filtering", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Successfully retrieved batch analytics", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/DashboardProjectsAnalyticsResponse" - } - } - } - }, - "400": { - "description": "Bad request" - }, - "401": { - "description": "Unauthorized" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/deployments/activity-graph": { - "get": { - "tags": [ - "Deployments" - ], - "summary": "Get deployment activity graph showing daily deployment counts\nSimilar to GitHub's contribution graph", - "operationId": "get_activity_graph", - "parameters": [ - { - "name": "project_id", - "in": "query", - "description": "Filter by project ID (optional)", - "required": false, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "environment_id", - "in": "query", - "description": "Filter by environment ID (optional)", - "required": false, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "days", - "in": "query", - "description": "Number of days to include (default: 365)", - "required": false, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Successfully retrieved activity graph", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ActivityGraphResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/deployments/{deployment_id}/vulnerability-scan": { - "get": { - "tags": [ - "Vulnerability Scans" - ], - "operationId": "get_scan_by_deployment", - "parameters": [ - { - "name": "deployment_id", - "in": "path", - "description": "Deployment ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Scan for the specified deployment", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ScanResponse" - } - } - } - }, - "401": { - "description": "Unauthorized", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "403": { - "description": "Insufficient permissions", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "404": { - "description": "No scan found for deployment", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/deployments/{id}/metrics": { - "get": { - "tags": [ - "Metrics" - ], - "summary": "Fetch a time-series range for a single metric on a deployment.", - "operationId": "DeploymentMetricsGetRange", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "Deployment ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "metric", - "in": "query", - "description": "Metric name, e.g. `\"pg.connections_active\"`.", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "range", - "in": "query", - "description": "Time window: `\"1h\"` | `\"6h\"` | `\"24h\"` | `\"7d\"`.", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "percentile", - "in": "query", - "description": "Optional histogram percentile (0\u2013100). When provided, the endpoint\nfetches histogram buckets and computes the requested quantile.", - "required": false, - "schema": { - "type": [ - "number", - "null" - ], - "format": "double" - } - } - ], - "responses": { - "200": { - "description": "Metric time series data points", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/MetricDataPoint" - } - } - } - } - }, - "400": { - "description": "Invalid query parameters" - }, - "401": { - "description": "Unauthorized" - }, - "500": { - "description": "Internal server error" - }, - "503": { - "description": "Metrics store not available" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/deployments/{id}/metrics/enable": { - "patch": { - "tags": [ - "Metrics" - ], - "summary": "Enable or disable OTLP metric ingestion for a deployment.", - "description": "When `enabled=true`, seeds the default container alert rules for the\ndeployment via [`temps_monitoring::seed_default_container_rules`] (idempotent).", - "operationId": "DeploymentMetricsToggle", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "Deployment ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ToggleDeploymentMetricsRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Metrics toggle applied" - }, - "400": { - "description": "Invalid request" - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/deployments/{id}/metrics/latest": { - "get": { - "tags": [ - "Metrics" - ], - "summary": "Fetch the most-recent metric values for a deployment.", - "operationId": "DeploymentMetricsGetLatest", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "Deployment ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Map of metric name to latest value", - "content": { - "application/json": { - "schema": { - "type": "object", - "additionalProperties": { - "type": "number", - "format": "double" - }, - "propertyNames": { - "type": "string" - } - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "500": { - "description": "Internal server error" - }, - "503": { - "description": "Metrics store not available" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/dns-providers": { - "get": { - "tags": [ - "DNS Providers" - ], - "summary": "List all DNS providers", - "operationId": "list_dns_providers", - "responses": { - "200": { - "description": "List of DNS providers", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/DnsProviderResponse" - } - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "post": { - "tags": [ - "DNS Providers" - ], - "summary": "Create a new DNS provider", - "description": "The provider's credentials will be tested before creation.\nIf the connection test fails, the provider will not be created.", - "operationId": "create_dns_provider", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateDnsProviderRequest" - } - } - }, - "required": true - }, - "responses": { - "201": { - "description": "DNS provider created", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/DnsProviderResponse" - } - } - } - }, - "400": { - "description": "Invalid request or connection test failed" - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/dns-providers/{id}": { - "get": { - "tags": [ - "DNS Providers" - ], - "summary": "Get a DNS provider by ID", - "operationId": "get_dns_provider", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "DNS provider details", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/DnsProviderResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "404": { - "description": "Provider not found" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "put": { - "tags": [ - "DNS Providers" - ], - "summary": "Update a DNS provider", - "description": "If new credentials are supplied, they are tested before the update is\npersisted (same as creation) -- otherwise a provider's credentials (and,\nfor Pebble, its target URL) could be swapped for something invalid or\nunsafe without ever going through validation.", - "operationId": "update_provider", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdateDnsProviderRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "DNS provider updated", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/DnsProviderResponse" - } - } - } - }, - "400": { - "description": "Invalid request" - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "404": { - "description": "Provider not found" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "delete": { - "tags": [ - "DNS Providers" - ], - "summary": "Delete a DNS provider", - "operationId": "delete_dns_provider", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "204": { - "description": "DNS provider deleted" - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "404": { - "description": "Provider not found" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/dns-providers/{id}/domains": { - "get": { - "tags": [ - "DNS Providers" - ], - "summary": "List managed domains for a provider", - "operationId": "list_managed_domains", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "List of managed domains", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ManagedDomainResponse" - } - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "404": { - "description": "Provider not found" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "post": { - "tags": [ - "DNS Providers" - ], - "summary": "Add a managed domain to a provider", - "operationId": "add_managed_domain", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AddManagedDomainApiRequest" - } - } - }, - "required": true - }, - "responses": { - "201": { - "description": "Managed domain added", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ManagedDomainResponse" - } - } - } - }, - "400": { - "description": "Invalid request" - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "404": { - "description": "Provider not found" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/dns-providers/{id}/test": { - "post": { - "tags": [ - "DNS Providers" - ], - "summary": "Test provider connection", - "operationId": "test_provider_connection", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Connection test result", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ConnectionTestResult" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "404": { - "description": "Provider not found" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/dns-providers/{id}/zones": { - "get": { - "tags": [ - "DNS Providers" - ], - "summary": "List zones available in a provider", - "operationId": "list_provider_zones", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "List of zones", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ZoneListResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "404": { - "description": "Provider not found" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/dns-providers/{provider_id}/domains/{domain}": { - "delete": { - "tags": [ - "DNS Providers" - ], - "summary": "Remove a managed domain", - "operationId": "remove_managed_domain", - "parameters": [ - { - "name": "provider_id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "domain", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "204": { - "description": "Managed domain removed" - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "404": { - "description": "Domain not found" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "patch": { - "tags": [ - "DNS Providers" - ], - "summary": "Update a managed domain's settings (hostname mode, sync opt-in, auto-manage).", - "operationId": "update_managed_domain", - "parameters": [ - { - "name": "provider_id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "domain", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdateManagedDomainApiRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Managed domain updated", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ManagedDomainResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "404": { - "description": "Domain not found" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/dns-providers/{provider_id}/domains/{domain}/apply-hostname-mode": { - "post": { - "tags": [ - "DNS Providers" - ], - "summary": "Apply a hostname mode to a managed domain (persist + optional DNS sync +\nroute reload).", - "operationId": "apply_hostname_mode", - "parameters": [ - { - "name": "provider_id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "domain", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ApplyHostnameModeRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Hostname mode applied", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HostnamePreviewResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions or token lacks zone access" - }, - "404": { - "description": "Domain not found" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/dns-providers/{provider_id}/domains/{domain}/hostname-preview": { - "get": { - "tags": [ - "DNS Providers" - ], - "summary": "Preview the impact of switching a managed domain's hostname mode.", - "operationId": "preview_hostname_mode", - "parameters": [ - { - "name": "mode", - "in": "query", - "description": "Target mode: standard|flat", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "sync", - "in": "query", - "description": "Include DNS record changes", - "required": false, - "schema": { - "type": "boolean" - } - }, - { - "name": "provider_id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "domain", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Hostname mode preview", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HostnamePreviewResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "404": { - "description": "Domain not found" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/dns-providers/{provider_id}/domains/{domain}/verify": { - "post": { - "tags": [ - "DNS Providers" - ], - "summary": "Verify a managed domain", - "operationId": "verify_managed_domain", - "parameters": [ - { - "name": "provider_id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "domain", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Domain verification result", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ManagedDomainResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "404": { - "description": "Domain not found" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/dns/lookup": { - "get": { - "tags": [ - "DNS" - ], - "summary": "Lookup DNS A records for a domain", - "operationId": "lookup_dns_a_records", - "parameters": [ - { - "name": "domain", - "in": "query", - "description": "Domain name to lookup", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Successfully retrieved DNS A records", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/DnsLookupResponse" - } - } - } - }, - "400": { - "description": "Invalid domain name or lookup failed", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/DnsLookupError" - } - } - } - } - } - } - }, - "/domains": { - "get": { - "tags": [ - "Domains" - ], - "summary": "List all domains", - "operationId": "list_domains", - "parameters": [ - { - "name": "page", - "in": "query", - "description": "Page number (1-indexed)", - "required": false, - "schema": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "minimum": 0 - }, - "example": 1 - }, - { - "name": "page_size", - "in": "query", - "description": "Number of items per page (max 100)", - "required": false, - "schema": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "minimum": 0 - }, - "example": 20 - }, - { - "name": "search", - "in": "query", - "description": "Search domains by name (substring match)", - "required": false, - "schema": { - "type": [ - "string", - "null" - ] - }, - "example": "example.com" - } - ], - "responses": { - "200": { - "description": "Domains retrieved successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ListDomainsResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "post": { - "tags": [ - "Domains" - ], - "summary": "Create a new domain", - "description": "Creates a new domain and automatically requests a Let's Encrypt challenge.\nYou can specify the challenge type (HTTP-01 or DNS-01) in the request.\n\n- **HTTP-01**: Validates domain ownership by placing a file on your web server at `/.well-known/acme-challenge/`\n- **DNS-01**: Validates domain ownership by adding a TXT record to your DNS (required for wildcard domains)", - "operationId": "create_domain", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateDomainRequest" - } - } - }, - "required": true - }, - "responses": { - "201": { - "description": "Domain created successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/DomainResponse" - } - } - } - }, - "400": { - "description": "Invalid input" - }, - "401": { - "description": "Unauthorized" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/domains/by-host/{hostname}": { - "get": { - "tags": [ - "Domains" - ], - "summary": "Get domain details by hostname", - "operationId": "get_domain_by_host", - "parameters": [ - { - "name": "hostname", - "in": "path", - "description": "Domain hostname", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Domain details retrieved successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/DomainResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "404": { - "description": "Domain not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/domains/by-host/{hostname}/cert-status": { - "get": { - "tags": [ - "Domains" - ], - "summary": "Get on-demand TLS certificate status for a hostname", - "description": "Returns the current cert lifecycle state for a single hostname (from the\n`domains` row) plus the most recent on-demand issuance attempt (from the\n`on_demand_cert_attempts` audit log). This is the operator's first-line\ndiagnostic, surfaced by `temps domain cert-status` (ADR-018 \u00a75). Returns the\nhostname with `None` fields when no on-demand activity exists for it (never a\n404, so the CLI can render \"no attempts recorded\").", - "operationId": "get_on_demand_cert_status", - "parameters": [ - { - "name": "hostname", - "in": "path", - "description": "Domain hostname", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "On-demand cert status retrieved successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CertStatusResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/domains/on-demand-certs": { - "get": { - "tags": [ - "Domains" - ], - "summary": "List on-demand TLS certificate attempts", - "description": "Returns rows from the append-only `on_demand_cert_attempts` audit log\n(ADR-018 \u00a75), newest first, each joined with the current authoritative cert\nstate (`status`, `expiration_time`, `backoff_until`) from the `domains` row.\nThis backs the console \"Certificates\" surface. No certificate or private-key\nmaterial is returned \u2014 only audit metadata.", - "operationId": "list_on_demand_certs", - "parameters": [ - { - "name": "page", - "in": "query", - "description": "Page number (1-indexed)", - "required": false, - "schema": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "minimum": 0 - }, - "example": 1 - }, - { - "name": "page_size", - "in": "query", - "description": "Number of items per page (max 100)", - "required": false, - "schema": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "minimum": 0 - }, - "example": 20 - } - ], - "responses": { - "200": { - "description": "On-demand cert attempts retrieved successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ListOnDemandCertsResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/domains/{domain_id}/order": { - "get": { - "tags": [ - "Domains" - ], - "summary": "Get ACME order for a domain", - "operationId": "get_domain_order", - "parameters": [ - { - "name": "domain_id", - "in": "path", - "description": "Domain ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Order retrieved successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AcmeOrderResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "404": { - "description": "Order not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "post": { - "tags": [ - "Domains" - ], - "summary": "Create or recreate ACME order for a domain", - "description": "Creates a new ACME order with Let's Encrypt for the specified domain.\nIf an order already exists, you should cancel it first using the cancel-order endpoint.\nReturns the challenge details that need to be fulfilled (DNS record or HTTP token).", - "operationId": "create_or_recreate_order", - "parameters": [ - { - "name": "domain_id", - "in": "path", - "description": "Domain ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Order created successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/DomainChallengeResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "404": { - "description": "Domain not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "delete": { - "tags": [ - "Domains" - ], - "summary": "Cancel ACME order for a domain", - "description": "Cancels the current ACME order for a domain and clears all challenge data.\nThis allows you to start over with a new order if the previous one failed or got stuck.", - "operationId": "cancel_domain_order", - "parameters": [ - { - "name": "domain_id", - "in": "path", - "description": "Domain ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Order cancelled successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/DomainResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "404": { - "description": "Domain not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/domains/{domain_id}/order/finalize": { - "post": { - "tags": [ - "Domains" - ], - "summary": "Finalize ACME order for a domain", - "description": "Finalizes the ACME order by completing the challenge validation and requesting the certificate.\nThis should be called after the challenge has been set up (DNS record added or HTTP token served).", - "operationId": "finalize_order", - "parameters": [ - { - "name": "domain_id", - "in": "path", - "description": "Domain ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Order finalized successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/DomainResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "404": { - "description": "Domain or order not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/domains/{domain_id}/setup-dns": { - "post": { - "tags": [ - "Domains" - ], - "summary": "Setup DNS challenge records automatically using a DNS provider", - "description": "This endpoint automatically creates the required DNS TXT records for ACME DNS-01 challenge\nvalidation using a configured DNS provider. The domain must have an active DNS challenge\npending (created via POST /domains/{id}/order with dns-01 challenge type).\n\nThis is similar to how email domain DNS records are auto-provisioned.", - "operationId": "setup_dns_challenge", - "parameters": [ - { - "name": "domain_id", - "in": "path", - "description": "Domain ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SetupDnsChallengeRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "DNS records created successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SetupDnsChallengeResponse" - } - } - } - }, - "400": { - "description": "Bad request - DNS provider not configured or no challenge pending" - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "404": { - "description": "Domain or DNS provider not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/domains/{domain}": { - "get": { - "tags": [ - "Domains" - ], - "summary": "Get domain by ID", - "operationId": "get_domain_by_id", - "parameters": [ - { - "name": "domain", - "in": "path", - "description": "Domain ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Domain retrieved successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/DomainResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "404": { - "description": "Domain not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "delete": { - "tags": [ - "Domains" - ], - "summary": "Delete a domain", - "operationId": "delete_domain", - "parameters": [ - { - "name": "domain", - "in": "path", - "description": "Domain name", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "204": { - "description": "Domain deleted successfully" - }, - "401": { - "description": "Unauthorized" - }, - "404": { - "description": "Domain not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/domains/{domain}/challenge-token": { - "get": { - "tags": [ - "Domains" - ], - "summary": "Get challenge token for a domain (returns plain text token)", - "operationId": "get_challenge_token", - "parameters": [ - { - "name": "domain", - "in": "path", - "description": "Domain name", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Challenge token retrieved successfully", - "content": { - "text/plain": { - "schema": { - "type": "string" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "404": { - "description": "Challenge not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/domains/{domain}/http-challenge-debug": { - "get": { - "tags": [ - "Domains" - ], - "summary": "Get HTTP challenge debug information", - "description": "Returns detailed debug information for HTTP-01 challenge including:\n- Whether a challenge exists for the domain\n- The challenge token and URL that Let's Encrypt will access\n- DNS resolution information showing where the domain currently points\n\nThis is useful for debugging why HTTP-01 challenges fail.", - "operationId": "get_http_challenge_debug", - "parameters": [ - { - "name": "domain", - "in": "path", - "description": "Domain name", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Debug information retrieved successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HttpChallengeDebugResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/domains/{domain}/provision": { - "post": { - "tags": [ - "Domains" - ], - "summary": "Provision a domain certificate", - "operationId": "provision_domain", - "parameters": [ - { - "name": "domain", - "in": "path", - "description": "Domain name", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Certificate provisioning initiated", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProvisionResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "404": { - "description": "Domain not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/domains/{domain}/renew": { - "post": { - "tags": [ - "Domains" - ], - "summary": "Renew domain certificate", - "description": "For HTTP-01 domains: Automatically renews the certificate\nFor DNS-01 domains (wildcards): Creates a new ACME order and returns challenge data", - "operationId": "renew_domain", - "parameters": [ - { - "name": "domain", - "in": "path", - "description": "Domain name", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Certificate renewal initiated", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProvisionResponse" - } - } - } - }, - "202": { - "description": "DNS challenge created - manual action required", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/DomainChallengeResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "404": { - "description": "Domain not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/domains/{domain}/status": { - "get": { - "tags": [ - "Domains" - ], - "summary": "Check domain status", - "operationId": "check_domain_status", - "parameters": [ - { - "name": "domain", - "in": "path", - "description": "Domain ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Domain status retrieved successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/DomainResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "404": { - "description": "Domain not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/email-domains": { - "get": { - "tags": [ - "Email Domains" - ], - "summary": "List all email domains", - "operationId": "list_email_domains", - "parameters": [ - { - "name": "provider_id", - "in": "query", - "description": "Only return domains belonging to this provider", - "required": false, - "schema": { - "type": [ - "integer", - "null" - ], - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "List of email domains", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/EmailDomainResponse" - } - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "post": { - "tags": [ - "Email Domains" - ], - "summary": "Create a new email domain", - "operationId": "create_email_domain", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateEmailDomainRequest" - } - } - }, - "required": true - }, - "responses": { - "201": { - "description": "Domain created successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/EmailDomainWithDnsResponse" - } - } - } - }, - "400": { - "description": "Invalid request" - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/email-domains/by-domain/{domain}": { - "get": { - "tags": [ - "Email Domains" - ], - "summary": "Get an email domain by domain name with DNS records", - "operationId": "get_domain_by_name", - "parameters": [ - { - "name": "domain", - "in": "path", - "description": "Domain name (e.g., 'mail.example.com')", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Email domain details with DNS records", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/EmailDomainWithDnsResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "404": { - "description": "Domain not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/email-domains/{id}": { - "get": { - "tags": [ - "Email Domains" - ], - "summary": "Get an email domain by ID with DNS records", - "operationId": "get_domain", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "Domain ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Email domain details with DNS records", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/EmailDomainWithDnsResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "404": { - "description": "Domain not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "delete": { - "tags": [ - "Email Domains" - ], - "summary": "Delete an email domain", - "operationId": "delete_email_domain", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "Domain ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "204": { - "description": "Domain deleted" - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "404": { - "description": "Domain not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/email-domains/{id}/dns-records": { - "get": { - "tags": [ - "Email Domains" - ], - "summary": "Get DNS records for an email domain", - "operationId": "get_domain_dns_records", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "Domain ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "DNS records for the domain", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/DnsRecordResponse" - } - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "404": { - "description": "Domain not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/email-domains/{id}/setup-dns": { - "post": { - "tags": [ - "Email Domains" - ], - "summary": "Setup DNS records for an email domain using a configured DNS provider", - "operationId": "setup_dns", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "Email Domain ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SetupDnsRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "DNS records setup result", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SetupDnsResponse" - } - } - } - }, - "400": { - "description": "Invalid request or DNS provider not configured" - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "404": { - "description": "Domain not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/email-domains/{id}/verify": { - "post": { - "tags": [ - "Email Domains" - ], - "summary": "Verify an email domain's DNS configuration", - "operationId": "verify_domain", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "Domain ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Domain verification result with DNS records", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/EmailDomainWithDnsResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "404": { - "description": "Domain not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/email-providers": { - "get": { - "tags": [ - "Email Providers" - ], - "summary": "List all email providers", - "operationId": "list_email_providers", - "responses": { - "200": { - "description": "List of email providers", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/EmailProviderResponse" - } - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "post": { - "tags": [ - "Email Providers" - ], - "summary": "Create a new email provider", - "operationId": "create_email_provider", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateEmailProviderRequest" - } - } - }, - "required": true - }, - "responses": { - "201": { - "description": "Provider created successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/EmailProviderResponse" - } - } - } - }, - "400": { - "description": "Invalid request" - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/email-providers/{id}": { - "get": { - "tags": [ - "Email Providers" - ], - "summary": "Get an email provider by ID", - "operationId": "get_email_provider", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "Provider ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Email provider details", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/EmailProviderResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "404": { - "description": "Provider not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "delete": { - "tags": [ - "Email Providers" - ], - "summary": "Delete an email provider", - "operationId": "delete_email_provider", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "Provider ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "204": { - "description": "Provider deleted" - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "404": { - "description": "Provider not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "patch": { - "tags": [ - "Email Providers" - ], - "summary": "Update an email provider", - "description": "Partial update \u2014 any field left out keeps its current value. Most importantly,\nomitting the credential block (`ses_credentials`/`scaleway_credentials`/`smtp_credentials`)\npreserves the stored secret, so operators can rename a provider without re-typing\npasswords. `provider_type` is immutable; to switch providers, delete and recreate.", - "operationId": "update_email_provider", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "Provider ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdateEmailProviderRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Provider updated", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/EmailProviderResponse" - } - } - } - }, - "400": { - "description": "Validation error" - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "404": { - "description": "Provider not found" - }, - "409": { - "description": "Provider type mismatch" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/email-providers/{id}/test": { - "post": { - "tags": [ - "Email Providers" - ], - "summary": "Test an email provider by sending a test email to the logged-in user", - "operationId": "test_provider", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "Provider ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/TestEmailRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Test email result", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/TestEmailResponse" - } - } - } - }, - "400": { - "description": "Invalid request" - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "404": { - "description": "Provider not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/email-providers/{id}/tracking/setup": { - "post": { - "tags": [ - "Email Providers" - ], - "summary": "One-click AWS-side setup of SES event tracking (SNS topic + webhook\nsubscription + SESv2 event destination), using the provider's stored\ncredentials.", - "operationId": "setup_email_tracking", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "Provider ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Setup completed", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/EmailTrackingSetupResponse" - } - } - } - }, - "400": { - "description": "Provider does not support event tracking" - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "404": { - "description": "Provider not found" - }, - "502": { - "description": "An AWS call failed \u2014 the response detail names the failed step" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/email-providers/{id}/tracking/status": { - "get": { - "tags": [ - "Email Providers" - ], - "summary": "Live status of SES event tracking for a provider", - "operationId": "get_email_tracking_status", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "Provider ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Event tracking status", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/EmailTrackingStatusResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "404": { - "description": "Provider not found" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/emails": { - "get": { - "tags": [ - "Emails" - ], - "summary": "List emails with optional filtering", - "operationId": "list_emails", - "parameters": [ - { - "name": "domain_id", - "in": "query", - "required": false, - "schema": { - "type": [ - "integer", - "null" - ], - "format": "int32" - } - }, - { - "name": "project_id", - "in": "query", - "required": false, - "schema": { - "type": [ - "integer", - "null" - ], - "format": "int32" - } - }, - { - "name": "status", - "in": "query", - "required": false, - "schema": { - "type": [ - "string", - "null" - ] - } - }, - { - "name": "from_address", - "in": "query", - "required": false, - "schema": { - "type": [ - "string", - "null" - ] - } - }, - { - "name": "page", - "in": "query", - "required": false, - "schema": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "minimum": 0 - } - }, - { - "name": "page_size", - "in": "query", - "required": false, - "schema": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "minimum": 0 - } - } - ], - "responses": { - "200": { - "description": "List of emails", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/PaginatedEmailsResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "post": { - "tags": [ - "Emails" - ], - "summary": "Send an email", - "operationId": "send_email", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SendEmailRequestBody" - } - } - }, - "required": true - }, - "responses": { - "201": { - "description": "Email sent successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SendEmailResponseBody" - } - } - } - }, - "400": { - "description": "Invalid request or domain not verified" - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/emails/events": { - "get": { - "tags": [ - "Email Tracking" - ], - "summary": "GET /emails/events", - "operationId": "get_global_events", - "parameters": [ - { - "name": "event_type", - "in": "query", - "description": "Filter by event type (open, click)", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "page", - "in": "query", - "description": "Page number (default: 1)", - "required": false, - "schema": { - "type": "integer", - "format": "int64", - "minimum": 0 - } - }, - { - "name": "page_size", - "in": "query", - "description": "Page size (default: 20, max: 100)", - "required": false, - "schema": { - "type": "integer", - "format": "int64", - "minimum": 0 - } - } - ], - "responses": { - "200": { - "description": "Paginated tracking events", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/PaginatedEventsResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/emails/events/stats": { - "get": { - "tags": [ - "Email Tracking" - ], - "summary": "GET /emails/events/stats", - "operationId": "get_global_event_stats", - "responses": { - "200": { - "description": "Global tracking statistics", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/GlobalEventStatsResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/emails/stats": { - "get": { - "tags": [ - "Emails" - ], - "summary": "Get email statistics", - "operationId": "get_email_stats", - "parameters": [ - { - "name": "domain_id", - "in": "query", - "description": "Optional domain ID to filter stats", - "required": false, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Email statistics", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/EmailStatsResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/emails/validate": { - "post": { - "tags": [ - "Email Validation" - ], - "summary": "Validate an email address", - "operationId": "validate_email", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ValidateEmailRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Email validation result", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ValidateEmailResponse" - } - } - } - }, - "400": { - "description": "Invalid request" - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/emails/{email_id}/track/click/{link_index}": { - "get": { - "tags": [ - "Email Tracking" - ], - "summary": "Track email link click - redirects to original URL", - "description": "This endpoint replaces original links in tracked emails.\nNo authentication required - it's called when the recipient clicks a link.", - "operationId": "track_click", - "parameters": [ - { - "name": "email_id", - "in": "path", - "description": "Email ID (UUID)", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "link_index", - "in": "path", - "description": "Link index", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "302": { - "description": "Redirect to original URL" - }, - "404": { - "description": "Link not found" - } - } - } - }, - "/emails/{email_id}/track/open": { - "get": { - "tags": [ - "Email Tracking" - ], - "summary": "Track email open - returns a 1x1 transparent GIF", - "description": "This endpoint is embedded as an tag in emails.\nNo authentication required - it's called by the email client.", - "operationId": "track_open", - "parameters": [ - { - "name": "email_id", - "in": "path", - "description": "Email ID (UUID)", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "1x1 transparent tracking pixel" - }, - "404": { - "description": "Email not found" - } - } - } - }, - "/emails/{id}": { - "get": { - "tags": [ - "Emails" - ], - "summary": "Get an email by ID", - "operationId": "get_email", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "Email ID (UUID)", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Email details", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/EmailResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "404": { - "description": "Email not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/emails/{id}/tracking": { - "get": { - "tags": [ - "Email Tracking" - ], - "summary": "Get email tracking summary", - "operationId": "get_email_tracking", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "Email ID (UUID)", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Tracking summary", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/EmailTrackingResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "404": { - "description": "Email not found" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/emails/{id}/tracking/events": { - "get": { - "tags": [ - "Email Tracking" - ], - "summary": "Get email tracking events", - "operationId": "get_email_events", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "Email ID (UUID)", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "event_type", - "in": "query", - "description": "Filter by event type (open, click)", - "required": false, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Tracking events", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/TrackingEventResponse" - } - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "404": { - "description": "Email not found" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/emails/{id}/tracking/links": { - "get": { - "tags": [ - "Email Tracking" - ], - "summary": "Get tracked links for an email", - "operationId": "get_email_links", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "Email ID (UUID)", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Tracked links", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/TrackedLinkResponse" - } - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "404": { - "description": "Email not found" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/external-services": { - "get": { - "tags": [ - "External Services" - ], - "summary": "Get all external services", - "operationId": "list_services", - "parameters": [ - { - "name": "page", - "in": "query", - "description": "Page number (1-indexed)", - "required": false, - "schema": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "minimum": 0 - }, - "example": 1 - }, - { - "name": "page_size", - "in": "query", - "description": "Number of items per page (max 100)", - "required": false, - "schema": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "minimum": 0 - }, - "example": 20 - }, - { - "name": "sort_by", - "in": "query", - "required": false, - "schema": { - "type": [ - "string", - "null" - ] - } - }, - { - "name": "sort_order", - "in": "query", - "required": false, - "schema": { - "type": [ - "string", - "null" - ] - } - } - ], - "responses": { - "200": { - "description": "List of external services", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ExternalServiceInfo" - } - } - } - } - }, - "500": { - "description": "Internal server error" - } - } - }, - "post": { - "tags": [ - "External Services" - ], - "summary": "Create new external service", - "operationId": "create_service", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateExternalServiceRequest" - } - } - }, - "required": true - }, - "responses": { - "201": { - "description": "Service created successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ExternalServiceInfo" - } - } - } - }, - "400": { - "description": "Invalid request" - }, - "500": { - "description": "Internal server error" - } - } - } - }, - "/external-services/available-containers": { - "get": { - "tags": [ - "External Services" - ], - "summary": "List available Docker containers that can be imported as services", - "operationId": "list_available_containers", - "responses": { - "200": { - "description": "List of available containers", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/AvailableContainerInfo" - } - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/external-services/by-slug/{slug}": { - "get": { - "tags": [ - "External Services" - ], - "summary": "Get external service details by slug", - "operationId": "get_service_by_slug", - "parameters": [ - { - "name": "slug", - "in": "path", - "description": "External service slug", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "External service details", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ExternalServiceDetails" - } - } - } - }, - "404": { - "description": "Service not found" - }, - "500": { - "description": "Internal server error" - } - } - } - }, - "/external-services/health-status-batch": { - "get": { - "tags": [ - "External Services" - ], - "summary": "Current health status for many services at once", - "description": "Powers the status dot on the Storage list page. Pass a comma-separated\nlist of service IDs via `?ids=1,2,3`. Omit to get every service.", - "operationId": "list_service_health_statuses", - "parameters": [ - { - "name": "ids", - "in": "query", - "description": "Comma-separated service IDs. Omit for all services.", - "required": false, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Batch of current health statuses", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ServiceHealthStatusBatchResponse" - } - } - } - }, - "500": { - "description": "Internal server error" - } - } - } - }, - "/external-services/import": { - "post": { - "tags": [ - "External Services" - ], - "summary": "Import an existing Docker container as a managed external service", - "operationId": "import_external_service", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ImportExternalServiceRequest" - } - } - }, - "required": true - }, - "responses": { - "201": { - "description": "Service imported successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ExternalServiceInfo" - } - } - } - }, - "400": { - "description": "Invalid request" - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/external-services/projects/{project_id}": { - "get": { - "tags": [ - "External Services" - ], - "summary": "List services linked to a project", - "operationId": "list_project_services", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "page", - "in": "query", - "description": "Page number (1-indexed)", - "required": false, - "schema": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "minimum": 0 - }, - "example": 1 - }, - { - "name": "page_size", - "in": "query", - "description": "Number of items per page (max 100)", - "required": false, - "schema": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "minimum": 0 - }, - "example": 20 - }, - { - "name": "sort_by", - "in": "query", - "required": false, - "schema": { - "type": [ - "string", - "null" - ] - } - }, - { - "name": "sort_order", - "in": "query", - "required": false, - "schema": { - "type": [ - "string", - "null" - ] - } - } - ], - "responses": { - "200": { - "description": "List of services linked to project", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ProjectServiceInfo" - } - } - } - } - }, - "404": { - "description": "Project not found" - }, - "500": { - "description": "Internal server error" - } - } - } - }, - "/external-services/projects/{project_id}/environment": { - "get": { - "tags": [ - "External Services" - ], - "summary": "Get all environment variables for all services linked to a project", - "operationId": "get_project_service_environment_variables", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Map of service IDs to their environment variables", - "content": { - "application/json": { - "schema": { - "type": "object", - "additionalProperties": { - "type": "object", - "additionalProperties": { - "type": "string" - }, - "propertyNames": { - "type": "string" - } - }, - "propertyNames": { - "type": "integer", - "format": "int32" - } - } - } - } - }, - "404": { - "description": "Project not found" - }, - "500": { - "description": "Internal server error" - } - } - } - }, - "/external-services/providers/metadata": { - "get": { - "tags": [ - "External Services" - ], - "summary": "Get provider metadata (display names, icons, descriptions)", - "operationId": "get_providers_metadata", - "responses": { - "200": { - "description": "List of provider metadata", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ProviderMetadata" - } - } - } - } - }, - "500": { - "description": "Internal server error" - } - } - } - }, - "/external-services/providers/metadata/{service_type}": { - "get": { - "tags": [ - "External Services" - ], - "summary": "Get metadata for a specific provider", - "operationId": "get_provider_metadata", - "parameters": [ - { - "name": "service_type", - "in": "path", - "description": "Service type (mongodb, postgres, redis, s3)", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Provider metadata", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProviderMetadata" - } - } - } - }, - "404": { - "description": "Provider not found" - }, - "500": { - "description": "Internal server error" - } - } - } - }, - "/external-services/types": { - "get": { - "tags": [ - "External Services" - ], - "summary": "Get available service types", - "operationId": "get_service_types", - "responses": { - "200": { - "description": "List of available service types", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ServiceTypeRoute" - } - } - } - } - }, - "500": { - "description": "Internal server error" - } - } - } - }, - "/external-services/types/{service_type}/parameters": { - "get": { - "tags": [ - "External Services" - ], - "summary": "Get parameter schema for a specific service type", - "operationId": "get_service_type_parameters", - "parameters": [ - { - "name": "service_type", - "in": "path", - "description": "Service type", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Service type parameter schema" - }, - "404": { - "description": "Service type not found" - }, - "500": { - "description": "Internal server error" - } - } - } - }, - "/external-services/{id}": { - "get": { - "tags": [ - "External Services" - ], - "summary": "Get external service details", - "operationId": "get_service", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "External service ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "External service details", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ExternalServiceDetails" - } - } - } - }, - "404": { - "description": "Service not found" - }, - "500": { - "description": "Internal server error" - } - } - }, - "put": { - "tags": [ - "External Services" - ], - "summary": "Update external service", - "operationId": "update_service", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "External service ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdateExternalServiceRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Service updated successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ExternalServiceInfo" - } - } - } - }, - "400": { - "description": "Invalid request" - }, - "404": { - "description": "Service not found" - }, - "409": { - "description": "A major upgrade is in progress for this service" - }, - "500": { - "description": "Internal server error" - } - } - }, - "delete": { - "tags": [ - "External Services" - ], - "summary": "Delete external service", - "operationId": "delete_service", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "External service ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "204": { - "description": "Service deleted successfully" - }, - "400": { - "description": "Cannot delete: service is still linked to projects" - }, - "404": { - "description": "Service not found" - }, - "500": { - "description": "Internal server error" - } - } - } - }, - "/external-services/{id}/cluster-health": { - "get": { - "tags": [ - "External Services" - ], - "summary": "Per-member health for a Postgres HA cluster.", - "description": "Reads pg_auto_failover's `pgautofailover.node` table from the cluster's\nmonitor (TLS, autoctl_node) and joins each member with its\n`pg_stat_replication` row from the current primary. Returns one row per\ndata member with role/state, sync state, and replay lag.\n\nReturns `200` with `monitor_error` set when the monitor is briefly\nunreachable (UI surfaces it as a banner above the table); the table\nitself is empty in that case. Returns `400` for non-cluster services.", - "operationId": "get_cluster_health", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "External service ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Per-member cluster health report", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ClusterHealthReportResponse" - } - } - } - }, - "400": { - "description": "Service is not a cluster" - }, - "401": { - "description": "Unauthorized" - }, - "404": { - "description": "Service not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/external-services/{id}/health-check": { - "post": { - "tags": [ - "External Services" - ], - "summary": "Run a health check for one service right now", - "description": "Triggers the same engine-specific probe as the background monitor, writes\na history row, updates the denormalized fields on `external_services`, and\nfires alerts on the Nth consecutive failure (so consecutive-failure state\nstays honest). Returns the fresh snapshot the UI can display immediately.", - "operationId": "trigger_service_health_check", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "External service ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Fresh health snapshot after probing", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ServiceHealthResponse" - } - } - } - }, - "404": { - "description": "Service not found" - }, - "500": { - "description": "Internal server error" - }, - "503": { - "description": "Health monitor not running on this node" - } - } - } - }, - "/external-services/{id}/health-status": { - "get": { - "tags": [ - "External Services" - ], - "summary": "Persisted health status for an external service", - "description": "Returns the latest health probe result recorded by\n`ExternalServiceHealthMonitor`, plus recent check history for sparklines\nand a 24-hour uptime percentage. Safe to poll from the UI every 30s.", - "operationId": "get_service_health_status", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "External service ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "limit", - "in": "query", - "description": "Max number of recent checks (default 50, max 200)", - "required": false, - "schema": { - "type": "integer", - "format": "int64", - "minimum": 0 - } - } - ], - "responses": { - "200": { - "description": "Current health + recent history", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ServiceHealthResponse" - } - } - } - }, - "404": { - "description": "Service not found" - }, - "500": { - "description": "Internal server error" - } - } - } - }, - "/external-services/{id}/members": { - "post": { - "tags": [ - "External Services" - ], - "summary": "Begin adding a single new member to a running cluster.", - "description": "Currently only `replica` members can be added at runtime. The\nresponse is **202 Accepted** as soon as the validation passes and\nthe placeholder `service_members` row is inserted. The actual\ncontainer provisioning + DNS registration runs in the background;\npoll `GET /external-services/{id}/members/{member_id}` to watch\n`provisioning_step` advance through the phases.", - "operationId": "add_cluster_member", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "External service ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AddClusterMemberRequest" - } - } - }, - "required": true - }, - "responses": { - "202": { - "description": "Cluster member provisioning started", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ServiceMemberInfo" - } - } - } - }, - "400": { - "description": "Validation failed (wrong topology, status, or role)" - }, - "404": { - "description": "Service not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/external-services/{id}/members/{member_id}": { - "get": { - "tags": [ - "External Services" - ], - "summary": "Get a single cluster member's current state.", - "description": "Used by the add-member page to poll the row every second while the\nbackground provisioning task walks through its phases. The\n`provisioning_step` field advances through `inserting_row` \u2192\n`provisioning_container` \u2192 `registering_dns` \u2192 `done` (or `failed`\nwith `provisioning_error` set).", - "operationId": "get_cluster_member", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "External service ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "member_id", - "in": "path", - "description": "Cluster member ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Cluster member details", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ServiceMemberInfo" - } - } - } - }, - "404": { - "description": "Service or member not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "delete": { - "tags": [ - "External Services" - ], - "summary": "Remove a single member from a running cluster.", - "description": "Refuses to remove the monitor (singleton), the current primary\n(failover first), or any member if the cluster would drop below the\n2-data-member quorum required for HA. Stops + removes the container,\ndeletes the row, and drops the Tier-2 DNS record.", - "operationId": "remove_cluster_member", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "External service ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "member_id", - "in": "path", - "description": "Cluster member ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "204": { - "description": "Cluster member removed" - }, - "400": { - "description": "Validation failed (monitor, primary, or quorum violation)" - }, - "404": { - "description": "Service or member not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/external-services/{id}/members/{member_id}/promote": { - "post": { - "tags": [ - "External Services" - ], - "summary": "Promote a replica to primary by triggering a pg_auto_failover\nfailover. The monitor demotes the current primary and the chosen\nreplica transitions to primary; the role reconciler then refreshes\nthe role-aliased VIPs (\u226430s).", - "operationId": "promote_cluster_member", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "External service ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "member_id", - "in": "path", - "description": "Cluster member ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "202": { - "description": "Promotion initiated" - }, - "400": { - "description": "Validation failed (monitor, already primary, not running, etc.)" - }, - "404": { - "description": "Service or member not found" - }, - "500": { - "description": "pg_autoctl perform promotion failed" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/external-services/{id}/metrics": { - "get": { - "tags": [ - "Metrics" - ], - "summary": "Fetch a time-series range for a single metric on an external service.", - "description": "Pass `percentile` to compute a histogram quantile instead of a plain\ngauge/counter average.", - "operationId": "ExternalServiceMetricsGetRange", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "External service ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "metric", - "in": "query", - "description": "Metric name, e.g. `\"pg.connections_active\"`.", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "range", - "in": "query", - "description": "Time window: `\"1h\"` | `\"6h\"` | `\"24h\"` | `\"7d\"`.", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "percentile", - "in": "query", - "description": "Optional histogram percentile (0\u2013100). When provided, the endpoint\nfetches histogram buckets and computes the requested quantile.", - "required": false, - "schema": { - "type": [ - "number", - "null" - ], - "format": "double" - } - } - ], - "responses": { - "200": { - "description": "Metric time series data points", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/MetricDataPoint" - } - } - } - } - }, - "400": { - "description": "Invalid query parameters" - }, - "401": { - "description": "Unauthorized" - }, - "500": { - "description": "Internal server error" - }, - "503": { - "description": "Metrics store not available" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/external-services/{id}/metrics/alert-rules": { - "get": { - "tags": [ - "Metrics" - ], - "summary": "List all monitoring alert rules for an external service.", - "operationId": "ExternalServiceMetricsGetAlertRules", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "External service ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "List of alert rules", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ServiceAlertRuleResponse" - } - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "post": { - "tags": [ - "Metrics" - ], - "summary": "Create a monitoring alert rule for an external service.", - "description": "If metric collection is enabled and the service engine has default rules,\nseeding is idempotent (ON CONFLICT DO NOTHING).", - "operationId": "ExternalServiceMetricsCreateAlertRule", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "External service ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ServiceCreateAlertRuleRequest" - } - } - }, - "required": true - }, - "responses": { - "201": { - "description": "Alert rule created", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ServiceAlertRuleResponse" - } - } - } - }, - "400": { - "description": "Invalid request" - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/external-services/{id}/metrics/alert-rules/{rule_id}": { - "put": { - "tags": [ - "Metrics" - ], - "summary": "Update an existing monitoring alert rule for an external service.", - "operationId": "ExternalServiceMetricsUpdateAlertRule", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "External service ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "rule_id", - "in": "path", - "description": "Alert rule ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ServiceUpdateAlertRuleRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Updated alert rule", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ServiceAlertRuleResponse" - } - } - } - }, - "400": { - "description": "Invalid request" - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "404": { - "description": "Alert rule not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "delete": { - "tags": [ - "Metrics" - ], - "summary": "Delete a monitoring alert rule for an external service.", - "operationId": "ExternalServiceMetricsDeleteAlertRule", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "External service ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "rule_id", - "in": "path", - "description": "Alert rule ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "204": { - "description": "Alert rule deleted" - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "404": { - "description": "Alert rule not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/external-services/{id}/metrics/by-database": { - "get": { - "tags": [ - "Metrics" - ], - "summary": "Return the latest per-database metric values for a Postgres service.", - "description": "Groups `pg_stat_database` / size metrics by `datname` so the UI can show a\nbreakdown table (each database with its own size, cache-hit ratio, etc.)\nrather than collapsing every database into one value.", - "operationId": "ExternalServiceMetricsByDatabase", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "External service ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Per-database metric breakdown", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/DatabaseMetricsResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "500": { - "description": "Internal server error" - }, - "503": { - "description": "Metrics not available" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/external-services/{id}/metrics/enable": { - "patch": { - "tags": [ - "Metrics" - ], - "summary": "Enable or disable metric collection for an external service.", - "description": "When `enabled=true`, seeds the default alert rules for the service's engine\nvia [`temps_monitoring::seed_default_rules`] (idempotent).", - "operationId": "ExternalServiceMetricsToggle", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "External service ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ToggleServiceMetricsRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Metrics toggle applied" - }, - "400": { - "description": "Invalid request" - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "404": { - "description": "Service not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/external-services/{id}/metrics/latest": { - "get": { - "tags": [ - "Metrics" - ], - "summary": "Fetch the most-recent value for every tracked metric on an external service.", - "operationId": "ExternalServiceMetricsGetLatest", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "External service ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Map of metric name to latest value", - "content": { - "application/json": { - "schema": { - "type": "object", - "additionalProperties": { - "type": "number", - "format": "double" - }, - "propertyNames": { - "type": "string" - } - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "500": { - "description": "Internal server error" - }, - "503": { - "description": "Metrics store not available" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/external-services/{id}/metrics/status": { - "get": { - "tags": [ - "Metrics" - ], - "summary": "Return the freshness status (last-received timestamp) for a service.", - "description": "Cheap O(1) lookup against `service_metrics_status` \u2014 used by the UI to show\n\"last received at \u2026\" without scanning the metrics hypertable.", - "operationId": "ExternalServiceMetricsStatus", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "External service ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Metrics freshness status", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/MetricsStatusResponse" - } - } - } - }, - "503": { - "description": "Metrics not available" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/external-services/{id}/parameters/{param_name}": { - "get": { - "tags": [ - "External Services" - ], - "summary": "Reveal one sensitive service parameter. Service detail responses never\ncontain plaintext values; every successful reveal is recorded separately.", - "operationId": "reveal_service_parameter", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "External service ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "param_name", - "in": "path", - "description": "Sensitive parameter name", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Sensitive parameter value", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SensitiveValueResponse" - } - } - } - }, - "400": { - "description": "Parameter is not sensitive" - }, - "403": { - "description": "Caller cannot access a project linked to this service" - }, - "404": { - "description": "Service or parameter not found" - }, - "500": { - "description": "Internal server error" - } - } - } - }, - "/external-services/{id}/preview-environment-masked": { - "get": { - "tags": [ - "External Services" - ], - "summary": "Get environment variables preview with masked sensitive values", - "operationId": "get_service_preview_environment_variables_masked", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "External service ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Preview of environment variables with sensitive values masked as ***", - "content": { - "application/json": { - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - }, - "propertyNames": { - "type": "string" - } - } - } - } - }, - "404": { - "description": "Service not found" - }, - "500": { - "description": "Internal server error" - } - } - } - }, - "/external-services/{id}/preview-environment-names": { - "get": { - "tags": [ - "External Services" - ], - "summary": "Get environment variable names preview (safe - no sensitive values)", - "operationId": "get_service_preview_environment_variable_names", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "External service ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "List of environment variable names that would be provided", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "type": "string" - } - } - } - } - }, - "404": { - "description": "Service not found" - }, - "500": { - "description": "Internal server error" - } - } - } - }, - "/external-services/{id}/projects": { - "get": { - "tags": [ - "External Services" - ], - "summary": "List projects linked to service", - "operationId": "list_service_projects", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "External service ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "page", - "in": "query", - "description": "Page number (1-indexed)", - "required": false, - "schema": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "minimum": 0 - }, - "example": 1 - }, - { - "name": "page_size", - "in": "query", - "description": "Number of items per page (max 100)", - "required": false, - "schema": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "minimum": 0 - }, - "example": 20 - }, - { - "name": "sort_by", - "in": "query", - "required": false, - "schema": { - "type": [ - "string", - "null" - ] - } - }, - { - "name": "sort_order", - "in": "query", - "required": false, - "schema": { - "type": [ - "string", - "null" - ] - } - } - ], - "responses": { - "200": { - "description": "List of linked projects", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ProjectServiceInfo" - } - } - } - } - }, - "404": { - "description": "Service not found" - }, - "500": { - "description": "Internal server error" - } - } - }, - "post": { - "tags": [ - "External Services" - ], - "summary": "Link service to project", - "operationId": "link_service_to_project", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "External service ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LinkServiceRequest" - } - } - }, - "required": true - }, - "responses": { - "201": { - "description": "Service linked to project successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProjectServiceInfo" - } - } - } - }, - "404": { - "description": "Service or project not found" - }, - "500": { - "description": "Internal server error" - } - } - } - }, - "/external-services/{id}/projects/{project_id}": { - "delete": { - "tags": [ - "External Services" - ], - "summary": "Unlink service from project", - "operationId": "unlink_service_from_project", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "External service ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "204": { - "description": "Service unlinked from project successfully" - }, - "404": { - "description": "Service link not found" - }, - "500": { - "description": "Internal server error" - } - } - } - }, - "/external-services/{id}/projects/{project_id}/environment": { - "get": { - "tags": [ - "External Services" - ], - "summary": "Get all environment variables for a service-project pair", - "operationId": "get_service_environment_variables", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "External service ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "List of environment variables", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/EnvironmentVariableInfo" - } - } - } - } - }, - "404": { - "description": "Service or project not found" - }, - "500": { - "description": "Internal server error" - } - } - } - }, - "/external-services/{id}/projects/{project_id}/environment/{var_name}": { - "get": { - "tags": [ - "External Services" - ], - "summary": "Get specific environment variable for a service-project pair", - "operationId": "get_service_environment_variable", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "External service ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "var_name", - "in": "path", - "description": "Environment variable name", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Environment variable value", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/EnvironmentVariableInfo" - } - } - } - }, - "403": { - "description": "Plaintext secret access is not permitted" - }, - "404": { - "description": "Service, project, or variable not found" - }, - "500": { - "description": "Internal server error" - } - } - } - }, - "/external-services/{id}/resources": { - "patch": { - "tags": [ - "External Services" - ], - "summary": "Update a service's resource limits (memory, CPU caps).", - "description": "Persists the new caps to the encrypted config AND live-applies them\nvia Docker's update API. Memory and CPU can be hot-changed without a\nrestart on running containers; stopped containers also accept the\nupdate and pick up the new caps on next start.\n\nPass `null` (or omit) any field to leave it unlimited. A request where\nevery field is `null` removes any existing limits.\n\nThe response includes a per-container `applied[]` list so the caller\ncan tell which members got the update and which were skipped (e.g.,\ncontainer not yet created, or `docker update` rejected because the\nnew memory cap is below current usage).", - "operationId": "update_service_resources", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "External service ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ServiceResourceLimits" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Updated resource limits", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ResourceLimitsUpdateResponse" - } - } - } - }, - "400": { - "description": "Invalid resource limits" - }, - "404": { - "description": "Service not found" - }, - "500": { - "description": "Internal server error" - } - } - } - }, - "/external-services/{id}/restore": { - "post": { - "tags": [ - "Restore" - ], - "operationId": "start_restore", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "External service id (source for the restore)", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/StartRestoreRequest" - } - } - }, - "required": true - }, - "responses": { - "202": { - "description": "Restore run started", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/RestoreRunView" - } - } - } - }, - "400": { - "description": "Validation error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "404": { - "description": "Backup or service not found", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/external-services/{id}/restore-capabilities": { - "get": { - "tags": [ - "Restore" - ], - "operationId": "get_restore_capabilities", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "External service id", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Capabilities declared by the service", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/RestoreCapabilitiesResponse" - } - } - } - }, - "404": { - "description": "Service not found", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/external-services/{id}/restore-plan": { - "post": { - "tags": [ - "Restore" - ], - "operationId": "plan_restore", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "Target service id", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/StartRestoreRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Preview of what the restore will do", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/RestorePlan" - } - } - } - }, - "400": { - "description": "Validation error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "404": { - "description": "Backup or service not found", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/external-services/{id}/restore-runs": { - "get": { - "tags": [ - "Restore" - ], - "operationId": "list_restore_runs_for_service", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "External service id", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Recent restore runs for the service", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/RestoreRunView" - } - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/external-services/{id}/retry": { - "post": { - "tags": [ - "External Services" - ], - "summary": "Retry a failed cluster service initialization.", - "description": "Cleans up any leftover containers from the previous attempt and\nre-runs cluster initialization with the provided member specifications.", - "operationId": "retry_cluster", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/RetryClusterRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Cluster retry initiated", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ExternalServiceInfo" - } - } - } - }, - "400": { - "description": "Service is not a failed cluster" - }, - "404": { - "description": "Service not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/external-services/{id}/runtime": { - "get": { - "tags": [ - "External Services" - ], - "summary": "Inspect a service's container(s): status, restart count, OOM-killed flag,\nexit code, and the cgroup limits actually applied.", - "operationId": "get_service_runtime", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "External service ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Container runtime snapshot", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ServiceRuntimeReport" - } - } - } - }, - "404": { - "description": "Service not found" - }, - "500": { - "description": "Internal server error" - } - } - } - }, - "/external-services/{id}/start": { - "post": { - "tags": [ - "External Services" - ], - "summary": "Start an external service", - "operationId": "start_service", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "External service ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Service started successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ExternalServiceInfo" - } - } - } - }, - "404": { - "description": "Service not found" - }, - "409": { - "description": "A Postgres major upgrade is in progress for this service" - }, - "500": { - "description": "Internal server error" - } - } - } - }, - "/external-services/{id}/stats": { - "get": { - "tags": [ - "External Services" - ], - "summary": "Sample current CPU/memory usage from each of a service's containers.\nOne-shot sample, no streaming. Cheap to call (single Docker round-trip\nper member) so the UI can poll on a 5\u201310s interval.", - "operationId": "get_service_stats", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "External service ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Container stats snapshot", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ServiceStatsReport" - } - } - } - }, - "404": { - "description": "Service not found" - }, - "500": { - "description": "Internal server error" - } - } - } - }, - "/external-services/{id}/stop": { - "post": { - "tags": [ - "External Services" - ], - "summary": "Stop an external service", - "operationId": "stop_service", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "External service ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Service stopped successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ExternalServiceInfo" - } - } - } - }, - "404": { - "description": "Service not found" - }, - "500": { - "description": "Internal server error" - } - } - } - }, - "/external-services/{id}/upgrade": { - "post": { - "tags": [ - "External Services" - ], - "summary": "Upgrade external service to new Docker image with data migration\nThis endpoint uses service-specific upgrade procedures (e.g., pg_upgrade for PostgreSQL)", - "operationId": "upgrade_service", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "External service ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpgradeExternalServiceRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Service upgraded successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ExternalServiceInfo" - } - } - } - }, - "400": { - "description": "Invalid request or upgrade not supported" - }, - "404": { - "description": "Service not found" - }, - "409": { - "description": "A major upgrade is already in progress for this service" - }, - "500": { - "description": "Internal server error" - } - } - } - }, - "/external-services/{id}/wal-health": { - "get": { - "tags": [ - "External Services" - ], - "summary": "Postgres WAL & archive health snapshot", - "description": "Returns the latest WAL/archive health snapshot recorded by the background\nhealth monitor for a Postgres external service. Powers the warning banner\non the service detail page when the disk is filling up due to stale\nreplication slots, archive backlog, or misconfigured `archive_command`.\n\nReturns 404 when no snapshot exists yet (probe hasn't run, or the service\nisn't Postgres).", - "operationId": "getPostgresWalHealth", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "External service ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Latest WAL health snapshot", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/PostgresWalHealth" - } - } - } - }, - "404": { - "description": "Service not found, or no WAL snapshot available" - }, - "500": { - "description": "Internal server error" - } - } - } - }, - "/external-services/{service_id}/pg-stat-statements/enable": { - "post": { - "tags": [ - "External Services" - ], - "summary": "Enable `pg_stat_statements` on a standalone Postgres service.", - "description": "Stops the container and restarts it so that the\n`shared_preload_libraries=pg_stat_statements` CMD flag (baked into every\nnew standalone Postgres container) takes effect. The named data volume is\nreused unchanged \u2014 no data is lost.\n\n**Clustered (HA) services are rejected** with 422 \u2014 a blind single-container\nrestart bypasses controlled failover. For clustered services the response\nbody describes the manual rolling-restart steps.\n\nConfirmation is the caller's responsibility (UI dialog / CLI `--yes` flag)\nbefore invoking this endpoint.", - "operationId": "ExternalServiceEnablePgStatStatements", - "parameters": [ - { - "name": "service_id", - "in": "path", - "description": "ID of the provisioned standalone Postgres service", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Container restarted; pg_stat_statements now active", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/EnablePgStatStatementsResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions (requires external_services:write)" - }, - "404": { - "description": "Service not found" - }, - "422": { - "description": "Service is not standalone Postgres (cluster or wrong type)" - }, - "500": { - "description": "Restart failed" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/external-services/{service_id}/pg-stat-statements/reset": { - "post": { - "tags": [ - "External Services" - ], - "summary": "Reset all statistics accumulated by `pg_stat_statements` for a Postgres\nservice. This affects every user, database, and normalized query tracked by\nthe target Postgres instance and cannot be undone.", - "operationId": "ExternalServiceResetPgStatStatements", - "parameters": [ - { - "name": "service_id", - "in": "path", - "description": "ID of the provisioned Postgres service", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "requestBody": { - "description": "Explicit confirmation of the global, irreversible reset", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ResetPgStatStatementsRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "All accumulated pg_stat_statements statistics cleared", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ResetPgStatStatementsResponse" - } - } - } - }, - "400": { - "description": "Missing or invalid reset confirmation" - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions (requires external_services:write)" - }, - "404": { - "description": "Service not found" - }, - "422": { - "description": "Service is not Postgres" - }, - "502": { - "description": "Target Postgres rejected or failed the reset operation" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/external-services/{service_id}/pg-stat-statements/slow-queries": { - "get": { - "tags": [ - "External Services" - ], - "operationId": "get_slow_queries", - "parameters": [ - { - "name": "service_id", - "in": "path", - "description": "ID of the provisioned Postgres service", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "page", - "in": "query", - "description": "Page number (1-based). Defaults to 1.", - "required": false, - "schema": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "minimum": 0 - } - }, - { - "name": "page_size", - "in": "query", - "description": "Number of rows per page (1\u2013100). Defaults to 20.", - "required": false, - "schema": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "minimum": 0 - } - }, - { - "name": "sort_by", - "in": "query", - "description": "Column to sort by: one of `calls`, `total_exec_time_ms`,\n`mean_exec_time_ms`, `rows`, `cache_hit_ratio`. Defaults to\n`mean_exec_time_ms`. Applied server-side so ordering stays\nconsistent across pages.", - "required": false, - "schema": { - "type": [ - "string", - "null" - ] - } - }, - { - "name": "sort_order", - "in": "query", - "description": "Sort direction: `asc` or `desc`. Defaults to `desc`.", - "required": false, - "schema": { - "type": [ - "string", - "null" - ] - } - } - ], - "responses": { - "200": { - "description": "Paginated slow queries from pg_stat_statements", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SlowQueriesResponse" - } - } - } - }, - "400": { - "description": "Invalid pagination or sort parameters" - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions (requires external_services:read)" - }, - "404": { - "description": "Service not found" - }, - "422": { - "description": "Service is not a Postgres service" - }, - "503": { - "description": "pg_stat_statements extension not available (container restart required)" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/external-services/{service_id}/query/containers": { - "get": { - "tags": [ - "External Services - Query" - ], - "summary": "List containers at the root level (databases, keyspaces, etc.)", - "operationId": "list_root_containers", - "parameters": [ - { - "name": "service_id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "List of root containers", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ContainerResponse" - } - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "404": { - "description": "Service not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/external-services/{service_id}/query/containers/{path}": { - "get": { - "tags": [ - "External Services - Query" - ], - "summary": "List containers at a specific path\nPath segments are separated by forward slashes\nExample: /external-services/1/query/containers/mydb lists schemas in database \"mydb\"", - "operationId": "list_containers_at_path", - "parameters": [ - { - "name": "service_id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "path", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "List of containers", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ContainerResponse" - } - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "404": { - "description": "Service or container not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/external-services/{service_id}/query/containers/{path}/entities": { - "get": { - "tags": [ - "External Services - Query" - ], - "summary": "List entities (tables, collections, etc.) in a container\nExample: /external-services/1/query/containers/mydb/public/entities lists tables in the public schema", - "operationId": "list_entities", - "parameters": [ - { - "name": "limit", - "in": "query", - "description": "Maximum number of entities to return (default: 100, max: 1000)", - "required": false, - "schema": { - "type": "integer", - "minimum": 0 - } - }, - { - "name": "token", - "in": "query", - "description": "Continuation token for pagination", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "service_id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "path", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Paginated list of entities", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/PaginatedEntitiesResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "404": { - "description": "Service or container not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/external-services/{service_id}/query/containers/{path}/entities/{entity}": { - "get": { - "tags": [ - "External Services - Query" - ], - "summary": "Get detailed information about an entity (table schema)", - "operationId": "get_entity_info", - "parameters": [ - { - "name": "service_id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "path", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "entity", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Entity details", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/EntityInfoResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "404": { - "description": "Service, container, or entity not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/external-services/{service_id}/query/containers/{path}/entities/{entity}/data": { - "post": { - "tags": [ - "External Services - Query" - ], - "summary": "Query data from an entity with optional filters, pagination, and sorting", - "operationId": "query_data", - "parameters": [ - { - "name": "service_id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "path", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "entity", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/QueryDataRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Query results", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/QueryDataResponse" - } - } - } - }, - "400": { - "description": "Invalid query" - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "404": { - "description": "Service, container, or entity not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/external-services/{service_id}/query/containers/{path}/entities/{entity}/download": { - "get": { - "tags": [ - "External Services - Query" - ], - "summary": "Download an object (S3 only) as a streaming response", - "operationId": "download_object", - "parameters": [ - { - "name": "service_id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "path", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "entity", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Object data stream", - "content": { - "application/octet-stream": {} - } - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "404": { - "description": "Object not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/external-services/{service_id}/query/containers/{path}/info": { - "get": { - "tags": [ - "External Services - Query" - ], - "summary": "Get information about a specific container", - "operationId": "get_container_info", - "parameters": [ - { - "name": "service_id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "path", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Container information", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ContainerResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "404": { - "description": "Service or container not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/external-services/{service_id}/query/explorer-support": { - "get": { - "tags": [ - "External Services - Query" - ], - "summary": "Check if a service supports query explorer functionality", - "operationId": "check_explorer_support", - "parameters": [ - { - "name": "service_id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Explorer support information", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ExplorerSupportResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "404": { - "description": "Service not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/external-services/{service_id}/upgrades": { - "get": { - "tags": [ - "Postgres Upgrades" - ], - "summary": "List recent upgrades for a single service (newest first, page size 50).", - "operationId": "list_pg_upgrades", - "parameters": [ - { - "name": "service_id", - "in": "path", - "description": "External service id", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Recent upgrades", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/PgUpgradeResponse" - } - } - } - } - }, - "500": { - "description": "Internal error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "post": { - "tags": [ - "Postgres Upgrades" - ], - "summary": "Start a new PostgreSQL major-version upgrade for a service.", - "operationId": "start_pg_upgrade", - "parameters": [ - { - "name": "service_id", - "in": "path", - "description": "External service id", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/StartPgUpgradeRequest" - } - } - }, - "required": true - }, - "responses": { - "201": { - "description": "Upgrade started", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/PgUpgradeResponse" - } - } - } - }, - "400": { - "description": "Invalid request" - }, - "409": { - "description": "An upgrade is already running for this service" - }, - "412": { - "description": "No default S3 source configured" - }, - "500": { - "description": "Internal error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/external-services/{service_id}/upgrades/{id}": { - "get": { - "tags": [ - "Postgres Upgrades" - ], - "summary": "Get a single upgrade by id, scoped to a service.", - "operationId": "get_pg_upgrade", - "parameters": [ - { - "name": "service_id", - "in": "path", - "description": "External service id", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "id", - "in": "path", - "description": "Upgrade id", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Upgrade", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/PgUpgradeResponse" - } - } - } - }, - "404": { - "description": "Not found" - }, - "500": { - "description": "Internal error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/external-services/{service_id}/upgrades/{id}/cancel": { - "post": { - "tags": [ - "Postgres Upgrades" - ], - "summary": "Cancel an in-flight upgrade. The orchestrator stops at its next phase\nboundary; already-terminal upgrades return 409.", - "operationId": "cancel_pg_upgrade", - "parameters": [ - { - "name": "service_id", - "in": "path", - "description": "External service id", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "id", - "in": "path", - "description": "Upgrade id", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Cancellation requested", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/PgUpgradeResponse" - } - } - } - }, - "404": { - "description": "Not found" - }, - "409": { - "description": "Upgrade already terminal" - }, - "500": { - "description": "Internal error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/external-services/{service_id}/upgrades/{id}/logs": { - "get": { - "tags": [ - "Postgres Upgrades" - ], - "summary": "Get the accumulated JSONL log content for an upgrade (for dashboard display).", - "operationId": "get_pg_upgrade_logs", - "parameters": [ - { - "name": "service_id", - "in": "path", - "description": "External service id", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "id", - "in": "path", - "description": "Upgrade id", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Log content", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/PgUpgradeLogResponse" - } - } - } - }, - "404": { - "description": "Not found" - }, - "500": { - "description": "Internal error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/external-services/{service_id}/upgrades/{id}/retry": { - "post": { - "tags": [ - "Postgres Upgrades" - ], - "summary": "Retry a failed upgrade. The phase is preserved, so the state machine\nresumes from where it failed.", - "operationId": "retry_pg_upgrade", - "parameters": [ - { - "name": "service_id", - "in": "path", - "description": "External service id", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "id", - "in": "path", - "description": "Upgrade id", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Retry scheduled", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/PgUpgradeResponse" - } - } - } - }, - "400": { - "description": "Upgrade is not in a retriable state" - }, - "404": { - "description": "Not found" - }, - "500": { - "description": "Internal error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/external-services/{service_id}/upgrades/{id}/rollback": { - "post": { - "tags": [ - "Postgres Upgrades" - ], - "summary": "Roll a completed upgrade back to its pre-upgrade PGDATA volume and old image.\nOnly valid while the rollback retention window is still open (see\n`ROLLBACK_RETENTION_DAYS`) and the rollback volume has not been swept.", - "operationId": "rollback_pg_upgrade", - "parameters": [ - { - "name": "service_id", - "in": "path", - "description": "External service id", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "id", - "in": "path", - "description": "Upgrade id", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Rollback complete", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/PgUpgradeResponse" - } - } - } - }, - "404": { - "description": "Not found" - }, - "409": { - "description": "Upgrade is not in a rollbackable state (not completed, volume swept, or retention expired)" - }, - "500": { - "description": "Internal error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/files/{file_path}": { - "get": { - "tags": [ - "Files" - ], - "operationId": "get_file", - "parameters": [ - { - "name": "file_path", - "in": "path", - "description": "Relative path to the file from static directory", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "File content retrieved successfully", - "content": { - "application/octet-stream": {} - } - }, - "401": { - "description": "Authentication required" - }, - "403": { - "description": "Access denied - path outside static directory or insufficient permissions" - }, - "404": { - "description": "File not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/flags/exposure": { - "post": { - "tags": [ - "Feature Flags" - ], - "summary": "Record which flags a running app actually evaluated.", - "description": "This is what makes `last_evaluated_at` mean something. The snapshot\nendpoint hands the SDK every flag in the environment and evaluation then\nhappens locally, so the control plane cannot otherwise tell a flag that is\nreferenced by live code from one nothing has called in a year. Stamping on\nsnapshot fetch would mark every flag as freshly used and defeat the point.\n\nScope comes from the deployment token, never the body. The endpoint writes\nonly `last_evaluated_at` \u2014 never a flag's value \u2014 so \"a deployment token\ncannot change what a flag serves\" still holds despite this being a write.", - "operationId": "record_flag_exposure", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/RecordExposureRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Exposure recorded", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/RecordExposureResponse" - } - } - } - }, - "400": { - "description": "Deployment token required" - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/flags/snapshot": { - "get": { - "tags": [ - "Feature Flags" - ], - "summary": "Every flag for the caller's environment, collapsed to what the evaluator\nneeds.", - "description": "Scope comes from the deployment token, never from the URL: a container's\nbaked-in `TEMPS_API_TOKEN` identifies exactly one project (and usually one\nenvironment), so a compromised app cannot read another tenant's flags by\nchanging a path parameter.\n\nSupports `If-None-Match`, so the SDK's background poll is a 304 in the\ncommon case.", - "operationId": "get_flag_snapshot", - "parameters": [ - { - "name": "environment_id", - "in": "query", - "description": "Required only when the calling token is project-wide rather than scoped\nto a single environment.", - "required": false, - "schema": { - "type": [ - "integer", - "null" - ], - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Snapshot for the environment", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/FlagSnapshotResponse" - } - } - } - }, - "304": { - "description": "Snapshot unchanged" - }, - "400": { - "description": "Environment could not be determined" - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/geo/{ip}": { - "get": { - "tags": [ - "geo" - ], - "summary": "Get geolocation information for an IP address", - "operationId": "get_ip_geolocation", - "parameters": [ - { - "name": "ip", - "in": "path", - "description": "IP address to geolocate (IPv4 or IPv6)", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Geolocation information retrieved", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/GeoLocationResponse" - } - } - } - }, - "400": { - "description": "Invalid IP address", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "401": { - "description": "Authentication required", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "403": { - "description": "Insufficient permissions", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "404": { - "description": "IP address not found in database", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/git-connections": { - "get": { - "tags": [ - "Git Providers" - ], - "summary": "List user's git provider connections", - "operationId": "list_connections", - "parameters": [ - { - "name": "page", - "in": "query", - "description": "Page number for pagination (default: 1)", - "required": false, - "schema": { - "type": "integer", - "format": "int64", - "minimum": 0 - } - }, - { - "name": "per_page", - "in": "query", - "description": "Number of items per page (default: 30, max: 100)", - "required": false, - "schema": { - "type": "integer", - "format": "int64", - "minimum": 0 - } - }, - { - "name": "sort", - "in": "query", - "description": "Sort field (created_at, updated_at, account_name)", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "direction", - "in": "query", - "description": "Sort direction (asc, desc), default: desc", - "required": false, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "List of connections", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ConnectionListResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/git-connections/{connection_id}": { - "delete": { - "tags": [ - "Git Providers" - ], - "summary": "Permanently delete a git provider connection", - "operationId": "delete_connection", - "parameters": [ - { - "name": "connection_id", - "in": "path", - "description": "Connection ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "204": { - "description": "Connection deleted successfully" - }, - "400": { - "description": "Connection is in use by projects and cannot be deleted" - }, - "401": { - "description": "Unauthorized" - }, - "404": { - "description": "Connection not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/git-connections/{connection_id}/activate": { - "post": { - "tags": [ - "Git Providers" - ], - "summary": "Activate a git provider connection", - "operationId": "activate_connection", - "parameters": [ - { - "name": "connection_id", - "in": "path", - "description": "Connection ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Connection activated successfully" - }, - "400": { - "description": "Provider is deactivated and connection cannot be activated" - }, - "401": { - "description": "Unauthorized" - }, - "404": { - "description": "Connection not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/git-connections/{connection_id}/deactivate": { - "post": { - "tags": [ - "Git Providers" - ], - "summary": "Deactivate a git provider connection", - "operationId": "deactivate_connection", - "parameters": [ - { - "name": "connection_id", - "in": "path", - "description": "Connection ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Connection deactivated successfully" - }, - "400": { - "description": "Connection is in use by projects and cannot be deactivated" - }, - "401": { - "description": "Unauthorized" - }, - "404": { - "description": "Connection not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/git-connections/{connection_id}/health-check": { - "post": { - "tags": [ - "Git Provider Connections" - ], - "summary": "Run an on-demand health check for a git connection.", - "description": "Probes the upstream (GitHub App, PAT, or OAuth token), persists the result,\nand fires admin notifications on status transitions. Returns the updated\nconnection.", - "operationId": "run_connection_health_check", - "parameters": [ - { - "name": "connection_id", - "in": "path", - "description": "Connection ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Health check completed", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ConnectionResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "404": { - "description": "Connection not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/git-connections/{connection_id}/repositories": { - "get": { - "tags": [ - "Git Providers" - ], - "summary": "List repositories for a specific connection", - "description": "Fetches repositories from the connected git provider with support for pagination, search, and filtering.\nThis endpoint calls the provider's API directly to get the most up-to-date repository list.", - "operationId": "list_repositories_by_connection", - "parameters": [ - { - "name": "connection_id", - "in": "path", - "description": "Connection ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "page", - "in": "query", - "description": "Page number for pagination", - "required": false, - "schema": { - "type": "integer", - "format": "int64", - "minimum": 0 - } - }, - { - "name": "per_page", - "in": "query", - "description": "Number of items per page (max 100)", - "required": false, - "schema": { - "type": "integer", - "format": "int64", - "minimum": 0 - } - }, - { - "name": "sort", - "in": "query", - "description": "Sort field (name, created_at, updated_at, stars, etc.)", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "direction", - "in": "query", - "description": "Sort direction (asc, desc)", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "search", - "in": "query", - "description": "Search term to filter repositories", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "owner", - "in": "query", - "description": "Filter by repository owner", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "language", - "in": "query", - "description": "Filter by programming language", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "private", - "in": "query", - "description": "Filter by private status (true/false)", - "required": false, - "schema": { - "type": "boolean" - } - } - ], - "responses": { - "200": { - "description": "List of repositories", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/RepositoryListResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "404": { - "description": "Connection not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/git-connections/{connection_id}/sync": { - "post": { - "tags": [ - "Git Providers" - ], - "summary": "Start a repository sync for a connection", - "description": "Kicks off a background sync of the connection's repositories from the\nprovider. Returns `202 Accepted` immediately \u2014 the caller should poll\nthe connection endpoint for `syncing` / `synced_repository_count`\nupdates rather than waiting on this response. The sync is guarded by\na hard deadline and always releases the `syncing` flag on exit, so a\nclient that disconnects mid-sync will not leave the connection stuck.", - "operationId": "sync_repositories", - "parameters": [ - { - "name": "connection_id", - "in": "path", - "description": "Connection ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "202": { - "description": "Repository sync started in background", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/RepositorySyncStartedResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "404": { - "description": "Connection not found" - }, - "409": { - "description": "Sync already in progress" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/git-connections/{connection_id}/update-token": { - "post": { - "tags": [ - "Git Provider Connections" - ], - "summary": "Update access token for a connection (when tokens expire or are rotated)", - "operationId": "update_connection_token", - "parameters": [ - { - "name": "connection_id", - "in": "path", - "description": "Connection ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdateTokenRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Token updated successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdateTokenResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "404": { - "description": "Connection not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/git-connections/{connection_id}/validate": { - "get": { - "tags": [ - "Git Provider Connections" - ], - "summary": "Validate a connection by testing the access token", - "operationId": "validate_connection", - "parameters": [ - { - "name": "connection_id", - "in": "path", - "description": "Connection ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Connection validation result", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ValidationResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "404": { - "description": "Connection not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/git-providers": { - "get": { - "tags": [ - "Git Providers" - ], - "summary": "List all git providers", - "operationId": "list_git_providers", - "responses": { - "200": { - "description": "List of providers", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ProviderResponse" - } - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "post": { - "tags": [ - "Git Providers" - ], - "summary": "Create a new git provider configuration", - "operationId": "create_git_provider", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateProviderRequest" - } - } - }, - "required": true - }, - "responses": { - "201": { - "description": "Provider created successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProviderResponse" - } - } - } - }, - "400": { - "description": "Bad request" - }, - "401": { - "description": "Unauthorized" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/git-providers/bitbucket": { - "post": { - "tags": [ - "Git Providers" - ], - "summary": "Create a Bitbucket Cloud provider with access token or app password authentication", - "operationId": "create_bitbucket_provider", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateBitbucketRequest" - } - } - }, - "required": true - }, - "responses": { - "201": { - "description": "Bitbucket provider created successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProviderResponse" - } - } - } - }, - "400": { - "description": "Bad request \u2014 missing or invalid auth fields" - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Forbidden" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/git-providers/generic": { - "post": { - "tags": [ - "Git Providers" - ], - "summary": "Create a Generic git provider for self-hosted or arbitrary HTTPS git hosts.\nSupports public repositories (no token) and private repositories (token-based).", - "operationId": "create_generic_provider", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateGenericRequest" - } - } - }, - "required": true - }, - "responses": { - "201": { - "description": "Generic git provider created successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProviderResponse" - } - } - } - }, - "400": { - "description": "Bad request \u2014 invalid clone URL or missing fields" - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Forbidden" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/git-providers/gitea/pat": { - "post": { - "tags": [ - "Git Providers" - ], - "summary": "Create a Gitea Personal Access Token provider", - "operationId": "create_gitea_pat_provider", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateGiteaPATRequest" - } - } - }, - "required": true - }, - "responses": { - "201": { - "description": "Gitea PAT provider created successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProviderResponse" - } - } - } - }, - "400": { - "description": "Bad request \u2014 invalid URL or missing fields" - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Forbidden" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/git-providers/github/pat": { - "post": { - "tags": [ - "Git Providers" - ], - "summary": "Create a GitHub Personal Access Token provider", - "operationId": "create_github_pat_provider", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateGitHubPATRequest" - } - } - }, - "required": true - }, - "responses": { - "201": { - "description": "GitHub PAT provider created successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProviderResponse" - } - } - } - }, - "400": { - "description": "Bad request" - }, - "401": { - "description": "Unauthorized" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/git-providers/gitlab/oauth": { - "post": { - "tags": [ - "Git Providers" - ], - "summary": "Create a GitLab OAuth provider", - "operationId": "create_gitlab_oauth_provider", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateGitLabOAuthRequest" - } - } - }, - "required": true - }, - "responses": { - "201": { - "description": "GitLab OAuth provider created successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProviderResponse" - } - } - } - }, - "400": { - "description": "Bad request" - }, - "401": { - "description": "Unauthorized" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/git-providers/gitlab/pat": { - "post": { - "tags": [ - "Git Providers" - ], - "summary": "Create a GitLab PAT provider", - "operationId": "create_gitlab_pat_provider", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateGitLabPATRequest" - } - } - }, - "required": true - }, - "responses": { - "201": { - "description": "GitLab PAT provider created successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProviderResponse" - } - } - } - }, - "400": { - "description": "Bad request" - }, - "401": { - "description": "Unauthorized" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/git-providers/{provider_id}": { - "get": { - "tags": [ - "Git Providers" - ], - "summary": "Get a specific git provider", - "operationId": "get_git_provider", - "parameters": [ - { - "name": "provider_id", - "in": "path", - "description": "Provider ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Provider details", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProviderResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "404": { - "description": "Provider not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "delete": { - "tags": [ - "Git Providers" - ], - "summary": "Permanently delete a git provider", - "operationId": "delete_git_provider", - "parameters": [ - { - "name": "provider_id", - "in": "path", - "description": "Provider ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "204": { - "description": "Provider deleted successfully" - }, - "400": { - "description": "Provider has connections and cannot be deleted" - }, - "401": { - "description": "Unauthorized" - }, - "404": { - "description": "Provider not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/git-providers/{provider_id}/activate": { - "post": { - "tags": [ - "Git Providers" - ], - "summary": "Activate a git provider", - "operationId": "activate_provider", - "parameters": [ - { - "name": "provider_id", - "in": "path", - "description": "Provider ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Provider activated successfully" - }, - "401": { - "description": "Unauthorized" - }, - "404": { - "description": "Provider not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/git-providers/{provider_id}/callback": { - "get": { - "tags": [ - "Git Providers" - ], - "summary": "Handle OAuth callback for a git provider", - "operationId": "handle_git_provider_oauth_callback", - "parameters": [ - { - "name": "provider_id", - "in": "path", - "description": "Git provider ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "code", - "in": "query", - "description": "OAuth authorization code", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "state", - "in": "query", - "description": "CSRF state token", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "302": { - "description": "Redirect to success page" - }, - "400": { - "description": "Bad request" - }, - "404": { - "description": "Provider not found" - }, - "500": { - "description": "Internal server error" - } - } - } - }, - "/git-providers/{provider_id}/connections": { - "get": { - "tags": [ - "Git Providers" - ], - "summary": "Get connections for a specific git provider", - "operationId": "get_provider_connections", - "parameters": [ - { - "name": "provider_id", - "in": "path", - "description": "Provider ID to get connections for", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "List of connections for the provider", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ConnectionResponse" - } - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "404": { - "description": "Provider not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/git-providers/{provider_id}/credentials": { - "patch": { - "tags": [ - "Git Providers" - ], - "summary": "Partially update credentials for an existing git provider. Only the fields\nyou send are replaced; omitted fields keep their stored values. Fields that\ndon't apply to the provider's auth method are ignored on the service side.", - "operationId": "update_git_provider_credentials", - "parameters": [ - { - "name": "provider_id", - "in": "path", - "description": "Git provider ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdateProviderCredentialsRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Credentials updated", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProviderResponse" - } - } - } - }, - "400": { - "description": "Bad request" - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Forbidden" - }, - "404": { - "description": "Provider not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/git-providers/{provider_id}/deactivate": { - "post": { - "tags": [ - "Git Providers" - ], - "summary": "Deactivate a git provider", - "operationId": "deactivate_provider", - "parameters": [ - { - "name": "provider_id", - "in": "path", - "description": "Provider ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Provider deactivated successfully" - }, - "401": { - "description": "Unauthorized" - }, - "404": { - "description": "Provider not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/git-providers/{provider_id}/deletion-check": { - "get": { - "tags": [ - "Git Providers" - ], - "summary": "Check if a git provider can be safely deleted", - "operationId": "check_provider_deletion_safety", - "parameters": [ - { - "name": "provider_id", - "in": "path", - "description": "Git provider ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Deletion check result", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProviderDeletionCheckResponse" - } - } - } - }, - "404": { - "description": "Provider not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/git-providers/{provider_id}/oauth/authorize": { - "get": { - "tags": [ - "Git Providers" - ], - "summary": "Start OAuth flow for a git provider", - "operationId": "start_git_provider_oauth", - "parameters": [ - { - "name": "provider_id", - "in": "path", - "description": "Git provider ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "302": { - "description": "Redirect to OAuth provider" - }, - "404": { - "description": "Provider not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/git-providers/{provider_id}/repositories": { - "get": { - "tags": [ - "Git Providers" - ], - "summary": "List all repositories for a specific provider", - "description": "Lists repositories synced to the database across every connection under\nthis provider, with the same pagination/filtering as `/repositories`.", - "operationId": "list_repositories_by_provider", - "parameters": [ - { - "name": "provider_id", - "in": "path", - "description": "Provider ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "page", - "in": "query", - "description": "Page number for pagination", - "required": false, - "schema": { - "type": "integer", - "format": "int64", - "minimum": 0 - } - }, - { - "name": "per_page", - "in": "query", - "description": "Number of items per page (max 100)", - "required": false, - "schema": { - "type": "integer", - "format": "int64", - "minimum": 0 - } - }, - { - "name": "sort", - "in": "query", - "description": "Sort field (name, created_at, updated_at, stars, watchers, size, issues)", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "direction", - "in": "query", - "description": "Sort direction (asc, desc)", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "search", - "in": "query", - "description": "Search term to filter repositories", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "owner", - "in": "query", - "description": "Filter by repository owner", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "language", - "in": "query", - "description": "Filter by programming language", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "private", - "in": "query", - "description": "Filter by private status (true/false)", - "required": false, - "schema": { - "type": "boolean" - } - } - ], - "responses": { - "200": { - "description": "List of repositories", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/RepositoryListResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "404": { - "description": "Provider not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/git-providers/{provider_id}/safe-delete": { - "delete": { - "tags": [ - "Git Providers" - ], - "summary": "Safely delete a git provider (only if no projects are using it)", - "operationId": "delete_provider_safely", - "parameters": [ - { - "name": "provider_id", - "in": "path", - "description": "Git provider ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "204": { - "description": "Provider successfully deleted" - }, - "400": { - "description": "Cannot delete provider because it's in use" - }, - "404": { - "description": "Provider not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/git/public/{provider}/{owner}/{repo}": { - "get": { - "tags": [ - "Public Repositories" - ], - "summary": "Get information about a public repository (supports GitHub and GitLab)", - "operationId": "get_public_repository", - "parameters": [ - { - "name": "provider", - "in": "path", - "description": "Git provider (github or gitlab)", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "owner", - "in": "path", - "description": "Repository owner", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "repo", - "in": "path", - "description": "Repository name", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Repository information", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/PublicRepositoryInfo" - } - } - } - }, - "400": { - "description": "Provider not supported" - }, - "404": { - "description": "Repository not found" - }, - "429": { - "description": "API rate limit exceeded" - }, - "500": { - "description": "Internal server error" - } - } - } - }, - "/git/public/{provider}/{owner}/{repo}/branches": { - "get": { - "tags": [ - "Public Repositories" - ], - "summary": "Get branches for a public repository (supports GitHub and GitLab)", - "operationId": "get_public_branches", - "parameters": [ - { - "name": "provider", - "in": "path", - "description": "Git provider (github or gitlab)", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "owner", - "in": "path", - "description": "Repository owner", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "repo", - "in": "path", - "description": "Repository name", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "fresh", - "in": "query", - "description": "Force fetch fresh data, bypassing cache (default: false)", - "required": false, - "schema": { - "type": "boolean" - } - } - ], - "responses": { - "200": { - "description": "List of branches", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/BranchListResponse" - } - } - } - }, - "400": { - "description": "Provider not supported" - }, - "404": { - "description": "Repository not found" - }, - "429": { - "description": "API rate limit exceeded" - }, - "500": { - "description": "Internal server error" - } - } - } - }, - "/git/public/{provider}/{owner}/{repo}/presets": { - "get": { - "tags": [ - "Public Repositories" - ], - "summary": "Detect presets for a public repository (supports GitHub and GitLab)", - "operationId": "detect_public_presets", - "parameters": [ - { - "name": "provider", - "in": "path", - "description": "Git provider (github or gitlab)", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "owner", - "in": "path", - "description": "Repository owner", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "repo", - "in": "path", - "description": "Repository name", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "branch", - "in": "query", - "description": "Branch name to detect presets for (default: repository's default branch)", - "required": false, - "schema": { - "type": [ - "string", - "null" - ] - } - }, - { - "name": "fresh", - "in": "query", - "description": "Force fetch fresh data, bypassing cache (default: false)", - "required": false, - "schema": { - "type": "boolean" - } - } - ], - "responses": { - "200": { - "description": "Detected presets", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/PublicPresetResponse" - } - } - } - }, - "400": { - "description": "Provider not supported" - }, - "404": { - "description": "Repository or branch not found" - }, - "429": { - "description": "API rate limit exceeded" - }, - "500": { - "description": "Internal server error" - } - } - } - }, - "/imports/discover": { - "post": { - "tags": [ - "Imports" - ], - "summary": "Discover workloads from a source", - "operationId": "discover_workloads", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/DiscoverRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "List of discovered workloads", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/DiscoverResponse" - } - } - } - }, - "400": { - "description": "Invalid request" - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/imports/execute": { - "post": { - "tags": [ - "Imports" - ], - "summary": "Execute an import", - "operationId": "execute_import", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ExecuteImportRequest" - } - } - }, - "required": true - }, - "responses": { - "202": { - "description": "Import execution started", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ExecuteImportResponse" - } - } - } - }, - "400": { - "description": "Invalid request" - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/imports/plan": { - "post": { - "tags": [ - "Imports" - ], - "summary": "Create an import plan", - "operationId": "create_plan", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreatePlanRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Import plan created", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreatePlanResponse" - } - } - } - }, - "400": { - "description": "Invalid request" - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/imports/sources": { - "get": { - "tags": [ - "Imports" - ], - "summary": "List available import sources", - "operationId": "list_sources", - "responses": { - "200": { - "description": "List of available import sources", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ImportSourceInfo" - } - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/imports/{session_id}": { - "get": { - "tags": [ - "Imports" - ], - "summary": "Get import status", - "operationId": "get_import_status", - "parameters": [ - { - "name": "session_id", - "in": "path", - "description": "Import session ID", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Import status", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ImportStatusResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "404": { - "description": "Import session not found" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/incidents/{incident_id}": { - "get": { - "tags": [ - "Status Page" - ], - "summary": "Get an incident by ID", - "operationId": "get_incident", - "parameters": [ - { - "name": "incident_id", - "in": "path", - "description": "Incident ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Successfully retrieved incident", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/IncidentResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "404": { - "description": "Incident not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/incidents/{incident_id}/status": { - "patch": { - "tags": [ - "Status Page" - ], - "summary": "Update incident status", - "operationId": "update_incident_status", - "parameters": [ - { - "name": "incident_id", - "in": "path", - "description": "Incident ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdateIncidentStatusRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Incident status updated successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/IncidentResponse" - } - } - } - }, - "400": { - "description": "Invalid request" - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "404": { - "description": "Incident not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/incidents/{incident_id}/updates": { - "get": { - "tags": [ - "Status Page" - ], - "summary": "Get incident updates", - "operationId": "get_incident_updates", - "parameters": [ - { - "name": "incident_id", - "in": "path", - "description": "Incident ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Successfully retrieved incident updates", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/IncidentUpdateResponse" - } - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "404": { - "description": "Incident not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/internal/nodes": { - "get": { - "tags": [ - "Nodes" - ], - "summary": "List all registered nodes (admin \u2014 session auth via RequireAuth)", - "operationId": "admin_list_nodes", - "responses": { - "200": { - "description": "List of nodes", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/NodeListResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/internal/nodes/register": { - "post": { - "tags": [ - "Nodes" - ], - "summary": "Register a new worker node or reconnect an existing one", - "operationId": "register_node", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/RegisterNodeApiRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Node reconnected successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/RegisterNodeResponse" - } - } - } - }, - "201": { - "description": "Node registered successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/RegisterNodeResponse" - } - } - } - }, - "400": { - "description": "Validation error" - }, - "500": { - "description": "Internal server error" - } - } - } - }, - "/internal/nodes/{node_id}": { - "get": { - "tags": [ - "Nodes" - ], - "summary": "Get a specific node by ID (admin \u2014 session auth via RequireAuth)", - "operationId": "admin_get_node", - "parameters": [ - { - "name": "node_id", - "in": "path", - "description": "Node ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Node details", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/NodeInfoResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "404": { - "description": "Node not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "delete": { - "tags": [ - "Nodes" - ], - "summary": "Remove a node from the cluster entirely. The node should be drained first\nto ensure containers have been rescheduled. If the node still has active\ncontainers, it will be drained automatically before removal.", - "operationId": "admin_remove_node", - "parameters": [ - { - "name": "node_id", - "in": "path", - "description": "Node ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Node removed", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/RemoveNodeResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "404": { - "description": "Node not found" - }, - "409": { - "description": "Node still has active containers" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/internal/nodes/{node_id}/containers": { - "get": { - "tags": [ - "Nodes" - ], - "summary": "List all containers running on a specific node", - "operationId": "admin_list_node_containers", - "parameters": [ - { - "name": "node_id", - "in": "path", - "description": "Node ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Containers on this node", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/NodeContainerListResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "404": { - "description": "Node not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/internal/nodes/{node_id}/dns/ack": { - "post": { - "tags": [ - "Internal DNS" - ], - "summary": "`POST /internal/nodes/{node_id}/dns/ack`", - "operationId": "post_dns_ack", - "parameters": [ - { - "name": "node_id", - "in": "path", - "description": "Node id, must match the bearer token's node", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/DnsAckRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "ACK accepted", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/DnsAckResponse" - } - } - } - }, - "400": { - "description": "ACK higher than server generation" - }, - "401": { - "description": "Missing or invalid bearer token" - }, - "404": { - "description": "Node not found" - }, - "500": { - "description": "Internal server error" - } - } - } - }, - "/internal/nodes/{node_id}/dns/changes": { - "get": { - "tags": [ - "Internal DNS" - ], - "summary": "`GET /internal/nodes/{node_id}/dns/changes?since=N`", - "operationId": "get_dns_changes", - "parameters": [ - { - "name": "node_id", - "in": "path", - "description": "Node id, must match the bearer token's node", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "since", - "in": "query", - "description": "Highest generation the agent has already applied. Pass `0` to\nrequest a full zone snapshot. Defaults to `0` if omitted.", - "required": false, - "schema": { - "type": "integer", - "format": "int64" - } - } - ], - "responses": { - "200": { - "description": "Diff or full snapshot", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/DnsChangesResponse" - } - } - } - }, - "401": { - "description": "Missing or invalid bearer token" - }, - "404": { - "description": "Node not found" - }, - "500": { - "description": "Internal server error" - } - } - } - }, - "/internal/nodes/{node_id}/drain": { - "get": { - "tags": [ - "Nodes" - ], - "summary": "Get the drain status for a node, including migration progress.", - "description": "Returns container counts and whether the drain is complete.\nCan be polled to track drain progress.", - "operationId": "admin_drain_status", - "parameters": [ - { - "name": "node_id", - "in": "path", - "description": "Node ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Drain status", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/DrainStatusResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "404": { - "description": "Node not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "post": { - "tags": [ - "Nodes" - ], - "summary": "Drain a node: mark it as \"draining\" so no new replicas are scheduled on it,\nand trigger redeployment of all affected environments so their containers\nare rescheduled to healthy nodes.", - "operationId": "admin_drain_node", - "parameters": [ - { - "name": "node_id", - "in": "path", - "description": "Node ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Node drain initiated", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/DrainNodeResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "404": { - "description": "Node not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "delete": { - "tags": [ - "Nodes" - ], - "summary": "Undrain (reactivate) a node so it can accept new deployments again.\nOnly works for nodes in \"draining\" or \"drained\" status.", - "operationId": "admin_undrain_node", - "parameters": [ - { - "name": "node_id", - "in": "path", - "description": "Node ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Node reactivated", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UndrainNodeResponse" - } - } - } - }, - "400": { - "description": "Node not in drainable state" - }, - "401": { - "description": "Unauthorized" - }, - "404": { - "description": "Node not found" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/internal/nodes/{node_id}/heartbeat": { - "post": { - "tags": [ - "Nodes" - ], - "summary": "Receive a heartbeat from a worker node", - "operationId": "node_heartbeat", - "parameters": [ - { - "name": "node_id", - "in": "path", - "description": "Node ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HeartbeatApiRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Heartbeat received", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HeartbeatResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "404": { - "description": "Node not found" - }, - "500": { - "description": "Internal server error" - } - } - } - }, - "/internal/nodes/{node_id}/network/peers": { - "get": { - "tags": [ - "Nodes" - ], - "summary": "`GET /internal/nodes/{node_id}/network/peers`", - "operationId": "list_peers", - "parameters": [ - { - "name": "node_id", - "in": "path", - "description": "Node id, must match the bearer token's node", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Peer list and self-allocation", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/PeerListResponse" - } - } - } - }, - "401": { - "description": "Missing or invalid bearer token" - }, - "404": { - "description": "Node not found" - }, - "500": { - "description": "Internal server error" - } - } - } - }, - "/internal/nodes/{node_id}/s3-credentials/{s3_source_id}": { - "get": { - "tags": [ - "Nodes" - ], - "summary": "Get decrypted S3 credentials for a backup/restore operation.", - "description": "Agents call this endpoint to receive the S3 credentials they need to upload\nor download backups. The credentials are decrypted from the stored S3 source\nand returned over the authenticated TLS/WireGuard channel.", - "operationId": "get_s3_credentials", - "parameters": [ - { - "name": "node_id", - "in": "path", - "description": "Node ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "s3_source_id", - "in": "path", - "description": "S3 source ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "S3 credentials", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/S3CredentialsResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "404": { - "description": "S3 source not found" - }, - "500": { - "description": "Internal server error" - } - } - } - }, - "/ip-access-control": { - "get": { - "tags": [ - "IP Access Control" - ], - "summary": "List all IP access control rules", - "operationId": "list_ip_access_control", - "parameters": [ - { - "name": "action", - "in": "query", - "description": "Filter by action (\"block\" or \"allow\")", - "required": false, - "schema": { - "type": [ - "string", - "null" - ] - } - } - ], - "responses": { - "200": { - "description": "List of IP access control rules", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/IpAccessControlResponse" - } - } - } - } - }, - "401": { - "description": "Unauthorized", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "403": { - "description": "Insufficient permissions", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "post": { - "tags": [ - "IP Access Control" - ], - "summary": "Create a new IP access control rule", - "operationId": "create_ip_access_control", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateIpAccessControlRequest" - } - } - }, - "required": true - }, - "responses": { - "201": { - "description": "IP access control rule created", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/IpAccessControlResponse" - } - } - } - }, - "400": { - "description": "Invalid request", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "401": { - "description": "Unauthorized", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "403": { - "description": "Insufficient permissions", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "409": { - "description": "Duplicate IP address", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/ip-access-control/check/{ip}": { - "get": { - "tags": [ - "IP Access Control" - ], - "summary": "Check if an IP address is blocked", - "operationId": "check_ip_blocked", - "parameters": [ - { - "name": "ip", - "in": "path", - "description": "IP address to check", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "IP block status" - }, - "401": { - "description": "Unauthorized", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "403": { - "description": "Insufficient permissions", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/ip-access-control/{id}": { - "get": { - "tags": [ - "IP Access Control" - ], - "summary": "Get a single IP access control rule by ID", - "operationId": "get_ip_access_control", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "IP access control rule ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "IP access control rule details", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/IpAccessControlResponse" - } - } - } - }, - "401": { - "description": "Unauthorized", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "403": { - "description": "Insufficient permissions", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "404": { - "description": "IP access control rule not found", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "delete": { - "tags": [ - "IP Access Control" - ], - "summary": "Delete an IP access control rule", - "operationId": "delete_ip_access_control", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "IP access control rule ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "204": { - "description": "IP access control rule deleted" - }, - "401": { - "description": "Unauthorized", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "403": { - "description": "Insufficient permissions", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "404": { - "description": "IP access control rule not found", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "patch": { - "tags": [ - "IP Access Control" - ], - "summary": "Update an IP access control rule", - "operationId": "update_ip_access_control", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "IP access control rule ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdateIpAccessControlRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "IP access control rule updated", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/IpAccessControlResponse" - } - } - } - }, - "400": { - "description": "Invalid request", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "401": { - "description": "Unauthorized", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "403": { - "description": "Insufficient permissions", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "404": { - "description": "IP access control rule not found", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/kv/del": { - "post": { - "tags": [ - "KV Store" - ], - "summary": "Delete one or more keys", - "operationId": "kv_del", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/DelRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Keys deleted", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/DelResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/kv/disable": { - "delete": { - "tags": [ - "KV Management" - ], - "summary": "Disable KV service", - "operationId": "kv_disable", - "responses": { - "200": { - "description": "KV service disabled", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/DisableKvResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "404": { - "description": "KV service not enabled" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/kv/enable": { - "post": { - "tags": [ - "KV Management" - ], - "summary": "Enable KV service", - "operationId": "kv_enable", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/EnableKvRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "KV service enabled", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/EnableKvResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/kv/expire": { - "post": { - "tags": [ - "KV Store" - ], - "summary": "Set expiration on a key", - "operationId": "kv_expire", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ExpireRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Expiration set", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ExpireResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/kv/get": { - "post": { - "tags": [ - "KV Store" - ], - "summary": "Get a value by key", - "operationId": "kv_get", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/GetRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Value retrieved", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/GetResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/kv/incr": { - "post": { - "tags": [ - "KV Store" - ], - "summary": "Increment a numeric value", - "operationId": "kv_incr", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/IncrRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Value incremented", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/IncrResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/kv/keys": { - "post": { - "tags": [ - "KV Store" - ], - "summary": "Get keys matching a pattern", - "operationId": "kv_keys", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/KeysRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Keys retrieved", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/KeysResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/kv/set": { - "post": { - "tags": [ - "KV Store" - ], - "summary": "Set a value with optional expiration", - "operationId": "kv_set", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SetRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Value set", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SetResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/kv/status": { - "get": { - "tags": [ - "KV Management" - ], - "summary": "Get KV service status", - "operationId": "kv_status", - "responses": { - "200": { - "description": "KV service status", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/KvStatusResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/kv/ttl": { - "post": { - "tags": [ - "KV Store" - ], - "summary": "Get time-to-live for a key", - "operationId": "kv_ttl", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/TtlRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "TTL retrieved", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/TtlResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/kv/update": { - "patch": { - "tags": [ - "KV Management" - ], - "summary": "Update KV service configuration", - "operationId": "kv_update", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdateKvRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "KV service updated", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdateKvResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "404": { - "description": "KV service not enabled" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/lb/routes": { - "get": { - "tags": [ - "Load Balancer" - ], - "operationId": "list_routes", - "responses": { - "200": { - "description": "List of routes", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/RouteResponse" - } - } - } - } - }, - "500": { - "description": "Internal server error" - } - } - }, - "post": { - "tags": [ - "Load Balancer" - ], - "operationId": "create_route", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateRouteRequest" - } - } - }, - "required": true - }, - "responses": { - "201": { - "description": "Route created successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/RouteResponse" - } - } - } - }, - "400": { - "description": "Invalid request" - } - } - } - }, - "/lb/routes/{domain}": { - "get": { - "tags": [ - "Load Balancer" - ], - "operationId": "get_route", - "parameters": [ - { - "name": "domain", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Route found", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/RouteResponse" - } - } - } - }, - "404": { - "description": "Route not found" - } - } - }, - "put": { - "tags": [ - "Load Balancer" - ], - "operationId": "update_route", - "parameters": [ - { - "name": "domain", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdateRouteRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Route updated successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/RouteResponse" - } - } - } - }, - "404": { - "description": "Route not found" - } - } - }, - "delete": { - "tags": [ - "Load Balancer" - ], - "operationId": "delete_route", - "parameters": [ - { - "name": "domain", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "204": { - "description": "Route deleted successfully" - }, - "404": { - "description": "Route not found" - } - } - } - }, - "/logout": { - "post": { - "tags": [ - "Authentication" - ], - "operationId": "logout", - "responses": { - "200": { - "description": "Successfully logged out" - }, - "401": { - "description": "Unauthorized" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "session_token": [] - } - ] - } - }, - "/logs/context": { - "get": { - "tags": [ - "Logs" - ], - "summary": "Get context lines surrounding a specific log line", - "operationId": "get_log_context", - "parameters": [ - { - "name": "chunk_id", - "in": "query", - "description": "Chunk ID", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "line_offset", - "in": "query", - "description": "Line offset within the chunk", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "lines", - "in": "query", - "description": "Context lines before and after (default: 25)", - "required": false, - "schema": { - "type": "integer", - "format": "int32", - "minimum": 0 - } - } - ], - "responses": { - "200": { - "description": "Context lines", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ContextLogsResponse" - } - } - } - }, - "400": { - "description": "Invalid parameters", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "401": { - "description": "Unauthorized", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "404": { - "description": "Chunk not found", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/logs/search": { - "post": { - "tags": [ - "Logs" - ], - "summary": "Search logs with structured filters and full text search", - "operationId": "search_logs", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SearchLogsRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Search results", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SearchLogsResponse" - } - } - } - }, - "400": { - "description": "Invalid search parameters", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "401": { - "description": "Unauthorized", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/logs/tail": { - "get": { - "tags": [ - "Logs" - ], - "summary": "Live tail logs via Server-Sent Events", - "operationId": "tail_logs", - "parameters": [ - { - "name": "project_id", - "in": "query", - "description": "Project ID", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "service", - "in": "query", - "description": "Service name", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "env", - "in": "query", - "description": "Environment", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "levels", - "in": "query", - "description": "Optional level filters", - "required": true, - "schema": { - "type": "array", - "items": { - "type": "string" - } - } - }, - { - "name": "text", - "in": "query", - "description": "Optional text filter", - "required": false, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "SSE stream of log lines" - }, - "401": { - "description": "Unauthorized", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/monitors-health/projects": { - "get": { - "tags": [ - "Status Page" - ], - "summary": "Get monitor-based health summaries for multiple projects in a single query", - "operationId": "get_projects_monitor_health", - "parameters": [ - { - "name": "project_ids", - "in": "query", - "description": "Comma-separated list of project IDs", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Health summaries per project", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProjectsMonitorHealthResponse" - } - } - } - }, - "400": { - "description": "Invalid parameters" - }, - "401": { - "description": "Unauthorized" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/monitors/{monitor_id}": { - "get": { - "tags": [ - "Status Page" - ], - "summary": "Get a monitor by ID", - "operationId": "get_monitor", - "parameters": [ - { - "name": "monitor_id", - "in": "path", - "description": "Monitor ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Successfully retrieved monitor", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/MonitorResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "404": { - "description": "Monitor not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "delete": { - "tags": [ - "Status Page" - ], - "summary": "Delete a monitor", - "operationId": "delete_monitor", - "parameters": [ - { - "name": "monitor_id", - "in": "path", - "description": "Monitor ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "204": { - "description": "Monitor deleted successfully" - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "404": { - "description": "Monitor not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/monitors/{monitor_id}/bucketed": { - "get": { - "tags": [ - "Status Page" - ], - "summary": "Get bucketed status data for a monitor using TimescaleDB", - "operationId": "get_bucketed_status", - "parameters": [ - { - "name": "monitor_id", - "in": "path", - "description": "Monitor ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "interval", - "in": "query", - "description": "Bucket interval: '5min', 'hourly', or 'daily' (default: hourly)", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "start_time", - "in": "query", - "description": "Start time (ISO 8601) (default: 24 hours ago)", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "end_time", - "in": "query", - "description": "End time (ISO 8601) (default: now)", - "required": false, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Successfully retrieved bucketed status data", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/StatusBucketedResponse" - } - } - } - }, - "400": { - "description": "Invalid parameters" - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "404": { - "description": "Monitor not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/monitors/{monitor_id}/current-status": { - "get": { - "tags": [ - "Status Page" - ], - "summary": "Get current status and uptime metrics for a monitor", - "operationId": "get_current_monitor_status", - "parameters": [ - { - "name": "monitor_id", - "in": "path", - "description": "Monitor ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "start_time", - "in": "query", - "description": "Custom start time (ISO 8601) - overrides timeframe", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "end_time", - "in": "query", - "description": "Custom end time (ISO 8601)", - "required": false, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Successfully retrieved current status", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CurrentStatusResponse" - } - } - } - }, - "400": { - "description": "Invalid time parameters" - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "404": { - "description": "Monitor not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/monitors/{monitor_id}/uptime": { - "get": { - "tags": [ - "Status Page" - ], - "summary": "Get uptime history for a monitor", - "operationId": "get_uptime_history", - "parameters": [ - { - "name": "monitor_id", - "in": "path", - "description": "Monitor ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "days", - "in": "query", - "description": "Number of days of history (default: 60) - ignored if start_time/end_time provided", - "required": false, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "start_time", - "in": "query", - "description": "Start time (ISO 8601) - overrides days parameter", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "end_time", - "in": "query", - "description": "End time (ISO 8601) - defaults to now", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Successfully retrieved uptime history", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UptimeHistoryResponse" - } - } - } - }, - "400": { - "description": "Invalid time parameters" - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "404": { - "description": "Monitor not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/nodes/{id}/metrics": { - "get": { - "tags": [ - "Metrics" - ], - "summary": "Fetch a time-series range for a single metric on a node.", - "operationId": "NodeMetricsGetRange", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "Node ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "metric", - "in": "query", - "description": "Metric name, e.g. `\"pg.connections_active\"`.", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "range", - "in": "query", - "description": "Time window: `\"1h\"` | `\"6h\"` | `\"24h\"` | `\"7d\"`.", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "percentile", - "in": "query", - "description": "Optional histogram percentile (0\u2013100). When provided, the endpoint\nfetches histogram buckets and computes the requested quantile.", - "required": false, - "schema": { - "type": [ - "number", - "null" - ], - "format": "double" - } - } - ], - "responses": { - "200": { - "description": "Metric time series data points", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/MetricDataPoint" - } - } - } - } - }, - "400": { - "description": "Invalid query parameters" - }, - "401": { - "description": "Unauthorized" - }, - "500": { - "description": "Internal server error" - }, - "503": { - "description": "Metrics store not available" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/notification-preferences": { - "get": { - "tags": [ - "Notification Preferences" - ], - "summary": "Get notification preferences", - "operationId": "get_preferences", - "responses": { - "200": { - "description": "Successfully retrieved preferences", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/NotificationPreferencesResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "put": { - "tags": [ - "Notification Preferences" - ], - "summary": "Update notification preferences", - "operationId": "update_preferences", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdatePreferencesRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Successfully updated preferences", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/NotificationPreferencesResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "delete": { - "tags": [ - "Notification Preferences" - ], - "summary": "Delete notification preferences", - "operationId": "delete_preferences", - "responses": { - "204": { - "description": "Successfully deleted preferences" - }, - "401": { - "description": "Unauthorized" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/notification-providers": { - "get": { - "tags": [ - "Notification Providers" - ], - "summary": "List all notification providers", - "operationId": "list_notification_providers", - "parameters": [ - { - "name": "page", - "in": "query", - "description": "Page number (1-indexed)", - "required": false, - "schema": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "minimum": 0 - }, - "example": 1 - }, - { - "name": "page_size", - "in": "query", - "description": "Number of items per page (max 100)", - "required": false, - "schema": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "minimum": 0 - }, - "example": 20 - }, - { - "name": "sort_by", - "in": "query", - "required": false, - "schema": { - "type": [ - "string", - "null" - ] - } - }, - { - "name": "sort_order", - "in": "query", - "required": false, - "schema": { - "type": [ - "string", - "null" - ] - } - } - ], - "responses": { - "200": { - "description": "Successfully retrieved providers", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/NotificationProviderResponse" - } - } - } - } - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "post": { - "tags": [ - "Notification Providers" - ], - "summary": "Create a new notification provider", - "operationId": "create_notification_provider", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateProviderRequest" - } - } - }, - "required": true - }, - "responses": { - "201": { - "description": "Successfully created provider", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/NotificationProviderResponse" - } - } - } - }, - "400": { - "description": "Invalid request" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/notification-providers/cloudflare": { - "post": { - "tags": [ - "Notification Providers" - ], - "summary": "Create a new Cloudflare Email Sending notification provider", - "operationId": "create_cloudflare_provider", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateCloudflareProviderRequest" - } - } - }, - "required": true - }, - "responses": { - "201": { - "description": "Successfully created Cloudflare provider", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/NotificationProviderResponse" - } - } - } - }, - "400": { - "description": "Invalid request" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/notification-providers/cloudflare/{id}": { - "put": { - "tags": [ - "Notification Providers" - ], - "summary": "Update a Cloudflare Email Sending notification provider", - "operationId": "update_cloudflare_provider", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "Provider ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdateCloudflareProviderRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Successfully updated Cloudflare provider", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/NotificationProviderResponse" - } - } - } - }, - "404": { - "description": "Provider not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/notification-providers/email": { - "post": { - "tags": [ - "Notification Providers" - ], - "summary": "Create a new Email notification provider", - "operationId": "create_notification_email_provider", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateNotificationEmailProviderRequest" - } - } - }, - "required": true - }, - "responses": { - "201": { - "description": "Successfully created Email provider", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/NotificationProviderResponse" - } - } - } - }, - "400": { - "description": "Invalid request" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/notification-providers/email/{id}": { - "put": { - "tags": [ - "Notification Providers" - ], - "summary": "Update an Email notification provider", - "operationId": "update_notification_email_provider", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "Provider ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdateNotificationEmailProviderRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Successfully updated Email provider", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/NotificationProviderResponse" - } - } - } - }, - "404": { - "description": "Provider not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/notification-providers/slack": { - "post": { - "tags": [ - "Notification Providers" - ], - "summary": "Create a new Slack notification provider", - "operationId": "create_slack_provider", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateSlackProviderRequest" - } - } - }, - "required": true - }, - "responses": { - "201": { - "description": "Successfully created Slack provider", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/NotificationProviderResponse" - } - } - } - }, - "400": { - "description": "Invalid request" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/notification-providers/slack/{id}": { - "put": { - "tags": [ - "Notification Providers" - ], - "summary": "Update a Slack notification provider", - "operationId": "update_slack_provider", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "Provider ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdateSlackProviderRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Successfully updated Slack provider", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/NotificationProviderResponse" - } - } - } - }, - "404": { - "description": "Provider not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/notification-providers/webhook": { - "post": { - "tags": [ - "Notification Providers" - ], - "summary": "Create a new Webhook notification provider", - "description": "Webhook providers send notifications as JSON payloads to any HTTP endpoint.\nYou can configure custom headers for authentication (Bearer tokens, API keys, etc.).\nThe webhook will receive a JSON payload with notification details including:\nid, title, message, type, priority, severity, timestamp, and metadata.", - "operationId": "create_webhook_provider", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateWebhookProviderRequest" - } - } - }, - "required": true - }, - "responses": { - "201": { - "description": "Successfully created Webhook provider", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/NotificationProviderResponse" - } - } - } - }, - "400": { - "description": "Invalid request" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/notification-providers/webhook/{id}": { - "put": { - "tags": [ - "Notification Providers" - ], - "summary": "Update a Webhook notification provider", - "operationId": "update_webhook_provider", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "Provider ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdateWebhookProviderRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Successfully updated Webhook provider", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/NotificationProviderResponse" - } - } - } - }, - "404": { - "description": "Provider not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/notification-providers/{id}": { - "get": { - "tags": [ - "Notification Providers" - ], - "summary": "Get a single notification provider", - "operationId": "get_notification_provider", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "Provider ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Successfully retrieved provider", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/NotificationProviderResponse" - } - } - } - }, - "404": { - "description": "Provider not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "put": { - "tags": [ - "Notification Providers" - ], - "summary": "Update a notification provider", - "operationId": "update_notification_provider", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "Provider ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdateProviderRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Successfully updated provider", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/NotificationProviderResponse" - } - } - } - }, - "400": { - "description": "Invalid masked provider configuration" - }, - "404": { - "description": "Provider not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "delete": { - "tags": [ - "Notification Providers" - ], - "summary": "Delete a notification provider", - "operationId": "delete_notification_provider", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "Provider ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "204": { - "description": "Successfully deleted provider" - }, - "404": { - "description": "Provider not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/notification-providers/{id}/config/{field}": { - "get": { - "tags": [ - "Notification Providers" - ], - "operationId": "reveal_notification_provider_config", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "Provider ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "field", - "in": "path", - "description": "Sensitive field, such as password or headers.Authorization", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Sensitive provider configuration value", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SensitiveConfigValueResponse" - } - } - } - }, - "400": { - "description": "Field is not revealable" - }, - "403": { - "description": "Missing secrets:read permission" - }, - "404": { - "description": "Provider or field not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/notification-providers/{id}/test": { - "post": { - "tags": [ - "Notification Providers" - ], - "summary": "Test a notification provider", - "operationId": "test_notification_provider", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "Provider ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Test result", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/TestProviderResponse" - } - } - } - }, - "404": { - "description": "Provider not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/orders": { - "get": { - "tags": [ - "Domains" - ], - "summary": "List all ACME orders", - "operationId": "list_orders", - "parameters": [ - { - "name": "page", - "in": "query", - "description": "Page number (1-indexed)", - "required": false, - "schema": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "minimum": 0 - }, - "example": 1 - }, - { - "name": "page_size", - "in": "query", - "description": "Number of items per page (max 100)", - "required": false, - "schema": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "minimum": 0 - }, - "example": 20 - }, - { - "name": "sort_by", - "in": "query", - "required": false, - "schema": { - "type": [ - "string", - "null" - ] - } - }, - { - "name": "sort_order", - "in": "query", - "required": false, - "schema": { - "type": [ - "string", - "null" - ] - } - } - ], - "responses": { - "200": { - "description": "Orders retrieved successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ListOrdersResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/otel/alerts": { - "get": { - "tags": [ - "Alerts" - ], - "summary": "List alert rules for a project (newest first, paginated).", - "operationId": "list_alerts", - "parameters": [ - { - "name": "project_id", - "in": "query", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "page", - "in": "query", - "description": "Page number (default: 1)", - "required": false, - "schema": { - "type": "integer", - "format": "int64", - "minimum": 0 - } - }, - { - "name": "page_size", - "in": "query", - "description": "Page size (default: 20, max: 100)", - "required": false, - "schema": { - "type": "integer", - "format": "int64", - "minimum": 0 - } - } - ], - "responses": { - "200": { - "description": "Alert rules for the project", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/OtelMetricAlertsResponse" - } - } - } - }, - "401": { - "description": "Unauthorized", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "403": { - "description": "Insufficient permissions", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "post": { - "tags": [ - "Alerts" - ], - "summary": "Create a new alert rule for a project.", - "operationId": "create_alert", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateMetricAlertRequest" - } - } - }, - "required": true - }, - "responses": { - "201": { - "description": "Alert rule created", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/OtelMetricAlertRuleResponse" - } - } - } - }, - "400": { - "description": "Validation error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "401": { - "description": "Unauthorized", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "403": { - "description": "Insufficient permissions", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/otel/alerts/preview": { - "post": { - "tags": [ - "Alerts" - ], - "summary": "Backtest an anomaly detector over a time range without saving a rule.", - "description": "Replays the metric against the same band the evaluator would use, returning\nthe per-bucket band + which points would have fired. Powers the form's\n\"would this have fired?\" preview and the explorer band overlay. Read-only.", - "operationId": "preview_alert", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AnomalyPreviewRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Per-bucket band + breach points", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AnomalyPreviewResponse" - } - } - } - }, - "400": { - "description": "Not an anomaly detector / bad input", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "401": { - "description": "Unauthorized", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "403": { - "description": "Insufficient permissions", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/otel/alerts/{id}": { - "get": { - "tags": [ - "Alerts" - ], - "summary": "Fetch a single alert rule by id.", - "operationId": "get_alert", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "Alert rule ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "project_id", - "in": "query", - "description": "Owning project ID (scopes the lookup)", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Alert rule", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/OtelMetricAlertRuleResponse" - } - } - } - }, - "401": { - "description": "Unauthorized", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "403": { - "description": "Insufficient permissions", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "404": { - "description": "Alert rule not found", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "delete": { - "tags": [ - "Alerts" - ], - "summary": "Delete an alert rule.", - "operationId": "delete_alert", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "Alert rule ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "project_id", - "in": "query", - "description": "Owning project ID (scopes the delete)", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "204": { - "description": "Alert rule deleted" - }, - "401": { - "description": "Unauthorized", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "403": { - "description": "Insufficient permissions", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "404": { - "description": "Alert rule not found", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "patch": { - "tags": [ - "Alerts" - ], - "summary": "Update an alert rule's fields.", - "operationId": "update_alert", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "Alert rule ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "project_id", - "in": "query", - "description": "Owning project ID (scopes the update)", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdateMetricAlertRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Alert rule updated", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/OtelMetricAlertRuleResponse" - } - } - } - }, - "400": { - "description": "Validation error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "401": { - "description": "Unauthorized", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "403": { - "description": "Insufficient permissions", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "404": { - "description": "Alert rule not found", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/otel/dashboards": { - "get": { - "tags": [ - "Dashboards" - ], - "summary": "List dashboards for a project (newest first, paginated).", - "operationId": "list_dashboards", - "parameters": [ - { - "name": "project_id", - "in": "query", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "page", - "in": "query", - "description": "Page number (default: 1)", - "required": false, - "schema": { - "type": "integer", - "format": "int64", - "minimum": 0 - } - }, - { - "name": "page_size", - "in": "query", - "description": "Page size (default: 20, max: 100)", - "required": false, - "schema": { - "type": "integer", - "format": "int64", - "minimum": 0 - } - } - ], - "responses": { - "200": { - "description": "Dashboards for the project", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/OtelDashboardsResponse" - } - } - } - }, - "401": { - "description": "Unauthorized", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "403": { - "description": "Insufficient permissions", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "post": { - "tags": [ - "Dashboards" - ], - "summary": "Create a new dashboard for a project.", - "operationId": "create_dashboard", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateDashboardRequest" - } - } - }, - "required": true - }, - "responses": { - "201": { - "description": "Dashboard created", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/OtelDashboardResponse" - } - } - } - }, - "400": { - "description": "Validation error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "401": { - "description": "Unauthorized", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "403": { - "description": "Insufficient permissions", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/otel/dashboards/{id}": { - "get": { - "tags": [ - "Dashboards" - ], - "summary": "Fetch a single dashboard by id.", - "operationId": "get_dashboard", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "Dashboard ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "project_id", - "in": "query", - "description": "Owning project ID (scopes the lookup)", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Dashboard", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/OtelDashboardResponse" - } - } - } - }, - "401": { - "description": "Unauthorized", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "403": { - "description": "Insufficient permissions", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "404": { - "description": "Dashboard not found", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "delete": { - "tags": [ - "Dashboards" - ], - "summary": "Delete a dashboard.", - "operationId": "delete_dashboard", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "Dashboard ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "project_id", - "in": "query", - "description": "Owning project ID (scopes the delete)", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "204": { - "description": "Dashboard deleted" - }, - "401": { - "description": "Unauthorized", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "403": { - "description": "Insufficient permissions", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "404": { - "description": "Dashboard not found", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "patch": { - "tags": [ - "Dashboards" - ], - "summary": "Update a dashboard's name and/or layout.", - "operationId": "update_dashboard", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "Dashboard ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "project_id", - "in": "query", - "description": "Owning project ID (scopes the update)", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdateDashboardRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Dashboard updated", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/OtelDashboardResponse" - } - } - } - }, - "400": { - "description": "Validation error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "401": { - "description": "Unauthorized", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "403": { - "description": "Insufficient permissions", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "404": { - "description": "Dashboard not found", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/otel/genai/traces": { - "get": { - "tags": [ - "GenAI" - ], - "summary": "Query GenAI trace summaries \u2014 traces containing spans with `gen_ai.*` attributes.", - "description": "`duration_ms` is the only field guaranteed to be milliseconds. `gen_ai.*`\nspan attributes (e.g. time-to-first-token, token latency) often follow the\nOTel GenAI semantic conventions, which use **seconds** (a fractional\ndouble), not milliseconds \u2014 do not read them as ms without converting.", - "operationId": "query_genai_traces", - "parameters": [ - { - "name": "project_id", - "in": "query", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "service_name", - "in": "query", - "description": "Filter by service name", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "gen_ai_system", - "in": "query", - "description": "Filter by AI system (openai, anthropic, etc.)", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "gen_ai_model", - "in": "query", - "description": "Filter by model (gpt-4, claude-sonnet-4-20250514, etc.)", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "start_time", - "in": "query", - "description": "Start time (RFC 3339)", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "end_time", - "in": "query", - "description": "End time (RFC 3339)", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "limit", - "in": "query", - "description": "Max traces to return (default: 50, max: 100)", - "required": false, - "schema": { - "type": "integer", - "format": "int64", - "minimum": 0 - } - }, - { - "name": "offset", - "in": "query", - "description": "Offset for pagination", - "required": false, - "schema": { - "type": "integer", - "format": "int64", - "minimum": 0 - } - } - ], - "responses": { - "200": { - "description": "GenAI trace summaries", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/GenAiTraceSummariesResponse" - } - } - } - }, - "401": { - "description": "Unauthorized", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "403": { - "description": "Insufficient permissions", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/otel/genai/traces/{project_id}/{trace_id}": { - "get": { - "tags": [ - "GenAI" - ], - "summary": "Get GenAI span details for a specific trace.", - "description": "`duration_ms` is the only field guaranteed to be milliseconds. `gen_ai.*`\nspan attributes (e.g. time-to-first-token, token latency) often follow the\nOTel GenAI semantic conventions, which use **seconds** (a fractional\ndouble), not milliseconds \u2014 do not read them as ms without converting.", - "operationId": "get_genai_trace", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "trace_id", - "in": "path", - "description": "Trace ID (hex)", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "GenAI trace span details", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/GenAiTraceDetailResponse" - } - } - } - }, - "401": { - "description": "Unauthorized", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "403": { - "description": "Insufficient permissions", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/otel/global/traces/{trace_id}": { - "get": { - "tags": [ - "Traces" - ], - "summary": "Assemble a unified cross-project span waterfall (Phase 2).", - "description": "Fans out to every project that holds spans for `trace_id` (up to 20\nprojects, 10,000 total spans). Spans are annotated with\n`project_id`/`project_name` and sorted by `start_time ASC`.\n`truncated: true` signals a hit on either cap; `truncated_projects`\nlists the dropped project IDs. See ADR-027 \u00a74 for the full design.", - "operationId": "getUnifiedTrace", - "parameters": [ - { - "name": "trace_id", - "in": "path", - "description": "Trace ID (32 lowercase hex characters)", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Unified cross-project trace waterfall", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UnifiedTrace" - } - } - } - }, - "400": { - "description": "trace_id is not 32 lowercase hex characters", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "401": { - "description": "Unauthorized", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "403": { - "description": "Insufficient permissions or deployment token", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/otel/health/{project_id}": { - "get": { - "tags": [ - "OTel" - ], - "summary": "Get health summaries for a project.", - "operationId": "get_health", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "environment_id", - "in": "query", - "description": "Filter by environment ID", - "required": false, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Health summaries", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HealthResponse" - } - } - } - }, - "401": { - "description": "Unauthorized", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "403": { - "description": "Insufficient permissions", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/otel/insights/{project_id}": { - "get": { - "tags": [ - "Insights" - ], - "summary": "List anomaly insights for a project.", - "operationId": "list_insights", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "status", - "in": "query", - "description": "Filter by status (active, resolved)", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "limit", - "in": "query", - "description": "Max insights to return (default: 20, max: 100)", - "required": false, - "schema": { - "type": "integer", - "format": "int64", - "minimum": 0 - } - }, - { - "name": "offset", - "in": "query", - "description": "Offset for pagination", - "required": false, - "schema": { - "type": "integer", - "format": "int64", - "minimum": 0 - } - } - ], - "responses": { - "200": { - "description": "Insights list", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/InsightsResponse" - } - } - } - }, - "401": { - "description": "Unauthorized", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "403": { - "description": "Insufficient permissions", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/otel/logs": { - "get": { - "tags": [ - "Telemetry Logs" - ], - "summary": "Query log records with optional filters.", - "operationId": "query_logs", - "parameters": [ - { - "name": "project_id", - "in": "query", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "severity", - "in": "query", - "description": "Filter by severity (TRACE, DEBUG, INFO, WARN, ERROR, FATAL)", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "service_name", - "in": "query", - "description": "Filter by service name", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "search", - "in": "query", - "description": "Full-text search in log body (ILIKE)", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "trace_id", - "in": "query", - "description": "Filter by correlated trace ID", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "start_time", - "in": "query", - "description": "Start time (RFC 3339)", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "end_time", - "in": "query", - "description": "End time (RFC 3339)", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "limit", - "in": "query", - "description": "Max logs to return (default: 100, max: 1000)", - "required": false, - "schema": { - "type": "integer", - "format": "int64", - "minimum": 0 - } - }, - { - "name": "offset", - "in": "query", - "description": "Offset for pagination", - "required": false, - "schema": { - "type": "integer", - "format": "int64", - "minimum": 0 - } - } - ], - "responses": { - "200": { - "description": "Log records", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LogsResponse" - } - } - } - }, - "401": { - "description": "Unauthorized", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "403": { - "description": "Insufficient permissions", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/otel/metric-label-keys": { - "get": { - "tags": [ - "Telemetry Metrics" - ], - "summary": "List the attribute (label) keys observed on a metric \u2014 powers the\nlabel-filter key autocomplete.", - "operationId": "list_metric_label_keys", - "parameters": [ - { - "name": "project_id", - "in": "query", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "metric_name", - "in": "query", - "description": "Metric to inspect", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "start_time", - "in": "query", - "description": "Window start (RFC 3339); defaults to 24h before end", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "end_time", - "in": "query", - "description": "Window end (RFC 3339); defaults to now", - "required": false, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Distinct label keys", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/OtelMetricLabelKeysResponse" - } - } - } - }, - "401": { - "description": "Unauthorized", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "403": { - "description": "Insufficient permissions", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/otel/metric-label-values": { - "get": { - "tags": [ - "Telemetry Metrics" - ], - "summary": "List the distinct values seen for a label key on a metric \u2014 powers value\nautocomplete once a key is chosen.", - "operationId": "list_metric_label_values", - "parameters": [ - { - "name": "project_id", - "in": "query", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "metric_name", - "in": "query", - "description": "Metric to inspect", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "label_key", - "in": "query", - "description": "Label key whose values to list (must match [a-zA-Z0-9_.:-])", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "start_time", - "in": "query", - "description": "Window start (RFC 3339); defaults to 24h before end", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "end_time", - "in": "query", - "description": "Window end (RFC 3339); defaults to now", - "required": false, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Distinct label values", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/OtelMetricLabelValuesResponse" - } - } - } - }, - "400": { - "description": "Invalid label key", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "401": { - "description": "Unauthorized", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "403": { - "description": "Insufficient permissions", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/otel/metric-names/{project_id}": { - "get": { - "tags": [ - "Telemetry Metrics" - ], - "summary": "List distinct metric names for a project.", - "operationId": "list_metric_names", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "List of metric names", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/OtelMetricNamesResponse" - } - } - } - }, - "401": { - "description": "Unauthorized", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "403": { - "description": "Insufficient permissions", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/otel/metrics": { - "get": { - "tags": [ - "Telemetry Metrics" - ], - "summary": "Query metrics with time bucketing.", - "operationId": "query_metrics", - "parameters": [ - { - "name": "project_id", - "in": "query", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "metric_name", - "in": "query", - "description": "Filter by metric name", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "service_name", - "in": "query", - "description": "Filter by service name", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "environment", - "in": "query", - "description": "Filter by deployment environment", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "start_time", - "in": "query", - "description": "Start time (RFC 3339)", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "end_time", - "in": "query", - "description": "End time (RFC 3339)", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "bucket_interval", - "in": "query", - "description": "Bucket interval (e.g. '1 hour', '5 minutes')", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "limit", - "in": "query", - "description": "Max buckets to return (default: 1000)", - "required": false, - "schema": { - "type": "integer", - "format": "int64", - "minimum": 0 - } - }, - { - "name": "metric_type", - "in": "query", - "description": "Filter by metric type (gauge, sum, histogram, exponential_histogram, summary)", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "aggregation", - "in": "query", - "description": "Per-bucket aggregation: avg (default), sum, min, max, count, rate, p50/p95/p99, quantile:0.95", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "label_filters", - "in": "query", - "description": "Comma-separated key=value data-point label filters (keys must match [a-zA-Z0-9_.:-])", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "group_by", - "in": "query", - "description": "Comma-separated label keys to group series by", - "required": false, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Metrics data", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/OtelMetricsResponse" - } - } - } - }, - "400": { - "description": "Invalid label key", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "401": { - "description": "Unauthorized", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "403": { - "description": "Insufficient permissions", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/otel/pipeline-stats": { - "get": { - "tags": [ - "OTel" - ], - "summary": "Get OTel pipeline statistics (admin/system view).", - "operationId": "get_pipeline_stats", - "responses": { - "200": { - "description": "Pipeline statistics", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/PipelineStatsResponse" - } - } - } - }, - "401": { - "description": "Unauthorized", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "403": { - "description": "Insufficient permissions", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/otel/quota/{project_id}": { - "get": { - "tags": [ - "OTel" - ], - "summary": "Get storage quota for a project.", - "operationId": "get_quota", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Storage quota", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/QuotaResponse" - } - } - } - }, - "401": { - "description": "Unauthorized", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "403": { - "description": "Insufficient permissions", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/otel/trace-summaries": { - "get": { - "tags": [ - "Traces" - ], - "summary": "Query trace summaries \u2014 one row per trace with span count, error count,\nroot span info, and proper trace-level pagination.", - "operationId": "query_trace_summaries", - "parameters": [ - { - "name": "project_id", - "in": "query", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "trace_id", - "in": "query", - "description": "Filter by trace ID", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "service_name", - "in": "query", - "description": "Filter by service name", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "status", - "in": "query", - "description": "Filter by status (OK, ERROR)", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "min_duration_ms", - "in": "query", - "description": "Minimum trace duration in ms", - "required": false, - "schema": { - "type": "number", - "format": "double" - } - }, - { - "name": "start_time", - "in": "query", - "description": "Start time (RFC 3339)", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "end_time", - "in": "query", - "description": "End time (RFC 3339)", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "environment_id", - "in": "query", - "description": "Filter by environment ID", - "required": false, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "deployment_id", - "in": "query", - "description": "Filter by deployment ID", - "required": false, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "name_pattern", - "in": "query", - "description": "Filter by span name pattern (ILIKE)", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "sort_by", - "in": "query", - "description": "Sort field: 'start_time' (default) or 'duration'", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "sort_order", - "in": "query", - "description": "Sort direction: 'asc' or 'desc' (default)", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "include_total", - "in": "query", - "description": "Compute the `total` count (default: true). Set false to skip the second aggregation when only the page is needed", - "required": false, - "schema": { - "type": "boolean" - } - }, - { - "name": "limit", - "in": "query", - "description": "Max traces to return (default: 50, max: 100)", - "required": false, - "schema": { - "type": "integer", - "format": "int64", - "minimum": 0 - } - }, - { - "name": "offset", - "in": "query", - "description": "Offset for pagination", - "required": false, - "schema": { - "type": "integer", - "format": "int64", - "minimum": 0 - } - } - ], - "responses": { - "200": { - "description": "Trace summaries", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/TraceSummariesResponse" - } - } - } - }, - "401": { - "description": "Unauthorized", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "403": { - "description": "Insufficient permissions", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/otel/traces": { - "get": { - "tags": [ - "Traces" - ], - "summary": "Query trace spans with optional filters.", - "description": "Each returned span has a `duration_ms` field (float, milliseconds) \u2014 this is\nthe ONLY field guaranteed to be in milliseconds. Spans also carry an\n`attributes` map of raw key/value pairs exactly as reported by the\ninstrumenting library: numeric attribute values may be seconds, milliseconds,\nmicroseconds, or nanoseconds depending on that library's convention, and\nnothing in this response labels the unit. Never assume an attribute's\nnumeric value shares `duration_ms`'s unit, and never state a duration in\nmilliseconds unless it came from a `duration_ms` field.", - "operationId": "query_traces", - "parameters": [ - { - "name": "project_id", - "in": "query", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "trace_id", - "in": "query", - "description": "Filter by trace ID", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "service_name", - "in": "query", - "description": "Filter by service name", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "status", - "in": "query", - "description": "Filter by status (OK, ERROR, UNSET)", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "min_duration_ms", - "in": "query", - "description": "Minimum span duration in ms", - "required": false, - "schema": { - "type": "number", - "format": "double" - } - }, - { - "name": "start_time", - "in": "query", - "description": "Start time (RFC 3339)", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "end_time", - "in": "query", - "description": "End time (RFC 3339)", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "environment_id", - "in": "query", - "description": "Filter by environment ID", - "required": false, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "deployment_id", - "in": "query", - "description": "Filter by deployment ID", - "required": false, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "limit", - "in": "query", - "description": "Max spans to return (default: 100, max: 1000)", - "required": false, - "schema": { - "type": "integer", - "format": "int64", - "minimum": 0 - } - }, - { - "name": "offset", - "in": "query", - "description": "Offset for pagination", - "required": false, - "schema": { - "type": "integer", - "format": "int64", - "minimum": 0 - } - } - ], - "responses": { - "200": { - "description": "Trace spans", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/TracesResponse" - } - } - } - }, - "401": { - "description": "Unauthorized", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "403": { - "description": "Insufficient permissions", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/otel/traces/cross-project/{trace_id}": { - "get": { - "tags": [ - "Traces" - ], - "summary": "Discover sibling projects that share the same `trace_id` (Phase 1 banner).", - "description": "Returns an empty `siblings` list when the trace is single-project \u2014 never\n404. Project names are included so the UI can render navigation links\nwithout a second round-trip. See ADR-027 \u00a73 for the full auth model and\ntopology-disclosure trade-offs.", - "operationId": "getCrossProjectTraceSiblings", - "parameters": [ - { - "name": "trace_id", - "in": "path", - "description": "Trace ID (32 lowercase hex characters)", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "exclude_project_id", - "in": "query", - "description": "Project ID to exclude (the caller's own project) so the UI does not render a self-link", - "required": false, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Sibling projects sharing this trace", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CrossProjectTraceResponse" - } - } - } - }, - "400": { - "description": "trace_id is not 32 lowercase hex characters", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "401": { - "description": "Unauthorized", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "403": { - "description": "Insufficient permissions or deployment token", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/otel/traces/{project_id}/{trace_id}": { - "get": { - "tags": [ - "Traces" - ], - "summary": "Get all spans for a specific trace.", - "description": "Each span has a `duration_ms` field (float, milliseconds) \u2014 the ONLY field\nguaranteed to be in milliseconds \u2014 plus an `attributes` map of raw\nkey/value pairs exactly as the instrumenting library reported them.\nNumeric attribute values (e.g. connection-pool wait times, queue delays)\nmay be in seconds, milliseconds, microseconds, or nanoseconds depending on\nthat library's own convention; this response never labels the unit. When\nexplaining what a span spent time on, only quote milliseconds from\n`duration_ms` (or from `start_time`/`end_time` deltas) \u2014 never assume a raw\nattribute number is already in milliseconds.", - "operationId": "get_trace", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "trace_id", - "in": "path", - "description": "Trace ID (hex)", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Trace spans tree", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/TracesResponse" - } - } - } - }, - "401": { - "description": "Unauthorized", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "403": { - "description": "Insufficient permissions", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/otel/v1/logs": { - "post": { - "tags": [ - "OTel Ingest" - ], - "summary": "Ingest log records via OTLP/HTTP protobuf.", - "description": "Authenticates via API key in header, decompresses, decodes protobuf,\nchecks rate limit and storage quota, routes high-severity logs\nto DB and all logs to S3.", - "operationId": "ingest_logs", - "requestBody": { - "description": "OTLP ExportLogsServiceRequest (protobuf, optionally gzip/zstd compressed)", - "content": { - "application/x-protobuf": { - "schema": { - "type": "string" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Logs accepted (OTLP protobuf response)" - }, - "400": { - "description": "Invalid payload", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "401": { - "description": "Missing or invalid API key", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "413": { - "description": "Storage quota exceeded", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "429": { - "description": "Rate limit exceeded", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "api_key": [] - } - ] - } - }, - "/otel/v1/metrics": { - "post": { - "tags": [ - "OTel Ingest" - ], - "summary": "Ingest metrics via OTLP/HTTP protobuf.", - "description": "Authenticates via API key in header, decompresses, decodes protobuf,\nchecks rate limit and storage quota, then stores.", - "operationId": "ingest_metrics", - "requestBody": { - "description": "OTLP ExportMetricsServiceRequest (protobuf, optionally gzip/zstd compressed)", - "content": { - "application/x-protobuf": { - "schema": { - "type": "string" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Metrics accepted (OTLP protobuf response)" - }, - "400": { - "description": "Invalid payload", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "401": { - "description": "Missing or invalid API key", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "413": { - "description": "Storage quota exceeded", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "429": { - "description": "Rate limit exceeded", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "api_key": [] - } - ] - } - }, - "/otel/v1/traces": { - "post": { - "tags": [ - "OTel Ingest" - ], - "summary": "Ingest trace spans via OTLP/HTTP protobuf.", - "description": "Authenticates via API key in header, decompresses, decodes protobuf,\nchecks rate limit and storage quota, then stores spans.", - "operationId": "ingest_traces", - "requestBody": { - "description": "OTLP ExportTraceServiceRequest (protobuf, optionally gzip/zstd compressed)", - "content": { - "application/x-protobuf": { - "schema": { - "type": "string" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Traces accepted (OTLP protobuf response)" - }, - "400": { - "description": "Invalid payload", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "401": { - "description": "Missing or invalid API key", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "413": { - "description": "Storage quota exceeded", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "429": { - "description": "Rate limit exceeded", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "api_key": [] - } - ] - } - }, - "/otel/v1/{project_id}/{environment_id}/{deployment_id}/logs": { - "post": { - "tags": [ - "OTel Ingest" - ], - "summary": "Ingest log records with project/environment/deployment in the URL path.", - "operationId": "ingest_logs_by_path", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "environment_id", - "in": "path", - "description": "Environment ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "deployment_id", - "in": "path", - "description": "Deployment ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "requestBody": { - "description": "OTLP ExportLogsServiceRequest (protobuf, optionally gzip/zstd compressed)", - "content": { - "application/x-protobuf": { - "schema": { - "type": "string" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Logs accepted (OTLP protobuf response)" - }, - "400": { - "description": "Invalid payload", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "401": { - "description": "Missing or invalid API key", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "413": { - "description": "Storage quota exceeded", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "429": { - "description": "Rate limit exceeded", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "api_key": [] - } - ] - } - }, - "/otel/v1/{project_id}/{environment_id}/{deployment_id}/metrics": { - "post": { - "tags": [ - "OTel Ingest" - ], - "summary": "Ingest metrics with project/environment/deployment in the URL path.", - "operationId": "ingest_metrics_by_path", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "environment_id", - "in": "path", - "description": "Environment ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "deployment_id", - "in": "path", - "description": "Deployment ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "requestBody": { - "description": "OTLP ExportMetricsServiceRequest (protobuf, optionally gzip/zstd compressed)", - "content": { - "application/x-protobuf": { - "schema": { - "type": "string" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Metrics accepted (OTLP protobuf response)" - }, - "400": { - "description": "Invalid payload", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "401": { - "description": "Missing or invalid API key", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "413": { - "description": "Storage quota exceeded", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "429": { - "description": "Rate limit exceeded", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "api_key": [] - } - ] - } - }, - "/otel/v1/{project_id}/{environment_id}/{deployment_id}/traces": { - "post": { - "tags": [ - "OTel Ingest" - ], - "summary": "Ingest trace spans with project/environment/deployment in the URL path.", - "operationId": "ingest_traces_by_path", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "environment_id", - "in": "path", - "description": "Environment ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "deployment_id", - "in": "path", - "description": "Deployment ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "requestBody": { - "description": "OTLP ExportTraceServiceRequest (protobuf, optionally gzip/zstd compressed)", - "content": { - "application/x-protobuf": { - "schema": { - "type": "string" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Traces accepted (OTLP protobuf response)" - }, - "400": { - "description": "Invalid payload", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "401": { - "description": "Missing or invalid API key", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "413": { - "description": "Storage quota exceeded", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "429": { - "description": "Rate limit exceeded", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "api_key": [] - } - ] - } - }, - "/performance/has-metrics": { - "get": { - "tags": [ - "Performance" - ], - "summary": "Check if performance metrics exist for a project", - "operationId": "has_performance_metrics", - "parameters": [ - { - "name": "project_id", - "in": "query", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Successfully checked performance metrics availability", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HasMetricsResponse" - } - } - } - }, - "401": { - "description": "Authentication required", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - }, - "403": { - "description": "Insufficient permissions", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/performance/metrics": { - "get": { - "tags": [ - "Performance" - ], - "summary": "Get performance metrics", - "operationId": "get_performance_metrics", - "parameters": [ - { - "name": "start_date", - "in": "query", - "description": "Start date in format YYYY-MM-DD HH:MM:SS", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "end_date", - "in": "query", - "description": "End date in format YYYY-MM-DD HH:MM:SS", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "project_id", - "in": "query", - "description": "Project ID or slug", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "environment_id", - "in": "query", - "description": "Environment ID (optional)", - "required": false, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "deployment_id", - "in": "query", - "description": "Deployment ID (optional)", - "required": false, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "device_type", - "in": "query", - "description": "Device type filter: desktop or mobile (optional)", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "include_bots", - "in": "query", - "description": "Include crawler/datacenter bot samples (default false)", - "required": false, - "schema": { - "type": "boolean" - } - }, - { - "name": "filter_path", - "in": "query", - "description": "Filter to one page pathname (optional)", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "filter_country", - "in": "query", - "description": "Filter to one country (optional)", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "filter_region", - "in": "query", - "description": "Filter to one region (optional)", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "filter_city", - "in": "query", - "description": "Filter to one city (optional)", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "filter_browser", - "in": "query", - "description": "Filter to one browser (optional)", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "filter_operating_system", - "in": "query", - "description": "Filter to one operating system (optional)", - "required": false, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Successfully retrieved performance metrics", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/PerformanceMetricsResponse" - } - } - } - }, - "400": { - "description": "Invalid date format or missing parameters", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - }, - "401": { - "description": "Authentication required", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - }, - "403": { - "description": "Insufficient permissions", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/performance/metrics-over-time": { - "get": { - "tags": [ - "Performance" - ], - "summary": "Get metrics over time", - "operationId": "get_metrics_over_time", - "parameters": [ - { - "name": "start_date", - "in": "query", - "description": "Start date in format YYYY-MM-DDTHH:MM:SSZ", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "end_date", - "in": "query", - "description": "End date in format YYYY-MM-DDTHH:MM:SSZ", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "project_id", - "in": "query", - "description": "Project ID or slug", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "environment_id", - "in": "query", - "description": "Environment ID (optional)", - "required": false, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "deployment_id", - "in": "query", - "description": "Deployment ID (optional)", - "required": false, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "device_type", - "in": "query", - "description": "Device type filter: desktop or mobile (optional)", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "include_bots", - "in": "query", - "description": "Include crawler/datacenter bot samples (default false)", - "required": false, - "schema": { - "type": "boolean" - } - }, - { - "name": "filter_path", - "in": "query", - "description": "Filter to one page pathname (optional)", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "filter_country", - "in": "query", - "description": "Filter to one country (optional)", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "filter_region", - "in": "query", - "description": "Filter to one region (optional)", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "filter_city", - "in": "query", - "description": "Filter to one city (optional)", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "filter_browser", - "in": "query", - "description": "Filter to one browser (optional)", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "filter_operating_system", - "in": "query", - "description": "Filter to one operating system (optional)", - "required": false, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Successfully retrieved metrics over time", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/MetricsOverTimeResponse" - } - } - } - }, - "400": { - "description": "Invalid date format or missing parameters", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - }, - "401": { - "description": "Authentication required", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - }, - "403": { - "description": "Insufficient permissions", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/performance/page-metrics": { - "get": { - "tags": [ - "Performance" - ], - "summary": "Get grouped page metrics", - "operationId": "get_grouped_page_metrics", - "parameters": [ - { - "name": "start_date", - "in": "query", - "description": "Start date in format YYYY-MM-DDTHH:MM:SSZ", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "end_date", - "in": "query", - "description": "End date in format YYYY-MM-DDTHH:MM:SSZ", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "project_id", - "in": "query", - "description": "Project ID or slug", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "environment_id", - "in": "query", - "description": "Environment ID (optional)", - "required": false, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "deployment_id", - "in": "query", - "description": "Deployment ID (optional)", - "required": false, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "group_by", - "in": "query", - "description": "Group by: path, country, region, city, device_type, browser, operating_system", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "device_type", - "in": "query", - "description": "Device type filter: desktop or mobile (optional)", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "include_bots", - "in": "query", - "description": "Include crawler/datacenter bot samples (default false)", - "required": false, - "schema": { - "type": "boolean" - } - }, - { - "name": "filter_path", - "in": "query", - "description": "Filter to one page pathname (optional)", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "filter_country", - "in": "query", - "description": "Filter to one country (optional)", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "filter_region", - "in": "query", - "description": "Filter to one region (optional)", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "filter_city", - "in": "query", - "description": "Filter to one city (optional)", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "filter_browser", - "in": "query", - "description": "Filter to one browser (optional)", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "filter_operating_system", - "in": "query", - "description": "Filter to one operating system (optional)", - "required": false, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Successfully retrieved grouped page metrics", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/GroupedPageMetricsResponse" - } - } - } - }, - "400": { - "description": "Invalid date format, missing parameters, or invalid group_by value", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - }, - "401": { - "description": "Authentication required", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - }, - "403": { - "description": "Insufficient permissions", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/platform/access-info": { - "get": { - "tags": [ - "Platform" - ], - "summary": "Get information about how the service is being accessed", - "description": "Returns details about the server's access mode, public IP address, private IP address,\nand domain creation capabilities. Both IP addresses are always included when available.", - "operationId": "get_access_info", - "responses": { - "200": { - "description": "Service access information", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ServiceAccessInfo" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/platform/private-ip": { - "get": { - "tags": [ - "Platform" - ], - "summary": "Get private/local IP address of the server", - "operationId": "get_private_ip", - "responses": { - "200": { - "description": "Successfully retrieved private IP address" - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/platform/public-ip": { - "get": { - "tags": [ - "Platform" - ], - "summary": "Get public IP address of the server", - "operationId": "get_public_ip", - "responses": { - "200": { - "description": "Successfully retrieved public IP address" - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/presets": { - "get": { - "tags": [ - "Presets" - ], - "summary": "List all available presets", - "operationId": "list_presets", - "responses": { - "200": { - "description": "List of available presets", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ListPresetsResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/presets/{slug}/dockerfile": { - "post": { - "tags": [ - "Presets" - ], - "summary": "Generate a Dockerfile from a preset", - "description": "Returns the Dockerfile content and build arguments for a given preset slug.\nThe CLI can use this to build Docker images locally without needing a Dockerfile\nin the project directory, enabling zero-config deployments.", - "operationId": "generate_preset_dockerfile", - "parameters": [ - { - "name": "slug", - "in": "path", - "description": "Preset slug (e.g., nextjs, vite, python)", - "required": true, - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/GenerateDockerfileRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Generated Dockerfile", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/GenerateDockerfileResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "404": { - "description": "Preset not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/preview-gateway/logs": { - "get": { - "tags": [ - "Preview Gateway" - ], - "operationId": "get_preview_gateway_logs", - "parameters": [ - { - "name": "tail", - "in": "query", - "description": "Lines to tail (default 200, max 2000)", - "required": false, - "schema": { - "type": "integer", - "minimum": 0 - } - } - ], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LogsResponse" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/preview-gateway/restart": { - "post": { - "tags": [ - "Preview Gateway" - ], - "operationId": "restart_preview_gateway", - "responses": { - "204": { - "description": "Gateway restarted" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/preview-gateway/settings": { - "get": { - "tags": [ - "Preview Gateway" - ], - "operationId": "get_preview_gateway_settings", - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/PreviewGatewaySettingsResponse" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "patch": { - "tags": [ - "Preview Gateway" - ], - "operationId": "patch_preview_gateway_settings", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/PatchSettingsRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/PreviewGatewaySettingsResponse" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/preview-gateway/status": { - "get": { - "tags": [ - "Preview Gateway" - ], - "operationId": "get_preview_gateway_status", - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/GatewayStatus" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/preview-gateway/upgrade": { - "post": { - "tags": [ - "Preview Gateway" - ], - "operationId": "upgrade_preview_gateway", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpgradeRequest" - } - } - }, - "required": true - }, - "responses": { - "204": { - "description": "Gateway upgraded" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects": { - "get": { - "tags": [ - "Projects" - ], - "summary": "Get a list of all projects", - "operationId": "get_projects", - "parameters": [ - { - "name": "page", - "in": "query", - "description": "Page number (1-based)", - "required": false, - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "per_page", - "in": "query", - "description": "Number of items per page", - "required": false, - "schema": { - "type": "integer", - "format": "int64" - } - } - ], - "responses": { - "200": { - "description": "List of projects", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/PaginatedProjectList" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "post": { - "tags": [ - "Projects" - ], - "summary": "Create a new project", - "operationId": "create_project", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateProjectRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Project created successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProjectResponse" - } - } - } - }, - "400": { - "description": "Invalid input" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/by-slug/{slug}": { - "get": { - "tags": [ - "Projects" - ], - "summary": "Get details of a specific project by slug", - "operationId": "get_project_by_slug", - "parameters": [ - { - "name": "slug", - "in": "path", - "description": "Project slug", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Project details", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProjectResponse" - } - } - } - }, - "404": { - "description": "Project not found" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/from-template": { - "post": { - "tags": [ - "Projects" - ], - "summary": "Create a new project from a template", - "description": "Creates a new repository from a template and sets up the project with the\nspecified configuration. The template is cloned to a new repository under\nthe authenticated user's account or specified organization.", - "operationId": "create_project_from_template", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateProjectFromTemplateRequest" - } - } - }, - "required": true - }, - "responses": { - "201": { - "description": "Project created successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateProjectFromTemplateResponse" - } - } - } - }, - "400": { - "description": "Invalid input" - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "404": { - "description": "Template not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/statistics": { - "get": { - "tags": [ - "Projects" - ], - "summary": "Get project statistics", - "operationId": "get_project_statistics", - "responses": { - "200": { - "description": "Project statistics", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProjectStatisticsResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{id}": { - "get": { - "tags": [ - "Projects" - ], - "summary": "Get details of a specific project", - "operationId": "get_project", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Project details", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProjectResponse" - } - } - } - }, - "404": { - "description": "Project not found" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "put": { - "tags": [ - "Projects" - ], - "operationId": "update_project", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateProjectRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Project updated successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProjectResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Forbidden" - }, - "404": { - "description": "Project not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "delete": { - "tags": [ - "Projects" - ], - "operationId": "delete_project", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "204": { - "description": "Project deleted successfully" - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Forbidden" - }, - "404": { - "description": "Project not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{id}/deployments": { - "get": { - "tags": [ - "Projects" - ], - "operationId": "get_project_deployments", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "page", - "in": "query", - "description": "Page number", - "required": false, - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "per_page", - "in": "query", - "description": "Items per page", - "required": false, - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "environment_id", - "in": "query", - "description": "Environment ID filter", - "required": false, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "List of deployments", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/DeploymentListResponse" - } - } - } - }, - "404": { - "description": "Project not found" - } - } - } - }, - "/projects/{id}/last-deployment": { - "get": { - "tags": [ - "Deployments" - ], - "summary": "Get the last deployment for a specific project", - "operationId": "get_last_deployment", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Last deployment details", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/DeploymentResponse" - } - } - } - }, - "404": { - "description": "Project not found or no deployments" - }, - "500": { - "description": "Internal server error" - } - } - } - }, - "/projects/{id}/source": { - "patch": { - "tags": [ - "Projects" - ], - "summary": "Change a project's source type to a Git-less type (docker_image /\nstatic_files / manual). Switching TO Git is done via the Git settings\nendpoint (`POST /projects/{id}/git`), which also supplies the repository and\nprovider connection.", - "operationId": "change_project_source", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ChangeProjectSourceRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Source type changed", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProjectResponse" - } - } - } - }, - "400": { - "description": "Invalid source type change (e.g. switching to Git here)" - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Forbidden" - }, - "404": { - "description": "Project not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{id}/trigger-pipeline": { - "post": { - "tags": [ - "Projects" - ], - "summary": "Trigger pipeline for a specific project", - "operationId": "trigger_project_pipeline", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/TriggerPipelinePayload" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Pipeline triggered successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/TriggerPipelineResponse" - } - } - } - }, - "400": { - "description": "Invalid request" - }, - "404": { - "description": "Project not found" - }, - "500": { - "description": "Internal server error" - } - } - } - }, - "/projects/{project_id}/access": { - "get": { - "tags": [ - "Teams" - ], - "operationId": "list_project_access", - "parameters": [ - { - "name": "project_id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Access grants", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ProjectAccessResponse" - } - } - } - } - }, - "403": { - "description": "Insufficient permissions or no access to this project" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "post": { - "tags": [ - "Teams" - ], - "operationId": "grant_project_access", - "parameters": [ - { - "name": "project_id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateProjectAccessRequest" - } - } - }, - "required": true - }, - "responses": { - "201": { - "description": "Access granted (idempotent upsert)", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProjectAccessResponse" - } - } - } - }, - "403": { - "description": "Insufficient permissions or no access to this project" - }, - "404": { - "description": "Team not found" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/access/{team_id}": { - "delete": { - "tags": [ - "Teams" - ], - "operationId": "revoke_project_access", - "parameters": [ - { - "name": "project_id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "team_id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "204": { - "description": "Access revoked" - }, - "403": { - "description": "Insufficient permissions or no access to this project" - }, - "404": { - "description": "Grant not found" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/active-visitors": { - "get": { - "tags": [ - "Events" - ], - "summary": "Get active visitors count", - "operationId": "get_active_visitors", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "environment_id", - "in": "query", - "description": "Filter by environment ID", - "required": false, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "deployment_id", - "in": "query", - "description": "Filter by deployment ID", - "required": false, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Successfully retrieved active visitors count", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ActiveVisitorsResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/agents": { - "get": { - "tags": [ - "Agents" - ], - "operationId": "list_agents", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "List of agents for project", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ListAgentsResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "post": { - "tags": [ - "Agents" - ], - "operationId": "create_agent", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpsertAgentRequest" - } - } - }, - "required": true - }, - "responses": { - "201": { - "description": "Agent created", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AgentConfigResponse" - } - } - } - }, - "400": { - "description": "Validation error" - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/agents/cli-status": { - "get": { - "tags": [ - "Agents" - ], - "operationId": "get_cli_status", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "provider", - "in": "query", - "description": "AI provider: claude_cli or codex_cli", - "required": false, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "CLI status" - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/agents/runs": { - "get": { - "tags": [ - "Agents" - ], - "operationId": "list_all_runs", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "page", - "in": "query", - "description": "Page number (1-based)", - "required": false, - "schema": { - "type": "integer", - "format": "int64", - "minimum": 0 - } - }, - { - "name": "page_size", - "in": "query", - "description": "Page size (max 100)", - "required": false, - "schema": { - "type": "integer", - "format": "int64", - "minimum": 0 - } - } - ], - "responses": { - "200": { - "description": "List of all agent runs for a project", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ListRunsResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/agents/runs/latest-for-source": { - "get": { - "tags": [ - "Agents" - ], - "operationId": "latest_run_for_source", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "trigger_source_type", - "in": "query", - "description": "Trigger source type, e.g. 'error_group'", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "trigger_source_id", - "in": "query", - "description": "Trigger source ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Latest matching run, or null if none", - "content": { - "application/json": { - "schema": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/AgentRunResponse" - } - ] - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/agents/runs/{run_id}": { - "get": { - "tags": [ - "Agents" - ], - "operationId": "get_run_with_logs", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "run_id", - "in": "path", - "description": "Run ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Run with logs", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AgentRunWithLogsResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "404": { - "description": "Run not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/agents/runs/{run_id}/cancel": { - "post": { - "tags": [ - "Agents" - ], - "operationId": "cancel_run", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "run_id", - "in": "path", - "description": "Agent run ID to cancel", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Run cancelled", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AgentRunResponse" - } - } - } - }, - "400": { - "description": "Run is already in a terminal state" - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "404": { - "description": "Run not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/agents/runs/{run_id}/retry": { - "post": { - "tags": [ - "Agents" - ], - "summary": "Retry a completed, failed, cancelled, or no_fix run with the same trigger context.\nCreates a new run record and spawns the executor.", - "operationId": "retry_run", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "run_id", - "in": "path", - "description": "Run ID to retry", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "202": { - "description": "New run created from retry", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AgentRunResponse" - } - } - } - }, - "400": { - "description": "Run is still active" - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "404": { - "description": "Run not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/agents/runs/{run_id}/stream": { - "get": { - "tags": [ - "Agents" - ], - "summary": "SSE endpoint for real-time streaming of run events.\nPolls the agent_run_logs table every 500ms for new entries and streams them.\nCloses when the run reaches a terminal status.", - "operationId": "stream_run_events", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "run_id", - "in": "path", - "description": "Agent run ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Server-Sent Events stream of run log events and terminal status", - "content": { - "text/event-stream": {} - } - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "404": { - "description": "Run not found" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/agents/sandbox-status": { - "get": { - "tags": [ - "Agents" - ], - "operationId": "get_sandbox_status", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Project-scoped sandbox readiness (Docker + agent image)", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SandboxStatusResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/agents/smoke-test": { - "post": { - "tags": [ - "Agents" - ], - "summary": "Run a smoke test to verify the selected AI CLI works in the environment\nwhere agents will actually execute (host or sandbox container). If no\n`provider_id` is supplied the globally active provider is tested.", - "operationId": "smoke_test_agent", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "provider_id", - "in": "query", - "description": "Provider id to test; defaults to the globally active provider", - "required": false, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Smoke test result for the AI CLI in the agent's execution environment", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SmokeTestResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/agents/{slug}": { - "get": { - "tags": [ - "Agents" - ], - "operationId": "get_agent", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "slug", - "in": "path", - "description": "Agent slug", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Agent config", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AgentConfigResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "404": { - "description": "Agent not found" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "put": { - "tags": [ - "Agents" - ], - "operationId": "update_agent", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "slug", - "in": "path", - "description": "Agent slug", - "required": true, - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpsertAgentRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Agent updated", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AgentConfigResponse" - } - } - } - }, - "400": { - "description": "Validation error" - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "404": { - "description": "Agent not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "delete": { - "tags": [ - "Agents" - ], - "operationId": "delete_agent", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "slug", - "in": "path", - "description": "Agent slug", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "204": { - "description": "Agent deleted" - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "404": { - "description": "Agent not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/agents/{slug}/runs": { - "get": { - "tags": [ - "Agents" - ], - "operationId": "list_agent_runs", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "slug", - "in": "path", - "description": "Agent slug", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "page", - "in": "query", - "description": "Page number (1-based)", - "required": false, - "schema": { - "type": "integer", - "format": "int64", - "minimum": 0 - } - }, - { - "name": "page_size", - "in": "query", - "description": "Page size (max 100)", - "required": false, - "schema": { - "type": "integer", - "format": "int64", - "minimum": 0 - } - } - ], - "responses": { - "200": { - "description": "List of runs for a specific agent", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ListRunsResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "404": { - "description": "Agent not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/agents/{slug}/trigger": { - "post": { - "tags": [ - "Agents" - ], - "operationId": "trigger_agent", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "slug", - "in": "path", - "description": "Agent slug", - "required": true, - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/TriggerAgentRequest" - } - } - }, - "required": true - }, - "responses": { - "202": { - "description": "Agent run created and queued", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AgentRunResponse" - } - } - } - }, - "400": { - "description": "Validation error" - }, - "401": { - "description": "Unauthorized" - }, - "402": { - "description": "Daily budget exceeded" - }, - "403": { - "description": "Insufficient permissions" - }, - "404": { - "description": "Agent not found" - }, - "422": { - "description": "AI CLI not installed" - }, - "429": { - "description": "Cooldown active" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/aggregated-buckets": { - "get": { - "tags": [ - "Events" - ], - "summary": "Get aggregated metrics by time bucket", - "operationId": "get_aggregated_buckets", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "start_date", - "in": "query", - "description": "Start date for the query range", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "end_date", - "in": "query", - "description": "End date for the query range", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "environment_id", - "in": "query", - "description": "Optional environment filter", - "required": false, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "deployment_id", - "in": "query", - "description": "Optional deployment filter", - "required": false, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "aggregation_level", - "in": "query", - "description": "Aggregation level: events, sessions, or visitors (default: events)", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "bucket_size", - "in": "query", - "description": "Time bucket size: '1 hour', '1 day', '1 week', etc. (default: '1 hour')", - "required": false, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Successfully retrieved aggregated buckets", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AggregatedBucketsResponse" - } - } - } - }, - "400": { - "description": "Bad request" - }, - "401": { - "description": "Unauthorized" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/ai/conversations": { - "get": { - "tags": [ - "AI Chat" - ], - "summary": "Find the existing chat for a context (returns `null` if none yet). Requires\nthe per-project `ai_debug_chat_enabled` toggle to be on; returns 403 when the\nfeature is disabled so revoking it consistently hides existing chat content.", - "operationId": "find_conversation", - "parameters": [ - { - "name": "project_id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "context_type", - "in": "query", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "context_id", - "in": "query", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/ConversationResponse" - } - ] - } - } - } - }, - "401": { - "description": "" - }, - "403": { - "description": "" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "post": { - "tags": [ - "AI Chat" - ], - "summary": "Get-or-create the chat for a context (seeds it on first open).", - "operationId": "create_conversation", - "parameters": [ - { - "name": "project_id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateConversationRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ConversationResponse" - } - } - } - }, - "401": { - "description": "" - }, - "403": { - "description": "" - }, - "404": { - "description": "" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/ai/conversations/list": { - "get": { - "tags": [ - "AI Chat" - ], - "summary": "List all active conversations for a project, most-recently-active first.\nPowers the conversation switcher in the AI assistant sidebar.", - "operationId": "list_conversations", - "parameters": [ - { - "name": "project_id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ConversationResponse" - } - } - } - } - }, - "401": { - "description": "" - }, - "403": { - "description": "" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/ai/conversations/{public_id}": { - "get": { - "tags": [ - "AI Chat" - ], - "summary": "Full conversation history (excluding the internal system seed).", - "operationId": "get_conversation", - "parameters": [ - { - "name": "project_id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "public_id", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ConversationDetailResponse" - } - } - } - }, - "401": { - "description": "" - }, - "403": { - "description": "" - }, - "404": { - "description": "" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "patch": { - "tags": [ - "AI Chat" - ], - "summary": "Rename a conversation (set its human-facing title).", - "operationId": "rename_conversation", - "parameters": [ - { - "name": "project_id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "public_id", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/RenameConversationRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ConversationResponse" - } - } - } - }, - "400": { - "description": "" - }, - "401": { - "description": "" - }, - "403": { - "description": "" - }, - "404": { - "description": "" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/ai/conversations/{public_id}/archive": { - "post": { - "tags": [ - "AI Chat" - ], - "summary": "Archive (soft-delete) a conversation.", - "operationId": "archive_conversation", - "parameters": [ - { - "name": "project_id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "public_id", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "204": { - "description": "" - }, - "401": { - "description": "" - }, - "403": { - "description": "" - }, - "404": { - "description": "" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/ai/conversations/{public_id}/messages": { - "post": { - "tags": [ - "AI Chat" - ], - "summary": "Send a user message; stream the assistant reply as Server-Sent Events.", - "operationId": "send_message", - "parameters": [ - { - "name": "project_id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "public_id", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SendMessageRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "SSE stream of assistant text deltas", - "content": { - "text/event-stream": {} - } - }, - "401": { - "description": "" - }, - "403": { - "description": "" - }, - "404": { - "description": "" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/ai/conversations/{public_id}/pending-actions": { - "get": { - "tags": [ - "AI Chat" - ], - "summary": "List all pending actions for a conversation (most-recently-proposed first).", - "operationId": "list_pending_actions", - "parameters": [ - { - "name": "project_id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "public_id", - "in": "path", - "description": "Conversation public id", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/PendingActionResponse" - } - } - } - } - }, - "401": { - "description": "" - }, - "403": { - "description": "" - }, - "404": { - "description": "" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/ai/pending-actions/{action_public_id}": { - "get": { - "tags": [ - "AI Chat" - ], - "summary": "Get a single pending action by its public id (scoped to the project).", - "operationId": "get_pending_action", - "parameters": [ - { - "name": "project_id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "action_public_id", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/PendingActionResponse" - } - } - } - }, - "401": { - "description": "" - }, - "403": { - "description": "" - }, - "404": { - "description": "" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/ai/pending-actions/{action_public_id}/confirm": { - "post": { - "tags": [ - "AI Chat" - ], - "summary": "Confirm a proposed AI action: validate permission, atomically claim, execute,\npersist outcome. The execution uses the CONFIRMING user's auth \u2014 never the model's.", - "operationId": "confirm_pending_action", - "parameters": [ - { - "name": "project_id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "action_public_id", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/PendingActionResponse" - } - } - } - }, - "401": { - "description": "" - }, - "403": { - "description": "" - }, - "404": { - "description": "" - }, - "409": { - "description": "" - }, - "503": { - "description": "" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/ai/pending-actions/{action_public_id}/reject": { - "post": { - "tags": [ - "AI Chat" - ], - "summary": "Reject a proposed AI action (no execution). Status transitions to \"rejected\".", - "operationId": "reject_pending_action", - "parameters": [ - { - "name": "project_id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "action_public_id", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/PendingActionResponse" - } - } - } - }, - "401": { - "description": "" - }, - "403": { - "description": "" - }, - "404": { - "description": "" - }, - "409": { - "description": "" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/ai/readiness": { - "get": { - "tags": [ - "AI Chat" - ], - "summary": "Report which AI prerequisites this project satisfies.", - "description": "Read-only and cheap, so the UI can decide up front whether to show a working\nentry point, an onboarding path, or nothing \u2014 instead of letting the user\nclick something that fails with a 409 they can't act on.", - "operationId": "get_chat_readiness", - "parameters": [ - { - "name": "project_id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Which AI prerequisites are met", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ChatReadinessResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "404": { - "description": "Project not found" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/alarms": { - "get": { - "tags": [ - "Alarms" - ], - "summary": "List alarms for a project with optional filters.", - "operationId": "listProjectAlarms", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "alarm_type", - "in": "query", - "description": "Filter by alarm type (e.g. `container_restart`, `outage`).", - "required": false, - "schema": { - "type": [ - "string", - "null" - ] - } - }, - { - "name": "status", - "in": "query", - "description": "Filter by status: `firing`, `acknowledged`, or `resolved`.", - "required": false, - "schema": { - "type": [ - "string", - "null" - ] - } - }, - { - "name": "severity", - "in": "query", - "description": "Filter by severity: `info`, `warning`, or `critical`.", - "required": false, - "schema": { - "type": [ - "string", - "null" - ] - } - }, - { - "name": "environment_id", - "in": "query", - "description": "Filter by environment ID.", - "required": false, - "schema": { - "type": [ - "integer", - "null" - ], - "format": "int32" - } - }, - { - "name": "deployment_id", - "in": "query", - "description": "Filter by deployment ID.", - "required": false, - "schema": { - "type": [ - "integer", - "null" - ], - "format": "int32" - } - }, - { - "name": "service_id", - "in": "query", - "description": "Filter by external service ID.", - "required": false, - "schema": { - "type": [ - "integer", - "null" - ], - "format": "int32" - } - }, - { - "name": "page", - "in": "query", - "description": "Page number (1-based, default 1).", - "required": false, - "schema": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "minimum": 0 - } - }, - { - "name": "page_size", - "in": "query", - "description": "Items per page (default 20, max 100).", - "required": false, - "schema": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "minimum": 0 - } - } - ], - "responses": { - "200": { - "description": "Paginated list of alarms", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AlarmListResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/alarms/summary": { - "get": { - "tags": [ - "Alarms" - ], - "summary": "Get alarm counts by status/severity/type for a project (dashboard summary widget).", - "operationId": "getProjectAlarmsSummary", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Alarm summary counts", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AlarmSummaryResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/alarms/{alarm_id}/acknowledge": { - "post": { - "tags": [ - "Alarms" - ], - "summary": "Acknowledge a firing alarm (marks it as seen but not resolved).", - "operationId": "acknowledgeAlarm", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "alarm_id", - "in": "path", - "description": "Alarm ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Alarm acknowledged" - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "404": { - "description": "Alarm not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/alarms/{alarm_id}/resolve": { - "post": { - "tags": [ - "Alarms" - ], - "summary": "Resolve an alarm.", - "operationId": "resolveAlarm", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "alarm_id", - "in": "path", - "description": "Alarm ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Alarm resolved" - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "404": { - "description": "Alarm not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/autofixer/analyze": { - "post": { - "tags": [ - "Autofixer" - ], - "summary": "Start an autofixer analysis run for the given error group.\nCreates the run record immediately and spawns analysis in the background.", - "operationId": "start_analysis", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/StartAnalysisRequest" - } - } - }, - "required": true - }, - "responses": { - "202": { - "description": "Analysis started; returns run_id for streaming", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AutofixerRunResponse" - } - } - } - }, - "400": { - "description": "Validation error" - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/autofixer/runs/{run_id}": { - "get": { - "tags": [ - "Autofixer" - ], - "summary": "Get a single autofixer run with its logs.", - "operationId": "get_run", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "run_id", - "in": "path", - "description": "Run ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Run with logs", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AutofixerRunWithLogsResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "404": { - "description": "Run not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/autofixer/runs/{run_id}/add-context": { - "post": { - "tags": [ - "Autofixer" - ], - "summary": "Append a user message to the run's context field.", - "operationId": "add_context", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "run_id", - "in": "path", - "description": "Run ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AddContextRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Context appended" - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "404": { - "description": "Run not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/autofixer/runs/{run_id}/cancel": { - "post": { - "tags": [ - "Autofixer" - ], - "summary": "Cancel an autofixer run and clean up the work directory.", - "operationId": "cancel", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "run_id", - "in": "path", - "description": "Run ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Run cancelled" - }, - "400": { - "description": "Run is already in a terminal state" - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "404": { - "description": "Run not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/autofixer/runs/{run_id}/create-pr": { - "post": { - "tags": [ - "Autofixer" - ], - "summary": "Push the fix branch and create a pull request.\nRequires phase == \"fix_ready\".", - "operationId": "create_pr", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "run_id", - "in": "path", - "description": "Run ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "201": { - "description": "PR created", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreatePrResponse" - } - } - } - }, - "400": { - "description": "Run not in fix_ready phase" - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "404": { - "description": "Run not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/autofixer/runs/{run_id}/fix": { - "post": { - "tags": [ - "Autofixer" - ], - "summary": "Transition from analysis to fix phase.\nRequires phase == \"analyzed\".", - "operationId": "start_fix", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "run_id", - "in": "path", - "description": "Run ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "202": { - "description": "Fix generation started" - }, - "400": { - "description": "Run not in analyzed phase" - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "404": { - "description": "Run not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/autofixer/runs/{run_id}/re-analyze": { - "post": { - "tags": [ - "Autofixer" - ], - "summary": "Continue the conversation with user feedback.\nUses the same Claude session (--continue) in the existing work directory.\nRequires phase == \"analyzed\".", - "operationId": "re_analyze", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "run_id", - "in": "path", - "description": "Run ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "202": { - "description": "Conversation continued with feedback" - }, - "400": { - "description": "Run not in analyzed phase" - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "404": { - "description": "Run not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/autofixer/runs/{run_id}/stream": { - "get": { - "tags": [ - "Agents" - ], - "summary": "SSE endpoint: streams run log events in real-time.\nPolls every 500 ms. Keeps the connection open through \"analyzed\" and \"fix_ready\"\nwaiting states; closes only on terminal statuses.", - "operationId": "stream_events", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "run_id", - "in": "path", - "description": "Autofixer run ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Server-Sent Events stream of autofixer run logs and status updates", - "content": { - "text/event-stream": {} - } - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "404": { - "description": "Run not found" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/automatic-deploy": { - "post": { - "tags": [ - "Projects" - ], - "summary": "Update automatic deployment setting for a project", - "operationId": "update_automatic_deploy", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdateAutomaticDeployRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Automatic deployment setting updated successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProjectResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Forbidden" - }, - "404": { - "description": "Project not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/custom-domains": { - "get": { - "tags": [ - "Custom Domains" - ], - "summary": "List all custom domains for a project", - "operationId": "list_custom_domains_for_project", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Custom domains retrieved successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ListCustomDomainsResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "post": { - "tags": [ - "Custom Domains" - ], - "summary": "Create a custom domain for a project", - "operationId": "create_custom_domain", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CustomDomainRequest" - } - } - }, - "required": true - }, - "responses": { - "201": { - "description": "Custom domain created successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CustomDomainResponse" - } - } - } - }, - "400": { - "description": "Invalid input" - }, - "401": { - "description": "Unauthorized" - }, - "409": { - "description": "Domain already exists" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/custom-domains/{domain_id}": { - "get": { - "tags": [ - "Custom Domains" - ], - "summary": "Get a custom domain by ID", - "operationId": "get_custom_domain", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "domain_id", - "in": "path", - "description": "Custom domain ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Custom domain retrieved successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CustomDomainResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "404": { - "description": "Custom domain not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "put": { - "tags": [ - "Custom Domains" - ], - "summary": "Update a custom domain", - "operationId": "update_custom_domain", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "domain_id", - "in": "path", - "description": "Custom domain ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdateCustomDomainRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Custom domain updated successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CustomDomainResponse" - } - } - } - }, - "400": { - "description": "Invalid input" - }, - "401": { - "description": "Unauthorized" - }, - "404": { - "description": "Custom domain not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "delete": { - "tags": [ - "Custom Domains" - ], - "summary": "Delete a custom domain", - "operationId": "delete_custom_domain", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "domain_id", - "in": "path", - "description": "Custom domain ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "204": { - "description": "Custom domain deleted successfully" - }, - "401": { - "description": "Unauthorized" - }, - "404": { - "description": "Custom domain not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/custom-domains/{domain_id}/link-certificate/{certificate_id}": { - "post": { - "tags": [ - "Custom Domains" - ], - "summary": "Link a custom domain to a certificate", - "operationId": "link_custom_domain_to_certificate", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "domain_id", - "in": "path", - "description": "Custom domain ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "certificate_id", - "in": "path", - "description": "Certificate ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Custom domain linked to certificate successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CustomDomainResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "404": { - "description": "Custom domain or certificate not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/deployment-config": { - "patch": { - "tags": [ - "Projects" - ], - "summary": "Update deployment configuration for a project", - "operationId": "update_project_deployment_config", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdateDeploymentConfigRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Deployment configuration updated successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProjectResponse" - } - } - } - }, - "400": { - "description": "Invalid deployment configuration" - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Forbidden" - }, - "404": { - "description": "Project not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/deployment-tokens": { - "get": { - "tags": [ - "Deployment Tokens" - ], - "summary": "List all deployment tokens for a project", - "operationId": "list_deployment_tokens", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "page", - "in": "query", - "description": "Page number (default: 1)", - "required": false, - "schema": { - "type": "integer", - "format": "int64", - "minimum": 0 - } - }, - { - "name": "page_size", - "in": "query", - "description": "Page size (default: 20, max: 100)", - "required": false, - "schema": { - "type": "integer", - "format": "int64", - "minimum": 0 - } - } - ], - "responses": { - "200": { - "description": "List of deployment tokens", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/DeploymentTokenListResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "post": { - "tags": [ - "Deployment Tokens" - ], - "summary": "Create a new deployment token for a project", - "operationId": "create_deployment_token", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateDeploymentTokenRequest" - } - } - }, - "required": true - }, - "responses": { - "201": { - "description": "Deployment token created successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateDeploymentTokenResponse" - } - } - } - }, - "400": { - "description": "Invalid request" - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "409": { - "description": "Token with this name already exists" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/deployment-tokens/{token_id}": { - "get": { - "tags": [ - "Deployment Tokens" - ], - "summary": "Get a specific deployment token", - "operationId": "get_deployment_token", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "token_id", - "in": "path", - "description": "Deployment token ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Deployment token details", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/DeploymentTokenResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "404": { - "description": "Deployment token not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "delete": { - "tags": [ - "Deployment Tokens" - ], - "summary": "Delete a deployment token", - "operationId": "delete_deployment_token", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "token_id", - "in": "path", - "description": "Deployment token ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "204": { - "description": "Deployment token deleted successfully" - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "404": { - "description": "Deployment token not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "patch": { - "tags": [ - "Deployment Tokens" - ], - "summary": "Update a deployment token", - "operationId": "update_deployment_token", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "token_id", - "in": "path", - "description": "Deployment token ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdateDeploymentTokenRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Deployment token updated successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/DeploymentTokenResponse" - } - } - } - }, - "400": { - "description": "Invalid request" - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "404": { - "description": "Deployment token not found" - }, - "409": { - "description": "Token with this name already exists" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/deployment-tokens/{token_id}/rotate": { - "post": { - "tags": [ - "Deployment Tokens" - ], - "summary": "Rotate a deployment token, invalidating its old secret and issuing a new one", - "operationId": "rotate_deployment_token", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "token_id", - "in": "path", - "description": "Deployment token ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Deployment token rotated successfully; the response contains the new plaintext token, shown only once", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateDeploymentTokenResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "404": { - "description": "Deployment token not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/deployments/{deployment_id}": { - "get": { - "tags": [ - "Deployments" - ], - "summary": "Get a specific deployment by ID for a project (identified by ID or slug)", - "operationId": "get_deployment", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID or slug", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "deployment_id", - "in": "path", - "description": "Deployment ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Deployment details", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/DeploymentResponse" - } - } - } - }, - "404": { - "description": "Project or deployment not found" - }, - "500": { - "description": "Internal server error" - } - } - } - }, - "/projects/{project_id}/deployments/{deployment_id}/cancel": { - "post": { - "tags": [ - "Projects" - ], - "summary": "Cancel a deployment", - "operationId": "cancel_deployment", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID or slug", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "deployment_id", - "in": "path", - "description": "Deployment ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Deployment cancelled successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/DeploymentStateResponse" - } - } - } - }, - "400": { - "description": "Deployment cannot be cancelled (already completed, failed, or cancelled)" - }, - "404": { - "description": "Project or deployment not found" - }, - "500": { - "description": "Internal server error" - } - } - } - }, - "/projects/{project_id}/deployments/{deployment_id}/container-logs": { - "get": { - "tags": [ - "Deployments" - ], - "summary": "List the captured (historical) container-log dumps for a deployment.", - "description": "Container runtime logs are normally only available live from the running\ncontainer. When a deployment is superseded its containers are torn down and\nthose logs would be lost \u2014 so just before teardown we capture each\ncontainer's logs to durable storage. This endpoint lists what was captured\nfor a given (often older) deployment, so a user can read the logs of a\ncontainer that no longer exists.", - "operationId": "list_deployment_container_logs", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "deployment_id", - "in": "path", - "description": "Deployment ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Captured container logs for the deployment", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/DeploymentContainerLogsListResponse" - } - } - } - }, - "404": { - "description": "Deployment not found in this project" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_token": [] - } - ] - } - }, - "/projects/{project_id}/deployments/{deployment_id}/container-logs/{log_id}": { - "get": { - "tags": [ - "Deployments" - ], - "summary": "Get the captured text content of a single historical container-log dump.", - "operationId": "get_deployment_container_log_content", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "deployment_id", - "in": "path", - "description": "Deployment ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "log_id", - "in": "path", - "description": "Captured log ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Captured container log content", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/DeploymentContainerLogContentResponse" - } - } - } - }, - "404": { - "description": "Captured log not found in this project" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_token": [] - } - ] - } - }, - "/projects/{project_id}/deployments/{deployment_id}/jobs": { - "get": { - "tags": [ - "Deployments" - ], - "summary": "Get jobs for a specific deployment", - "description": "Returns all jobs (workflow tasks) for a deployment, ordered by execution order.\nThis replaces the old deployment stages endpoint.", - "operationId": "get_deployment_jobs", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "deployment_id", - "in": "path", - "description": "Deployment ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Jobs retrieved successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/DeploymentJobsResponse" - } - } - } - }, - "404": { - "description": "Deployment not found" - }, - "500": { - "description": "Internal server error" - } - } - } - }, - "/projects/{project_id}/deployments/{deployment_id}/jobs/{job_id}/logs": { - "get": { - "tags": [ - "Deployments" - ], - "summary": "Get logs for a specific deployment job", - "operationId": "get_deployment_job_logs", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "deployment_id", - "in": "path", - "description": "Deployment ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "job_id", - "in": "path", - "description": "Job ID", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Job logs retrieved successfully", - "content": { - "text/plain": { - "schema": { - "type": "string" - } - } - } - }, - "404": { - "description": "Job or logs not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_token": [] - } - ] - } - }, - "/projects/{project_id}/deployments/{deployment_id}/jobs/{job_id}/logs/tail": { - "get": { - "tags": [ - "Deployments" - ], - "summary": "Tail logs for a specific deployment job in real-time via WebSocket", - "description": "**WebSocket Streaming**: Logs are sent as raw text, one line per WebSocket message.\n\n**Authentication**: Requires authentication via session cookie (browser clients)\nor API key (API clients). For browser-based WebSocket connections, ensure the user\nis logged in - the browser automatically includes session cookies in the WebSocket\nupgrade request.\n\n**API Client Authentication**: Include API key in Authorization header:\n```text\nAuthorization: Bearer tk_your_api_key_here\n```", - "operationId": "tail_deployment_job_logs", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "deployment_id", - "in": "path", - "description": "Deployment ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "job_id", - "in": "path", - "description": "Job ID", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "101": { - "description": "WebSocket connection established for streaming deployment job logs" - }, - "404": { - "description": "Job or logs not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_token": [] - } - ] - } - }, - "/projects/{project_id}/deployments/{deployment_id}/operations": { - "get": { - "tags": [ - "Deployments" - ], - "summary": "Get all operations for a deployment", - "operationId": "get_deployment_operations", - "parameters": [ - { - "name": "project_id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "deployment_id", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "List of operations", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/OperationResultsResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "404": { - "description": "Deployment not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "post": { - "tags": [ - "Deployments" - ], - "summary": "Execute a deployment operation (deploy, mark_complete, take_screenshot)", - "operationId": "execute_deployment_operation", - "parameters": [ - { - "name": "project_id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "deployment_id", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ExecuteOperationRequest" - } - } - }, - "required": true - }, - "responses": { - "202": { - "description": "Operation executed", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/OperationResultResponse" - } - } - } - }, - "400": { - "description": "Invalid operation" - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "404": { - "description": "Deployment not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/deployments/{deployment_id}/operations/{operation_type}": { - "get": { - "tags": [ - "Deployments" - ], - "summary": "Get the status of a specific operation type", - "operationId": "get_deployment_operation_status", - "parameters": [ - { - "name": "project_id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "deployment_id", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "operation_type", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Operation status", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/OperationResultResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "404": { - "description": "Operation not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/deployments/{deployment_id}/pause": { - "post": { - "tags": [ - "Projects" - ], - "summary": "Pause a deployment", - "operationId": "pause_deployment", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID or slug", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "deployment_id", - "in": "path", - "description": "Deployment ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Deployment paused successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/DeploymentStateResponse" - } - } - } - }, - "404": { - "description": "Project or deployment not found" - }, - "500": { - "description": "Internal server error" - } - } - } - }, - "/projects/{project_id}/deployments/{deployment_id}/promote": { - "post": { - "tags": [ - "Deployments" - ], - "summary": "Promote a deployment to another environment", - "description": "Creates a new deployment in the target environment using the source deployment's\nDocker image. Useful for promoting a validated preview/staging deployment to production.", - "operationId": "promote_deployment", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "deployment_id", - "in": "path", - "description": "Source deployment ID to promote", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/PromoteDeploymentRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Promotion initiated successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/DeploymentResponse" - } - } - } - }, - "400": { - "description": "Invalid deployment state for promotion" - }, - "404": { - "description": "Project, deployment, or target environment not found" - }, - "500": { - "description": "Internal server error" - } - } - } - }, - "/projects/{project_id}/deployments/{deployment_id}/resume": { - "post": { - "tags": [ - "Projects" - ], - "summary": "Resume a deployment", - "operationId": "resume_deployment", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID or slug", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "deployment_id", - "in": "path", - "description": "Deployment ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Deployment resumed successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/DeploymentStateResponse" - } - } - } - }, - "404": { - "description": "Project or deployment not found" - }, - "500": { - "description": "Internal server error" - } - } - } - }, - "/projects/{project_id}/deployments/{deployment_id}/rollback": { - "post": { - "tags": [ - "Projects" - ], - "operationId": "rollback_to_deployment", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "deployment_id", - "in": "path", - "description": "Deployment ID to rollback to", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Rollback initiated successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/DeploymentResponse" - } - } - } - }, - "404": { - "description": "Project or deployment not found" - }, - "500": { - "description": "Internal server error" - } - } - } - }, - "/projects/{project_id}/deployments/{deployment_id}/teardown": { - "delete": { - "tags": [ - "Projects" - ], - "summary": "Teardown a specific deployment", - "operationId": "teardown_deployment", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID or slug", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "deployment_id", - "in": "path", - "description": "Deployment ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "204": { - "description": "Deployment torn down successfully" - }, - "404": { - "description": "Project or deployment not found" - }, - "500": { - "description": "Internal server error" - } - } - } - }, - "/projects/{project_id}/dsns": { - "get": { - "tags": [], - "summary": "List all DSNs for a project", - "operationId": "list_dsns", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "List of DSNs", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ProjectDSNResponse" - } - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "post": { - "tags": [], - "summary": "Create a new DSN for a project", - "operationId": "create_dsn", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateDSNRequest" - } - } - }, - "required": true - }, - "responses": { - "201": { - "description": "DSN created", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProjectDSNResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "404": { - "description": "Project not found" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/dsns/get-or-create": { - "post": { - "tags": [], - "summary": "Get or create DSN for a project/environment/deployment combination", - "operationId": "get_or_create_dsn", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/GetOrCreateDSNRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "DSN retrieved or created", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProjectDSNResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "404": { - "description": "Project not found" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/dsns/{dsn_id}/regenerate": { - "post": { - "tags": [], - "summary": "Regenerate DSN keys (rotate keys)", - "operationId": "regenerate_dsn", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "dsn_id", - "in": "path", - "description": "DSN ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/RegenerateDSNRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "DSN keys regenerated", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProjectDSNResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "404": { - "description": "DSN not found" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/dsns/{dsn_id}/revoke": { - "post": { - "tags": [], - "summary": "Revoke (deactivate) a DSN", - "operationId": "revoke_dsn", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "dsn_id", - "in": "path", - "description": "DSN ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "204": { - "description": "DSN revoked" - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "404": { - "description": "DSN not found" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/env-vars": { - "get": { - "tags": [ - "Projects" - ], - "summary": "Get environment variables for a project, optionally filtered by environment", - "operationId": "get_environment_variables", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID or slug", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "environment_id", - "in": "query", - "description": "Optional environment ID to filter by", - "required": false, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "List of environment variables", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/EnvironmentVariableResponse" - } - } - } - } - }, - "404": { - "description": "Project not found" - }, - "500": { - "description": "Internal server error" - } - } - }, - "post": { - "tags": [ - "Projects" - ], - "summary": "Create a new environment variable", - "operationId": "create_environment_variable", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID or slug", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateEnvironmentVariableRequest" - } - } - }, - "required": true - }, - "responses": { - "201": { - "description": "Environment variables created successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/EnvironmentVariableResponse" - } - } - } - }, - "400": { - "description": "Invalid input" - }, - "404": { - "description": "Project not found" - }, - "500": { - "description": "Internal server error" - } - } - } - }, - "/projects/{project_id}/env-vars/resolved": { - "get": { - "tags": [ - "Projects" - ], - "summary": "Resolved env vars for a project (manual + integration-sourced, merged).", - "description": "Returns the effective set of environment variables a deployment would see,\ncombining manually-defined vars with those contributed by linked external\nservices (Postgres, Redis, S3, etc.). Each entry is tagged with its source\nso the UI can render an integration icon, and manual entries that shadow an\nintegration key carry a reference to the integration they override.\n\nValues are always returned as a masked preview. Use the per-key reveal\nendpoint for plaintext (audit-logged).", - "operationId": "get_resolved_environment_variables", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID or slug", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "environment_id", - "in": "query", - "description": "Optional environment ID to filter manual vars by", - "required": false, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Resolved environment variables", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ResolvedEnvVarResponse" - } - } - } - } - }, - "404": { - "description": "Project not found" - }, - "500": { - "description": "Internal server error" - } - } - } - }, - "/projects/{project_id}/env-vars/resolved/{key}/value": { - "get": { - "tags": [ - "Projects" - ], - "summary": "Reveal the plaintext value of a resolved environment variable.", - "description": "Mirrors `GET /projects/{id}/env-vars/{key}/value` but handles keys sourced\nfrom linked integrations (which are not stored in the `env_vars` table).\nResolution order mirrors the merged view:\n\n1. Manual env var with this key \u2014 this endpoint reads the manual store when\n the key exists there, then writes its own reveal audit event so callers\n can safely use one endpoint regardless of source.\n2. Integration env var supplied by a linked external service.\n\nReturns 404 when neither a manual var nor an integration produces the key.", - "operationId": "get_resolved_environment_variable_value", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID or slug", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "key", - "in": "path", - "description": "Environment variable key", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "environment_id", - "in": "query", - "description": "Optional environment ID", - "required": false, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "var_id", - "in": "query", - "description": "Exact manual environment-variable row ID", - "required": false, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "service_id", - "in": "query", - "description": "Integration service ID shown by the resolved list", - "required": false, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Resolved environment variable value", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/EnvironmentVariableValueResponse" - } - } - } - }, - "403": { - "description": "Plaintext secret access is not permitted" - }, - "404": { - "description": "Project, key, or integration not found" - }, - "409": { - "description": "Environment variable key is ambiguous" - }, - "500": { - "description": "Internal server error" - } - } - } - }, - "/projects/{project_id}/env-vars/{key}/value": { - "get": { - "tags": [ - "Projects" - ], - "summary": "Get environment variable value by key", - "operationId": "get_environment_variable_value", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID or slug", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "key", - "in": "path", - "description": "Environment variable key", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "environment_id", - "in": "query", - "description": "Optional environment ID", - "required": false, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "var_id", - "in": "query", - "description": "Exact environment-variable row ID", - "required": false, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Environment variable value", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/EnvironmentVariableValueResponse" - } - } - } - }, - "403": { - "description": "Plaintext secret access is not permitted" - }, - "404": { - "description": "Project or variable not found" - }, - "409": { - "description": "Environment variable key is ambiguous" - }, - "500": { - "description": "Internal server error" - } - } - } - }, - "/projects/{project_id}/env-vars/{var_id}": { - "put": { - "tags": [ - "Projects" - ], - "summary": "Update an environment variable", - "operationId": "update_environment_variable", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID or slug", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "var_id", - "in": "path", - "description": "Environment variable ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdateEnvironmentVariableRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Environment variables updated successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/EnvironmentVariableResponse" - } - } - } - }, - "400": { - "description": "Invalid input" - }, - "404": { - "description": "Project or variable not found" - }, - "500": { - "description": "Internal server error" - } - } - }, - "delete": { - "tags": [ - "Projects" - ], - "summary": "Delete an environment variable", - "operationId": "delete_environment_variable", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID or slug", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "var_id", - "in": "path", - "description": "Environment variable ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "204": { - "description": "Environment variable deleted successfully" - }, - "404": { - "description": "Project or variable not found" - }, - "500": { - "description": "Internal server error" - } - } - } - }, - "/projects/{project_id}/environments": { - "get": { - "tags": [ - "Projects" - ], - "summary": "Get all environments for a project", - "operationId": "get_environments", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID or slug", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "List of environments", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/EnvironmentResponse" - } - } - } - } - }, - "404": { - "description": "Project not found" - }, - "500": { - "description": "Internal server error" - } - } - }, - "post": { - "tags": [ - "Projects" - ], - "summary": "Create a new environment for a project", - "operationId": "create_environment", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID or slug", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateEnvironmentRequest" - } - } - }, - "required": true - }, - "responses": { - "201": { - "description": "Environment created successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/EnvironmentResponse" - } - } - } - }, - "400": { - "description": "Invalid input" - }, - "404": { - "description": "Project not found" - }, - "500": { - "description": "Internal server error" - } - } - } - }, - "/projects/{project_id}/environments/{env_id}": { - "get": { - "tags": [ - "Projects" - ], - "summary": "Get a specific environment by ID or slug", - "operationId": "get_environment", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID or slug", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "env_id", - "in": "path", - "description": "Environment ID or slug", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Environment details", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/EnvironmentResponse" - } - } - } - }, - "404": { - "description": "Project or environment not found" - }, - "500": { - "description": "Internal server error" - } - } - }, - "delete": { - "tags": [ - "Projects" - ], - "summary": "Delete an environment permanently", - "description": "Permanently deletes an environment and all related data. Cannot delete:\n- Production environments (name = \"Production\")\n\nWarning: This action is permanent and cannot be undone.\nActive deployments are automatically cancelled before deletion.", - "operationId": "delete_environment", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "env_id", - "in": "path", - "description": "Environment ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "204": { - "description": "Environment permanently deleted" - }, - "400": { - "description": "Cannot delete production environment" - }, - "404": { - "description": "Project or environment not found" - }, - "428": { - "description": "Recent MFA verification required" - }, - "500": { - "description": "Internal server error" - } - } - } - }, - "/projects/{project_id}/environments/{env_id}/crons": { - "get": { - "tags": [ - "Crons" - ], - "operationId": "get_environment_crons", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "env_id", - "in": "path", - "description": "Environment ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "List of cron jobs", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/CronInfo" - } - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "500": { - "description": "Internal server error" - } - } - } - }, - "/projects/{project_id}/environments/{env_id}/crons/{cron_id}": { - "get": { - "tags": [ - "Crons" - ], - "operationId": "get_cron_by_id", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "env_id", - "in": "path", - "description": "Environment ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "cron_id", - "in": "path", - "description": "Cron Job ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Cron job details", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CronInfo" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "404": { - "description": "Cron job not found" - }, - "500": { - "description": "Internal server error" - } - } - } - }, - "/projects/{project_id}/environments/{env_id}/crons/{cron_id}/executions": { - "get": { - "tags": [ - "Crons" - ], - "operationId": "get_cron_executions", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "env_id", - "in": "path", - "description": "Environment ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "cron_id", - "in": "path", - "description": "Cron Job ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "page", - "in": "query", - "description": "Page number (default: 1)", - "required": false, - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "per_page", - "in": "query", - "description": "Items per page (default: 20)", - "required": false, - "schema": { - "type": "integer", - "format": "int64" - } - } - ], - "responses": { - "200": { - "description": "List of cron job executions", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/CronExecutionInfo" - } - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "404": { - "description": "Cron job not found" - }, - "500": { - "description": "Internal server error" - } - } - } - }, - "/projects/{project_id}/environments/{env_id}/domains": { - "get": { - "tags": [ - "Projects" - ], - "summary": "Get all environment domains for a specific environment", - "operationId": "get_environment_domains", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID or slug", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "env_id", - "in": "path", - "description": "Environment ID or slug", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "List of environment domains", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/EnvironmentDomainResponse" - } - } - } - } - }, - "404": { - "description": "Project or environment not found" - }, - "500": { - "description": "Internal server error" - } - } - }, - "post": { - "tags": [ - "Projects" - ], - "summary": "Add a new environment domain", - "operationId": "add_environment_domain", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID or slug", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "env_id", - "in": "path", - "description": "Environment ID or slug", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AddEnvironmentDomainRequest" - } - } - }, - "required": true - }, - "responses": { - "201": { - "description": "Domain added successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/EnvironmentDomainResponse" - } - } - } - }, - "400": { - "description": "Invalid input" - }, - "404": { - "description": "Project or environment not found" - }, - "500": { - "description": "Internal server error" - } - } - } - }, - "/projects/{project_id}/environments/{env_id}/domains/{domain_id}": { - "delete": { - "tags": [ - "Projects" - ], - "summary": "Delete an environment domain", - "operationId": "delete_environment_domain", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID or slug", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "env_id", - "in": "path", - "description": "Environment ID or slug", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "domain_id", - "in": "path", - "description": "Domain ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "204": { - "description": "Domain deleted successfully" - }, - "404": { - "description": "Project, environment, or domain not found" - }, - "500": { - "description": "Internal server error" - } - } - } - }, - "/projects/{project_id}/environments/{env_id}/settings": { - "put": { - "tags": [ - "Projects" - ], - "summary": "Update environment settings", - "operationId": "update_environment_settings", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID or slug", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "env_id", - "in": "path", - "description": "Environment ID or slug", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdateEnvironmentSettingsRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Environment settings updated successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/EnvironmentResponse" - } - } - } - }, - "404": { - "description": "Project or environment not found" - }, - "500": { - "description": "Internal server error" - } - } - } - }, - "/projects/{project_id}/environments/{env_id}/sleep": { - "post": { - "tags": [ - "Environments" - ], - "summary": "Sleep an on-demand environment", - "description": "Manually put an on-demand environment to sleep. Stops containers and sets\n`sleeping = true`. If no OnDemandWaker is available, falls back to DB flag only.", - "operationId": "sleep_environment", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "env_id", - "in": "path", - "description": "Environment ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Environment put to sleep", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/EnvironmentResponse" - } - } - } - }, - "400": { - "description": "On-demand not enabled for this environment" - }, - "404": { - "description": "Environment not found" - }, - "429": { - "description": "Too many state transitions, retry after cooldown" - }, - "500": { - "description": "Internal server error" - } - } - } - }, - "/projects/{project_id}/environments/{env_id}/subdomain": { - "patch": { - "tags": [ - "Projects" - ], - "summary": "Rename the auto-managed subdomain for an environment.", - "description": "Replaces the environment's previous subdomain entirely \u2014 the old\nhostname stops resolving once the proxy reloads its route table.\nCustom domains attached to the environment are unaffected.", - "operationId": "update_environment_subdomain", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID or slug", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "env_id", - "in": "path", - "description": "Environment ID or slug", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdateEnvironmentSubdomainRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Subdomain updated successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/EnvironmentResponse" - } - } - } - }, - "400": { - "description": "Invalid subdomain or conflict with another environment" - }, - "404": { - "description": "Project or environment not found" - }, - "500": { - "description": "Internal server error" - } - } - } - }, - "/projects/{project_id}/environments/{env_id}/teardown": { - "delete": { - "tags": [ - "Projects" - ], - "summary": "Teardown an environment and all its active deployments", - "operationId": "teardown_environment", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID or slug", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "env_id", - "in": "path", - "description": "Environment ID or slug", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "204": { - "description": "Environment torn down successfully" - }, - "404": { - "description": "Project or environment not found" - }, - "500": { - "description": "Internal server error" - } - } - } - }, - "/projects/{project_id}/environments/{env_id}/wake": { - "post": { - "tags": [ - "Environments" - ], - "summary": "Wake a sleeping on-demand environment", - "description": "Manually wake an environment that has been put to sleep by the on-demand\nidle timeout. Starts containers, waits for health checks, then sets\n`sleeping = false`. If no OnDemandWaker is available (proxy not running\nin same process), falls back to setting the DB flag only.", - "operationId": "wake_environment", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "env_id", - "in": "path", - "description": "Environment ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Environment woken up", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/EnvironmentResponse" - } - } - } - }, - "400": { - "description": "On-demand not enabled for this environment" - }, - "404": { - "description": "Environment not found" - }, - "429": { - "description": "Too many state transitions, retry after cooldown" - }, - "500": { - "description": "Internal server error" - } - } - } - }, - "/projects/{project_id}/environments/{environment_id}/container-logs": { - "get": { - "tags": [ - "Deployments" - ], - "summary": "Get logs for a container in an environment via WebSocket", - "operationId": "get_container_logs", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "environment_id", - "in": "path", - "description": "Environment ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "start_date", - "in": "query", - "description": "Start date for logs", - "required": false, - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "end_date", - "in": "query", - "description": "End date for logs", - "required": false, - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "tail", - "in": "query", - "description": "Number of lines to tail (or 'all')", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "container_name", - "in": "query", - "description": "Optional container name (defaults to first/primary container)", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "timestamps", - "in": "query", - "description": "Include timestamps in log output (default: false)", - "required": false, - "schema": { - "type": "boolean" - } - }, - { - "name": "follow", - "in": "query", - "description": "Follow log output in real-time (default: true)", - "required": false, - "schema": { - "type": "boolean" - } - } - ], - "responses": { - "101": { - "description": "WebSocket connection established for streaming container logs" - }, - "400": { - "description": "Not a server-type project" - }, - "404": { - "description": "Project, deployment, or container not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/environments/{environment_id}/containers": { - "get": { - "tags": [ - "Deployments" - ], - "summary": "List all containers for an environment", - "operationId": "list_containers", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "environment_id", - "in": "path", - "description": "Environment ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "List of containers", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ContainerListResponse" - } - } - } - }, - "400": { - "description": "Not a server-type project" - }, - "404": { - "description": "Project or environment not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/environments/{environment_id}/containers/{container_id}": { - "get": { - "tags": [ - "Containers" - ], - "summary": "Get detailed information about a specific container", - "operationId": "get_container_detail", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "environment_id", - "in": "path", - "description": "Environment ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "container_id", - "in": "path", - "description": "Container ID", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Container details", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ContainerDetailResponse" - } - } - } - }, - "404": { - "description": "Container not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/environments/{environment_id}/containers/{container_id}/environment/{variable_name}": { - "get": { - "tags": [ - "Containers" - ], - "operationId": "get_container_environment_variable", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "environment_id", - "in": "path", - "description": "Environment ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "container_id", - "in": "path", - "description": "Container ID", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "variable_name", - "in": "path", - "description": "Environment variable name", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Environment variable value", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ContainerEnvironmentVariableValueResponse" - } - } - } - }, - "403": { - "description": "Plaintext secret access is not permitted" - }, - "404": { - "description": "Container or environment variable not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/environments/{environment_id}/containers/{container_id}/logs": { - "get": { - "tags": [ - "Deployments" - ], - "summary": "Get logs for a specific container by container ID via WebSocket", - "operationId": "get_container_logs_by_id", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "environment_id", - "in": "path", - "description": "Environment ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "container_id", - "in": "path", - "description": "Container ID", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "start_date", - "in": "query", - "description": "Start date for logs", - "required": false, - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "end_date", - "in": "query", - "description": "End date for logs", - "required": false, - "schema": { - "type": "integer", - "format": "int64" - } - }, - { - "name": "tail", - "in": "query", - "description": "Number of lines to tail (or 'all')", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "timestamps", - "in": "query", - "description": "Include timestamps in log output (default: false)", - "required": false, - "schema": { - "type": "boolean" - } - }, - { - "name": "follow", - "in": "query", - "description": "Follow log output in real-time (default: true)", - "required": false, - "schema": { - "type": "boolean" - } - } - ], - "responses": { - "101": { - "description": "WebSocket connection established for streaming container logs" - }, - "400": { - "description": "Not a server-type project" - }, - "404": { - "description": "Project, environment, or container not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/environments/{environment_id}/containers/{container_id}/metrics": { - "get": { - "tags": [ - "Containers" - ], - "summary": "Get metrics/stats for a specific container", - "operationId": "get_container_metrics", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "environment_id", - "in": "path", - "description": "Environment ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "container_id", - "in": "path", - "description": "Container ID", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Container metrics retrieved successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ContainerMetricsResponse" - } - } - } - }, - "404": { - "description": "Container not found" - }, - "500": { - "description": "Internal server error" - } - } - } - }, - "/projects/{project_id}/environments/{environment_id}/containers/{container_id}/metrics/history": { - "get": { - "tags": [ - "Containers" - ], - "summary": "Fetch a time-series range for a single container resource metric\n(recorded by the container health monitor every ~30s).", - "description": "Useful metric names: `container.cpu_percent`,\n`container.cpu_utilization_percent`, `container.memory_used_bytes`,\n`container.memory_percent`, `container.network_rx_bytes_delta`,\n`container.network_tx_bytes_delta`.", - "operationId": "ContainerMetricsGetHistory", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "environment_id", - "in": "path", - "description": "Environment ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "container_id", - "in": "path", - "description": "Container ID", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "metric", - "in": "query", - "description": "Dotted metric name, e.g. `container.cpu_percent` or\n`container.memory_used_bytes`.", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "range", - "in": "query", - "description": "Time window: `1h`, `6h`, `24h`, or `7d` (defaults to `1h`).", - "required": false, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Metric time series data points", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ContainerMetricHistoryPoint" - } - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "404": { - "description": "Container not found" - }, - "500": { - "description": "Internal server error" - }, - "503": { - "description": "Metrics store not available" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/environments/{environment_id}/containers/{container_id}/metrics/stream": { - "get": { - "tags": [ - "Containers" - ], - "summary": "Stream container metrics via Server-Sent Events (SSE)", - "operationId": "stream_container_metrics", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "environment_id", - "in": "path", - "description": "Environment ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "container_id", - "in": "path", - "description": "Container ID", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "interval", - "in": "query", - "description": "Update interval in milliseconds (default: 1000)", - "required": false, - "schema": { - "type": "integer", - "format": "int64", - "minimum": 0 - } - } - ], - "responses": { - "200": { - "description": "Metrics stream established (Server-Sent Events)" - }, - "404": { - "description": "Container not found" - }, - "500": { - "description": "Internal server error" - } - } - } - }, - "/projects/{project_id}/environments/{environment_id}/containers/{container_id}/restart": { - "post": { - "tags": [ - "Containers" - ], - "summary": "Restart a container", - "operationId": "restart_container", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "environment_id", - "in": "path", - "description": "Environment ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "container_id", - "in": "path", - "description": "Container ID", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Container restarted successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ContainerActionResponse" - } - } - } - }, - "404": { - "description": "Container not found" - }, - "500": { - "description": "Internal server error" - } - } - } - }, - "/projects/{project_id}/environments/{environment_id}/containers/{container_id}/start": { - "post": { - "tags": [ - "Containers" - ], - "summary": "Start a container", - "operationId": "start_container", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "environment_id", - "in": "path", - "description": "Environment ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "container_id", - "in": "path", - "description": "Container ID", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Container started successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ContainerActionResponse" - } - } - } - }, - "404": { - "description": "Container not found" - }, - "500": { - "description": "Internal server error" - } - } - } - }, - "/projects/{project_id}/environments/{environment_id}/containers/{container_id}/stop": { - "post": { - "tags": [ - "Containers" - ], - "summary": "Stop a specific container", - "operationId": "stop_container", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "environment_id", - "in": "path", - "description": "Environment ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "container_id", - "in": "path", - "description": "Container ID", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Container stopped successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ContainerActionResponse" - } - } - } - }, - "404": { - "description": "Container not found" - }, - "500": { - "description": "Internal server error" - } - } - } - }, - "/projects/{project_id}/environments/{environment_id}/deploy/image": { - "post": { - "tags": [ - "Deployments" - ], - "summary": "Deploy from an external Docker image", - "description": "Triggers a deployment using a pre-built Docker image from an external registry.\nThe image will be pulled and deployed to the specified environment.", - "operationId": "deploy_from_image", - "parameters": [ - { - "name": "project_id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "environment_id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/DeployFromImageRequest" - } - } - }, - "required": true - }, - "responses": { - "202": { - "description": "Deployment started", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/RemoteDeploymentResponse" - } - } - } - }, - "400": { - "description": "Invalid request" - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "404": { - "description": "Project or environment not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/environments/{environment_id}/deploy/image-upload": { - "post": { - "tags": [ - "Deployments" - ], - "summary": "Deploy from an uploaded Docker image tarball", - "description": "Uploads a Docker image tarball (from `docker save`) and deploys it directly.\nThe image is imported using `docker load` and then deployed to the specified environment.\nThis is useful when you want to deploy an image without pushing to a registry first.\n\nThe uploaded file should be a tarball created by `docker save myimage:tag > image.tar`\nor `docker save myimage:tag | gzip > image.tar.gz` (gzip compressed tarballs are also supported).", - "operationId": "deploy_from_image_upload", - "parameters": [ - { - "name": "tag", - "in": "query", - "description": "Tag to apply to the imported image (e.g., \"myapp:v1.0\")\nIf not provided, a unique tag will be generated", - "required": false, - "schema": { - "type": [ - "string", - "null" - ] - } - }, - { - "name": "health_check_path", - "in": "query", - "description": "Optional HTTP health-check path override (e.g. \"/api/healthz\").\nMust start with '/'. When omitted, defaults to \"/\".", - "required": false, - "schema": { - "type": [ - "string", - "null" - ] - } - }, - { - "name": "project_id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "environment_id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "202": { - "description": "Image imported and deployment started", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/RemoteDeploymentResponse" - } - } - } - }, - "400": { - "description": "Invalid request or unsupported format" - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "404": { - "description": "Project or environment not found" - }, - "413": { - "description": "Image tarball too large" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/environments/{environment_id}/deploy/static": { - "post": { - "tags": [ - "Deployments" - ], - "summary": "Deploy from an uploaded static bundle", - "description": "Triggers a deployment using a previously uploaded static file bundle.", - "operationId": "deploy_from_static", - "parameters": [ - { - "name": "project_id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "environment_id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/DeployFromStaticRequest" - } - } - }, - "required": true - }, - "responses": { - "202": { - "description": "Deployment started", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/RemoteDeploymentResponse" - } - } - } - }, - "400": { - "description": "Invalid request" - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "404": { - "description": "Project, environment, or bundle not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/error-alert-rules": { - "get": { - "tags": [ - "error-alert-rules" - ], - "summary": "List all alert rules for a project", - "operationId": "list_alert_rules", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "List of alert rules", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/AlertRuleResponse" - } - } - } - } - }, - "500": { - "description": "Internal server error" - } - } - }, - "post": { - "tags": [ - "error-alert-rules" - ], - "summary": "Create a new alert rule", - "operationId": "create_alert_rule", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateAlertRuleRequest" - } - } - }, - "required": true - }, - "responses": { - "201": { - "description": "Alert rule created", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AlertRuleResponse" - } - } - } - }, - "400": { - "description": "Validation error" - }, - "500": { - "description": "Internal server error" - } - } - } - }, - "/projects/{project_id}/error-alert-rules/{rule_id}": { - "get": { - "tags": [ - "error-alert-rules" - ], - "summary": "Get a specific alert rule", - "operationId": "get_alert_rule", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "rule_id", - "in": "path", - "description": "Alert rule ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Alert rule details", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AlertRuleResponse" - } - } - } - }, - "404": { - "description": "Alert rule not found" - }, - "500": { - "description": "Internal server error" - } - } - }, - "put": { - "tags": [ - "error-alert-rules" - ], - "summary": "Update an existing alert rule", - "operationId": "update_alert_rule", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "rule_id", - "in": "path", - "description": "Alert rule ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdateAlertRuleRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Alert rule updated", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AlertRuleResponse" - } - } - } - }, - "400": { - "description": "Validation error" - }, - "404": { - "description": "Alert rule not found" - }, - "500": { - "description": "Internal server error" - } - } - }, - "delete": { - "tags": [ - "error-alert-rules" - ], - "summary": "Delete an alert rule", - "operationId": "delete_alert_rule", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "rule_id", - "in": "path", - "description": "Alert rule ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "204": { - "description": "Alert rule deleted" - }, - "404": { - "description": "Alert rule not found" - }, - "500": { - "description": "Internal server error" - } - } - } - }, - "/projects/{project_id}/error-dashboard-stats": { - "get": { - "tags": [ - "error-tracking" - ], - "summary": "Get error dashboard statistics", - "operationId": "get_error_dashboard_stats", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "start_time", - "in": "query", - "required": true, - "schema": { - "type": "string", - "format": "date-time" - } - }, - { - "name": "end_time", - "in": "query", - "required": true, - "schema": { - "type": "string", - "format": "date-time" - } - }, - { - "name": "environment_id", - "in": "query", - "required": false, - "schema": { - "type": [ - "integer", - "null" - ], - "format": "int32" - } - }, - { - "name": "compare_to_previous", - "in": "query", - "required": false, - "schema": { - "type": [ - "boolean", - "null" - ] - } - } - ], - "responses": { - "200": { - "description": "Error dashboard statistics", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorDashboardStatsResponse" - } - } - } - }, - "500": { - "description": "Internal server error" - } - } - } - }, - "/projects/{project_id}/error-groups": { - "get": { - "tags": [ - "error-tracking" - ], - "summary": "List error groups for a project", - "operationId": "list_error_groups", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "page", - "in": "query", - "required": false, - "schema": { - "type": "integer", - "format": "int64", - "minimum": 0 - } - }, - { - "name": "page_size", - "in": "query", - "required": false, - "schema": { - "type": "integer", - "format": "int64", - "minimum": 0 - } - }, - { - "name": "status", - "in": "query", - "required": false, - "schema": { - "type": [ - "string", - "null" - ] - } - }, - { - "name": "environment_id", - "in": "query", - "required": false, - "schema": { - "type": [ - "integer", - "null" - ], - "format": "int32" - } - }, - { - "name": "start_date", - "in": "query", - "required": false, - "schema": { - "type": [ - "string", - "null" - ], - "format": "date-time" - } - }, - { - "name": "end_date", - "in": "query", - "required": false, - "schema": { - "type": [ - "string", - "null" - ], - "format": "date-time" - } - }, - { - "name": "sort_by", - "in": "query", - "required": false, - "schema": { - "type": [ - "string", - "null" - ] - } - }, - { - "name": "sort_order", - "in": "query", - "required": false, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Paginated list of error groups", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/PaginatedErrorGroupsResponse" - } - } - } - }, - "500": { - "description": "Internal server error" - } - } - } - }, - "/projects/{project_id}/error-groups/{group_id}": { - "get": { - "tags": [ - "error-tracking" - ], - "summary": "Get a specific error group", - "operationId": "get_error_group", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "group_id", - "in": "path", - "description": "Error group ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Error group details", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorGroupResponse" - } - } - } - }, - "404": { - "description": "Error group not found" - }, - "500": { - "description": "Internal server error" - } - } - }, - "put": { - "tags": [ - "error-tracking" - ], - "summary": "Update error group status", - "operationId": "update_error_group", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "group_id", - "in": "path", - "description": "Error group ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdateErrorGroupRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Error group updated successfully" - }, - "404": { - "description": "Error group not found" - }, - "500": { - "description": "Internal server error" - } - } - } - }, - "/projects/{project_id}/error-groups/{group_id}/events": { - "get": { - "tags": [ - "error-tracking" - ], - "summary": "List error events for a specific group", - "operationId": "list_error_events", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "group_id", - "in": "path", - "description": "Error group ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "page", - "in": "query", - "required": false, - "schema": { - "type": "integer", - "format": "int64", - "minimum": 0 - } - }, - { - "name": "page_size", - "in": "query", - "required": false, - "schema": { - "type": "integer", - "format": "int64", - "minimum": 0 - } - } - ], - "responses": { - "200": { - "description": "Paginated list of error events", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/PaginatedErrorEventsResponse" - } - } - } - }, - "404": { - "description": "Error group not found" - }, - "500": { - "description": "Internal server error" - } - } - } - }, - "/projects/{project_id}/error-groups/{group_id}/events/{event_id}": { - "get": { - "tags": [ - "error-tracking" - ], - "summary": "Get a specific error event", - "operationId": "get_error_event", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "group_id", - "in": "path", - "description": "Error group ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "event_id", - "in": "path", - "description": "Error event ID", - "required": true, - "schema": { - "type": "integer", - "format": "int64" - } - } - ], - "responses": { - "200": { - "description": "Error event details", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorEventResponse" - } - } - } - }, - "404": { - "description": "Event not found" - }, - "500": { - "description": "Internal server error" - } - } - } - }, - "/projects/{project_id}/error-stats": { - "get": { - "tags": [ - "error-tracking" - ], - "summary": "Get error statistics for a project", - "operationId": "get_error_stats", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Error statistics", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorGroupStatsResponse" - } - } - } - }, - "500": { - "description": "Internal server error" - } - } - } - }, - "/projects/{project_id}/error-time-series": { - "get": { - "tags": [ - "error-tracking" - ], - "summary": "Get error time series data for charts", - "operationId": "get_error_time_series", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "start_time", - "in": "query", - "required": true, - "schema": { - "type": "string", - "format": "date-time" - } - }, - { - "name": "end_time", - "in": "query", - "required": true, - "schema": { - "type": "string", - "format": "date-time" - } - }, - { - "name": "bucket", - "in": "query", - "description": "Time bucket size (e.g., \"1h\", \"15m\", \"1d\", \"1 hour\", \"30 minutes\")", - "required": false, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Error time series data", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ErrorTimeSeriesDataResponse" - } - } - } - } - }, - "500": { - "description": "Internal server error" - } - } - } - }, - "/projects/{project_id}/events": { - "get": { - "tags": [ - "Events" - ], - "summary": "Get event counts with filtering", - "operationId": "get_events_count", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "start_date", - "in": "query", - "description": "Start date for filtering events", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "end_date", - "in": "query", - "description": "End date for filtering events", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "environment_id", - "in": "query", - "description": "Filter by environment ID", - "required": false, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "limit", - "in": "query", - "description": "Maximum number of events to return (default: 20, max: 100)", - "required": false, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "custom_events_only", - "in": "query", - "description": "Only return custom events, excluding system events like page_view, page_leave, heartbeat (default: true)", - "required": false, - "schema": { - "type": "boolean" - } - }, - { - "name": "aggregation_level", - "in": "query", - "description": "Aggregation level: events, sessions, or visitors (default: events)", - "required": false, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Successfully retrieved event counts", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/EventCount" - } - } - } - } - }, - "400": { - "description": "Bad request" - }, - "401": { - "description": "Unauthorized" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/events/breakdown": { - "get": { - "tags": [ - "Events" - ], - "summary": "Get event type breakdown", - "operationId": "get_event_type_breakdown", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "start_date", - "in": "query", - "description": "Start date for filtering events", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "end_date", - "in": "query", - "description": "End date for filtering events", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "environment_id", - "in": "query", - "description": "Filter by environment ID", - "required": false, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "aggregation_level", - "in": "query", - "description": "Aggregation level: events, sessions, or visitors (default: events)", - "required": false, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Successfully retrieved event type breakdown", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/EventTypeBreakdown" - } - } - } - } - }, - "400": { - "description": "Bad request" - }, - "401": { - "description": "Unauthorized" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/events/ingest": { - "post": { - "tags": [ - "Events" - ], - "summary": "Record an analytics event via the console API with explicit project ID.", - "description": "The app backend forwards the user's encrypted Temps cookies, so visitor/session\nidentity is resolved automatically by middleware. No geolocation or user-agent\nenrichment is performed \u2014 this is a lightweight server-side ingestion path.", - "operationId": "record_console_event", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ConsoleEventPayload" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Event recorded successfully" - }, - "400": { - "description": "Bad request" - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/events/properties/breakdown": { - "get": { - "tags": [ - "Events" - ], - "summary": "Get property breakdown by grouping events by a column", - "operationId": "get_property_breakdown", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "start_date", - "in": "query", - "description": "Start date in '%Y-%m-%d %H:%M:%S' format", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "end_date", - "in": "query", - "description": "End date in '%Y-%m-%d %H:%M:%S' format", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "group_by", - "in": "query", - "description": "Column to group by (channel, device_type, browser, etc.)", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "environment_id", - "in": "query", - "description": "Filter by environment ID", - "required": false, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "deployment_id", - "in": "query", - "description": "Filter by deployment ID", - "required": false, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "event_name", - "in": "query", - "description": "Filter by event name", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "aggregation_level", - "in": "query", - "description": "Aggregation level: events, sessions, or visitors - default: events", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "limit", - "in": "query", - "description": "Maximum number of results (default: 20, max: 100)", - "required": false, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "filter_country", - "in": "query", - "description": "Filter by country (for region/city drill-downs)", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "filter_region", - "in": "query", - "description": "Filter by region (for city drill-downs)", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "filter_browser", - "in": "query", - "description": "Filter by browser name (for version drill-downs)", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "filter_os", - "in": "query", - "description": "Filter by OS name (for version drill-downs)", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "filter_channel", - "in": "query", - "description": "Filter by channel name (for channel drill-downs)", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "filter_referrer", - "in": "query", - "description": "Filter by referrer hostname (for referrer drill-downs)", - "required": false, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Successfully retrieved property breakdown", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/PropertyBreakdownResponse" - } - } - } - }, - "400": { - "description": "Bad request" - }, - "401": { - "description": "Unauthorized" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/events/properties/timeline": { - "get": { - "tags": [ - "Events" - ], - "summary": "Get property timeline by grouping events by a column over time", - "operationId": "get_property_timeline", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "start_date", - "in": "query", - "description": "Start date in '%Y-%m-%d %H:%M:%S' format", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "end_date", - "in": "query", - "description": "End date in '%Y-%m-%d %H:%M:%S' format", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "group_by", - "in": "query", - "description": "Column to group by (channel, device_type, browser, etc.)", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "environment_id", - "in": "query", - "description": "Filter by environment ID", - "required": false, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "deployment_id", - "in": "query", - "description": "Filter by deployment ID", - "required": false, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "event_name", - "in": "query", - "description": "Filter by event name", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "aggregation_level", - "in": "query", - "description": "Aggregation level: events, sessions, or visitors - default: events", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "bucket_size", - "in": "query", - "description": "Time bucket: hour, day, week, month (default: auto-detect)", - "required": false, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Successfully retrieved property timeline", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/PropertyTimelineResponse" - } - } - } - }, - "400": { - "description": "Bad request" - }, - "401": { - "description": "Unauthorized" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/events/timeline": { - "get": { - "tags": [ - "Events" - ], - "summary": "Get events timeline", - "operationId": "get_events_timeline", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "start_date", - "in": "query", - "description": "Start date for filtering events", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "end_date", - "in": "query", - "description": "End date for filtering events", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "environment_id", - "in": "query", - "description": "Filter by environment ID", - "required": false, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "event_name", - "in": "query", - "description": "Filter by specific event name", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "bucket_size", - "in": "query", - "description": "Bucket size: hour, day, or week (auto-detected if not specified)", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "aggregation_level", - "in": "query", - "description": "Aggregation level: events, sessions, or visitors (default: events)", - "required": false, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Successfully retrieved events timeline", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/EventTimeline" - } - } - } - } - }, - "400": { - "description": "Bad request" - }, - "401": { - "description": "Unauthorized" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/events/unique": { - "get": { - "tags": [ - "Funnels" - ], - "summary": "Get all unique/distinct event types for a project (paginated)", - "operationId": "get_unique_events", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "page", - "in": "query", - "description": "Page number (default: 1)", - "required": false, - "schema": { - "type": "integer", - "format": "int64", - "minimum": 0 - } - }, - { - "name": "page_size", - "in": "query", - "description": "Items per page (default: 50, max: 100)", - "required": false, - "schema": { - "type": "integer", - "format": "int64", - "minimum": 0 - } - } - ], - "responses": { - "200": { - "description": "Unique event types retrieved successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/EventTypesResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/external-images": { - "get": { - "tags": [ - "External Images" - ], - "summary": "List external images for a project", - "operationId": "list_remote_external_images", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "page", - "in": "query", - "description": "Page number (default: 1)", - "required": false, - "schema": { - "type": "integer", - "format": "int64", - "minimum": 0 - } - }, - { - "name": "page_size", - "in": "query", - "description": "Items per page (default: 20)", - "required": false, - "schema": { - "type": "integer", - "format": "int64", - "minimum": 0 - } - } - ], - "responses": { - "200": { - "description": "List of external images", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/PaginatedExternalImagesResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "post": { - "tags": [ - "External Images" - ], - "summary": "Register an external Docker image", - "description": "Registers an external Docker image reference without triggering a deployment.\nThe image can be deployed later using the deploy/image endpoint.", - "operationId": "register_external_image", - "parameters": [ - { - "name": "project_id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/RegisterImageRequest" - } - } - }, - "required": true - }, - "responses": { - "201": { - "description": "Image registered successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ExternalImageResponse" - } - } - } - }, - "400": { - "description": "Invalid request" - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "404": { - "description": "Project not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/external-images/{image_id}": { - "get": { - "tags": [ - "External Images" - ], - "summary": "Get details of a specific external image", - "operationId": "get_remote_external_image", - "parameters": [ - { - "name": "project_id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "image_id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Image details", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ExternalImageResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "404": { - "description": "Image not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "delete": { - "tags": [ - "External Images" - ], - "summary": "Delete an external image", - "operationId": "delete_external_image", - "parameters": [ - { - "name": "project_id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "image_id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "204": { - "description": "Image deleted" - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "404": { - "description": "Image not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/flags": { - "get": { - "tags": [ - "Feature Flags" - ], - "operationId": "list_flags", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "include_archived", - "in": "query", - "description": "Include archived flags. Defaults to false.", - "required": false, - "schema": { - "type": "boolean" - } - }, - { - "name": "page", - "in": "query", - "description": "1-indexed page number. Defaults to 1.", - "required": false, - "schema": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "minimum": 0 - } - }, - { - "name": "page_size", - "in": "query", - "description": "Items per page. Defaults to 20, capped at 100.", - "required": false, - "schema": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "minimum": 0 - } - } - ], - "responses": { - "200": { - "description": "Flags listed", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/FlagListResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "post": { - "tags": [ - "Feature Flags" - ], - "operationId": "create_flag", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateFlagRequest" - } - } - }, - "required": true - }, - "responses": { - "201": { - "description": "Flag created", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/FlagResponse" - } - } - } - }, - "400": { - "description": "Validation error" - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "409": { - "description": "Flag key already exists" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/flags/{key}": { - "get": { - "tags": [ - "Feature Flags" - ], - "operationId": "get_flag", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "key", - "in": "path", - "description": "Flag key", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Flag retrieved", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/FlagResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "404": { - "description": "Flag not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "delete": { - "tags": [ - "Feature Flags" - ], - "operationId": "archive_flag", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "key", - "in": "path", - "description": "Flag key", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Flag archived", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ArchiveFlagResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "404": { - "description": "Flag not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "patch": { - "tags": [ - "Feature Flags" - ], - "operationId": "update_flag", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "key", - "in": "path", - "description": "Flag key", - "required": true, - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdateFlagRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Flag updated", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/FlagResponse" - } - } - } - }, - "400": { - "description": "Validation error" - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "404": { - "description": "Flag not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/flags/{key}/environments/{environment_id}": { - "put": { - "tags": [ - "Feature Flags" - ], - "summary": "Set a flag's value in one environment, and/or flip its kill switch.", - "operationId": "set_flag_environment", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "key", - "in": "path", - "description": "Flag key", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "environment_id", - "in": "path", - "description": "Environment ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SetFlagEnvironmentRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Environment value set", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/FlagEnvironmentResponse" - } - } - } - }, - "400": { - "description": "Validation error" - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "404": { - "description": "Flag or environment not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/flags/{key}/restore": { - "post": { - "tags": [ - "Feature Flags" - ], - "summary": "Bring an archived flag back.", - "description": "Archiving is otherwise one-way: the key stays reserved so the flag cannot\neven be re-created under the same name, which makes an accidental archive\nunrecoverable through the API.", - "operationId": "restore_flag", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "key", - "in": "path", - "description": "Flag key", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Flag restored", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/FlagResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "404": { - "description": "Flag not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/funnels": { - "get": { - "tags": [ - "Funnels" - ], - "summary": "List all funnels for a project", - "operationId": "list_funnels", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Funnels retrieved successfully", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/FunnelResponse" - } - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "post": { - "tags": [ - "Funnels" - ], - "summary": "Create a new funnel", - "operationId": "create_funnel", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateFunnelRequest" - } - } - }, - "required": true - }, - "responses": { - "201": { - "description": "Funnel created successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateFunnelResponse" - } - } - } - }, - "400": { - "description": "Bad request" - }, - "401": { - "description": "Unauthorized" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/funnels/preview": { - "post": { - "tags": [ - "Funnels" - ], - "summary": "Preview funnel metrics without creating the funnel", - "operationId": "preview_funnel_metrics", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateFunnelRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Funnel metrics preview", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/FunnelMetricsResponse" - } - } - } - }, - "400": { - "description": "Bad request" - }, - "401": { - "description": "Unauthorized" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/funnels/{funnel_id}": { - "put": { - "tags": [ - "Funnels" - ], - "summary": "Update a funnel", - "operationId": "update_funnel", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "funnel_id", - "in": "path", - "description": "Funnel ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateFunnelRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Funnel updated successfully" - }, - "400": { - "description": "Bad request" - }, - "401": { - "description": "Unauthorized" - }, - "404": { - "description": "Funnel not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "delete": { - "tags": [ - "Funnels" - ], - "summary": "Delete a funnel", - "operationId": "delete_funnel", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "funnel_id", - "in": "path", - "description": "Funnel ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Funnel deleted successfully" - }, - "401": { - "description": "Unauthorized" - }, - "404": { - "description": "Funnel not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/funnels/{funnel_id}/metrics": { - "get": { - "tags": [ - "Funnels" - ], - "summary": "Get funnel metrics", - "operationId": "get_funnel_metrics", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "funnel_id", - "in": "path", - "description": "Funnel ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "environment_id", - "in": "query", - "description": "Environment ID filter", - "required": false, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "country_code", - "in": "query", - "description": "Country code filter", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "start_date", - "in": "query", - "description": "Start date filter (ISO 8601)", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "end_date", - "in": "query", - "description": "End date filter (ISO 8601)", - "required": false, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Funnel metrics retrieved successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/FunnelMetricsResponse" - } - } - } - }, - "400": { - "description": "Bad request" - }, - "401": { - "description": "Unauthorized" - }, - "404": { - "description": "Funnel not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/git": { - "post": { - "tags": [ - "Projects" - ], - "summary": "Update git settings for a project", - "operationId": "update_git_settings", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdateGitSettingsRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Git settings updated successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProjectResponse" - } - } - } - }, - "400": { - "description": "Invalid git configuration or branch does not exist" - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Forbidden" - }, - "404": { - "description": "Project not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/gitlab/reinstall-webhook": { - "post": { - "tags": [ - "Projects" - ], - "summary": "Reinstall the GitLab webhook for a project", - "description": "Removes the existing webhook (if any) and installs a fresh one.\nUse this when a webhook has been manually deleted on the GitLab side\nand automatic deployments have stopped working.", - "operationId": "reinstall_gitlab_webhook", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Webhook reinstalled", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ReinstallWebhookResponse" - } - } - } - }, - "400": { - "description": "Project is not connected to a GitLab repository" - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Forbidden" - }, - "404": { - "description": "Project not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/has-error-groups": { - "get": { - "tags": [ - "error-tracking" - ], - "summary": "Check if project has any error groups", - "operationId": "has_error_groups", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Error groups existence check", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HasErrorGroupsResponse" - } - } - } - }, - "500": { - "description": "Internal server error" - } - } - } - }, - "/projects/{project_id}/has-events": { - "get": { - "tags": [ - "Events" - ], - "summary": "Check if project has any analytics events", - "operationId": "has_analytics_events", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Successfully checked for events", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HasEventsResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/hourly-visits": { - "get": { - "tags": [ - "Events" - ], - "summary": "Get hourly visits", - "operationId": "get_hourly_visits", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "start_date", - "in": "query", - "description": "Start date for filtering visits", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "end_date", - "in": "query", - "description": "End date for filtering visits", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "environment_id", - "in": "query", - "description": "Filter by environment ID", - "required": false, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "aggregation_level", - "in": "query", - "description": "Aggregation level: events (page views), sessions (unique sessions), or visitors (unique visitors) - default: events", - "required": false, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Successfully retrieved hourly visits", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/EventTimeline" - } - } - } - } - }, - "400": { - "description": "Bad request" - }, - "401": { - "description": "Unauthorized" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/images": { - "get": { - "tags": [ - "External Images" - ], - "summary": "List all external images for a project", - "operationId": "list_external_images", - "parameters": [ - { - "name": "project_id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "List of external images", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/PushedExternalImageResponse" - } - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/images/push": { - "post": { - "tags": [ - "External Images" - ], - "summary": "Push an external Docker image", - "operationId": "push_external_image", - "parameters": [ - { - "name": "project_id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/PushImageRequest" - } - } - }, - "required": true - }, - "responses": { - "201": { - "description": "Image pushed successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/PushedExternalImageResponse" - } - } - } - }, - "400": { - "description": "Invalid request" - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/images/{image_id}": { - "get": { - "tags": [ - "External Images" - ], - "summary": "Get details of a specific external image", - "operationId": "get_external_image", - "parameters": [ - { - "name": "project_id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "image_id", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Image details", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/PushedExternalImageResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "404": { - "description": "Image not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/incidents": { - "get": { - "tags": [ - "Status Page" - ], - "summary": "List incidents for a project", - "operationId": "list_incidents", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "environment_id", - "in": "query", - "description": "Filter by environment ID", - "required": false, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "status", - "in": "query", - "description": "Filter by status", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "page", - "in": "query", - "description": "Page number", - "required": false, - "schema": { - "type": "integer", - "format": "int64", - "minimum": 0 - } - }, - { - "name": "page_size", - "in": "query", - "description": "Items per page", - "required": false, - "schema": { - "type": "integer", - "format": "int64", - "minimum": 0 - } - } - ], - "responses": { - "200": { - "description": "Successfully retrieved incidents" - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "post": { - "tags": [ - "Status Page" - ], - "summary": "Create a new incident", - "operationId": "create_incident", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateIncidentRequest" - } - } - }, - "required": true - }, - "responses": { - "201": { - "description": "Incident created successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/IncidentResponse" - } - } - } - }, - "400": { - "description": "Invalid request" - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/incidents/bucketed": { - "get": { - "tags": [ - "Status Page" - ], - "summary": "Get bucketed incident data for a project", - "operationId": "get_bucketed_incidents", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "environment_id", - "in": "query", - "description": "Filter by environment ID", - "required": false, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "interval", - "in": "query", - "description": "Bucket interval: '5min', 'hourly', or 'daily' (default: hourly)", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "start_time", - "in": "query", - "description": "Start time (ISO 8601) (default: 7 days ago)", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "end_time", - "in": "query", - "description": "End time (ISO 8601) (default: now)", - "required": false, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Successfully retrieved bucketed incident data", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/IncidentBucketedResponse" - } - } - } - }, - "400": { - "description": "Invalid parameters" - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/logs": { - "delete": { - "tags": [ - "Logs" - ], - "summary": "Purge all logs for a project before a given timestamp", - "operationId": "purge_project_logs", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/PurgeLogsRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Purge completed" - }, - "400": { - "description": "Invalid parameters", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "401": { - "description": "Unauthorized", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "403": { - "description": "Insufficient permissions", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/mcp-servers": { - "get": { - "tags": [ - "Agents" - ], - "operationId": "list_mcps", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ListMcpsResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "post": { - "tags": [ - "Agents" - ], - "operationId": "create_mcp", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateMcpRequest" - } - } - }, - "required": true - }, - "responses": { - "201": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/McpDefinitionResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/mcp-servers/{slug}": { - "get": { - "tags": [ - "Agents" - ], - "operationId": "get_mcp", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "slug", - "in": "path", - "description": "MCP server slug", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/McpDefinitionResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "404": { - "description": "MCP server not found" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "put": { - "tags": [ - "Agents" - ], - "operationId": "update_mcp", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "slug", - "in": "path", - "description": "MCP server slug", - "required": true, - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdateMcpRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/McpDefinitionResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "404": { - "description": "MCP server not found" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "delete": { - "tags": [ - "Agents" - ], - "operationId": "delete_mcp", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "slug", - "in": "path", - "description": "MCP server slug", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "204": { - "description": "MCP server deleted" - }, - "401": { - "description": "Unauthorized" - }, - "404": { - "description": "MCP server not found" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/mcp-servers/{slug}/config/{field}": { - "get": { - "tags": [ - "Agents" - ], - "operationId": "reveal_mcp_config", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "slug", - "in": "path", - "description": "MCP server slug", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "field", - "in": "path", - "description": "Sensitive field path, such as url or env.API_TOKEN", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SensitiveMcpConfigValueResponse" - } - } - } - }, - "400": { - "description": "Field is not revealable" - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Missing secrets:read permission" - }, - "404": { - "description": "MCP server or field not found" - }, - "500": { - "description": "Configuration read or audit failed" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/monitors": { - "get": { - "tags": [ - "Status Page" - ], - "summary": "List monitors for a project", - "operationId": "list_monitors", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "environment_id", - "in": "query", - "description": "Filter by environment ID", - "required": false, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Successfully retrieved monitors", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/MonitorResponse" - } - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "post": { - "tags": [ - "Status Page" - ], - "summary": "Create a new monitor", - "operationId": "create_monitor", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateMonitorRequest" - } - } - }, - "required": true - }, - "responses": { - "201": { - "description": "Monitor created successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/MonitorResponse" - } - } - } - }, - "400": { - "description": "Invalid request" - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/observe/events": { - "get": { - "tags": [ - "Observability" - ], - "summary": "List a merged page of observability events for a project.", - "description": "Each row carries everything the side panel needs to render \u2014 no\nfollow-up fetch is required for the common case. Heavy fields\n(stacktraces, headers, span attributes) are truncated server-side and\nexpose a `*_truncated` flag; clients fetch the full row from the\n`/full` endpoint only when the user explicitly clicks \"Show full\".", - "operationId": "observability_list_events", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "kinds", - "in": "query", - "description": "Comma-separated kinds: `log,request,span,error,revenue`. Empty or\nmissing returns every kind.", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "from", - "in": "query", - "description": "Inclusive lower bound on event timestamp (ISO 8601, `Z` suffix).", - "required": false, - "schema": { - "type": "string", - "format": "date-time" - } - }, - { - "name": "to", - "in": "query", - "description": "Inclusive upper bound on event timestamp.", - "required": false, - "schema": { - "type": "string", - "format": "date-time" - } - }, - { - "name": "deployment_id", - "in": "query", - "required": false, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "environment_id", - "in": "query", - "required": false, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "search", - "in": "query", - "description": "Free-text substring matched against per-kind summary fields\n(request path / error class / revenue event_type).", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "limit", - "in": "query", - "description": "Page size (default 50, max 200).", - "required": false, - "schema": { - "type": "integer", - "format": "int64", - "minimum": 0 - } - }, - { - "name": "hide_bots", - "in": "query", - "description": "When `true`, exclude bot/crawler request rows. When `false`, only\ninclude bot rows. Omitted means \"include everything\" (default).\nOnly affects the `Request` kind.", - "required": false, - "schema": { - "type": "boolean" - } - } - ], - "responses": { - "200": { - "description": "Merged event page", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/EventsResponse" - } - } - } - }, - "400": { - "description": "Invalid filter (kinds, time range, \u2026)", - "content": { - "text/plain": { - "schema": { - "type": "string" - } - } - } - }, - "401": { - "description": "Unauthorized", - "content": { - "text/plain": { - "schema": { - "type": "string" - } - } - } - }, - "403": { - "description": "Insufficient permissions", - "content": { - "text/plain": { - "schema": { - "type": "string" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "text/plain": { - "schema": { - "type": "string" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/observe/events/{kind}/{event_id}/full": { - "get": { - "tags": [ - "Observability" - ], - "summary": "Fetch the un-truncated form of one event by `(kind, id)`. Side panel\n\"Show full\" action calls this \u2014 the list response carries truncated\npreviews + a `*_truncated` flag to let the UI decide whether to fetch.", - "operationId": "observability_full_event", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "kind", - "in": "path", - "description": "Event kind discriminator", - "required": true, - "schema": { - "$ref": "#/components/schemas/EventKind" - } - }, - { - "name": "event_id", - "in": "path", - "description": "Per-kind identity: request_id for requests, `{trace_id}:{span_id}` for spans, serial id for errors/revenue", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "ts", - "in": "query", - "description": "The row's event timestamp as returned by the list endpoint. Optional,\nbut strongly recommended: it bounds the lookup to the storage\npartitions/chunks around that instant instead of scanning the whole\nretention window.", - "required": false, - "schema": { - "type": "string", - "format": "date-time" - } - } - ], - "responses": { - "200": { - "description": "Full row", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/FullEvent" - } - } - } - }, - "401": { - "description": "Unauthorized", - "content": { - "text/plain": { - "schema": { - "type": "string" - } - } - } - }, - "403": { - "description": "Insufficient permissions", - "content": { - "text/plain": { - "schema": { - "type": "string" - } - } - } - }, - "404": { - "description": "Event not found in project", - "content": { - "text/plain": { - "schema": { - "type": "string" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "text/plain": { - "schema": { - "type": "string" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/releases/{release}/source-files": { - "get": { - "tags": [ - "source-maps" - ], - "summary": "List uploaded source files for a release (metadata only).", - "operationId": "list_source_files", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "release", - "in": "path", - "description": "Release version", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "List of source files", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SourceFileListResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "post": { - "tags": [ - "source-maps" - ], - "summary": "Upload a raw source file for a release (native symbolication).", - "description": "Accepts a multipart form with:\n- `file`: the source file bytes (required)\n- `file_path`: the path of the file as it appears in stack frames (required;\n derived from the uploaded filename if omitted). Normalized with the `~`\n prefix convention, matching source-map storage.\n\nRequires the project's `error_source_context_enabled` toggle to be on.\nUpserts on (project, release, file_path).", - "operationId": "upload_source_file", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "release", - "in": "path", - "description": "Release version", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "201": { - "description": "Source file uploaded", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SourceFileResponse" - } - } - } - }, - "400": { - "description": "Missing fields" - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "409": { - "description": "Source context disabled for project" - }, - "413": { - "description": "Source file too large" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "delete": { - "tags": [ - "source-maps" - ], - "summary": "Delete all uploaded source files for a release.", - "operationId": "delete_release_source_files", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "release", - "in": "path", - "description": "Release version", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Source files deleted", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/DeleteResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/releases/{release}/source-maps": { - "get": { - "tags": [ - "source-maps" - ], - "summary": "List all source maps for a specific release", - "operationId": "list_source_maps", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "release", - "in": "path", - "description": "Release version", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "List of source maps", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SourceMapListResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "post": { - "tags": [ - "source-maps" - ], - "summary": "Upload a source map for a release.", - "description": "Accepts a multipart form with:\n- `file`: The .map file (required)\n- `file_path`: The URL path of the minified file as it appears in stack traces (required).\n Uses the ~ prefix convention (e.g., \"~/assets/main.js\").\n If a full URL is provided, it will be normalized automatically.\n- `dist`: Optional distribution identifier\n\nIf a source map already exists for the same (project, release, file_path), it is replaced.", - "operationId": "upload_source_map", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "release", - "in": "path", - "description": "Release version", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "201": { - "description": "Source map uploaded", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SourceMapResponse" - } - } - } - }, - "400": { - "description": "Invalid source map or missing fields" - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "413": { - "description": "Source map too large" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "delete": { - "tags": [ - "source-maps" - ], - "summary": "Delete all source maps for a specific release", - "operationId": "delete_release_source_maps", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "release", - "in": "path", - "description": "Release version", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Source maps deleted", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/DeleteResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/revenue/events": { - "get": { - "tags": [ - "Revenue" - ], - "summary": "Recent ingested events for the activity feed.", - "operationId": "revenue_recent_events", - "parameters": [ - { - "name": "project_id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/RecentEventResponse" - } - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/revenue/integrations": { - "get": { - "tags": [ - "Revenue" - ], - "summary": "List revenue integrations for a project.", - "operationId": "revenue_list_integrations", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/IntegrationResponse" - } - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "post": { - "tags": [ - "Revenue" - ], - "summary": "Create a new revenue integration. Response contains the generated\nwebhook path that the user must paste into their provider's dashboard.", - "operationId": "revenue_create_integration", - "parameters": [ - { - "name": "project_id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateIntegrationBody" - } - } - }, - "required": true - }, - "responses": { - "201": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/IntegrationResponse" - } - } - } - }, - "400": { - "description": "Validation error" - }, - "409": { - "description": "Already connected" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/revenue/integrations/{integration_id}": { - "delete": { - "tags": [ - "Revenue" - ], - "summary": "Delete a revenue integration (permanent \u2014 use rotate_token to refresh\ncredentials without breaking history).", - "operationId": "revenue_delete_integration", - "parameters": [ - { - "name": "project_id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "integration_id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "204": { - "description": "" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/revenue/integrations/{integration_id}/config": { - "post": { - "tags": [ - "Revenue" - ], - "summary": "Replace the typed provider config on an integration. Passing `null`\nclears the config back to the accept-everything default. The config's\nprovider tag must match the integration's provider.", - "operationId": "revenue_update_config", - "parameters": [ - { - "name": "project_id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "integration_id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdateConfigBody" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/IntegrationResponse" - } - } - } - }, - "400": { - "description": "Validation error" - }, - "404": { - "description": "Integration not found" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/revenue/integrations/{integration_id}/import/invoices": { - "post": { - "tags": [ - "Revenue" - ], - "summary": "Import a Stripe invoices CSV export. Each paid invoice becomes an\n`invoice.paid` event so historical MRR/charge totals populate the\ntimeseries. Ingestion is idempotent: re-uploading the same file is a\nno-op.", - "operationId": "revenue_import_invoices_csv", - "parameters": [ - { - "name": "project_id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "integration_id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ImportOutcomeResponse" - } - } - } - }, - "400": { - "description": "Malformed CSV or wrong provider" - }, - "404": { - "description": "Integration not found" - }, - "413": { - "description": "CSV too large" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/revenue/integrations/{integration_id}/import/subscriptions": { - "post": { - "tags": [ - "Revenue" - ], - "summary": "Import a Stripe subscriptions CSV export. Use this to backfill MRR /\nactive subscriptions when migrating from Stripe without providing\nAPI keys. Webhooks remain the source of truth for live updates \u2014\nCSV rows never overwrite newer webhook state.", - "operationId": "revenue_import_subscriptions_csv", - "parameters": [ - { - "name": "project_id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "integration_id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ImportOutcomeResponse" - } - } - } - }, - "400": { - "description": "Malformed CSV or wrong provider" - }, - "404": { - "description": "Integration not found" - }, - "413": { - "description": "CSV too large" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/revenue/integrations/{integration_id}/rotate-token": { - "post": { - "tags": [ - "Revenue" - ], - "summary": "Rotate the webhook path token. Returns the new integration state \u2014\nthe user must paste the new URL into their provider's dashboard.", - "operationId": "revenue_rotate_token", - "parameters": [ - { - "name": "project_id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "integration_id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/IntegrationResponse" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/revenue/integrations/{integration_id}/update-secret": { - "post": { - "tags": [ - "Revenue" - ], - "summary": "Replace the stored signing secret without rotating the webhook URL.\nUse this after rotating the secret in the provider's dashboard.", - "operationId": "revenue_update_secret", - "parameters": [ - { - "name": "project_id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "integration_id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdateSecretBody" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/IntegrationResponse" - } - } - } - }, - "400": { - "description": "Validation error" - }, - "404": { - "description": "Integration not found" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/revenue/metrics/customers": { - "get": { - "tags": [ - "Revenue" - ], - "summary": "New + churned customers per bucket.", - "operationId": "revenue_metrics_customers", - "parameters": [ - { - "name": "project_id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/CustomerMovementResponse" - } - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/revenue/metrics/mrr": { - "get": { - "tags": [ - "Revenue" - ], - "summary": "Bucketed MRR timeseries for the revenue chart.", - "operationId": "revenue_metrics_mrr", - "parameters": [ - { - "name": "project_id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/MrrBucketResponse" - } - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/revenue/metrics/summary": { - "get": { - "tags": [ - "Revenue" - ], - "summary": "Current MRR / ARR / churn / ARPU for a project, in one currency.", - "operationId": "revenue_metrics_summary", - "parameters": [ - { - "name": "project_id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/MetricsSummaryResponse" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/secrets": { - "get": { - "tags": [ - "Secrets" - ], - "summary": "List project secrets (metadata only \u2014 values never returned).", - "operationId": "listProjectSecrets", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "environment_id", - "in": "query", - "description": "Optional environment filter", - "required": false, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "List of secrets (metadata only, no values)", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ProjectSecretResponse" - } - } - } - } - }, - "404": { - "description": "Project not found" - }, - "500": { - "description": "Internal server error" - } - } - }, - "post": { - "tags": [ - "Secrets" - ], - "summary": "Create a new secret. The value is encrypted before storage and will be\nmounted as a file at `/run/secrets/` on the next deployment.\nThe plaintext value is NOT returned \u2014 the response carries only metadata.", - "operationId": "createProjectSecret", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateProjectSecretRequest" - } - } - }, - "required": true - }, - "responses": { - "201": { - "description": "Secret created", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProjectSecretResponse" - } - } - } - }, - "400": { - "description": "Invalid key or value too large" - }, - "409": { - "description": "Key already exists in project" - }, - "500": { - "description": "Internal server error" - } - } - } - }, - "/projects/{project_id}/secrets/{secret_id}": { - "put": { - "tags": [ - "Secrets" - ], - "summary": "Update a project secret. Value rotation requires a redeploy to take effect \u2014\nrunning containers keep their currently-mounted values until the next\ndeployment.", - "operationId": "updateProjectSecret", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "secret_id", - "in": "path", - "description": "Secret ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdateProjectSecretRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Secret updated", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProjectSecretResponse" - } - } - } - }, - "400": { - "description": "Value too large" - }, - "404": { - "description": "Secret not found" - }, - "500": { - "description": "Internal server error" - } - } - }, - "delete": { - "tags": [ - "Secrets" - ], - "summary": "Delete a project secret. Running containers keep their mounted secret files\nuntil they are redeployed.", - "operationId": "deleteProjectSecret", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "secret_id", - "in": "path", - "description": "Secret ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "204": { - "description": "Secret deleted" - }, - "404": { - "description": "Secret not found" - }, - "500": { - "description": "Internal server error" - } - } - } - }, - "/projects/{project_id}/settings": { - "post": { - "tags": [ - "Projects" - ], - "summary": "Update project settings", - "operationId": "update_project_settings", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdateProjectSettingsRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Project settings updated successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProjectResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Forbidden" - }, - "404": { - "description": "Project not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/skills": { - "get": { - "tags": [ - "Agents" - ], - "operationId": "list_skills", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ListSkillsResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "post": { - "tags": [ - "Agents" - ], - "operationId": "create_skill", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateSkillRequest" - } - } - }, - "required": true - }, - "responses": { - "201": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SkillDefinitionResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/skills/upload": { - "post": { - "tags": [ - "Agents" - ], - "summary": "Upload a skill with an archive (tar.gz) \u2014 project-scoped.", - "operationId": "upload_skill", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "requestBody": { - "content": { - "multipart/form-data": { - "schema": { - "type": "string" - } - } - }, - "required": true - }, - "responses": { - "201": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SkillDefinitionResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/skills/{slug}": { - "get": { - "tags": [ - "Agents" - ], - "operationId": "get_skill", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "slug", - "in": "path", - "description": "Skill slug", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SkillDefinitionResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "404": { - "description": "Skill not found" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "put": { - "tags": [ - "Agents" - ], - "operationId": "update_skill", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "slug", - "in": "path", - "description": "Skill slug", - "required": true, - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdateSkillRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SkillDefinitionResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "404": { - "description": "Skill not found" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "delete": { - "tags": [ - "Agents" - ], - "operationId": "delete_skill", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "slug", - "in": "path", - "description": "Skill slug", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "204": { - "description": "Skill deleted" - }, - "401": { - "description": "Unauthorized" - }, - "404": { - "description": "Skill not found" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/skills/{slug}/archive": { - "get": { - "tags": [ - "Agents" - ], - "summary": "Download a skill's archive (tar.gz) \u2014 project-scoped.", - "operationId": "download_skill_archive", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "slug", - "in": "path", - "description": "Skill slug", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Skill archive tar.gz", - "content": { - "application/gzip": {} - } - }, - "401": { - "description": "Unauthorized" - }, - "404": { - "description": "Skill not found or has no archive" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/source-map-releases": { - "get": { - "tags": [ - "source-maps" - ], - "summary": "List all releases that have source maps for a project", - "operationId": "list_releases", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "List of releases", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ReleaseListResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/source-maps/{source_map_id}": { - "delete": { - "tags": [ - "source-maps" - ], - "summary": "Delete a specific source map by ID", - "operationId": "delete_source_map", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "source_map_id", - "in": "path", - "description": "Source map ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "204": { - "description": "Source map deleted" - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "404": { - "description": "Source map not found" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/static-bundles": { - "get": { - "tags": [ - "Static Bundles" - ], - "summary": "List static bundles for a project", - "operationId": "list_static_bundles", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "page", - "in": "query", - "description": "Page number (default: 1)", - "required": false, - "schema": { - "type": "integer", - "format": "int64", - "minimum": 0 - } - }, - { - "name": "page_size", - "in": "query", - "description": "Items per page (default: 20)", - "required": false, - "schema": { - "type": "integer", - "format": "int64", - "minimum": 0 - } - } - ], - "responses": { - "200": { - "description": "List of static bundles", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/PaginatedStaticBundlesResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/static-bundles/{bundle_id}": { - "get": { - "tags": [ - "Static Bundles" - ], - "summary": "Get details of a specific static bundle", - "operationId": "get_static_bundle", - "parameters": [ - { - "name": "project_id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "bundle_id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Bundle details", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/StaticBundleResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "404": { - "description": "Bundle not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "delete": { - "tags": [ - "Static Bundles" - ], - "summary": "Delete a static bundle", - "operationId": "delete_static_bundle", - "parameters": [ - { - "name": "project_id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "bundle_id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "204": { - "description": "Bundle deleted" - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "404": { - "description": "Bundle not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/status": { - "get": { - "tags": [ - "Status Page" - ], - "summary": "Get status page overview", - "operationId": "get_status_overview", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "environment_id", - "in": "query", - "description": "Filter by environment ID", - "required": false, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Successfully retrieved status overview", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/StatusPageOverview" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/unique-counts": { - "get": { - "tags": [ - "Events" - ], - "summary": "Get unique counts over time frame", - "operationId": "get_unique_counts", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "start_date", - "in": "query", - "description": "Start date in '%Y-%m-%d %H:%M:%S' format", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "end_date", - "in": "query", - "description": "End date in '%Y-%m-%d %H:%M:%S' format", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "environment_id", - "in": "query", - "description": "Filter by environment ID", - "required": false, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "deployment_id", - "in": "query", - "description": "Filter by deployment ID", - "required": false, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "metric", - "in": "query", - "description": "Metric to count: 'sessions' (unique sessions), 'visitors' (unique visitors), 'returning_visitors' (visitors seen before the range), or 'page_views' (total page views) (default: 'sessions')", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Successfully retrieved count", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UniqueCountsResponse" - } - } - } - }, - "400": { - "description": "Bad request" - }, - "401": { - "description": "Unauthorized" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/upload/static": { - "post": { - "tags": [ - "Static Bundles" - ], - "summary": "Upload a static bundle for later deployment", - "description": "Uploads a tar.gz or zip file containing static assets. The bundle can be\ndeployed later using the deploy/static endpoint.", - "operationId": "upload_static_bundle", - "parameters": [ - { - "name": "project_id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "201": { - "description": "Bundle uploaded successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/StaticBundleResponse" - } - } - } - }, - "400": { - "description": "Invalid request or unsupported format" - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "404": { - "description": "Project not found" - }, - "413": { - "description": "Bundle too large" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/vulnerability-scans": { - "get": { - "tags": [ - "Vulnerability Scans" - ], - "operationId": "list_project_scans", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "page", - "in": "query", - "description": "Page number (default: 1)", - "required": false, - "schema": { - "type": "integer", - "format": "int64", - "minimum": 0 - } - }, - { - "name": "page_size", - "in": "query", - "description": "Page size (default: 20, max: 100)", - "required": false, - "schema": { - "type": "integer", - "format": "int64", - "minimum": 0 - } - } - ], - "responses": { - "200": { - "description": "List of vulnerability scans", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ScanResponse" - } - } - } - } - }, - "401": { - "description": "Unauthorized", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "403": { - "description": "Insufficient permissions", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "post": { - "tags": [ - "Vulnerability Scans" - ], - "operationId": "trigger_scan", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/TriggerScanRequest" - } - } - }, - "required": true - }, - "responses": { - "202": { - "description": "Scan triggered successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/TriggerScanResponse" - } - } - } - }, - "400": { - "description": "Invalid request", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "401": { - "description": "Unauthorized", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "403": { - "description": "Insufficient permissions", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/vulnerability-scans/environments": { - "get": { - "tags": [ - "Vulnerability Scans" - ], - "operationId": "get_latest_scans_per_environment", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Latest scans per environment for current deployments", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ScanResponse" - } - } - } - } - }, - "401": { - "description": "Unauthorized", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "403": { - "description": "Insufficient permissions", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/vulnerability-scans/latest": { - "get": { - "tags": [ - "Vulnerability Scans" - ], - "operationId": "get_latest_scan", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "environment_id", - "in": "query", - "description": "Filter by environment ID", - "required": false, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Latest scan for project", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ScanResponse" - } - } - } - }, - "401": { - "description": "Unauthorized", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "403": { - "description": "Insufficient permissions", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "404": { - "description": "No scans found", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/webhooks": { - "get": { - "tags": [ - "Webhooks" - ], - "summary": "List all webhooks for a project", - "operationId": "list_webhooks", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "page", - "in": "query", - "description": "Page number (1-indexed)", - "required": false, - "schema": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "minimum": 0 - }, - "example": 1 - }, - { - "name": "page_size", - "in": "query", - "description": "Number of items per page (max 100)", - "required": false, - "schema": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "minimum": 0 - }, - "example": 20 - }, - { - "name": "sort_by", - "in": "query", - "required": false, - "schema": { - "type": [ - "string", - "null" - ] - } - }, - { - "name": "sort_order", - "in": "query", - "required": false, - "schema": { - "type": [ - "string", - "null" - ] - } - } - ], - "responses": { - "200": { - "description": "List of webhooks", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/WebhookResponse" - } - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Forbidden" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "post": { - "tags": [ - "Webhooks" - ], - "summary": "Create a new webhook", - "operationId": "create_webhook", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateWebhookRequestBody" - } - } - }, - "required": true - }, - "responses": { - "201": { - "description": "Webhook created", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/WebhookResponse" - } - } - } - }, - "400": { - "description": "Invalid request" - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Forbidden" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/webhooks/{webhook_id}": { - "get": { - "tags": [ - "Webhooks" - ], - "summary": "Get a specific webhook", - "operationId": "get_webhook", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "webhook_id", - "in": "path", - "description": "Webhook ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Webhook details", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/WebhookResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Forbidden" - }, - "404": { - "description": "Webhook not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "put": { - "tags": [ - "Webhooks" - ], - "summary": "Update a webhook", - "operationId": "update_webhook", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "webhook_id", - "in": "path", - "description": "Webhook ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdateWebhookRequestBody" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Webhook updated", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/WebhookResponse" - } - } - } - }, - "400": { - "description": "Invalid request" - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Forbidden" - }, - "404": { - "description": "Webhook not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "delete": { - "tags": [ - "Webhooks" - ], - "summary": "Delete a webhook", - "operationId": "delete_webhook", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "webhook_id", - "in": "path", - "description": "Webhook ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "204": { - "description": "Webhook deleted" - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Forbidden" - }, - "404": { - "description": "Webhook not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/webhooks/{webhook_id}/deliveries": { - "get": { - "tags": [ - "Webhook Deliveries" - ], - "summary": "List webhook deliveries", - "operationId": "list_deliveries", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "webhook_id", - "in": "path", - "description": "Webhook ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "limit", - "in": "query", - "description": "Number of deliveries to return (default: 50)", - "required": false, - "schema": { - "type": "integer", - "format": "int64", - "minimum": 0 - } - } - ], - "responses": { - "200": { - "description": "List of deliveries", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/WebhookDeliveryResponse" - } - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Forbidden" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/webhooks/{webhook_id}/deliveries/{delivery_id}": { - "get": { - "tags": [ - "Webhook Deliveries" - ], - "summary": "Get a specific webhook delivery by ID", - "operationId": "get_delivery", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "webhook_id", - "in": "path", - "description": "Webhook ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "delivery_id", - "in": "path", - "description": "Delivery ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Delivery details including full payload", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/WebhookDeliveryResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Forbidden" - }, - "404": { - "description": "Delivery not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/webhooks/{webhook_id}/deliveries/{delivery_id}/retry": { - "post": { - "tags": [ - "Webhook Deliveries" - ], - "summary": "Retry a failed delivery", - "operationId": "retry_delivery", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "webhook_id", - "in": "path", - "description": "Webhook ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "delivery_id", - "in": "path", - "description": "Delivery ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Delivery retried", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/WebhookDeliveryResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Forbidden" - }, - "404": { - "description": "Delivery not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/projects/{project_id}/workflows/dry-run": { - "post": { - "tags": [ - "Workflows" - ], - "operationId": "workflow_dry_run", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/WorkflowDryRunRequest" - } - } - }, - "required": true - }, - "responses": { - "202": { - "description": "Ephemeral run created and queued", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AgentRunResponse" - } - } - } - }, - "400": { - "description": "Validation error (bad YAML, oversized payload, capped limits exceeded)" - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "404": { - "description": "Project not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/proxy-logs": { - "get": { - "tags": [ - "Proxy Logs" - ], - "summary": "Get proxy logs with optional filters and pagination", - "operationId": "get_proxy_logs", - "parameters": [ - { - "name": "project_id", - "in": "query", - "description": "Filter by project ID", - "required": false, - "schema": { - "type": [ - "integer", - "null" - ], - "format": "int32" - } - }, - { - "name": "environment_id", - "in": "query", - "description": "Filter by environment ID", - "required": false, - "schema": { - "type": [ - "integer", - "null" - ], - "format": "int32" - } - }, - { - "name": "deployment_id", - "in": "query", - "description": "Filter by deployment ID", - "required": false, - "schema": { - "type": [ - "integer", - "null" - ], - "format": "int32" - } - }, - { - "name": "session_id", - "in": "query", - "description": "Filter by session ID", - "required": false, - "schema": { - "type": [ - "integer", - "null" - ], - "format": "int32" - } - }, - { - "name": "visitor_id", - "in": "query", - "description": "Filter by visitor ID", - "required": false, - "schema": { - "type": [ - "integer", - "null" - ], - "format": "int32" - } - }, - { - "name": "start_date", - "in": "query", - "description": "Start date for filtering (ISO 8601 format).\n\n**Defaults to 1 hour before `end_date` (or before now) when omitted.**\nThe listing is always time-bounded: an unbounded query would have to\nconsider the entire retention window \u2014 100M+ rows on a busy deployment \u2014\nto return a single page. Pass an explicit `start_date` to widen the\nwindow, up to the configured retention horizon.\n\nThe maximum span between `start_date` and `end_date` is 7 days when\n`project_id` is omitted, or 30 days when a single `project_id` is set \u2014\na project-scoped query is bounded by that project's own row count\nrather than the whole deployment's. A wider request is rejected with a\n400 naming the applicable cap.", - "required": false, - "schema": { - "type": [ - "string", - "null" - ], - "format": "date-time" - } - }, - { - "name": "end_date", - "in": "query", - "description": "End date for filtering (ISO 8601 format). Defaults to now.", - "required": false, - "schema": { - "type": [ - "string", - "null" - ], - "format": "date-time" - } - }, - { - "name": "method", - "in": "query", - "description": "Filter by HTTP method (GET, POST, etc.)", - "required": false, - "schema": { - "type": [ - "string", - "null" - ] - } - }, - { - "name": "host", - "in": "query", - "description": "Filter by host header", - "required": false, - "schema": { - "type": [ - "string", - "null" - ] - } - }, - { - "name": "path", - "in": "query", - "description": "Filter by path (supports partial match)", - "required": false, - "schema": { - "type": [ - "string", - "null" - ] - } - }, - { - "name": "client_ip", - "in": "query", - "description": "Filter by client IP address", - "required": false, - "schema": { - "type": [ - "string", - "null" - ] - } - }, - { - "name": "status_code", - "in": "query", - "description": "Filter by HTTP status code", - "required": false, - "schema": { - "type": [ - "integer", - "null" - ], - "format": "int32" - } - }, - { - "name": "response_time_min", - "in": "query", - "description": "Filter by minimum response time in ms", - "required": false, - "schema": { - "type": [ - "integer", - "null" - ], - "format": "int32" - } - }, - { - "name": "response_time_max", - "in": "query", - "description": "Filter by maximum response time in ms", - "required": false, - "schema": { - "type": [ - "integer", - "null" - ], - "format": "int32" - } - }, - { - "name": "routing_status", - "in": "query", - "description": "Filter by routing status (routed, no_project, error, pending)", - "required": false, - "schema": { - "type": [ - "string", - "null" - ] - } - }, - { - "name": "request_source", - "in": "query", - "description": "Filter by request source (proxy, api, console, cli)", - "required": false, - "schema": { - "type": [ - "string", - "null" - ] - } - }, - { - "name": "is_system_request", - "in": "query", - "description": "Filter by system request flag", - "required": false, - "schema": { - "type": [ - "boolean", - "null" - ] - } - }, - { - "name": "user_agent", - "in": "query", - "description": "Filter by user agent string (partial match)", - "required": false, - "schema": { - "type": [ - "string", - "null" - ] - } - }, - { - "name": "browser", - "in": "query", - "description": "Filter by browser name", - "required": false, - "schema": { - "type": [ - "string", - "null" - ] - } - }, - { - "name": "operating_system", - "in": "query", - "description": "Filter by operating system", - "required": false, - "schema": { - "type": [ - "string", - "null" - ] - } - }, - { - "name": "device_type", - "in": "query", - "description": "Filter by device type (mobile, desktop, tablet)", - "required": false, - "schema": { - "type": [ - "string", - "null" - ] - } - }, - { - "name": "is_bot", - "in": "query", - "description": "Filter by bot detection", - "required": false, - "schema": { - "type": [ - "boolean", - "null" - ] - } - }, - { - "name": "exclude_bots", - "in": "query", - "description": "When `true`, exclude rows flagged as bots while KEEPING rows whose\n`is_bot` is NULL (older rows without detection metadata). This is the\ntri-state complement of `is_bot=false`, which matches only rows\nexplicitly detected as non-bots. `false`/omitted is a no-op.", - "required": false, - "schema": { - "type": [ - "boolean", - "null" - ] - } - }, - { - "name": "bot_name", - "in": "query", - "description": "Filter by bot name", - "required": false, - "schema": { - "type": [ - "string", - "null" - ] - } - }, - { - "name": "ai_provider", - "in": "query", - "description": "Filter by AI provider (e.g. `OpenAI`, `Anthropic`, `Perplexity`). Matches\nthe canonical provider returned by the AI agent detector.", - "required": false, - "schema": { - "type": [ - "string", - "null" - ] - } - }, - { - "name": "ai_agent", - "in": "query", - "description": "Filter by AI agent name (e.g. `GPTBot`, `ChatGPT-User`). Equivalent to\nfiltering `bot_name` against a known AI taxonomy.", - "required": false, - "schema": { - "type": [ - "string", - "null" - ] - } - }, - { - "name": "is_ai_agent", - "in": "query", - "description": "When `true`, only return requests classified as known AI agents\n(regardless of provider/agent). Mutually compatible with the above.", - "required": false, - "schema": { - "type": [ - "boolean", - "null" - ] - } - }, - { - "name": "request_size_min", - "in": "query", - "description": "Filter by minimum request size in bytes", - "required": false, - "schema": { - "type": [ - "integer", - "null" - ], - "format": "int64" - } - }, - { - "name": "request_size_max", - "in": "query", - "description": "Filter by maximum request size in bytes", - "required": false, - "schema": { - "type": [ - "integer", - "null" - ], - "format": "int64" - } - }, - { - "name": "response_size_min", - "in": "query", - "description": "Filter by minimum response size in bytes", - "required": false, - "schema": { - "type": [ - "integer", - "null" - ], - "format": "int64" - } - }, - { - "name": "response_size_max", - "in": "query", - "description": "Filter by maximum response size in bytes", - "required": false, - "schema": { - "type": [ - "integer", - "null" - ], - "format": "int64" - } - }, - { - "name": "cache_status", - "in": "query", - "description": "Filter by cache status", - "required": false, - "schema": { - "type": [ - "string", - "null" - ] - } - }, - { - "name": "container_id", - "in": "query", - "description": "Filter by container ID", - "required": false, - "schema": { - "type": [ - "string", - "null" - ] - } - }, - { - "name": "upstream_host", - "in": "query", - "description": "Filter by upstream host", - "required": false, - "schema": { - "type": [ - "string", - "null" - ] - } - }, - { - "name": "has_error", - "in": "query", - "description": "Filter by presence of error message", - "required": false, - "schema": { - "type": [ - "boolean", - "null" - ] - } - }, - { - "name": "page", - "in": "query", - "description": "Page number (default: 1)", - "required": false, - "schema": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "minimum": 0 - } - }, - { - "name": "page_size", - "in": "query", - "description": "Page size (default: 20, max: 100)", - "required": false, - "schema": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "minimum": 0 - } - }, - { - "name": "sort_by", - "in": "query", - "description": "Sort by field (default: timestamp)", - "required": false, - "schema": { - "type": [ - "string", - "null" - ] - } - }, - { - "name": "sort_order", - "in": "query", - "description": "Sort order (asc or desc, default: desc)", - "required": false, - "schema": { - "type": [ - "string", - "null" - ] - } - } - ], - "responses": { - "200": { - "description": "List of proxy logs", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProxyLogsPaginatedResponse" - } - } - } - }, - "401": { - "description": "Unauthorized", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "403": { - "description": "Insufficient permissions", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/proxy-logs/ai-agents/known": { - "get": { - "tags": [ - "Proxy Logs" - ], - "summary": "List every AI agent the detector knows how to classify.", - "description": "Returned in the same order as the internal taxonomy so the UI can use it as\na stable dropdown.", - "operationId": "list_known_ai_agents", - "responses": { - "200": { - "description": "Known AI agents", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/KnownAiAgentsResponse" - } - } - } - }, - "401": { - "description": "Unauthorized", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "403": { - "description": "Insufficient permissions", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/proxy-logs/request/{request_id}": { - "get": { - "tags": [ - "Proxy Logs" - ], - "summary": "Get a proxy log by request ID (for tracing)", - "operationId": "get_proxy_log_by_request_id", - "parameters": [ - { - "name": "request_id", - "in": "path", - "description": "Request ID from pingora", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "timestamp", - "in": "query", - "description": "Event time of the log row (ISO 8601). When provided, the lookup is\nbounded to the hypertable chunks around this instant instead of\nscanning (and decompressing) the whole retention window. The list\nendpoint already returns this value per row \u2014 always pass it when\nnavigating from a list.", - "required": false, - "schema": { - "type": [ - "string", - "null" - ], - "format": "date-time" - } - } - ], - "responses": { - "200": { - "description": "Proxy log found", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProxyLogResponse" - } - } - } - }, - "401": { - "description": "Unauthorized", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "403": { - "description": "Insufficient permissions", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "404": { - "description": "Proxy log not found", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/proxy-logs/stats/ai-agent-pages": { - "get": { - "tags": [ - "Proxy Logs" - ], - "summary": "Get the top pages accessed by a specific AI agent over a time window.", - "description": "Returns page paths ranked by request count, scoped to a single canonical\nagent name (e.g. `ChatGPT-User`). Use `GET /proxy-logs/ai-agents/known` to\nlist all valid agent names. Unknown agent names return an empty items array.", - "operationId": "get_ai_agent_pages", - "parameters": [ - { - "name": "agent", - "in": "query", - "description": "Canonical agent name to filter by (e.g. `ChatGPT-User`, `ClaudeBot`).\nMust be a name returned by `GET /proxy-logs/ai-agents/known`.", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "project_id", - "in": "query", - "description": "Filter by project ID.", - "required": false, - "schema": { - "type": [ - "integer", - "null" - ], - "format": "int32" - } - }, - { - "name": "environment_id", - "in": "query", - "description": "Filter by environment ID.", - "required": false, - "schema": { - "type": [ - "integer", - "null" - ], - "format": "int32" - } - }, - { - "name": "start_time", - "in": "query", - "description": "Start time (ISO 8601). Defaults to `end_time - 7d`.", - "required": false, - "schema": { - "type": [ - "string", - "null" - ] - }, - "example": "2026-05-22T00:00:00Z" - }, - { - "name": "end_time", - "in": "query", - "description": "End time (ISO 8601). Defaults to now.", - "required": false, - "schema": { - "type": [ - "string", - "null" - ] - }, - "example": "2026-05-29T00:00:00Z" - }, - { - "name": "limit", - "in": "query", - "description": "Maximum rows to return. Capped at 100 server-side.", - "required": false, - "schema": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "minimum": 0 - } - } - ], - "responses": { - "200": { - "description": "Pages breakdown for the requested agent", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AiAgentPagesResponse" - } - } - } - }, - "400": { - "description": "Invalid parameters", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "401": { - "description": "Unauthorized", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "403": { - "description": "Insufficient permissions", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/proxy-logs/stats/ai-agents": { - "get": { - "tags": [ - "Proxy Logs" - ], - "summary": "Get the per-AI-agent breakdown for a project over a time window.", - "operationId": "get_ai_agent_breakdown", - "parameters": [ - { - "name": "project_id", - "in": "query", - "description": "Filter by project ID (recommended for per-project analytics).", - "required": false, - "schema": { - "type": [ - "integer", - "null" - ], - "format": "int32" - } - }, - { - "name": "environment_id", - "in": "query", - "description": "Filter by environment ID.", - "required": false, - "schema": { - "type": [ - "integer", - "null" - ], - "format": "int32" - } - }, - { - "name": "start_time", - "in": "query", - "description": "Start time (ISO 8601). Defaults to `end_time - 7d`.", - "required": false, - "schema": { - "type": [ - "string", - "null" - ] - }, - "example": "2026-05-22T00:00:00Z" - }, - { - "name": "end_time", - "in": "query", - "description": "End time (ISO 8601). Defaults to now.", - "required": false, - "schema": { - "type": [ - "string", - "null" - ] - }, - "example": "2026-05-29T00:00:00Z" - }, - { - "name": "limit", - "in": "query", - "description": "Maximum rows to return. Capped at 100 server-side.", - "required": false, - "schema": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "minimum": 0 - } - }, - { - "name": "path", - "in": "query", - "description": "Optional exact path filter. Only used by the AI pages breakdown \u2014 when\nset, returns the single matching page so callers can ask \"how many AI\nagents hit this page?\".", - "required": false, - "schema": { - "type": [ - "string", - "null" - ] - } - } - ], - "responses": { - "200": { - "description": "AI agent breakdown", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AiAgentBreakdownResponse" - } - } - } - }, - "400": { - "description": "Invalid parameters", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "401": { - "description": "Unauthorized", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "403": { - "description": "Insufficient permissions", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/proxy-logs/stats/ai-agents/timeline": { - "get": { - "tags": [ - "Proxy Logs" - ], - "summary": "Time-bucketed AI-agent request volume, split by provider or agent.", - "description": "Powers the \"AI agents over time\" stacked chart. Same data source as the AI\nagent breakdown (request logs), just bucketed.", - "operationId": "get_ai_agent_timeline", - "parameters": [ - { - "name": "project_id", - "in": "query", - "description": "Filter by project ID.", - "required": false, - "schema": { - "type": [ - "integer", - "null" - ], - "format": "int32" - } - }, - { - "name": "environment_id", - "in": "query", - "description": "Filter by environment ID.", - "required": false, - "schema": { - "type": [ - "integer", - "null" - ], - "format": "int32" - } - }, - { - "name": "start_time", - "in": "query", - "description": "Start time (ISO 8601). Defaults to `end_time - 7d`.", - "required": false, - "schema": { - "type": [ - "string", - "null" - ] - }, - "example": "2026-05-22T00:00:00Z" - }, - { - "name": "end_time", - "in": "query", - "description": "End time (ISO 8601). Defaults to now.", - "required": false, - "schema": { - "type": [ - "string", - "null" - ] - }, - "example": "2026-05-29T00:00:00Z" - }, - { - "name": "group_by", - "in": "query", - "description": "Grouping dimension: `provider` (default) or `agent`.", - "required": false, - "schema": { - "type": [ - "string", - "null" - ] - }, - "example": "provider" - }, - { - "name": "bucket", - "in": "query", - "description": "Bucket interval override (e.g. `1 hour`, `1 day`). Auto-selected from the\nwindow width when omitted.", - "required": false, - "schema": { - "type": [ - "string", - "null" - ] - }, - "example": "1 hour" - } - ], - "responses": { - "200": { - "description": "AI agent timeline", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AiAgentTimelineResponse" - } - } - } - }, - "400": { - "description": "Invalid parameters", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "401": { - "description": "Unauthorized", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "403": { - "description": "Insufficient permissions", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/proxy-logs/stats/ai-pages": { - "get": { - "tags": [ - "Proxy Logs" - ], - "summary": "Get the top pages crawled by AI agents over a time window.", - "operationId": "get_ai_page_breakdown", - "parameters": [ - { - "name": "project_id", - "in": "query", - "description": "Filter by project ID (recommended for per-project analytics).", - "required": false, - "schema": { - "type": [ - "integer", - "null" - ], - "format": "int32" - } - }, - { - "name": "environment_id", - "in": "query", - "description": "Filter by environment ID.", - "required": false, - "schema": { - "type": [ - "integer", - "null" - ], - "format": "int32" - } - }, - { - "name": "start_time", - "in": "query", - "description": "Start time (ISO 8601). Defaults to `end_time - 7d`.", - "required": false, - "schema": { - "type": [ - "string", - "null" - ] - }, - "example": "2026-05-22T00:00:00Z" - }, - { - "name": "end_time", - "in": "query", - "description": "End time (ISO 8601). Defaults to now.", - "required": false, - "schema": { - "type": [ - "string", - "null" - ] - }, - "example": "2026-05-29T00:00:00Z" - }, - { - "name": "limit", - "in": "query", - "description": "Maximum rows to return. Capped at 100 server-side.", - "required": false, - "schema": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "minimum": 0 - } - }, - { - "name": "path", - "in": "query", - "description": "Optional exact path filter. Only used by the AI pages breakdown \u2014 when\nset, returns the single matching page so callers can ask \"how many AI\nagents hit this page?\".", - "required": false, - "schema": { - "type": [ - "string", - "null" - ] - } - } - ], - "responses": { - "200": { - "description": "AI page breakdown", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AiPageBreakdownResponse" - } - } - } - }, - "400": { - "description": "Invalid parameters", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "401": { - "description": "Unauthorized", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "403": { - "description": "Insufficient permissions", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/proxy-logs/stats/ai-status": { - "get": { - "tags": [ - "Proxy Logs" - ], - "summary": "HTTP status-class breakdown for AI-agent traffic \u2014 are bots being served\n(2xx) or hitting broken/blocked pages (4xx/5xx)?", - "operationId": "get_ai_status_breakdown", - "parameters": [ - { - "name": "project_id", - "in": "query", - "description": "Filter by project ID (recommended for per-project analytics).", - "required": false, - "schema": { - "type": [ - "integer", - "null" - ], - "format": "int32" - } - }, - { - "name": "environment_id", - "in": "query", - "description": "Filter by environment ID.", - "required": false, - "schema": { - "type": [ - "integer", - "null" - ], - "format": "int32" - } - }, - { - "name": "start_time", - "in": "query", - "description": "Start time (ISO 8601). Defaults to `end_time - 7d`.", - "required": false, - "schema": { - "type": [ - "string", - "null" - ] - }, - "example": "2026-05-22T00:00:00Z" - }, - { - "name": "end_time", - "in": "query", - "description": "End time (ISO 8601). Defaults to now.", - "required": false, - "schema": { - "type": [ - "string", - "null" - ] - }, - "example": "2026-05-29T00:00:00Z" - }, - { - "name": "limit", - "in": "query", - "description": "Maximum rows to return. Capped at 100 server-side.", - "required": false, - "schema": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "minimum": 0 - } - }, - { - "name": "path", - "in": "query", - "description": "Optional exact path filter. Only used by the AI pages breakdown \u2014 when\nset, returns the single matching page so callers can ask \"how many AI\nagents hit this page?\".", - "required": false, - "schema": { - "type": [ - "string", - "null" - ] - } - } - ], - "responses": { - "200": { - "description": "AI status breakdown", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AiStatusBreakdownResponse" - } - } - } - }, - "400": { - "description": "Invalid parameters", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "401": { - "description": "Unauthorized", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "403": { - "description": "Insufficient permissions", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/proxy-logs/stats/projects-health": { - "get": { - "tags": [ - "Proxy Logs" - ], - "summary": "Get health summaries for multiple projects (last 1 hour)", - "operationId": "get_projects_health", - "parameters": [ - { - "name": "project_ids", - "in": "query", - "description": "Comma-separated list of project IDs", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "start_time", - "in": "query", - "description": "Optional start time (ISO 8601). Defaults to `end_time - 1h`.", - "required": false, - "schema": { - "type": [ - "string", - "null" - ] - }, - "example": "2025-10-23T00:00:00Z" - }, - { - "name": "end_time", - "in": "query", - "description": "Optional end time (ISO 8601). Defaults to now.", - "required": false, - "schema": { - "type": [ - "string", - "null" - ] - }, - "example": "2025-10-23T23:59:59Z" - }, - { - "name": "is_bot", - "in": "query", - "description": "Filter by bot detection. Pass `false` to exclude bots, `true` for bots only.", - "required": false, - "schema": { - "type": [ - "boolean", - "null" - ] - } - } - ], - "responses": { - "200": { - "description": "Health summaries per project", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProjectsHealthResponse" - } - } - } - }, - "400": { - "description": "Invalid parameters", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "401": { - "description": "Unauthorized", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "403": { - "description": "Insufficient permissions", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/proxy-logs/stats/time-buckets": { - "get": { - "tags": [ - "Proxy Logs" - ], - "summary": "Get time-bucketed statistics with optional filters", - "operationId": "get_time_bucket_stats", - "parameters": [ - { - "name": "start_time", - "in": "query", - "description": "Start time (ISO 8601 format)", - "required": true, - "schema": { - "type": "string" - }, - "example": "2025-10-23T00:00:00Z" - }, - { - "name": "end_time", - "in": "query", - "description": "End time (ISO 8601 format)", - "required": true, - "schema": { - "type": "string" - }, - "example": "2025-10-23T23:59:59Z" - }, - { - "name": "bucket_interval", - "in": "query", - "description": "Bucket interval (e.g., \"1 hour\", \"1 day\", \"5 minutes\")", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "method", - "in": "query", - "description": "Filter by HTTP method", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "client_ip", - "in": "query", - "description": "Filter by client IP", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "project_id", - "in": "query", - "description": "Filter by project ID", - "required": false, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "environment_id", - "in": "query", - "description": "Filter by environment ID", - "required": false, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "deployment_id", - "in": "query", - "description": "Filter by deployment ID", - "required": false, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "host", - "in": "query", - "description": "Filter by host", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "status_code", - "in": "query", - "description": "Filter by status code", - "required": false, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "status_code_class", - "in": "query", - "description": "Filter by status code class (e.g. \"2xx\", \"3xx\", \"4xx\", \"5xx\")", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "routing_status", - "in": "query", - "description": "Filter by routing status", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "request_source", - "in": "query", - "description": "Filter by request source", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "is_bot", - "in": "query", - "description": "Filter by bot detection", - "required": false, - "schema": { - "type": "boolean" - } - }, - { - "name": "device_type", - "in": "query", - "description": "Filter by device type", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "has_project", - "in": "query", - "description": "When true, only count requests that matched a project\n(project_id IS NOT NULL). Makes chart totals line up with the\nper-project health cards.", - "required": false, - "schema": { - "type": "boolean" - } - } - ], - "responses": { - "200": { - "description": "Time-bucketed statistics", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/TimeBucketStatsResponse" - } - } - } - }, - "400": { - "description": "Invalid parameters", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "401": { - "description": "Unauthorized", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "403": { - "description": "Insufficient permissions", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/proxy-logs/stats/today": { - "get": { - "tags": [ - "Proxy Logs" - ], - "summary": "Get today's request count with optional filters", - "operationId": "get_today_stats", - "parameters": [ - { - "name": "method", - "in": "query", - "description": "Filter by HTTP method", - "required": false, - "schema": { - "type": [ - "string", - "null" - ] - } - }, - { - "name": "client_ip", - "in": "query", - "description": "Filter by client IP", - "required": false, - "schema": { - "type": [ - "string", - "null" - ] - } - }, - { - "name": "project_id", - "in": "query", - "description": "Filter by project ID", - "required": false, - "schema": { - "type": [ - "integer", - "null" - ], - "format": "int32" - } - }, - { - "name": "environment_id", - "in": "query", - "description": "Filter by environment ID", - "required": false, - "schema": { - "type": [ - "integer", - "null" - ], - "format": "int32" - } - }, - { - "name": "deployment_id", - "in": "query", - "description": "Filter by deployment ID", - "required": false, - "schema": { - "type": [ - "integer", - "null" - ], - "format": "int32" - } - }, - { - "name": "host", - "in": "query", - "description": "Filter by host", - "required": false, - "schema": { - "type": [ - "string", - "null" - ] - } - }, - { - "name": "status_code", - "in": "query", - "description": "Filter by status code", - "required": false, - "schema": { - "type": [ - "integer", - "null" - ], - "format": "int32" - } - }, - { - "name": "status_code_class", - "in": "query", - "description": "Filter by status code class (e.g. \"2xx\", \"3xx\", \"4xx\", \"5xx\")", - "required": false, - "schema": { - "type": [ - "string", - "null" - ] - } - }, - { - "name": "routing_status", - "in": "query", - "description": "Filter by routing status", - "required": false, - "schema": { - "type": [ - "string", - "null" - ] - } - }, - { - "name": "request_source", - "in": "query", - "description": "Filter by request source", - "required": false, - "schema": { - "type": [ - "string", - "null" - ] - } - }, - { - "name": "is_bot", - "in": "query", - "description": "Filter by bot detection", - "required": false, - "schema": { - "type": [ - "boolean", - "null" - ] - } - }, - { - "name": "device_type", - "in": "query", - "description": "Filter by device type", - "required": false, - "schema": { - "type": [ - "string", - "null" - ] - } - } - ], - "responses": { - "200": { - "description": "Today's request count", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/TodayStatsResponse" - } - } - } - }, - "401": { - "description": "Unauthorized", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "403": { - "description": "Insufficient permissions", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/proxy-logs/{id}": { - "get": { - "tags": [ - "Proxy Logs" - ], - "summary": "Get a single proxy log by ID", - "operationId": "get_proxy_log_by_id", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "Proxy log ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "timestamp", - "in": "query", - "description": "Event time of the log row (ISO 8601). When provided, the lookup is\nbounded to the hypertable chunks around this instant instead of\nscanning (and decompressing) the whole retention window. The list\nendpoint already returns this value per row \u2014 always pass it when\nnavigating from a list.", - "required": false, - "schema": { - "type": [ - "string", - "null" - ], - "format": "date-time" - } - } - ], - "responses": { - "200": { - "description": "Proxy log found", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProxyLogResponse" - } - } - } - }, - "401": { - "description": "Unauthorized", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "403": { - "description": "Insufficient permissions", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "404": { - "description": "Proxy log not found", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/repositories": { - "get": { - "tags": [ - "Git Providers" - ], - "summary": "List synced repositories with advanced filtering", - "description": "Lists repositories that have been synced to the database with filtering options.\nThis provides fast access to repository metadata with filtering by connection, search, and other criteria.", - "operationId": "list_synced_repositories", - "parameters": [ - { - "name": "page", - "in": "query", - "description": "Page number for pagination", - "required": false, - "schema": { - "type": "integer", - "format": "int64", - "minimum": 0 - } - }, - { - "name": "per_page", - "in": "query", - "description": "Number of items per page (max 100)", - "required": false, - "schema": { - "type": "integer", - "format": "int64", - "minimum": 0 - } - }, - { - "name": "sort", - "in": "query", - "description": "Sort field (name, created_at, updated_at, stars, watchers, size, issues)", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "direction", - "in": "query", - "description": "Sort direction (asc, desc)", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "search", - "in": "query", - "description": "Search term to filter repositories", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "owner", - "in": "query", - "description": "Filter by repository owner", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "language", - "in": "query", - "description": "Filter by programming language", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "private", - "in": "query", - "description": "Filter by private status (true/false)", - "required": false, - "schema": { - "type": "boolean" - } - }, - { - "name": "git_provider_connection_id", - "in": "query", - "description": "Filter by git provider connection ID", - "required": false, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "List of synced repositories", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/RepositoryListResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/repositories/{owner}/{name}": { - "get": { - "tags": [ - "Git Providers" - ], - "summary": "Get repository by owner and name from any connection", - "operationId": "get_repository_by_name", - "parameters": [ - { - "name": "owner", - "in": "path", - "description": "Repository owner", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "name", - "in": "path", - "description": "Repository name", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "connection_id", - "in": "query", - "description": "Optional specific connection ID to search", - "required": false, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Repository found", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/RepositoryResponse" - } - } - } - }, - "404": { - "description": "Repository not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/repositories/{owner}/{name}/all": { - "get": { - "tags": [ - "Git Providers" - ], - "summary": "Get all repositories with same owner/name from all git providers", - "operationId": "get_all_repositories_by_name", - "parameters": [ - { - "name": "owner", - "in": "path", - "description": "Repository owner", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "name", - "in": "path", - "description": "Repository name", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Repositories found from all providers", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/RepositoryResponse" - } - } - } - } - }, - "404": { - "description": "No repositories found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/repositories/{owner}/{name}/preset": { - "get": { - "tags": [ - "Git Providers" - ], - "summary": "Get repository preset by owner and name", - "operationId": "get_repository_preset_by_name", - "parameters": [ - { - "name": "owner", - "in": "path", - "description": "Repository owner", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "name", - "in": "path", - "description": "Repository name", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "branch", - "in": "query", - "description": "Git branch to check (defaults to repository's default branch)", - "required": false, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Repository preset calculated successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/RepositoryPresetResponse" - } - } - } - }, - "404": { - "description": "Repository not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/repositories/{owner}/{repo}/branches": { - "get": { - "tags": [ - "Repositories" - ], - "summary": "Get repository branches", - "operationId": "get_repository_branches", - "parameters": [ - { - "name": "owner", - "in": "path", - "description": "Repository owner", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "repo", - "in": "path", - "description": "Repository name", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "connection_id", - "in": "query", - "description": "Git provider connection ID (required when multiple connections have the same repo)", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "fresh", - "in": "query", - "description": "Force fetch fresh data, bypassing cache (default: false)", - "required": false, - "schema": { - "type": "boolean" - } - } - ], - "responses": { - "200": { - "description": "List of branches", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/BranchListResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "404": { - "description": "Repository not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/repositories/{owner}/{repo}/tags": { - "get": { - "tags": [ - "Repositories" - ], - "summary": "Get repository tags", - "operationId": "get_repository_tags", - "parameters": [ - { - "name": "owner", - "in": "path", - "description": "Repository owner", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "repo", - "in": "path", - "description": "Repository name", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "connection_id", - "in": "query", - "description": "Git provider connection ID (required when multiple connections have the same repo)", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "fresh", - "in": "query", - "description": "Force fetch fresh data, bypassing cache (default: false)", - "required": false, - "schema": { - "type": "boolean" - } - } - ], - "responses": { - "200": { - "description": "List of tags", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/TagListResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "404": { - "description": "Repository not found" - }, - "429": { - "description": "Fresh tag lookup rate limit exceeded" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/repositories/{repository_id}/preset/live": { - "get": { - "tags": [ - "Git Providers" - ], - "operationId": "get_repository_preset_live", - "parameters": [ - { - "name": "repository_id", - "in": "path", - "description": "Repository ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "branch", - "in": "query", - "description": "Git branch to check (defaults to repository's default branch)", - "required": false, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Repository presets calculated successfully - includes root preset and projects in subdirectories", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/RepositoryPresetResponse" - } - } - } - }, - "400": { - "description": "Bad request" - }, - "401": { - "description": "The git provider rejected the stored credential - the connection must be re-authorized" - }, - "404": { - "description": "Repository not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/repository/{repository_id}": { - "get": { - "tags": [ - "Git Providers" - ], - "summary": "Get repository by ID", - "operationId": "get_repository_by_id", - "parameters": [ - { - "name": "repository_id", - "in": "path", - "description": "Repository ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Repository found", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/RepositoryResponse" - } - } - } - }, - "404": { - "description": "Repository not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/repository/{repository_id}/branches": { - "get": { - "tags": [ - "Repositories" - ], - "summary": "Get repository branches by repository ID", - "operationId": "get_branches_by_repository_id", - "parameters": [ - { - "name": "repository_id", - "in": "path", - "description": "Repository ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "fresh", - "in": "query", - "description": "Force fetch fresh data, bypassing cache (default: false)", - "required": false, - "schema": { - "type": "boolean" - } - } - ], - "responses": { - "200": { - "description": "List of branches", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/BranchListResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "404": { - "description": "Repository not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/repository/{repository_id}/commits": { - "get": { - "tags": [ - "Repositories" - ], - "summary": "List recent commits for a repository branch", - "operationId": "list_commits_by_repository_id", - "parameters": [ - { - "name": "repository_id", - "in": "path", - "description": "Repository ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "branch", - "in": "query", - "description": "Branch name to list commits for", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "per_page", - "in": "query", - "description": "Number of commits to return (default: 20, max: 100)", - "required": false, - "schema": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "minimum": 0 - } - } - ], - "responses": { - "200": { - "description": "List of commits", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CommitListResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "404": { - "description": "Repository not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/repository/{repository_id}/commits/{commit_sha}": { - "get": { - "tags": [ - "Repositories" - ], - "summary": "Check if a commit exists in a repository", - "operationId": "check_commit_exists", - "parameters": [ - { - "name": "repository_id", - "in": "path", - "description": "Repository ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "commit_sha", - "in": "path", - "description": "Commit SHA to check", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Commit existence check result", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CommitExistsResponse" - } - } - } - }, - "400": { - "description": "Invalid commit SHA" - }, - "401": { - "description": "Unauthorized" - }, - "404": { - "description": "Repository not found" - }, - "429": { - "description": "Commit lookup rate limit exceeded" - }, - "500": { - "description": "Internal server error" - }, - "502": { - "description": "Git provider request failed" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/repository/{repository_id}/tags": { - "get": { - "tags": [ - "Repositories" - ], - "summary": "Get repository tags by repository ID", - "operationId": "get_tags_by_repository_id", - "parameters": [ - { - "name": "repository_id", - "in": "path", - "description": "Repository ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "fresh", - "in": "query", - "description": "Force fetch fresh data, bypassing cache (default: false)", - "required": false, - "schema": { - "type": "boolean" - } - } - ], - "responses": { - "200": { - "description": "List of tags", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/TagListResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "404": { - "description": "Repository not found" - }, - "429": { - "description": "Fresh tag lookup rate limit exceeded" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/restore-runs/{id}": { - "get": { - "tags": [ - "Restore" - ], - "operationId": "get_restore_run", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "Restore run id", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Restore run progress", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/RestoreRunView" - } - } - } - }, - "404": { - "description": "Restore run not found", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/revenue/events": { - "get": { - "tags": [ - "Revenue" - ], - "summary": "Org-wide revenue events across every project. Powers the revenue\ntransactions page. Supports filtering by project, date range, and\nevent type.", - "operationId": "revenue_global_events", - "parameters": [ - { - "name": "project_id", - "in": "query", - "description": "Filter to a single project", - "required": false, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "from", - "in": "query", - "description": "Lower bound (inclusive), ISO-8601", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "to", - "in": "query", - "description": "Upper bound (inclusive), ISO-8601", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "event_types", - "in": "query", - "description": "Comma-separated event types (e.g. `invoice.paid,charge.succeeded`)", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "limit", - "in": "query", - "description": "Max rows, default 100, max 500", - "required": false, - "schema": { - "type": "integer", - "format": "int64" - } - } - ], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/GlobalRecentEventResponse" - } - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/revenue/metrics/global-mrr": { - "get": { - "tags": [ - "Revenue" - ], - "summary": "Org-wide MRR total, summed across every project in the install.\nPowers the single-number MRR card on the main dashboard.", - "operationId": "revenue_metrics_global_mrr", - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/GlobalMrrResponse" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/revenue/metrics/global-summary": { - "get": { - "tags": [ - "Revenue" - ], - "summary": "Org-wide revenue summary: MRR, paid cash (30d + all-time), refunds,\nactive subscriptions/customers, and transaction count. Powers the\nheader on the Revenue transactions page.", - "operationId": "revenue_metrics_global_summary", - "parameters": [ - { - "name": "currency", - "in": "query", - "description": "ISO-4217 currency code, default USD", - "required": false, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/GlobalRevenueSummaryResponse" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/revenue/providers": { - "get": { - "tags": [ - "Revenue" - ], - "summary": "List registered providers (what the UI needs to render the \"Connect\"\ndropdown + its wizard instructions).", - "operationId": "revenue_list_providers", - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ProviderDescriptor" - } - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/session-replays": { - "get": { - "tags": [ - "Analytics" - ], - "summary": "Get session replays for a project", - "operationId": "get_project_session_replays", - "parameters": [ - { - "name": "project_id", - "in": "query", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "environment_id", - "in": "query", - "description": "Environment ID (optional)", - "required": false, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "page", - "in": "query", - "description": "Page number (1-based)", - "required": false, - "schema": { - "type": "integer", - "format": "int64", - "minimum": 0 - } - }, - { - "name": "per_page", - "in": "query", - "description": "Items per page", - "required": false, - "schema": { - "type": "integer", - "format": "int64", - "minimum": 0 - } - } - ], - "responses": { - "200": { - "description": "Session replays retrieved successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/GetProjectSessionReplaysResponse" - } - } - } - }, - "400": { - "description": "Bad request", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - }, - "401": { - "description": "Authentication required", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - }, - "403": { - "description": "Insufficient permissions", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/sessions/{session_id}/events": { - "get": { - "tags": [ - "Events" - ], - "summary": "Get events for a specific session", - "operationId": "get_session_events", - "parameters": [ - { - "name": "session_id", - "in": "path", - "description": "Session ID", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "environment_id", - "in": "query", - "description": "Filter by environment ID", - "required": false, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Successfully retrieved session events", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AnalyticsSessionEventsResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "404": { - "description": "Session not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/settings": { - "get": { - "tags": [ - "Settings" - ], - "summary": "Get application settings", - "operationId": "get_settings", - "responses": { - "200": { - "description": "Application settings with masked sensitive fields", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AppSettingsResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "put": { - "tags": [ - "Settings" - ], - "summary": "Update application settings", - "operationId": "update_settings", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AppSettings" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Settings updated successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SettingsUpdateResponse" - } - } - } - }, - "400": { - "description": "Bad request - invalid settings" - }, - "401": { - "description": "Unauthorized" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/settings/agent-token": { - "post": { - "tags": [ - "Agents" - ], - "summary": "Save an encrypted AI provider token for use in sandbox containers.", - "operationId": "save_agent_token", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SaveAgentTokenRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Token encrypted and persisted", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SaveAgentTokenResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "500": { - "description": "Encryption or database error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/settings/ai-providers": { - "get": { - "tags": [ - "Agents" - ], - "summary": "List the AI provider catalog. Includes per-provider \"is a credential\nconfigured?\" so the settings UI can render configured/not-configured\nbadges without leaking the encrypted credential.", - "operationId": "list_ai_providers", - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProviderCatalogResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/settings/ai-providers/{provider_id}": { - "patch": { - "tags": [ - "Agents" - ], - "summary": "Update provider-scoped settings without touching the saved credential.\nToday that means just `default_model`; future per-provider settings\n(base URL overrides, request headers, etc.) can land here too without\nchanging the shape of `save_credential`.", - "operationId": "update_ai_provider", - "parameters": [ - { - "name": "provider_id", - "in": "path", - "description": "AI provider ID", - "required": true, - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdateAiProviderRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdateAiProviderResponse" - } - } - } - }, - "400": { - "description": "Unknown provider" - }, - "401": { - "description": "Unauthorized" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/settings/ai-providers/{provider_id}/activate": { - "post": { - "tags": [ - "Agents" - ], - "summary": "Activate a provider as the platform-wide default. Refuses to activate a\nprovider that doesn't have a credential saved yet \u2014 the UI enforces the\nsame rule on the button, but we re-check server-side so a stale tab\ncan't bypass it.", - "operationId": "activate_ai_provider", - "parameters": [ - { - "name": "provider_id", - "in": "path", - "description": "AI provider ID", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ActivateProviderResponse" - } - } - } - }, - "400": { - "description": "Provider not configured" - }, - "401": { - "description": "Unauthorized" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/settings/ai-providers/{provider_id}/credential": { - "post": { - "tags": [ - "Agents" - ], - "summary": "Save (or replace) a provider's credential. The credential is encrypted\nwith `EncryptionService` and stored inside\n`agent_sandbox.providers[provider_id].credentials_encrypted`.", - "description": "The plaintext shape depends on the flavor's `credential_format`:\n - `ApiKey` / `OauthToken`: the key/token string.\n - `ConfigFile`: the full file body (e.g. OpenCode's `auth.json`).", - "operationId": "save_ai_provider_credential", - "parameters": [ - { - "name": "provider_id", - "in": "path", - "description": "AI provider ID", - "required": true, - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SaveCredentialRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SaveCredentialResponse" - } - } - } - }, - "400": { - "description": "Validation error" - }, - "401": { - "description": "Unauthorized" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/settings/disk-status": { - "get": { - "tags": [ - "Settings" - ], - "summary": "Get current disk usage for the control-plane server", - "description": "Returns live disk usage for the monitored path along with any disks that\nmeet or exceed the configured alert threshold. Read-only \u2014 does not send\nnotifications. Used by the dashboard to surface a low-disk-space warning.", - "operationId": "get_disk_status", - "responses": { - "200": { - "description": "Current disk usage and threshold alerts", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/DiskSpaceCheckResult" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/settings/enrollment-tokens": { - "get": { - "tags": [ - "Settings" - ], - "summary": "List currently-valid node enrollment tokens (hashes elided).", - "operationId": "list_enrollment_tokens", - "responses": { - "200": { - "description": "Active enrollment tokens", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/EnrollmentTokenListResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "post": { - "tags": [ - "Settings" - ], - "summary": "Mint a short-lived, single-use node enrollment token.", - "operationId": "mint_enrollment_token", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/MintEnrollmentTokenRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Enrollment token minted", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/MintEnrollmentTokenResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/settings/enrollment-tokens/{id}": { - "delete": { - "tags": [ - "Settings" - ], - "summary": "Revoke a node enrollment token by id.", - "operationId": "revoke_enrollment_token", - "parameters": [ - { - "name": "id", - "in": "path", - "description": "Enrollment token id", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Enrollment token revoked", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SettingsUpdateResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "404": { - "description": "Enrollment token not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/settings/join-token": { - "delete": { - "tags": [ - "Settings" - ], - "summary": "Revoke the current join token", - "description": "Removes the stored join token hash, allowing any node to register\n(if no other authentication is in place).", - "operationId": "revoke_join_token", - "responses": { - "200": { - "description": "Join token revoked", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SettingsUpdateResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/settings/join-token/generate": { - "post": { - "tags": [ - "Settings" - ], - "summary": "Generate a new join token for multi-node cluster registration", - "description": "Creates a random 32-byte hex token, stores the SHA-256 hash in settings,\nand returns the plaintext exactly once. If a token already exists, it is replaced.", - "operationId": "generate_join_token", - "responses": { - "200": { - "description": "Join token generated", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/GenerateJoinTokenResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/settings/join-token/status": { - "get": { - "tags": [ - "Settings" - ], - "summary": "Check whether a join token is currently configured", - "operationId": "get_join_token_status", - "responses": { - "200": { - "description": "Join token status", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/JoinTokenStatusResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/settings/mcp-servers": { - "get": { - "tags": [ - "Agents" - ], - "operationId": "list_global_mcps", - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ListMcpsResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "post": { - "tags": [ - "Agents" - ], - "operationId": "create_global_mcp", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateMcpRequest" - } - } - }, - "required": true - }, - "responses": { - "201": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/McpDefinitionResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/settings/mcp-servers/{slug}": { - "get": { - "tags": [ - "Agents" - ], - "operationId": "get_global_mcp", - "parameters": [ - { - "name": "slug", - "in": "path", - "description": "MCP server slug", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/McpDefinitionResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "404": { - "description": "MCP server not found" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "put": { - "tags": [ - "Agents" - ], - "operationId": "update_global_mcp", - "parameters": [ - { - "name": "slug", - "in": "path", - "description": "MCP server slug", - "required": true, - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdateMcpRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/McpDefinitionResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "404": { - "description": "MCP server not found" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "delete": { - "tags": [ - "Agents" - ], - "operationId": "delete_global_mcp", - "parameters": [ - { - "name": "slug", - "in": "path", - "description": "MCP server slug", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "204": { - "description": "MCP server deleted" - }, - "401": { - "description": "Unauthorized" - }, - "404": { - "description": "MCP server not found" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/settings/mcp-servers/{slug}/config/{field}": { - "get": { - "tags": [ - "Agents" - ], - "operationId": "reveal_global_mcp_config", - "parameters": [ - { - "name": "slug", - "in": "path", - "description": "MCP server slug", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "field", - "in": "path", - "description": "Sensitive field path, such as url or env.API_TOKEN", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SensitiveMcpConfigValueResponse" - } - } - } - }, - "400": { - "description": "Field is not revealable" - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Missing secrets:read permission" - }, - "404": { - "description": "MCP server or field not found" - }, - "500": { - "description": "Configuration read or audit failed" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/settings/routes/refresh": { - "post": { - "tags": [ - "Settings" - ], - "summary": "Manually refresh the proxy route table", - "description": "Reloads all routes from the database into the in-memory proxy cache.\nUseful as a workaround when routes are out of sync.", - "operationId": "refresh_route_table", - "responses": { - "200": { - "description": "Route table refreshed", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/RouteRefreshResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/settings/sandbox-rebuild": { - "post": { - "tags": [ - "Agents" - ], - "operationId": "rebuild_sandbox_image", - "responses": { - "200": { - "description": "Server-Sent Events stream of rebuild progress; final event `{\"type\":\"done\",\"success\":bool,...}`", - "content": { - "text/event-stream": {} - } - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/settings/sandbox-status": { - "get": { - "tags": [ - "Agents" - ], - "operationId": "get_global_sandbox_status", - "responses": { - "200": { - "description": "Global sandbox readiness for the settings page", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SandboxStatusResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/settings/secrets": { - "get": { - "tags": [ - "Secrets" - ], - "operationId": "list_secrets", - "responses": { - "200": { - "description": "List of global agent secrets", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ListSecretsResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "post": { - "tags": [ - "Secrets" - ], - "operationId": "upsert_secret", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpsertSecretRequest" - } - } - }, - "required": true - }, - "responses": { - "201": { - "description": "Secret created/updated", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SecretResponse" - } - } - } - }, - "400": { - "description": "Validation error" - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/settings/secrets/{name}": { - "delete": { - "tags": [ - "Secrets" - ], - "operationId": "delete_secret", - "parameters": [ - { - "name": "name", - "in": "path", - "description": "Secret name", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "204": { - "description": "Secret deleted" - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "404": { - "description": "Secret not found" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/settings/skills": { - "get": { - "tags": [ - "Agents" - ], - "operationId": "list_global_skills", - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ListSkillsResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "post": { - "tags": [ - "Agents" - ], - "operationId": "create_global_skill", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateSkillRequest" - } - } - }, - "required": true - }, - "responses": { - "201": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SkillDefinitionResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/settings/skills/upload": { - "post": { - "tags": [ - "Agents" - ], - "summary": "Upload a skill with an archive (tar.gz) \u2014 global.", - "operationId": "upload_global_skill", - "requestBody": { - "content": { - "multipart/form-data": { - "schema": { - "type": "string" - } - } - }, - "required": true - }, - "responses": { - "201": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SkillDefinitionResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/settings/skills/{slug}": { - "get": { - "tags": [ - "Agents" - ], - "operationId": "get_global_skill", - "parameters": [ - { - "name": "slug", - "in": "path", - "description": "Skill slug", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SkillDefinitionResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "404": { - "description": "Skill not found" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "put": { - "tags": [ - "Agents" - ], - "operationId": "update_global_skill", - "parameters": [ - { - "name": "slug", - "in": "path", - "description": "Skill slug", - "required": true, - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdateSkillRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SkillDefinitionResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "404": { - "description": "Skill not found" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "delete": { - "tags": [ - "Agents" - ], - "operationId": "delete_global_skill", - "parameters": [ - { - "name": "slug", - "in": "path", - "description": "Skill slug", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "204": { - "description": "Skill deleted" - }, - "401": { - "description": "Unauthorized" - }, - "404": { - "description": "Skill not found" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/settings/skills/{slug}/archive": { - "get": { - "tags": [ - "Agents" - ], - "summary": "Download a skill's archive (tar.gz) \u2014 global.", - "operationId": "download_global_skill_archive", - "parameters": [ - { - "name": "slug", - "in": "path", - "description": "Skill slug", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Skill archive tar.gz", - "content": { - "application/gzip": {} - } - }, - "401": { - "description": "Unauthorized" - }, - "404": { - "description": "Skill not found or has no archive" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/settings/update-status": { - "get": { - "tags": [ - "Settings" - ], - "summary": "Report whether a newer temps release is available for this install.", - "operationId": "get_update_status", - "responses": { - "200": { - "description": "Release update status for this install", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdateStatusResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/teams": { - "get": { - "tags": [ - "Teams" - ], - "operationId": "list_teams", - "parameters": [ - { - "name": "page", - "in": "query", - "description": "1-indexed page", - "required": false, - "schema": { - "type": "integer", - "format": "int64", - "minimum": 0 - } - }, - { - "name": "page_size", - "in": "query", - "description": "default 20, max 100", - "required": false, - "schema": { - "type": "integer", - "format": "int64", - "minimum": 0 - } - } - ], - "responses": { - "200": { - "description": "Paginated teams", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/TeamListResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "post": { - "tags": [ - "Teams" - ], - "operationId": "create_team", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateTeamRequest" - } - } - }, - "required": true - }, - "responses": { - "201": { - "description": "Team created", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/TeamResponse" - } - } - } - }, - "400": { - "description": "Validation error" - }, - "403": { - "description": "Insufficient permissions" - }, - "409": { - "description": "Slug already taken" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/teams/{team_id}": { - "get": { - "tags": [ - "Teams" - ], - "operationId": "get_team", - "parameters": [ - { - "name": "team_id", - "in": "path", - "description": "Team id", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Team", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/TeamResponse" - } - } - } - }, - "403": { - "description": "Insufficient permissions" - }, - "404": { - "description": "Team not found" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "delete": { - "tags": [ - "Teams" - ], - "operationId": "delete_team", - "parameters": [ - { - "name": "team_id", - "in": "path", - "description": "Team id", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "204": { - "description": "Team deleted" - }, - "403": { - "description": "Insufficient permissions" - }, - "404": { - "description": "Team not found" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "patch": { - "tags": [ - "Teams" - ], - "operationId": "update_team", - "parameters": [ - { - "name": "team_id", - "in": "path", - "description": "Team id", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdateTeamRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Updated team", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/TeamResponse" - } - } - } - }, - "400": { - "description": "Validation error" - }, - "403": { - "description": "Insufficient permissions" - }, - "404": { - "description": "Team not found" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/teams/{team_id}/members": { - "get": { - "tags": [ - "Teams" - ], - "operationId": "list_team_members", - "parameters": [ - { - "name": "team_id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Members", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/TeamMemberResponse" - } - } - } - } - }, - "403": { - "description": "Insufficient permissions" - }, - "404": { - "description": "Team not found" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "post": { - "tags": [ - "Teams" - ], - "operationId": "add_team_member", - "parameters": [ - { - "name": "team_id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateTeamMemberRequest" - } - } - }, - "required": true - }, - "responses": { - "201": { - "description": "Member added", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/TeamMemberResponse" - } - } - } - }, - "403": { - "description": "Insufficient permissions" - }, - "404": { - "description": "Team not found" - }, - "409": { - "description": "User already a member" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/teams/{team_id}/members/{user_id}": { - "delete": { - "tags": [ - "Teams" - ], - "operationId": "remove_team_member", - "parameters": [ - { - "name": "team_id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "user_id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "204": { - "description": "Member removed" - }, - "403": { - "description": "Insufficient permissions" - }, - "404": { - "description": "Member not found" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "patch": { - "tags": [ - "Teams" - ], - "operationId": "update_team_member_role", - "parameters": [ - { - "name": "team_id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "user_id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdateMemberRoleRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Updated membership", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/TeamMemberResponse" - } - } - } - }, - "403": { - "description": "Insufficient permissions" - }, - "404": { - "description": "Member not found" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/teams/{team_id}/projects": { - "get": { - "tags": [ - "Teams" - ], - "operationId": "list_team_projects", - "parameters": [ - { - "name": "team_id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Projects this team has access to", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ProjectAccessResponse" - } - } - } - } - }, - "403": { - "description": "Insufficient permissions" - }, - "404": { - "description": "Team not found" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/templates": { - "get": { - "tags": [ - "Templates" - ], - "summary": "List all available templates", - "description": "Returns a list of all public templates, optionally filtered by tag or featured status.", - "operationId": "list_project_templates", - "parameters": [ - { - "name": "tag", - "in": "query", - "description": "Filter templates by tag", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "featured", - "in": "query", - "description": "Only return featured templates", - "required": false, - "schema": { - "type": "boolean" - } - } - ], - "responses": { - "200": { - "description": "List of templates", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ListTemplatesResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/templates/tags": { - "get": { - "tags": [ - "Templates" - ], - "summary": "List all available template tags", - "description": "Returns a list of all unique tags used by public templates.", - "operationId": "list_project_template_tags", - "responses": { - "200": { - "description": "List of tags", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ListTagsResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/templates/{slug}": { - "get": { - "tags": [ - "Templates" - ], - "summary": "Get a specific template by slug", - "description": "Returns detailed information about a single template.", - "operationId": "get_project_template", - "parameters": [ - { - "name": "slug", - "in": "path", - "description": "Template slug", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Template details", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/TemplateResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "404": { - "description": "Template not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/user/me": { - "get": { - "tags": [ - "Authentication" - ], - "operationId": "get_current_user", - "responses": { - "200": { - "description": "Successfully retrieved user information", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UserResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "session_token": [] - } - ] - } - }, - "/users": { - "get": { - "tags": [ - "Users" - ], - "operationId": "list_users", - "parameters": [ - { - "name": "include_deleted", - "in": "query", - "description": "Include deleted users in the response", - "required": true, - "schema": { - "type": "boolean" - } - } - ], - "responses": { - "200": { - "description": "List all users with their roles", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/RouteUserWithRoles" - } - } - } - } - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "post": { - "tags": [ - "Users" - ], - "summary": "Create a new user with roles", - "operationId": "create_user", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateUserRequest" - } - } - }, - "required": true - }, - "responses": { - "201": { - "description": "User created successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/RouteUserWithRoles" - } - } - } - }, - "400": { - "description": "Invalid input" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/users/me": { - "patch": { - "tags": [ - "Users" - ], - "summary": "Update current user's information", - "operationId": "update_self", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdateSelfRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "User updated successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/RouteUserWithRoles" - } - } - } - }, - "400": { - "description": "Invalid input" - }, - "401": { - "description": "Unauthorized" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/users/me/mfa": { - "delete": { - "tags": [ - "Users" - ], - "operationId": "disable_mfa", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/DisableMfaRequest" - } - } - }, - "required": true - }, - "responses": { - "204": { - "description": "MFA disabled" - }, - "400": { - "description": "Invalid verification code" - }, - "401": { - "description": "Unauthorized" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/users/me/mfa/setup": { - "post": { - "tags": [ - "Users" - ], - "operationId": "setup_mfa", - "responses": { - "200": { - "description": "MFA setup data", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/MfaSetupResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/users/me/mfa/verify": { - "post": { - "tags": [ - "Users" - ], - "operationId": "verify_and_enable_mfa", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/VerifyMfaRequest" - } - } - }, - "required": true - }, - "responses": { - "204": { - "description": "MFA verified and enabled" - }, - "400": { - "description": "Invalid code" - }, - "401": { - "description": "Unauthorized" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/users/me/password": { - "post": { - "tags": [ - "Users" - ], - "operationId": "change_password_self", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ChangePasswordRequest" - } - } - }, - "required": true - }, - "responses": { - "204": { - "description": "Password updated" - }, - "400": { - "description": "Validation error (weak password, same as current, MFA missing)" - }, - "401": { - "description": "Current password incorrect or MFA code invalid" - }, - "403": { - "description": "Account has no password set (SSO only)" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/users/{user_id}": { - "delete": { - "tags": [ - "Users" - ], - "summary": "Delete a user", - "operationId": "delete_user", - "parameters": [ - { - "name": "user_id", - "in": "path", - "description": "User ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "204": { - "description": "User deleted successfully" - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Forbidden - Cannot delete yourself or non-admin attempt" - }, - "404": { - "description": "User not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "patch": { - "tags": [ - "Users" - ], - "summary": "Update user information (admin only)", - "operationId": "update_user", - "parameters": [ - { - "name": "user_id", - "in": "path", - "description": "User ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdateUserRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "User updated successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/RouteUserWithRoles" - } - } - } - }, - "400": { - "description": "Invalid input" - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Forbidden - Non-admin attempt" - }, - "404": { - "description": "User not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/users/{user_id}/restore": { - "post": { - "tags": [ - "Users" - ], - "operationId": "restore_user", - "parameters": [ - { - "name": "user_id", - "in": "path", - "description": "User ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "User restored successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/RouteUserWithRoles" - } - } - } - }, - "400": { - "description": "User is not deleted" - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Forbidden - Non-admin attempt" - }, - "404": { - "description": "User not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/users/{user_id}/roles": { - "post": { - "tags": [ - "Users" - ], - "operationId": "assign_role", - "parameters": [ - { - "name": "user_id", - "in": "path", - "description": "User ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AssignRoleRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Role assigned successfully" - }, - "400": { - "description": "Invalid role type" - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Admin role required or self-modification forbidden" - }, - "404": { - "description": "User or role not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/users/{user_id}/roles/{role_type}": { - "delete": { - "tags": [ - "Users" - ], - "operationId": "remove_role", - "parameters": [ - { - "name": "user_id", - "in": "path", - "description": "User ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "role_type", - "in": "path", - "description": "Role type to remove", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "204": { - "description": "Role removed successfully" - }, - "400": { - "description": "Invalid role type" - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Forbidden - Cannot modify own roles or non-admin attempt" - }, - "404": { - "description": "User or role not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/v1/sandboxes": { - "get": { - "tags": [ - "Sandboxes" - ], - "operationId": "list_sandboxes", - "parameters": [ - { - "name": "page", - "in": "query", - "description": "Page (1-indexed)", - "required": false, - "schema": { - "type": "integer", - "format": "int64", - "minimum": 0 - } - }, - { - "name": "page_size", - "in": "query", - "description": "Items per page (default 20, max 100)", - "required": false, - "schema": { - "type": "integer", - "format": "int64", - "minimum": 0 - } - } - ], - "responses": { - "200": { - "description": "List sandboxes", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ListSandboxesResponse" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "post": { - "tags": [ - "Sandboxes" - ], - "operationId": "create_sandbox", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateSandboxBody" - } - } - }, - "required": true - }, - "responses": { - "201": { - "description": "Sandbox created", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SandboxResponse" - } - } - } - }, - "400": { - "description": "Validation error" - }, - "401": { - "description": "Unauthorized" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/v1/sandboxes/rootfs": { - "get": { - "tags": [ - "Sandboxes" - ], - "summary": "Inspect rootfs storage: the Firecracker digest-keyed cache (with which\nsandboxes reference each entry) and per-VM disks. Empty on Docker-only\nhosts. Admin/read scope \u2014 this exposes host storage layout.", - "operationId": "rootfs_report", - "responses": { - "200": { - "description": "Rootfs storage report" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/v1/sandboxes/rootfs/gc": { - "post": { - "tags": [ - "Sandboxes" - ], - "summary": "Reclaim rootfs cache entries not backing any live sandbox. Idempotent;\nsafe to call any time (live VMs hold their own per-VM disks).", - "operationId": "rootfs_gc", - "responses": { - "200": { - "description": "Reclaimed cache entries" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/v1/sandboxes/{id}": { - "get": { - "tags": [ - "Sandboxes" - ], - "operationId": "get_sandbox", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Sandbox details", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SandboxResponse" - } - } - } - }, - "404": { - "description": "Not found" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/v1/sandboxes/{id}/cmd": { - "post": { - "tags": [ - "Sandboxes" - ], - "summary": "Run a command inside the sandbox (`@vercel/sandbox`-compatible).", - "description": "`wait=false` (default) returns `{ command: {..., exitCode: null} }`\nimmediately once the background task is spawned.\n\n`wait=true` streams `application/x-ndjson`: the first line is the\nrunning envelope, the second is the finished envelope with `exitCode`.", - "operationId": "cmd", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CmdBody" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Command started (wait=false) or finished (wait=true)", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CmdResponse" - } - } - } - }, - "404": { - "description": "Sandbox not found" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/v1/sandboxes/{id}/cmd/{cmd_id}": { - "get": { - "tags": [ - "Sandboxes" - ], - "operationId": "get_cmd", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "cmd_id", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Command snapshot", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CmdResponse" - } - } - } - }, - "404": { - "description": "Sandbox or command not found" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/v1/sandboxes/{id}/cmd/{cmd_id}/logs": { - "get": { - "tags": [ - "Sandboxes" - ], - "summary": "Stream a command's stdout/stderr as `application/x-ndjson`\n(`@vercel/sandbox`-compatible). Each line is either\n`{stream:\"stdout\"|\"stderr\", data:\"...\"}` or\n`{stream:\"error\", data:{code, message}}`.", - "operationId": "cmd_logs", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "cmd_id", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "NDJSON stream of log events" - }, - "404": { - "description": "Sandbox or command not found" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/v1/sandboxes/{id}/destroy": { - "post": { - "tags": [ - "Sandboxes" - ], - "operationId": "destroy_sandbox", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "204": { - "description": "Sandbox destroyed (alias for `/stop` with an explicit verb)" - }, - "404": { - "description": "Not found" - }, - "409": { - "description": "Sandbox belongs to an active agent run \u2014 stop the run instead" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/v1/sandboxes/{id}/domain": { - "get": { - "tags": [ - "Sandboxes" - ], - "operationId": "domain", - "parameters": [ - { - "name": "port", - "in": "query", - "description": "Port inside the sandbox (1..=65535)", - "required": true, - "schema": { - "type": "integer", - "format": "int32", - "minimum": 0 - } - }, - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Preview URL for the port", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SandboxDomainResponse" - } - } - } - }, - "400": { - "description": "Invalid port" - }, - "404": { - "description": "Sandbox not found" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/v1/sandboxes/{id}/events": { - "get": { - "tags": [ - "Sandboxes" - ], - "summary": "The operations timeline for a sandbox (lifecycle events only \u2014 never\nshell/exec activity), newest first.", - "operationId": "list_events", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Operations timeline", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SandboxEventsResponse" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/v1/sandboxes/{id}/exec": { - "post": { - "tags": [ - "Sandboxes" - ], - "operationId": "exec", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ExecBody" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Command finished (non-zero exit is NOT an error)", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ExecResponse" - } - } - } - }, - "404": { - "description": "Sandbox not found" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/v1/sandboxes/{id}/exec-detached": { - "post": { - "tags": [ - "Sandboxes" - ], - "operationId": "exec_detached", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ExecBody" - } - } - }, - "required": true - }, - "responses": { - "202": { - "description": "Command accepted; poll /jobs/{job_id}", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ExecDetachedResponse" - } - } - } - }, - "404": { - "description": "Sandbox not found" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/v1/sandboxes/{id}/extend-timeout": { - "post": { - "tags": [ - "Sandboxes" - ], - "operationId": "extend_timeout", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ExtendTimeoutBody" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Timeout extended", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SandboxResponse" - } - } - } - }, - "400": { - "description": "Validation error" - }, - "404": { - "description": "Not found" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/v1/sandboxes/{id}/fs/mkdir": { - "post": { - "tags": [ - "Sandboxes" - ], - "operationId": "mkdir", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/MkdirBody" - } - } - }, - "required": true - }, - "responses": { - "204": { - "description": "Directory created (or already existed)" - }, - "400": { - "description": "Validation error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/v1/sandboxes/{id}/fs/read": { - "get": { - "tags": [ - "Sandboxes" - ], - "operationId": "read_file", - "parameters": [ - { - "name": "path", - "in": "query", - "description": "Absolute file path inside the sandbox", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "File contents (base64)", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ReadFileResponse" - } - } - } - }, - "400": { - "description": "Validation error" - }, - "404": { - "description": "Sandbox or file not found" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/v1/sandboxes/{id}/fs/stat": { - "get": { - "tags": [ - "Sandboxes" - ], - "operationId": "stat_path", - "parameters": [ - { - "name": "path", - "in": "query", - "description": "Absolute path inside the sandbox", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Stat info (exists=false when missing \u2014 not an error)", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/StatResponse" - } - } - } - }, - "400": { - "description": "Validation error" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/v1/sandboxes/{id}/fs/write": { - "post": { - "tags": [ - "Sandboxes" - ], - "summary": "Write a file into the sandbox. Accepts two body shapes \u2014 the SDK\npicks one based on `Content-Type`:", - "description": "- **`application/json`** (temps-native): `{path, contents_b64, mode}`\n \u2014 one file, base64-encoded.\n- **`application/gzip`** (`@vercel/sandbox`): a gzipped tarball of\n one-or-more entries, with the target extract dir carried in the\n `x-cwd` header. The SDK's `writeFile` and `writeFiles` both post\n here; they differ only in how many entries the tarball contains.\n\nWhy merge them on one route: the SDK is hardcoded to\n`POST /fs/write`, so splitting tar uploads onto a separate path would\nforce us to break SDK compat. Instead we dispatch on Content-Type,\npreserve JSON for native callers, and add tar for SDK callers.", - "operationId": "write_file", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/WriteFileBody" - } - } - }, - "required": true - }, - "responses": { - "204": { - "description": "File(s) written" - }, - "400": { - "description": "Validation error or invalid base64" - }, - "404": { - "description": "Sandbox not found" - }, - "415": { - "description": "Unsupported Content-Type (expected application/json or application/gzip)" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/v1/sandboxes/{id}/fs/write-batch": { - "post": { - "tags": [ - "Sandboxes" - ], - "summary": "Batch-write multiple files in a single request. Mirrors\n`@vercel/sandbox` `writeFiles()`. Semantics are fail-fast: if any\nfile errors, previously-written entries are left in place and the\nerror describes which file broke.", - "operationId": "write_files", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/WriteFilesBody" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "All files written", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/WriteFilesResponse" - } - } - } - }, - "400": { - "description": "Validation error or invalid base64" - }, - "404": { - "description": "Sandbox not found" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/v1/sandboxes/{id}/jobs": { - "get": { - "tags": [ - "Sandboxes" - ], - "operationId": "list_jobs", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Detached jobs for this sandbox", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ListJobsResponse" - } - } - } - }, - "404": { - "description": "Sandbox not found" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/v1/sandboxes/{id}/jobs/{job_id}": { - "get": { - "tags": [ - "Sandboxes" - ], - "operationId": "job_status", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "job_id", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Job status snapshot", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/JobStatusResponse" - } - } - } - }, - "404": { - "description": "Sandbox or job not found" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/v1/sandboxes/{id}/jobs/{job_id}/kill": { - "post": { - "tags": [ - "Sandboxes" - ], - "summary": "Terminate a detached job. Aborts the server-side tracking task and\nsends SIGTERM (or SIGKILL if `force=true`) to any matching processes\ninside the sandbox container. Returns 204 on success; 404 if the\nsandbox or job is unknown.", - "operationId": "kill_job", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "job_id", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/KillJobBody" - } - } - }, - "required": true - }, - "responses": { - "204": { - "description": "Job killed" - }, - "404": { - "description": "Sandbox or job not found" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/v1/sandboxes/{id}/jobs/{job_id}/logs": { - "get": { - "tags": [ - "Sandboxes" - ], - "summary": "SSE endpoint streaming each stdout/stderr line from a detached job\nas it's produced. Mirrors the `Command.logs()` async iterator shape\non `@vercel/sandbox` \u2014 events carry `{ stream, data }`.", - "description": "Late subscribers only see events produced after they connect. The\nJobState snapshot (`GET /jobs/{job_id}`) covers the history.\n\nA \"done\" sentinel event fires when the broadcast channel closes\n(the exec task has exited and dropped the sender), signalling\ncallers they can stop reading.", - "operationId": "job_logs", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "job_id", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "SSE stream of log events" - }, - "404": { - "description": "Sandbox or job not found" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/v1/sandboxes/{id}/pause": { - "post": { - "tags": [ - "Sandboxes" - ], - "operationId": "pause_sandbox", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Sandbox paused (container stopped, state preserved)", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SandboxResponse" - } - } - } - }, - "404": { - "description": "Not found" - }, - "409": { - "description": "Sandbox is in an incompatible state (e.g. already destroyed)" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/v1/sandboxes/{id}/preview-link": { - "post": { - "tags": [ - "Sandboxes" - ], - "summary": "Mint a shareable link to a sandbox preview.", - "description": "`GET /domain` returns the bare preview URL, which is useless to anyone who\ndoes not already hold the sandbox's preview password \u2014 so sharing a\nprotected preview meant sharing that password, which is the same secret for\nevery recipient and can only be withdrawn by rotating it for all of them.\n\nThis returns the same URL carrying a short-lived, sandbox-scoped grant. The\nrecipient's browser exchanges it for the ordinary preview cookie and lands\non `path`. The grant never reaches the sandbox, so preview application code\ncannot read it and re-share it.\n\nAnyone holding the returned URL can view the preview until it expires;\nthere is no per-link revocation short of rotating the preview password.", - "operationId": "sandbox_create_preview_link", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/PreviewShareLinkBody" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Shareable preview link", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/PreviewShareLinkResponse" - } - } - } - }, - "400": { - "description": "Invalid port" - }, - "404": { - "description": "Sandbox not found" - }, - "409": { - "description": "Sandbox has no preview password" - }, - "500": { - "description": "Preview grant minting failed" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/v1/sandboxes/{id}/preview-password": { - "put": { - "tags": [ - "Sandboxes" - ], - "operationId": "set_preview_password", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SetPreviewPasswordBody" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Preview password set or rotated", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SetPreviewPasswordResponse" - } - } - } - }, - "400": { - "description": "Password too short or too long" - }, - "404": { - "description": "Sandbox not found" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "delete": { - "tags": [ - "Sandboxes" - ], - "operationId": "clear_preview_password", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "204": { - "description": "Preview password removed (sandbox is now URL-only protected)" - }, - "404": { - "description": "Sandbox not found" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/v1/sandboxes/{id}/resize": { - "post": { - "tags": [ - "Sandboxes" - ], - "summary": "Grow a Firecracker sandbox's root disk. Offline resize \u2014 the VM reboots\n(filesystem/data persist) rather than resizing fully live.", - "operationId": "resize_sandbox", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ResizeSandboxBody" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Resized", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SandboxResponse" - } - } - } - }, - "400": { - "description": "Invalid size or unsupported backend" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/v1/sandboxes/{id}/restart": { - "post": { - "tags": [ - "Sandboxes" - ], - "operationId": "restart_sandbox", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Sandbox container restarted in place", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SandboxResponse" - } - } - } - }, - "404": { - "description": "Not found" - }, - "409": { - "description": "Sandbox is stopped (use /resume) or already destroyed" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/v1/sandboxes/{id}/resume": { - "post": { - "tags": [ - "Sandboxes" - ], - "operationId": "resume_sandbox", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Sandbox resumed; expires_at refreshed", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SandboxResponse" - } - } - } - }, - "404": { - "description": "Not found" - }, - "409": { - "description": "Sandbox is not in a resumable state" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/v1/sandboxes/{id}/source": { - "post": { - "tags": [ - "Sandboxes" - ], - "operationId": "source_sandbox", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SourceBody" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Source content seeded into the sandbox work dir", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SandboxResponse" - } - } - } - }, - "400": { - "description": "Validation error (embedded creds, conflicting fields, etc.)" - }, - "404": { - "description": "Sandbox not found" - }, - "409": { - "description": "Sandbox is not running" - }, - "500": { - "description": "Source seed failed inside sandbox" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/v1/sandboxes/{id}/stop": { - "post": { - "tags": [ - "Sandboxes" - ], - "operationId": "stop_sandbox", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "204": { - "description": "Sandbox stopped and destroyed" - }, - "404": { - "description": "Not found" - }, - "409": { - "description": "Sandbox belongs to an active agent run \u2014 stop the run instead" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/v1/sandboxes/{id}/{cmd_id}/kill": { - "post": { - "tags": [ - "Sandboxes" - ], - "summary": "Kill a running command (`@vercel/sandbox`-compatible). The SDK\ncalls `POST /v1/sandboxes/{id}/{cmdId}/kill` \u2014 note the path has the\ncommand ID directly under the sandbox, NOT under `/jobs/` or `/cmd/`.", - "operationId": "cmd_kill", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "cmd_id", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CmdKillBody" - } - } - } - }, - "responses": { - "200": { - "description": "Command killed; returns final snapshot", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CmdResponse" - } - } - } - }, - "404": { - "description": "Sandbox or command not found" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/visitors/{visitor_id}/session-replays": { - "get": { - "tags": [ - "Analytics" - ], - "summary": "Get session replays for a visitor", - "operationId": "get_visitor_sessions", - "parameters": [ - { - "name": "visitor_id", - "in": "path", - "description": "Visitor ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "page", - "in": "query", - "description": "Page number (1-based)", - "required": false, - "schema": { - "type": "integer", - "format": "int64", - "minimum": 0 - } - }, - { - "name": "per_page", - "in": "query", - "description": "Items per page", - "required": false, - "schema": { - "type": "integer", - "format": "int64", - "minimum": 0 - } - } - ], - "responses": { - "200": { - "description": "Session replays retrieved successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/GetVisitorSessionsResponse" - } - } - } - }, - "401": { - "description": "Authentication required", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - }, - "403": { - "description": "Insufficient permissions", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/visitors/{visitor_id}/session-replays/{session_id}": { - "get": { - "tags": [ - "Analytics" - ], - "summary": "Get session replay data with visitor info (without events)", - "operationId": "get_session_replay", - "parameters": [ - { - "name": "visitor_id", - "in": "path", - "description": "Visitor ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "session_id", - "in": "path", - "description": "Session ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Session replay retrieved successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/GetSessionReplayResponse" - } - } - } - }, - "401": { - "description": "Authentication required", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - }, - "403": { - "description": "Insufficient permissions", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - }, - "404": { - "description": "Session not found", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "delete": { - "tags": [ - "Analytics" - ], - "summary": "Delete a session replay", - "operationId": "delete_session_replay", - "parameters": [ - { - "name": "visitor_id", - "in": "path", - "description": "Visitor ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "session_id", - "in": "path", - "description": "Session ID", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Session replay deleted successfully" - }, - "401": { - "description": "Authentication required", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - }, - "403": { - "description": "Insufficient permissions", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - }, - "404": { - "description": "Session not found", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/visitors/{visitor_id}/session-replays/{session_id}/duration": { - "put": { - "tags": [ - "Analytics" - ], - "summary": "Update session duration", - "operationId": "update_session_duration", - "parameters": [ - { - "name": "visitor_id", - "in": "path", - "description": "Visitor ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "session_id", - "in": "path", - "description": "Session ID", - "required": true, - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdateSessionDurationRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Session duration updated successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdateSessionDurationResponse" - } - } - } - }, - "401": { - "description": "Authentication required", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - }, - "403": { - "description": "Insufficient permissions", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - }, - "404": { - "description": "Session not found", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/visitors/{visitor_id}/session-replays/{session_id}/events": { - "get": { - "tags": [ - "Analytics" - ], - "summary": "Get session replay events (with session and visitor metadata)", - "operationId": "get_session_replay_events", - "parameters": [ - { - "name": "visitor_id", - "in": "path", - "description": "Visitor ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "session_id", - "in": "path", - "description": "Session ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Session replay with events retrieved successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SessionReplayWithEventsDto" - } - } - } - }, - "401": { - "description": "Authentication required", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - }, - "403": { - "description": "Insufficient permissions", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - }, - "404": { - "description": "Session not found", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "post": { - "tags": [ - "Analytics" - ], - "summary": "Add events to an existing session", - "operationId": "add_events", - "parameters": [ - { - "name": "visitor_id", - "in": "path", - "description": "Visitor ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "session_id", - "in": "path", - "description": "Session ID", - "required": true, - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AddEventsRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Events added successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AddEventsResponse" - } - } - } - }, - "400": { - "description": "Bad request", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - }, - "401": { - "description": "Authentication required", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - }, - "403": { - "description": "Insufficient permissions", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - }, - "404": { - "description": "Session not found", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ErrorResponse" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/vulnerability-scans/{scan_id}": { - "get": { - "tags": [ - "Vulnerability Scans" - ], - "operationId": "get_scan", - "parameters": [ - { - "name": "scan_id", - "in": "path", - "description": "Scan ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Scan details", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ScanResponse" - } - } - } - }, - "401": { - "description": "Unauthorized", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "403": { - "description": "Insufficient permissions", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "404": { - "description": "Scan not found", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - }, - "delete": { - "tags": [ - "Vulnerability Scans" - ], - "operationId": "delete_scan", - "parameters": [ - { - "name": "scan_id", - "in": "path", - "description": "Scan ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "204": { - "description": "Scan deleted" - }, - "401": { - "description": "Unauthorized", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "403": { - "description": "Insufficient permissions", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "404": { - "description": "Scan not found", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/vulnerability-scans/{scan_id}/vulnerabilities": { - "get": { - "tags": [ - "Vulnerability Scans" - ], - "operationId": "get_scan_vulnerabilities", - "parameters": [ - { - "name": "scan_id", - "in": "path", - "description": "Scan ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - }, - { - "name": "page", - "in": "query", - "description": "Page number (default: 1)", - "required": false, - "schema": { - "type": "integer", - "format": "int64", - "minimum": 0 - } - }, - { - "name": "page_size", - "in": "query", - "description": "Page size (default: 20, max: 100)", - "required": false, - "schema": { - "type": "integer", - "format": "int64", - "minimum": 0 - } - }, - { - "name": "severity", - "in": "query", - "description": "Filter by severity (CRITICAL, HIGH, MEDIUM, LOW)", - "required": false, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "List of vulnerabilities", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/VulnerabilityResponse" - } - } - } - } - }, - "401": { - "description": "Unauthorized", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "403": { - "description": "Insufficient permissions", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "404": { - "description": "Scan not found", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/webhook-event-types": { - "get": { - "tags": [ - "Webhooks" - ], - "summary": "List available event types", - "operationId": "list_event_types", - "responses": { - "200": { - "description": "List of available event types", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/EventTypeResponse" - } - } - } - } - } - } - } - }, - "/weekly-digest/trigger": { - "post": { - "tags": [ - "Notification Preferences" - ], - "summary": "Trigger weekly digest generation manually", - "operationId": "trigger_weekly_digest", - "responses": { - "200": { - "description": "Weekly digest triggered successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/TriggerDigestResponse" - } - } - } - }, - "500": { - "description": "Failed to generate digest" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/x/plugins": { - "get": { - "tags": [ - "External Plugins" - ], - "summary": "List all running external plugins and their manifests.", - "description": "Requires only a valid session/token (no specific permission) since the\nmanifest drives sidebar navigation rendering for every authenticated\nuser, not just admins.", - "operationId": "list_external_plugins", - "responses": { - "200": { - "description": "List of all running external plugins", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/PluginManifest" - } - } - } - } - }, - "401": { - "description": "Unauthorized" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/x/plugins/reload": { - "post": { - "tags": [ - "External Plugins" - ], - "summary": "Reload all external plugins.", - "description": "Stops all running plugin processes, re-scans the plugins directory,\nstarts any discovered binaries, and hot-swaps the proxy router so new\nand removed plugins take effect immediately without a server restart.\n\nRequires `SystemAdmin` permission.", - "operationId": "reload_plugins", - "responses": { - "200": { - "description": "Plugins reloaded successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ReloadResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - } - }, - "security": [ - { - "bearer_auth": [] - } - ] - } - }, - "/{project_id}/envelope/": { - "post": { - "tags": [ - "sentry-ingestor" - ], - "summary": "Ingest a Sentry envelope (binary payload)", - "operationId": "ingest_sentry_envelope", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "requestBody": { - "description": "Sentry envelope as binary data", - "content": { - "application/octet-stream": { - "schema": { - "type": "string" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Envelope ingested" - }, - "400": { - "description": "Bad request" - }, - "401": { - "description": "Unauthorized" - }, - "413": { - "description": "Request body too large (exceeds 2 MiB)" - } - } - } - }, - "/{project_id}/store/": { - "post": { - "tags": [ - "sentry-ingestor" - ], - "summary": "Ingest a Sentry event (JSON payload)", - "operationId": "ingest_sentry_event", - "parameters": [ - { - "name": "project_id", - "in": "path", - "description": "Project ID", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SentryEventRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "description": "Event ingested", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SentryEventResponse" - } - } - } - }, - "400": { - "description": "Bad request" - }, - "401": { - "description": "Unauthorized" - }, - "413": { - "description": "Request body too large (exceeds 2 MiB)" - } - } - } - }, - "audit/logs": { - "get": { - "tags": [ - "Audit Logs" - ], - "summary": "List audit logs with optional filtering", - "operationId": "list_audit_logs", - "parameters": [ - { - "name": "operation_type", - "in": "query", - "description": "Filter logs by operation type (omit for all)", - "required": false, - "schema": { - "type": "string" - }, - "example": "user.login" - }, - { - "name": "user_id", - "in": "query", - "description": "Filter logs by user ID (omit for all users)", - "required": false, - "schema": { - "type": "integer", - "format": "int32" - }, - "example": 1 - }, - { - "name": "from", - "in": "query", - "description": "Start timestamp (milliseconds since epoch)", - "required": false, - "schema": { - "type": "string", - "format": "date-time" - }, - "example": 1 - }, - { - "name": "to", - "in": "query", - "description": "End timestamp (milliseconds since epoch)", - "required": false, - "schema": { - "type": "string", - "format": "date-time" - }, - "example": 1 - }, - { - "name": "limit", - "in": "query", - "description": "Maximum number of logs to return", - "required": false, - "schema": { - "type": "integer", - "format": "int32" - }, - "example": 100 - }, - { - "name": "offset", - "in": "query", - "description": "Number of logs to skip", - "required": false, - "schema": { - "type": "integer", - "format": "int32" - }, - "example": 0 - } - ], - "responses": { - "200": { - "description": "List of audit logs", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/AuditLogResponse" - } - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "api_key": [] - } - ] - } - }, - "audit/logs/{id}": { - "get": { - "tags": [ - "Audit Logs" - ], - "summary": "Get a specific audit log entry by ID", - "operationId": "get_audit_log", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Audit log details", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AuditLogResponse" - } - } - } - }, - "401": { - "description": "Unauthorized" - }, - "403": { - "description": "Insufficient permissions" - }, - "404": { - "description": "Audit log not found" - }, - "500": { - "description": "Internal server error" - } - }, - "security": [ - { - "api_key": [] - } - ] - } - } - }, - "components": { - "schemas": { - "AcmeOrderResponse": { - "type": "object", - "required": [ - "id", - "order_url", - "domain_id", - "email", - "status", - "identifiers", - "created_at", - "updated_at" - ], - "properties": { - "authorizations": {}, - "certificate_url": { - "type": [ - "string", - "null" - ] - }, - "challenge_validation": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/ChallengeValidationStatus", - "description": "Live challenge validation status fetched from Let's Encrypt" - } - ] - }, - "created_at": { - "type": "integer", - "format": "int64" - }, - "domain_id": { - "type": "integer", - "format": "int32" - }, - "email": { - "type": "string" - }, - "error": { - "type": [ - "string", - "null" - ] - }, - "error_type": { - "type": [ - "string", - "null" - ] - }, - "expires_at": { - "type": [ - "integer", - "null" - ], - "format": "int64" - }, - "finalize_url": { - "type": [ - "string", - "null" - ] - }, - "id": { - "type": "integer", - "format": "int32" - }, - "identifiers": {}, - "order_url": { - "type": "string" - }, - "status": { - "type": "string" - }, - "updated_at": { - "type": "integer", - "format": "int64" - } - } - }, - "ActivateProviderResponse": { - "type": "object", - "required": [ - "default_provider" - ], - "properties": { - "default_provider": { - "type": "string" - } - } - }, - "ActiveVisitor": { - "type": "object", - "required": [ - "session_id", - "session_start", - "last_activity", - "page_count", - "event_count", - "duration_seconds", - "is_active" - ], - "properties": { - "current_page": { - "type": [ - "string", - "null" - ] - }, - "duration_seconds": { - "type": "integer", - "format": "int64" - }, - "event_count": { - "type": "integer", - "format": "int32" - }, - "is_active": { - "type": "boolean" - }, - "last_activity": { - "type": "string" - }, - "page_count": { - "type": "integer", - "format": "int32" - }, - "session_id": { - "type": "string" - }, - "session_start": { - "type": "string" - }, - "visitor_id": { - "type": [ - "string", - "null" - ] - } - } - }, - "ActiveVisitorsQuery": { - "type": "object", - "properties": { - "deployment_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "environment_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - } - } - }, - "ActiveVisitorsResponse": { - "type": "object", - "required": [ - "active_visitors", - "window_minutes" - ], - "properties": { - "active_visitors": { - "type": "integer", - "format": "int64" - }, - "window_minutes": { - "type": "integer", - "format": "int32" - } - } - }, - "ActivityDay": { - "type": "object", - "description": "Daily activity count for a single day", - "required": [ - "date", - "count", - "level" - ], - "properties": { - "count": { - "type": "integer", - "format": "int64", - "description": "Number of deployments on this day" - }, - "date": { - "type": "string", - "description": "Date in YYYY-MM-DD format", - "example": "2024-06-15" - }, - "level": { - "type": "integer", - "format": "int32", - "description": "Intensity level (0-4) for visualization\n0: No activity, 1: Low (1-2), 2: Medium (3-5), 3: High (6-10), 4: Very High (11+)", - "example": 2 - } - } - }, - "ActivityEvent": { - "type": "object", - "description": "A single activity event for the real-time activity feed", - "required": [ - "id", - "timestamp", - "event_type", - "page_path", - "is_crawler" - ], - "properties": { - "browser": { - "type": [ - "string", - "null" - ], - "description": "Browser" - }, - "city": { - "type": [ - "string", - "null" - ], - "description": "Visitor's city (from ip_geolocations)" - }, - "country": { - "type": [ - "string", - "null" - ], - "description": "Visitor's country (from ip_geolocations)" - }, - "country_code": { - "type": [ - "string", - "null" - ], - "description": "Visitor's country code (from ip_geolocations)" - }, - "device_type": { - "type": [ - "string", - "null" - ], - "description": "Device type" - }, - "event_name": { - "type": [ - "string", - "null" - ], - "description": "Event name (for custom events)" - }, - "event_type": { - "type": "string", - "description": "Event type: \"page_view\", \"custom\", etc." - }, - "id": { - "type": "integer", - "format": "int64", - "description": "Event ID" - }, - "is_crawler": { - "type": "boolean", - "description": "Whether this event was from a crawler" - }, - "latitude": { - "type": [ - "number", - "null" - ], - "format": "double", - "description": "Latitude" - }, - "longitude": { - "type": [ - "number", - "null" - ], - "format": "double", - "description": "Longitude" - }, - "operating_system": { - "type": [ - "string", - "null" - ], - "description": "Operating system" - }, - "page_path": { - "type": "string", - "description": "Page path where the event happened" - }, - "page_title": { - "type": [ - "string", - "null" - ], - "description": "Page title" - }, - "referrer": { - "type": [ - "string", - "null" - ], - "description": "Referrer" - }, - "timestamp": { - "type": "string", - "format": "date-time", - "description": "When the event occurred" - }, - "visitor_id": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Visitor numeric ID" - } - } - }, - "ActivityGraphQuery": { - "type": "object", - "description": "Query parameters for activity graph endpoint", - "properties": { - "days": { - "type": "integer", - "format": "int32", - "description": "Number of days to include (default: 365 for last year)" - }, - "environment_id": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Optional environment ID to filter activity" - }, - "project_id": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Optional project ID to filter activity" - } - } - }, - "ActivityGraphResponse": { - "type": "object", - "description": "Response for activity graph showing daily deployment activity", - "required": [ - "days", - "total_count", - "start_date", - "end_date" - ], - "properties": { - "days": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ActivityDay" - }, - "description": "Array of daily activity counts" - }, - "end_date": { - "type": "string", - "description": "Date range end (YYYY-MM-DD)", - "example": "2024-12-31" - }, - "start_date": { - "type": "string", - "description": "Date range start (YYYY-MM-DD)", - "example": "2024-01-01" - }, - "total_count": { - "type": "integer", - "format": "int64", - "description": "Total count of activities across all days" - } - } - }, - "AddClusterMemberRequest": { - "type": "object", - "description": "Request body for adding a single member to a running cluster.", - "required": [ - "role" - ], - "properties": { - "node_id": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Target worker node ID. Omit or null to run on the control plane." - }, - "role": { - "type": "string", - "description": "Member role. Currently only `replica` is accepted at runtime \u2014\nmonitor is a singleton, primary is elected by pg_auto_failover.", - "example": "replica" - } - } - }, - "AddContextRequest": { - "type": "object", - "required": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - }, - "AddEnvironmentDomainRequest": { - "type": "object", - "required": [ - "domain", - "is_primary" - ], - "properties": { - "domain": { - "type": "string" - }, - "is_primary": { - "type": "boolean" - } - } - }, - "AddEventsRequest": { - "type": "object", - "required": [ - "events" - ], - "properties": { - "events": { - "type": "string" - } - } - }, - "AddEventsResponse": { - "type": "object", - "required": [ - "event_count", - "message" - ], - "properties": { - "event_count": { - "type": "integer", - "minimum": 0 - }, - "message": { - "type": "string" - } - } - }, - "AddManagedDomainApiRequest": { - "type": "object", - "description": "Request to add a managed domain", - "required": [ - "domain" - ], - "properties": { - "auto_manage": { - "type": "boolean" - }, - "domain": { - "type": "string", - "example": "example.com" - }, - "generated_hostname_mode": { - "type": [ - "string", - "null" - ], - "description": "Generated hostname layout: `\"standard\"` (default) or `\"flat\"`." - }, - "sync_generated_records": { - "type": "boolean", - "description": "Opt in to reconciling generated hostnames into this domain's DNS zone." - } - } - }, - "AdminGateResponse": { - "type": "object", - "required": [ - "allowed_ips", - "allowed_hosts", - "trust_forwarded_for", - "source", - "editable" - ], - "properties": { - "allowed_hosts": { - "type": "array", - "items": { - "type": "string" - }, - "description": "`Host` header values allowed. Empty = any host." - }, - "allowed_ips": { - "type": "array", - "items": { - "type": "string" - }, - "description": "IPs / CIDRs allowed to reach the admin listener. Empty = any source." - }, - "editable": { - "type": "boolean", - "description": "True when the config is writable through this API. False when env\nvars are dictating the active config." - }, - "source": { - "$ref": "#/components/schemas/AdminGateSource", - "description": "Where the active config came from." - }, - "trust_forwarded_for": { - "type": "boolean", - "description": "When true, the gate trusts `X-Forwarded-For` from loopback peers." - } - } - }, - "AdminGateSource": { - "type": "string", - "description": "Where the active gate configuration came from. Env-supplied configs are\nfrozen at the process level \u2014 the UI shows them read-only and refuses to\npersist DB writes. DB-supplied configs are editable at runtime.", - "enum": [ - "default", - "db", - "env" - ] - }, - "AgentConfigResponse": { - "type": "object", - "description": "Response DTO for a single agent \u2014 masks the encrypted API key.", - "required": [ - "id", - "project_id", - "slug", - "name", - "source", - "enabled", - "trigger_config", - "ai_provider", - "api_key_set", - "max_turns", - "timeout_seconds", - "daily_budget_cents", - "cooldown_minutes", - "branch_prefix", - "deliverable", - "created_at", - "updated_at" - ], - "properties": { - "ai_model": { - "type": [ - "string", - "null" - ], - "description": "Preferred model for the CLI (e.g. \"sonnet\", \"gpt-5-codex\"). `None` means default." - }, - "ai_provider": { - "type": "string" - }, - "ai_provider_key_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "api_key_set": { - "type": "boolean", - "description": "`true` if an API key is set; `false` otherwise." - }, - "branch_prefix": { - "type": "string" - }, - "config_repo_branch": { - "type": [ - "string", - "null" - ], - "description": "Branch of the config repo to use." - }, - "config_repo_url": { - "type": [ - "string", - "null" - ], - "description": "Private config repo containing .claude/ directory (skills, MCP, plugins)." - }, - "cooldown_minutes": { - "type": "integer", - "format": "int32" - }, - "created_at": { - "type": "string" - }, - "daily_budget_cents": { - "type": "integer", - "format": "int32" - }, - "deliverable": { - "type": "string" - }, - "description": { - "type": [ - "string", - "null" - ] - }, - "enabled": { - "type": "boolean" - }, - "id": { - "type": "integer", - "format": "int32" - }, - "max_turns": { - "type": "integer", - "format": "int32" - }, - "mcp_servers_config": { - "description": "MCP servers config (Claude Code settings.json mcpServers format).\nCredential-bearing legacy inline values are write-only and appear as\n`***`. Omit this field on update to preserve their stored values." - }, - "name": { - "type": "string" - }, - "project_id": { - "type": "integer", - "format": "int32" - }, - "prompt": { - "type": [ - "string", - "null" - ] - }, - "sandbox_enabled": { - "type": [ - "boolean", - "null" - ], - "description": "None = use global sandbox setting, true = force on, false = force off" - }, - "skills_config": { - "description": "Skills config as JSON array." - }, - "slug": { - "type": "string" - }, - "source": { - "type": "string" - }, - "timeout_seconds": { - "type": "integer", - "format": "int32" - }, - "tools_config": { - "description": "Tools config as JSON array. Legacy custom-tool webhook URLs and headers\nare write-only and appear as `***`. Omit this field on update to\npreserve their stored values." - }, - "trigger_config": {}, - "updated_at": { - "type": "string" - }, - "webhook_token": { - "type": [ - "string", - "null" - ], - "description": "Secret token for the `X-Webhook-Token` header. Shown once when created,\nmasked with `***` prefix in subsequent reads." - }, - "webhook_url": { - "type": [ - "string", - "null" - ], - "description": "Public webhook URL for triggering this agent externally.\nOnly set when `on: { webhook: true }` is configured.\nUsage: `POST {webhook_url}` with header `X-Webhook-Token: {webhook_token}`" - } - } - }, - "AgentRunLogResponse": { - "type": "object", - "required": [ - "id", - "run_id", - "level", - "message", - "created_at" - ], - "properties": { - "created_at": { - "type": "string" - }, - "id": { - "type": "integer", - "format": "int64" - }, - "level": { - "type": "string" - }, - "message": { - "type": "string" - }, - "metadata": {}, - "run_id": { - "type": "integer", - "format": "int32" - } - } - }, - "AgentRunResponse": { - "type": "object", - "required": [ - "id", - "project_id", - "source", - "trigger_type", - "status", - "tokens_input", - "tokens_output", - "estimated_cost_cents", - "files_changed", - "created_at", - "sandbox_enabled" - ], - "properties": { - "agent_name": { - "type": [ - "string", - "null" - ], - "description": "Name of the agent that created this run, if available." - }, - "agent_slug": { - "type": [ - "string", - "null" - ], - "description": "Slug of the agent that created this run, if available." - }, - "ai_model": { - "type": [ - "string", - "null" - ] - }, - "ai_output": { - "type": [ - "string", - "null" - ] - }, - "ai_provider": { - "type": [ - "string", - "null" - ], - "description": "AI provider slug that executed this run (e.g. claude_cli, codex_cli, opencode)." - }, - "ai_reasoning": { - "type": [ - "string", - "null" - ] - }, - "ai_session_id": { - "type": [ - "string", - "null" - ], - "description": "Claude CLI session UUID for resuming conversations via `--resume`." - }, - "analysis": { - "type": [ - "string", - "null" - ], - "description": "Report / analysis text produced by the agent (used for report/notification deliverables)." - }, - "branch_name": { - "type": [ - "string", - "null" - ] - }, - "commit_sha": { - "type": [ - "string", - "null" - ] - }, - "completed_at": { - "type": [ - "string", - "null" - ] - }, - "config_id": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Optional. NULL for ephemeral CLI runs (`source = \"cli_ephemeral\"`) and\nhistorical autofixer runs that pre-date the agent_id column." - }, - "created_at": { - "type": "string" - }, - "ephemeral_yaml": { - "type": [ - "string", - "null" - ], - "description": "Full WorkflowYamlConfig as YAML text. Populated only when\n`source = \"cli_ephemeral\"`. Used by the web UI to show a \"View YAML\"\nmodal so the user can see exactly what the executor ran." - }, - "error_message": { - "type": [ - "string", - "null" - ] - }, - "estimated_cost_cents": { - "type": "integer", - "format": "int32" - }, - "files_changed": { - "type": "integer", - "format": "int32" - }, - "id": { - "type": "integer", - "format": "int32" - }, - "phase": { - "type": [ - "string", - "null" - ], - "description": "Autofixer phase: \"analyzing\", \"analyzed\", \"fixing\", \"fix_ready\", \"no_fix\",\n\"pr_created\", or NULL for non-autofixer runs." - }, - "pr_number": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "pr_url": { - "type": [ - "string", - "null" - ] - }, - "preview_url": { - "type": [ - "string", - "null" - ] - }, - "project_id": { - "type": "integer", - "format": "int32" - }, - "prompt_text": { - "type": [ - "string", - "null" - ], - "description": "Final assembled prompt the AI CLI actually saw (trigger context block +\nYAML prompt, with error-group fields interpolated). Captured once per\nrun. `None` for pre-migration rows." - }, - "run_config": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/AutofixRunConfig", - "description": "Per-run AI options the user chose when starting an autofixer run\n(provider, model, max_turns, branch). NULL for generic agent runs\nand historical rows. Used to prefill the retry dialog." - } - ] - }, - "sandbox_enabled": { - "type": "boolean", - "description": "Legacy field \u2014 all runs now execute in a sandbox. Kept for\nbackwards-compatible JSON shape; always `true`." - }, - "source": { - "type": "string", - "description": "`committed` (the run's config lives in `project_agents`) or\n`cli_ephemeral` (the config was uploaded via the CLI for a one-off\ndry run; see `ephemeral_yaml`)." - }, - "started_at": { - "type": [ - "string", - "null" - ] - }, - "status": { - "type": "string" - }, - "tokens_input": { - "type": "integer", - "format": "int32" - }, - "tokens_output": { - "type": "integer", - "format": "int32" - }, - "trigger_source_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "trigger_source_type": { - "type": [ - "string", - "null" - ] - }, - "trigger_type": { - "type": "string" - }, - "user_context": { - "type": [ - "string", - "null" - ], - "description": "User-provided context for this run (e.g. webhook payload, manual instructions)." - } - } - }, - "AgentRunWithLogsResponse": { - "type": "object", - "required": [ - "run", - "logs" - ], - "properties": { - "logs": { - "type": "array", - "items": { - "$ref": "#/components/schemas/AgentRunLogResponse" - } - }, - "run": { - "$ref": "#/components/schemas/AgentRunResponse" - } - } - }, - "AgentSandboxSettings": { - "type": "object", - "description": "Global agent sandbox settings. Controls whether agent runs are isolated\ninside Docker containers by default. Individual agents can override this.", - "properties": { - "api_key_encrypted": { - "type": [ - "string", - "null" - ], - "description": "DEPRECATED: use `providers[default_provider].credentials_encrypted` instead.", - "default": null - }, - "auth_type": { - "type": "string", - "description": "DEPRECATED: use `providers[default_provider].auth_type` instead.", - "default": "subscription" - }, - "cpu_limit": { - "type": "number", - "format": "double", - "description": "CPU limit in cores for sandbox containers", - "default": 4.0, - "example": 4.0 - }, - "custom_image": { - "type": "string", - "description": "Custom Docker image (only used when runtime is \"custom\").\nMust have git and claude CLI installed.", - "default": "", - "example": "" - }, - "default_provider": { - "type": "string", - "description": "Default AI provider for agents: \"claude_cli\", \"opencode\", or \"codex_cli\".\nWorkspaces always use this provider \u2014 no per-session override.", - "default": "claude_cli", - "example": "claude_cli" - }, - "enabled": { - "type": "boolean", - "description": "Sandbox is always enabled \u2014 the executor refuses to run any agent\noutside a sandboxed container. Field is retained so existing settings\nrows still deserialize, but it is ignored at runtime.", - "default": true - }, - "memory_limit_mb": { - "type": "integer", - "format": "int64", - "description": "Memory limit in MB for sandbox containers", - "default": 8192, - "example": 8192, - "minimum": 0 - }, - "network_mode": { - "type": "string", - "description": "Network access level: \"full\" (unrestricted), \"restricted\" (Temps network only), \"none\" (no network)", - "default": "full", - "example": "full" - }, - "providers": { - "type": "object", - "description": "Per-provider auth + config. Keyed by provider id (e.g. `claude_cli`,\n`codex_cli`, `opencode`). Adding a new provider only requires a new\ncatalog entry on the Rust side \u2014 the JSON column stays migration-free.", - "default": {}, - "additionalProperties": { - "$ref": "#/components/schemas/ProviderConfig" - }, - "propertyNames": { - "type": "string" - } - }, - "runtime": { - "type": "string", - "description": "Runtime preset: \"node\", \"bun\", \"python\", \"rust\", \"go\", \"full\", or \"custom\"", - "default": "node", - "example": "node" - }, - "sandbox_backend": { - "type": [ - "string", - "null" - ], - "description": "Default isolation backend for sandboxes: \"docker\" (default) or\n\"firecracker\" (ADR-029; requires `temps firecracker setup`). Only\nconsulted when the Firecracker backend probes available \u2014 otherwise\nDocker is used regardless.", - "default": null, - "example": "docker" - } - } - }, - "AgentSandboxSettingsMasked": { - "type": "object", - "description": "Agent sandbox settings with masked per-provider credentials.\nEach provider entry reports only whether a credential is saved, not\nthe encrypted blob itself. Non-sensitive fields (auth_type, default_model,\nextra) are passed through so the UI can render provider-specific state.", - "required": [ - "default_provider", - "providers", - "api_key_saved", - "auth_type", - "enabled", - "runtime", - "custom_image", - "cpu_limit", - "memory_limit_mb", - "network_mode", - "sandbox_backend" - ], - "properties": { - "api_key_saved": { - "type": "boolean" - }, - "auth_type": { - "type": "string" - }, - "cpu_limit": { - "type": "number", - "format": "double" - }, - "custom_image": { - "type": "string" - }, - "default_provider": { - "type": "string" - }, - "enabled": { - "type": "boolean" - }, - "memory_limit_mb": { - "type": "integer", - "format": "int64", - "minimum": 0 - }, - "network_mode": { - "type": "string" - }, - "providers": { - "type": "object", - "additionalProperties": { - "$ref": "#/components/schemas/ProviderConfigMasked" - }, - "propertyNames": { - "type": "string" - } - }, - "runtime": { - "type": "string" - }, - "sandbox_backend": { - "type": "string" - } - } - }, - "AggregatedBucketItem": { - "type": "object", - "required": [ - "timestamp", - "count" - ], - "properties": { - "count": { - "type": "integer", - "format": "int64" - }, - "timestamp": { - "type": "string" - } - } - }, - "AggregatedBucketsQuery": { - "type": "object", - "description": "Query parameters for aggregated metrics by time bucket", - "required": [ - "start_date", - "end_date" - ], - "properties": { - "aggregation_level": { - "$ref": "#/components/schemas/AggregationLevel", - "description": "Aggregation level: events, sessions, or visitors" - }, - "bucket_size": { - "type": "string", - "description": "Time bucket size: \"1 hour\", \"1 day\", \"1 week\", etc. (default: \"1 hour\")" - }, - "deployment_id": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Optional deployment filter" - }, - "end_date": { - "type": "string", - "format": "date-time", - "description": "End date for the query range" - }, - "environment_id": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Optional environment filter" - }, - "start_date": { - "type": "string", - "format": "date-time", - "description": "Start date for the query range" - } - } - }, - "AggregatedBucketsResponse": { - "type": "object", - "required": [ - "bucket_size", - "aggregation_level", - "items", - "total" - ], - "properties": { - "aggregation_level": { - "type": "string" - }, - "bucket_size": { - "type": "string" - }, - "items": { - "type": "array", - "items": { - "$ref": "#/components/schemas/AggregatedBucketItem" - } - }, - "total": { - "type": "integer", - "format": "int64" - } - } - }, - "AggregationLevel": { - "type": "string", - "enum": [ - "events", - "sessions", - "visitors" - ] - }, - "AggregationTemporality": { - "type": "string", - "description": "The aggregation temporality of a Sum/Histogram/ExponentialHistogram metric.\n\nMirrors OTel's `AggregationTemporality` proto enum: whether reported values\nare cumulative since the start of the series (Cumulative) or only the delta\nsince the previous report (Delta).", - "enum": [ - "unspecified", - "delta", - "cumulative" - ] - }, - "AiAgentBreakdownResponse": { - "type": "object", - "description": "Response wrapping the AI agent breakdown rows.", - "required": [ - "items", - "start_time", - "end_time" - ], - "properties": { - "end_time": { - "type": "string" - }, - "items": { - "type": "array", - "items": { - "$ref": "#/components/schemas/AiAgentBreakdownRow" - } - }, - "start_time": { - "type": "string" - } - } - }, - "AiAgentBreakdownRow": { - "type": "object", - "description": "One row in the AI-agent analytics breakdown. `agent` is the canonical\ncrawler name (e.g. `GPTBot`, `Claude-User`), `provider` is the vendor used\nfor grouping + logos. The UI mirrors the browsers card and ranks by\n`request_count`.", - "required": [ - "provider", - "agent", - "purpose", - "request_count", - "unique_ips" - ], - "properties": { - "agent": { - "type": "string" - }, - "last_seen": { - "type": [ - "string", - "null" - ], - "description": "Last-seen timestamp in RFC3339 format, or `None` if no rows matched.", - "example": "2026-05-29T12:00:00Z" - }, - "provider": { - "type": "string" - }, - "purpose": { - "type": "string" - }, - "request_count": { - "type": "integer", - "format": "int64" - }, - "unique_ips": { - "type": "integer", - "format": "int64" - } - } - }, - "AiAgentDescriptor": { - "type": "object", - "description": "Static descriptor for one entry in the known-AI-agents taxonomy.", - "required": [ - "provider", - "agent", - "purpose" - ], - "properties": { - "agent": { - "type": "string" - }, - "provider": { - "type": "string" - }, - "purpose": { - "type": "string" - } - } - }, - "AiAgentPageRow": { - "type": "object", - "description": "One row in the pages-by-agent breakdown. Returned by\n[`ProxyLogService::get_ai_agent_pages`] for a single named agent.\n`unique_ips` counts distinct client IPs that hit this path via that agent\n(same definition as the per-agent unique-IPs in [`AiAgentBreakdownRow`]).", - "required": [ - "path", - "request_count", - "unique_ips" - ], - "properties": { - "last_seen": { - "type": [ - "string", - "null" - ], - "description": "Last-seen timestamp in RFC3339 format, or `None` if no rows matched.", - "example": "2026-05-29T12:00:00Z" - }, - "path": { - "type": "string" - }, - "request_count": { - "type": "integer", - "format": "int64" - }, - "unique_ips": { - "type": "integer", - "format": "int64" - } - } - }, - "AiAgentPagesResponse": { - "type": "object", - "description": "Response wrapping the per-agent pages breakdown rows.", - "required": [ - "agent", - "items", - "start_time", - "end_time" - ], - "properties": { - "agent": { - "type": "string", - "description": "The agent name this breakdown is scoped to." - }, - "end_time": { - "type": "string" - }, - "items": { - "type": "array", - "items": { - "$ref": "#/components/schemas/AiAgentPageRow" - } - }, - "start_time": { - "type": "string" - } - } - }, - "AiAgentTimelineResponse": { - "type": "object", - "description": "Response wrapping the AI agent timeline rows.", - "required": [ - "items", - "start_time", - "end_time", - "bucket", - "group_by" - ], - "properties": { - "bucket": { - "type": "string", - "description": "Bucket interval used for the buckets (so the UI can label the x-axis).", - "example": "1 hour" - }, - "end_time": { - "type": "string" - }, - "group_by": { - "type": "string", - "description": "Echoes the grouping dimension actually applied.", - "example": "provider" - }, - "items": { - "type": "array", - "items": { - "$ref": "#/components/schemas/AiAgentTimelineRow" - } - }, - "start_time": { - "type": "string" - } - } - }, - "AiAgentTimelineRow": { - "type": "object", - "description": "One point in the AI-agent timeline: the request count for a single\n(`bucket`, `key`) pair, where `key` is a provider or agent name depending on\nthe requested grouping. The UI pivots these into one stacked series per\n`key` across the shared bucket x-axis.", - "required": [ - "bucket", - "key", - "request_count" - ], - "properties": { - "bucket": { - "type": "string", - "description": "Bucket start in RFC3339 format.", - "example": "2026-05-29T12:00:00Z" - }, - "key": { - "type": "string", - "description": "Provider or agent name this count belongs to.", - "example": "OpenAI" - }, - "request_count": { - "type": "integer", - "format": "int64" - } - } - }, - "AiChatLimitsSettings": { - "type": "object", - "description": "Bounds on one AI chat turn.\n\nA turn is bounded by TIME rather than by a number of steps. A step count\nsays nothing about cost or about how long someone has been watching a\nspinner, and it cuts short exactly the long, productive turns the chat\nexists for. The user can already see each tool call and press Stop; the\ndeadline is what guarantees an *unattended* turn still ends.\n\nThe right value is a property of the model, which is why it is configurable\nrather than compiled in: a full alert-suggestion turn takes ~10 minutes\nagainst a slow local model and seconds against a hosted one.", - "properties": { - "turn_timeout_secs": { - "type": "integer", - "format": "int32", - "description": "How long one turn may run before it is stopped and the partial answer\nreturned, in seconds. The user is told the turn was cut short.\n\nChecked between steps, not mid-call: a model round already in flight\nfinishes, so a turn can overrun by up to one round. Against a slow\nself-hosted model that is a minute or two. Aborting mid-stream would cut\nthe answer off in the middle of a sentence and throw away work already\npaid for, which is worse than a late stop.", - "default": 900, - "example": 900, - "maximum": 3600, - "minimum": 30 - } - } - }, - "AiConfigSettings": { - "type": "object", - "description": "Global AI configuration settings. Controls the default config repo\ncontaining `.claude/` directory (skills, MCP servers, plugins) that\ngets overlaid into every agent sandbox.", - "properties": { - "config_repo": { - "type": "string", - "description": "Global config repo URL in \"owner/repo\" format (e.g. \"myorg/claude-config\").\nCloned at agent run time and overlaid into the sandbox's `.claude/` directory.", - "default": "", - "example": "" - }, - "config_repo_branch": { - "type": "string", - "description": "Branch of the config repo to use.", - "default": "main", - "example": "main" - } - } - }, - "AiPageBreakdownResponse": { - "type": "object", - "description": "Response wrapping the AI page breakdown rows.", - "required": [ - "items", - "start_time", - "end_time" - ], - "properties": { - "end_time": { - "type": "string" - }, - "items": { - "type": "array", - "items": { - "$ref": "#/components/schemas/AiPageBreakdownRow" - } - }, - "start_time": { - "type": "string" - } - } - }, - "AiPageBreakdownRow": { - "type": "object", - "description": "One row in the AI-crawled-pages breakdown. `agent_count` is the number of\n*distinct* AI agents that hit this path, so the UI can show both how heavily\nand how broadly a page is being crawled.", - "required": [ - "path", - "request_count", - "agent_count" - ], - "properties": { - "agent_count": { - "type": "integer", - "format": "int64" - }, - "last_seen": { - "type": [ - "string", - "null" - ], - "description": "Last-seen timestamp in RFC3339 format, or `None` if no rows matched.", - "example": "2026-05-29T12:00:00Z" - }, - "path": { - "type": "string" - }, - "request_count": { - "type": "integer", - "format": "int64" - } - } - }, - "AiStatusBreakdownResponse": { - "type": "object", - "description": "Response wrapping the AI status breakdown rows.", - "required": [ - "items", - "start_time", - "end_time" - ], - "properties": { - "end_time": { - "type": "string" - }, - "items": { - "type": "array", - "items": { - "$ref": "#/components/schemas/AiStatusBreakdownRow" - } - }, - "start_time": { - "type": "string" - } - } - }, - "AiStatusBreakdownRow": { - "type": "object", - "description": "One row in the AI-agent HTTP status breakdown: the request count for a\nstatus class (`2xx`/`3xx`/`4xx`/`5xx`/`other`) across crawler traffic.", - "required": [ - "status_class", - "request_count" - ], - "properties": { - "request_count": { - "type": "integer", - "format": "int64" - }, - "status_class": { - "type": "string", - "description": "Status class label.", - "example": "2xx" - } - } - }, - "AlarmListResponse": { - "type": "object", - "description": "Paginated list of alarms.", - "required": [ - "items", - "total", - "page", - "page_size" - ], - "properties": { - "items": { - "type": "array", - "items": { - "$ref": "#/components/schemas/AlarmResponse" - } - }, - "page": { - "type": "integer", - "format": "int64", - "minimum": 0 - }, - "page_size": { - "type": "integer", - "format": "int64", - "minimum": 0 - }, - "total": { - "type": "integer", - "format": "int64", - "minimum": 0 - } - } - }, - "AlarmResponse": { - "type": "object", - "description": "Full alarm representation returned by list/summary endpoints.", - "required": [ - "id", - "project_id", - "alarm_type", - "severity", - "status", - "title", - "fired_at", - "created_at", - "updated_at" - ], - "properties": { - "acknowledged_at": { - "type": [ - "string", - "null" - ], - "description": "ISO-8601 UTC timestamp when the alarm was acknowledged, if any." - }, - "acknowledged_by": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "User ID who acknowledged the alarm, if any." - }, - "alarm_type": { - "type": "string" - }, - "container_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "created_at": { - "type": "string", - "description": "ISO-8601 UTC timestamp when the row was created." - }, - "deployment_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "environment_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "fired_at": { - "type": "string", - "description": "ISO-8601 UTC timestamp when the alarm fired." - }, - "id": { - "type": "integer", - "format": "int32" - }, - "message": { - "type": [ - "string", - "null" - ] - }, - "metadata": { - "description": "Arbitrary JSON metadata attached by the alarm source." - }, - "project_id": { - "type": "integer", - "format": "int32" - }, - "resolved_at": { - "type": [ - "string", - "null" - ], - "description": "ISO-8601 UTC timestamp when the alarm was resolved, if any." - }, - "service_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "severity": { - "type": "string" - }, - "status": { - "type": "string" - }, - "title": { - "type": "string" - }, - "updated_at": { - "type": "string", - "description": "ISO-8601 UTC timestamp when the row was last updated." - } - } - }, - "AlarmSummaryResponse": { - "type": "object", - "description": "Re-export AlarmSummary for the OpenAPI schema.", - "required": [ - "total_active", - "firing", - "acknowledged", - "critical", - "warning", - "by_type" - ], - "properties": { - "acknowledged": { - "type": "integer", - "format": "int32", - "minimum": 0 - }, - "by_type": { - "type": "object", - "additionalProperties": { - "type": "integer", - "format": "int32", - "minimum": 0 - }, - "propertyNames": { - "type": "string" - } - }, - "critical": { - "type": "integer", - "format": "int32", - "minimum": 0 - }, - "firing": { - "type": "integer", - "format": "int32", - "minimum": 0 - }, - "total_active": { - "type": "integer", - "format": "int32", - "minimum": 0 - }, - "warning": { - "type": "integer", - "format": "int32", - "minimum": 0 - } - } - }, - "AlertRuleResponse": { - "type": "object", - "required": [ - "id", - "project_id", - "name", - "trigger_type", - "trigger_config", - "notification_priority", - "cooldown_minutes", - "enabled", - "created_at", - "updated_at" - ], - "properties": { - "cooldown_minutes": { - "type": "integer", - "format": "int32" - }, - "created_at": { - "type": "string" - }, - "enabled": { - "type": "boolean" - }, - "environment_filter": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "error_level_filter": { - "type": [ - "string", - "null" - ] - }, - "id": { - "type": "integer", - "format": "int32" - }, - "name": { - "type": "string" - }, - "notification_priority": { - "type": "string" - }, - "project_id": { - "type": "integer", - "format": "int32" - }, - "trigger_config": {}, - "trigger_type": { - "type": "string" - }, - "updated_at": { - "type": "string" - } - } - }, - "AllocEntry": { - "type": "object", - "description": "Wire-format allocation. `null` in the JSON when the node hasn't been\nallocated yet \u2014 workers should treat that as \"single-host mode, do\nnot bring up the overlay\".", - "required": [ - "node_id", - "compute_cidr", - "bridge_address", - "underlay_address" - ], - "properties": { - "bridge_address": { - "type": "string" - }, - "compute_cidr": { - "type": "string" - }, - "node_id": { - "type": "string", - "description": "Stable v5 UUID derived from the database node id." - }, - "underlay_address": { - "type": "string" - } - } - }, - "AnalyticsSessionEventsResponse": { - "type": "object", - "required": [ - "session_id", - "events", - "total_events" - ], - "properties": { - "events": { - "type": "array", - "items": { - "$ref": "#/components/schemas/SessionEvent" - } - }, - "session_id": { - "type": "string" - }, - "total_events": { - "type": "integer", - "minimum": 0 - } - } - }, - "AnnotatedSpan": { - "type": "object", - "description": "A single span annotated with the project that originally stored it.\nUsed in `UnifiedTrace` to let the UI colour-code spans by project.", - "required": [ - "project_id", - "project_name", - "span" - ], - "properties": { - "project_id": { - "type": "integer", - "format": "int32", - "description": "The project that stored this span (same as `span.project_id`)." - }, - "project_name": { - "type": "string", - "description": "Human-readable project name for waterfall colour-coding and legend." - }, - "span": { - "$ref": "#/components/schemas/SpanRecord", - "description": "Original span data verbatim from storage." - } - } - }, - "AnomalyAlgorithm": { - "type": "string", - "description": "Anomaly baseline algorithm. Adding one (e.g. a new robust variant) is a\ncode-only enum addition \u2014 no migration, since it lives inside the blob.", - "enum": [ - "robust", - "basic", - "agile", - "ewma" - ] - }, - "AnomalyParams": { - "type": "object", - "description": "Seasonal anomaly-band detector parameters (stub \u2014 not yet evaluated).", - "properties": { - "algorithm": { - "$ref": "#/components/schemas/AnomalyAlgorithm", - "description": "Baseline model. `robust` is the default (seasonal, stable, flags level\nshifts); `ewma`/`agile` adopt level shifts; `basic` is non-seasonal." - }, - "baseline_lookback_days": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "How far back to build the baseline. `None` = an evaluator default." - }, - "deviations": { - "type": "number", - "format": "double", - "description": "Band width in robust standard deviations (Datadog's `bounds`)." - }, - "direction": { - "$ref": "#/components/schemas/Direction", - "description": "Which side(s) of the band a deviation must be on to count." - }, - "pct_anomalous": { - "type": "number", - "format": "double", - "description": "Fraction (0..=1) of points in the window that must be anomalous to fire." - }, - "seasonality": { - "$ref": "#/components/schemas/Seasonality", - "description": "Seasonality model for the baseline." - } - } - }, - "AnomalyPreviewPointResponse": { - "type": "object", - "required": [ - "bucket", - "value", - "lower", - "upper", - "breaching" - ], - "properties": { - "breaching": { - "type": "boolean" - }, - "bucket": { - "type": "string", - "example": "2025-10-12T12:15:47Z" - }, - "lower": { - "type": "number", - "format": "double", - "description": "Lower edge of the expected band at this point." - }, - "upper": { - "type": "number", - "format": "double", - "description": "Upper edge of the expected band at this point." - }, - "value": { - "type": "number", - "format": "double" - } - } - }, - "AnomalyPreviewRequest": { - "type": "object", - "required": [ - "project_id", - "metric_name", - "aggregation", - "window_secs", - "detection_config" - ], - "properties": { - "aggregation": { - "type": "string", - "description": "One of `avg|sum|min|max|count|rate|p50|p90|p95|p99`." - }, - "detection_config": { - "$ref": "#/components/schemas/DetectionConfig", - "description": "The detector to backtest. `static` and `anomaly` are supported \u2014 the\nkinds the evaluator actually runs." - }, - "end_time": { - "type": [ - "string", - "null" - ], - "description": "RFC 3339; defaults to now.", - "example": "2025-10-12T12:15:47Z" - }, - "metric_name": { - "type": "string" - }, - "project_id": { - "type": "integer", - "format": "int32" - }, - "start_time": { - "type": [ - "string", - "null" - ], - "description": "RFC 3339; defaults to 7 days before `end_time`.", - "example": "2025-10-12T12:15:47Z" - }, - "window_secs": { - "type": "integer", - "format": "int32" - } - } - }, - "AnomalyPreviewResponse": { - "type": "object", - "required": [ - "points", - "breach_count", - "baseline_samples", - "sufficient" - ], - "properties": { - "baseline_samples": { - "type": "integer", - "format": "int64", - "description": "Baseline sample count (drives the `sufficient` flag)." - }, - "breach_count": { - "type": "integer", - "format": "int64", - "description": "How many points in the range would have fired." - }, - "points": { - "type": "array", - "items": { - "$ref": "#/components/schemas/AnomalyPreviewPointResponse" - } - }, - "sufficient": { - "type": "boolean", - "description": "Whether the baseline had enough history for a trustworthy band." - } - } - }, - "ApiKeyListResponse": { - "type": "object", - "required": [ - "api_keys", - "total" - ], - "properties": { - "api_keys": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ApiKeyResponse" - } - }, - "total": { - "type": "integer", - "format": "int64", - "minimum": 0 - } - } - }, - "ApiKeyResponse": { - "type": "object", - "required": [ - "id", - "name", - "key_prefix", - "role_type", - "is_active", - "created_at" - ], - "properties": { - "created_at": { - "type": "string", - "format": "date-time", - "example": "2024-01-01T00:00:00Z" - }, - "expires_at": { - "type": [ - "string", - "null" - ], - "format": "date-time", - "example": "2024-12-31T23:59:59Z" - }, - "id": { - "type": "integer", - "format": "int32" - }, - "is_active": { - "type": "boolean" - }, - "key_prefix": { - "type": "string" - }, - "last_used_at": { - "type": [ - "string", - "null" - ], - "format": "date-time", - "example": "2024-01-01T00:00:00Z" - }, - "name": { - "type": "string" - }, - "permissions": { - "type": [ - "array", - "null" - ], - "items": { - "type": "string" - } - }, - "role_type": { - "type": "string" - } - } - }, - "AppSettings": { - "type": "object", - "description": "Application settings stored in the database\nAll fields have sensible defaults for easy onboarding", - "properties": { - "agent_sandbox": { - "oneOf": [ - { - "$ref": "#/components/schemas/AgentSandboxSettings" - } - ], - "default": { - "default_provider": "claude_cli", - "providers": {}, - "auth_type": "subscription", - "api_key_encrypted": null, - "enabled": true, - "runtime": "node", - "custom_image": "", - "cpu_limit": 4.0, - "memory_limit_mb": 8192, - "network_mode": "full", - "sandbox_backend": null - } - }, - "ai_chat_limits": { - "oneOf": [ - { - "$ref": "#/components/schemas/AiChatLimitsSettings", - "description": "Limits on a single AI chat turn. Operator-tunable because the right\nvalue depends on the model: a turn against a slow self-hosted model can\nlegitimately take ten minutes, while a hosted one finishes in seconds\nand a shorter ceiling keeps costs predictable." - } - ], - "default": { - "turn_timeout_secs": 900 - } - }, - "ai_config": { - "oneOf": [ - { - "$ref": "#/components/schemas/AiConfigSettings" - } - ], - "default": { - "config_repo": "", - "config_repo_branch": "main" - } - }, - "build_limits": { - "oneOf": [ - { - "$ref": "#/components/schemas/BuildLimitsSettings", - "description": "Build-time resource limits applied on the control plane to prevent\n`docker build` from saturating host CPU/RAM. Worker nodes are\nintentionally NOT subject to these limits (each worker is dedicated\nhardware that already has its own per-host headroom)." - } - ], - "default": { - "max_concurrent": 2, - "cpu_limit_cores": 0.0, - "memory_limit_mb": 0 - } - }, - "cluster_dns": { - "oneOf": [ - { - "$ref": "#/components/schemas/ClusterDnsSettings", - "description": "Cluster-DNS resolver settings (ADR-024, experimental beta). Off by\ndefault \u2014 see `ClusterDnsSettings` for the incident background and\ntrade-offs. Must be explicitly enabled by operators who need\n`*.temps.local` service-to-service resolution inside containers." - } - ], - "default": { - "enabled": false - } - }, - "console_version": { - "type": [ - "string", - "null" - ], - "description": "Binary version tag (e.g. \"v0.1.0\") of the *console* process\n(`temps serve`, role=all or role=console) that last started. Written\non console startup; read by the standalone `temps proxy` to detect\nversion skew during a rolling upgrade (ADR-017 Phase 3). `None` on\ninstalls that never ran a console build carrying this field.\n\nThis is informational state written by the binary itself \u2014 NOT an\noperator-tunable setting. It is intentionally absent from\n`AppSettingsResponse` and the PATCH path so an operator cannot\naccidentally overwrite the self-recorded value.", - "default": null - }, - "container_logs": { - "oneOf": [ - { - "$ref": "#/components/schemas/ContainerLogSettings" - } - ], - "default": { - "max_size": "50m", - "max_file": 3, - "service_max_size": "20m", - "service_max_file": 3 - } - }, - "disk_space_alert": { - "oneOf": [ - { - "$ref": "#/components/schemas/DiskSpaceAlertSettings" - } - ], - "default": { - "enabled": true, - "threshold_percent": 80, - "check_interval_seconds": 300, - "monitor_path": null - } - }, - "dns_provider": { - "oneOf": [ - { - "$ref": "#/components/schemas/DnsProviderSettings" - } - ], - "default": { - "provider": "manual", - "cloudflare_api_key": null - } - }, - "docker_registry": { - "oneOf": [ - { - "$ref": "#/components/schemas/DockerRegistrySettings" - } - ], - "default": { - "enabled": false, - "registry_url": null, - "username": null, - "password": null, - "tls_verify": true, - "ca_certificate": null - } - }, - "edge_target": { - "type": [ - "string", - "null" - ], - "description": "Public edge target that generated DNS records point at when a managed\ndomain opts into automatic record sync. An IPv4/IPv6 address produces an\n`A`/`AAAA` record; anything else is treated as a `CNAME` target. `None`\ndisables DNS record sync regardless of per-domain opt-in.", - "default": null - }, - "external_url": { - "type": [ - "string", - "null" - ], - "default": null - }, - "insecure_tls": { - "type": "boolean", - "description": "Skip TLS certificate verification on outbound HTTP clients built by the\nserver (deployer, agent, remote service client). Strictly opt-in for\noperators running self-signed control plane / worker certs on a trusted\ninternal network. Worker\u2192control-plane traffic that traverses the public\ninternet must keep this `false` \u2014 otherwise a MitM steals the join token.", - "default": false - }, - "internal_url": { - "type": [ - "string", - "null" - ], - "description": "URL that service containers use to reach the Temps API from *inside*\nthe Docker network (OTLP metrics ingest, agent callbacks, etc.). On\nDocker Desktop this defaults to `http://host.docker.internal:`;\non Linux it requires the `host.docker.internal:host-gateway` host\nmapping (which Temps adds to provisioned containers). Distinct from\n`external_url`, which is the public-facing address.", - "default": null - }, - "letsencrypt": { - "oneOf": [ - { - "$ref": "#/components/schemas/LetsEncryptSettings" - } - ], - "default": { - "email": null, - "environment": "production" - } - }, - "monitoring": { - "oneOf": [ - { - "$ref": "#/components/schemas/MonitoringSettings", - "description": "Metrics observability settings. Controls the MetricsStore backend,\nscrape interval, and tiered retention windows." - } - ], - "default": { - "enabled": false, - "store": "timescale_db", - "scrape_interval_secs": 30, - "retention_raw_days": 7, - "retention_hourly_days": 90, - "retention_daily_years": 2, - "clickhouse_url": null - } - }, - "multi_node": { - "oneOf": [ - { - "$ref": "#/components/schemas/MultiNodeSettings" - } - ], - "default": { - "join_token_hash": null, - "private_address": null, - "legacy_shared_token_enabled": true, - "cluster_ca_cert_pem": null, - "cluster_ca_key_encrypted": null, - "require_mtls": false, - "node_cpu_alert_percent": 90.0, - "node_memory_alert_percent": 90.0, - "node_disk_alert_percent": 90.0 - } - }, - "observability_compression": { - "oneOf": [ - { - "$ref": "#/components/schemas/ObservabilityCompressionSettings", - "description": "TimescaleDB compression delays for immutable observability data.\nChanges are applied at runtime by the Settings API." - } - ], - "default": { - "proxy_logs_after_hours": 24, - "otel_spans_after_hours": 24 - } - }, - "observability_retention": { - "oneOf": [ - { - "$ref": "#/components/schemas/ObservabilityRetentionSettings", - "description": "Retention windows for raw proxy and OpenTelemetry telemetry.\nTimescaleDB policies are updated at runtime by the Settings API." - } - ], - "default": { - "proxy_logs_days": 30, - "otel_spans_days": 90, - "otel_logs_days": 90, - "otel_metrics_days": 90 - } - }, - "on_demand_tls": { - "oneOf": [ - { - "$ref": "#/components/schemas/OnDemandTlsSettings" - } - ], - "default": { - "enabled": false, - "zone": null, - "max_concurrent": 3, - "hourly_cap": 10, - "deployment_url_mode": "http" - } - }, - "preview_domain": { - "type": "string", - "default": "localho.st" - }, - "preview_gateway": { - "oneOf": [ - { - "$ref": "#/components/schemas/PreviewGatewaySettings" - } - ], - "default": { - "image": "ghcr.io/gotempsh/temps-preview-gateway:latest", - "host_port": 8090, - "auto_upgrade": true - } - }, - "rate_limiting": { - "oneOf": [ - { - "$ref": "#/components/schemas/RateLimitSettings" - } - ], - "default": { - "enabled": false, - "max_requests_per_minute": 60, - "max_requests_per_hour": 1000, - "whitelist_ips": [], - "blacklist_ips": [] - } - }, - "require_mfa_for_admins": { - "type": "boolean", - "description": "When `true`, any user holding the `Admin` role must have MFA enrolled\n(`users.mfa_enabled = true`) to complete a **password** login. Users\nwithout MFA enrolled are rejected with a typed error instructing them\nto enroll before retrying. This only gates the password-login path\n(`AuthService::login`) -- SSO/OIDC logins are handled by a separate\ncode path (`OidcService::resolve_user` + `oidc_handler`) and are\nintentionally unaffected, since federating identity to a\nproperly-hardened IdP is itself an acceptable alternative to local\nTOTP MFA. Modeled as a settings row (not an env var) per CLAUDE.md so\nan operator can flip it at runtime via the Settings API without\nrestarting the binary.", - "default": false - }, - "screenshots": { - "oneOf": [ - { - "$ref": "#/components/schemas/ScreenshotSettings" - } - ], - "default": { - "enabled": false, - "provider": "local", - "url": "" - } - }, - "security_headers": { - "oneOf": [ - { - "$ref": "#/components/schemas/SecurityHeadersSettings" - } - ], - "default": { - "enabled": false, - "preset": "moderate", - "content_security_policy": "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' data:; connect-src 'self'; frame-ancestors 'self'", - "x_frame_options": "SAMEORIGIN", - "x_content_type_options": "nosniff", - "x_xss_protection": "1; mode=block", - "strict_transport_security": "max-age=31536000; includeSubDomains", - "referrer_policy": "strict-origin-when-cross-origin", - "permissions_policy": "geolocation=(), microphone=(), camera=()" - } - }, - "setup_complete": { - "type": "boolean", - "description": "Set to `true` by `temps setup` (all modes) once initial configuration\nhas been applied. The web onboarding wizard reads this from the server\nand skips itself when true, preventing the \"Configure Base Domain\" wall\nfrom appearing on installs that were already configured via the CLI.", - "default": false - } - } - }, - "AppSettingsResponse": { - "type": "object", - "description": "Safe response for application settings that masks sensitive fields", - "required": [ - "preview_domain", - "screenshots", - "letsencrypt", - "dns_provider", - "security_headers", - "rate_limiting", - "docker_registry", - "disk_space_alert", - "container_logs", - "agent_sandbox", - "ai_config", - "preview_gateway", - "multi_node", - "monitoring", - "observability_compression", - "observability_retention", - "effective_metrics_store", - "effective_observability_store", - "insecure_tls", - "setup_complete", - "require_mfa_for_admins", - "cluster_dns", - "build_limits", - "ai_chat_limits" - ], - "properties": { - "agent_sandbox": { - "$ref": "#/components/schemas/AgentSandboxSettingsMasked" - }, - "ai_chat_limits": { - "$ref": "#/components/schemas/AiChatLimitsSettings", - "description": "Per-turn limits for the AI chat. No sensitive content." - }, - "ai_config": { - "$ref": "#/components/schemas/AiConfigSettings" - }, - "build_limits": { - "$ref": "#/components/schemas/BuildLimitsSettings", - "description": "Build-time resource limits (control-plane only). No sensitive content,\npassed through as-is." - }, - "cluster_dns": { - "$ref": "#/components/schemas/ClusterDnsSettings", - "description": "Cluster-DNS resolver settings (ADR-024, experimental beta). No masking\nneeded \u2014 `enabled` is a plain bool with no sensitive content. Passed\nthrough as-is so the settings UI can read and toggle the flag." - }, - "container_logs": { - "$ref": "#/components/schemas/ContainerLogSettings" - }, - "disk_space_alert": { - "$ref": "#/components/schemas/DiskSpaceAlertSettings" - }, - "dns_provider": { - "$ref": "#/components/schemas/DnsProviderSettingsMasked" - }, - "docker_registry": { - "$ref": "#/components/schemas/DockerRegistrySettingsMasked" - }, - "edge_target": { - "type": [ - "string", - "null" - ], - "description": "Public edge target that synced DNS records point at (IP \u2192 A/AAAA, else CNAME)." - }, - "effective_metrics_store": { - "$ref": "#/components/schemas/MetricsStoreKind", - "description": "The storage backend the runtime is **actually** using for metrics,\nafter reconciling the `monitoring.store` toggle with the server's\n`TEMPS_CLICKHOUSE_*` configuration. When `monitoring.store` is\n`click_house` but those env vars are not fully set, the runtime falls\nback to TimescaleDB \u2014 in that case this reports `timescale_db` even\nthough `monitoring.store` says `click_house`. The UI shows this as the\neffective backend and warns when it diverges from the configured store." - }, - "effective_observability_store": { - "$ref": "#/components/schemas/MetricsStoreKind", - "description": "Storage backend actually used for proxy logs, OTel spans, and OTel\nmetrics. OTel logs remain TimescaleDB-backed. Unlike resource metrics,\nthese domains switch to ClickHouse whenever the server-level ClickHouse\nconnection is configured; they do not use the monitoring store toggle." - }, - "external_url": { - "type": [ - "string", - "null" - ] - }, - "insecure_tls": { - "type": "boolean" - }, - "internal_url": { - "type": [ - "string", - "null" - ] - }, - "letsencrypt": { - "$ref": "#/components/schemas/LetsEncryptSettings" - }, - "monitored_services_count": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "description": "Number of enabled, running services the MetricsScraper currently\nincludes. Used for the lightweight storage estimate in the UI.", - "minimum": 0 - }, - "monitoring": { - "$ref": "#/components/schemas/MonitoringSettingsMasked" - }, - "multi_node": { - "$ref": "#/components/schemas/MultiNodeSettingsMasked" - }, - "observability_compression": { - "$ref": "#/components/schemas/ObservabilityCompressionSettings", - "description": "TimescaleDB compression delays for immutable proxy logs and OTel spans." - }, - "observability_retention": { - "$ref": "#/components/schemas/ObservabilityRetentionSettings", - "description": "Retention windows for raw proxy logs and OpenTelemetry data." - }, - "preview_domain": { - "type": "string" - }, - "preview_gateway": { - "$ref": "#/components/schemas/PreviewGatewaySettingsMasked" - }, - "rate_limiting": { - "$ref": "#/components/schemas/RateLimitSettings" - }, - "require_mfa_for_admins": { - "type": "boolean", - "description": "When enabled, Admin-role accounts without MFA enrolled are rejected\nat password login (bherila/temps#32). SSO/OIDC logins are unaffected." - }, - "screenshots": { - "$ref": "#/components/schemas/ScreenshotSettings" - }, - "security_headers": { - "$ref": "#/components/schemas/SecurityHeadersSettings" - }, - "setup_complete": { - "type": "boolean", - "description": "Whether `temps setup` has been run at least once. The web onboarding\nwizard checks this field on load and skips itself when true." - } - } - }, - "ApplyHostnameModeRequest": { - "type": "object", - "description": "Request to apply a hostname mode (recompute + optional DNS sync).", - "required": [ - "mode" - ], - "properties": { - "mode": { - "type": "string", - "description": "Target mode to apply: `\"standard\"` or `\"flat\"`." - }, - "sync_dns": { - "type": "boolean", - "description": "Also reconcile the provider's DNS zone for the affected hostnames." - } - } - }, - "ArchiveFlagResponse": { - "type": "object", - "required": [ - "key" - ], - "properties": { - "archived_at": { - "type": [ - "string", - "null" - ] - }, - "key": { - "type": "string" - } - } - }, - "ArchiveMode": { - "type": "string", - "enum": [ - "off", - "on", - "always", - "unknown" - ] - }, - "AssignRoleRequest": { - "type": "object", - "required": [ - "user_id", - "role_type" - ], - "properties": { - "role_type": { - "type": "string" - }, - "user_id": { - "type": "integer", - "format": "int32" - } - } - }, - "AttachScheduleServicesRequest": { - "type": "object", - "description": "Body for `POST /api/backups/schedules/{id}/services` \u2014 attach external\nservices to a backup schedule. Idempotent.", - "required": [ - "service_ids" - ], - "properties": { - "service_ids": { - "type": "array", - "items": { - "type": "integer", - "format": "int32" - }, - "description": "External service ids to attach. Duplicates are de-duplicated server-side." - } - } - }, - "AttachScheduleServicesResponse": { - "type": "object", - "description": "Response for `POST /api/backups/schedules/{id}/services`.", - "required": [ - "inserted", - "total_attached" - ], - "properties": { - "inserted": { - "type": "integer", - "format": "int64", - "description": "Number of rows actually inserted (excludes rows skipped by\n`ON CONFLICT DO NOTHING`).", - "minimum": 0 - }, - "total_attached": { - "type": "integer", - "description": "Total number of services now attached to the schedule.", - "minimum": 0 - } - } - }, - "AuditLogIpInfo": { - "type": "object", - "description": "IP address information in audit log", - "required": [ - "ip" - ], - "properties": { - "city": { - "type": [ - "string", - "null" - ], - "description": "City name", - "example": "San Francisco" - }, - "country": { - "type": [ - "string", - "null" - ], - "description": "Country code", - "example": "US" - }, - "ip": { - "type": "string", - "description": "IP address", - "example": "192.168.1.1" - }, - "latitude": { - "type": [ - "number", - "null" - ], - "format": "double", - "description": "Latitude", - "example": 37.7749 - }, - "longitude": { - "type": [ - "number", - "null" - ], - "format": "double", - "description": "Longitude", - "example": 122.4194 - } - } - }, - "AuditLogResponse": { - "type": "object", - "description": "Response type for audit log entries", - "required": [ - "id", - "operation_type", - "audit_date" - ], - "properties": { - "audit_date": { - "type": "integer", - "format": "int64", - "description": "When the action occurred", - "example": 11932193 - }, - "data": { - "description": "Additional context about the action" - }, - "id": { - "type": "integer", - "format": "int32", - "description": "Unique identifier for the audit log entry" - }, - "ip_address": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/AuditLogIpInfo", - "description": "IP address details" - } - ] - }, - "operation_type": { - "type": "string", - "description": "The type of action that was performed", - "example": "USER_LOGIN" - }, - "user": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/AuditLogUserInfo", - "description": "User details who performed the action" - } - ] - }, - "user_id": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "The user who performed the action (`null` when that account has\nsince been deleted; `data` retains the original actor context)" - } - } - }, - "AuditLogUserInfo": { - "type": "object", - "description": "User information in audit log", - "required": [ - "id", - "name", - "email" - ], - "properties": { - "email": { - "type": "string", - "description": "User's email", - "example": "john.doe@example.com" - }, - "id": { - "type": "integer", - "format": "int32", - "description": "User ID" - }, - "name": { - "type": "string", - "description": "User's name", - "example": "John Doe" - } - } - }, - "AuthFlavorDto": { - "type": "object", - "description": "One auth flavor surfaced to the UI. Mirrors `AuthFlavor` in the catalog\nbut without the seed-path / env-var fields the frontend doesn't need\n(those are server-side only \u2014 exposing them just bloats the response).", - "required": [ - "id", - "label", - "description", - "format" - ], - "properties": { - "description": { - "type": "string" - }, - "env_var": { - "type": [ - "string", - "null" - ], - "description": "For `api_key` format: the env var name that will be set inside the\nsandbox. Useful for showing the user \"we'll set OPENAI_API_KEY\" so\nthey know what their key controls." - }, - "format": { - "type": "string", - "description": "`api_key`, `oauth_token`, or `config_file` \u2014 drives which input UI\nthe settings page renders (single-line vs. multi-line textarea)." - }, - "id": { - "type": "string" - }, - "label": { - "type": "string" - } - } - }, - "AuthResponse": { - "type": "object", - "required": [ - "success", - "message", - "mfa_required" - ], - "properties": { - "message": { - "type": "string" - }, - "mfa_required": { - "type": "boolean" - }, - "success": { - "type": "boolean" - }, - "user_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - } - } - }, - "AuthStatusResponse": { - "type": "object", - "required": [ - "status" - ], - "properties": { - "cli_token": { - "type": [ - "string", - "null" - ] - }, - "status": { - "type": "string" - } - } - }, - "AuthTokenResponse": { - "type": "object", - "required": [ - "access_token", - "refresh_token", - "expires_at" - ], - "properties": { - "access_token": { - "type": "string" - }, - "expires_at": { - "type": "integer", - "format": "int64" - }, - "refresh_token": { - "type": "string" - } - } - }, - "AutoWatchParams": { - "type": "object", - "description": "Auto-watch (Watchdog-style) detector parameters (stub \u2014 not evaluated).", - "properties": { - "direction": { - "$ref": "#/components/schemas/Direction", - "description": "The engine self-tunes the band; the user supplies only the direction." - } - } - }, - "AutofixRunConfig": { - "type": "object", - "description": "User-chosen per-run options, persisted as JSON in `agent_runs.run_config`.\nEvery field is optional \u2014 unset fields fall back to the provider defaults\nin settings, then to built-in defaults.", - "properties": { - "branch": { - "type": [ - "string", - "null" - ], - "description": "Branch to clone instead of the project's main branch.", - "default": null - }, - "max_turns": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Per-run turn cap applied to every phase of this run. Only enforced\nfor CLIs with a turn flag (Claude Code); Codex/OpenCode run to\ncompletion. `None` uses the provider's per-phase defaults.", - "default": null - }, - "model": { - "type": [ - "string", - "null" - ], - "description": "Model id for the chosen provider. `None` uses the provider's saved\ndefault model, or the CLI's own default.", - "default": null - }, - "provider": { - "type": [ - "string", - "null" - ], - "description": "AI provider id (\"claude_cli\", \"codex_cli\", \"opencode\"). `None` uses\nthe platform default provider from agent sandbox settings.", - "default": null - } - } - }, - "AutofixerRunResponse": { - "type": "object", - "required": [ - "id", - "project_id", - "status", - "tokens_input", - "tokens_output", - "files_changed", - "created_at" - ], - "properties": { - "ai_model": { - "type": [ - "string", - "null" - ] - }, - "ai_output": { - "type": [ - "string", - "null" - ] - }, - "ai_provider": { - "type": [ - "string", - "null" - ], - "description": "AI provider slug this run executes with (e.g. claude_cli, codex_cli)." - }, - "analysis": { - "type": [ - "string", - "null" - ] - }, - "branch_name": { - "type": [ - "string", - "null" - ] - }, - "completed_at": { - "type": [ - "string", - "null" - ] - }, - "created_at": { - "type": "string" - }, - "error_message": { - "type": [ - "string", - "null" - ] - }, - "files_changed": { - "type": "integer", - "format": "int32" - }, - "id": { - "type": "integer", - "format": "int32" - }, - "phase": { - "type": [ - "string", - "null" - ] - }, - "pr_number": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "pr_url": { - "type": [ - "string", - "null" - ] - }, - "project_id": { - "type": "integer", - "format": "int32" - }, - "run_config": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/AutofixRunConfig", - "description": "Per-run options the run was started with; used to prefill the\nretry / start-over dialog." - } - ] - }, - "started_at": { - "type": [ - "string", - "null" - ] - }, - "status": { - "type": "string" - }, - "tokens_input": { - "type": "integer", - "format": "int32" - }, - "tokens_output": { - "type": "integer", - "format": "int32" - }, - "trigger_source_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "user_context": { - "type": [ - "string", - "null" - ] - } - } - }, - "AutofixerRunWithLogsResponse": { - "type": "object", - "required": [ - "run", - "logs" - ], - "properties": { - "logs": { - "type": "array", - "items": { - "$ref": "#/components/schemas/AgentRunLogResponse" - } - }, - "run": { - "$ref": "#/components/schemas/AutofixerRunResponse" - } - } - }, - "AvailableContainerInfo": { - "type": "object", - "description": "Available Docker container that can be imported as a service", - "required": [ - "container_id", - "container_name", - "image", - "version", - "service_type", - "is_running" - ], - "properties": { - "container_id": { - "type": "string", - "description": "Container ID or name", - "example": "abc123def456" - }, - "container_name": { - "type": "string", - "description": "Container display name", - "example": "my-postgres" - }, - "exposed_ports": { - "type": "array", - "items": { - "type": "integer", - "format": "int32", - "minimum": 0 - }, - "description": "Exposed ports (e.g., [5432] for PostgreSQL, [6379] for Redis)" - }, - "image": { - "type": "string", - "description": "Docker image name (e.g., \"gotempsh/postgres-walg:18-bookworm\")", - "example": "gotempsh/postgres-walg:18-bookworm" - }, - "is_running": { - "type": "boolean", - "description": "Whether the container is currently running", - "example": true - }, - "service_type": { - "$ref": "#/components/schemas/ServiceTypeRoute", - "description": "Service type this container represents" - }, - "version": { - "type": "string", - "description": "Extracted version from image", - "example": "18" - } - } - }, - "AvailablePermissions": { - "type": "object", - "description": "Response containing all available permissions for frontend validation", - "required": [ - "permissions", - "roles" - ], - "properties": { - "permissions": { - "type": "array", - "items": { - "$ref": "#/components/schemas/PermissionInfo" - }, - "description": "All available permissions in the system" - }, - "roles": { - "type": "array", - "items": { - "$ref": "#/components/schemas/RoleInfo" - }, - "description": "All available roles" - } - } - }, - "BackupAlertListResponse": { - "type": "object", - "description": "Response body for the list-backup-alerts endpoint.", - "required": [ - "alerts" - ], - "properties": { - "alerts": { - "type": "array", - "items": { - "$ref": "#/components/schemas/BackupAlertResponse" - }, - "description": "All currently open (unresolved) alerts, newest first." - } - } - }, - "BackupAlertResponse": { - "type": "object", - "description": "A single open backup alert surfaced in the UI banner.\n\nAlerts are auto-opened by the watcher and auto-resolved when the triggering\ncondition clears. No manual dismiss is required or supported.\n\nThe optional `schedule_s3_source_id` field is included so the UI can\ndeep-link an `overdue_schedule` alert to the S3 source detail page that\nhosts the schedule. `stalled_job` alerts no longer carry a deep-link\ntarget \u2014 the alert message text contains the backup id for display.", - "required": [ - "id", - "kind", - "severity", - "message", - "opened_at" - ], - "properties": { - "id": { - "type": "integer", - "format": "int64", - "description": "Database id of the alert row." - }, - "kind": { - "type": "string", - "description": "`\"overdue_schedule\"` or `\"stalled_job\"`." - }, - "message": { - "type": "string", - "description": "Human-readable description of the alert condition." - }, - "opened_at": { - "type": "string", - "description": "RFC 3339 timestamp when the alert was opened.", - "example": "2026-05-15T10:00:00Z" - }, - "schedule_id": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "FK to `backup_schedules.id`. Set for `overdue_schedule` alerts." - }, - "schedule_name": { - "type": [ - "string", - "null" - ], - "description": "Human-readable name of the linked schedule, if applicable." - }, - "schedule_s3_source_id": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "FK to `backup_schedules.s3_source_id`. The UI uses this to deep-link\nthe alert to the S3 source detail page that hosts the schedule.\nSet for `overdue_schedule` alerts." - }, - "severity": { - "type": "string", - "description": "`\"warning\"` or `\"critical\"`." - } - } - }, - "BackupResponse": { - "type": "object", - "description": "Response type for backup", - "required": [ - "id", - "name", - "backup_id", - "backup_type", - "state", - "started_at", - "s3_source_id", - "s3_location", - "metadata", - "compression_type", - "created_by", - "tags" - ], - "properties": { - "attempts": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "How many times this job has been claimed and run. `null` for legacy\nbackups with no `backup_jobs` row." - }, - "backup_id": { - "type": "string" - }, - "backup_type": { - "type": "string" - }, - "checksum": { - "type": [ - "string", - "null" - ] - }, - "completed_at": { - "type": [ - "integer", - "null" - ], - "format": "int64" - }, - "compression_type": { - "type": "string" - }, - "created_by": { - "type": "integer", - "format": "int32" - }, - "current_step": { - "type": [ - "string", - "null" - ], - "description": "Name of the engine step currently executing (e.g., `\"walg_push\"`).\n`null` when no `backup_jobs` row exists for this backup (legacy rows\npre-dating ADR-014), or when the job has not yet completed its first step." - }, - "error_message": { - "type": [ - "string", - "null" - ] - }, - "expires_at": { - "type": [ - "integer", - "null" - ], - "format": "int64" - }, - "external_service": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/ExternalServiceSummary", - "description": "External service that owns this backup (Redis, Postgres, etc.).\n`null` for control-plane backups (the Temps server's own database)." - } - ] - }, - "file_count": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "id": { - "type": "integer", - "format": "int32" - }, - "live_size_bytes": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "description": "Best-effort partial size while a backup is still running, computed\nby listing the S3 prefix. Null when the backup is finished\n(`size_bytes` is authoritative in that case)." - }, - "max_attempts": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Maximum attempts before the job is permanently failed. `null` for\nlegacy backups." - }, - "max_runtime_secs": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "description": "Resolved wall-clock timeout for this backup job (seconds). `null` for\nlegacy backups. Derived from the three-tier resolution order:\ncaller override \u2192 schedule override \u2192 engine default." - }, - "metadata": {}, - "name": { - "type": "string" - }, - "s3_location": { - "type": "string" - }, - "s3_source_id": { - "type": "integer", - "format": "int32" - }, - "schedule_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "size_bytes": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "description": "Final size of the backup once completed. Null while running." - }, - "started_at": { - "type": "integer", - "format": "int64" - }, - "state": { - "type": "string" - }, - "tags": { - "type": "array", - "items": { - "type": "string" - } - } - } - }, - "BackupScheduleResponse": { - "type": "object", - "description": "Response type for backup schedule", - "required": [ - "id", - "name", - "backup_type", - "retention_period", - "s3_source_id", - "schedule_expression", - "enabled", - "created_at", - "updated_at", - "tags", - "target_all_services", - "include_control_plane" - ], - "properties": { - "backup_type": { - "type": "string" - }, - "created_at": { - "type": "integer", - "format": "int64" - }, - "description": { - "type": [ - "string", - "null" - ] - }, - "enabled": { - "type": "boolean" - }, - "id": { - "type": "integer", - "format": "int32" - }, - "include_control_plane": { - "type": "boolean", - "description": "When `true`, every run also produces a `control_plane` backup\n(Temps's own Postgres). When `false`, only the external service\nfan-out happens." - }, - "last_run": { - "type": [ - "integer", - "null" - ], - "format": "int64" - }, - "max_runtime_secs": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "description": "Per-schedule wall-clock timeout override for backup jobs (seconds).\n`null` means the engine-family default is used. See\n`temps_backup_core::timeouts::default_max_runtime_secs`." - }, - "name": { - "type": "string" - }, - "next_run": { - "type": [ - "integer", - "null" - ], - "format": "int64" - }, - "retention_period": { - "type": "integer", - "format": "int32" - }, - "s3_source_id": { - "type": "integer", - "format": "int32" - }, - "schedule_expression": { - "type": "string", - "example": "0 0 * * *" - }, - "tags": { - "type": "array", - "items": { - "type": "string" - } - }, - "target_all_services": { - "type": "boolean", - "description": "When `true`, the schedule auto-includes every external service on\nthe host (and any future ones). When `false`, the schedule only\ntargets services attached via `backup_schedule_services`." - }, - "updated_at": { - "type": "integer", - "format": "int64" - } - } - }, - "BitbucketAuthInput": { - "oneOf": [ - { - "type": "object", - "description": "Personal / Workspace / Repository Access Token.", - "required": [ - "token", - "type" - ], - "properties": { - "token": { - "type": "string", - "description": "The Bitbucket access token value." - }, - "type": { - "type": "string", - "enum": [ - "access_token" - ] - } - } - }, - { - "type": "object", - "description": "HTTP Basic / App Password authentication.", - "required": [ - "username", - "password", - "type" - ], - "properties": { - "password": { - "type": "string", - "description": "App password generated in Bitbucket security settings." - }, - "type": { - "type": "string", - "enum": [ - "app_password" - ] - }, - "username": { - "type": "string", - "description": "Bitbucket account username." - } - } - } - ], - "description": "Authentication input for a Bitbucket Cloud provider. Use `access_token` for\na Repository or Workspace Access Token (PAT), or `username` + `app_password`\nfor App Password (HTTP Basic) authentication." - }, - "BlobResponse": { - "type": "object", - "description": "Response after uploading a blob", - "required": [ - "url", - "pathname", - "contentType", - "size", - "uploadedAt" - ], - "properties": { - "contentType": { - "type": "string", - "description": "Content type of the blob", - "example": "image/png" - }, - "pathname": { - "type": "string", - "description": "Original pathname", - "example": "images/avatar-abc123.png" - }, - "size": { - "type": "integer", - "format": "int64", - "description": "Size in bytes", - "example": 12345 - }, - "uploadedAt": { - "type": "string", - "format": "date-time", - "description": "Upload timestamp", - "example": "2025-01-03T12:00:00Z" - }, - "url": { - "type": "string", - "description": "URL path to access the blob", - "example": "/api/blob/123/images/avatar-abc123.png" - } - } - }, - "BlobStatusResponse": { - "type": "object", - "description": "Response for Blob service status", - "required": [ - "enabled", - "healthy" - ], - "properties": { - "docker_image": { - "type": [ - "string", - "null" - ], - "description": "Docker image being used", - "example": "ghcr.io/rustfs/rustfs:0.5.0" - }, - "enabled": { - "type": "boolean", - "description": "Whether the Blob service is enabled", - "example": true - }, - "healthy": { - "type": "boolean", - "description": "Whether the service is healthy", - "example": true - }, - "version": { - "type": [ - "string", - "null" - ], - "description": "Current version (if running)", - "example": "0.5.0" - } - } - }, - "BranchInfo": { - "type": "object", - "required": [ - "name", - "commit_sha", - "protected" - ], - "properties": { - "commit_sha": { - "type": "string" - }, - "name": { - "type": "string" - }, - "protected": { - "type": "boolean" - } - } - }, - "BranchListResponse": { - "type": "object", - "required": [ - "branches" - ], - "properties": { - "branches": { - "type": "array", - "items": { - "$ref": "#/components/schemas/BranchInfo" - } - } - } - }, - "BrowserCount": { - "type": "object", - "required": [ - "browser", - "count", - "percentage" - ], - "properties": { - "browser": { - "type": "string" - }, - "count": { - "type": "integer", - "format": "int64" - }, - "percentage": { - "type": "number", - "format": "double" - } - } - }, - "BrowsersQuery": { - "type": "object", - "required": [ - "start_date", - "end_date", - "project_id" - ], - "properties": { - "end_date": { - "type": "string", - "format": "date-time" - }, - "environment_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "limit": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "project_id": { - "type": "integer", - "format": "int32" - }, - "start_date": { - "type": "string", - "format": "date-time" - } - } - }, - "BuildConfiguration": { - "type": "object", - "description": "Build configuration (for building images from source)", - "required": [ - "context", - "args" - ], - "properties": { - "args": { - "type": "object", - "description": "Build arguments", - "additionalProperties": { - "type": "string" - }, - "propertyNames": { - "type": "string" - } - }, - "context": { - "type": "string", - "description": "Build context (Dockerfile path or buildpack)" - }, - "dockerfile": { - "type": [ - "string", - "null" - ], - "description": "Dockerfile path (relative to context)" - }, - "target": { - "type": [ - "string", - "null" - ], - "description": "Target stage (for multi-stage builds)" - } - } - }, - "BuildLimitsSettings": { - "type": "object", - "description": "Control-plane build resource limits.\n\nCaps how many builds run concurrently AND how much CPU/memory each build\nis allowed to consume. A single global semaphore in the deployer crate\ngates every `DockerRuntime::build_image` call to `max_concurrent`. When\nthe semaphore is full, additional builds queue and wait \u2014 they do not\nfail. Per-build CPU/memory caps are forwarded to Docker via\n`BuildImageOptions { memory, cpuquota, cpuperiod }`.\n\n`cpu_limit_cores = 0.0` or `memory_limit_mb = 0` means \"no explicit cap\"\n\u2014 fall back to the legacy 50%-of-host heuristic for backwards\ncompatibility with operators who never visit the settings page.", - "properties": { - "cpu_limit_cores": { - "type": "number", - "format": "float", - "description": "CPU cores allowed per build (float, e.g. 2.0 = 2 cores, 0.5 = half\na core). 0 means \"use the legacy 50%-of-host default\".", - "default": 0.0, - "example": 2.0, - "minimum": 0 - }, - "max_concurrent": { - "type": "integer", - "format": "int32", - "description": "Maximum number of `docker build` operations allowed to run at the\nsame time on the control plane. Additional builds queue. Min 1.", - "default": 2, - "example": 2, - "minimum": 1 - }, - "memory_limit_mb": { - "type": "integer", - "format": "int32", - "description": "Memory allowed per build, in megabytes. 0 means \"use the legacy\n50%-of-host default\". Docker enforces this as a hard cap \u2014 builds\nthat exceed it OOM-kill.", - "default": 0, - "example": 2048, - "minimum": 0 - } - } - }, - "CancelBackupResponse": { - "type": "object", - "description": "Response body for cancel endpoints.", - "required": [ - "cancelled" - ], - "properties": { - "cancelled": { - "type": "integer", - "format": "int64", - "description": "Number of rows that were actually flipped to `failed`. `0` is a valid\nsuccess and means the backup was already terminal \u2014 the call is\nidempotent.", - "minimum": 0 - } - } - }, - "CertStatusResponse": { - "type": "object", - "description": "Current on-demand cert status for a single hostname (ADR-018 \u00a75). Backs\n`GET /domains/by-host/{hostname}/cert-status`.", - "required": [ - "hostname" - ], - "properties": { - "backoff_until": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "description": "On-demand negative-cache deadline (epoch millis), when in backoff." - }, - "hostname": { - "type": "string", - "description": "SNI hostname." - }, - "last_attempt": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/OnDemandCertAttemptResponse", - "description": "The most recent on-demand issuance attempt for this hostname, if any." - } - ] - }, - "status": { - "type": [ - "string", - "null" - ], - "description": "Current cert lifecycle status from the `domains` row, when one exists." - } - } - }, - "ChallengeConfig": { - "type": "object", - "description": "Challenge configuration (future feature)\nFor CAPTCHA, JS challenges, proof-of-work, etc.", - "required": [ - "challengeType", - "difficulty" - ], - "properties": { - "challengeType": { - "type": "string", - "description": "Challenge type: \"captcha\", \"js_challenge\", \"proof_of_work\"" - }, - "difficulty": { - "type": "integer", - "format": "int32", - "description": "Challenge difficulty level (1-10)", - "minimum": 0 - }, - "protectedPaths": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Paths that require challenges" - } - } - }, - "ChallengeError": { - "type": "object", - "required": [ - "type", - "detail", - "status" - ], - "properties": { - "detail": { - "type": "string", - "description": "Human-readable error description" - }, - "status": { - "type": "integer", - "format": "int32", - "description": "HTTP status code" - }, - "type": { - "type": "string", - "description": "Error type (e.g., \"urn:ietf:params:acme:error:unauthorized\")" - } - } - }, - "ChallengeValidationStatus": { - "type": "object", - "required": [ - "type", - "url", - "status", - "token" - ], - "properties": { - "error": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/ChallengeError", - "description": "Error details if validation failed" - } - ] - }, - "status": { - "type": "string", - "description": "Challenge status (e.g., \"pending\", \"valid\", \"invalid\")" - }, - "token": { - "type": "string", - "description": "Challenge token" - }, - "type": { - "type": "string", - "description": "Challenge type (e.g., \"dns-01\", \"http-01\")" - }, - "url": { - "type": "string", - "description": "Challenge validation URL" - }, - "validated": { - "type": [ - "string", - "null" - ], - "description": "When the challenge was validated (if successful)" - } - } - }, - "ChangePasswordRequest": { - "type": "object", - "required": [ - "current_password", - "new_password" - ], - "properties": { - "current_password": { - "type": "string", - "example": "current_password_value" - }, - "mfa_code": { - "type": [ - "string", - "null" - ], - "description": "TOTP code (or recovery code). Required iff the user has MFA enabled.", - "example": "123456" - }, - "new_password": { - "type": "string", - "example": "new_password_value" - }, - "revoke_other_sessions": { - "type": "boolean", - "description": "When true, every session OTHER than the one making this request is\nrevoked. Defaults to false; the UI surfaces this as a checkbox." - } - } - }, - "ChangeProjectSourceRequest": { - "type": "object", - "description": "Change a project's source type to a Git-less type (docker_image /\nstatic_files / manual). Switching TO `git` is done via the Git settings\nendpoint (which also supplies the repository + provider connection).", - "required": [ - "source_type" - ], - "properties": { - "source_type": { - "$ref": "#/components/schemas/SourceType" - } - } - }, - "ChatCompletionChoice": { - "type": "object", - "required": [ - "index", - "message" - ], - "properties": { - "finish_reason": { - "type": [ - "string", - "null" - ] - }, - "index": { - "type": "integer", - "format": "int32" - }, - "message": { - "$ref": "#/components/schemas/ChatMessage" - } - } - }, - "ChatCompletionRequest": { - "allOf": [ - { - "type": [ - "object", - "null" - ], - "description": "Tolerates extra SDK fields (stream_options, logprobs, etc.)", - "additionalProperties": {}, - "propertyNames": { - "type": "string" - } - }, - { - "type": "object", - "required": [ - "model", - "messages" - ], - "properties": { - "frequency_penalty": { - "type": [ - "number", - "null" - ], - "format": "double" - }, - "max_tokens": { - "type": [ - "integer", - "null" - ], - "format": "int64" - }, - "messages": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ChatMessage" - } - }, - "model": { - "type": "string" - }, - "n": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "presence_penalty": { - "type": [ - "number", - "null" - ], - "format": "double" - }, - "response_format": {}, - "seed": { - "type": [ - "integer", - "null" - ], - "format": "int64" - }, - "stop": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/StopSequence" - } - ] - }, - "stream": { - "type": "boolean" - }, - "temperature": { - "type": [ - "number", - "null" - ], - "format": "double" - }, - "tool_choice": {}, - "tools": { - "type": [ - "array", - "null" - ], - "items": {} - }, - "top_p": { - "type": [ - "number", - "null" - ], - "format": "double" - }, - "user": { - "type": [ - "string", - "null" - ] - } - } - } - ], - "description": "OpenAI-compatible chat completion request.\nUses `deny_unknown_fields = false` (serde default) so that SDK-specific\nfields like `stream_options`, `logprobs`, `top_logprobs`, `logit_bias`,\n`parallel_tool_calls`, etc. are silently accepted without breaking." - }, - "ChatCompletionResponse": { - "type": "object", - "required": [ - "id", - "object", - "created", - "model", - "choices" - ], - "properties": { - "choices": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ChatCompletionChoice" - } - }, - "created": { - "type": "integer", - "format": "int64" - }, - "id": { - "type": "string" - }, - "model": { - "type": "string" - }, - "object": { - "type": "string" - }, - "usage": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/UsageInfo" - } - ] - } - } - }, - "ChatMessage": { - "type": "object", - "required": [ - "role" - ], - "properties": { - "content": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/MessageContent" - } - ] - }, - "name": { - "type": [ - "string", - "null" - ] - }, - "role": { - "type": "string" - }, - "tool_call_id": { - "type": [ - "string", - "null" - ] - }, - "tool_calls": { - "type": [ - "array", - "null" - ], - "items": {} - } - } - }, - "ChatReadinessResponse": { - "type": "object", - "description": "What still has to be true before an AI chat can run a turn in this project.\n\nThe three gates are independent and fail for different reasons with different\nfixes, so they are reported separately rather than collapsed into one boolean:\nan instance admin configures a provider (instance-wide), while the two toggles\nare per-project. Collapsing them would leave the user with \"AI unavailable\"\nand no idea which of three places to go.", - "required": [ - "ai_configured", - "chat_enabled", - "write_actions_enabled" - ], - "properties": { - "ai_configured": { - "type": "boolean", - "description": "An AI provider is configured on this instance. Fixed in\nSettings \u2192 AI Providers; instance-wide, not per project." - }, - "chat_enabled": { - "type": "boolean", - "description": "The per-project read-only chat toggle is on (the default)." - }, - "write_actions_enabled": { - "type": "boolean", - "description": "The per-project write-actions opt-in is on. Required for any flow where\nthe assistant *proposes* changes; irrelevant for read-only questions." - } - } - }, - "ChildBackupEntryResponse": { - "type": "object", - "description": "A single child backup entry in the `GET /backups/{id}/children` response.\n\nEach entry corresponds to one `external_service_backups` row joined with\n`external_services`, providing service metadata without a second request.", - "required": [ - "id", - "service_id", - "service_name", - "service_type", - "state", - "backup_type", - "started_at", - "s3_location", - "compression_type" - ], - "properties": { - "backup_type": { - "type": "string", - "description": "Backup variant (e.g. \"full\", \"incremental\")." - }, - "compression_type": { - "type": "string", - "description": "Compression algorithm used (e.g. \"gzip\", \"lz4\")." - }, - "error_message": { - "type": [ - "string", - "null" - ], - "description": "Engine-reported error message when `state = \"failed\"`." - }, - "finished_at": { - "type": [ - "string", - "null" - ], - "description": "When the child backup finished, if known.", - "example": "2025-01-15T14:35:00.456Z" - }, - "id": { - "type": "integer", - "format": "int32", - "description": "Row ID from `external_service_backups`." - }, - "s3_location": { - "type": "string", - "description": "Object key or `s3://` URL where the backup data lives." - }, - "service_id": { - "type": "integer", - "format": "int32", - "description": "FK to `external_services.id`." - }, - "service_name": { - "type": "string", - "description": "Human-readable name of the external service (e.g. \"redis-prod\")." - }, - "service_type": { - "type": "string", - "description": "Service type string (e.g. \"postgres\", \"redis\", \"mongodb\", \"s3\").", - "example": "postgres" - }, - "size_bytes": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "description": "Size of the child backup in bytes, if available." - }, - "started_at": { - "type": "string", - "description": "When the child backup started (RFC 3339).", - "example": "2025-01-15T14:30:00.123Z" - }, - "state": { - "type": "string", - "description": "Current state: \"pending\" | \"running\" | \"completed\" | \"failed\"." - } - } - }, - "ChildBackupListResponse": { - "type": "object", - "description": "Response body for `GET /backups/{id}/children`.\n\nReturns an empty `children` list (not 404) when the parent backup has no\nchild records (e.g. control-plane backups).", - "required": [ - "children" - ], - "properties": { - "children": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ChildBackupEntryResponse" - }, - "description": "Zero or more child backup entries ordered by `external_service_backups.id` ASC." - } - } - }, - "CleanupExpiredBackupsRequest": { - "type": "object", - "properties": { - "expected_backup_ids": { - "type": [ - "array", - "null" - ], - "items": { - "type": "string" - }, - "description": "Exact candidates returned by the dry run. Execution fails if the\nretention selection has changed since preview." - } - } - }, - "CliDeviceApproveRequest": { - "type": "object", - "required": [ - "user_code" - ], - "properties": { - "user_code": { - "type": "string" - } - } - }, - "CliDeviceApproveResponse": { - "type": "object", - "required": [ - "user_code", - "status" - ], - "properties": { - "status": { - "type": "string" - }, - "user_code": { - "type": "string" - } - } - }, - "CliDeviceLookupResponse": { - "type": "object", - "required": [ - "user_code", - "status", - "expires_at" - ], - "properties": { - "client_name": { - "type": [ - "string", - "null" - ] - }, - "expires_at": { - "type": "string", - "format": "date-time" - }, - "requested_ip": { - "type": [ - "string", - "null" - ] - }, - "status": { - "type": "string", - "description": "`pending` | `approved` | `denied` | `expired`." - }, - "user_code": { - "type": "string" - } - } - }, - "CliDevicePollRequest": { - "type": "object", - "required": [ - "device_code" - ], - "properties": { - "device_code": { - "type": "string" - } - } - }, - "CliDevicePollResponse": { - "oneOf": [ - { - "type": "object", - "description": "Still waiting on the user to approve in the browser.", - "required": [ - "status" - ], - "properties": { - "status": { - "type": "string", - "enum": [ - "authorization_pending" - ] - } - } - }, - { - "type": "object", - "description": "CLI is polling faster than the server-suggested interval.", - "required": [ - "status" - ], - "properties": { - "status": { - "type": "string", - "enum": [ - "slow_down" - ] - } - } - }, - { - "type": "object", - "description": "User denied the request in the browser.", - "required": [ - "status" - ], - "properties": { - "status": { - "type": "string", - "enum": [ - "access_denied" - ] - } - } - }, - { - "type": "object", - "description": "The session has expired without approval.", - "required": [ - "status" - ], - "properties": { - "status": { - "type": "string", - "enum": [ - "expired_token" - ] - } - } - }, - { - "type": "object", - "description": "The session was approved; this is the only response that carries\nthe API key. The key is returned exactly once and then cleared\nfrom the session row.", - "required": [ - "user_id", - "email", - "role", - "api_key", - "key_prefix", - "status" - ], - "properties": { - "api_key": { - "type": "string" - }, - "email": { - "type": "string" - }, - "expires_at": { - "type": [ - "string", - "null" - ], - "format": "date-time" - }, - "key_prefix": { - "type": "string" - }, - "role": { - "type": "string" - }, - "status": { - "type": "string", - "enum": [ - "approved" - ] - }, - "user_id": { - "type": "integer", - "format": "int32" - } - } - } - ] - }, - "CliDeviceStartRequest": { - "type": "object", - "properties": { - "client_name": { - "type": [ - "string", - "null" - ], - "description": "Friendly hostname / client identifier shown in the browser approval\nscreen. Sanitized before display.", - "example": "dviejo-mac.local" - } - } - }, - "CliDeviceStartResponse": { - "type": "object", - "required": [ - "device_code", - "user_code", - "verification_uri", - "verification_uri_complete", - "expires_in", - "interval" - ], - "properties": { - "device_code": { - "type": "string", - "description": "Opaque secret the CLI polls with. Never display to a human." - }, - "expires_in": { - "type": "integer", - "format": "int64", - "description": "Seconds until the device_code expires." - }, - "interval": { - "type": "integer", - "format": "int64", - "description": "Suggested polling interval, in seconds." - }, - "user_code": { - "type": "string", - "description": "Short human-readable code the user types into the browser.", - "example": "ABCD-1234" - }, - "verification_uri": { - "type": "string", - "description": "Base verification URL \u2014 the CLI may display this when the\npre-filled URL is too long to be useful.", - "example": "https://temps.example.com/cli-login" - }, - "verification_uri_complete": { - "type": "string", - "description": "`verification_uri` with `user_code` pre-filled. Open this directly.", - "example": "https://temps.example.com/cli-login/ABCD-1234" - } - } - }, - "CliLoginRequest": { - "type": "object", - "required": [ - "username", - "password" - ], - "properties": { - "password": { - "type": "string" - }, - "username": { - "type": "string" - } - } - }, - "CloudProvider": { - "type": "string", - "description": "Cloud provider detected from node metadata", - "enum": [ - "aws", - "gcp", - "azure", - "hetzner", - "digitalocean", - "other" - ] - }, - "CloudflareConfig": { - "type": "object", - "description": "Configuration for a Cloudflare Email Sending notification provider.\n\nNotifications are delivered through Cloudflare's transactional Email Sending\nAPI. Only the account, token, sender and recipients are configured here \u2014\nsubject and body are derived from each notification.", - "required": [ - "account_id", - "api_token", - "from_address", - "to_addresses" - ], - "properties": { - "account_id": { - "type": "string", - "description": "Cloudflare account id that owns the Email Sending configuration.", - "example": "023e105f4ecef8ad9ca31a8372d0c353" - }, - "api_token": { - "type": "string", - "description": "Cloudflare API token with the Email Sending permission. Encrypted at\nrest and masked in normal API responses." - }, - "from_address": { - "type": "string", - "description": "Verified sender address (must belong to a domain enabled for Cloudflare\nEmail Sending).", - "example": "welcome@infracf.example.com" - }, - "from_name": { - "type": [ - "string", - "null" - ], - "description": "Optional human-friendly sender name shown in the recipient's inbox." - }, - "to_addresses": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Recipients that should receive the notification." - } - } - }, - "ClusterCapacity": { - "type": "object", - "description": "Total cluster capacity (sum of node allocatable resources)", - "required": [ - "node_count", - "cpu_millis", - "memory_mb" - ], - "properties": { - "cpu_millis": { - "type": "integer", - "format": "int64", - "description": "Total allocatable CPU in millicores" - }, - "memory_mb": { - "type": "integer", - "format": "int64", - "description": "Total allocatable memory in MB" - }, - "node_count": { - "type": "integer", - "description": "Number of nodes", - "minimum": 0 - } - } - }, - "ClusterDnsSettings": { - "type": "object", - "description": "Cluster-DNS resolver settings (ADR-024, experimental beta).\n\nWhen `enabled`, the Temps control plane starts a Hickory DNS resolver and\ninjects it as the first nameserver into every deployed container via\n`HostConfig.Dns` \u2014 giving containers the ability to resolve `*.temps.local`\nFQDNs for service-to-service communication. Worker nodes pick this flag up\nfrom the `/api/internal/nodes/{id}/network/peers` wire response and gate\ntheir own per-node resolver the same way.\n\n**Default: `false` (disabled).**\n\nWhy disabled by default: a production incident showed that when the injected\nHickory resolver was slow or transiently unresponsive for a non-`*.temps.local`\n(external) hostname, glibc's resolver cycled through all three nameservers\n(`172.20.0.1`, `1.1.1.1`, `8.8.8.8`) at ~5 s timeout \u00d7 2 attempts each,\ncausing 22\u201327 s delays for outbound TCP connections. Disabling the injection\nrestores Docker's embedded DNS as the sole resolver, eliminating that failure\nmode. Operators running single/multi-node installs that depend on\n`*.temps.local` resolution must explicitly opt in by setting `enabled: true`.\n\n`bool` defaults to `false` in Rust and JSON (`#[serde(default)]`), so the\nsafe-off behaviour is automatic for new installs and legacy settings rows.", - "properties": { - "enabled": { - "type": "boolean", - "description": "Master switch. When `false` (default), no custom DNS is injected into\ncontainers \u2014 they use Docker's embedded DNS which forwards to the host's\nown `resolv.conf`. When `true`, the control-plane Hickory resolver is\nstarted and its bridge IP is injected as the first nameserver so\n`*.temps.local` FQDNs resolve inside containers.", - "default": false, - "example": false - } - } - }, - "ClusterHealthReportResponse": { - "type": "object", - "description": "Response body for `GET /external-services/{id}/cluster-health`.", - "required": [ - "checked_at", - "monitor_response_ms", - "members" - ], - "properties": { - "checked_at": { - "type": "string", - "description": "ISO-8601 wall-clock when the report was generated.", - "example": "2025-10-12T12:15:47.609192Z" - }, - "members": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ClusterMemberHealthResponse" - } - }, - "monitor_error": { - "type": [ - "string", - "null" - ], - "description": "Set when the monitor itself was unreachable. UI shows a banner." - }, - "monitor_response_ms": { - "type": "integer", - "format": "int64", - "description": "Round-trip to query the monitor (ms)." - } - } - }, - "ClusterMemberHealthResponse": { - "type": "object", - "description": "One row in the cluster Members table \u2014 see `GET /external-services/{id}/cluster-health`.", - "required": [ - "nodename", - "nodehost", - "nodeport", - "reported_state", - "goal_state", - "health", - "seconds_since_report", - "candidate_priority", - "replication_quorum" - ], - "properties": { - "candidate_priority": { - "type": "integer", - "format": "int32" - }, - "goal_state": { - "type": "string", - "description": "What the monitor *wants* the node to be. Differs from\n`reported_state` mid-transition (failover, demotion, etc.)." - }, - "health": { - "type": "integer", - "format": "int32", - "description": "pg_auto_failover liveness signal: `1` healthy, `0` unknown\n(no recent report), `-1` unhealthy." - }, - "nodehost": { - "type": "string" - }, - "nodename": { - "type": "string" - }, - "nodeport": { - "type": "integer", - "format": "int32" - }, - "replay_lag_ms": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "description": "`replay_lag` from `pg_stat_replication`, in milliseconds." - }, - "replication_quorum": { - "type": "boolean" - }, - "reported_state": { - "type": "string", - "description": "What the node *last told the monitor* it was. Stale during outages." - }, - "seconds_since_report": { - "type": "integer", - "format": "int64", - "description": "Wall-clock seconds since the node last reported in." - }, - "sync_state": { - "type": [ - "string", - "null" - ], - "description": "`sync` / `quorum` / `async` for secondaries; `null` for the primary." - } - } - }, - "ClusterMemberRequest": { - "type": "object", - "description": "Request spec for a single cluster member.", - "required": [ - "role" - ], - "properties": { - "node_id": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Target worker node ID. Omit or null to run on the control plane." - }, - "role": { - "type": "string", - "description": "Service-type-specific role (e.g., \"monitor\", \"primary\", \"replica\")", - "example": "primary" - } - } - }, - "CmdBody": { - "type": "object", - "required": [ - "command" - ], - "properties": { - "args": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Arguments to pass to the binary. Defaults to empty." - }, - "command": { - "type": "string", - "description": "Binary name (argv[0]) \u2014 e.g. `\"ls\"`, `\"node\"`. The SDK sends this\nseparately from `args`." - }, - "cwd": { - "type": [ - "string", - "null" - ], - "description": "Working directory override." - }, - "env": { - "type": "object", - "description": "Extra env vars.", - "additionalProperties": { - "type": "string" - }, - "propertyNames": { - "type": "string" - } - }, - "sudo": { - "type": "boolean", - "description": "When true, the SDK runs the command privileged. We ignore it today\n\u2014 the underlying provider always runs as the sandbox's own user." - }, - "wait": { - "type": "boolean", - "description": "When true, the response is an `application/x-ndjson` stream where\nthe first line is the running-command envelope and the second line\nis the finished-command envelope with `exitCode`." - } - } - }, - "CmdInner": { - "type": "object", - "description": "Inner `command` object \u2014 matches the SDK's zod validator exactly.\n`exitCode` is `null` until the command terminates; `startedAt` is Unix\nepoch milliseconds.", - "required": [ - "id", - "name", - "args", - "cwd", - "sandboxId", - "startedAt" - ], - "properties": { - "args": { - "type": "array", - "items": { - "type": "string" - } - }, - "cwd": { - "type": "string" - }, - "exitCode": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "sandboxId": { - "type": "string" - }, - "startedAt": { - "type": "integer", - "format": "int64" - } - } - }, - "CmdKillBody": { - "type": "object", - "description": "SDK-shaped kill body. The SDK sends `{signal: AbortSignal}` but only\nuses the signal for HTTP request abortion client-side; there's no\nsignal name on the wire.", - "properties": { - "force": { - "type": "boolean", - "description": "Optional: when true, SIGKILL instead of SIGTERM." - } - } - }, - "CmdResponse": { - "type": "object", - "description": "`@vercel/sandbox` envelope: `{ command: {...} }`.", - "required": [ - "command" - ], - "properties": { - "command": { - "$ref": "#/components/schemas/CmdInner" - } - } - }, - "CommitExistsResponse": { - "type": "object", - "required": [ - "exists" - ], - "properties": { - "commit": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/CommitInfo", - "description": "Commit metadata when the requested SHA exists." - } - ] - }, - "commit_sha": { - "type": [ - "string", - "null" - ] - }, - "exists": { - "type": "boolean" - } - } - }, - "CommitInfo": { - "type": "object", - "required": [ - "sha", - "message", - "author", - "author_email", - "date" - ], - "properties": { - "author": { - "type": "string", - "description": "Author name" - }, - "author_email": { - "type": "string", - "description": "Author email" - }, - "date": { - "type": "string", - "format": "date-time", - "description": "Commit date in ISO 8601 format", - "example": "2025-10-12T12:15:47.609192Z" - }, - "message": { - "type": "string", - "description": "Commit message" - }, - "sha": { - "type": "string", - "description": "Commit SHA hash" - } - } - }, - "CommitListResponse": { - "type": "object", - "required": [ - "commits" - ], - "properties": { - "commits": { - "type": "array", - "items": { - "$ref": "#/components/schemas/CommitInfo" - } - } - } - }, - "Comparator": { - "type": "string", - "description": "Comparator for static/forecast threshold detectors. Serializes to the\nkeyword forms `gt|gte|lt|lte` (NOT the SQL operators used by\n`temps-monitoring::compare`).", - "enum": [ - "gt", - "gte", - "lt", - "lte" - ] - }, - "ComposePublicPort": { - "type": "object", - "description": "A port that should be exposed publicly through the proxy for a compose service.", - "required": [ - "service", - "port" - ], - "properties": { - "port": { - "type": "integer", - "format": "int32", - "description": "Container port to expose (e.g. 8123)", - "minimum": 0 - }, - "service": { - "type": "string", - "description": "Compose service name (e.g. \"web\", \"clickhouse\")" - } - } - }, - "ConnectionListQuery": { - "type": "object", - "properties": { - "direction": { - "type": [ - "string", - "null" - ] - }, - "page": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "minimum": 0 - }, - "per_page": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "minimum": 0 - }, - "sort": { - "type": [ - "string", - "null" - ] - } - } - }, - "ConnectionListResponse": { - "type": "object", - "required": [ - "connections", - "total_count", - "page", - "per_page" - ], - "properties": { - "connections": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ConnectionResponse" - } - }, - "page": { - "type": "integer", - "format": "int64", - "minimum": 0 - }, - "per_page": { - "type": "integer", - "format": "int64", - "minimum": 0 - }, - "total_count": { - "type": "integer", - "minimum": 0 - } - } - }, - "ConnectionResponse": { - "type": "object", - "required": [ - "id", - "provider_id", - "account_name", - "account_type", - "is_active", - "is_expired", - "syncing", - "synced_repository_count", - "health_status", - "consecutive_health_failures", - "created_at", - "updated_at" - ], - "properties": { - "account_name": { - "type": "string" - }, - "account_type": { - "type": "string" - }, - "consecutive_health_failures": { - "type": "integer", - "format": "int32" - }, - "created_at": { - "type": "string", - "format": "date-time" - }, - "health_message": { - "type": [ - "string", - "null" - ], - "description": "Human-readable reason when health_status is \"unhealthy\"; null otherwise." - }, - "health_status": { - "type": "string", - "description": "Current health status: \"healthy\", \"unhealthy\", or \"unknown\"." - }, - "id": { - "type": "integer", - "format": "int32" - }, - "installation_id": { - "type": [ - "string", - "null" - ] - }, - "is_active": { - "type": "boolean" - }, - "is_expired": { - "type": "boolean" - }, - "last_health_check_at": { - "type": [ - "string", - "null" - ], - "format": "date-time" - }, - "last_synced_at": { - "type": [ - "string", - "null" - ], - "format": "date-time" - }, - "provider_id": { - "type": "integer", - "format": "int32" - }, - "synced_repository_count": { - "type": "integer", - "format": "int32", - "description": "Running count of repositories persisted by the current (or most\nrecent) sync. Resets to 0 when a new sync begins; useful for showing\nlive progress on large syncs." - }, - "syncing": { - "type": "boolean" - }, - "updated_at": { - "type": "string", - "format": "date-time" - }, - "user_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - } - } - }, - "ConnectionTestResult": { - "type": "object", - "description": "Connection test result", - "required": [ - "success", - "message" - ], - "properties": { - "message": { - "type": "string" - }, - "success": { - "type": "boolean" - } - } - }, - "ConsoleEventPayload": { - "type": "object", - "description": "Payload for server-side event ingestion via the console API.\n\nThe app backend reads the encrypted `_temps_visitor_id` and `_temps_sid`\ncookie values from the user's request and forwards them here.\nTemps decrypts them server-side to resolve visitor/session identity.", - "required": [ - "event_name", - "environment_id", - "deployment_id" - ], - "properties": { - "deployment_id": { - "type": "integer", - "format": "int32", - "description": "Deployment ID to attribute the event to" - }, - "environment_id": { - "type": "integer", - "format": "int32", - "description": "Environment ID to attribute the event to" - }, - "event_data": { - "description": "Arbitrary JSON event data" - }, - "event_name": { - "type": "string", - "description": "Event name (e.g. \"purchase\", \"signup\", custom event names)" - }, - "request_path": { - "type": "string", - "description": "Page path context (defaults to \"/\")" - }, - "request_query": { - "type": "string", - "description": "Query string context" - }, - "session_id": { - "type": [ - "string", - "null" - ], - "description": "Encrypted `_temps_sid` cookie value from the user's browser" - }, - "visitor_id": { - "type": [ - "string", - "null" - ], - "description": "Encrypted `_temps_visitor_id` cookie value from the user's browser" - } - } - }, - "ContainerActionResponse": { - "type": "object", - "description": "Response indicating success of container state change", - "required": [ - "container_id", - "container_name", - "action", - "status", - "message" - ], - "properties": { - "action": { - "type": "string" - }, - "container_id": { - "type": "string" - }, - "container_name": { - "type": "string" - }, - "message": { - "type": "string" - }, - "status": { - "type": "string" - } - } - }, - "ContainerDetailResponse": { - "type": "object", - "description": "Detailed container information with environment variables and metrics", - "required": [ - "id", - "container_id", - "container_name", - "image_name", - "status", - "deployment_id", - "created_at", - "deployed_at", - "container_port", - "environment_variables" - ], - "properties": { - "container_id": { - "type": "string" - }, - "container_name": { - "type": "string" - }, - "container_port": { - "type": "integer", - "format": "int32", - "description": "Port inside the container" - }, - "cpu_limit_cores": { - "type": [ - "number", - "null" - ], - "format": "double", - "description": "CPU limit in whole cores (e.g. 1.0). None when no limit is configured." - }, - "created_at": { - "type": "string", - "example": "2025-10-12T12:15:47.609192Z" - }, - "deployed_at": { - "type": "string", - "example": "2025-10-12T12:15:47.609192Z" - }, - "deployment_id": { - "type": "integer", - "format": "int32" - }, - "environment_variables": { - "type": "array", - "items": { - "$ref": "#/components/schemas/EnvVarResponse" - }, - "description": "Environment variables (sensitive values masked)" - }, - "error_message": { - "type": [ - "string", - "null" - ], - "description": "Free-form error string from Docker's container state on exit." - }, - "exit_code": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Process exit code reported by Docker. None while still running." - }, - "exit_reason": { - "type": [ - "string", - "null" - ], - "description": "Human-readable reason the container exited." - }, - "finished_at": { - "type": [ - "string", - "null" - ], - "description": "When the container exited (Docker's FinishedAt). None while running.", - "example": "2025-10-12T12:16:47.609192Z" - }, - "host_port": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Port on the host machine" - }, - "id": { - "type": "integer", - "format": "int32" - }, - "image_name": { - "type": "string" - }, - "oom_killed": { - "type": [ - "boolean", - "null" - ], - "description": "True when Docker's OOM killer terminated the container." - }, - "ready_at": { - "type": [ - "string", - "null" - ], - "example": "2025-10-12T12:16:47.609192Z" - }, - "resource_limits": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/ResourceLimitsResponse", - "description": "Resource limits" - } - ] - }, - "restart_count": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "description": "Container restart count from Docker" - }, - "service_name": { - "type": [ - "string", - "null" - ], - "description": "Compose service name (e.g. \"web\", \"redis\"). None for single-container deployments." - }, - "service_url": { - "type": [ - "string", - "null" - ], - "description": "Per-service URL for compose deployments" - }, - "started_at": { - "type": [ - "string", - "null" - ], - "description": "When the container's main process most recently started.", - "example": "2025-10-12T12:15:50.000000Z" - }, - "status": { - "type": "string" - } - } - }, - "ContainerEnvironmentVariableValueResponse": { - "type": "object", - "required": [ - "value" - ], - "properties": { - "value": { - "type": "string" - } - } - }, - "ContainerInfoResponse": { - "type": "object", - "required": [ - "container_id", - "container_name", - "image_name", - "status", - "created_at" - ], - "properties": { - "container_id": { - "type": "string" - }, - "container_name": { - "type": "string" - }, - "cpu_limit_cores": { - "type": [ - "number", - "null" - ], - "format": "double", - "description": "CPU limit in whole cores (e.g. 1.0). None when no limit is configured." - }, - "created_at": { - "type": "string", - "example": "2025-10-12T12:15:47.609192Z" - }, - "error_message": { - "type": [ - "string", - "null" - ], - "description": "Free-form error string from Docker's container state on exit." - }, - "exit_code": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Process exit code reported by Docker. None while still running." - }, - "exit_reason": { - "type": [ - "string", - "null" - ], - "description": "Human-readable reason the container exited (e.g. \"OOMKilled\",\n\"Killed by SIGKILL (exit code 137)\", \"Exit code 1\"). None while running." - }, - "finished_at": { - "type": [ - "string", - "null" - ], - "description": "When the container exited (Docker's FinishedAt). None while running.", - "example": "2025-10-12T12:16:47.609192Z" - }, - "image_name": { - "type": "string" - }, - "node_name": { - "type": [ - "string", - "null" - ], - "description": "Node name where this container is running. None for local (single-node) deployments." - }, - "oom_killed": { - "type": [ - "boolean", - "null" - ], - "description": "True when Docker's OOM killer terminated the container." - }, - "restart_count": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "description": "Container restart count from Docker. The UI shows a chip when this is\n> 0 so a crash loop is visible without opening detail." - }, - "service_name": { - "type": [ - "string", - "null" - ], - "description": "Compose service name (e.g. \"web\", \"redis\"). None for single-container deployments." - }, - "service_url": { - "type": [ - "string", - "null" - ], - "description": "Per-service URL for compose deployments (e.g. \"https://web-myapp.localho.st\")" - }, - "started_at": { - "type": [ - "string", - "null" - ], - "description": "When the container's main process most recently started. The UI uses\nthis for the uptime label so the count resets when a container is\nrestarted in place. None for containers that never started.", - "example": "2025-10-12T12:15:50.000000Z" - }, - "status": { - "type": "string" - } - } - }, - "ContainerInventoryItem": { - "type": "object", - "description": "A container reported by the agent during heartbeat reconciliation.", - "required": [ - "container_id", - "container_name" - ], - "properties": { - "container_id": { - "type": "string", - "description": "Docker container ID" - }, - "container_name": { - "type": "string", - "description": "Docker container name" - } - } - }, - "ContainerListResponse": { - "type": "object", - "required": [ - "containers", - "total" - ], - "properties": { - "containers": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ContainerInfoResponse" - } - }, - "total": { - "type": "integer", - "minimum": 0 - } - } - }, - "ContainerLogSettings": { - "type": "object", - "description": "Docker container log rotation settings\nControls the `--log-opt max-size` and `--log-opt max-file` for containers", - "properties": { - "max_file": { - "type": "integer", - "format": "int32", - "description": "Maximum number of rotated log files to keep (e.g., 3 means up to 3 x max_size total)", - "default": 3, - "example": 3, - "minimum": 0 - }, - "max_size": { - "type": "string", - "description": "Maximum size of each log file (e.g., \"50m\", \"100m\", \"1g\")\nDocker default is unlimited; we default to \"50m\" to prevent disk exhaustion", - "default": "50m", - "example": "50m" - }, - "service_max_file": { - "type": "integer", - "format": "int32", - "description": "Maximum rotated log files for external service containers", - "default": 3, - "example": 3, - "minimum": 0 - }, - "service_max_size": { - "type": "string", - "description": "Maximum size for external service container logs (postgres, redis, etc.)\nDefaults to \"20m\" since services are typically less verbose than app containers", - "default": "20m", - "example": "20m" - } - } - }, - "ContainerLogsQuery": { - "type": "object", - "properties": { - "container_name": { - "type": [ - "string", - "null" - ], - "description": "Optional container name to get logs from (if deployment has multiple containers)" - }, - "end_date": { - "type": [ - "integer", - "null" - ], - "format": "int64" - }, - "follow": { - "type": "boolean", - "description": "Follow log output in real-time (default: true for backward compatibility)" - }, - "start_date": { - "type": [ - "integer", - "null" - ], - "format": "int64" - }, - "tail": { - "type": [ - "string", - "null" - ] - }, - "timestamps": { - "type": "boolean", - "description": "Include timestamps in log output (default: false)" - } - } - }, - "ContainerMetricHistoryPoint": { - "type": "object", - "description": "One bucketed data point of a container resource metric time series.", - "required": [ - "time", - "value" - ], - "properties": { - "time": { - "type": "string", - "description": "Bucket timestamp (ISO 8601 with `Z` suffix).", - "example": "2025-10-12T12:15:00+00:00" - }, - "value": { - "type": "number", - "format": "double", - "description": "Averaged metric value for the bucket." - } - } - }, - "ContainerMetricsHistoryQuery": { - "type": "object", - "description": "Query parameters for the container metrics history endpoint.", - "required": [ - "metric" - ], - "properties": { - "metric": { - "type": "string", - "description": "Dotted metric name, e.g. `container.cpu_percent` or\n`container.memory_used_bytes`." - }, - "range": { - "type": "string", - "description": "Time window: `1h`, `6h`, `24h`, or `7d` (defaults to `1h`)." - } - } - }, - "ContainerMetricsResponse": { - "type": "object", - "description": "Container resource metrics (CPU, memory usage)", - "required": [ - "container_id", - "container_name", - "cpu_percent", - "memory_bytes", - "network_rx_bytes", - "network_tx_bytes", - "timestamp" - ], - "properties": { - "container_id": { - "type": "string" - }, - "container_name": { - "type": "string" - }, - "cpu_limit_cores": { - "type": [ - "number", - "null" - ], - "format": "double", - "description": "CPU limit in whole cores (e.g. 1.0). None = no limit." - }, - "cpu_percent": { - "type": "number", - "format": "double", - "description": "CPU usage as a multi-core percentage (Docker convention: 200 = 2 cores\nfully pinned). Divide by 100 to get cores used." - }, - "memory_bytes": { - "type": "integer", - "format": "int64", - "description": "Memory usage in bytes", - "minimum": 0 - }, - "memory_limit_bytes": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "description": "Memory limit in bytes (if set)", - "minimum": 0 - }, - "memory_percent": { - "type": [ - "number", - "null" - ], - "format": "double", - "description": "Memory usage percentage (0-100) if limit is set" - }, - "network_rx_bytes": { - "type": "integer", - "format": "int64", - "description": "Network bytes received", - "minimum": 0 - }, - "network_tx_bytes": { - "type": "integer", - "format": "int64", - "description": "Network bytes transmitted", - "minimum": 0 - }, - "timestamp": { - "type": "string", - "description": "Timestamp of metrics collection", - "example": "2025-10-12T12:15:47.609192Z" - } - } - }, - "ContainerResponse": { - "type": "object", - "required": [ - "name", - "container_type", - "can_contain_containers", - "can_contain_entities", - "metadata" - ], - "properties": { - "can_contain_containers": { - "type": "boolean", - "description": "Can this container hold other containers?", - "example": true - }, - "can_contain_entities": { - "type": "boolean", - "description": "Can this container hold entities (tables, collections, etc.)?", - "example": false - }, - "child_container_type": { - "type": [ - "string", - "null" - ], - "description": "Type of child containers (if can_contain_containers is true)", - "example": "schema" - }, - "container_type": { - "type": "string", - "description": "Container type (database, schema, keyspace, bucket, etc.)", - "example": "database" - }, - "entity_count_hint": { - "type": [ - "string", - "null" - ], - "description": "Hint for UI on expected entity count (small = sidebar, large = pagination)", - "example": "large" - }, - "entity_type_label": { - "type": [ - "string", - "null" - ], - "description": "Label for entity type (if can_contain_entities is true)", - "example": "table" - }, - "metadata": { - "description": "Additional metadata" - }, - "name": { - "type": "string", - "description": "Container name", - "example": "mydb" - } - } - }, - "ContainerRuntimeInfo": { - "type": "object", - "description": "Snapshot of a container's lifecycle state from `docker inspect`.\n`restart_count` and `oom_killed` are the load-bearing fields when\ndiagnosing crash loops \u2014 the kernel OOM killer never reaches the\napplication's logs, so seeing `oom_killed=true` is the only signal\nthat a memory limit was the cause.", - "required": [ - "role", - "container_name", - "resource_limits" - ], - "properties": { - "container_id": { - "type": [ - "string", - "null" - ], - "description": "Container Docker id, when present. None = container does not exist\n(was never created or was removed externally)." - }, - "container_name": { - "type": "string", - "description": "Stable name of the Docker container (e.g. `postgres-mydb`)." - }, - "exit_code": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "description": "Last container exit code, when known. Non-zero = unclean stop." - }, - "finished_at": { - "type": [ - "string", - "null" - ], - "description": "ISO-8601 timestamp of the most recent termination, when known." - }, - "image": { - "type": [ - "string", - "null" - ], - "description": "Currently-effective Docker image (e.g. `gotempsh/postgres-walg:18-bookworm`)." - }, - "oom_killed": { - "type": [ - "boolean", - "null" - ], - "description": "True when the container's last termination was caused by the\nkernel OOM killer. Set if the user enabled hard memory limits\nand the working set exceeded them." - }, - "resource_limits": { - "$ref": "#/components/schemas/ServiceResourceLimits", - "description": "Currently-applied resource limits read off the container's\n`HostConfig`. Compare this against the user-configured limits to\ndetect drift (an old container that never picked up new caps)." - }, - "restart_count": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "description": "Total restarts since the container was created. Useful for\ndetecting crash loops \u2014 a steady stream means something is killing\nthe container repeatedly (frequently OOM)." - }, - "role": { - "type": "string", - "description": "`service_members.role` for cluster members; \"standalone\" otherwise." - }, - "started_at": { - "type": [ - "string", - "null" - ], - "description": "ISO-8601 timestamp of when the container last started. None when\nit has never started (i.e. created but never run)." - }, - "status": { - "type": [ - "string", - "null" - ], - "description": "Bollard container state (\"running\", \"exited\", \"dead\", etc.). None\nwhen the container does not exist." - } - } - }, - "ContainerStatsSample": { - "type": "object", - "description": "Live resource usage sample for a single container.\n\n`cpu_percent` is computed by Docker's standard formula:\n ((cpu_delta / system_delta) * online_cpus) * 100\n`memory_percent` is `(memory_usage / memory_limit) * 100` \u2014 when no\nmemory limit is set the limit reported by Docker is the host's total\nRAM, so a 5% reading means \"5% of host RAM\", not \"5% of allocated\".", - "required": [ - "role", - "container_name" - ], - "properties": { - "container_name": { - "type": "string" - }, - "cpu_percent": { - "type": [ - "number", - "null" - ], - "format": "double", - "description": "CPU usage as a percentage. `None` when the container is not running\n(Docker returns no usable counters)." - }, - "memory_limit_bytes": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "description": "Memory limit in bytes (host RAM if no limit set).", - "minimum": 0 - }, - "memory_percent": { - "type": [ - "number", - "null" - ], - "format": "double", - "description": "Memory usage as a percentage of `memory_limit_bytes`." - }, - "memory_usage_bytes": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "description": "Resident memory usage in bytes.", - "minimum": 0 - }, - "online_cpus": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Number of cores Docker observed at sample time. Used by the UI\nto label \"x/y cores\" instead of just a percent.", - "minimum": 0 - }, - "role": { - "type": "string" - } - } - }, - "ContentPart": { - "type": "object", - "required": [ - "type" - ], - "properties": { - "image_url": {}, - "text": { - "type": [ - "string", - "null" - ] - }, - "type": { - "type": "string" - } - } - }, - "ContextLine": { - "type": "object", - "description": "A line in context response", - "required": [ - "timestamp", - "level", - "message", - "line_offset", - "is_match" - ], - "properties": { - "fields": {}, - "is_match": { - "type": "boolean", - "description": "Whether this line matched the original search" - }, - "level": { - "$ref": "#/components/schemas/LogLevel" - }, - "line_offset": { - "type": "integer", - "format": "int32" - }, - "message": { - "type": "string" - }, - "timestamp": { - "type": "string" - } - } - }, - "ContextLogsRequest": { - "type": "object", - "required": [ - "chunk_id", - "line_offset" - ], - "properties": { - "chunk_id": { - "type": "string" - }, - "line_offset": { - "type": "integer", - "format": "int32" - }, - "lines": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Number of context lines before and after (default: 25)", - "minimum": 0 - } - } - }, - "ContextLogsResponse": { - "type": "object", - "required": [ - "lines", - "target_index" - ], - "properties": { - "lines": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ContextLine" - } - }, - "target_index": { - "type": "integer", - "minimum": 0 - } - } - }, - "ConversationDetailResponse": { - "allOf": [ - { - "$ref": "#/components/schemas/ConversationResponse" - }, - { - "type": "object", - "required": [ - "messages" - ], - "properties": { - "messages": { - "type": "array", - "items": { - "$ref": "#/components/schemas/MessageResponse" - }, - "description": "Turns oldest-first. The `system` seed message is omitted (internal)." - } - } - } - ] - }, - "ConversationResponse": { - "type": "object", - "required": [ - "public_id", - "context_type", - "context_id", - "status", - "created_at", - "last_activity_at" - ], - "properties": { - "context_id": { - "type": "string" - }, - "context_type": { - "type": "string" - }, - "created_at": { - "type": "string" - }, - "last_activity_at": { - "type": "string" - }, - "public_id": { - "type": "string" - }, - "status": { - "type": "string" - }, - "title": { - "type": [ - "string", - "null" - ] - } - } - }, - "ConversationSummary": { - "type": "object", - "description": "A conversation summary grouping related AI invocations.", - "required": [ - "conversation_id", - "message_count", - "total_input_tokens", - "total_output_tokens", - "total_tokens", - "total_cost_microcents", - "avg_latency_ms", - "models_used", - "first_at", - "last_at" - ], - "properties": { - "avg_latency_ms": { - "type": "number", - "format": "double" - }, - "conversation_id": { - "type": "string" - }, - "first_at": { - "type": "string" - }, - "last_at": { - "type": "string" - }, - "message_count": { - "type": "integer", - "format": "int64" - }, - "models_used": { - "type": "array", - "items": { - "type": "string" - } - }, - "total_cost_microcents": { - "type": "integer", - "format": "int64" - }, - "total_input_tokens": { - "type": "integer", - "format": "int64" - }, - "total_output_tokens": { - "type": "integer", - "format": "int64" - }, - "total_tokens": { - "type": "integer", - "format": "int64" - } - } - }, - "ConversationsQueryParams": { - "type": "object", - "properties": { - "from": { - "type": [ - "string", - "null" - ], - "description": "ISO 8601 start time (defaults to 24h ago)" - }, - "limit": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "description": "Max results (defaults to 50, max 100)", - "minimum": 0 - }, - "model": { - "type": [ - "string", - "null" - ], - "description": "Filter by model name" - }, - "tags": { - "type": [ - "string", - "null" - ], - "description": "Filter by tags (comma-separated, AND logic)" - }, - "to": { - "type": [ - "string", - "null" - ], - "description": "ISO 8601 end time (defaults to now)" - }, - "user_id": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Filter by user ID" - } - } - }, - "CopyBlobRequest": { - "type": "object", - "description": "Request to copy a blob", - "required": [ - "fromUrl", - "toPathname" - ], - "properties": { - "fromUrl": { - "type": "string", - "description": "Source blob URL or pathname", - "example": "/api/blob/10/images/avatar.png" - }, - "projectId": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Project ID (required for API key/session auth, optional for deployment tokens)", - "example": 1 - }, - "toPathname": { - "type": "string", - "description": "Destination pathname", - "example": "images/avatar-copy.png" - } - } - }, - "CostAnalysis": { - "type": "object", - "description": "Full cluster cost + rightsizing analysis attached to an import plan.", - "required": [ - "nodes", - "capacity", - "requested", - "usage_source", - "overprovisioning", - "recommendation", - "notes" - ], - "properties": { - "actual_usage": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/ResourceFootprint", - "description": "Measured usage from the metrics API (`metrics.k8s.io`).\n`None` when metrics-server is not installed." - } - ] - }, - "capacity": { - "$ref": "#/components/schemas/ClusterCapacity", - "description": "Total cluster capacity (sum of node allocatable resources)" - }, - "control_plane_monthly_usd": { - "type": [ - "number", - "null" - ], - "format": "double", - "description": "Managed control-plane fee included in `current_monthly_usd` (EKS/GKE\ncharge ~$73/mo per cluster). `None` when not applicable/unknown." - }, - "current_monthly_usd": { - "type": [ - "number", - "null" - ], - "format": "double", - "description": "Estimated total infrastructure cost per month in USD (compute nodes +\ncontrol-plane fee). `None` when no node could be priced." - }, - "nodes": { - "type": "array", - "items": { - "$ref": "#/components/schemas/NodeCostInfo" - }, - "description": "Per-node inventory with price estimates where the instance type is known" - }, - "notes": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Honesty notes: what could not be measured, which numbers are\nestimates, and any assumptions made. Always shown to the user." - }, - "overprovisioning": { - "$ref": "#/components/schemas/OverprovisioningAssessment", - "description": "Requests-vs-capacity-vs-usage assessment" - }, - "provider": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/CloudProvider", - "description": "Detected cloud provider (from node `providerID` prefixes)" - } - ] - }, - "recommendation": { - "$ref": "#/components/schemas/TargetRecommendation", - "description": "The temps/Hetzner target sizing and savings estimate" - }, - "requested": { - "$ref": "#/components/schemas/ResourceFootprint", - "description": "Sum of pod resource *requests* across running pods \u2014 what the\nscheduler has reserved, i.e. what the cluster is sized for." - }, - "usage_source": { - "$ref": "#/components/schemas/UsageSource", - "description": "How the usage numbers were obtained (drives UI wording)" - } - } - }, - "CreateAlertRuleRequest": { - "type": "object", - "required": [ - "name", - "trigger_type" - ], - "properties": { - "cooldown_minutes": { - "type": "integer", - "format": "int32", - "description": "Minimum minutes between notifications for same rule+group" - }, - "enabled": { - "type": "boolean" - }, - "environment_filter": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Optional environment ID to filter alerts" - }, - "error_level_filter": { - "type": [ - "string", - "null" - ], - "description": "Optional error type/level filter" - }, - "name": { - "type": "string" - }, - "notification_priority": { - "type": "string", - "description": "Notification priority: Low, Normal, High, Critical" - }, - "trigger_config": { - "description": "Trigger-specific configuration (e.g., {\"count\": 100, \"window_minutes\": 60} for frequency)" - }, - "trigger_type": { - "type": "string", - "description": "Trigger type: new_issue, regression, frequency, new_user, user_count, status_change" - } - } - }, - "CreateApiKeyRequest": { - "type": "object", - "required": [ - "name", - "role_type" - ], - "properties": { - "expires_at": { - "type": [ - "string", - "null" - ], - "format": "date-time", - "example": "2024-12-31T23:59:59Z" - }, - "name": { - "type": "string" - }, - "permissions": { - "type": [ - "array", - "null" - ], - "items": { - "type": "string" - }, - "example": [ - "projects:read", - "deployments:read" - ] - }, - "role_type": { - "type": "string", - "example": "admin" - } - } - }, - "CreateApiKeyResponse": { - "type": "object", - "required": [ - "id", - "name", - "key_prefix", - "role_type", - "api_key", - "created_at" - ], - "properties": { - "api_key": { - "type": "string" - }, - "created_at": { - "type": "string", - "format": "date-time", - "example": "2024-01-01T00:00:00Z" - }, - "expires_at": { - "type": [ - "string", - "null" - ], - "format": "date-time", - "example": "2024-12-31T23:59:59Z" - }, - "id": { - "type": "integer", - "format": "int32" - }, - "key_prefix": { - "type": "string" - }, - "name": { - "type": "string" - }, - "permissions": { - "type": [ - "array", - "null" - ], - "items": { - "type": "string" - } - }, - "role_type": { - "type": "string" - } - } - }, - "CreateBackupScheduleRequest": { - "type": "object", - "required": [ - "name", - "backup_type", - "retention_period", - "schedule_expression", - "enabled", - "tags" - ], - "properties": { - "backup_type": { - "type": "string" - }, - "description": { - "type": [ - "string", - "null" - ] - }, - "enabled": { - "type": "boolean" - }, - "include_control_plane": { - "type": [ - "boolean", - "null" - ], - "description": "When `true` (default), every run also produces a `control_plane`\nbackup of Temps's own database. Operators who use Temps purely as\na backup orchestrator for external DBs can set this to `false` to\nkeep the run history focused on those services." - }, - "max_runtime_secs": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "description": "Optional wall-clock timeout override for jobs created by this schedule\n(seconds). When set, overrides the engine-family default. `null` means\n\"use engine default.\" The per-job `max_runtime_secs` in\n`EnqueueJobParams` can still override this for ad-hoc triggers." - }, - "name": { - "type": "string" - }, - "retention_period": { - "type": "integer", - "format": "int32" - }, - "s3_source_id": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Optional S3 source. If omitted, the current default S3 source is used." - }, - "schedule_expression": { - "type": "string" - }, - "tags": { - "type": "array", - "items": { - "type": "string" - } - }, - "target_all_services": { - "type": [ - "boolean", - "null" - ], - "description": "When `true` (default), the schedule backs up every external service\non the host \u2014 including databases created in the future. When\n`false`, the schedule backs up only the services explicitly attached\nvia `POST /backups/schedules/{id}/services`. Omit to use the default." - } - } - }, - "CreateBitbucketRequest": { - "type": "object", - "required": [ - "name", - "auth" - ], - "properties": { - "auth": { - "$ref": "#/components/schemas/BitbucketAuthInput", - "description": "Authentication credentials \u2014 either an access token or an app password." - }, - "name": { - "type": "string", - "description": "Display name for this provider." - } - } - }, - "CreateCloudflareProviderRequest": { - "type": "object", - "required": [ - "name", - "config" - ], - "properties": { - "config": { - "$ref": "#/components/schemas/CloudflareConfig" - }, - "enabled": { - "type": [ - "boolean", - "null" - ] - }, - "name": { - "type": "string" - } - } - }, - "CreateConversationRequest": { - "type": "object", - "required": [ - "context_type", - "context_id" - ], - "properties": { - "context_id": { - "type": "string", - "description": "The entity id (ints stringified)." - }, - "context_type": { - "type": "string", - "description": "e.g. `\"deployment\"`." - } - } - }, - "CreateDSNRequest": { - "type": "object", - "properties": { - "base_url": { - "type": [ - "string", - "null" - ] - }, - "deployment_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "environment_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "name": { - "type": [ - "string", - "null" - ] - } - } - }, - "CreateDashboardRequest": { - "type": "object", - "required": [ - "project_id", - "name", - "layout" - ], - "properties": { - "layout": { - "$ref": "#/components/schemas/DashboardLayout" - }, - "name": { - "type": "string" - }, - "project_id": { - "type": "integer", - "format": "int32" - } - } - }, - "CreateDeploymentTokenRequest": { - "type": "object", - "required": [ - "name" - ], - "properties": { - "deployment_id": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Optional deployment ID - if set, token is scoped to a specific deployment" - }, - "environment_id": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Optional environment ID - if not set, token applies to all environments" - }, - "expires_at": { - "type": [ - "string", - "null" - ], - "format": "date-time", - "example": "2024-12-31T23:59:59Z" - }, - "name": { - "type": "string" - }, - "permissions": { - "type": [ - "array", - "null" - ], - "items": { - "type": "string" - }, - "description": "List of permissions (e.g., [\"visitors:enrich\", \"emails:send\"])\nIf not provided, defaults to full access", - "example": [ - "visitors:enrich", - "emails:send" - ] - } - } - }, - "CreateDeploymentTokenResponse": { - "type": "object", - "required": [ - "id", - "project_id", - "name", - "token_prefix", - "token", - "created_at" - ], - "properties": { - "created_at": { - "type": "string", - "format": "date-time", - "example": "2024-01-01T00:00:00Z" - }, - "deployment_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "environment_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "expires_at": { - "type": [ - "string", - "null" - ], - "format": "date-time", - "example": "2024-12-31T23:59:59Z" - }, - "id": { - "type": "integer", - "format": "int32" - }, - "name": { - "type": "string" - }, - "permissions": { - "type": [ - "array", - "null" - ], - "items": { - "type": "string" - } - }, - "project_id": { - "type": "integer", - "format": "int32" - }, - "token": { - "type": "string", - "description": "The full token value - only returned on creation" - }, - "token_prefix": { - "type": "string" - } - } - }, - "CreateDnsProviderRequest": { - "type": "object", - "description": "Request to create a new DNS provider", - "required": [ - "name", - "provider_type", - "credentials" - ], - "properties": { - "credentials": { - "$ref": "#/components/schemas/DnsProviderCredentials", - "description": "Provider credentials" - }, - "description": { - "type": [ - "string", - "null" - ], - "description": "Optional description" - }, - "name": { - "type": "string", - "description": "User-friendly name", - "example": "My Cloudflare" - }, - "provider_type": { - "$ref": "#/components/schemas/DnsProviderType", - "description": "Provider type" - } - } - }, - "CreateDomainRequest": { - "type": "object", - "required": [ - "domain" - ], - "properties": { - "challenge_type": { - "type": "string", - "description": "Challenge type for Let's Encrypt validation. Options: \"http-01\" (default) or \"dns-01\"" - }, - "domain": { - "type": "string" - } - } - }, - "CreateEmailDomainRequest": { - "type": "object", - "required": [ - "provider_id", - "domain" - ], - "properties": { - "domain": { - "type": "string", - "description": "Domain name (e.g., \"updates.example.com\")", - "example": "updates.example.com" - }, - "provider_id": { - "type": "integer", - "format": "int32", - "description": "Provider ID to use for this domain" - } - } - }, - "CreateEmailProviderRequest": { - "type": "object", - "required": [ - "name", - "provider_type", - "region" - ], - "properties": { - "name": { - "type": "string", - "description": "User-friendly name for the provider", - "example": "My AWS SES" - }, - "provider_type": { - "$ref": "#/components/schemas/EmailProviderTypeRoute", - "description": "Provider type" - }, - "region": { - "type": "string", - "description": "Cloud region. For SMTP this is informational only \u2014 the host/port carry the real routing.", - "example": "us-east-1" - }, - "scaleway_credentials": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/ScalewayCredentialsRequest", - "description": "Scaleway credentials (required if provider_type is scaleway)" - } - ] - }, - "ses_credentials": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/SesCredentialsRequest", - "description": "AWS SES credentials (required if provider_type is ses)" - } - ] - }, - "smtp_credentials": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/SmtpCredentialsRequest", - "description": "Generic SMTP credentials (required if provider_type is smtp). Use when\nyou only have SMTP creds and want to import an already-set-up domain." - } - ] - }, - "sns_topic_arn": { - "type": [ - "string", - "null" - ], - "description": "Exact SNS topic allowed to deliver SES events for this provider." - } - } - }, - "CreateEnvironmentRequest": { - "type": "object", - "required": [ - "name", - "branch" - ], - "properties": { - "branch": { - "type": "string" - }, - "name": { - "type": "string" - }, - "set_as_preview": { - "type": "boolean", - "description": "If true, set this environment as the preview environment for the project" - } - } - }, - "CreateEnvironmentVariableRequest": { - "type": "object", - "required": [ - "key", - "value", - "environment_ids" - ], - "properties": { - "environment_ids": { - "type": "array", - "items": { - "type": "integer", - "format": "int32" - } - }, - "include_in_preview": { - "type": "boolean", - "description": "Include this environment variable in preview environments (default: true)" - }, - "is_secret": { - "type": "boolean", - "description": "When true the variable is treated as write-only: never returned in\nplaintext from the API, masked in the UI, and updates that omit the\nvalue preserve the existing ciphertext. The flag is one-way \u2014 secret\nvars cannot be demoted back to regular vars." - }, - "key": { - "type": "string" - }, - "value": { - "type": "string" - } - } - }, - "CreateExternalServiceRequest": { - "type": "object", - "required": [ - "name", - "service_type", - "parameters" - ], - "properties": { - "members": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ClusterMemberRequest" - }, - "description": "Cluster member specifications. Required when topology is \"cluster\"." - }, - "name": { - "type": "string" - }, - "node_id": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Target node ID for the service. Omit or null to run on the control plane." - }, - "parameters": { - "type": "object", - "additionalProperties": {}, - "propertyNames": { - "type": "string" - } - }, - "service_type": { - "$ref": "#/components/schemas/ServiceTypeRoute" - }, - "topology": { - "type": "string", - "description": "Service topology: \"standalone\" (default) or \"cluster\" (HA multi-member).", - "example": "standalone" - }, - "version": { - "type": [ - "string", - "null" - ] - } - } - }, - "CreateFlagRequest": { - "type": "object", - "required": [ - "key", - "value_type", - "default_value" - ], - "properties": { - "client_visible": { - "type": "boolean", - "description": "Whether the flag may be exposed on the unauthenticated same-origin\nevaluation endpoint. Defaults to `false`: flags are server-only unless\nexplicitly opted in, because targeting rules can encode business logic." - }, - "default_value": { - "description": "Served whenever evaluation cannot do better. Must match `value_type`.\n\nLeft unannotated so utoipa emits a free-form schema: a bool flag's\ndefault is `false`, not an object, and `value_type = Object` would tell\nevery generated client otherwise." - }, - "description": { - "type": [ - "string", - "null" - ] - }, - "key": { - "type": "string", - "description": "Stable key used in application code. Immutable after create.", - "example": "checkout.v2" - }, - "value_type": { - "$ref": "#/components/schemas/FlagValueType", - "description": "Fixed at create: retyping would invalidate every stored value and every\ncall site." - } - } - }, - "CreateFunnelRequest": { - "type": "object", - "required": [ - "name", - "steps" - ], - "properties": { - "description": { - "type": [ - "string", - "null" - ] - }, - "name": { - "type": "string" - }, - "steps": { - "type": "array", - "items": { - "$ref": "#/components/schemas/CreateFunnelStep" - } - } - } - }, - "CreateFunnelResponse": { - "type": "object", - "required": [ - "funnel_id", - "message" - ], - "properties": { - "funnel_id": { - "type": "integer", - "format": "int32" - }, - "message": { - "type": "string" - } - } - }, - "CreateFunnelStep": { - "type": "object", - "required": [ - "event_name" - ], - "properties": { - "event_filter": { - "type": "array", - "items": { - "$ref": "#/components/schemas/SmartFilter" - } - }, - "event_name": { - "type": "string" - } - } - }, - "CreateGenericRequest": { - "type": "object", - "required": [ - "name", - "clone_url" - ], - "properties": { - "base_url": { - "type": [ - "string", - "null" - ], - "description": "Optional base URL of the git host for display purposes (no API is called)." - }, - "clone_url": { - "type": "string", - "description": "HTTPS clone URL for the repository, e.g. `https://git.example.com/org/repo.git`." - }, - "name": { - "type": "string", - "description": "Display name for this provider." - }, - "token": { - "type": [ - "string", - "null" - ], - "description": "Access token or password. Omit (or set to `null`) for public repositories." - }, - "token_username": { - "type": [ - "string", - "null" - ], - "description": "HTTP Basic username used with the token. Defaults to `x-access-token` when\nabsent or empty. Ignored for public (unauthenticated) repositories." - } - } - }, - "CreateGitHubPATRequest": { - "type": "object", - "required": [ - "name", - "token" - ], - "properties": { - "name": { - "type": "string" - }, - "token": { - "type": "string" - } - } - }, - "CreateGitLabOAuthRequest": { - "type": "object", - "required": [ - "name", - "client_id", - "client_secret", - "redirect_uri" - ], - "properties": { - "base_url": { - "type": [ - "string", - "null" - ] - }, - "client_id": { - "type": "string" - }, - "client_secret": { - "type": "string" - }, - "name": { - "type": "string" - }, - "redirect_uri": { - "type": "string" - } - } - }, - "CreateGitLabPATRequest": { - "type": "object", - "required": [ - "name", - "token" - ], - "properties": { - "base_url": { - "type": [ - "string", - "null" - ] - }, - "name": { - "type": "string" - }, - "token": { - "type": "string" - } - } - }, - "CreateGiteaPATRequest": { - "type": "object", - "required": [ - "name", - "token", - "base_url" - ], - "properties": { - "base_url": { - "type": "string", - "description": "HTTPS base URL of the Gitea instance, e.g. `https://git.example.com`." - }, - "name": { - "type": "string", - "description": "Display name for this provider." - }, - "token": { - "type": "string", - "description": "Personal access token issued by the Gitea instance." - } - } - }, - "CreateIncidentRequest": { - "type": "object", - "required": [ - "title", - "severity" - ], - "properties": { - "description": { - "type": [ - "string", - "null" - ] - }, - "environment_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "monitor_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "severity": { - "type": "string" - }, - "title": { - "type": "string" - } - } - }, - "CreateIntegrationBody": { - "type": "object", - "required": [ - "provider", - "signing_secret" - ], - "properties": { - "provider": { - "type": "string", - "description": "Registered provider name, e.g. \"stripe\"." - }, - "signing_secret": { - "type": "string", - "description": "Signing secret from the provider's dashboard." - } - } - }, - "CreateIpAccessControlRequest": { - "type": "object", - "description": "Request to create an IP access control rule", - "required": [ - "ip_address", - "action" - ], - "properties": { - "action": { - "type": "string", - "description": "Action to take: \"block\" or \"allow\"", - "example": "block" - }, - "ip_address": { - "type": "string", - "description": "IP address in CIDR notation (e.g., \"192.168.1.1\" or \"10.0.0.0/24\")", - "example": "192.168.1.100" - }, - "reason": { - "type": [ - "string", - "null" - ], - "description": "Optional reason for the action", - "example": "Malicious activity detected" - } - } - }, - "CreateMcpRequest": { - "type": "object", - "required": [ - "slug", - "name", - "config" - ], - "properties": { - "config": { - "type": "object" - }, - "description": { - "type": [ - "string", - "null" - ] - }, - "name": { - "type": "string" - }, - "slug": { - "type": "string" - } - } - }, - "CreateMetricAlertRequest": { - "type": "object", - "required": [ - "project_id", - "name", - "metric_name", - "aggregation", - "detection_config", - "window_secs", - "for_duration_secs", - "severity", - "enabled" - ], - "properties": { - "aggregation": { - "type": "string", - "description": "One of `avg|sum|min|max|count|rate|p50|p90|p95|p99`." - }, - "detection_config": { - "$ref": "#/components/schemas/DetectionConfig", - "description": "The detector: a discriminated union keyed by `kind`. Today only\n`{ \"kind\": \"static\", \"comparator\": \"gt\", \"threshold\": 500 }` is evaluable." - }, - "dynamic_alerts": { - "type": "boolean", - "description": "When true (and `group_by` is set) fire one independent alarm per breaching\nseries. Static detectors only. Default false." - }, - "enabled": { - "type": "boolean" - }, - "for_duration_secs": { - "type": "integer", - "format": "int32" - }, - "group_by": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Label keys to break the metric down by, e.g. `[\"endpoint\",\"region\"]`. Empty\n(the default) = one aggregate stream. Max 2 keys; keys must match\n`[a-zA-Z0-9_.:-]`." - }, - "grouped_notification_threshold": { - "type": "integer", - "format": "int32", - "description": "When more than this many series transition to firing in the same tick, only\nthe first gets the expensive chart/AI enrichment. Range 1\u20131000, default 5." - }, - "label_filters": { - "type": "array", - "items": { - "type": "array", - "items": false, - "prefixItems": [ - { - "type": "string" - }, - { - "type": "string" - } - ] - }, - "description": "AND-combined label equality filters: `[[\"key\",\"value\"],\u2026]`. Empty = no\nfiltering (the default). Max 10 pairs; keys must match `[a-zA-Z0-9_.:-]`;\nvalues capped at 500 characters." - }, - "max_series": { - "type": "integer", - "format": "int32", - "description": "Cardinality cap for dynamic alerting: at most this many series (top by\n`|value|`). Range 1\u2013100, default 20." - }, - "metric_name": { - "type": "string" - }, - "name": { - "type": "string" - }, - "project_id": { - "type": "integer", - "format": "int32" - }, - "severity": { - "type": "string", - "description": "One of `info|warning|critical`." - }, - "window_secs": { - "type": "integer", - "format": "int32" - } - } - }, - "CreateMonitorRequest": { - "type": "object", - "required": [ - "name", - "monitor_type", - "environment_id" - ], - "properties": { - "check_interval_seconds": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "check_path": { - "type": [ - "string", - "null" - ] - }, - "environment_id": { - "type": "integer", - "format": "int32" - }, - "monitor_type": { - "type": "string" - }, - "name": { - "type": "string" - } - } - }, - "CreateNotificationEmailProviderRequest": { - "type": "object", - "required": [ - "name", - "config" - ], - "properties": { - "config": { - "$ref": "#/components/schemas/EmailConfig" - }, - "enabled": { - "type": [ - "boolean", - "null" - ] - }, - "name": { - "type": "string" - } - } - }, - "CreateOidcProviderRequest": { - "type": "object", - "required": [ - "name", - "issuer_url", - "client_id", - "client_secret" - ], - "properties": { - "client_id": { - "type": "string" - }, - "client_secret": { - "type": "string" - }, - "default_role": { - "type": "string" - }, - "enabled": { - "type": "boolean" - }, - "group_claim": { - "type": "string" - }, - "issuer_url": { - "type": "string" - }, - "jit_provisioning": { - "type": "boolean" - }, - "name": { - "type": "string" - }, - "role_claim": { - "type": "string" - }, - "scopes": { - "type": "string" - }, - "template": { - "type": "string" - }, - "trust_idp_email": { - "type": "boolean", - "description": "Defaults false. Set to true only for IdPs where an admin\ncontrols user provisioning (corporate Okta, Azure AD) and\nself-signup of arbitrary emails is not possible \u2014 see the\n`trust_idp_email` field on `oidc_providers::Model` for the\nsecurity tradeoff this enables." - } - } - }, - "CreateOidcRoleMappingRequest": { - "type": "object", - "required": [ - "priority", - "idp_group", - "role" - ], - "properties": { - "idp_group": { - "type": "string" - }, - "priority": { - "type": "integer", - "format": "int32" - }, - "role": { - "type": "string" - } - } - }, - "CreatePlanRequest": { - "type": "object", - "description": "Request to create an import plan", - "required": [ - "source", - "workload_id" - ], - "properties": { - "credentials": { - "$ref": "#/components/schemas/ImportCredentials", - "description": "Platform credentials (required for cloud platforms like Vercel, Railway)" - }, - "repository_id": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Optional repository ID to associate with the import\nIf provided, preset will be detected from the repository" - }, - "source": { - "$ref": "#/components/schemas/ImportSource", - "description": "Source to import from" - }, - "workload_id": { - "$ref": "#/components/schemas/WorkloadId", - "description": "Workload ID to import" - } - } - }, - "CreatePlanResponse": { - "type": "object", - "description": "Response with created plan", - "required": [ - "session_id", - "plan", - "validation", - "can_execute" - ], - "properties": { - "can_execute": { - "type": "boolean", - "description": "Whether the plan can be executed" - }, - "plan": { - "$ref": "#/components/schemas/ImportPlan", - "description": "Generated import plan" - }, - "session_id": { - "type": "string", - "description": "Session ID for tracking" - }, - "validation": { - "$ref": "#/components/schemas/ValidationReport", - "description": "Validation report" - } - } - }, - "CreatePrResponse": { - "type": "object", - "required": [ - "run", - "pr_url", - "pr_number", - "branch_name" - ], - "properties": { - "branch_name": { - "type": "string" - }, - "pr_number": { - "type": "integer", - "format": "int32" - }, - "pr_url": { - "type": "string" - }, - "run": { - "$ref": "#/components/schemas/AutofixerRunResponse" - } - } - }, - "CreateProjectAccessRequest": { - "type": "object", - "required": [ - "team_id", - "role" - ], - "properties": { - "role": { - "$ref": "#/components/schemas/TeamRole" - }, - "team_id": { - "type": "integer", - "format": "int32" - } - } - }, - "CreateProjectFromTemplateRequest": { - "type": "object", - "description": "Request to create a project from a template\n\nSupports two deploy modes:\n * **Fork mode** \u2014 when `git_provider_connection_id` is set, the template\n repo is cloned into a new repository under the user's Git account and the\n project tracks that fork (git-push deploys, automatic deploy on push).\n * **One-click public-repo mode** \u2014 when `git_provider_connection_id` is\n omitted, the project deploys directly from the template's public source\n repository (no fork, no Git account required). This is the activation\n path: a brand-new user with no Git provider connected can still deploy a\n demo in one click. `repository_name` / `repository_owner` are ignored in\n this mode, and automatic-deploy-on-push is unavailable (there is no fork\n to receive webhooks).", - "required": [ - "template_slug", - "project_name" - ], - "properties": { - "automatic_deploy": { - "type": "boolean", - "description": "Enable automatic deployment on push (defaults to true). Only honoured in\nfork mode; public-repo deploys cannot receive push webhooks." - }, - "environment_variables": { - "type": "array", - "items": { - "$ref": "#/components/schemas/EnvVarInput" - }, - "description": "Environment variables to set (key-value pairs)" - }, - "git_provider_connection_id": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Git provider connection ID. When omitted, the project deploys directly\nfrom the template's public source repository instead of forking it." - }, - "private": { - "type": "boolean", - "description": "Whether to make the repository private (defaults to true)" - }, - "project_name": { - "type": "string", - "description": "Name for the new project" - }, - "repository_name": { - "type": [ - "string", - "null" - ], - "description": "Name for the new repository to create. Required in fork mode; ignored in\none-click public-repo mode." - }, - "repository_owner": { - "type": [ - "string", - "null" - ], - "description": "Owner/organization for the new repository (defaults to authenticated user)" - }, - "storage_service_ids": { - "type": "array", - "items": { - "type": "integer", - "format": "int32" - }, - "description": "External storage service IDs to attach to the project" - }, - "template_slug": { - "type": "string", - "description": "Template slug to use as the base" - } - } - }, - "CreateProjectFromTemplateResponse": { - "type": "object", - "description": "Response after creating a project from template", - "required": [ - "project_id", - "project_slug", - "project_name", - "repository_url", - "template_slug", - "message" - ], - "properties": { - "message": { - "type": "string", - "description": "Message with additional info" - }, - "project_id": { - "type": "integer", - "format": "int32", - "description": "ID of the created project" - }, - "project_name": { - "type": "string", - "description": "Name of the created project" - }, - "project_slug": { - "type": "string", - "description": "Slug of the created project" - }, - "repository_url": { - "type": "string", - "description": "URL of the created repository" - }, - "template_slug": { - "type": "string", - "description": "Template that was used" - } - } - }, - "CreateProjectRequest": { - "type": "object", - "required": [ - "name", - "directory", - "main_branch", - "preset", - "storage_service_ids" - ], - "properties": { - "automatic_deploy": { - "type": [ - "boolean", - "null" - ] - }, - "build_command": { - "type": [ - "string", - "null" - ] - }, - "custom_domain": { - "type": [ - "string", - "null" - ] - }, - "directory": { - "type": "string" - }, - "environment_variables": { - "type": [ - "array", - "null" - ], - "items": { - "type": "array", - "items": false, - "prefixItems": [ - { - "type": "string" - }, - { - "type": "string" - } - ] - } - }, - "exposed_port": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Port exposed by the container (fallback when image has no EXPOSE directive)\n\nPriority order for port resolution:\n1. Image EXPOSE directive (auto-detected from built image)\n2. Environment-level exposed_port (overrides this value per environment)\n3. This project-level exposed_port (fallback)\n4. Default: 3000\n\nOnly set this if your image doesn't use EXPOSE directive.", - "example": 8080 - }, - "git_provider_connection_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "git_url": { - "type": [ - "string", - "null" - ] - }, - "install_command": { - "type": [ - "string", - "null" - ] - }, - "is_on_demand": { - "type": [ - "boolean", - "null" - ] - }, - "is_public_repo": { - "type": [ - "boolean", - "null" - ] - }, - "is_web_app": { - "type": [ - "boolean", - "null" - ] - }, - "main_branch": { - "type": "string" - }, - "name": { - "type": "string" - }, - "output_dir": { - "type": [ - "string", - "null" - ] - }, - "performance_metrics_enabled": { - "type": "boolean" - }, - "preset": { - "type": "string" - }, - "preset_config": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/PresetConfigSchema", - "description": "Preset-specific configuration\n\nDifferent presets accept different configuration options:\n- **Dockerfile preset**: Accepts `DockerfilePresetConfig` with `dockerfile_path` and `build_context`\n- **Nixpacks preset**: Accepts ordered `providers` (for example `[\"...\", \"python\"]`)\n and optional inline `nixpacksConfig` TOML\n- **Static presets** (Vite, Next.js, etc.): Accept `StaticPresetConfig` with build commands and output dir\n\nExample for Dockerfile preset:\n```json\n{\n \"dockerfilePath\": \"docker/Dockerfile\",\n \"buildContext\": \"./api\"\n}\n```" - } - ] - }, - "project_type": { - "type": [ - "string", - "null" - ] - }, - "repo_name": { - "type": [ - "string", - "null" - ] - }, - "repo_owner": { - "type": [ - "string", - "null" - ] - }, - "source_type": { - "$ref": "#/components/schemas/SourceType", - "description": "Source type for deployments\n\nDetermines how the project is deployed:\n- **git** (default): Traditional Git-based deployments - source code is pulled, built, and deployed\n- **docker_image**: Deploy pre-built Docker images from external registries (DockerHub, GHCR, etc.)\n- **static_files**: Deploy pre-built static files uploaded as tar.gz or zip bundles\n\nFor `docker_image` and `static_files` source types, `repo_name` and `repo_owner` are optional." - }, - "storage_service_ids": { - "type": "array", - "items": { - "type": "integer", - "format": "int32" - } - }, - "use_default_wildcard": { - "type": [ - "boolean", - "null" - ] - } - } - }, - "CreateProjectSecretRequest": { - "type": "object", - "description": "Request to create a new project secret.\n\nProject secrets are mounted into the container as files under\n`/run/secrets/` (mode 0400, tmpfs) instead of as environment variables.\nValues are always encrypted at rest and never returned in plaintext from\nthe API after create. Distinct from agent secrets (global `/settings/secrets`).", - "required": [ - "key", - "value" - ], - "properties": { - "environment_ids": { - "type": "array", - "items": { - "type": "integer", - "format": "int32" - } - }, - "include_in_preview": { - "type": "boolean", - "description": "Include this secret in preview environments." - }, - "key": { - "type": "string", - "description": "Identifier for the secret. Becomes the filename at `/run/secrets/`.\nMust start with a letter or underscore and contain only A-Z, a-z, 0-9, _." - }, - "value": { - "type": "string", - "description": "Plaintext value, <= 1 MiB." - } - } - }, - "CreateProviderKeyRequest": { - "type": "object", - "required": [ - "provider", - "display_name", - "api_key" - ], - "properties": { - "api_key": { - "type": "string" - }, - "base_url": { - "type": [ - "string", - "null" - ] - }, - "default_model": { - "type": [ - "string", - "null" - ], - "description": "Optional model id to pin for this provider (e.g. \"gpt-4o-mini\")." - }, - "display_name": { - "type": "string" - }, - "provider": { - "type": "string" - } - } - }, - "CreateProviderRequest": { - "type": "object", - "required": [ - "name", - "provider_type", - "config" - ], - "properties": { - "config": {}, - "enabled": { - "type": [ - "boolean", - "null" - ] - }, - "name": { - "type": "string" - }, - "provider_type": { - "type": "string" - } - } - }, - "CreateRouteRequest": { - "type": "object", - "required": [ - "domain", - "host", - "port" - ], - "properties": { - "domain": { - "type": "string" - }, - "host": { - "type": "string" - }, - "port": { - "type": "integer", - "format": "int32" - }, - "route_type": { - "type": [ - "string", - "null" - ], - "description": "Route type: \"http\" (default) matches on HTTP Host header,\n\"tls\" matches on TLS SNI hostname for TCP passthrough" - } - } - }, - "CreateS3SourceRequest": { - "type": "object", - "required": [ - "name", - "bucket_name", - "bucket_path", - "access_key_id", - "secret_key", - "region" - ], - "properties": { - "access_key_id": { - "type": "string" - }, - "bucket_name": { - "type": "string" - }, - "bucket_path": { - "type": "string" - }, - "endpoint": { - "type": [ - "string", - "null" - ], - "description": "Optional endpoint URL for S3-compatible services like MinIO", - "example": "http://minio.example.com:9000" - }, - "force_path_style": { - "type": [ - "boolean", - "null" - ], - "description": "Whether to use path-style addressing (default: true)", - "example": true - }, - "is_default": { - "type": [ - "boolean", - "null" - ], - "description": "When true, make this the default source (will swap out any existing default).\nThe very first S3 source is always created as default regardless of this flag.", - "example": false - }, - "name": { - "type": "string" - }, - "region": { - "type": "string" - }, - "secret_key": { - "type": "string" - } - } - }, - "CreateSandboxBody": { - "type": "object", - "properties": { - "_runtime": { - "type": [ - "string", - "null" - ] - }, - "backend": { - "type": [ - "string", - "null" - ], - "description": "Isolation backend: `\"docker\"` (default) or `\"firecracker\"` (ADR-029,\nhardware-virtualized microVM \u2014 requires a host provisioned with\n`temps firecracker setup`). Omit for the platform default; existing\nclients are unaffected. Requesting an unavailable backend fails with\n400 rather than silently downgrading isolation." - }, - "cpu_limit": { - "type": [ - "number", - "null" - ], - "format": "double" - }, - "disk_size_mb": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "description": "Root disk size in MB (Firecracker only; Docker ignores it). Omit for\nthe platform default (1 GiB).", - "minimum": 0 - }, - "env": { - "type": "object", - "description": "Extra env vars baked into the container on create.", - "additionalProperties": { - "type": "string" - }, - "propertyNames": { - "type": "string" - } - }, - "image": { - "type": [ - "string", - "null" - ], - "description": "Docker image override. `null` uses the platform default." - }, - "memory_limit_mb": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "minimum": 0 - }, - "name": { - "type": [ - "string", - "null" - ] - }, - "networkPolicy": {}, - "pids_limit": { - "type": [ - "integer", - "null" - ], - "format": "int64" - }, - "ports": { - "type": "array", - "items": { - "type": "integer", - "format": "int32", - "minimum": 0 - }, - "description": "Ports the sandbox will listen on. Each port becomes a `routes[]`\nentry in the create/get response so `@vercel/sandbox`'s\n`sandbox.domain(port)` can resolve it client-side without an\nextra round-trip." - }, - "preview_password": { - "type": [ - "string", - "null" - ], - "description": "Optional preview-URL password. When set, every preview URL served\nfor this sandbox is gated behind a login form. 8\u2013256 characters.\nOmit to leave preview URLs open (the sandbox ID remains the only\ngate). The plaintext is never returned; only the last-4 hint is\nsurfaced in `SandboxResponse.preview_password_hint`." - }, - "projectId": { - "type": [ - "string", - "null" - ] - }, - "resources": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/ResourcesBody", - "description": "`@vercel/sandbox`'s nested resources object. When present, its\n`memory` / `vcpus` populate `memory_limit_mb` / `cpu_limit` if those\nweren't sent directly." - } - ] - }, - "source": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/SourceBody", - "description": "Optional initial content to seed into the work dir. Clones a\nrepo or extracts a tarball after the sandbox is created." - } - ] - }, - "timeout": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "description": "Idle timeout as sent by `@vercel/sandbox` (milliseconds). Converted\nto seconds when `timeout_secs` is absent.", - "minimum": 0 - }, - "timeout_secs": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "description": "Idle timeout in seconds (temps-native). Clamped to `[60, 86400]`.", - "minimum": 0 - } - } - }, - "CreateSkillRequest": { - "type": "object", - "required": [ - "slug", - "name", - "content" - ], - "properties": { - "content": { - "type": "string" - }, - "description": { - "type": [ - "string", - "null" - ] - }, - "name": { - "type": "string" - }, - "slug": { - "type": "string" - } - } - }, - "CreateSlackProviderRequest": { - "type": "object", - "required": [ - "name", - "config" - ], - "properties": { - "config": { - "$ref": "#/components/schemas/SlackConfig" - }, - "enabled": { - "type": [ - "boolean", - "null" - ] - }, - "name": { - "type": "string" - } - } - }, - "CreateTeamMemberRequest": { - "type": "object", - "required": [ - "user_id", - "role" - ], - "properties": { - "role": { - "$ref": "#/components/schemas/TeamRole" - }, - "user_id": { - "type": "integer", - "format": "int32" - } - } - }, - "CreateTeamRequest": { - "type": "object", - "required": [ - "name", - "slug" - ], - "properties": { - "description": { - "type": [ - "string", - "null" - ] - }, - "name": { - "type": "string" - }, - "slug": { - "type": "string" - } - } - }, - "CreateUserRequest": { - "type": "object", - "required": [ - "username", - "roles" - ], - "properties": { - "email": { - "type": [ - "string", - "null" - ] - }, - "password": { - "type": [ - "string", - "null" - ] - }, - "roles": { - "type": "array", - "items": { - "type": "string" - } - }, - "username": { - "type": "string" - } - } - }, - "CreateWebhookProviderRequest": { - "type": "object", - "required": [ - "name", - "config" - ], - "properties": { - "config": { - "$ref": "#/components/schemas/WebhookConfig" - }, - "enabled": { - "type": [ - "boolean", - "null" - ] - }, - "name": { - "type": "string" - } - } - }, - "CreateWebhookRequestBody": { - "type": "object", - "required": [ - "url", - "events" - ], - "properties": { - "enabled": { - "type": [ - "boolean", - "null" - ], - "description": "Whether the webhook is enabled", - "default": true - }, - "events": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Event types to subscribe to", - "example": [ - "deployment.created", - "deployment.succeeded" - ] - }, - "secret": { - "type": [ - "string", - "null" - ], - "description": "Secret for HMAC signature verification (optional)" - }, - "url": { - "type": "string", - "description": "Target URL for webhook delivery", - "example": "https://example.com/webhook" - } - } - }, - "CreatedResource": { - "type": "object", - "description": "Resource created during import (for rollback / audit)", - "required": [ - "resource_type", - "resource_id", - "resource_name" - ], - "properties": { - "resource_id": { - "type": "integer", - "format": "int32", - "description": "Resource ID" - }, - "resource_name": { - "type": "string", - "description": "Resource name" - }, - "resource_type": { - "type": "string", - "description": "Resource type (project, environment, deployment, service, domain, etc.)" - } - } - }, - "CronExecutionInfo": { - "type": "object", - "required": [ - "id", - "cron_id", - "executed_at", - "url", - "status_code", - "headers", - "response_time_ms" - ], - "properties": { - "cron_id": { - "type": "integer", - "format": "int32" - }, - "error_message": { - "type": [ - "string", - "null" - ] - }, - "executed_at": { - "type": "string" - }, - "headers": { - "type": "string" - }, - "id": { - "type": "integer", - "format": "int32" - }, - "response_time_ms": { - "type": "integer", - "format": "int32" - }, - "status_code": { - "type": "integer", - "format": "int32" - }, - "url": { - "type": "string" - } - } - }, - "CronInfo": { - "type": "object", - "required": [ - "id", - "project_id", - "environment_id", - "path", - "schedule", - "created_at", - "updated_at" - ], - "properties": { - "created_at": { - "type": "string" - }, - "deleted_at": { - "type": [ - "string", - "null" - ] - }, - "environment_id": { - "type": "integer", - "format": "int32" - }, - "id": { - "type": "integer", - "format": "int32" - }, - "next_run": { - "type": [ - "string", - "null" - ] - }, - "path": { - "type": "string" - }, - "project_id": { - "type": "integer", - "format": "int32" - }, - "schedule": { - "type": "string" - }, - "updated_at": { - "type": "string" - } - } - }, - "CrossProjectSiblingRef": { - "type": "object", - "description": "A sibling project that shares the same `trace_id`, returned by the\nPhase 1 cross-project banner endpoint.", - "required": [ - "project_id", - "project_name", - "project_slug", - "first_seen" - ], - "properties": { - "first_seen": { - "type": "string", - "format": "date-time", - "description": "ISO 8601 timestamp (UTC, `Z` suffix) of first span ingest for this\n`(trace_id, project_id)` pair." - }, - "project_id": { - "type": "integer", - "format": "int32" - }, - "project_name": { - "type": "string" - }, - "project_slug": { - "type": "string", - "description": "URL slug used to link into the sibling project's single-project trace view." - } - } - }, - "CrossProjectTraceResponse": { - "type": "object", - "description": "Response body for `GET /otel/traces/cross-project/{trace_id}`.\n\nAn empty `siblings` vec is the normal single-project case \u2014 never 404.", - "required": [ - "trace_id", - "siblings" - ], - "properties": { - "siblings": { - "type": "array", - "items": { - "$ref": "#/components/schemas/CrossProjectSiblingRef" - }, - "description": "Projects other than the caller's that hold spans for this trace,\nordered by `first_seen ASC`." - }, - "trace_id": { - "type": "string", - "description": "The trace_id that was queried (echoed back for client convenience)." - } - } - }, - "CurrentStatusResponse": { - "type": "object", - "required": [ - "monitor_id", - "current_status", - "uptime_percentage" - ], - "properties": { - "avg_response_time_ms": { - "type": [ - "number", - "null" - ], - "format": "double" - }, - "current_status": { - "type": "string" - }, - "last_check_at": { - "type": [ - "string", - "null" - ], - "format": "date-time" - }, - "monitor_id": { - "type": "integer", - "format": "int32" - }, - "uptime_percentage": { - "type": "number", - "format": "double" - } - } - }, - "CustomDomainRequest": { - "type": "object", - "required": [ - "domain", - "environment_id" - ], - "properties": { - "branch": { - "type": [ - "string", - "null" - ] - }, - "domain": { - "type": "string" - }, - "environment_id": { - "type": "integer", - "format": "int32" - }, - "redirect_to": { - "type": [ - "string", - "null" - ] - }, - "service_name": { - "type": [ - "string", - "null" - ], - "description": "Docker Compose service name this domain routes to (only for docker-compose projects)" - }, - "status_code": { - "type": [ - "integer", - "null" - ], - "format": "int32" - } - } - }, - "CustomDomainResponse": { - "type": "object", - "required": [ - "id", - "project_id", - "domain", - "status", - "created_at", - "updated_at" - ], - "properties": { - "branch": { - "type": [ - "string", - "null" - ] - }, - "created_at": { - "type": "integer", - "format": "int64" - }, - "domain": { - "type": "string" - }, - "domain_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "environment": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/DomainEnvironmentResponse" - } - ] - }, - "expiration_time": { - "type": [ - "integer", - "null" - ], - "format": "int64" - }, - "id": { - "type": "integer", - "format": "int32" - }, - "last_renewed": { - "type": [ - "integer", - "null" - ], - "format": "int64" - }, - "message": { - "type": [ - "string", - "null" - ] - }, - "project_id": { - "type": "integer", - "format": "int32" - }, - "redirect_to": { - "type": [ - "string", - "null" - ] - }, - "service_name": { - "type": [ - "string", - "null" - ], - "description": "Docker Compose service name this domain routes to" - }, - "status": { - "type": "string" - }, - "status_code": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "updated_at": { - "type": "integer", - "format": "int64" - } - } - }, - "CustomerMovementResponse": { - "type": "object", - "required": [ - "bucket", - "new_customers", - "churned_customers" - ], - "properties": { - "bucket": { - "type": "string", - "format": "date-time" - }, - "churned_customers": { - "type": "integer", - "format": "int64" - }, - "new_customers": { - "type": "integer", - "format": "int64" - } - } - }, - "DashboardLayout": { - "type": "object", - "description": "The typed layout persisted (as JSONB) in `metric_dashboards.layout`.", - "required": [ - "sections" - ], - "properties": { - "sections": { - "type": "array", - "items": { - "$ref": "#/components/schemas/DashboardSection" - }, - "description": "Ordered sections that make up the dashboard." - } - } - }, - "DashboardProjectsAnalyticsQuery": { - "type": "object", - "description": "Query parameters for batch dashboard analytics", - "required": [ - "project_ids", - "start_date", - "end_date" - ], - "properties": { - "end_date": { - "type": "string", - "format": "date-time", - "description": "End date for the query range" - }, - "project_ids": { - "type": "string", - "description": "Comma-separated list of project IDs" - }, - "start_date": { - "type": "string", - "format": "date-time", - "description": "Start date for the query range" - } - } - }, - "DashboardProjectsAnalyticsResponse": { - "type": "object", - "description": "Batch response for dashboard project analytics", - "required": [ - "projects" - ], - "properties": { - "projects": { - "type": "object", - "description": "Map of project_id -> analytics data", - "additionalProperties": { - "$ref": "#/components/schemas/ProjectDashboardAnalytics" - }, - "propertyNames": { - "type": "string" - } - } - } - }, - "DashboardSection": { - "type": "object", - "description": "A titled group of tiles within a dashboard.", - "required": [ - "id", - "title", - "tiles" - ], - "properties": { - "id": { - "type": "string", - "description": "Stable client-generated section id." - }, - "tiles": { - "type": "array", - "items": { - "$ref": "#/components/schemas/DashboardTile" - }, - "description": "Tiles rendered within this section." - }, - "title": { - "type": "string", - "description": "Section heading." - } - } - }, - "DashboardTile": { - "type": "object", - "description": "A single metric tile within a dashboard section.", - "required": [ - "id", - "metric_name", - "aggregation" - ], - "properties": { - "aggregation": { - "type": "string", - "description": "Aggregation applied per bucket: one of\n`avg|sum|min|max|count|rate|p50|p90|p95|p99`." - }, - "group_by": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Label keys to break the metric down by (group-by / multi-series view).\nEmpty = single aggregated series (current behavior). Max 2 keys \u2014 more\ndimensions are unreadable in a chart (ADR-026 Phase 2). Each key must\nmatch `[a-zA-Z0-9_.:-]`. Wired directly to `MetricQuery.group_by` by\nthe tile query path (separate frontend task)." - }, - "id": { - "type": "string", - "description": "Stable client-generated tile id (used as a React key / for reordering)." - }, - "label_filters": { - "type": "array", - "items": { - "type": "array", - "items": false, - "prefixItems": [ - { - "type": "string" - }, - { - "type": "string" - } - ] - }, - "description": "AND-combined label equality filters: `[[\"key\",\"value\"],\u2026]`. Empty = no\nfiltering. Max 10 pairs; keys must match `[a-zA-Z0-9_.:-]`; values\ncapped at 500 characters. Not yet wired into the tile query path\n(Phase 1 ADR-026 \u2014 field round-trips and validates; query wiring is\na separate frontend task)." - }, - "metric_name": { - "type": "string", - "description": "The metric name to chart (e.g. `http.server.duration`)." - }, - "title": { - "type": [ - "string", - "null" - ], - "description": "Optional display title; falls back to the metric name in the UI." - } - } - }, - "DataImplication": { - "type": "object", - "description": "A specific data implication the user needs to understand", - "required": [ - "severity", - "message" - ], - "properties": { - "message": { - "type": "string", - "description": "Human-readable description of what could happen" - }, - "recommended_action": { - "type": [ - "string", - "null" - ], - "description": "What the user should do about it (if anything)" - }, - "severity": { - "$ref": "#/components/schemas/DataImplicationSeverity", - "description": "Severity of this implication" - } - } - }, - "DataImplicationSeverity": { - "type": "string", - "description": "Severity of a data implication", - "enum": [ - "info", - "warning", - "data-not-migrated", - "potential-data-loss" - ] - }, - "DatabaseMetricsResponse": { - "type": "object", - "description": "Response for the per-database metrics breakdown.", - "required": [ - "databases" - ], - "properties": { - "databases": { - "type": "array", - "items": { - "$ref": "#/components/schemas/DatabaseMetricsRow" - }, - "description": "One entry per database, sorted by the first metric descending\n(largest first) so the biggest database leads the table." - } - } - }, - "DatabaseMetricsRow": { - "type": "object", - "description": "Per-database metric values for a Postgres service.\n\nA Postgres instance can host many databases (some unrelated to this\nservice). The collector records per-`datname` series; this groups the\nlatest value of each requested metric by database so the UI can render a\n\"Databases\" breakdown table instead of one collapsed number.", - "required": [ - "database", - "metrics" - ], - "properties": { - "database": { - "type": "string", - "description": "Database name (`datname`)." - }, - "metrics": { - "type": "object", - "description": "Latest value of each requested metric for this database\n(e.g. `{\"pg.database_size_bytes\": 7943871, \"pg.cache_hit_ratio\": 0.99}`).", - "additionalProperties": { - "type": "number", - "format": "double" - }, - "propertyNames": { - "type": "string" - } - } - } - }, - "DelRequest": { - "type": "object", - "description": "Request to delete keys", - "required": [ - "keys" - ], - "properties": { - "keys": { - "type": "array", - "items": { - "type": "string" - }, - "description": "The key(s) to delete", - "example": [ - "user:123", - "user:456" - ] - }, - "project_id": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Project ID (required for API key/session auth, optional for deployment tokens)", - "example": 1 - } - } - }, - "DelResponse": { - "type": "object", - "description": "Response for delete operation", - "required": [ - "deleted" - ], - "properties": { - "deleted": { - "type": "integer", - "format": "int64", - "description": "Number of keys deleted", - "example": 2 - } - } - }, - "DeleteBlobRequest": { - "type": "object", - "description": "Request to delete blobs", - "required": [ - "pathnames" - ], - "properties": { - "pathnames": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Pathnames to delete (relative to project)", - "example": [ - "images/avatar.png", - "documents/file.pdf" - ] - }, - "projectId": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Project ID (required for API key/session auth, optional for deployment tokens)", - "example": 1 - } - } - }, - "DeleteBlobResponse": { - "type": "object", - "description": "Response after deleting blobs", - "required": [ - "deleted" - ], - "properties": { - "deleted": { - "type": "integer", - "format": "int64", - "description": "Number of blobs deleted", - "example": 2 - } - } - }, - "DeleteResponse": { - "type": "object", - "required": [ - "deleted" - ], - "properties": { - "deleted": { - "type": "integer", - "format": "int64", - "minimum": 0 - } - } - }, - "DeployFromImageRequest": { - "type": "object", - "properties": { - "external_image_id": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "External image ID (if already registered). If provided without image_ref,\nthe image reference will be fetched from the registered external image." - }, - "health_check_path": { - "type": [ - "string", - "null" - ], - "description": "Optional HTTP health-check path override (e.g. \"/api/healthz\").\nImage deploys can't read `.temps.yaml`, so this sets the path the deployer\nprobes after the container starts and the path the environment's uptime\nmonitor checks. Must start with '/'. When omitted, defaults to \"/\".", - "example": "/api/healthz" - }, - "image_ref": { - "type": [ - "string", - "null" - ], - "description": "Docker image reference (e.g., \"ghcr.io/org/app:v1.0\")\nRequired if external_image_id is not provided", - "example": "ghcr.io/myorg/myapp:v1.0" - }, - "metadata": { - "description": "Optional deployment metadata" - } - } - }, - "DeployFromImageUploadQuery": { - "type": "object", - "description": "Query parameters for deploying from an uploaded image tarball", - "properties": { - "health_check_path": { - "type": [ - "string", - "null" - ], - "description": "Optional HTTP health-check path override (e.g. \"/api/healthz\").\nMust start with '/'. When omitted, defaults to \"/\".", - "example": "/api/healthz" - }, - "tag": { - "type": [ - "string", - "null" - ], - "description": "Tag to apply to the imported image (e.g., \"myapp:v1.0\")\nIf not provided, a unique tag will be generated", - "example": "myapp:v1.0" - } - } - }, - "DeployFromStaticRequest": { - "type": "object", - "required": [ - "static_bundle_id" - ], - "properties": { - "health_check_path": { - "type": [ - "string", - "null" - ], - "description": "Optional HTTP health-check path override (e.g. \"/api/healthz\").\nStatic deploys can't read `.temps.yaml`, so this sets the path the deployer\nprobes after the container starts and the path the environment's uptime\nmonitor checks. Must start with '/'. When omitted, defaults to \"/\".", - "example": "/api/healthz" - }, - "metadata": { - "description": "Optional deployment metadata" - }, - "static_bundle_id": { - "type": "integer", - "format": "int32", - "description": "Static bundle ID (required)" - } - } - }, - "DeploymentConfig": { - "type": "object", - "description": "Deployment configuration shared between projects and environments\n\nThis configuration can be set at the project level (as defaults) and\noverridden at the environment level for specific deployments.\n\nNote: Environment variables are managed separately and are not part of this config.", - "properties": { - "antiAffinity": { - "type": "boolean", - "description": "Anti-affinity: spread replicas across different nodes.\n\nWhen enabled, the scheduler avoids placing two replicas of the same\nenvironment on the same node. If there are fewer eligible nodes than\nreplicas, remaining replicas wrap around (best-effort spreading).\n\nDefaults to `true` \u2014 replicas spread by default." - }, - "automaticDeploy": { - "type": [ - "boolean", - "null" - ], - "description": "Enable automatic deployments on git push.\n`None` = inherit from project config; `Some(true/false)` = explicit override.\nStored as JSONB so absent key \u2192 `None` (inherit), never silently defaults to false." - }, - "containerExecEnabled": { - "type": "boolean", - "description": "Enable container exec/shell access (disabled by default for security)" - }, - "cpuLimit": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "CPU limit in microcores, where 1_000_000 = 1 full CPU core\n(e.g., 2_000_000 = 2 CPUs). NOT millicores. `None` = uncapped." - }, - "cpuRequest": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "CPU request in microcores, where 1_000_000 = 1 full CPU core\n(e.g., 100_000 = 0.1 CPU, 500_000 = 0.5 CPU, 2_000_000 = 2 CPUs).\nNOT millicores \u2014 the deployer formats this as `{n}u` and converts\n`n / 1_000_000` cores into Docker nano_cpus." - }, - "crossArchitectureBuilds": { - "type": [ - "boolean", - "null" - ], - "description": "Build one image per architecture the eligible nodes run.\n\n`None`/`false` (the default) builds exactly once, on the control\nplane's native platform \u2014 byte-for-byte the behaviour of a\nsingle-architecture cluster. When enabled and the nodes this\ndeployment could land on span more than one architecture, the build\njob produces one image per architecture; the non-native ones go\nthrough the daemon's `platform` option, which requires QEMU binfmt\nhandlers registered on the control plane.\n\n**Opt-in on purpose.** Cross-architecture builds are emulated and\nsubstantially slower, and deriving them from cluster topology would\nmean a single node joining silently changes build behaviour for every\ndeployment in the cluster. It also keeps the decision on operator\nconfig rather than on a value each node reports about itself.\n\n`Option` so an environment inherits the project's setting\n(`None`) or overrides it, matching `automatic_deploy`." - }, - "exposedPort": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Port exposed by the container\nIf not specified, will be auto-detected from Docker image or default to 3000" - }, - "idleTimeoutSeconds": { - "type": "integer", - "format": "int32", - "description": "Seconds of inactivity before containers are stopped in on-demand mode.\nOnly used when `on_demand` is true. Min: 60, Max: 86400 (24h).\nDefault: 300 (5 minutes)." - }, - "memoryLimit": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Memory limit in megabytes. Three-state semantics:\n- `None` \u2192 inherit the parent layer (env inherits project, project\n inherits the seeded default); used by the settings UI's \"Use default\".\n- `Some(0)` \u2192 explicit **uncapped**: stop inheriting and run with no\n memory limit. This is the deliberate escape hatch for dedicated\n workloads, distinct from `None`.\n- `Some(n)` \u2192 hard cap of `n` MB.\n\n`merge`/resolution keep `Some(0)` as a present value (it wins precedence\nover a parent cap), and the deployer collapses it to \"no limit\" before\ntalking to Docker." - }, - "memoryRequest": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Memory request in megabytes (e.g., 128 = 128MB)" - }, - "onDemand": { - "type": "boolean", - "description": "Enable on-demand mode (scale-to-zero).\nWhen enabled, containers are stopped after `idle_timeout_seconds` of no traffic\nand automatically started when a new request arrives." - }, - "performanceMetricsEnabled": { - "type": "boolean", - "description": "Enable performance metrics collection (speed insights)" - }, - "replicas": { - "type": "integer", - "format": "int32", - "description": "Number of replicas/instances to run\nDefaults to 1 replica" - }, - "security": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/SecurityConfig", - "description": "Security configuration (headers, rate limiting, attack mode, etc.)\nThese settings inherit and override from parent level (Environment > Project > Global)" - } - ] - }, - "sessionRecordingEnabled": { - "type": "boolean", - "description": "Enable session recording for analytics" - }, - "targetLabels": { - "description": "Label selector for node-based scheduling. Replicas are only deployed to\nnodes whose labels match the selector.\n\nMatching rules:\n- **Same key, array value** \u2192 OR: node must match any value\n- **Different keys** \u2192 AND: node must satisfy all keys\n\nExample: `{\"region\": [\"us\", \"asia\"], \"gpu\": \"true\"}`\n\u2192 (region=us OR region=asia) AND gpu=true\n\nApplied after `target_nodes` filtering (they stack)." - }, - "targetNodes": { - "type": [ - "array", - "null" - ], - "items": { - "type": "integer", - "format": "int32" - }, - "description": "Optional list of node IDs to deploy to. When set, replicas are distributed\nonly across these nodes (round-robin). When None, the scheduler distributes\nacross all active nodes (or deploys locally if no nodes exist)." - }, - "wakeTimeoutSeconds": { - "type": "integer", - "format": "int32", - "description": "Max seconds to wait for containers to start when waking from on-demand sleep.\nRequests return 503 if exceeded. Default: 30." - } - } - }, - "DeploymentConfigSnapshot": { - "type": "object", - "description": "Deployment configuration snapshot for deployments\n\nThis extends DeploymentConfig with environment variables to capture\nthe complete state of a deployment at the time it was created.", - "properties": { - "automaticDeploy": { - "type": "boolean", - "description": "Enable automatic deployments on git push" - }, - "containerExecEnabled": { - "type": "boolean", - "description": "Enable container exec/shell access" - }, - "cpuLimit": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "CPU limit in millicores" - }, - "cpuRequest": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "CPU request in millicores" - }, - "environmentVariables": { - "type": "object", - "description": "Environment variables used for this deployment", - "additionalProperties": { - "type": "string" - }, - "propertyNames": { - "type": "string" - } - }, - "exposedPort": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Port exposed by the container" - }, - "memoryLimit": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Memory limit in megabytes" - }, - "memoryRequest": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Memory request in megabytes" - }, - "performanceMetricsEnabled": { - "type": "boolean", - "description": "Enable performance metrics collection" - }, - "replicas": { - "type": "integer", - "format": "int32", - "description": "Number of replicas" - }, - "sessionRecordingEnabled": { - "type": "boolean", - "description": "Enable session recording" - } - } - }, - "DeploymentConfiguration": { - "type": "object", - "description": "Deployment-level configuration", - "required": [ - "image", - "strategy", - "env_vars", - "ports", - "volumes", - "network", - "resources" - ], - "properties": { - "build": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/BuildConfiguration", - "description": "Build configuration (if building from source)" - } - ] - }, - "command": { - "type": [ - "array", - "null" - ], - "items": { - "type": "string" - }, - "description": "Command override" - }, - "entrypoint": { - "type": [ - "array", - "null" - ], - "items": { - "type": "string" - }, - "description": "Entrypoint override" - }, - "env_vars": { - "type": "array", - "items": { - "$ref": "#/components/schemas/EnvironmentVariable" - }, - "description": "Environment variables" - }, - "git": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/GitSourcePlan", - "description": "Where the application's source code lives, when the source platform\nbuilds from a git repository. Execution uses this to link the temps\nproject to the same repository so the real deployment pipeline can\nclone and build it." - } - ] - }, - "health_check": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/HealthCheckConfiguration", - "description": "Health check configuration" - } - ] - }, - "image": { - "type": "string", - "description": "Image to deploy" - }, - "network": { - "$ref": "#/components/schemas/NetworkConfiguration", - "description": "Network configuration" - }, - "ports": { - "type": "array", - "items": { - "$ref": "#/components/schemas/PortMapping" - }, - "description": "Port mappings" - }, - "resources": { - "$ref": "#/components/schemas/ResourceLimits", - "description": "Resource limits" - }, - "strategy": { - "$ref": "#/components/schemas/DeploymentStrategy", - "description": "Deployment strategy" - }, - "volumes": { - "type": "array", - "items": { - "$ref": "#/components/schemas/VolumeMount" - }, - "description": "Volume mounts" - }, - "working_dir": { - "type": [ - "string", - "null" - ], - "description": "Working directory" - } - } - }, - "DeploymentContainerLogContentResponse": { - "type": "object", - "description": "A single captured container-log dump, including its full text content.", - "required": [ - "id", - "container_name", - "size_bytes", - "truncated", - "captured_at", - "content" - ], - "properties": { - "captured_at": { - "type": "integer", - "format": "int64" - }, - "container_name": { - "type": "string" - }, - "content": { - "type": "string", - "description": "The captured plain-text log content." - }, - "id": { - "type": "integer", - "format": "int32" - }, - "service_name": { - "type": [ - "string", - "null" - ] - }, - "size_bytes": { - "type": "integer", - "format": "int64" - }, - "truncated": { - "type": "boolean" - } - } - }, - "DeploymentContainerLogResponse": { - "type": "object", - "description": "Metadata for one captured (historical) container-log dump. Listed on the\ndeployment detail page so a user can pick which past container's logs to read.", - "required": [ - "id", - "deployment_id", - "container_id", - "container_name", - "size_bytes", - "truncated", - "captured_at" - ], - "properties": { - "captured_at": { - "type": "integer", - "format": "int64", - "description": "Unix epoch milliseconds of when the logs were captured (just before\nteardown). Matches the timestamp convention used by `DeploymentResponse`." - }, - "container_id": { - "type": "string" - }, - "container_name": { - "type": "string" - }, - "deployment_id": { - "type": "integer", - "format": "int32" - }, - "id": { - "type": "integer", - "format": "int32" - }, - "node_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "service_name": { - "type": [ - "string", - "null" - ] - }, - "size_bytes": { - "type": "integer", - "format": "int64" - }, - "truncated": { - "type": "boolean" - } - } - }, - "DeploymentContainerLogsListResponse": { - "type": "object", - "description": "The list of captured container-log dumps for a deployment.", - "required": [ - "logs" - ], - "properties": { - "logs": { - "type": "array", - "items": { - "$ref": "#/components/schemas/DeploymentContainerLogResponse" - } - } - } - }, - "DeploymentEnvironmentResponse": { - "type": "object", - "required": [ - "id", - "name", - "slug", - "domains" - ], - "properties": { - "domains": { - "type": "array", - "items": { - "type": "string" - } - }, - "id": { - "type": "integer", - "format": "int32" - }, - "name": { - "type": "string" - }, - "slug": { - "type": "string" - } - } - }, - "DeploymentJobResponse": { - "type": "object", - "required": [ - "id", - "deployment_id", - "job_id", - "job_type", - "name", - "status", - "created_at", - "updated_at", - "log_id" - ], - "properties": { - "created_at": { - "type": "integer", - "format": "int64" - }, - "dependencies": {}, - "deployment_id": { - "type": "integer", - "format": "int32" - }, - "description": { - "type": [ - "string", - "null" - ] - }, - "error_message": { - "type": [ - "string", - "null" - ] - }, - "execution_order": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "finished_at": { - "type": [ - "integer", - "null" - ], - "format": "int64" - }, - "id": { - "type": "integer", - "format": "int32" - }, - "job_config": { - "description": "Internal workflow configuration is intentionally redacted. It can\ncontain legacy plaintext secrets or encrypted secret envelopes." - }, - "job_id": { - "type": "string" - }, - "job_type": { - "type": "string" - }, - "log_id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "outputs": {}, - "started_at": { - "type": [ - "integer", - "null" - ], - "format": "int64" - }, - "status": { - "type": "string" - }, - "updated_at": { - "type": "integer", - "format": "int64" - } - } - }, - "DeploymentJobsResponse": { - "type": "object", - "required": [ - "jobs", - "total" - ], - "properties": { - "jobs": { - "type": "array", - "items": { - "$ref": "#/components/schemas/DeploymentJobResponse" - } - }, - "total": { - "type": "integer", - "minimum": 0 - } - } - }, - "DeploymentListResponse": { - "type": "object", - "required": [ - "deployments", - "total", - "page", - "per_page" - ], - "properties": { - "deployments": { - "type": "array", - "items": { - "$ref": "#/components/schemas/DeploymentResponse" - } - }, - "page": { - "type": "integer", - "format": "int64" - }, - "per_page": { - "type": "integer", - "format": "int64" - }, - "total": { - "type": "integer", - "format": "int64" - } - } - }, - "DeploymentMetadata": { - "type": "object", - "description": "Deployment metadata - typed information about the deployment", - "properties": { - "buildDurationMs": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "description": "Build duration in milliseconds" - }, - "builder": { - "type": [ - "string", - "null" - ], - "description": "Docker builder used (e.g., \"nixpacks\", \"dockerfile\")" - }, - "deploymentDurationMs": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "description": "Deployment duration in milliseconds" - }, - "deploymentSourceType": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/SourceType", - "description": "Source type for THIS specific deployment (for Manual/flexible projects)\nThis allows Manual projects to have deployments via different methods\n(docker_image, static_files, or git) while keeping per-deployment tracking" - } - ] - }, - "dockerfilePath": { - "type": [ - "string", - "null" - ], - "description": "Dockerfile path if using Dockerfile builder" - }, - "externalImageId": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "External image ID (reference to external_images table)" - }, - "externalImageRef": { - "type": [ - "string", - "null" - ], - "description": "External Docker image reference (for docker_image source type)\ne.g., \"ghcr.io/org/app:v1.0\" or \"docker.io/myapp:sha-abc123\"" - }, - "fileCount": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Number of files in the build output" - }, - "gitPushEvent": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/GitPushEvent", - "description": "Git push event that triggered this deployment (if from webhook)" - } - ] - }, - "healthCheckPath": { - "type": [ - "string", - "null" - ], - "description": "Explicit deploy-time HTTP health-check path override.\nImage/static deploys can't read `.temps.yaml`, so this lets the deploy\nrequest set a custom path (e.g. \"/api/healthz\"). When present it takes\npriority over any `.temps.yaml` `health.path` value. Always starts with '/'." - }, - "imageSizeBytes": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "description": "Total size of the built image in bytes" - }, - "imageUploadedLocally": { - "type": "boolean", - "description": "Whether the image was uploaded directly (via docker save/load) rather than pulled from registry\nWhen true, the PullExternalImageJob is skipped since the image is already loaded locally" - }, - "isRollback": { - "type": "boolean", - "description": "Whether this is a rollback deployment" - }, - "labels": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Custom labels/tags for the deployment" - }, - "rolledBackFromId": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "ID of the deployment this was rolled back from (if applicable)" - }, - "staticBundleContentType": { - "type": [ - "string", - "null" - ], - "description": "Static bundle content type (for proper extraction: application/gzip or application/zip)" - }, - "staticBundleId": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Static bundle ID (reference to static_bundles table, for static_files source type)" - }, - "staticBundlePath": { - "type": [ - "string", - "null" - ], - "description": "Static bundle path in blob storage (for static_files source type)" - }, - "uploadedImageId": { - "type": [ - "string", - "null" - ], - "description": "Docker image ID of the locally uploaded image (sha256:...)\nUsed to verify the image exists before deployment" - } - } - }, - "DeploymentResponse": { - "type": "object", - "required": [ - "id", - "project_id", - "environment_id", - "environment", - "status", - "url", - "created_at", - "is_current" - ], - "properties": { - "branch": { - "type": [ - "string", - "null" - ] - }, - "cancelled_reason": { - "type": [ - "string", - "null" - ] - }, - "commit_author": { - "type": [ - "string", - "null" - ] - }, - "commit_date": { - "type": [ - "integer", - "null" - ], - "format": "int64" - }, - "commit_hash": { - "type": [ - "string", - "null" - ] - }, - "commit_message": { - "type": [ - "string", - "null" - ] - }, - "created_at": { - "type": "integer", - "format": "int64" - }, - "deployment_config": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/DeploymentConfigSnapshot", - "description": "Deployment configuration snapshot (CPU, memory, replicas, environment variables, etc.)" - } - ] - }, - "environment": { - "$ref": "#/components/schemas/DeploymentEnvironmentResponse" - }, - "environment_id": { - "type": "integer", - "format": "int32" - }, - "finished_at": { - "type": [ - "integer", - "null" - ], - "format": "int64" - }, - "id": { - "type": "integer", - "format": "int32" - }, - "is_current": { - "type": "boolean" - }, - "metadata": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/DeploymentMetadata", - "description": "Deployment metadata (build info, git event, etc.)" - } - ] - }, - "project_id": { - "type": "integer", - "format": "int32" - }, - "screenshot_location": { - "type": [ - "string", - "null" - ] - }, - "started_at": { - "type": [ - "integer", - "null" - ], - "format": "int64" - }, - "status": { - "type": "string" - }, - "tag": { - "type": [ - "string", - "null" - ] - }, - "url": { - "type": "string" - } - } - }, - "DeploymentStateResponse": { - "type": "object", - "required": [ - "id", - "state", - "message" - ], - "properties": { - "id": { - "type": "integer", - "format": "int32" - }, - "message": { - "type": "string" - }, - "state": { - "type": "string" - } - } - }, - "DeploymentStrategy": { - "type": "string", - "description": "Deployment strategy", - "enum": [ - "replace", - "blue-green", - "rolling" - ] - }, - "DeploymentTokenListResponse": { - "type": "object", - "required": [ - "tokens", - "total" - ], - "properties": { - "tokens": { - "type": "array", - "items": { - "$ref": "#/components/schemas/DeploymentTokenResponse" - } - }, - "total": { - "type": "integer", - "format": "int64", - "minimum": 0 - } - } - }, - "DeploymentTokenResponse": { - "type": "object", - "required": [ - "id", - "project_id", - "name", - "token_prefix", - "is_active", - "created_at" - ], - "properties": { - "created_at": { - "type": "string", - "format": "date-time", - "example": "2024-01-01T00:00:00Z" - }, - "created_by": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "deployment_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "environment_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "expires_at": { - "type": [ - "string", - "null" - ], - "format": "date-time", - "example": "2024-12-31T23:59:59Z" - }, - "id": { - "type": "integer", - "format": "int32" - }, - "is_active": { - "type": "boolean" - }, - "last_used_at": { - "type": [ - "string", - "null" - ], - "format": "date-time", - "example": "2024-01-01T00:00:00Z" - }, - "name": { - "type": "string" - }, - "permissions": { - "type": [ - "array", - "null" - ], - "items": { - "type": "string" - } - }, - "project_id": { - "type": "integer", - "format": "int32" - }, - "token_prefix": { - "type": "string" - } - } - }, - "DetectionConfig": { - "oneOf": [ - { - "allOf": [ - { - "$ref": "#/components/schemas/StaticParams", - "description": "v0 (shipping): static threshold comparison of the aggregated value." - }, - { - "type": "object", - "required": [ - "kind" - ], - "properties": { - "kind": { - "type": "string", - "enum": [ - "static" - ] - } - } - } - ], - "description": "v0 (shipping): static threshold comparison of the aggregated value." - }, - { - "allOf": [ - { - "$ref": "#/components/schemas/AnomalyParams", - "description": "Seasonal anomaly band (basic/agile/robust/ewma share this variant \u2014 the\nalgorithm is a field, not a new kind). Creation rejected until evaluated." - }, - { - "type": "object", - "required": [ - "kind" - ], - "properties": { - "kind": { - "type": "string", - "enum": [ - "anomaly" - ] - } - } - } - ], - "description": "Seasonal anomaly band (basic/agile/robust/ewma share this variant \u2014 the\nalgorithm is a field, not a new kind). Creation rejected until evaluated." - }, - { - "allOf": [ - { - "$ref": "#/components/schemas/ForecastParams", - "description": "Predict a future threshold breach (capacity planning). Stub." - }, - { - "type": "object", - "required": [ - "kind" - ], - "properties": { - "kind": { - "type": "string", - "enum": [ - "forecast" - ] - } - } - } - ], - "description": "Predict a future threshold breach (capacity planning). Stub." - }, - { - "allOf": [ - { - "$ref": "#/components/schemas/OutlierParams", - "description": "Cross-series population outlier (one host misbehaving vs its peers). Stub." - }, - { - "type": "object", - "required": [ - "kind" - ], - "properties": { - "kind": { - "type": "string", - "enum": [ - "outlier" - ] - } - } - } - ], - "description": "Cross-series population outlier (one host misbehaving vs its peers). Stub." - }, - { - "allOf": [ - { - "$ref": "#/components/schemas/AutoWatchParams", - "description": "Watchdog-style self-tuning auto-watch (engine picks bounds). Stub." - }, - { - "type": "object", - "required": [ - "kind" - ], - "properties": { - "kind": { - "type": "string", - "enum": [ - "auto_watch" - ] - } - } - } - ], - "description": "Watchdog-style self-tuning auto-watch (engine picks bounds). Stub." - } - ], - "description": "The typed detector definition stored (as jsonb) in\n`metric_alert_rules.detection_config`.\n\nToday only [`DetectionConfig::Static`] is evaluable; the other variants are\nschema-present (so the SDK/UI and storage are already future-shaped) but\nrejected by [`DetectionConfig::validate`] until their evaluator lands. Each is\nthen enabled code-only, with no schema migration." - }, - "DeviceCount": { - "type": "object", - "required": [ - "device_type", - "count", - "percentage" - ], - "properties": { - "count": { - "type": "integer", - "format": "int64" - }, - "device_type": { - "type": "string" - }, - "percentage": { - "type": "number", - "format": "double" - } - } - }, - "DigestSections": { - "type": "object", - "description": "Sections that can be included in the weekly digest\nNote: `#[serde(default)]` allows backward compatibility when deserializing\nold data that may have `security` and `resources` fields instead of `projects`", - "properties": { - "deployments": { - "type": "boolean", - "default": true - }, - "errors": { - "type": "boolean", - "default": true - }, - "funnels": { - "type": "boolean", - "default": true - }, - "performance": { - "type": "boolean", - "default": true - }, - "projects": { - "type": "boolean", - "default": true - } - } - }, - "Direction": { - "type": "string", - "description": "Which side(s) of an anomaly band count as a deviation.", - "enum": [ - "both", - "above", - "below" - ] - }, - "DisableBlobResponse": { - "type": "object", - "description": "Response after disabling Blob service", - "required": [ - "success", - "message" - ], - "properties": { - "message": { - "type": "string", - "description": "Human-readable message", - "example": "Blob service disabled successfully" - }, - "success": { - "type": "boolean", - "description": "Whether the operation succeeded", - "example": true - } - } - }, - "DisableKvResponse": { - "type": "object", - "description": "Response after disabling KV service", - "required": [ - "success", - "message" - ], - "properties": { - "message": { - "type": "string", - "description": "Status message", - "example": "KV service disabled successfully" - }, - "success": { - "type": "boolean", - "description": "Whether the service was successfully disabled" - } - } - }, - "DisableMfaRequest": { - "type": "object", - "required": [ - "code" - ], - "properties": { - "code": { - "type": "string" - } - } - }, - "DiscoverRequest": { - "type": "object", - "description": "Request to discover workloads", - "required": [ - "source" - ], - "properties": { - "credentials": { - "$ref": "#/components/schemas/ImportCredentials", - "description": "Platform credentials (required for cloud platforms like Vercel, Railway)" - }, - "selector": { - "$ref": "#/components/schemas/ImportSelector", - "description": "Optional selector to filter workloads" - }, - "source": { - "$ref": "#/components/schemas/ImportSource", - "description": "Source to discover from" - } - } - }, - "DiscoverResponse": { - "type": "object", - "description": "Response with discovered workloads", - "required": [ - "workloads" - ], - "properties": { - "workloads": { - "type": "array", - "items": { - "$ref": "#/components/schemas/WorkloadDescriptor" - }, - "description": "Discovered workloads" - } - } - }, - "DiskInfo": { - "type": "object", - "description": "Disk space information for a single disk/partition", - "required": [ - "mount_point", - "total_bytes", - "used_bytes", - "available_bytes", - "usage_percent", - "file_system" - ], - "properties": { - "available_bytes": { - "type": "integer", - "format": "int64", - "description": "Available space in bytes", - "minimum": 0 - }, - "file_system": { - "type": "string", - "description": "File system type (e.g., \"ext4\", \"apfs\")" - }, - "mount_point": { - "type": "string", - "description": "Mount point of the disk" - }, - "total_bytes": { - "type": "integer", - "format": "int64", - "description": "Total space in bytes", - "minimum": 0 - }, - "usage_percent": { - "type": "number", - "format": "double", - "description": "Usage percentage (0-100)" - }, - "used_bytes": { - "type": "integer", - "format": "int64", - "description": "Used space in bytes", - "minimum": 0 - } - } - }, - "DiskSpaceAlert": { - "type": "object", - "description": "Alert for a disk that exceeds the threshold", - "required": [ - "mount_point", - "usage_percent", - "threshold_percent", - "available_bytes", - "available_human" - ], - "properties": { - "available_bytes": { - "type": "integer", - "format": "int64", - "description": "Available space in bytes", - "minimum": 0 - }, - "available_human": { - "type": "string", - "description": "Human-readable available space" - }, - "mount_point": { - "type": "string", - "description": "Mount point of the disk" - }, - "threshold_percent": { - "type": "integer", - "format": "int32", - "description": "Configured threshold percentage", - "minimum": 0 - }, - "usage_percent": { - "type": "number", - "format": "double", - "description": "Current usage percentage" - } - } - }, - "DiskSpaceAlertSettings": { - "type": "object", - "description": "Disk space alert settings for monitoring disk usage", - "properties": { - "check_interval_seconds": { - "type": "integer", - "format": "int64", - "description": "Interval in seconds between disk space checks", - "default": 300, - "example": 300, - "minimum": 60 - }, - "enabled": { - "type": "boolean", - "description": "Whether disk space alerts are enabled", - "default": true - }, - "monitor_path": { - "type": [ - "string", - "null" - ], - "description": "Restrict monitoring to the disk backing this path. When unset (the\ndefault), every mounted writable volume is monitored \u2014 including\ndedicated volumes such as `/var/lib/docker`.", - "default": null - }, - "threshold_percent": { - "type": "integer", - "format": "int32", - "description": "Threshold percentage (0-100) at which to trigger alerts", - "default": 80, - "example": 80, - "maximum": 100, - "minimum": 0 - } - } - }, - "DiskSpaceCheckResult": { - "type": "object", - "description": "Result of a disk space check", - "required": [ - "checked_at", - "enabled", - "threshold_percent", - "disks", - "alerts" - ], - "properties": { - "alerts": { - "type": "array", - "items": { - "$ref": "#/components/schemas/DiskSpaceAlert" - }, - "description": "Disks that meet or exceed the threshold" - }, - "checked_at": { - "type": "string", - "format": "date-time", - "description": "Timestamp of the check (ISO 8601, UTC)", - "example": "2026-05-28T12:15:47.609192Z" - }, - "disks": { - "type": "array", - "items": { - "$ref": "#/components/schemas/DiskInfo" - }, - "description": "List of all monitored disks" - }, - "enabled": { - "type": "boolean", - "description": "Whether disk space monitoring is enabled in settings" - }, - "threshold_percent": { - "type": "integer", - "format": "int32", - "description": "Configured alert threshold percentage (0-100)", - "minimum": 0 - } - } - }, - "DnsAckRequest": { - "type": "object", - "required": [ - "applied_generation" - ], - "properties": { - "applied_generation": { - "type": "integer", - "format": "int64", - "description": "Highest generation the agent has actually applied locally." - } - } - }, - "DnsAckResponse": { - "type": "object", - "required": [ - "node_id", - "applied_generation", - "server_generation" - ], - "properties": { - "applied_generation": { - "type": "integer", - "format": "int64" - }, - "node_id": { - "type": "integer", - "format": "int32" - }, - "server_generation": { - "type": "integer", - "format": "int64" - } - } - }, - "DnsChallengeRecordResult": { - "type": "object", - "description": "Result of a single DNS TXT record creation for ACME challenge", - "required": [ - "name", - "value", - "success", - "message" - ], - "properties": { - "message": { - "type": "string", - "description": "Human-readable message about the operation" - }, - "name": { - "type": "string", - "description": "TXT record name (e.g., \"_acme-challenge.example.com\")", - "example": "_acme-challenge.example.com" - }, - "success": { - "type": "boolean", - "description": "Whether the record was created successfully" - }, - "value": { - "type": "string", - "description": "TXT record value (the ACME challenge token)", - "example": "abc123..." - } - } - }, - "DnsChangesResponse": { - "type": "object", - "required": [ - "generation", - "full_snapshot", - "records", - "removed_ids" - ], - "properties": { - "full_snapshot": { - "type": "boolean", - "description": "`true` \u21d2 replace the local zone with `records`. `false` \u21d2 merge\n`records` into the existing zone (and remove `removed_ids`)." - }, - "generation": { - "type": "integer", - "format": "int64", - "description": "Highest generation included in this response. Agent ACKs this back." - }, - "records": { - "type": "array", - "items": { - "$ref": "#/components/schemas/EndpointDto" - } - }, - "removed_ids": { - "type": "array", - "items": { - "type": "integer", - "format": "int64" - }, - "description": "IDs the agent should remove from its zone. Always empty in the v1\nprotocol \u2014 the resolver reconciles by name on snapshot mode. Kept\nin the wire format so a future tombstone-based protocol doesn't\nrequire a breaking change." - } - } - }, - "DnsCompletionResponse": { - "type": "object", - "required": [ - "domain", - "status" - ], - "properties": { - "domain": { - "type": "string" - }, - "status": { - "type": "string" - } - } - }, - "DnsLookupError": { - "type": "object", - "description": "Error response for DNS lookup failures", - "required": [ - "error", - "domain" - ], - "properties": { - "domain": { - "type": "string", - "description": "Domain name that failed", - "example": "nonexistent.com" - }, - "error": { - "type": "string", - "description": "Error message", - "example": "DNS lookup failed: domain not found" - } - } - }, - "DnsLookupRequest": { - "type": "object", - "description": "Request to lookup DNS A records for a domain", - "required": [ - "domain" - ], - "properties": { - "domain": { - "type": "string", - "description": "Domain name to lookup", - "example": "example.com" - } - } - }, - "DnsLookupResponse": { - "type": "object", - "description": "Response containing DNS A records", - "required": [ - "domain", - "records", - "count", - "dns_servers" - ], - "properties": { - "count": { - "type": "integer", - "description": "Number of records found", - "example": 1, - "minimum": 0 - }, - "dns_servers": { - "type": "array", - "items": { - "type": "string" - }, - "description": "DNS servers used for the lookup", - "example": [ - "8.8.8.8", - "8.8.4.4" - ] - }, - "domain": { - "type": "string", - "description": "Domain name that was queried", - "example": "example.com" - }, - "records": { - "type": "array", - "items": { - "type": "string" - }, - "description": "List of A record IP addresses", - "example": [ - "93.184.216.34" - ] - } - } - }, - "DnsProviderCredentials": { - "oneOf": [ - { - "type": "object", - "required": [ - "api_token", - "type" - ], - "properties": { - "account_id": { - "type": [ - "string", - "null" - ] - }, - "api_token": { - "type": "string", - "example": "your-api-token" - }, - "type": { - "type": "string", - "enum": [ - "cloudflare" - ] - } - } - }, - { - "type": "object", - "required": [ - "api_user", - "api_key", - "type" - ], - "properties": { - "api_key": { - "type": "string", - "example": "your-api-key" - }, - "api_user": { - "type": "string", - "example": "your-username" - }, - "client_ip": { - "type": [ - "string", - "null" - ] - }, - "sandbox": { - "type": "boolean" - }, - "type": { - "type": "string", - "enum": [ - "namecheap" - ] - } - } - }, - { - "type": "object", - "required": [ - "access_key_id", - "secret_access_key", - "type" - ], - "properties": { - "access_key_id": { - "type": "string", - "example": "AKIAIOSFODNN7EXAMPLE" - }, - "region": { - "type": [ - "string", - "null" - ], - "example": "us-east-1" - }, - "secret_access_key": { - "type": "string", - "example": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY" - }, - "session_token": { - "type": [ - "string", - "null" - ] - }, - "type": { - "type": "string", - "enum": [ - "route53" - ] - } - } - }, - { - "type": "object", - "required": [ - "api_token", - "type" - ], - "properties": { - "api_token": { - "type": "string", - "example": "dop_v1_your-token" - }, - "type": { - "type": "string", - "enum": [ - "digitalocean" - ] - } - } - }, - { - "type": "object", - "required": [ - "service_account_email", - "private_key", - "project_id", - "type" - ], - "properties": { - "private_key": { - "type": "string", - "example": "-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----" - }, - "project_id": { - "type": "string", - "example": "my-gcp-project" - }, - "service_account_email": { - "type": "string", - "example": "dns-admin@myproject.iam.gserviceaccount.com" - }, - "type": { - "type": "string", - "enum": [ - "gcp" - ] - } - } - }, - { - "type": "object", - "required": [ - "tenant_id", - "client_id", - "client_secret", - "subscription_id", - "resource_group", - "type" - ], - "properties": { - "client_id": { - "type": "string", - "example": "00000000-0000-0000-0000-000000000000" - }, - "client_secret": { - "type": "string" - }, - "resource_group": { - "type": "string", - "example": "my-resource-group" - }, - "subscription_id": { - "type": "string", - "example": "00000000-0000-0000-0000-000000000000" - }, - "tenant_id": { - "type": "string", - "example": "00000000-0000-0000-0000-000000000000" - }, - "type": { - "type": "string", - "enum": [ - "azure" - ] - } - } - }, - { - "type": "object", - "description": "Pebble challtestsrv mock DNS (LOCAL DEV/TEST ONLY)", - "required": [ - "management_url", - "type" - ], - "properties": { - "management_url": { - "type": "string", - "example": "http://localhost:8055" - }, - "type": { - "type": "string", - "enum": [ - "pebble" - ] - } - } - } - ], - "description": "DNS provider credentials (API-facing)" - }, - "DnsProviderResponse": { - "type": "object", - "description": "DNS provider response", - "required": [ - "id", - "name", - "provider_type", - "credentials", - "is_active", - "flat_hostnames_supported", - "created_at", - "updated_at" - ], - "properties": { - "created_at": { - "type": "string" - }, - "credentials": { - "description": "Masked credentials for display" - }, - "description": { - "type": [ - "string", - "null" - ] - }, - "flat_hostnames_supported": { - "type": "boolean", - "description": "Whether this provider benefits from the flat hostname mode (e.g. Cloudflare\nUniversal SSL). The UI surfaces/recommends the Flat toggle when true." - }, - "id": { - "type": "integer", - "format": "int32" - }, - "is_active": { - "type": "boolean" - }, - "last_error": { - "type": [ - "string", - "null" - ] - }, - "last_used_at": { - "type": [ - "string", - "null" - ] - }, - "name": { - "type": "string" - }, - "provider_type": { - "type": "string" - }, - "updated_at": { - "type": "string" - } - } - }, - "DnsProviderSettings": { - "type": "object", - "properties": { - "cloudflare_api_key": { - "type": [ - "string", - "null" - ], - "default": null - }, - "provider": { - "type": "string", - "default": "manual" - } - } - }, - "DnsProviderSettingsMasked": { - "type": "object", - "description": "DNS provider settings with masked sensitive fields", - "required": [ - "provider" - ], - "properties": { - "cloudflare_api_key": { - "type": [ - "string", - "null" - ] - }, - "provider": { - "type": "string" - } - } - }, - "DnsProviderType": { - "type": "string", - "description": "Supported DNS provider types", - "enum": [ - "cloudflare", - "namecheap", - "route53", - "digitalocean", - "gcp", - "azure", - "manual", - "pebble" - ] - }, - "DnsRecord": { - "type": "object", - "description": "A DNS record", - "required": [ - "zone", - "name", - "fqdn", - "content", - "ttl" - ], - "properties": { - "content": { - "$ref": "#/components/schemas/DnsRecordContent", - "description": "Record content" - }, - "fqdn": { - "type": "string", - "description": "Fully qualified domain name", - "example": "www.example.com" - }, - "id": { - "type": [ - "string", - "null" - ], - "description": "Provider-specific record ID (if exists)", - "example": "abc123" - }, - "metadata": { - "type": "object", - "description": "Provider-specific metadata", - "additionalProperties": { - "type": "string" - }, - "propertyNames": { - "type": "string" - } - }, - "name": { - "type": "string", - "description": "Record name (without zone, e.g., \"www\" or \"@\" for root)", - "example": "www" - }, - "proxied": { - "type": "boolean", - "description": "Whether this record is proxied (Cloudflare-specific)" - }, - "ttl": { - "type": "integer", - "format": "int32", - "description": "Time to live in seconds", - "example": 300, - "minimum": 0 - }, - "zone": { - "type": "string", - "description": "Zone/domain this record belongs to", - "example": "example.com" - } - } - }, - "DnsRecordChange": { - "type": "object", - "description": "A single DNS record change the Cloudflare sync would make.", - "required": [ - "action", - "name", - "record_type", - "value" - ], - "properties": { - "action": { - "type": "string", - "description": "`\"create\"`, `\"update\"`, or `\"delete\"`." - }, - "name": { - "type": "string" - }, - "record_type": { - "type": "string", - "description": "Record type, e.g. `\"A\"` or `\"CNAME\"`." - }, - "value": { - "type": "string" - } - } - }, - "DnsRecordContent": { - "oneOf": [ - { - "type": "object", - "description": "A record - IPv4 address (as string, e.g., \"192.0.2.1\")", - "required": [ - "value", - "type" - ], - "properties": { - "type": { - "type": "string", - "enum": [ - "A" - ] - }, - "value": { - "type": "object", - "description": "A record - IPv4 address (as string, e.g., \"192.0.2.1\")", - "required": [ - "address" - ], - "properties": { - "address": { - "type": "string", - "example": "192.0.2.1" - } - } - } - } - }, - { - "type": "object", - "description": "AAAA record - IPv6 address (as string, e.g., \"2001:db8::1\")", - "required": [ - "value", - "type" - ], - "properties": { - "type": { - "type": "string", - "enum": [ - "AAAA" - ] - }, - "value": { - "type": "object", - "description": "AAAA record - IPv6 address (as string, e.g., \"2001:db8::1\")", - "required": [ - "address" - ], - "properties": { - "address": { - "type": "string", - "example": "2001:db8::1" - } - } - } - } - }, - { - "type": "object", - "description": "CNAME record - canonical name", - "required": [ - "value", - "type" - ], - "properties": { - "type": { - "type": "string", - "enum": [ - "CNAME" - ] - }, - "value": { - "type": "object", - "description": "CNAME record - canonical name", - "required": [ - "target" - ], - "properties": { - "target": { - "type": "string" - } - } - } - } - }, - { - "type": "object", - "description": "TXT record - text content", - "required": [ - "value", - "type" - ], - "properties": { - "type": { - "type": "string", - "enum": [ - "TXT" - ] - }, - "value": { - "type": "object", - "description": "TXT record - text content", - "required": [ - "content" - ], - "properties": { - "content": { - "type": "string" - } - } - } - } - }, - { - "type": "object", - "description": "MX record - mail exchange", - "required": [ - "value", - "type" - ], - "properties": { - "type": { - "type": "string", - "enum": [ - "MX" - ] - }, - "value": { - "type": "object", - "description": "MX record - mail exchange", - "required": [ - "priority", - "target" - ], - "properties": { - "priority": { - "type": "integer", - "format": "int32", - "minimum": 0 - }, - "target": { - "type": "string" - } - } - } - } - }, - { - "type": "object", - "description": "NS record - nameserver", - "required": [ - "value", - "type" - ], - "properties": { - "type": { - "type": "string", - "enum": [ - "NS" - ] - }, - "value": { - "type": "object", - "description": "NS record - nameserver", - "required": [ - "nameserver" - ], - "properties": { - "nameserver": { - "type": "string" - } - } - } - } - }, - { - "type": "object", - "description": "SRV record - service", - "required": [ - "value", - "type" - ], - "properties": { - "type": { - "type": "string", - "enum": [ - "SRV" - ] - }, - "value": { - "type": "object", - "description": "SRV record - service", - "required": [ - "priority", - "weight", - "port", - "target" - ], - "properties": { - "port": { - "type": "integer", - "format": "int32", - "minimum": 0 - }, - "priority": { - "type": "integer", - "format": "int32", - "minimum": 0 - }, - "target": { - "type": "string" - }, - "weight": { - "type": "integer", - "format": "int32", - "minimum": 0 - } - } - } - } - }, - { - "type": "object", - "description": "CAA record - certification authority authorization", - "required": [ - "value", - "type" - ], - "properties": { - "type": { - "type": "string", - "enum": [ - "CAA" - ] - }, - "value": { - "type": "object", - "description": "CAA record - certification authority authorization", - "required": [ - "flags", - "tag", - "value" - ], - "properties": { - "flags": { - "type": "integer", - "format": "int32", - "minimum": 0 - }, - "tag": { - "type": "string" - }, - "value": { - "type": "string" - } - } - } - } - }, - { - "type": "object", - "description": "PTR record - pointer", - "required": [ - "value", - "type" - ], - "properties": { - "type": { - "type": "string", - "enum": [ - "PTR" - ] - }, - "value": { - "type": "object", - "description": "PTR record - pointer", - "required": [ - "target" - ], - "properties": { - "target": { - "type": "string" - } - } - } - } - } - ], - "description": "DNS record content - varies by record type" - }, - "DnsRecordResponse": { - "type": "object", - "required": [ - "record_type", - "name", - "value", - "status" - ], - "properties": { - "name": { - "type": "string", - "description": "DNS record name (host)", - "example": "temps._domainkey.example.com" - }, - "priority": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Priority (for MX records)", - "example": "10", - "minimum": 0 - }, - "record_type": { - "type": "string", - "description": "Record type: TXT, CNAME, MX", - "example": "TXT" - }, - "status": { - "$ref": "#/components/schemas/DnsRecordStatusResponse", - "description": "Verification status: unknown, verified, pending, failed" - }, - "value": { - "type": "string", - "description": "DNS record value", - "example": "v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3..." - } - } - }, - "DnsRecordSetupResult": { - "type": "object", - "description": "Result of a single DNS record creation", - "required": [ - "record_type", - "name", - "success", - "automatic", - "message" - ], - "properties": { - "automatic": { - "type": "boolean", - "description": "Whether the operation was automatic or manual" - }, - "message": { - "type": "string", - "description": "Human-readable message" - }, - "name": { - "type": "string", - "description": "Record name" - }, - "record_type": { - "type": "string", - "description": "Record type (TXT, CNAME, MX)" - }, - "success": { - "type": "boolean", - "description": "Whether the record was created successfully" - } - } - }, - "DnsRecordStatusResponse": { - "type": "string", - "description": "DNS record verification status", - "enum": [ - "unknown", - "verified", - "pending", - "failed" - ] - }, - "DnsZone": { - "type": "object", - "description": "A DNS zone (domain managed by the provider)", - "required": [ - "id", - "name", - "status", - "nameservers" - ], - "properties": { - "id": { - "type": "string", - "description": "Provider-specific zone ID", - "example": "zone123" - }, - "metadata": { - "type": "object", - "description": "Provider-specific metadata", - "additionalProperties": { - "type": "string" - }, - "propertyNames": { - "type": "string" - } - }, - "name": { - "type": "string", - "description": "Zone name (domain)", - "example": "example.com" - }, - "nameservers": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Nameservers for this zone" - }, - "status": { - "type": "string", - "description": "Zone status", - "example": "active" - } - } - }, - "DockerComposePresetConfig": { - "type": "object", - "description": "Configuration for Docker Compose deployments.", - "properties": { - "composeOverride": { - "type": [ - "string", - "null" - ], - "description": "User-provided docker-compose.override.yml content." - }, - "composePath": { - "type": [ - "string", - "null" - ], - "description": "Path to the Compose file relative to the project directory." - }, - "publicPorts": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ComposePublicPort" - }, - "description": "Compose service ports that should be publicly routed." - } - } - }, - "DockerRegistrySettings": { - "type": "object", - "properties": { - "ca_certificate": { - "type": [ - "string", - "null" - ], - "default": null - }, - "enabled": { - "type": "boolean", - "default": false - }, - "password": { - "type": [ - "string", - "null" - ], - "default": null - }, - "registry_url": { - "type": [ - "string", - "null" - ], - "default": null - }, - "tls_verify": { - "type": "boolean", - "default": true - }, - "username": { - "type": [ - "string", - "null" - ], - "default": null - } - } - }, - "DockerRegistrySettingsMasked": { - "type": "object", - "description": "Docker registry settings with masked sensitive fields", - "required": [ - "enabled", - "tls_verify" - ], - "properties": { - "ca_certificate": { - "type": [ - "string", - "null" - ] - }, - "enabled": { - "type": "boolean" - }, - "password": { - "type": [ - "string", - "null" - ] - }, - "registry_url": { - "type": [ - "string", - "null" - ] - }, - "tls_verify": { - "type": "boolean" - }, - "username": { - "type": [ - "string", - "null" - ] - } - } - }, - "DockerfilePresetConfig": { - "type": "object", - "description": "Configuration for Dockerfile preset\nAllows customizing the Dockerfile path and build context for Docker-based deployments", - "properties": { - "buildContext": { - "type": [ - "string", - "null" - ], - "description": "Custom build context path (relative to repository root)\nIf not specified, uses the project's directory setting", - "example": "./api" - }, - "dockerfilePath": { - "type": [ - "string", - "null" - ], - "description": "Custom Dockerfile path (relative to build context)\nIf not specified, defaults to \"Dockerfile\" in the build context", - "example": "docker/Dockerfile" - }, - "variant": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/DockerfileVariant", - "description": "Catalog variant. Normally omitted; `custom` selects the generated\nDockerfile compatibility preset." - } - ] - } - } - }, - "DockerfileVariant": { - "type": "string", - "description": "Catalog variant persisted under the canonical Dockerfile preset.\n\nExisting rows predate this discriminator and therefore deserialize as\n[`DockerfileVariant::File`].", - "enum": [ - "file", - "custom" - ] - }, - "DomainAction": { - "type": "string", - "description": "What to do with a domain during migration", - "enum": [ - "import", - "skip" - ] - }, - "DomainChallengeResponse": { - "type": "object", - "required": [ - "domain", - "txt_records", - "status" - ], - "properties": { - "domain": { - "type": "string" - }, - "status": { - "type": "string" - }, - "txt_records": { - "type": "array", - "items": { - "$ref": "#/components/schemas/TxtRecord" - }, - "description": "Array of TXT records to add to DNS. For wildcards, multiple records are required." - } - } - }, - "DomainEnvironmentResponse": { - "type": "object", - "required": [ - "id", - "name", - "slug" - ], - "properties": { - "id": { - "type": "integer", - "format": "int32" - }, - "name": { - "type": "string" - }, - "slug": { - "type": "string" - } - } - }, - "DomainError": { - "type": "object", - "required": [ - "message", - "code" - ], - "properties": { - "code": { - "type": "string" - }, - "details": { - "type": [ - "string", - "null" - ] - }, - "message": { - "type": "string" - } - } - }, - "DomainPlan": { - "type": "object", - "description": "Plan for migrating a single custom domain", - "required": [ - "domain", - "environment", - "action", - "action_description" - ], - "properties": { - "action": { - "$ref": "#/components/schemas/DomainAction", - "description": "What to do with this domain" - }, - "action_description": { - "type": "string", - "description": "Human-readable explanation" - }, - "domain": { - "type": "string", - "description": "Full domain name" - }, - "environment": { - "type": "string", - "description": "Which environment to associate with (\"production\")" - }, - "redirect_to": { - "type": [ - "string", - "null" - ], - "description": "Redirect target (if this is a redirect domain)" - }, - "replacement": { - "type": [ - "string", - "null" - ], - "description": "The temps-side address that replaces this domain when it is skipped.\n\nSource-generated domains (sslip.io / traefik.me / platform subdomains)\nembed the source server's IP and would keep pointing at the old\nmachine \u2014 this tells the user where the app will be reachable on\ntemps instead." - }, - "status_code": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Redirect status code" - } - } - }, - "DomainResponse": { - "type": "object", - "required": [ - "id", - "domain", - "status", - "is_wildcard", - "verification_method", - "created_at", - "updated_at" - ], - "properties": { - "certificate": { - "type": [ - "string", - "null" - ], - "description": "The PEM-encoded certificate chain (can be displayed in browser or downloaded)" - }, - "created_at": { - "type": "integer", - "format": "int64" - }, - "dns_challenge_token": { - "type": [ - "string", - "null" - ] - }, - "dns_challenge_value": { - "type": [ - "string", - "null" - ] - }, - "domain": { - "type": "string" - }, - "expiration_time": { - "type": [ - "integer", - "null" - ], - "format": "int64" - }, - "id": { - "type": "integer", - "format": "int32" - }, - "is_wildcard": { - "type": "boolean" - }, - "last_error": { - "type": [ - "string", - "null" - ] - }, - "last_error_type": { - "type": [ - "string", - "null" - ] - }, - "last_renewed": { - "type": [ - "integer", - "null" - ], - "format": "int64" - }, - "on_demand_backoff_until": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "description": "On-demand TLS negative-cache deadline (epoch millis), when this hostname's\non-demand HTTP-01 issuance is in backoff after a failure (ADR-018 \u00a74).\n`None` means no active backoff." - }, - "status": { - "type": "string" - }, - "updated_at": { - "type": "integer", - "format": "int64" - }, - "verification_method": { - "type": "string" - } - } - }, - "DrainNodeResponse": { - "type": "object", - "required": [ - "id", - "name", - "status", - "affected_environments", - "message" - ], - "properties": { - "affected_environments": { - "type": "integer", - "minimum": 0 - }, - "id": { - "type": "integer", - "format": "int32" - }, - "message": { - "type": "string" - }, - "name": { - "type": "string" - }, - "status": { - "type": "string" - } - } - }, - "DrainStatusResponse": { - "type": "object", - "description": "Progress of a node drain operation.", - "required": [ - "node_id", - "node_name", - "status", - "remaining_containers", - "drain_complete", - "can_remove", - "message" - ], - "properties": { - "can_remove": { - "type": "boolean", - "description": "Can the node be safely removed?" - }, - "drain_complete": { - "type": "boolean", - "description": "Whether the drain is complete (all containers migrated)" - }, - "message": { - "type": "string" - }, - "node_id": { - "type": "integer", - "format": "int32" - }, - "node_name": { - "type": "string" - }, - "remaining_containers": { - "type": "integer", - "description": "Number of containers still on this node", - "minimum": 0 - }, - "status": { - "type": "string" - } - } - }, - "DropOffPoint": { - "type": "object", - "description": "Drop-off point: pages where visitors leave the site", - "required": [ - "page_path", - "exit_count", - "total_views", - "exit_rate" - ], - "properties": { - "exit_count": { - "type": "integer", - "format": "int64", - "description": "Number of exits from this page" - }, - "exit_rate": { - "type": "number", - "format": "double", - "description": "Exit rate for this page (exit_count / total_views)" - }, - "page_path": { - "type": "string", - "description": "The page path where visitors drop off" - }, - "total_views": { - "type": "integer", - "format": "int64", - "description": "Total views of this page" - } - } - }, - "EmailConfig": { - "type": "object", - "required": [ - "smtp_host", - "smtp_port", - "username", - "password", - "from_address", - "to_addresses" - ], - "properties": { - "accept_invalid_certs": { - "type": "boolean" - }, - "from_address": { - "type": "string" - }, - "from_name": { - "type": [ - "string", - "null" - ] - }, - "password": { - "type": "string" - }, - "smtp_host": { - "type": "string" - }, - "smtp_port": { - "type": "integer", - "format": "int32", - "minimum": 0 - }, - "starttls_required": { - "type": "boolean" - }, - "tls_mode": { - "$ref": "#/components/schemas/TlsMode" - }, - "to_addresses": { - "type": "array", - "items": { - "type": "string" - } - }, - "username": { - "type": "string" - } - } - }, - "EmailDomainResponse": { - "type": "object", - "required": [ - "id", - "provider_id", - "domain", - "status", - "created_at", - "updated_at" - ], - "properties": { - "created_at": { - "type": "string", - "example": "2025-12-03T10:30:00Z" - }, - "domain": { - "type": "string", - "example": "updates.example.com" - }, - "id": { - "type": "integer", - "format": "int32" - }, - "last_verified_at": { - "type": [ - "string", - "null" - ] - }, - "provider_id": { - "type": "integer", - "format": "int32" - }, - "status": { - "type": "string", - "example": "verified" - }, - "updated_at": { - "type": "string", - "example": "2025-12-03T10:30:00Z" - }, - "verification_error": { - "type": [ - "string", - "null" - ] - } - } - }, - "EmailDomainWithDnsResponse": { - "type": "object", - "required": [ - "domain", - "dns_records" - ], - "properties": { - "dns_records": { - "type": "array", - "items": { - "$ref": "#/components/schemas/DnsRecordResponse" - } - }, - "domain": { - "$ref": "#/components/schemas/EmailDomainResponse" - } - } - }, - "EmailProviderResponse": { - "type": "object", - "required": [ - "id", - "name", - "provider_type", - "region", - "is_active", - "credentials", - "created_at", - "updated_at" - ], - "properties": { - "created_at": { - "type": "string", - "example": "2025-12-03T10:30:00Z" - }, - "credentials": { - "description": "Masked credentials for display" - }, - "id": { - "type": "integer", - "format": "int32" - }, - "is_active": { - "type": "boolean" - }, - "name": { - "type": "string", - "example": "My AWS SES" - }, - "provider_type": { - "$ref": "#/components/schemas/EmailProviderTypeRoute" - }, - "region": { - "type": "string", - "example": "us-east-1" - }, - "sns_topic_arn": { - "type": [ - "string", - "null" - ] - }, - "updated_at": { - "type": "string", - "example": "2025-12-03T10:30:00Z" - } - } - }, - "EmailProviderTypeRoute": { - "type": "string", - "enum": [ - "ses", - "scaleway", - "smtp" - ] - }, - "EmailRequest": { - "type": "object", - "description": "Request body carrying just an email address (password-reset request).", - "required": [ - "email" - ], - "properties": { - "email": { - "type": "string" - } - } - }, - "EmailResponse": { - "type": "object", - "required": [ - "id", - "from_address", - "to_addresses", - "subject", - "status", - "created_at", - "track_opens", - "track_clicks", - "open_count", - "click_count" - ], - "properties": { - "bcc_addresses": { - "type": [ - "array", - "null" - ], - "items": { - "type": "string" - } - }, - "cc_addresses": { - "type": [ - "array", - "null" - ], - "items": { - "type": "string" - } - }, - "click_count": { - "type": "integer", - "format": "int32", - "description": "Number of times links in the email were clicked" - }, - "created_at": { - "type": "string", - "example": "2025-12-03T10:30:00Z" - }, - "domain_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "error_message": { - "type": [ - "string", - "null" - ] - }, - "first_clicked_at": { - "type": [ - "string", - "null" - ], - "description": "When a link was first clicked" - }, - "first_opened_at": { - "type": [ - "string", - "null" - ], - "description": "When the email was first opened" - }, - "from_address": { - "type": "string", - "example": "hello@updates.example.com" - }, - "from_name": { - "type": [ - "string", - "null" - ] - }, - "headers": { - "type": [ - "object", - "null" - ], - "additionalProperties": { - "type": "string" - }, - "propertyNames": { - "type": "string" - } - }, - "html_body": { - "type": [ - "string", - "null" - ] - }, - "id": { - "type": "string", - "example": "550e8400-e29b-41d4-a716-446655440000" - }, - "open_count": { - "type": "integer", - "format": "int32", - "description": "Number of times the email was opened" - }, - "project_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "provider_message_id": { - "type": [ - "string", - "null" - ] - }, - "reply_to": { - "type": [ - "string", - "null" - ] - }, - "sent_at": { - "type": [ - "string", - "null" - ] - }, - "status": { - "type": "string", - "example": "sent" - }, - "subject": { - "type": "string" - }, - "tags": { - "type": [ - "array", - "null" - ], - "items": { - "type": "string" - } - }, - "text_body": { - "type": [ - "string", - "null" - ] - }, - "to_addresses": { - "type": "array", - "items": { - "type": "string" - } - }, - "track_clicks": { - "type": "boolean", - "description": "Whether click tracking is enabled" - }, - "track_opens": { - "type": "boolean", - "description": "Whether open tracking is enabled" - }, - "tracked_html_body": { - "type": [ - "string", - "null" - ], - "description": "The final HTML sent to the provider (with tracking pixel and rewritten links)" - } - } - }, - "EmailStatsResponse": { - "type": "object", - "required": [ - "total", - "sent", - "failed", - "queued", - "captured" - ], - "properties": { - "captured": { - "type": "integer", - "format": "int64", - "description": "Emails captured without sending (Mailhog mode - no provider configured)", - "minimum": 0 - }, - "failed": { - "type": "integer", - "format": "int64", - "minimum": 0 - }, - "queued": { - "type": "integer", - "format": "int64", - "minimum": 0 - }, - "sent": { - "type": "integer", - "format": "int64", - "minimum": 0 - }, - "total": { - "type": "integer", - "format": "int64", - "minimum": 0 - } - } - }, - "EmailStatusResponse": { - "type": "object", - "required": [ - "email_configured", - "password_reset_available", - "oidc_providers" - ], - "properties": { - "email_configured": { - "type": "boolean" - }, - "oidc_providers": { - "type": "array", - "items": { - "$ref": "#/components/schemas/OidcProviderSummary" - } - }, - "password_reset_available": { - "type": "boolean" - } - } - }, - "EmailTrackingResponse": { - "type": "object", - "description": "Email tracking summary", - "required": [ - "email_id", - "track_opens", - "track_clicks", - "open_count", - "click_count", - "unique_opens", - "unique_clicks", - "links" - ], - "properties": { - "click_count": { - "type": "integer", - "format": "int32" - }, - "email_id": { - "type": "string" - }, - "first_clicked_at": { - "type": [ - "string", - "null" - ] - }, - "first_opened_at": { - "type": [ - "string", - "null" - ] - }, - "links": { - "type": "array", - "items": { - "$ref": "#/components/schemas/TrackedLinkResponse" - } - }, - "open_count": { - "type": "integer", - "format": "int32" - }, - "track_clicks": { - "type": "boolean" - }, - "track_opens": { - "type": "boolean" - }, - "unique_clicks": { - "type": "integer", - "format": "int64", - "minimum": 0 - }, - "unique_opens": { - "type": "integer", - "format": "int64", - "minimum": 0 - } - } - }, - "EmailTrackingSetupResponse": { - "type": "object", - "description": "Result of the one-click AWS-side event-tracking setup.", - "required": [ - "topic_arn", - "webhook_url", - "subscription_requested", - "event_destination_attached" - ], - "properties": { - "event_destination_attached": { - "type": "boolean", - "description": "The SESv2 event destination (bounce/complaint/delivery) is attached\nto the `temps-tracking` configuration set." - }, - "subscription_requested": { - "type": "boolean", - "description": "The webhook subscription was requested; SNS confirms it\nasynchronously through the webhook itself." - }, - "topic_arn": { - "type": "string", - "example": "arn:aws:sns:us-east-1:123456789012:temps-email-events-1" - }, - "webhook_url": { - "type": "string" - } - } - }, - "EmailTrackingStatusResponse": { - "type": "object", - "description": "Live status of the SES event-tracking pipeline for one provider.", - "required": [ - "webhook_url", - "supports_event_tracking" - ], - "properties": { - "last_event_at": { - "type": [ - "string", - "null" - ], - "description": "Most recent delivered/bounced/complained event recorded for an email\nsent through this provider. `null` means no provider feedback has\narrived yet.", - "example": "2026-07-18T10:31:00Z" - }, - "sns_topic_arn": { - "type": [ - "string", - "null" - ] - }, - "subscription_confirmed_at": { - "type": [ - "string", - "null" - ], - "description": "When the SNS subscription for the current topic was confirmed.\n`null` with a topic set usually means the subscription is still\npending \u2014 most often because the endpoint was subscribed before the\ntopic ARN was saved here.", - "example": "2026-07-18T10:30:00Z" - }, - "supports_event_tracking": { - "type": "boolean", - "description": "Only SES providers support SNS event tracking." - }, - "webhook_url": { - "type": "string", - "description": "Public webhook endpoint SNS must deliver events to.", - "example": "https://temps.example.com/api/t/webhook/ses" - } - } - }, - "EmbeddingData": { - "type": "object", - "required": [ - "object", - "embedding", - "index" - ], - "properties": { - "embedding": { - "type": "array", - "items": { - "type": "number", - "format": "double" - } - }, - "index": { - "type": "integer", - "format": "int32" - }, - "object": { - "type": "string" - } - } - }, - "EmbeddingInput": { - "oneOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ] - }, - "EmbeddingRequest": { - "type": "object", - "required": [ - "model", - "input" - ], - "properties": { - "dimensions": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "encoding_format": { - "type": [ - "string", - "null" - ] - }, - "input": { - "$ref": "#/components/schemas/EmbeddingInput" - }, - "model": { - "type": "string" - } - } - }, - "EmbeddingResponse": { - "type": "object", - "required": [ - "object", - "data", - "model", - "usage" - ], - "properties": { - "data": { - "type": "array", - "items": { - "$ref": "#/components/schemas/EmbeddingData" - } - }, - "model": { - "type": "string" - }, - "object": { - "type": "string" - }, - "usage": { - "$ref": "#/components/schemas/EmbeddingUsage" - } - } - }, - "EmbeddingUsage": { - "type": "object", - "required": [ - "prompt_tokens", - "total_tokens" - ], - "properties": { - "prompt_tokens": { - "type": "integer", - "format": "int64" - }, - "total_tokens": { - "type": "integer", - "format": "int64" - } - } - }, - "EnableBlobRequest": { - "type": "object", - "description": "Request to enable Blob service", - "properties": { - "docker_image": { - "type": [ - "string", - "null" - ], - "description": "Docker image to use (optional, defaults to RustFS)", - "example": "ghcr.io/rustfs/rustfs:0.5.0" - }, - "root_password": { - "type": [ - "string", - "null" - ], - "description": "Root password for S3 access" - }, - "root_user": { - "type": [ - "string", - "null" - ], - "description": "Root user for S3 access" - } - } - }, - "EnableBlobResponse": { - "type": "object", - "description": "Response after enabling Blob service", - "required": [ - "success", - "message", - "status" - ], - "properties": { - "message": { - "type": "string", - "description": "Human-readable message", - "example": "Blob service enabled successfully" - }, - "status": { - "$ref": "#/components/schemas/BlobStatusResponse", - "description": "Current status" - }, - "success": { - "type": "boolean", - "description": "Whether the operation succeeded", - "example": true - } - } - }, - "EnableKvRequest": { - "type": "object", - "description": "Request to enable the KV service", - "properties": { - "docker_image": { - "type": [ - "string", - "null" - ], - "description": "Docker image to use (optional, uses default if not provided)", - "example": "gotempsh/redis-walg:8-bookworm" - }, - "max_memory": { - "type": [ - "string", - "null" - ], - "description": "Maximum memory allocation (e.g., \"256mb\", \"1gb\")", - "example": "256mb" - }, - "persistence": { - "type": "boolean", - "description": "Enable data persistence" - } - } - }, - "EnableKvResponse": { - "type": "object", - "description": "Response after enabling KV service", - "required": [ - "success", - "message", - "status" - ], - "properties": { - "message": { - "type": "string", - "description": "Status message", - "example": "KV service enabled successfully" - }, - "status": { - "$ref": "#/components/schemas/KvStatusResponse", - "description": "Current service status" - }, - "success": { - "type": "boolean", - "description": "Whether the service was successfully enabled" - } - } - }, - "EnablePgStatStatementsResponse": { - "type": "object", - "description": "Response for the enable pg_stat_statements endpoint.", - "required": [ - "message" - ], - "properties": { - "message": { - "type": "string", - "description": "Human-readable message confirming the action." - } - } - }, - "EndpointDto": { - "type": "object", - "description": "One DNS record on the wire. Mirrors `service_endpoints::Model` but\nkeeps the API stable across entity evolution. `target_ip` is a string\n(v4 or v6 literal, or CNAME target hostname) parsed by the resolver.", - "required": [ - "id", - "fqdn", - "record_type", - "ttl", - "owner_kind", - "owner_id", - "generation" - ], - "properties": { - "fqdn": { - "type": "string" - }, - "generation": { - "type": "integer", - "format": "int64" - }, - "id": { - "type": "integer", - "format": "int64" - }, - "node_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "owner_id": { - "type": "integer", - "format": "int64" - }, - "owner_kind": { - "type": "string" - }, - "record_type": { - "type": "string" - }, - "target_ip": { - "type": [ - "string", - "null" - ] - }, - "target_port": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "ttl": { - "type": "integer", - "format": "int32" - } - } - }, - "EnqueuedJob": { - "type": "object", - "description": "A single job that was successfully enqueued during a fan-out run.", - "required": [ - "backup_id", - "job_id", - "engine" - ], - "properties": { - "backup_id": { - "type": "integer", - "format": "int32", - "description": "FK to `backups.id` for this job." - }, - "engine": { - "type": "string", - "description": "Engine key (e.g. `\"control_plane\"`, `\"redis\"`, `\"postgres_pgdump\"`)." - }, - "job_id": { - "type": "integer", - "format": "int64", - "description": "FK to `backup_jobs.id` for this job." - }, - "target_service_id": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "FK to `external_services.id` when this is an external-service job.\n`None` for the control-plane job." - } - } - }, - "EnrichVisitorRequest": { - "type": "object", - "required": [ - "custom_data" - ], - "properties": { - "custom_data": { - "type": "object" - } - } - }, - "EnrichVisitorResponse": { - "type": "object", - "required": [ - "success", - "visitor_id", - "message" - ], - "properties": { - "message": { - "type": "string" - }, - "success": { - "type": "boolean" - }, - "visitor_id": { - "type": "string" - } - } - }, - "EnrollmentTokenInfo": { - "type": "object", - "required": [ - "id", - "expires_at", - "used_count", - "max_uses", - "created_at" - ], - "properties": { - "bound_node_name": { - "type": [ - "string", - "null" - ] - }, - "created_at": { - "type": "string" - }, - "expires_at": { - "type": "string" - }, - "id": { - "type": "integer", - "format": "int32" - }, - "max_uses": { - "type": "integer", - "format": "int32" - }, - "used_count": { - "type": "integer", - "format": "int32" - } - } - }, - "EnrollmentTokenListResponse": { - "type": "object", - "required": [ - "tokens" - ], - "properties": { - "tokens": { - "type": "array", - "items": { - "$ref": "#/components/schemas/EnrollmentTokenInfo" - } - } - } - }, - "EntityInfoResponse": { - "type": "object", - "required": [ - "container_path", - "entity", - "entity_type", - "fields" - ], - "properties": { - "container_path": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Full container path", - "example": [ - "mydb", - "public" - ] - }, - "entity": { - "type": "string", - "description": "Entity name", - "example": "users" - }, - "entity_type": { - "type": "string", - "description": "Entity type", - "example": "table" - }, - "fields": { - "type": "array", - "items": { - "$ref": "#/components/schemas/FieldResponse" - }, - "description": "Field definitions" - }, - "metadata": { - "description": "Additional metadata (content_type, last_modified, etag, etc.)" - }, - "row_count": { - "type": [ - "integer", - "null" - ], - "description": "Approximate row count (for tables/collections)", - "example": 1234, - "minimum": 0 - }, - "size_bytes": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "description": "Size in bytes (for objects/files)", - "example": 1048576, - "minimum": 0 - }, - "sort_schema": { - "description": "JSON Schema for sort options (if supported)" - } - } - }, - "EntityResponse": { - "type": "object", - "required": [ - "name", - "entity_type" - ], - "properties": { - "entity_type": { - "type": "string", - "description": "Entity type (table, view, collection, etc.)", - "example": "table" - }, - "name": { - "type": "string", - "description": "Entity name (table/collection)", - "example": "users" - }, - "row_count": { - "type": [ - "integer", - "null" - ], - "description": "Approximate row count", - "example": 1234, - "minimum": 0 - }, - "size_bytes": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "description": "Size in bytes (for files/objects)", - "example": 1048576, - "minimum": 0 - } - } - }, - "EnvVarInput": { - "type": "object", - "description": "Input for environment variable", - "required": [ - "name", - "value" - ], - "properties": { - "name": { - "type": "string", - "description": "Variable name" - }, - "value": { - "type": "string", - "description": "Variable value" - } - } - }, - "EnvVarIntegrationInfo": { - "type": "object", - "required": [ - "service_id", - "service_name", - "service_type", - "service_updated_at" - ], - "properties": { - "service_id": { - "type": "integer", - "format": "int32" - }, - "service_name": { - "type": "string" - }, - "service_slug": { - "type": [ - "string", - "null" - ] - }, - "service_type": { - "type": "string" - }, - "service_updated_at": { - "type": "string" - } - } - }, - "EnvVarResponse": { - "type": "object", - "description": "Environment variable with masked sensitive values", - "required": [ - "key", - "value", - "is_masked" - ], - "properties": { - "is_masked": { - "type": "boolean", - "description": "Whether this is a sensitive/masked value" - }, - "key": { - "type": "string" - }, - "value": { - "type": "string" - } - } - }, - "EnvVarTemplateResponse": { - "type": "object", - "description": "Environment variable template response", - "required": [ - "name", - "required" - ], - "properties": { - "default": { - "type": [ - "string", - "null" - ], - "description": "Default value if not provided by user" - }, - "default_generator": { - "type": [ - "string", - "null" - ], - "description": "Frontend-side generator hint for the default value\n(e.g. `app_url`, `random_secret`, `random_hex_32`)" - }, - "description": { - "type": [ - "string", - "null" - ], - "description": "Description of what this variable is used for" - }, - "example": { - "type": [ - "string", - "null" - ], - "description": "Example value for documentation" - }, - "name": { - "type": "string", - "description": "Name of the environment variable" - }, - "required": { - "type": "boolean", - "description": "Whether this variable is required" - } - } - }, - "EnvironmentConfiguration": { - "type": "object", - "description": "Environment-level configuration", - "required": [ - "name", - "subdomain", - "resources" - ], - "properties": { - "name": { - "type": "string", - "description": "Environment name" - }, - "resources": { - "$ref": "#/components/schemas/ResourceLimits", - "description": "Resource limits for environment" - }, - "subdomain": { - "type": "string", - "description": "Proposed subdomain" - } - } - }, - "EnvironmentDomainResponse": { - "type": "object", - "required": [ - "id", - "environment_id", - "domain", - "created_at", - "url" - ], - "properties": { - "created_at": { - "type": "integer", - "format": "int64" - }, - "domain": { - "type": "string" - }, - "environment_id": { - "type": "integer", - "format": "int32" - }, - "id": { - "type": "integer", - "format": "int32" - }, - "url": { - "type": "string", - "description": "Full URL for this domain (e.g., https://buildtolearndev-production.example.com)", - "example": "https://buildtolearndev-production.example.com" - } - } - }, - "EnvironmentInfo": { - "type": "object", - "required": [ - "id", - "name", - "main_url" - ], - "properties": { - "current_deployment_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "id": { - "type": "integer", - "format": "int32" - }, - "main_url": { - "type": "string" - }, - "name": { - "type": "string" - } - } - }, - "EnvironmentResponse": { - "type": "object", - "required": [ - "id", - "project_id", - "name", - "slug", - "main_url", - "subdomain", - "created_at", - "updated_at", - "is_preview", - "protected", - "sleeping" - ], - "properties": { - "attack_mode": { - "type": [ - "boolean", - "null" - ], - "description": "Per-environment CAPTCHA attack-mode override.\n`null` means inherit the project-level `attack_mode`; `true`/`false`\nexplicitly enable/disable the challenge for this environment. Always\nserialized (NOT skipped) so the UI can distinguish `null` from `false`." - }, - "branch": { - "type": [ - "string", - "null" - ] - }, - "created_at": { - "type": "integer", - "format": "int64" - }, - "current_deployment_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "deployment_config": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/DeploymentConfig", - "description": "Deployment configuration for this environment (overrides project-level config)" - } - ] - }, - "estimated_sleep_at": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "description": "Estimated time (epoch millis) when the environment will go to sleep\nbased on last activity + idle timeout. NULL when sleeping or on-demand disabled." - }, - "force_https": { - "type": [ - "boolean", - "null" - ], - "description": "Per-environment HTTP\u2192HTTPS redirect override.\n`null` means inherit the proxy default (redirect only when the host has\nan active TLS certificate); `true` always redirects plain HTTP for this\nenvironment, `false` never does. Always serialized (NOT skipped) so the\nUI can distinguish `null` from `false`." - }, - "id": { - "type": "integer", - "format": "int32" - }, - "is_preview": { - "type": "boolean", - "description": "Indicates if this is a preview environment (auto-created per branch)\nFor preview environments, 'branch' contains the feature branch name" - }, - "last_activity_at": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "description": "Last proxied request timestamp (epoch millis) for on-demand environments.\nNULL when on-demand is disabled or no traffic has been received yet." - }, - "main_url": { - "type": "string" - }, - "name": { - "type": "string" - }, - "project_id": { - "type": "integer", - "format": "int32" - }, - "protected": { - "type": "boolean", - "description": "When true, git pushes do NOT auto-deploy to this environment.\nDeployments must be promoted from another environment." - }, - "sleeping": { - "type": "boolean", - "description": "When true, the environment's containers are currently stopped due to\ninactivity (on-demand mode) and will start on the next request." - }, - "slug": { - "type": "string" - }, - "subdomain": { - "type": "string", - "description": "The host label stored for this environment (e.g.\n`myproject-production`). This is the prefix that is combined with the\nplatform's preview domain at request time to produce `main_url`. Edit\nthis via the rename-subdomain endpoint, not the full URL." - }, - "updated_at": { - "type": "integer", - "format": "int64" - } - } - }, - "EnvironmentVariable": { - "type": "object", - "description": "Environment variable", - "required": [ - "key", - "value", - "is_secret" - ], - "properties": { - "is_secret": { - "type": "boolean", - "description": "Whether this is a secret (should be encrypted)" - }, - "key": { - "type": "string", - "description": "Variable name" - }, - "source_description": { - "type": [ - "string", - "null" - ], - "description": "Where this env var originates from (for traceability)" - }, - "value": { - "type": "string", - "description": "Variable value (may be redacted for secrets)" - } - } - }, - "EnvironmentVariableInfo": { - "type": "object", - "required": [ - "name", - "value", - "sensitive" - ], - "properties": { - "name": { - "type": "string" - }, - "sensitive": { - "type": "boolean", - "description": "Whether this variable contains sensitive data (passwords, keys, tokens)", - "example": false - }, - "value": { - "type": "string" - } - } - }, - "EnvironmentVariableResponse": { - "type": "object", - "required": [ - "id", - "key", - "created_at", - "updated_at", - "environments", - "include_in_preview", - "is_secret" - ], - "properties": { - "created_at": { - "type": "integer", - "format": "int64" - }, - "environments": { - "type": "array", - "items": { - "$ref": "#/components/schemas/EnvironmentInfo" - } - }, - "id": { - "type": "integer", - "format": "int32" - }, - "include_in_preview": { - "type": "boolean", - "description": "Include this environment variable in preview environments" - }, - "is_secret": { - "type": "boolean", - "description": "Whether the variable is a write-only secret. Secrets always have\n`value: None` in responses." - }, - "key": { - "type": "string" - }, - "updated_at": { - "type": "integer", - "format": "int64" - }, - "value": { - "type": [ - "string", - "null" - ], - "description": "Plaintext value for non-secret vars (or `\"***\"` mask for list responses).\n`None` for secret vars \u2014 secrets are write-only." - } - } - }, - "EnvironmentVariableValueResponse": { - "type": "object", - "required": [ - "value" - ], - "properties": { - "value": { - "type": "string" - } - } - }, - "ErrorDashboardStatsQuery": { - "type": "object", - "required": [ - "start_time", - "end_time" - ], - "properties": { - "compare_to_previous": { - "type": [ - "boolean", - "null" - ] - }, - "end_time": { - "type": "string", - "format": "date-time" - }, - "environment_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "start_time": { - "type": "string", - "format": "date-time" - } - } - }, - "ErrorDashboardStatsResponse": { - "type": "object", - "required": [ - "total_errors", - "total_errors_previous_period", - "total_errors_change_percent", - "error_groups", - "error_groups_previous_period", - "start_time", - "end_time" - ], - "properties": { - "comparison_end_time": { - "type": [ - "string", - "null" - ], - "format": "date-time" - }, - "comparison_start_time": { - "type": [ - "string", - "null" - ], - "format": "date-time" - }, - "end_time": { - "type": "string", - "format": "date-time" - }, - "error_groups": { - "type": "integer", - "format": "int64" - }, - "error_groups_previous_period": { - "type": "integer", - "format": "int64" - }, - "start_time": { - "type": "string", - "format": "date-time" - }, - "total_errors": { - "type": "integer", - "format": "int64" - }, - "total_errors_change_percent": { - "type": "number", - "format": "double" - }, - "total_errors_previous_period": { - "type": "integer", - "format": "int64" - } - } - }, - "ErrorEventResponse": { - "type": "object", - "required": [ - "id", - "error_group_id", - "timestamp", - "created_at" - ], - "properties": { - "created_at": { - "type": "string" - }, - "data": { - "description": "Full error event data (contains raw Sentry event or custom error data)" - }, - "error_group_id": { - "type": "integer", - "format": "int32" - }, - "id": { - "type": "integer", - "format": "int64" - }, - "source": { - "type": [ - "string", - "null" - ], - "description": "Source of the error event (e.g., \"sentry\", \"custom\", \"bugsnag\")" - }, - "timestamp": { - "type": "string" - } - } - }, - "ErrorGroupResponse": { - "type": "object", - "required": [ - "id", - "title", - "error_type", - "first_seen", - "last_seen", - "total_count", - "status", - "project_id", - "created_at", - "updated_at" - ], - "properties": { - "assigned_to": { - "type": [ - "string", - "null" - ] - }, - "created_at": { - "type": "string" - }, - "deployment_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "environment_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "error_type": { - "type": "string" - }, - "first_seen": { - "type": "string" - }, - "id": { - "type": "integer", - "format": "int32" - }, - "last_seen": { - "type": "string" - }, - "message_template": { - "type": [ - "string", - "null" - ] - }, - "project_id": { - "type": "integer", - "format": "int32" - }, - "status": { - "type": "string" - }, - "title": { - "type": "string" - }, - "total_count": { - "type": "integer", - "format": "int32" - }, - "updated_at": { - "type": "string" - }, - "visitor_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - } - } - }, - "ErrorGroupStatsResponse": { - "type": "object", - "required": [ - "total_groups", - "unresolved_groups", - "resolved_groups", - "ignored_groups" - ], - "properties": { - "ignored_groups": { - "type": "integer", - "format": "int64" - }, - "resolved_groups": { - "type": "integer", - "format": "int64" - }, - "total_groups": { - "type": "integer", - "format": "int64" - }, - "unresolved_groups": { - "type": "integer", - "format": "int64" - } - } - }, - "ErrorResponse": { - "type": "object", - "required": [ - "error" - ], - "properties": { - "details": { - "type": [ - "string", - "null" - ] - }, - "error": { - "type": "string" - } - } - }, - "ErrorRow": { - "type": "object", - "required": [ - "id", - "ts", - "error_group_id", - "fingerprint", - "error_class", - "stacktrace_preview", - "stacktrace_truncated" - ], - "properties": { - "deployment_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "environment_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "error_class": { - "type": "string" - }, - "error_group_id": { - "type": "integer", - "format": "int32" - }, - "fingerprint": { - "type": "string" - }, - "id": { - "type": "integer", - "format": "int64" - }, - "message": { - "type": [ - "string", - "null" - ] - }, - "stacktrace_preview": {}, - "stacktrace_truncated": { - "type": "boolean" - }, - "trace_id": { - "type": [ - "string", - "null" - ] - }, - "ts": { - "type": "string", - "format": "date-time" - } - } - }, - "ErrorTimeSeriesDataResponse": { - "type": "object", - "required": [ - "timestamp", - "count" - ], - "properties": { - "count": { - "type": "integer", - "format": "int64" - }, - "timestamp": { - "type": "string" - } - } - }, - "ErrorTimeSeriesQuery": { - "type": "object", - "required": [ - "start_time", - "end_time" - ], - "properties": { - "bucket": { - "type": "string", - "description": "Time bucket size (e.g., \"1h\", \"15m\", \"1d\", \"1 hour\", \"30 minutes\")", - "example": "1h" - }, - "end_time": { - "type": "string", - "format": "date-time" - }, - "start_time": { - "type": "string", - "format": "date-time" - } - } - }, - "EventActivityBucket": { - "type": "object", - "description": "Time bucket data point for event activity graph", - "required": [ - "timestamp", - "count", - "unique_visitors" - ], - "properties": { - "count": { - "type": "integer", - "format": "int64", - "description": "Number of event occurrences in this bucket" - }, - "timestamp": { - "type": "string", - "description": "Timestamp for this bucket (ISO 8601)" - }, - "unique_visitors": { - "type": "integer", - "format": "int64", - "description": "Number of unique visitors in this bucket" - } - } - }, - "EventBreakdown": { - "type": "string", - "enum": [ - "country", - "region", - "city" - ] - }, - "EventBrowserStats": { - "type": "object", - "description": "Browser stats for an event", - "required": [ - "browser", - "count", - "percentage" - ], - "properties": { - "browser": { - "type": "string", - "description": "Browser name" - }, - "count": { - "type": "integer", - "format": "int64", - "description": "Number of event occurrences from this browser" - }, - "percentage": { - "type": "number", - "format": "double", - "description": "Percentage of total events" - } - } - }, - "EventCount": { - "type": "object", - "required": [ - "event_name", - "count", - "percentage" - ], - "properties": { - "count": { - "type": "integer", - "format": "int64" - }, - "event_name": { - "type": "string" - }, - "percentage": { - "type": "number", - "format": "double" - } - } - }, - "EventCountryStats": { - "type": "object", - "description": "Country stats for an event", - "required": [ - "country", - "count", - "percentage" - ], - "properties": { - "count": { - "type": "integer", - "format": "int64", - "description": "Number of event occurrences from this country" - }, - "country": { - "type": "string", - "description": "Country name" - }, - "country_code": { - "type": [ - "string", - "null" - ], - "description": "ISO country code (2-letter)" - }, - "percentage": { - "type": "number", - "format": "double", - "description": "Percentage of total events" - } - } - }, - "EventDetailQuery": { - "type": "object", - "description": "Query parameters for event detail analytics", - "required": [ - "event_name", - "project_id", - "start_date", - "end_date" - ], - "properties": { - "bucket_interval": { - "type": [ - "string", - "null" - ], - "description": "Bucket interval for time series: 'hour', 'day', 'week', 'month' (default: auto)" - }, - "end_date": { - "type": "string", - "format": "date-time" - }, - "environment_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "event_name": { - "type": "string", - "description": "The specific event name to get details for" - }, - "project_id": { - "type": "integer", - "format": "int32" - }, - "start_date": { - "type": "string", - "format": "date-time" - } - } - }, - "EventDetailResponse": { - "type": "object", - "description": "Summary response for a specific event's analytics", - "required": [ - "event_name", - "total_count", - "unique_visitors", - "unique_sessions", - "activity_over_time", - "referrers", - "countries", - "browsers", - "bucket_interval" - ], - "properties": { - "activity_over_time": { - "type": "array", - "items": { - "$ref": "#/components/schemas/EventActivityBucket" - }, - "description": "Time series data for event activity graph" - }, - "browsers": { - "type": "array", - "items": { - "$ref": "#/components/schemas/EventBrowserStats" - }, - "description": "Browser distribution of visitors who triggered this event" - }, - "bucket_interval": { - "type": "string", - "description": "Bucket interval used for time series ('hour', 'day', etc.)" - }, - "countries": { - "type": "array", - "items": { - "$ref": "#/components/schemas/EventCountryStats" - }, - "description": "Geographic distribution of visitors who triggered this event" - }, - "event_name": { - "type": "string", - "description": "The event name being analyzed" - }, - "referrers": { - "type": "array", - "items": { - "$ref": "#/components/schemas/EventReferrerStats" - }, - "description": "Top referrer hostnames for visitors who triggered this event" - }, - "total_count": { - "type": "integer", - "format": "int64", - "description": "Total number of times this event was triggered in the date range" - }, - "unique_sessions": { - "type": "integer", - "format": "int64", - "description": "Number of unique sessions where this event occurred" - }, - "unique_visitors": { - "type": "integer", - "format": "int64", - "description": "Number of unique visitors who triggered this event" - } - } - }, - "EventEntriesQuery": { - "type": "object", - "description": "Query parameters for the raw event entries list", - "required": [ - "event_name", - "project_id", - "start_date", - "end_date" - ], - "properties": { - "end_date": { - "type": "string", - "format": "date-time" - }, - "environment_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "event_name": { - "type": "string", - "description": "The specific event name to list occurrences for" - }, - "page": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "description": "Page number (1-based, default: 1)", - "minimum": 0 - }, - "per_page": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "description": "Items per page (default: 20, max: 100)", - "minimum": 0 - }, - "project_id": { - "type": "integer", - "format": "int32" - }, - "start_date": { - "type": "string", - "format": "date-time" - } - } - }, - "EventEntriesResponse": { - "type": "object", - "description": "Paginated response for raw event entries", - "required": [ - "event_name", - "total_count", - "page", - "per_page", - "entries" - ], - "properties": { - "entries": { - "type": "array", - "items": { - "$ref": "#/components/schemas/EventEntryInfo" - }, - "description": "Individual event occurrences, most recent first" - }, - "event_name": { - "type": "string", - "description": "The event name" - }, - "page": { - "type": "integer", - "format": "int64", - "description": "Current page number", - "minimum": 0 - }, - "per_page": { - "type": "integer", - "format": "int64", - "description": "Items per page", - "minimum": 0 - }, - "total_count": { - "type": "integer", - "format": "int64", - "description": "Total number of occurrences of this event in the date range" - } - } - }, - "EventEntryInfo": { - "type": "object", - "description": "A single raw occurrence of an event, including its custom JSON properties", - "required": [ - "id", - "timestamp", - "page_path", - "href" - ], - "properties": { - "browser": { - "type": [ - "string", - "null" - ], - "description": "Browser name" - }, - "city": { - "type": [ - "string", - "null" - ], - "description": "City of the visitor at the time of the event" - }, - "country": { - "type": [ - "string", - "null" - ], - "description": "Country of the visitor at the time of the event" - }, - "country_code": { - "type": [ - "string", - "null" - ], - "description": "ISO country code (2-letter)" - }, - "device_type": { - "type": [ - "string", - "null" - ], - "description": "Device type (Desktop, Mobile, Tablet)" - }, - "href": { - "type": "string", - "description": "Full URL where the event was triggered" - }, - "id": { - "type": "integer", - "format": "int64", - "description": "Event row ID" - }, - "page_path": { - "type": "string", - "description": "Page path where the event was triggered" - }, - "props": { - "type": [ - "object", - "null" - ], - "description": "Custom event properties as JSON (null when the event carried no data)" - }, - "session_id": { - "type": [ - "string", - "null" - ], - "description": "Session ID the event belongs to (if any)" - }, - "timestamp": { - "type": "string", - "format": "date-time", - "description": "When the event occurred" - }, - "visitor_id": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Visitor numeric ID (if known)" - }, - "visitor_uuid": { - "type": [ - "string", - "null" - ], - "description": "Visitor UUID (if known)" - } - } - }, - "EventKind": { - "type": "string", - "description": "Tag enum for filter parameters and routing. Matches the variant\ndiscriminator used by `ObservabilityEvent`.", - "enum": [ - "request", - "span", - "error", - "revenue" - ] - }, - "EventMetricsPayload": { - "type": "object", - "required": [ - "event_name", - "event_data", - "request_path", - "request_query" - ], - "properties": { - "cls": { - "type": [ - "number", - "null" - ], - "format": "float", - "description": "Cumulative Layout Shift (score)" - }, - "event_data": {}, - "event_name": { - "type": "string" - }, - "fcp": { - "type": [ - "number", - "null" - ], - "format": "float", - "description": "First Contentful Paint (milliseconds)" - }, - "fid": { - "type": [ - "number", - "null" - ], - "format": "float", - "description": "First Input Delay (milliseconds)" - }, - "inp": { - "type": [ - "number", - "null" - ], - "format": "float", - "description": "Interaction to Next Paint (milliseconds)" - }, - "language": { - "type": [ - "string", - "null" - ] - }, - "lcp": { - "type": [ - "number", - "null" - ], - "format": "float", - "description": "Largest Contentful Paint (milliseconds)" - }, - "page_title": { - "type": [ - "string", - "null" - ] - }, - "referrer": { - "type": [ - "string", - "null" - ], - "description": "Referrer URL (falls back to Referer header if not provided)" - }, - "request_path": { - "type": "string" - }, - "request_query": { - "type": "string" - }, - "screen_height": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "minimum": 0 - }, - "screen_width": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "minimum": 0 - }, - "ttfb": { - "type": [ - "number", - "null" - ], - "format": "float", - "description": "Time to First Byte (milliseconds)" - }, - "viewport_height": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "minimum": 0 - }, - "viewport_width": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "minimum": 0 - } - } - }, - "EventReferrerStats": { - "type": "object", - "description": "Referrer stats for an event", - "required": [ - "referrer", - "count", - "percentage" - ], - "properties": { - "count": { - "type": "integer", - "format": "int64", - "description": "Number of event occurrences from this referrer" - }, - "percentage": { - "type": "number", - "format": "double", - "description": "Percentage of total events" - }, - "referrer": { - "type": "string", - "description": "Referrer hostname or \"Direct\"" - } - } - }, - "EventTimeline": { - "type": "object", - "required": [ - "date", - "count" - ], - "properties": { - "count": { - "type": "integer", - "format": "int64" - }, - "date": { - "type": "string", - "format": "date-time" - } - } - }, - "EventTimelineQuery": { - "type": "object", - "required": [ - "start_date", - "end_date" - ], - "properties": { - "aggregation_level": { - "$ref": "#/components/schemas/AggregationLevel", - "description": "Aggregation level: events (raw count), sessions (unique sessions), or visitors (unique visitors)" - }, - "bucket_size": { - "type": [ - "string", - "null" - ], - "description": "Bucket size: hour, day, or week (auto-detected if not specified)" - }, - "end_date": { - "type": "string", - "format": "date-time" - }, - "environment_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "event_name": { - "type": [ - "string", - "null" - ] - }, - "start_date": { - "type": "string", - "format": "date-time" - } - } - }, - "EventType": { - "type": "object", - "required": [ - "name", - "count" - ], - "properties": { - "count": { - "type": "integer", - "format": "int64" - }, - "name": { - "type": "string" - } - } - }, - "EventTypeBreakdown": { - "type": "object", - "required": [ - "event_type", - "count", - "percentage" - ], - "properties": { - "count": { - "type": "integer", - "format": "int64" - }, - "event_type": { - "type": "string" - }, - "percentage": { - "type": "number", - "format": "double" - } - } - }, - "EventTypeBreakdownQuery": { - "type": "object", - "required": [ - "start_date", - "end_date" - ], - "properties": { - "aggregation_level": { - "$ref": "#/components/schemas/AggregationLevel", - "description": "Aggregation level: events (raw count), sessions (unique sessions), or visitors (unique visitors)" - }, - "end_date": { - "type": "string", - "format": "date-time" - }, - "environment_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "start_date": { - "type": "string", - "format": "date-time" - } - } - }, - "EventTypeResponse": { - "type": "object", - "required": [ - "event_type", - "description", - "category" - ], - "properties": { - "category": { - "type": "string" - }, - "description": { - "type": "string" - }, - "event_type": { - "type": "string" - } - } - }, - "EventTypesResponse": { - "type": "object", - "required": [ - "events", - "total", - "page", - "page_size" - ], - "properties": { - "events": { - "type": "array", - "items": { - "$ref": "#/components/schemas/EventType" - } - }, - "page": { - "type": "integer", - "format": "int64", - "minimum": 0 - }, - "page_size": { - "type": "integer", - "format": "int64", - "minimum": 0 - }, - "total": { - "type": "integer", - "format": "int64", - "minimum": 0 - } - } - }, - "EventVisitorInfo": { - "type": "object", - "description": "A visitor who triggered a specific event", - "required": [ - "visitor_id", - "visitor_uuid", - "event_count", - "first_triggered", - "last_triggered" - ], - "properties": { - "browser": { - "type": [ - "string", - "null" - ], - "description": "Browser name" - }, - "city": { - "type": [ - "string", - "null" - ], - "description": "Visitor's city" - }, - "country": { - "type": [ - "string", - "null" - ], - "description": "Visitor's country" - }, - "country_code": { - "type": [ - "string", - "null" - ], - "description": "Visitor's country code" - }, - "device_type": { - "type": [ - "string", - "null" - ], - "description": "Device type (Desktop, Mobile, Tablet)" - }, - "event_count": { - "type": "integer", - "format": "int64", - "description": "Number of times this visitor triggered the event" - }, - "first_triggered": { - "type": "string", - "format": "date-time", - "description": "When the visitor first triggered the event in the date range" - }, - "last_triggered": { - "type": "string", - "format": "date-time", - "description": "When the visitor last triggered the event in the date range" - }, - "referrer_hostname": { - "type": [ - "string", - "null" - ], - "description": "Referrer hostname for the event" - }, - "visitor_id": { - "type": "integer", - "format": "int32", - "description": "Visitor numeric ID" - }, - "visitor_uuid": { - "type": "string", - "description": "Visitor UUID" - } - } - }, - "EventVisitorsQuery": { - "type": "object", - "description": "Query parameters for event visitors list", - "required": [ - "event_name", - "project_id", - "start_date", - "end_date" - ], - "properties": { - "end_date": { - "type": "string", - "format": "date-time" - }, - "environment_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "event_name": { - "type": "string", - "description": "The specific event name to list visitors for" - }, - "page": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "description": "Page number (1-based, default: 1)", - "minimum": 0 - }, - "per_page": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "description": "Items per page (default: 20, max: 100)", - "minimum": 0 - }, - "project_id": { - "type": "integer", - "format": "int32" - }, - "start_date": { - "type": "string", - "format": "date-time" - } - } - }, - "EventVisitorsResponse": { - "type": "object", - "description": "Paginated response for event visitors", - "required": [ - "event_name", - "total_count", - "page", - "per_page", - "visitors" - ], - "properties": { - "event_name": { - "type": "string", - "description": "The event name" - }, - "page": { - "type": "integer", - "format": "int64", - "description": "Current page number", - "minimum": 0 - }, - "per_page": { - "type": "integer", - "format": "int64", - "description": "Items per page", - "minimum": 0 - }, - "total_count": { - "type": "integer", - "format": "int64", - "description": "Total number of unique visitors who triggered this event" - }, - "visitors": { - "type": "array", - "items": { - "$ref": "#/components/schemas/EventVisitorInfo" - }, - "description": "Individual visitors who triggered this event" - } - } - }, - "EventsCountQuery": { - "type": "object", - "required": [ - "start_date", - "end_date" - ], - "properties": { - "aggregation_level": { - "$ref": "#/components/schemas/AggregationLevel", - "description": "Aggregation level: events (raw count), sessions (unique sessions), or visitors (unique visitors)" - }, - "custom_events_only": { - "type": [ - "boolean", - "null" - ], - "description": "Only return custom events, excluding system events like page_view, page_leave, heartbeat (default: true)" - }, - "end_date": { - "type": "string", - "format": "date-time" - }, - "environment_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "limit": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "start_date": { - "type": "string", - "format": "date-time" - } - } - }, - "EventsResponse": { - "type": "object", - "required": [ - "events", - "applied_kinds" - ], - "properties": { - "applied_kinds": { - "type": "array", - "items": { - "$ref": "#/components/schemas/EventKind" - }, - "description": "Echo of the kinds filter actually applied (server-resolved). Useful\nfor clients that pass `kinds=` empty and want to know what they got." - }, - "events": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ObservabilityEvent" - } - } - } - }, - "ExecBody": { - "type": "object", - "required": [ - "cmd" - ], - "properties": { - "cmd": { - "type": "array", - "items": { - "type": "string" - } - }, - "cwd": { - "type": [ - "string", - "null" - ] - }, - "env": { - "type": "object", - "additionalProperties": { - "type": "string" - }, - "propertyNames": { - "type": "string" - } - } - }, - "additionalProperties": false - }, - "ExecDetachedResponse": { - "type": "object", - "required": [ - "job_id" - ], - "properties": { - "job_id": { - "type": "string" - } - } - }, - "ExecResponse": { - "type": "object", - "required": [ - "exit_code", - "stdout", - "stderr" - ], - "properties": { - "exit_code": { - "type": "integer", - "format": "int32" - }, - "stderr": { - "type": "string" - }, - "stdout": { - "type": "string" - } - } - }, - "ExecuteImportRequest": { - "type": "object", - "description": "Request to execute an import", - "required": [ - "session_id", - "project_name", - "preset", - "directory", - "main_branch" - ], - "properties": { - "directory": { - "type": "string", - "description": "Project directory", - "example": "." - }, - "dry_run": { - "type": [ - "boolean", - "null" - ], - "description": "Dry run mode (don't create resources)" - }, - "main_branch": { - "type": "string", - "description": "Main branch name", - "example": "main" - }, - "preset": { - "type": "string", - "description": "Preset to use for the project (e.g., \"nextjs\", \"express\", \"docker\")" - }, - "project_name": { - "type": "string", - "description": "Project name to use (overrides the name from the plan)", - "example": "my-app" - }, - "session_id": { - "type": "string", - "description": "Session ID from plan creation" - } - } - }, - "ExecuteImportResponse": { - "type": "object", - "description": "Response from import execution", - "required": [ - "session_id", - "status", - "step_results" - ], - "properties": { - "deployment_id": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Created deployment ID (if completed)" - }, - "environment_id": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Created environment ID (if completed)" - }, - "project_id": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Created project ID (if completed)" - }, - "session_id": { - "type": "string", - "description": "Session ID" - }, - "status": { - "$ref": "#/components/schemas/ImportExecutionStatus", - "description": "Execution status" - }, - "step_results": { - "type": "array", - "items": { - "$ref": "#/components/schemas/StepResult" - }, - "description": "Per-step results (in execution order)" - } - } - }, - "ExecuteOperationRequest": { - "type": "object", - "required": [ - "operation" - ], - "properties": { - "operation": { - "type": "string" - } - } - }, - "ExpireRequest": { - "type": "object", - "description": "Request to set expiration on a key", - "required": [ - "key", - "seconds" - ], - "properties": { - "key": { - "type": "string", - "description": "The key to set expiration on", - "example": "session:abc" - }, - "project_id": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Project ID (required for API key/session auth, optional for deployment tokens)", - "example": 1 - }, - "seconds": { - "type": "integer", - "format": "int64", - "description": "Expiration time in seconds", - "example": 3600 - } - } - }, - "ExpireResponse": { - "type": "object", - "description": "Response for expire operation", - "required": [ - "success" - ], - "properties": { - "success": { - "type": "boolean", - "description": "True if expiration was set, false if key doesn't exist" - } - } - }, - "ExplorerSupportResponse": { - "type": "object", - "required": [ - "supported", - "service_type", - "capabilities", - "hierarchy" - ], - "properties": { - "capabilities": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Capabilities supported by this service", - "example": [ - "sql" - ] - }, - "filter_schema": { - "description": "JSON Schema for filter format with embedded UI hints (if supported)" - }, - "hierarchy": { - "type": "array", - "items": { - "$ref": "#/components/schemas/HierarchyLevel" - }, - "description": "Hierarchy levels (describes the navigation structure)" - }, - "reason": { - "type": [ - "string", - "null" - ], - "description": "Reason why explorer is not supported (if applicable)" - }, - "service_type": { - "type": "string", - "description": "Service type", - "example": "postgres" - }, - "supported": { - "type": "boolean", - "description": "Whether the service supports query explorer functionality", - "example": true - } - } - }, - "ExtendTimeoutBody": { - "type": "object", - "properties": { - "duration": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "description": "`@vercel/sandbox`-compatible alternative \u2014 duration in milliseconds.\nUsed when `extra_secs` is absent.", - "minimum": 0 - }, - "extra_secs": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "description": "Extra seconds to add to the existing `expires_at` (temps-native).", - "minimum": 0 - } - } - }, - "ExternalImageResponse": { - "type": "object", - "required": [ - "id", - "project_id", - "image_ref", - "pushed_at", - "created_at" - ], - "properties": { - "created_at": { - "type": "string", - "format": "date-time", - "example": "2025-10-12T12:15:47.609192Z" - }, - "digest": { - "type": [ - "string", - "null" - ] - }, - "id": { - "type": "integer", - "format": "int32" - }, - "image_ref": { - "type": "string" - }, - "metadata": {}, - "project_id": { - "type": "integer", - "format": "int32" - }, - "pushed_at": { - "type": "string", - "format": "date-time", - "example": "2025-10-12T12:15:47.609192Z" - }, - "size_bytes": { - "type": [ - "integer", - "null" - ], - "format": "int64" - }, - "tag": { - "type": [ - "string", - "null" - ] - } - } - }, - "ExternalServiceBackupResponse": { - "type": "object", - "description": "Response type for external service backup", - "required": [ - "id", - "service_id", - "backup_id", - "backup_type", - "state", - "started_at", - "s3_location", - "metadata", - "compression_type", - "created_by" - ], - "properties": { - "backup_id": { - "type": "integer", - "format": "int32" - }, - "backup_type": { - "type": "string" - }, - "checksum": { - "type": [ - "string", - "null" - ] - }, - "compression_type": { - "type": "string" - }, - "created_by": { - "type": "integer", - "format": "int32" - }, - "error_message": { - "type": [ - "string", - "null" - ] - }, - "expires_at": { - "type": [ - "string", - "null" - ], - "example": "2025-02-15T14:30:00.123Z" - }, - "finished_at": { - "type": [ - "string", - "null" - ], - "example": "2025-01-15T14:35:00.456Z" - }, - "id": { - "type": "integer", - "format": "int32" - }, - "metadata": {}, - "s3_location": { - "type": "string" - }, - "service_id": { - "type": "integer", - "format": "int32" - }, - "size_bytes": { - "type": [ - "integer", - "null" - ], - "format": "int64" - }, - "started_at": { - "type": "string", - "example": "2025-01-15T14:30:00.123Z" - }, - "state": { - "type": "string" - } - } - }, - "ExternalServiceDetails": { - "type": "object", - "required": [ - "service", - "sensitive_parameters" - ], - "properties": { - "current_parameters": { - "type": [ - "object", - "null" - ], - "additionalProperties": { - "type": "string" - }, - "propertyNames": { - "type": "string" - } - }, - "parameter_schema": {}, - "sensitive_parameters": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Parameter names whose values are masked in `current_parameters` and\nmay be fetched only through the audited reveal endpoint." - }, - "service": { - "$ref": "#/components/schemas/ExternalServiceInfo" - } - } - }, - "ExternalServiceInfo": { - "type": "object", - "required": [ - "id", - "name", - "service_type", - "status", - "created_at", - "updated_at", - "topology" - ], - "properties": { - "connection_info": { - "type": [ - "string", - "null" - ] - }, - "created_at": { - "type": "string" - }, - "error_message": { - "type": [ - "string", - "null" - ], - "description": "Error message from failed initialization." - }, - "id": { - "type": "integer", - "format": "int32" - }, - "members": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ServiceMemberInfo" - }, - "description": "Cluster members (empty for standalone services)." - }, - "metrics_enabled": { - "type": "boolean", - "description": "Whether metric collection is enabled for this service. The UI uses this\nto decide whether to poll the monitoring endpoints." - }, - "name": { - "type": "string" - }, - "node_id": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Node ID where the service runs. Null means control plane (local)." - }, - "service_type": { - "$ref": "#/components/schemas/ServiceTypeRoute" - }, - "status": { - "type": "string" - }, - "topology": { - "type": "string", - "description": "Service topology: \"standalone\" (single container) or \"cluster\" (HA multi-member).", - "example": "standalone" - }, - "updated_at": { - "type": "string" - }, - "version": { - "type": [ - "string", - "null" - ] - } - } - }, - "ExternalServiceSummary": { - "type": "object", - "description": "Summary of the external service that owns a backup. Only populated for\nexternal-service backups (Redis, Postgres, etc.); absent for control-plane\nbackups.", - "required": [ - "id", - "name", - "service_type" - ], - "properties": { - "id": { - "type": "integer", - "format": "int32", - "description": "Database id of the external service." - }, - "name": { - "type": "string", - "description": "Human-readable service name (e.g. \"redis-prod\")." - }, - "service_type": { - "type": "string", - "description": "Service type string (e.g. \"postgres\", \"redis\", \"mongodb\").", - "example": "postgres" - } - } - }, - "FieldResponse": { - "type": "object", - "required": [ - "name", - "field_type", - "nullable" - ], - "properties": { - "field_type": { - "type": "string", - "description": "Field type (Int32, String, Timestamp, etc.)", - "example": "Int64" - }, - "name": { - "type": "string", - "description": "Field name", - "example": "id" - }, - "nullable": { - "type": "boolean", - "description": "Whether the field is nullable", - "example": false - } - } - }, - "FiringSeriesEntry": { - "type": "object", - "description": "A single currently-firing series for a dynamic alert rule, snapshotted from\nthe evaluator's in-memory per-series firing map at read time (ADR-026 Phase 3).", - "required": [ - "series_key", - "series_label" - ], - "properties": { - "alarm_id": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "The open alarm's id, when one was created (absent if suppressed)." - }, - "series_key": { - "type": "array", - "items": { - "type": "array", - "items": false, - "prefixItems": [ - { - "type": "string" - }, - { - "type": "string" - } - ] - }, - "description": "The series' label pairs, e.g. `[[\"endpoint\",\"/checkout\"],[\"region\",\"eu-west\"]]`." - }, - "series_label": { - "type": "string", - "description": "The human-readable joined label, e.g. `endpoint=/checkout, region=eu-west`." - } - } - }, - "FlagEnvironmentResponse": { - "type": "object", - "required": [ - "environment_id", - "enabled" - ], - "properties": { - "enabled": { - "type": "boolean" - }, - "environment_id": { - "type": "integer", - "format": "int32" - }, - "value": {} - } - }, - "FlagListResponse": { - "type": "object", - "description": "Note the absence of `salt`: it is never exposed. Publishing the bucketing\nsalt would let a client predict, and self-select into, a rollout cohort.", - "required": [ - "flags", - "total", - "page", - "page_size", - "total_pages" - ], - "properties": { - "flags": { - "type": "array", - "items": { - "$ref": "#/components/schemas/FlagResponse" - } - }, - "page": { - "type": "integer", - "format": "int64", - "minimum": 0 - }, - "page_size": { - "type": "integer", - "format": "int64", - "minimum": 0 - }, - "total": { - "type": "integer", - "format": "int64", - "description": "Total flags matching the filter, across all pages.", - "minimum": 0 - }, - "total_pages": { - "type": "integer", - "format": "int64", - "minimum": 0 - } - } - }, - "FlagResponse": { - "type": "object", - "required": [ - "id", - "key", - "value_type", - "default_value", - "client_visible", - "created_at", - "updated_at", - "environments" - ], - "properties": { - "archived_at": { - "type": [ - "string", - "null" - ] - }, - "client_visible": { - "type": "boolean" - }, - "created_at": { - "type": "string" - }, - "default_value": {}, - "description": { - "type": [ - "string", - "null" - ] - }, - "environments": { - "type": "array", - "items": { - "$ref": "#/components/schemas/FlagEnvironmentResponse" - }, - "description": "Per-environment overrides. Empty means the flag inherits its default\neverywhere." - }, - "id": { - "type": "integer", - "format": "int32" - }, - "key": { - "type": "string" - }, - "last_evaluated_at": { - "type": [ - "string", - "null" - ], - "description": "When an app last actually evaluated this flag. `None` means never seen,\nwhich is a real answer rather than missing data." - }, - "updated_at": { - "type": "string" - }, - "value_type": { - "type": "string" - } - } - }, - "FlagSnapshot": { - "type": "object", - "description": "A single flag, already resolved down to one environment. This is what the\nevaluator sees and what the SDK caches in memory.", - "required": [ - "key", - "value_type", - "default_value", - "enabled" - ], - "properties": { - "default_value": { - "description": "Served whenever evaluation cannot do better. Genuinely polymorphic by\ndesign \u2014 the surrounding struct carries the type." - }, - "enabled": { - "type": "boolean", - "description": "False means the kill switch is engaged for this environment." - }, - "environment_value": { - "description": "`None` means \"inherit `default_value`\"." - }, - "key": { - "type": "string" - }, - "value_type": { - "$ref": "#/components/schemas/FlagValueType" - } - } - }, - "FlagSnapshotResponse": { - "type": "object", - "required": [ - "environment_id", - "flags" - ], - "properties": { - "environment_id": { - "type": "integer", - "format": "int32" - }, - "flags": { - "type": "array", - "items": { - "$ref": "#/components/schemas/FlagSnapshot" - }, - "description": "Flags collapsed to what the evaluator needs, sorted by key so the\nserialized form \u2014 and therefore the ETag \u2014 is stable." - } - } - }, - "FlagValueType": { - "type": "string", - "description": "The declared type of a flag's value. Fixed at create time.", - "enum": [ - "bool", - "string", - "number", - "json" - ] - }, - "ForecastAlgorithm": { - "type": "string", - "description": "Forecast model family.", - "enum": [ - "linear", - "seasonal" - ] - }, - "ForecastParams": { - "type": "object", - "description": "Forecast detector parameters (stub \u2014 not yet evaluated).", - "required": [ - "forecast_horizon_secs", - "comparator", - "threshold" - ], - "properties": { - "algorithm": { - "$ref": "#/components/schemas/ForecastAlgorithm" - }, - "comparator": { - "$ref": "#/components/schemas/Comparator", - "description": "Comparator + threshold the *forecast* is checked against." - }, - "deviations": { - "type": "number", - "format": "double" - }, - "forecast_horizon_secs": { - "type": "integer", - "format": "int32", - "description": "How far ahead to project before checking the breach condition." - }, - "threshold": { - "type": "number", - "format": "double" - } - } - }, - "FullError": { - "type": "object", - "required": [ - "id", - "ts", - "error_group_id", - "fingerprint", - "error_class" - ], - "properties": { - "data": { - "description": "Full JSONB blob from `error_events.data` \u2014 stack trace, breadcrumbs,\nrequest context, everything. Schema is documented per source SDK." - }, - "deployment_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "environment_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "error_class": { - "type": "string" - }, - "error_group_id": { - "type": "integer", - "format": "int32" - }, - "fingerprint": { - "type": "string" - }, - "id": { - "type": "integer", - "format": "int64" - }, - "message": { - "type": [ - "string", - "null" - ] - }, - "trace_id": { - "type": [ - "string", - "null" - ] - }, - "ts": { - "type": "string", - "format": "date-time" - } - } - }, - "FullEvent": { - "oneOf": [ - { - "allOf": [ - { - "$ref": "#/components/schemas/FullRequest" - }, - { - "type": "object", - "required": [ - "type" - ], - "properties": { - "type": { - "type": "string", - "enum": [ - "request" - ] - } - } - } - ] - }, - { - "allOf": [ - { - "$ref": "#/components/schemas/FullError" - }, - { - "type": "object", - "required": [ - "type" - ], - "properties": { - "type": { - "type": "string", - "enum": [ - "error" - ] - } - } - } - ] - }, - { - "allOf": [ - { - "$ref": "#/components/schemas/RevenueRow" - }, - { - "type": "object", - "required": [ - "type" - ], - "properties": { - "type": { - "type": "string", - "enum": [ - "revenue" - ] - } - } - } - ] - }, - { - "allOf": [ - { - "$ref": "#/components/schemas/SpanRow", - "description": "`SpanRow.attributes` is the truncated form; re-fetching returns\nthe same shape so the panel has a stable contract." - }, - { - "type": "object", - "required": [ - "type" - ], - "properties": { - "type": { - "type": "string", - "enum": [ - "span" - ] - } - } - } - ], - "description": "`SpanRow.attributes` is the truncated form; re-fetching returns\nthe same shape so the panel has a stable contract." - } - ], - "description": "One un-truncated row, returned by the `/full/{type}/{id}` endpoint when\nthe user clicks \"Show full\". Same shape as the list rows, but with the\nraw heavy fields restored (no truncation flags) so the side panel can\nrender the long form." - }, - "FullRequest": { - "type": "object", - "required": [ - "id", - "ts", - "method", - "host", - "path", - "status" - ], - "properties": { - "client_ip": { - "type": [ - "string", - "null" - ] - }, - "deployment_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "environment_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "error_group_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "host": { - "type": "string" - }, - "id": { - "type": "string", - "description": "The request's unique `request_id` \u2014 same identity the list rows carry\n(backend-agnostic; ClickHouse rows have no serial PK)." - }, - "latency_ms": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "method": { - "type": "string" - }, - "path": { - "type": "string" - }, - "referrer": { - "type": [ - "string", - "null" - ] - }, - "request_headers": {}, - "response_headers": {}, - "status": { - "type": "integer", - "format": "int32" - }, - "trace_id": { - "type": [ - "string", - "null" - ] - }, - "ts": { - "type": "string", - "format": "date-time" - }, - "user_agent": { - "type": [ - "string", - "null" - ] - } - } - }, - "FunnelMetricsResponse": { - "type": "object", - "required": [ - "funnel_id", - "funnel_name", - "total_entries", - "step_conversions", - "overall_conversion_rate", - "average_completion_time_seconds" - ], - "properties": { - "average_completion_time_seconds": { - "type": "number", - "format": "double" - }, - "funnel_id": { - "type": "integer", - "format": "int32" - }, - "funnel_name": { - "type": "string" - }, - "overall_conversion_rate": { - "type": "number", - "format": "double" - }, - "step_conversions": { - "type": "array", - "items": { - "$ref": "#/components/schemas/StepConversionResponse" - } - }, - "total_entries": { - "type": "integer", - "format": "int64", - "minimum": 0 - } - } - }, - "FunnelResponse": { - "type": "object", - "required": [ - "id", - "name", - "is_active", - "created_at", - "updated_at" - ], - "properties": { - "created_at": { - "type": "string" - }, - "description": { - "type": [ - "string", - "null" - ] - }, - "id": { - "type": "integer", - "format": "int32" - }, - "is_active": { - "type": "boolean" - }, - "name": { - "type": "string" - }, - "updated_at": { - "type": "string" - } - } - }, - "GatewayStatus": { - "type": "object", - "description": "Detailed gateway container status surfaced to the settings UI.", - "required": [ - "present", - "running", - "health", - "container_name", - "expected_image", - "drift", - "auto_upgrade" - ], - "properties": { - "auto_upgrade": { - "type": "boolean", - "description": "True if `auto_upgrade` is enabled in settings." - }, - "container_name": { - "type": "string", - "description": "Container name." - }, - "drift": { - "type": "boolean", - "description": "True when `image != expected_image` and the container is present." - }, - "expected_image": { - "type": "string", - "description": "The image the supervisor *expects* (from settings/constant). If this\ndiffers from `image`, the UI shows a \"drift\" badge." - }, - "health": { - "type": "string", - "description": "Higher-level health label: \"running\" | \"restarting\" | \"crash_looping\"\n| \"stopped\" | \"missing\". UI should prefer this over `running`." - }, - "host_port": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Host port that the container's :8080 is published on.", - "minimum": 0 - }, - "image": { - "type": [ - "string", - "null" - ], - "description": "Image reference the container was created with (e.g.\n`ghcr.io/gotempsh/temps-preview-gateway:latest`)." - }, - "image_digest": { - "type": [ - "string", - "null" - ], - "description": "Image digest if available (e.g. `sha256:\u2026`)." - }, - "last_error": { - "type": [ - "string", - "null" - ], - "description": "Error string Docker recorded for the container (e.g. startup failure)." - }, - "last_exit_code": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "description": "Exit code of the last run, if the container is not currently running." - }, - "network": { - "type": [ - "string", - "null" - ], - "description": "Network the container is attached to (should be `temps-sandbox-net`)." - }, - "present": { - "type": "boolean", - "description": "Whether the container exists at all." - }, - "restart_count": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "description": "Number of times Docker has restarted the container." - }, - "running": { - "type": "boolean", - "description": "Whether the container is currently running." - }, - "started_at": { - "type": [ - "string", - "null" - ], - "description": "ISO 8601 timestamp the container was started at, if running." - } - } - }, - "GenAiEvent": { - "type": "object", - "description": "A GenAI-related event extracted from span events.\n\nCovers `gen_ai.client.inference.operation.details` and `gen_ai.evaluation.result`\nevents per the OTel GenAI semantic conventions.", - "required": [ - "span_id", - "trace_id", - "event_name", - "timestamp", - "attributes" - ], - "properties": { - "attributes": { - "type": "object", - "description": "All event attributes.", - "additionalProperties": { - "type": "string" - }, - "propertyNames": { - "type": "string" - } - }, - "event_name": { - "type": "string" - }, - "span_id": { - "type": "string" - }, - "timestamp": { - "type": "string", - "format": "date-time" - }, - "trace_id": { - "type": "string" - } - } - }, - "GenAiSpanDetail": { - "type": "object", - "description": "A single GenAI span with extracted semantic convention fields.\n\nFields are aligned with the OpenTelemetry GenAI Semantic Conventions spec:\n", - "required": [ - "span_id", - "name", - "kind", - "start_time", - "duration_ms", - "status_code", - "attributes" - ], - "properties": { - "agent_description": { - "type": [ - "string", - "null" - ], - "description": "Agent description from `gen_ai.agent.description`." - }, - "agent_id": { - "type": [ - "string", - "null" - ], - "description": "Agent identifier from `gen_ai.agent.id`." - }, - "agent_name": { - "type": [ - "string", - "null" - ], - "description": "Agent name from `gen_ai.agent.name`." - }, - "agent_version": { - "type": [ - "string", - "null" - ], - "description": "Agent version from `gen_ai.agent.version`." - }, - "attributes": { - "type": "object", - "description": "All span attributes for extensibility.", - "additionalProperties": { - "type": "string" - }, - "propertyNames": { - "type": "string" - } - }, - "aws_bedrock_guardrail_id": { - "type": [ - "string", - "null" - ], - "description": "AWS Bedrock guardrail ID from `aws.bedrock.guardrail.id`." - }, - "aws_bedrock_knowledge_base_id": { - "type": [ - "string", - "null" - ], - "description": "AWS Bedrock knowledge base ID from `aws.bedrock.knowledge_base.id`." - }, - "azure_resource_provider_namespace": { - "type": [ - "string", - "null" - ], - "description": "Azure resource provider namespace from `azure.resource_provider.namespace`." - }, - "cache_creation_input_tokens": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "description": "Tokens written to provider cache from `gen_ai.usage.cache_creation.input_tokens`." - }, - "cache_read_input_tokens": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "description": "Tokens served from provider cache from `gen_ai.usage.cache_read.input_tokens`." - }, - "conversation_id": { - "type": [ - "string", - "null" - ], - "description": "Unique conversation/session/thread ID from `gen_ai.conversation.id`." - }, - "data_source_id": { - "type": [ - "string", - "null" - ], - "description": "Data source identifier from `gen_ai.data_source.id`." - }, - "duration_ms": { - "type": "number", - "format": "double" - }, - "embeddings_dimension_count": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "description": "Output embedding dimensions from `gen_ai.embeddings.dimension.count`." - }, - "error_type": { - "type": [ - "string", - "null" - ], - "description": "Error type from `error.type` when the span status is ERROR." - }, - "gen_ai_model": { - "type": [ - "string", - "null" - ], - "description": "The requested model from `gen_ai.request.model`." - }, - "gen_ai_operation": { - "type": [ - "string", - "null" - ], - "description": "The operation type from `gen_ai.operation.name` (e.g. \"chat\", \"embeddings\", \"execute_tool\")." - }, - "gen_ai_response_model": { - "type": [ - "string", - "null" - ], - "description": "The model that actually generated the response from `gen_ai.response.model`." - }, - "gen_ai_system": { - "type": [ - "string", - "null" - ], - "description": "The GenAI provider from `gen_ai.provider.name` (falls back to deprecated `gen_ai.system`)." - }, - "input_messages": { - "type": [ - "string", - "null" - ], - "description": "Chat history input from `gen_ai.input.messages` (opt-in, JSON string)." - }, - "input_tokens": { - "type": [ - "integer", - "null" - ], - "format": "int64" - }, - "kind": { - "$ref": "#/components/schemas/SpanKind" - }, - "name": { - "type": "string" - }, - "openai_api_type": { - "type": [ - "string", - "null" - ], - "description": "OpenAI API type from `openai.api.type` (chat_completions, responses)." - }, - "openai_request_service_tier": { - "type": [ - "string", - "null" - ], - "description": "Requested service tier from `openai.request.service_tier`." - }, - "openai_response_service_tier": { - "type": [ - "string", - "null" - ], - "description": "Actual service tier from `openai.response.service_tier`." - }, - "openai_system_fingerprint": { - "type": [ - "string", - "null" - ], - "description": "System fingerprint from `openai.response.system_fingerprint`." - }, - "output_messages": { - "type": [ - "string", - "null" - ], - "description": "Model output from `gen_ai.output.messages` (opt-in, JSON string)." - }, - "output_tokens": { - "type": [ - "integer", - "null" - ], - "format": "int64" - }, - "output_type": { - "type": [ - "string", - "null" - ], - "description": "Output content type from `gen_ai.output.type` (text, json, image, speech)." - }, - "parent_span_id": { - "type": [ - "string", - "null" - ] - }, - "request_choice_count": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "description": "Number of choices requested from `gen_ai.request.choice.count`." - }, - "request_encoding_formats": { - "type": [ - "array", - "null" - ], - "items": { - "type": "string" - }, - "description": "Requested encoding formats from `gen_ai.request.encoding_formats`." - }, - "request_frequency_penalty": { - "type": [ - "number", - "null" - ], - "format": "double", - "description": "Frequency penalty from `gen_ai.request.frequency_penalty`." - }, - "request_max_tokens": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "description": "Max tokens from `gen_ai.request.max_tokens`." - }, - "request_presence_penalty": { - "type": [ - "number", - "null" - ], - "format": "double", - "description": "Presence penalty from `gen_ai.request.presence_penalty`." - }, - "request_seed": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "description": "Seed for reproducibility from `gen_ai.request.seed`." - }, - "request_stop_sequences": { - "type": [ - "array", - "null" - ], - "items": { - "type": "string" - }, - "description": "Stop sequences from `gen_ai.request.stop_sequences`." - }, - "request_temperature": { - "type": [ - "number", - "null" - ], - "format": "double", - "description": "Temperature setting from `gen_ai.request.temperature`." - }, - "request_top_k": { - "type": [ - "number", - "null" - ], - "format": "double", - "description": "Top-k setting from `gen_ai.request.top_k`." - }, - "request_top_p": { - "type": [ - "number", - "null" - ], - "format": "double", - "description": "Top-p setting from `gen_ai.request.top_p`." - }, - "response_finish_reasons": { - "type": [ - "array", - "null" - ], - "items": { - "type": "string" - }, - "description": "Reasons the model stopped from `gen_ai.response.finish_reasons` (e.g. [\"stop\"])." - }, - "response_id": { - "type": [ - "string", - "null" - ], - "description": "Unique completion ID from `gen_ai.response.id` (e.g. \"chatcmpl-123\")." - }, - "retrieval_documents": { - "type": [ - "string", - "null" - ], - "description": "Retrieved documents from `gen_ai.retrieval.documents` (opt-in, JSON string)." - }, - "retrieval_query_text": { - "type": [ - "string", - "null" - ], - "description": "Retrieval query text from `gen_ai.retrieval.query.text` (opt-in)." - }, - "server_address": { - "type": [ - "string", - "null" - ], - "description": "GenAI server address from `server.address`." - }, - "server_port": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "description": "GenAI server port from `server.port`." - }, - "span_id": { - "type": "string" - }, - "start_time": { - "type": "string", - "format": "date-time" - }, - "status_code": { - "$ref": "#/components/schemas/SpanStatusCode" - }, - "system_instructions": { - "type": [ - "string", - "null" - ], - "description": "System instructions from `gen_ai.system_instructions` (opt-in, JSON string)." - }, - "tool_call_arguments": { - "type": [ - "string", - "null" - ], - "description": "Tool call arguments from `gen_ai.tool.call.arguments` (opt-in, JSON string)." - }, - "tool_call_id": { - "type": [ - "string", - "null" - ], - "description": "Tool call ID from `gen_ai.tool.call.id`." - }, - "tool_call_result": { - "type": [ - "string", - "null" - ], - "description": "Tool call result from `gen_ai.tool.call.result` (opt-in, JSON string)." - }, - "tool_definitions": { - "type": [ - "string", - "null" - ], - "description": "Tool definitions from `gen_ai.tool.definitions` (opt-in, JSON string)." - }, - "tool_description": { - "type": [ - "string", - "null" - ], - "description": "Tool description from `gen_ai.tool.description`." - }, - "tool_name": { - "type": [ - "string", - "null" - ], - "description": "Tool name from `gen_ai.tool.name`." - }, - "tool_type": { - "type": [ - "string", - "null" - ], - "description": "Tool type from `gen_ai.tool.type` (function, extension, datastore)." - } - } - }, - "GenAiTraceDetailResponse": { - "type": "object", - "required": [ - "trace_id", - "spans", - "span_count", - "events", - "event_count" - ], - "properties": { - "event_count": { - "type": "integer", - "minimum": 0 - }, - "events": { - "type": "array", - "items": { - "$ref": "#/components/schemas/GenAiEvent" - } - }, - "span_count": { - "type": "integer", - "minimum": 0 - }, - "spans": { - "type": "array", - "items": { - "$ref": "#/components/schemas/GenAiSpanDetail" - } - }, - "trace_id": { - "type": "string" - } - } - }, - "GenAiTraceSummariesResponse": { - "type": "object", - "required": [ - "data", - "total" - ], - "properties": { - "data": { - "type": "array", - "items": { - "$ref": "#/components/schemas/GenAiTraceSummary" - } - }, - "total": { - "type": "integer", - "format": "int64", - "minimum": 0 - } - } - }, - "GenAiTraceSummary": { - "type": "object", - "description": "Summary of a GenAI conversation \u2014 aggregated from OTel spans with `gen_ai.*` attributes.", - "required": [ - "trace_id", - "root_span_name", - "service_name", - "start_time", - "duration_ms", - "span_count", - "error_count" - ], - "properties": { - "duration_ms": { - "type": "number", - "format": "double" - }, - "error_count": { - "type": "integer", - "format": "int64" - }, - "gen_ai_model": { - "type": [ - "string", - "null" - ], - "description": "The requested model from `gen_ai.request.model`." - }, - "gen_ai_operation": { - "type": [ - "string", - "null" - ], - "description": "The operation type from `gen_ai.operation.name` (e.g. \"chat\", \"embeddings\")." - }, - "gen_ai_system": { - "type": [ - "string", - "null" - ], - "description": "The GenAI provider (e.g. \"openai\", \"anthropic\") from `gen_ai.provider.name`." - }, - "root_span_name": { - "type": "string" - }, - "service_name": { - "type": "string" - }, - "span_count": { - "type": "integer", - "format": "int64" - }, - "start_time": { - "type": "string", - "format": "date-time" - }, - "total_cache_creation_input_tokens": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "description": "Total cache-creation input tokens across all spans." - }, - "total_cache_read_input_tokens": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "description": "Total cache-read input tokens across all spans." - }, - "total_input_tokens": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "description": "Total input tokens across all spans in this trace." - }, - "total_output_tokens": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "description": "Total output tokens across all spans in this trace." - }, - "trace_id": { - "type": "string" - } - } - }, - "GeneralStatsQuery": { - "type": "object", - "required": [ - "start_date", - "end_date" - ], - "properties": { - "end_date": { - "type": "string", - "format": "date-time" - }, - "start_date": { - "type": "string", - "format": "date-time" - } - } - }, - "GeneralStatsResponse": { - "type": "object", - "required": [ - "total_unique_visitors", - "total_visits", - "total_page_views", - "total_events", - "total_projects", - "avg_bounce_rate", - "avg_engagement_rate", - "project_breakdown" - ], - "properties": { - "avg_bounce_rate": { - "type": "number", - "format": "double" - }, - "avg_engagement_rate": { - "type": "number", - "format": "double" - }, - "page_views_trend_percentage": { - "type": [ - "number", - "null" - ], - "format": "double", - "description": "Percentage change in page views vs previous period" - }, - "previous_page_views": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "description": "Previous period page views" - }, - "previous_unique_visitors": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "description": "Previous period unique visitors (same duration, shifted back)" - }, - "project_breakdown": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ProjectStatsBreakdown" - } - }, - "total_events": { - "type": "integer", - "format": "int64" - }, - "total_page_views": { - "type": "integer", - "format": "int64" - }, - "total_projects": { - "type": "integer", - "format": "int64" - }, - "total_unique_visitors": { - "type": "integer", - "format": "int64" - }, - "total_visits": { - "type": "integer", - "format": "int64" - }, - "visitors_trend_percentage": { - "type": [ - "number", - "null" - ], - "format": "double", - "description": "Percentage change in unique visitors vs previous period" - } - } - }, - "GenerateDockerfileRequest": { - "type": "object", - "description": "Request body for generating a Dockerfile from a preset", - "properties": { - "build_command": { - "type": [ - "string", - "null" - ], - "description": "Custom build command (overrides preset default)", - "example": "npm run build" - }, - "install_command": { - "type": [ - "string", - "null" - ], - "description": "Custom install command (overrides preset default)", - "example": "npm ci" - }, - "output_dir": { - "type": [ - "string", - "null" - ], - "description": "Output directory for static builds", - "example": "dist" - }, - "package_manager": { - "type": [ - "string", - "null" - ], - "description": "Package manager used by the project (npm, yarn, pnpm, bun)\nIf not provided, defaults to npm", - "example": "npm" - }, - "project_name": { - "type": [ - "string", - "null" - ], - "description": "Project name/slug used for container naming", - "example": "my-app" - }, - "use_buildkit": { - "type": "boolean", - "description": "Whether to use BuildKit cache mounts for faster builds" - } - } - }, - "GenerateDockerfileResponse": { - "type": "object", - "description": "Response containing a generated Dockerfile and build arguments", - "required": [ - "dockerfile", - "build_args", - "preset" - ], - "properties": { - "build_args": { - "type": "object", - "description": "Build arguments to pass to `docker build --build-arg KEY=VALUE`", - "additionalProperties": { - "type": "string" - }, - "propertyNames": { - "type": "string" - } - }, - "dockerfile": { - "type": "string", - "description": "The generated Dockerfile content" - }, - "preset": { - "type": "string", - "description": "The preset slug used for generation" - } - } - }, - "GenerateJoinTokenResponse": { - "type": "object", - "description": "Response returned when a join token is generated (plaintext shown once)", - "required": [ - "token", - "message" - ], - "properties": { - "message": { - "type": "string" - }, - "token": { - "type": "string", - "description": "The plaintext join token \u2014 shown only once, save it now" - } - } - }, - "GeoLocationResponse": { - "type": "object", - "description": "Response containing geolocation information for an IP address", - "required": [ - "ip", - "is_eu" - ], - "properties": { - "city": { - "type": [ - "string", - "null" - ], - "description": "City name", - "example": "Mountain View" - }, - "country": { - "type": [ - "string", - "null" - ], - "description": "Country name", - "example": "United States" - }, - "country_code": { - "type": [ - "string", - "null" - ], - "description": "ISO country code (2 letters)", - "example": "US" - }, - "ip": { - "type": "string", - "description": "IP address that was geolocated", - "example": "8.8.8.8" - }, - "is_eu": { - "type": "boolean", - "description": "Whether the IP is in the European Union", - "example": false - }, - "latitude": { - "type": [ - "number", - "null" - ], - "format": "double", - "description": "Latitude coordinate", - "example": 37.386 - }, - "longitude": { - "type": [ - "number", - "null" - ], - "format": "double", - "description": "Longitude coordinate", - "example": -122.0838 - }, - "region": { - "type": [ - "string", - "null" - ], - "description": "Region/state name", - "example": "California" - }, - "timezone": { - "type": [ - "string", - "null" - ], - "description": "Timezone identifier", - "example": "America/Los_Angeles" - } - } - }, - "GeoRestrictionsConfig": { - "type": "object", - "description": "Geographic restrictions configuration (future feature)", - "properties": { - "allowedCountries": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Allow traffic only from specific countries" - }, - "blockedCountries": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Block traffic from specific countries (ISO 3166-1 alpha-2 codes)" - } - } - }, - "GetDeploymentsParams": { - "type": "object", - "properties": { - "environment_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "page": { - "type": [ - "integer", - "null" - ], - "format": "int64" - }, - "per_page": { - "type": [ - "integer", - "null" - ], - "format": "int64" - } - } - }, - "GetEnvironmentVariablesQuery": { - "type": "object", - "properties": { - "environment_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "service_id": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Required by integration-value reveals to bind the plaintext response to\nthe exact service displayed by the client." - }, - "var_id": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Exact manual env-var row to reveal. Required by the dashboard so\nduplicate keys on disjoint environments cannot cross-reveal." - } - } - }, - "GetFunnelMetricsQuery": { - "type": "object", - "properties": { - "country_code": { - "type": [ - "string", - "null" - ] - }, - "end_date": { - "type": [ - "string", - "null" - ], - "format": "date-time" - }, - "environment_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "start_date": { - "type": [ - "string", - "null" - ], - "format": "date-time" - } - } - }, - "GetOrCreateDSNRequest": { - "type": "object", - "properties": { - "base_url": { - "type": [ - "string", - "null" - ] - }, - "deployment_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "environment_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - } - } - }, - "GetProjectSecretsQuery": { - "type": "object", - "properties": { - "environment_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - } - } - }, - "GetProjectSessionReplaysQuery": { - "type": "object", - "required": [ - "project_id" - ], - "properties": { - "environment_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "page": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "minimum": 0 - }, - "per_page": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "minimum": 0 - }, - "project_id": { - "type": "integer", - "format": "int32" - } - } - }, - "GetProjectSessionReplaysResponse": { - "type": "object", - "required": [ - "sessions", - "page", - "per_page", - "total_count" - ], - "properties": { - "page": { - "type": "integer", - "format": "int64", - "minimum": 0 - }, - "per_page": { - "type": "integer", - "format": "int64", - "minimum": 0 - }, - "sessions": { - "type": "array", - "items": { - "$ref": "#/components/schemas/SessionReplayWithVisitorDto" - } - }, - "total_count": { - "type": "integer", - "format": "int64", - "minimum": 0 - } - } - }, - "GetRequest": { - "type": "object", - "description": "Request to get a value by key", - "required": [ - "key" - ], - "properties": { - "key": { - "type": "string", - "description": "The key to retrieve", - "example": "user:123" - }, - "project_id": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Project ID (required for API key/session auth, optional for deployment tokens)", - "example": 1 - } - } - }, - "GetResponse": { - "type": "object", - "description": "Response for get operation", - "properties": { - "value": { - "description": "The value, or null if not found" - } - } - }, - "GetSessionReplayResponse": { - "type": "object", - "required": [ - "session" - ], - "properties": { - "session": { - "$ref": "#/components/schemas/SessionReplayWithVisitorDto" - } - } - }, - "GetUniqueEventsQuery": { - "type": "object", - "properties": { - "page": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "minimum": 0 - }, - "page_size": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "minimum": 0 - } - } - }, - "GetVisitorSessionsQuery": { - "type": "object", - "properties": { - "page": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "minimum": 0 - }, - "per_page": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "minimum": 0 - } - } - }, - "GetVisitorSessionsResponse": { - "type": "object", - "required": [ - "sessions", - "page", - "per_page", - "total_count" - ], - "properties": { - "page": { - "type": "integer", - "format": "int64", - "minimum": 0 - }, - "per_page": { - "type": "integer", - "format": "int64", - "minimum": 0 - }, - "sessions": { - "type": "array", - "items": { - "$ref": "#/components/schemas/SessionReplayWithVisitorDto" - } - }, - "total_count": { - "type": "integer", - "minimum": 0 - } - } - }, - "GitPushEvent": { - "type": "object", - "description": "Git push event information that triggered the deployment", - "required": [ - "repo", - "owner", - "branch", - "commit" - ], - "properties": { - "branch": { - "type": "string", - "description": "Branch that was pushed" - }, - "commit": { - "type": "string", - "description": "Commit SHA" - }, - "owner": { - "type": "string", - "description": "Repository owner/organization" - }, - "repo": { - "type": "string", - "description": "Repository name" - } - } - }, - "GitRefResponse": { - "type": "object", - "description": "Git repository reference response", - "required": [ - "url", - "ref" - ], - "properties": { - "path": { - "type": [ - "string", - "null" - ], - "description": "Path within the repository (for monorepos)" - }, - "ref": { - "type": "string", - "description": "Git reference (branch, tag, or commit)" - }, - "url": { - "type": "string", - "description": "Git repository URL" - } - } - }, - "GitSourcePlan": { - "type": "object", - "description": "Git repository the source platform deploys from", - "required": [ - "owner", - "repo", - "branch", - "is_public" - ], - "properties": { - "branch": { - "type": "string", - "description": "Branch the source platform deploys" - }, - "clone_url": { - "type": [ - "string", - "null" - ], - "description": "Full clone URL, e.g. `https://github.com/owner/repo.git`" - }, - "is_public": { - "type": "boolean", - "description": "True when the repository is public (no credentials on the source\nplatform) \u2014 the project can then build without a git provider\nconnection." - }, - "owner": { - "type": "string", - "description": "Repository owner (organization or user)" - }, - "repo": { - "type": "string", - "description": "Repository name" - } - } - }, - "GlobalConversationResponse": { - "type": "object", - "description": "A conversation in the unified cross-project switcher: carries the project it\nbelongs to (name/slug) so the UI can show where the chat was started and\nlink back to the source.", - "required": [ - "public_id", - "project_id", - "context_type", - "context_id", - "status", - "created_at", - "last_activity_at" - ], - "properties": { - "context_id": { - "type": "string" - }, - "context_type": { - "type": "string" - }, - "created_at": { - "type": "string" - }, - "last_activity_at": { - "type": "string" - }, - "project_id": { - "type": "integer", - "format": "int32" - }, - "project_name": { - "type": [ - "string", - "null" - ] - }, - "project_slug": { - "type": [ - "string", - "null" - ] - }, - "public_id": { - "type": "string" - }, - "status": { - "type": "string" - }, - "title": { - "type": [ - "string", - "null" - ] - } - } - }, - "GlobalEventStatsResponse": { - "type": "object", - "required": [ - "delivered", - "opened", - "clicked", - "bounced", - "complained" - ], - "properties": { - "bounce_rate": { - "type": [ - "number", - "null" - ], - "format": "double" - }, - "bounced": { - "type": "integer", - "format": "int64", - "minimum": 0 - }, - "click_rate": { - "type": [ - "number", - "null" - ], - "format": "double" - }, - "clicked": { - "type": "integer", - "format": "int64", - "minimum": 0 - }, - "complained": { - "type": "integer", - "format": "int64", - "minimum": 0 - }, - "delivered": { - "type": "integer", - "format": "int64", - "minimum": 0 - }, - "open_rate": { - "type": [ - "number", - "null" - ], - "format": "double" - }, - "opened": { - "type": "integer", - "format": "int64", - "minimum": 0 - } - } - }, - "GlobalMrrResponse": { - "type": "object", - "required": [ - "currency", - "current_mrr_minor", - "previous_mrr_minor" - ], - "properties": { - "change_percentage": { - "type": [ - "number", - "null" - ], - "format": "double", - "description": "Percentage change vs 24h ago. Null when previous MRR is zero\n(no baseline to compare against)." - }, - "currency": { - "type": "string" - }, - "current_mrr_minor": { - "type": "integer", - "format": "int64" - }, - "previous_mrr_minor": { - "type": "integer", - "format": "int64", - "description": "MRR 24h before now, reconstructed from the event log." - } - } - }, - "GlobalRecentEventResponse": { - "type": "object", - "required": [ - "id", - "project_id", - "project_name", - "occurred_at", - "event_type" - ], - "properties": { - "amount_minor": { - "type": [ - "integer", - "null" - ], - "format": "int64" - }, - "currency": { - "type": [ - "string", - "null" - ] - }, - "customer_ref": { - "type": [ - "string", - "null" - ] - }, - "event_type": { - "type": "string" - }, - "id": { - "type": "integer", - "format": "int64" - }, - "mrr_minor": { - "type": [ - "integer", - "null" - ], - "format": "int64" - }, - "occurred_at": { - "type": "string", - "format": "date-time" - }, - "project_id": { - "type": "integer", - "format": "int32" - }, - "project_name": { - "type": "string" - } - } - }, - "GlobalRevenueSummaryResponse": { - "type": "object", - "required": [ - "currency", - "current_mrr_minor", - "paid_last_30d_minor", - "refunded_last_30d_minor", - "paid_all_time_minor", - "refunded_all_time_minor", - "active_subscriptions", - "active_customers", - "transactions_last_30d" - ], - "properties": { - "active_customers": { - "type": "integer", - "format": "int64" - }, - "active_subscriptions": { - "type": "integer", - "format": "int64" - }, - "currency": { - "type": "string" - }, - "current_mrr_minor": { - "type": "integer", - "format": "int64" - }, - "paid_all_time_minor": { - "type": "integer", - "format": "int64" - }, - "paid_last_30d_minor": { - "type": "integer", - "format": "int64" - }, - "refunded_all_time_minor": { - "type": "integer", - "format": "int64" - }, - "refunded_last_30d_minor": { - "type": "integer", - "format": "int64" - }, - "transactions_last_30d": { - "type": "integer", - "format": "int64" - } - } - }, - "GroupedPageMetric": { - "type": "object", - "required": [ - "group_key", - "events" - ], - "properties": { - "cls": { - "type": [ - "number", - "null" - ], - "format": "float" - }, - "country_code": { - "type": [ - "string", - "null" - ], - "description": "ISO 3166-1 alpha-2 code of the group's country. Populated for the\ngeographic dimensions (country/region/city) so clients can match map\ngeometries without name-based lookups; null otherwise." - }, - "events": { - "type": "integer", - "format": "int64" - }, - "fcp": { - "type": [ - "number", - "null" - ], - "format": "float" - }, - "group_key": { - "type": "string" - }, - "inp": { - "type": [ - "number", - "null" - ], - "format": "float" - }, - "lcp": { - "type": [ - "number", - "null" - ], - "format": "float" - }, - "ttfb": { - "type": [ - "number", - "null" - ], - "format": "float" - } - } - }, - "GroupedPageMetricsQuery": { - "allOf": [ - { - "$ref": "#/components/schemas/SpeedSegmentFilters", - "description": "Segment filters \u2014 same shape as `PerformanceMetricsQuery`." - }, - { - "type": "object", - "required": [ - "start_date", - "end_date", - "project_id", - "group_by" - ], - "properties": { - "deployment_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "device_type": { - "type": [ - "string", - "null" - ], - "description": "Device type filter: \"desktop\" or \"mobile\"" - }, - "end_date": { - "type": "string", - "format": "date-time" - }, - "environment_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "group_by": { - "type": "string" - }, - "include_bots": { - "type": [ - "boolean", - "null" - ], - "description": "Include crawler/datacenter (bot) samples. Defaults to false." - }, - "project_id": { - "type": "integer", - "format": "int32" - }, - "start_date": { - "type": "string", - "format": "date-time" - } - } - } - ] - }, - "GroupedPageMetricsResponse": { - "type": "object", - "required": [ - "groups", - "total_events", - "grouped_by" - ], - "properties": { - "grouped_by": { - "type": "string" - }, - "groups": { - "type": "array", - "items": { - "$ref": "#/components/schemas/GroupedPageMetric" - } - }, - "total_events": { - "type": "integer", - "format": "int64" - } - } - }, - "HasAnalyticsEventsResponse": { - "type": "object", - "required": [ - "has_events" - ], - "properties": { - "has_events": { - "type": "boolean" - } - } - }, - "HasErrorGroupsResponse": { - "type": "object", - "required": [ - "has_error_groups" - ], - "properties": { - "has_error_groups": { - "type": "boolean" - } - } - }, - "HasEventsQuery": { - "type": "object", - "required": [ - "project_id" - ], - "properties": { - "environment_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "project_id": { - "type": "integer", - "format": "int32" - } - } - }, - "HasEventsResponse": { - "type": "object", - "required": [ - "has_events" - ], - "properties": { - "has_events": { - "type": "boolean" - } - } - }, - "HasMetricsQuery": { - "type": "object", - "required": [ - "project_id" - ], - "properties": { - "project_id": { - "type": "integer", - "format": "int32" - } - } - }, - "HasMetricsResponse": { - "type": "object", - "required": [ - "has_metrics" - ], - "properties": { - "has_metrics": { - "type": "boolean" - } - } - }, - "HealthCheckConfiguration": { - "type": "object", - "description": "Health check configuration", - "required": [ - "port", - "interval", - "timeout", - "retries" - ], - "properties": { - "http_path": { - "type": [ - "string", - "null" - ], - "description": "HTTP path to check (if applicable)" - }, - "interval": { - "type": "integer", - "format": "int32", - "description": "Interval between checks (seconds)", - "minimum": 0 - }, - "port": { - "type": "integer", - "format": "int32", - "description": "Port to check", - "minimum": 0 - }, - "retries": { - "type": "integer", - "format": "int32", - "description": "Number of retries before marking unhealthy", - "minimum": 0 - }, - "timeout": { - "type": "integer", - "format": "int32", - "description": "Timeout for each check (seconds)", - "minimum": 0 - } - } - }, - "HealthCheckEntryResponse": { - "type": "object", - "required": [ - "checked_at", - "status" - ], - "properties": { - "checked_at": { - "type": "string", - "description": "ISO 8601 timestamp of when the probe ran.", - "example": "2026-04-22T11:30:00Z" - }, - "error_message": { - "type": [ - "string", - "null" - ], - "description": "Present only when the probe failed or was degraded." - }, - "response_time_ms": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "TCP connect latency in milliseconds." - }, - "status": { - "type": "string", - "description": "\"operational\" | \"degraded\" | \"down\"", - "example": "operational" - } - } - }, - "HealthResponse": { - "type": "object", - "required": [ - "summaries" - ], - "properties": { - "summaries": { - "type": "array", - "items": { - "$ref": "#/components/schemas/HealthSummary" - } - } - } - }, - "HealthStatus": { - "type": "string", - "description": "Overall health status.", - "enum": [ - "healthy", - "degraded", - "down", - "unknown" - ] - }, - "HealthSummary": { - "type": "object", - "description": "Pre-computed health summary for a project environment.", - "required": [ - "project_id", - "service_name", - "status", - "uptime_pct", - "error_rate", - "p95_latency_ms", - "cpu_usage_pct", - "memory_usage_pct", - "computed_at" - ], - "properties": { - "computed_at": { - "type": "string", - "format": "date-time" - }, - "cpu_usage_pct": { - "type": "number", - "format": "double" - }, - "environment_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "error_rate": { - "type": "number", - "format": "double" - }, - "last_deploy_at": { - "type": [ - "string", - "null" - ], - "format": "date-time" - }, - "last_deploy_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "memory_usage_pct": { - "type": "number", - "format": "double" - }, - "p95_latency_ms": { - "type": "number", - "format": "double" - }, - "project_id": { - "type": "integer", - "format": "int32" - }, - "service_name": { - "type": "string" - }, - "status": { - "$ref": "#/components/schemas/HealthStatus" - }, - "uptime_pct": { - "type": "number", - "format": "double" - } - } - }, - "HeartbeatApiRequest": { - "type": "object", - "properties": { - "architecture": { - "type": [ - "string", - "null" - ], - "description": "Container platform of this node's Docker daemon (`linux/amd64`,\n`linux/arm64`), read from `docker info` by the agent. Absent from\npre-multi-arch agents; the stored value is then left untouched." - }, - "capacity": { - "description": "Resource capacity/usage info as JSON (cpu_usage, memory_usage, etc.)" - }, - "containers": { - "type": [ - "array", - "null" - ], - "items": { - "$ref": "#/components/schemas/ContainerInventoryItem" - }, - "description": "Container inventory for reconciliation (sent on first heartbeat after agent startup).\nEach entry has `container_id` and `container_name` of temps-managed containers." - }, - "labels": { - "description": "Updated node labels for scheduling (allows runtime label changes)." - } - } - }, - "HeartbeatResponse": { - "type": "object", - "required": [ - "status", - "message" - ], - "properties": { - "message": { - "type": "string" - }, - "status": { - "type": "string" - } - } - }, - "HierarchyLevel": { - "type": "object", - "description": "Describes a level in the data source hierarchy", - "required": [ - "level", - "name", - "container_type", - "can_list_containers", - "can_list_entities" - ], - "properties": { - "can_list_containers": { - "type": "boolean", - "description": "Can list containers at this level?", - "example": true - }, - "can_list_entities": { - "type": "boolean", - "description": "Can list entities at this level?", - "example": false - }, - "container_type": { - "type": "string", - "description": "Type of container at this level", - "example": "database" - }, - "level": { - "type": "integer", - "format": "int32", - "description": "Level number (0 = root)", - "example": 0, - "minimum": 0 - }, - "name": { - "type": "string", - "description": "Human-readable name for this level", - "example": "root" - } - } - }, - "HistogramSummary": { - "type": "object", - "description": "An explicit-bucket histogram aggregated over a time bucket.\n\nCarries the reduced scalars (count/sum/min/max) plus the explicit bucket\nlayout \u2014 `bounds` (the upper bounds) and `bucket_counts` (observation counts,\nsummed element-wise across the window; length is `bounds.len() + 1`, the last\nentry being the +Inf overflow bucket). With these, a caller can reconstruct\nany quantile (e.g. p95) via cumulative-count interpolation.", - "required": [ - "count", - "sum", - "bounds", - "bucket_counts" - ], - "properties": { - "bounds": { - "type": "array", - "items": { - "type": "number", - "format": "double" - }, - "description": "Explicit bucket upper bounds (OTLP `explicit_bounds`), ascending." - }, - "bucket_counts": { - "type": "array", - "items": { - "type": "integer", - "format": "int64", - "minimum": 0 - }, - "description": "Per-bucket observation counts summed element-wise across the window.\nLength is `bounds.len() + 1` (the trailing element is the +Inf bucket)." - }, - "count": { - "type": "integer", - "format": "int64", - "description": "Total observation count summed across the bucket window.", - "minimum": 0 - }, - "max": { - "type": [ - "number", - "null" - ], - "format": "double", - "description": "Maximum observed value, when reported by the producer." - }, - "min": { - "type": [ - "number", - "null" - ], - "format": "double", - "description": "Minimum observed value, when reported by the producer." - }, - "sum": { - "type": "number", - "format": "double", - "description": "Sum of observed values across the bucket window." - } - } - }, - "HostnameChange": { - "type": "object", - "description": "A single generated-hostname change in a flatten preview/apply.", - "required": [ - "kind", - "id", - "old", - "new" - ], - "properties": { - "id": { - "type": "integer", - "format": "int32", - "description": "Row id of the affected record." - }, - "kind": { - "type": "string", - "description": "`\"deployment\"` or `\"environment\"`." - }, - "new": { - "type": "string" - }, - "old": { - "type": "string" - } - } - }, - "HostnamePreviewResponse": { - "type": "object", - "description": "Combined preview of a hostname-mode change.", - "required": [ - "hostname_changes", - "dns_changes", - "total" - ], - "properties": { - "dns_changes": { - "type": "array", - "items": { - "$ref": "#/components/schemas/DnsRecordChange" - } - }, - "hostname_changes": { - "type": "array", - "items": { - "$ref": "#/components/schemas/HostnameChange" - } - }, - "total": { - "type": "integer", - "minimum": 0 - }, - "zone_access_ok": { - "type": [ - "boolean", - "null" - ], - "description": "Whether the provider token can manage this zone (None if not checked)." - } - } - }, - "HourlyPageSessions": { - "type": "object", - "required": [ - "timestamp", - "session_count", - "event_count", - "avg_duration_seconds" - ], - "properties": { - "avg_duration_seconds": { - "type": "number", - "format": "double" - }, - "event_count": { - "type": "integer", - "format": "int64" - }, - "session_count": { - "type": "integer", - "format": "int64" - }, - "timestamp": { - "type": "string" - } - } - }, - "HourlyVisitsQuery": { - "type": "object", - "required": [ - "start_date", - "end_date" - ], - "properties": { - "aggregation_level": { - "$ref": "#/components/schemas/AggregationLevel", - "description": "Aggregation level: events (page views), sessions (unique sessions), or visitors (unique visitors)" - }, - "end_date": { - "type": "string", - "format": "date-time" - }, - "environment_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "start_date": { - "type": "string", - "format": "date-time" - } - } - }, - "HttpChallengeDebugResponse": { - "type": "object", - "required": [ - "domain", - "challenge_exists", - "dns_a_records", - "dns_aaaa_records" - ], - "properties": { - "challenge_exists": { - "type": "boolean" - }, - "challenge_token": { - "type": [ - "string", - "null" - ] - }, - "challenge_url": { - "type": [ - "string", - "null" - ], - "description": "The full URL that Let's Encrypt will try to access to validate the challenge" - }, - "dns_a_records": { - "type": "array", - "items": { - "type": "string" - }, - "description": "IPv4 addresses the domain points to" - }, - "dns_aaaa_records": { - "type": "array", - "items": { - "type": "string" - }, - "description": "IPv6 addresses the domain points to" - }, - "dns_error": { - "type": [ - "string", - "null" - ], - "description": "Any DNS resolution errors" - }, - "domain": { - "type": "string" - }, - "validation_url": { - "type": [ - "string", - "null" - ], - "description": "The ACME validation URL (internal to ACME protocol)" - } - } - }, - "ImportCredentials": { - "type": "object", - "description": "Platform-specific credentials for accessing the source system.\n\nFor platforms like Vercel and Railway, this contains the API token.\nFor self-hosted platforms like Coolify and Dokploy, this also contains\nthe `base_url` of the instance.\n\nLocal importers (Docker) can use `ImportCredentials::none()`.", - "properties": { - "base_url": { - "type": [ - "string", - "null" - ], - "description": "Base URL override (for self-hosted platforms like Coolify, Dokploy)\n\nExample: `https://coolify.example.com`" - }, - "extra": { - "type": "object", - "description": "Additional platform-specific parameters", - "additionalProperties": { - "type": "string" - }, - "propertyNames": { - "type": "string" - } - }, - "team_id": { - "type": [ - "string", - "null" - ], - "description": "Team or organization ID (for platforms with team scoping like Vercel)" - }, - "token": { - "type": [ - "string", - "null" - ], - "description": "API token / bearer token for the source platform" - } - } - }, - "ImportExecutionStatus": { - "type": "string", - "description": "Import execution status", - "enum": [ - "pending", - "inprogress", - "completed", - "failed" - ] - }, - "ImportExternalServiceRequest": { - "type": "object", - "description": "Request to import a Docker container as a managed service", - "required": [ - "name", - "service_type", - "parameters", - "container_id" - ], - "properties": { - "container_id": { - "type": "string", - "description": "Container ID or name to import", - "example": "abc123def456" - }, - "name": { - "type": "string", - "description": "Name to register the service as in Temps", - "example": "production-database" - }, - "parameters": { - "type": "object", - "description": "Service configuration parameters", - "additionalProperties": {}, - "propertyNames": { - "type": "string" - } - }, - "service_type": { - "$ref": "#/components/schemas/ServiceTypeRoute", - "description": "Service type" - }, - "version": { - "type": [ - "string", - "null" - ], - "description": "Optional version override" - } - } - }, - "ImportOutcomeResponse": { - "type": "object", - "required": [ - "rows_read", - "inserted", - "updated", - "skipped_stale", - "skipped_invalid", - "errors" - ], - "properties": { - "errors": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ImportRowErrorResponse" - } - }, - "inserted": { - "type": "integer", - "minimum": 0 - }, - "rows_read": { - "type": "integer", - "minimum": 0 - }, - "skipped_invalid": { - "type": "integer", - "minimum": 0 - }, - "skipped_stale": { - "type": "integer", - "minimum": 0 - }, - "updated": { - "type": "integer", - "minimum": 0 - } - } - }, - "ImportPlan": { - "type": "object", - "description": "Complete import plan describing all operations to onboard a workload.\n\nThe plan is generated from a snapshot and presented to the user for review\nbefore any resources are created. Users can modify individual items\n(skip services, change actions) before approving execution.", - "required": [ - "version", - "source", - "source_id", - "project", - "environment", - "deployment", - "summary", - "metadata" - ], - "properties": { - "additional_deployments": { - "type": "array", - "items": { - "$ref": "#/components/schemas/DeploymentConfiguration" - }, - "description": "Additional deployments (workers, cron jobs, etc.)" - }, - "cost_analysis": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/CostAnalysis", - "description": "Cost, overprovisioning, and savings analysis. Populated by importers\nthat can observe the whole source cluster (currently Kubernetes);\n`None` for container/platform imports." - } - ] - }, - "deployment": { - "$ref": "#/components/schemas/DeploymentConfiguration", - "description": "Primary deployment configuration" - }, - "domains": { - "type": "array", - "items": { - "$ref": "#/components/schemas/DomainPlan" - }, - "description": "Custom domains to migrate" - }, - "environment": { - "$ref": "#/components/schemas/EnvironmentConfiguration", - "description": "Environment configuration" - }, - "metadata": { - "$ref": "#/components/schemas/PlanMetadata", - "description": "Plan metadata" - }, - "project": { - "$ref": "#/components/schemas/ProjectConfiguration", - "description": "Project configuration" - }, - "services": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ServicePlan" - }, - "description": "Services to migrate (databases, caches, blob stores)\n\nEach service has an `action` field the user can change before execution." - }, - "source": { - "type": "string", - "description": "Source system this plan was generated from" - }, - "source_id": { - "type": "string", - "description": "Source workload / project ID in the source system" - }, - "steps": { - "type": "array", - "items": { - "$ref": "#/components/schemas/MigrationStep" - }, - "description": "Ordered list of migration steps that will be executed.\n\nThis is the human-readable execution plan. Each step describes what\nwill happen, what risks are involved, and what the user should verify.\nSteps are executed in order. If a step fails, execution stops and\nalready-created resources are reported for manual cleanup." - }, - "summary": { - "$ref": "#/components/schemas/MigrationSummary", - "description": "Human-readable summary of the entire migration" - }, - "version": { - "type": "string", - "description": "Plan version for compatibility tracking" - } - } - }, - "ImportRowErrorResponse": { - "type": "object", - "required": [ - "row", - "reason" - ], - "properties": { - "reason": { - "type": "string" - }, - "row": { - "type": "integer", - "minimum": 0 - } - } - }, - "ImportSelector": { - "type": "object", - "description": "Selector for discovering workloads", - "properties": { - "label_filter": { - "type": [ - "object", - "null" - ], - "description": "Filter by labels/tags", - "additionalProperties": { - "type": "string" - }, - "propertyNames": { - "type": "string" - } - }, - "limit": { - "type": [ - "integer", - "null" - ], - "description": "Limit number of results", - "minimum": 0 - }, - "name_pattern": { - "type": [ - "string", - "null" - ], - "description": "Filter by name pattern (glob/regex)" - }, - "status_filter": { - "type": [ - "array", - "null" - ], - "items": { - "type": "string" - }, - "description": "Filter by status (running, stopped, deployed, etc.)" - }, - "workload_type_filter": { - "type": [ - "array", - "null" - ], - "items": { - "type": "string" - }, - "description": "Filter by workload type (container, function, static-site, etc.)" - } - } - }, - "ImportSource": { - "type": "string", - "description": "Import source identifier", - "enum": [ - "docker", - "coolify", - "dokploy", - "vercel", - "netlify", - "railway", - "render", - "fly", - "kubernetes", - "caprover", - "portainer", - "kamal", - "custom" - ] - }, - "ImportSourceCapabilities": { - "type": "object", - "description": "Source capabilities", - "required": [ - "supports_volumes", - "supports_networks", - "supports_health_checks", - "supports_resource_limits", - "supports_build", - "supports_services", - "supports_domains", - "supports_project_snapshot", - "supports_cost_analysis", - "requires_credentials" - ], - "properties": { - "requires_credentials": { - "type": "boolean", - "description": "Whether this source requires API credentials (token, base URL)" - }, - "supports_build": { - "type": "boolean" - }, - "supports_cost_analysis": { - "type": "boolean", - "description": "Supports cluster cost + overprovisioning analysis in the plan" - }, - "supports_domains": { - "type": "boolean", - "description": "Supports custom domain migration" - }, - "supports_health_checks": { - "type": "boolean" - }, - "supports_networks": { - "type": "boolean" - }, - "supports_project_snapshot": { - "type": "boolean", - "description": "Supports full project-level snapshots" - }, - "supports_resource_limits": { - "type": "boolean" - }, - "supports_services": { - "type": "boolean", - "description": "Supports service migration (databases, caches, etc.)" - }, - "supports_volumes": { - "type": "boolean" - } - } - }, - "ImportSourceInfo": { - "type": "object", - "description": "Information about an import source", - "required": [ - "source", - "name", - "version", - "available", - "capabilities" - ], - "properties": { - "available": { - "type": "boolean", - "description": "Whether the source is currently available" - }, - "capabilities": { - "$ref": "#/components/schemas/ImportSourceCapabilities", - "description": "Capabilities" - }, - "name": { - "type": "string", - "description": "Human-readable name" - }, - "source": { - "$ref": "#/components/schemas/ImportSource", - "description": "Source identifier" - }, - "version": { - "type": "string", - "description": "Source version" - } - } - }, - "ImportStatusResponse": { - "type": "object", - "description": "Response with import status", - "required": [ - "session_id", - "status", - "errors", - "warnings", - "created_at", - "updated_at" - ], - "properties": { - "created_at": { - "type": "string", - "format": "date-time", - "description": "Created at timestamp" - }, - "deployment_id": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Created deployment ID" - }, - "environment_id": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Created environment ID" - }, - "errors": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Errors (if any)" - }, - "plan": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/ImportPlan", - "description": "Import plan" - } - ] - }, - "project_id": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Created project ID" - }, - "session_id": { - "type": "string", - "description": "Session ID" - }, - "status": { - "$ref": "#/components/schemas/ImportExecutionStatus", - "description": "Current status" - }, - "updated_at": { - "type": "string", - "format": "date-time", - "description": "Updated at timestamp" - }, - "validation": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/ValidationReport", - "description": "Validation report" - } - ] - }, - "warnings": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Warnings (if any)" - } - } - }, - "IncidentBucket": { - "type": "object", - "required": [ - "bucket_start", - "total_incidents", - "minor_incidents", - "major_incidents", - "critical_incidents", - "resolved_incidents", - "active_incidents" - ], - "properties": { - "active_incidents": { - "type": "integer", - "format": "int64" - }, - "avg_resolution_time_minutes": { - "type": [ - "number", - "null" - ], - "format": "double" - }, - "bucket_start": { - "type": "string", - "format": "date-time" - }, - "critical_incidents": { - "type": "integer", - "format": "int64" - }, - "major_incidents": { - "type": "integer", - "format": "int64" - }, - "minor_incidents": { - "type": "integer", - "format": "int64" - }, - "resolved_incidents": { - "type": "integer", - "format": "int64" - }, - "total_incidents": { - "type": "integer", - "format": "int64" - } - } - }, - "IncidentBucketedResponse": { - "type": "object", - "required": [ - "project_id", - "interval", - "buckets" - ], - "properties": { - "buckets": { - "type": "array", - "items": { - "$ref": "#/components/schemas/IncidentBucket" - } - }, - "environment_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "interval": { - "type": "string" - }, - "project_id": { - "type": "integer", - "format": "int32" - } - } - }, - "IncidentResponse": { - "type": "object", - "required": [ - "id", - "project_id", - "title", - "severity", - "status", - "started_at", - "created_at", - "updated_at" - ], - "properties": { - "created_at": { - "type": "string", - "format": "date-time" - }, - "description": { - "type": [ - "string", - "null" - ] - }, - "environment_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "id": { - "type": "integer", - "format": "int32" - }, - "monitor_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "project_id": { - "type": "integer", - "format": "int32" - }, - "resolved_at": { - "type": [ - "string", - "null" - ], - "format": "date-time" - }, - "severity": { - "type": "string" - }, - "started_at": { - "type": "string", - "format": "date-time" - }, - "status": { - "type": "string" - }, - "title": { - "type": "string" - }, - "updated_at": { - "type": "string", - "format": "date-time" - } - } - }, - "IncidentUpdateResponse": { - "type": "object", - "required": [ - "id", - "incident_id", - "status", - "message", - "created_at" - ], - "properties": { - "created_at": { - "type": "string", - "format": "date-time" - }, - "id": { - "type": "integer", - "format": "int32" - }, - "incident_id": { - "type": "integer", - "format": "int32" - }, - "message": { - "type": "string" - }, - "status": { - "type": "string" - } - } - }, - "IncrRequest": { - "type": "object", - "description": "Request to increment a value", - "required": [ - "key" - ], - "properties": { - "amount": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "description": "Amount to increment by (default: 1)" - }, - "key": { - "type": "string", - "description": "The key to increment", - "example": "counter" - }, - "project_id": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Project ID (required for API key/session auth, optional for deployment tokens)", - "example": 1 - } - } - }, - "IncrResponse": { - "type": "object", - "description": "Response for increment operation", - "required": [ - "value" - ], - "properties": { - "value": { - "type": "integer", - "format": "int64", - "description": "New value after increment", - "example": 42 - } - } - }, - "InitAuthResponse": { - "type": "object", - "required": [ - "auth_url", - "session_token" - ], - "properties": { - "auth_url": { - "type": "string" - }, - "session_token": { - "type": "string" - } - } - }, - "Insight": { - "type": "object", - "description": "An anomaly insight.", - "required": [ - "id", - "project_id", - "service_name", - "severity", - "status", - "title", - "description", - "anomaly_ids", - "started_at", - "created_at", - "updated_at" - ], - "properties": { - "anomaly_ids": { - "type": "array", - "items": { - "type": "integer", - "format": "int64" - } - }, - "correlated_deploy_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "created_at": { - "type": "string", - "format": "date-time" - }, - "description": { - "type": "string" - }, - "environment": { - "type": [ - "string", - "null" - ] - }, - "id": { - "type": "integer", - "format": "int64" - }, - "metric_name": { - "type": [ - "string", - "null" - ] - }, - "project_id": { - "type": "integer", - "format": "int32" - }, - "resolved_at": { - "type": [ - "string", - "null" - ], - "format": "date-time" - }, - "service_name": { - "type": "string" - }, - "severity": { - "$ref": "#/components/schemas/InsightSeverity" - }, - "started_at": { - "type": "string", - "format": "date-time" - }, - "status": { - "$ref": "#/components/schemas/InsightStatus" - }, - "title": { - "type": "string" - }, - "updated_at": { - "type": "string", - "format": "date-time" - } - } - }, - "InsightSeverity": { - "type": "string", - "description": "Severity of an anomaly insight.", - "enum": [ - "low", - "medium", - "high", - "critical" - ] - }, - "InsightStatus": { - "type": "string", - "description": "Status of an insight.", - "enum": [ - "active", - "resolved" - ] - }, - "InsightsResponse": { - "type": "object", - "required": [ - "data", - "count" - ], - "properties": { - "count": { - "type": "integer", - "minimum": 0 - }, - "data": { - "type": "array", - "items": { - "$ref": "#/components/schemas/Insight" - } - } - } - }, - "IntegrationResponse": { - "type": "object", - "required": [ - "id", - "project_id", - "provider", - "webhook_path_token", - "webhook_path", - "status", - "has_secret", - "created_at" - ], - "properties": { - "config": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/ProviderConfig", - "description": "Typed provider config \u2014 allowlist and metered-billing mode. Null\nwhen the operator hasn't configured one yet (accept everything)." - } - ] - }, - "created_at": { - "type": "string", - "format": "date-time" - }, - "has_secret": { - "type": "boolean" - }, - "id": { - "type": "integer", - "format": "int32" - }, - "last_event_at": { - "type": [ - "string", - "null" - ], - "format": "date-time" - }, - "project_id": { - "type": "integer", - "format": "int32" - }, - "provider": { - "type": "string" - }, - "status": { - "type": "string" - }, - "webhook_path": { - "type": "string", - "description": "Relative path the UI can display and copy. The frontend builds\nthe full URL by prefixing its own origin." - }, - "webhook_path_token": { - "type": "string", - "description": "Unguessable token embedded in the public webhook URL. The full\nURL is `{api_origin}/webhooks/revenue/{provider}/{webhook_path_token}`." - } - } - }, - "IpAccessControlQuery": { - "type": "object", - "description": "Query parameters for listing IP access control rules", - "properties": { - "action": { - "type": [ - "string", - "null" - ], - "description": "Filter by action (\"block\" or \"allow\")" - } - } - }, - "IpAccessControlResponse": { - "type": "object", - "description": "Response model for IP access control rules", - "required": [ - "id", - "ip_address", - "action", - "created_at", - "updated_at" - ], - "properties": { - "action": { - "type": "string" - }, - "created_at": { - "type": "string", - "example": "2025-10-12T12:15:47.609Z" - }, - "created_by": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "id": { - "type": "integer", - "format": "int32" - }, - "ip_address": { - "type": "string" - }, - "reason": { - "type": [ - "string", - "null" - ] - }, - "updated_at": { - "type": "string", - "example": "2025-10-12T12:15:47.609Z" - } - } - }, - "JobStatusResponse": { - "type": "object", - "description": "Snapshot of a background job. `status` is one of \"running\" | \"exited\"\n| \"failed\"; `exit_code` is populated only when `status == \"exited\"`.", - "required": [ - "status", - "stdout", - "stderr" - ], - "properties": { - "exit_code": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "reason": { - "type": [ - "string", - "null" - ] - }, - "status": { - "type": "string" - }, - "stderr": { - "type": "string" - }, - "stdout": { - "type": "string" - } - } - }, - "JobSummaryResponse": { - "type": "object", - "description": "Row in the jobs list. Omits stdout/stderr so a noisy dev server doesn't\nbloat the list payload \u2014 callers drill into `GET /jobs/{id}` for the\nfull buffer.", - "required": [ - "id", - "status", - "cmd", - "started_at" - ], - "properties": { - "cmd": { - "type": "string" - }, - "exit_code": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "id": { - "type": "string" - }, - "reason": { - "type": [ - "string", - "null" - ] - }, - "started_at": { - "type": "string" - }, - "status": { - "type": "string" - } - } - }, - "JoinTokenStatusResponse": { - "type": "object", - "description": "Response for join token status check", - "required": [ - "has_token" - ], - "properties": { - "has_token": { - "type": "boolean", - "description": "Whether a join token has been configured" - } - } - }, - "JourneyEvent": { - "type": "object", - "description": "A single event in the visitor journey timeline", - "required": [ - "id", - "event_type", - "event_name", - "occurred_at", - "is_entry", - "is_exit", - "is_bounce" - ], - "properties": { - "event_data": { - "description": "Custom event properties (for custom events)" - }, - "event_name": { - "type": "string", - "description": "Resolved event name (event_name for custom events, event_type for system events)" - }, - "event_type": { - "type": "string", - "description": "Event type: \"page_view\", \"page_leave\", \"custom\", \"web_vitals\"" - }, - "id": { - "type": "integer", - "format": "int64", - "description": "Event ID" - }, - "is_bounce": { - "type": "boolean", - "description": "Whether this was a bounce" - }, - "is_entry": { - "type": "boolean", - "description": "Whether this is the entry page of the session" - }, - "is_exit": { - "type": "boolean", - "description": "Whether this is the exit page of the session" - }, - "occurred_at": { - "type": "string", - "format": "date-time", - "description": "When the event occurred" - }, - "page_path": { - "type": [ - "string", - "null" - ], - "description": "Page path where the event happened" - }, - "page_title": { - "type": [ - "string", - "null" - ], - "description": "Page title (if available)" - }, - "referrer": { - "type": [ - "string", - "null" - ], - "description": "Referrer URL for this event" - }, - "scroll_depth": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Scroll depth percentage (0-100)" - }, - "session_page_number": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Page number within the session (1-indexed)" - }, - "time_on_page": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Time spent on page in seconds (computed, not from column)" - } - } - }, - "JourneySession": { - "type": "object", - "description": "A session within the visitor journey, grouping events", - "required": [ - "session_id", - "started_at", - "duration_seconds", - "page_views", - "events_count", - "is_bounced", - "is_engaged", - "events" - ], - "properties": { - "channel": { - "type": [ - "string", - "null" - ], - "description": "Traffic source: channel (e.g. \"organic\", \"direct\", \"social\")" - }, - "duration_seconds": { - "type": "integer", - "format": "int64", - "description": "Session duration in seconds" - }, - "ended_at": { - "type": [ - "string", - "null" - ], - "format": "date-time", - "description": "When the session ended" - }, - "entry_path": { - "type": [ - "string", - "null" - ], - "description": "Entry page path" - }, - "events": { - "type": "array", - "items": { - "$ref": "#/components/schemas/JourneyEvent" - }, - "description": "Events within this session, ordered chronologically" - }, - "events_count": { - "type": "integer", - "format": "int64", - "description": "Total events in this session" - }, - "exit_path": { - "type": [ - "string", - "null" - ], - "description": "Exit page path" - }, - "is_bounced": { - "type": "boolean", - "description": "Whether the session was a bounce" - }, - "is_engaged": { - "type": "boolean", - "description": "Whether the visitor was engaged (had non-pageview events)" - }, - "page_views": { - "type": "integer", - "format": "int64", - "description": "Number of page views in this session" - }, - "referrer": { - "type": [ - "string", - "null" - ], - "description": "Traffic source: referrer URL" - }, - "referrer_hostname": { - "type": [ - "string", - "null" - ], - "description": "Traffic source: referrer hostname" - }, - "session_id": { - "type": "integer", - "format": "int32", - "description": "Session internal ID" - }, - "started_at": { - "type": "string", - "format": "date-time", - "description": "When the session started" - }, - "utm_campaign": { - "type": [ - "string", - "null" - ], - "description": "UTM campaign parameter" - }, - "utm_medium": { - "type": [ - "string", - "null" - ], - "description": "UTM medium parameter" - }, - "utm_source": { - "type": [ - "string", - "null" - ], - "description": "UTM source parameter" - } - } - }, - "KeysRequest": { - "type": "object", - "description": "Request to get keys matching a pattern", - "required": [ - "pattern" - ], - "properties": { - "pattern": { - "type": "string", - "description": "Pattern to match (supports * and ? wildcards)", - "example": "user:*" - }, - "project_id": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Project ID (required for API key/session auth, optional for deployment tokens)", - "example": 1 - } - } - }, - "KeysResponse": { - "type": "object", - "description": "Response for keys operation", - "required": [ - "keys" - ], - "properties": { - "keys": { - "type": "array", - "items": { - "type": "string" - }, - "description": "List of matching keys", - "example": [ - "user:1", - "user:2", - "user:3" - ] - } - } - }, - "KillJobBody": { - "type": "object", - "properties": { - "force": { - "type": "boolean", - "description": "When true, sends SIGKILL immediately. Defaults to SIGTERM so the\nprocess gets a chance to flush (mirrors `Command.kill()` in\n`@vercel/sandbox`, which also accepts a signal override)." - } - }, - "additionalProperties": false - }, - "KnownAiAgentsResponse": { - "type": "object", - "description": "Response listing every AI agent the detector knows about.", - "required": [ - "items" - ], - "properties": { - "items": { - "type": "array", - "items": { - "$ref": "#/components/schemas/AiAgentDescriptor" - } - } - } - }, - "KvStatusResponse": { - "type": "object", - "description": "Response for KV service status", - "required": [ - "enabled", - "healthy" - ], - "properties": { - "docker_image": { - "type": [ - "string", - "null" - ], - "description": "Docker image being used", - "example": "gotempsh/redis-walg:8-bookworm" - }, - "enabled": { - "type": "boolean", - "description": "Whether the KV service is enabled" - }, - "healthy": { - "type": "boolean", - "description": "Whether the underlying Redis service is healthy" - }, - "version": { - "type": [ - "string", - "null" - ], - "description": "Service version", - "example": "7.2" - } - } - }, - "LemonSqueezyConfig": { - "type": "object", - "properties": { - "product_allowlist": { - "type": "array", - "items": { - "type": "string" - } - }, - "variant_allowlist": { - "type": "array", - "items": { - "type": "string" - } - } - } - }, - "LetsEncryptSettings": { - "type": "object", - "properties": { - "email": { - "type": [ - "string", - "null" - ], - "default": null - }, - "environment": { - "type": "string", - "default": "production" - } - } - }, - "LineContext": { - "type": "object", - "description": "Raw surrounding lines for a single match (grep -C style).", - "required": [ - "before", - "after" - ], - "properties": { - "after": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ContextLine" - }, - "description": "Lines immediately after the match, oldest-first." - }, - "before": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ContextLine" - }, - "description": "Lines immediately before the match, oldest-first." - } - } - }, - "LinkServiceRequest": { - "type": "object", - "required": [ - "project_id" - ], - "properties": { - "project_id": { - "type": "integer", - "format": "int32" - } - } - }, - "ListAgentsResponse": { - "type": "object", - "required": [ - "items", - "total" - ], - "properties": { - "items": { - "type": "array", - "items": { - "$ref": "#/components/schemas/AgentConfigResponse" - } - }, - "total": { - "type": "integer", - "minimum": 0 - } - } - }, - "ListApiKeysQuery": { - "type": "object", - "properties": { - "page": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "minimum": 0 - }, - "page_size": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "minimum": 0 - } - } - }, - "ListAuditLogsQuery": { - "type": "object", - "description": "Query parameters for listing audit logs.\n\nEvery field is optional \u2014 omitting one means \"don't filter on it\". Deriving\n`IntoParams` makes utoipa render them as optional query params with the\ncorrect types; the previous hand-written `params((\"operation_type\", Query,\n\u2026))` tuples defaulted every param to `required: true, type: string`, which\nmisled both API clients and the AI `describe_api`/`call_api` tools into\nthinking all filters were mandatory.", - "properties": { - "from": { - "type": [ - "string", - "null" - ], - "format": "date-time", - "description": "Start timestamp (milliseconds since epoch)" - }, - "limit": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Maximum number of logs to return" - }, - "offset": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Number of logs to skip" - }, - "operation_type": { - "type": [ - "string", - "null" - ], - "description": "Filter logs by operation type (omit for all)" - }, - "to": { - "type": [ - "string", - "null" - ], - "format": "date-time", - "description": "End timestamp (milliseconds since epoch)" - }, - "user_id": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Filter logs by user ID (omit for all users)" - } - } - }, - "ListBlobsQuery": { - "type": "object", - "description": "Query parameters for listing blobs", - "properties": { - "cursor": { - "type": [ - "string", - "null" - ], - "description": "Continuation token for pagination" - }, - "limit": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Maximum number of items to return", - "example": 100 - }, - "prefix": { - "type": [ - "string", - "null" - ], - "description": "Prefix to filter by", - "example": "images/" - }, - "project_id": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Project ID (required for API key/session auth, optional for deployment tokens)", - "example": 1 - } - } - }, - "ListBlobsResponse": { - "type": "object", - "description": "Response for listing blobs", - "required": [ - "blobs", - "hasMore" - ], - "properties": { - "blobs": { - "type": "array", - "items": { - "$ref": "#/components/schemas/BlobResponse" - }, - "description": "List of blobs" - }, - "cursor": { - "type": [ - "string", - "null" - ], - "description": "Continuation token for next page" - }, - "hasMore": { - "type": "boolean", - "description": "Whether there are more results", - "example": false - } - } - }, - "ListCustomDomainsResponse": { - "type": "object", - "required": [ - "domains", - "total" - ], - "properties": { - "domains": { - "type": "array", - "items": { - "$ref": "#/components/schemas/CustomDomainResponse" - } - }, - "total": { - "type": "integer", - "minimum": 0 - } - } - }, - "ListDeploymentTokensQuery": { - "type": "object", - "properties": { - "page": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "example": 1, - "minimum": 0 - }, - "page_size": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "example": 20, - "minimum": 0 - } - } - }, - "ListDomainsResponse": { - "type": "object", - "required": [ - "domains", - "total", - "page", - "page_size" - ], - "properties": { - "domains": { - "type": "array", - "items": { - "$ref": "#/components/schemas/DomainResponse" - } - }, - "page": { - "type": "integer", - "format": "int64", - "minimum": 0 - }, - "page_size": { - "type": "integer", - "format": "int64", - "minimum": 0 - }, - "total": { - "type": "integer", - "format": "int64", - "minimum": 0 - } - } - }, - "ListEntitiesQuery": { - "type": "object", - "properties": { - "limit": { - "type": "integer", - "description": "Maximum number of entities to return", - "example": 100, - "minimum": 0 - }, - "token": { - "type": [ - "string", - "null" - ], - "description": "Continuation token for pagination (backend-specific)" - } - } - }, - "ListErrorEventsQuery": { - "type": "object", - "properties": { - "page": { - "type": "integer", - "format": "int64", - "minimum": 0 - }, - "page_size": { - "type": "integer", - "format": "int64", - "minimum": 0 - } - } - }, - "ListErrorGroupsQuery": { - "type": "object", - "properties": { - "end_date": { - "type": [ - "string", - "null" - ], - "format": "date-time" - }, - "environment_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "page": { - "type": "integer", - "format": "int64", - "minimum": 0 - }, - "page_size": { - "type": "integer", - "format": "int64", - "minimum": 0 - }, - "sort_by": { - "type": [ - "string", - "null" - ] - }, - "sort_order": { - "type": "string" - }, - "start_date": { - "type": [ - "string", - "null" - ], - "format": "date-time" - }, - "status": { - "type": [ - "string", - "null" - ] - } - } - }, - "ListJobsResponse": { - "type": "object", - "required": [ - "items" - ], - "properties": { - "items": { - "type": "array", - "items": { - "$ref": "#/components/schemas/JobSummaryResponse" - } - } - } - }, - "ListMcpsResponse": { - "type": "object", - "description": "Concrete list wrapper for MCP server definitions (utoipa requires non-generic types).", - "required": [ - "items", - "total" - ], - "properties": { - "items": { - "type": "array", - "items": { - "$ref": "#/components/schemas/McpDefinitionResponse" - } - }, - "total": { - "type": "integer", - "minimum": 0 - } - } - }, - "ListOnDemandCertsResponse": { - "type": "object", - "description": "Paginated list of on-demand cert attempts (ADR-018 \u00a75 console \"Certificates\"\nsurface). Joined with current `domains.status`, newest first.", - "required": [ - "certs", - "total", - "page", - "page_size" - ], - "properties": { - "certs": { - "type": "array", - "items": { - "$ref": "#/components/schemas/OnDemandCertRow" - } - }, - "page": { - "type": "integer", - "format": "int64", - "minimum": 0 - }, - "page_size": { - "type": "integer", - "format": "int64", - "minimum": 0 - }, - "total": { - "type": "integer", - "format": "int64", - "minimum": 0 - } - } - }, - "ListOrdersResponse": { - "type": "object", - "required": [ - "orders" - ], - "properties": { - "orders": { - "type": "array", - "items": { - "$ref": "#/components/schemas/AcmeOrderResponse" - } - } - } - }, - "ListPresetsResponse": { - "type": "object", - "required": [ - "presets", - "total" - ], - "properties": { - "presets": { - "type": "array", - "items": { - "$ref": "#/components/schemas/PresetResponse" - } - }, - "total": { - "type": "integer", - "minimum": 0 - } - } - }, - "ListRunsResponse": { - "type": "object", - "required": [ - "items", - "total", - "page", - "page_size" - ], - "properties": { - "items": { - "type": "array", - "items": { - "$ref": "#/components/schemas/AgentRunResponse" - } - }, - "page": { - "type": "integer", - "format": "int64", - "minimum": 0 - }, - "page_size": { - "type": "integer", - "format": "int64", - "minimum": 0 - }, - "total": { - "type": "integer", - "format": "int64", - "minimum": 0 - } - } - }, - "ListSandboxesResponse": { - "type": "object", - "description": "SDK list response: `{ sandboxes: [...], pagination: {...} }`.", - "required": [ - "sandboxes", - "pagination" - ], - "properties": { - "pagination": { - "$ref": "#/components/schemas/Pagination" - }, - "sandboxes": { - "type": "array", - "items": { - "$ref": "#/components/schemas/SandboxInner" - } - } - } - }, - "ListScansQuery": { - "type": "object", - "properties": { - "page": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "example": 1, - "minimum": 0 - }, - "page_size": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "example": 20, - "minimum": 0 - } - } - }, - "ListSecretsResponse": { - "type": "object", - "required": [ - "items", - "total" - ], - "properties": { - "items": { - "type": "array", - "items": { - "$ref": "#/components/schemas/SecretResponse" - } - }, - "total": { - "type": "integer", - "minimum": 0 - } - } - }, - "ListSkillsResponse": { - "type": "object", - "description": "Concrete list wrapper for skill definitions (utoipa requires non-generic types).", - "required": [ - "items", - "total" - ], - "properties": { - "items": { - "type": "array", - "items": { - "$ref": "#/components/schemas/SkillDefinitionResponse" - } - }, - "total": { - "type": "integer", - "minimum": 0 - } - } - }, - "ListTagsResponse": { - "type": "object", - "description": "Response for listing tags", - "required": [ - "tags", - "total" - ], - "properties": { - "tags": { - "type": "array", - "items": { - "type": "string" - }, - "description": "List of available tags" - }, - "total": { - "type": "integer", - "description": "Total number of tags", - "minimum": 0 - } - } - }, - "ListTemplatesQuery": { - "type": "object", - "description": "Query parameters for listing templates", - "properties": { - "featured": { - "type": [ - "boolean", - "null" - ], - "description": "Only return featured templates" - }, - "tag": { - "type": [ - "string", - "null" - ], - "description": "Filter templates by tag" - } - } - }, - "ListTemplatesResponse": { - "type": "object", - "description": "Response for listing templates", - "required": [ - "templates", - "total" - ], - "properties": { - "templates": { - "type": "array", - "items": { - "$ref": "#/components/schemas/TemplateResponse" - }, - "description": "List of templates" - }, - "total": { - "type": "integer", - "description": "Total number of templates", - "minimum": 0 - } - } - }, - "ListVulnerabilitiesQuery": { - "type": "object", - "properties": { - "page": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "example": 1, - "minimum": 0 - }, - "page_size": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "example": 20, - "minimum": 0 - }, - "severity": { - "type": [ - "string", - "null" - ], - "example": "CRITICAL" - } - } - }, - "LiveVisitorInfo": { - "type": "object", - "required": [ - "id", - "visitor_id", - "project_id", - "environment_id", - "first_seen", - "last_seen", - "is_crawler" - ], - "properties": { - "city": { - "type": [ - "string", - "null" - ] - }, - "country": { - "type": [ - "string", - "null" - ] - }, - "country_code": { - "type": [ - "string", - "null" - ] - }, - "crawler_name": { - "type": [ - "string", - "null" - ] - }, - "current_page": { - "type": [ - "string", - "null" - ], - "description": "Most recent page path visited by this visitor" - }, - "custom_data": {}, - "environment_id": { - "type": "integer", - "format": "int32" - }, - "first_channel": { - "type": [ - "string", - "null" - ], - "description": "Marketing channel from the first visit (e.g. \"Organic Search\", \"Direct\")" - }, - "first_referrer": { - "type": [ - "string", - "null" - ], - "description": "Full referrer URL from the visitor's first session" - }, - "first_referrer_hostname": { - "type": [ - "string", - "null" - ], - "description": "Hostname extracted from first_referrer" - }, - "first_seen": { - "type": "string", - "format": "date-time", - "example": "2024-01-01T00:00:00" - }, - "id": { - "type": "integer", - "format": "int32" - }, - "ip_address": { - "type": [ - "string", - "null" - ] - }, - "ip_address_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "is_crawler": { - "type": "boolean" - }, - "is_eu": { - "type": [ - "boolean", - "null" - ] - }, - "last_seen": { - "type": "string", - "format": "date-time", - "example": "2024-01-01T00:00:00" - }, - "latitude": { - "type": [ - "number", - "null" - ], - "format": "double" - }, - "longitude": { - "type": [ - "number", - "null" - ], - "format": "double" - }, - "project_id": { - "type": "integer", - "format": "int32" - }, - "region": { - "type": [ - "string", - "null" - ] - }, - "timezone": { - "type": [ - "string", - "null" - ] - }, - "user_agent": { - "type": [ - "string", - "null" - ] - }, - "visitor_id": { - "type": "string" - } - } - }, - "LiveVisitorsListResponse": { - "type": "object", - "required": [ - "total_count", - "visitors", - "window_minutes" - ], - "properties": { - "total_count": { - "type": "integer", - "format": "int64" - }, - "visitors": { - "type": "array", - "items": { - "$ref": "#/components/schemas/LiveVisitorInfo" - } - }, - "window_minutes": { - "type": "integer", - "format": "int32" - } - } - }, - "LocationCount": { - "type": "object", - "required": [ - "location", - "count", - "percentage" - ], - "properties": { - "count": { - "type": "integer", - "format": "int64" - }, - "location": { - "type": "string" - }, - "percentage": { - "type": "number", - "format": "double" - } - } - }, - "LocationGranularity": { - "type": "string", - "enum": [ - "country", - "region", - "city" - ] - }, - "LocationInfo": { - "type": "object", - "properties": { - "city": { - "type": [ - "string", - "null" - ] - }, - "country": { - "type": [ - "string", - "null" - ] - }, - "region": { - "type": [ - "string", - "null" - ] - } - } - }, - "LogLevel": { - "type": "string", - "description": "Normalized log level", - "enum": [ - "TRACE", - "DEBUG", - "INFO", - "WARN", - "ERROR" - ] - }, - "LogRecord": { - "type": "object", - "description": "A single log record ready for storage.", - "required": [ - "project_id", - "resource", - "timestamp", - "observed_timestamp", - "severity", - "severity_text", - "body", - "attributes" - ], - "properties": { - "attributes": { - "type": "object", - "additionalProperties": { - "type": "string" - }, - "propertyNames": { - "type": "string" - } - }, - "body": { - "type": "string" - }, - "deployment_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "observed_timestamp": { - "type": "string", - "format": "date-time" - }, - "project_id": { - "type": "integer", - "format": "int32" - }, - "resource": { - "$ref": "#/components/schemas/ResourceInfo" - }, - "severity": { - "$ref": "#/components/schemas/LogSeverity" - }, - "severity_text": { - "type": "string" - }, - "span_id": { - "type": [ - "string", - "null" - ] - }, - "timestamp": { - "type": "string", - "format": "date-time" - }, - "trace_id": { - "type": [ - "string", - "null" - ] - } - } - }, - "LogSearchLine": { - "type": "object", - "description": "A single line in search results", - "required": [ - "timestamp", - "level", - "service", - "message", - "chunk_id", - "line_offset" - ], - "properties": { - "chunk_id": { - "type": "string" - }, - "container_id": { - "type": "string", - "description": "Container this line came from \u2014 lets the UI tag/group lines by container\nin a combined (\"show all\") multi-container view." - }, - "context": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/LineContext", - "description": "Raw surrounding lines (grep -C). `None` unless `context_lines > 0` was\nrequested. Overlapping windows between nearby matches are merged: the\nshared neighbors appear on the earlier match only, so the frontend can\nrender one continuous block without duplicated lines." - } - ] - }, - "deploy_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "fields": {}, - "level": { - "$ref": "#/components/schemas/LogLevel" - }, - "line_offset": { - "type": "integer", - "format": "int32" - }, - "message": { - "type": "string" - }, - "node_id": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Worker node the line came from (`None` = control-plane-local)." - }, - "node_name": { - "type": [ - "string", - "null" - ], - "description": "Human-readable node name for display." - }, - "service": { - "type": "string" - }, - "timestamp": { - "type": "string" - } - } - }, - "LogSeverity": { - "type": "string", - "description": "Log severity level (simplified from OTel's 24 levels).", - "enum": [ - "TRACE", - "DEBUG", - "INFO", - "WARN", - "ERROR", - "FATAL" - ] - }, - "LogSource": { - "type": "object", - "description": "A distinct log source (container) seen in the queried scope. Used to populate\nthe history filter dropdowns with the *full* set of containers/nodes for the\nproject + env + deployment + time window \u2014 independent of the active\ncontainer/node/service filter, so the user can switch between them.", - "required": [ - "container_id", - "service" - ], - "properties": { - "container_id": { - "type": "string" - }, - "node_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "node_name": { - "type": [ - "string", - "null" - ] - }, - "service": { - "type": "string" - } - } - }, - "LogStream": { - "type": "string", - "description": "Log output stream", - "enum": [ - "stdout", - "stderr" - ] - }, - "LoginRequest": { - "type": "object", - "required": [ - "email", - "password" - ], - "properties": { - "email": { - "type": "string" - }, - "password": { - "type": "string" - } - } - }, - "LogsQuery": { - "type": "object", - "properties": { - "tail": { - "type": [ - "integer", - "null" - ], - "description": "Number of lines to return from the tail. Defaults to 200, capped at 2000.", - "minimum": 0 - } - } - }, - "LogsResponse": { - "type": "object", - "required": [ - "data", - "count" - ], - "properties": { - "count": { - "type": "integer", - "minimum": 0 - }, - "data": { - "type": "array", - "items": { - "$ref": "#/components/schemas/LogRecord" - } - } - } - }, - "ManagedDomainResponse": { - "type": "object", - "description": "Managed domain response", - "required": [ - "id", - "provider_id", - "domain", - "auto_manage", - "verified", - "generated_hostname_mode", - "sync_generated_records", - "created_at", - "updated_at" - ], - "properties": { - "auto_manage": { - "type": "boolean" - }, - "created_at": { - "type": "string" - }, - "domain": { - "type": "string" - }, - "generated_hostname_mode": { - "type": "string", - "description": "Generated hostname layout: `\"standard\"` or `\"flat\"`." - }, - "id": { - "type": "integer", - "format": "int32" - }, - "provider_id": { - "type": "integer", - "format": "int32" - }, - "sync_generated_records": { - "type": "boolean", - "description": "Whether generated hostnames are reconciled into the provider's DNS zone." - }, - "updated_at": { - "type": "string" - }, - "verification_error": { - "type": [ - "string", - "null" - ] - }, - "verified": { - "type": "boolean" - }, - "verified_at": { - "type": [ - "string", - "null" - ] - }, - "zone_access_error": { - "type": [ - "string", - "null" - ], - "description": "Detail for a failed zone-access check." - }, - "zone_access_ok": { - "type": [ - "boolean", - "null" - ], - "description": "Last token zone-access check: `Some(true)`/`Some(false)`/`None` (unchecked)." - }, - "zone_id": { - "type": [ - "string", - "null" - ] - } - } - }, - "ManualAction": { - "type": "object", - "description": "A manual action the user must perform outside of the automated migration", - "required": [ - "timing", - "description", - "reason" - ], - "properties": { - "description": { - "type": "string", - "description": "Human-readable description" - }, - "reason": { - "type": "string", - "description": "Why this can't be automated" - }, - "timing": { - "$ref": "#/components/schemas/ManualActionTiming", - "description": "When this action needs to happen" - } - } - }, - "ManualActionTiming": { - "type": "string", - "description": "When a manual action needs to happen relative to migration", - "enum": [ - "before-migration", - "after-migration", - "within-hours" - ] - }, - "McpDefinitionResponse": { - "type": "object", - "required": [ - "id", - "slug", - "name", - "config", - "created_at", - "updated_at" - ], - "properties": { - "config": { - "type": "object" - }, - "created_at": { - "type": "string" - }, - "description": { - "type": [ - "string", - "null" - ] - }, - "id": { - "type": "integer", - "format": "int32" - }, - "name": { - "type": "string" - }, - "project_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "slug": { - "type": "string" - }, - "updated_at": { - "type": "string" - } - } - }, - "MessageContent": { - "oneOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "$ref": "#/components/schemas/ContentPart" - } - } - ] - }, - "MessagePart": { - "oneOf": [ - { - "type": "object", - "required": [ - "text", - "type" - ], - "properties": { - "text": { - "type": "string" - }, - "type": { - "type": "string", - "enum": [ - "text" - ] - } - } - }, - { - "type": "object", - "required": [ - "tool", - "type" - ], - "properties": { - "tool": { - "$ref": "#/components/schemas/ToolInfo" - }, - "type": { - "type": "string", - "enum": [ - "tool" - ] - } - } - } - ], - "description": "One ordered segment of an assistant turn: a chunk of prose, or a tool\ninvocation. Mirrors the `metadata.parts` persisted by the chat service." - }, - "MessageResponse": { - "type": "object", - "required": [ - "role", - "content", - "created_at" - ], - "properties": { - "content": { - "type": "string" - }, - "created_at": { - "type": "string" - }, - "parts": { - "type": [ - "array", - "null" - ], - "items": { - "$ref": "#/components/schemas/MessagePart" - }, - "description": "Ordered render segments (text / tool, in the order they occurred) so a\nreloaded chat shows the same interleaving as the live stream. Absent for\nolder messages persisted before parts were tracked; the client then falls\nback to `tools` (rendered first) + `content`." - }, - "role": { - "type": "string" - }, - "tools": { - "type": [ - "array", - "null" - ], - "items": { - "$ref": "#/components/schemas/ToolInfo" - }, - "description": "Tools the assistant ran on this turn (persisted in message metadata), so\nthe chat replays its tool work after a reload. Absent for plain turns." - } - } - }, - "MeteredMode": { - "type": "string", - "description": "How to treat metered-billing subscriptions when computing MRR.\n\n* `DeriveFromInvoices` (default): ignore the subscription row's\n `mrr_minor` for metered items and rely on the per-invoice\n [`NormalizedEventType::MrrRealized`] events instead. Correct for\n pure-metered, hybrid, tiered, and flat \u2014 recommended.\n* `UseSubscription`: trust whatever MRR the subscription parser\n returns (0 for metered). Legacy behavior.\n* `Ignore`: drop metered subscriptions from MRR entirely.", - "enum": [ - "derive_from_invoices", - "use_subscription", - "ignore" - ] - }, - "MetricAggregation": { - "oneOf": [ - { - "type": "string", - "description": "Arithmetic mean of the scalar value in each bucket. The default.", - "enum": [ - "avg" - ] - }, - { - "type": "string", - "description": "Sum of the scalar value in each bucket.", - "enum": [ - "sum" - ] - }, - { - "type": "string", - "description": "Minimum scalar value in each bucket.", - "enum": [ - "min" - ] - }, - { - "type": "string", - "description": "Maximum scalar value in each bucket.", - "enum": [ - "max" - ] - }, - { - "type": "string", - "description": "Number of points in each bucket.", - "enum": [ - "count" - ] - }, - { - "type": "string", - "description": "Per-second rate of change of a cumulative monotonic counter, computed as\n`(max - min) / window_seconds` within each bucket. Non-monotonic series\nfall back to a simple delta.", - "enum": [ - "rate_per_sec" - ] - }, - { - "type": "object", - "description": "A quantile of the scalar value in each bucket. The carried `f64` is the\nrequested quantile in `[0.0, 1.0]`.", - "required": [ - "quantile" - ], - "properties": { - "quantile": { - "type": "number", - "format": "double", - "description": "A quantile of the scalar value in each bucket. The carried `f64` is the\nrequested quantile in `[0.0, 1.0]`." - } - } - } - ], - "description": "The aggregation applied when reducing raw metric points into a time bucket.\n\nStore-neutral: every storage backend (ClickHouse today, TimescaleDB later)\nmust be able to satisfy this contract. `Quantile(q)` carries the requested\nquantile in `[0.0, 1.0]` (e.g. `0.95` for p95)." - }, - "MetricBucket": { - "type": "object", - "description": "A time-bucketed metric aggregate for chart display.\n\nStore-neutral response contract. The legacy scalar fields\n(`avg_value`/`min_value`/`max_value`/`count`) are always populated for chart\nback-compat. The richer fields describe the explicitly-requested\n[`MetricAggregation`] (`value`), optional `quantiles`, an optional\n`histogram_summary`, and a `series_key` identifying the label-set when the\nquery used `group_by`.", - "required": [ - "bucket", - "avg_value", - "min_value", - "max_value", - "count" - ], - "properties": { - "avg_value": { - "type": "number", - "format": "double" - }, - "bucket": { - "type": "string", - "format": "date-time" - }, - "count": { - "type": "integer", - "format": "int64" - }, - "histogram_summary": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/HistogramSummary", - "description": "A reduced histogram summary when the bucketed metric is a histogram." - } - ] - }, - "max_value": { - "type": "number", - "format": "double" - }, - "min_value": { - "type": "number", - "format": "double" - }, - "quantiles": { - "type": "array", - "items": { - "type": "array", - "items": false, - "prefixItems": [ - { - "type": "number", - "format": "double" - }, - { - "type": "number", - "format": "double" - } - ] - }, - "description": "Computed quantile/value pairs `(quantile, value)` when the query asked for\nquantile aggregation; otherwise empty." - }, - "series_key": { - "type": [ - "array", - "null" - ], - "items": { - "type": "array", - "items": false, - "prefixItems": [ - { - "type": "string" - }, - { - "type": "string" - } - ] - }, - "description": "The label-set this bucket belongs to, as ordered `(key, value)` pairs,\nwhen the query grouped by labels. Empty/`None` = the single ungrouped\naggregate stream." - }, - "value": { - "type": "number", - "format": "double", - "description": "The value of the requested [`MetricAggregation`] for this bucket. For the\ndefault `Avg` aggregation this equals `avg_value`. `#[serde(default)]` so\npre-existing payloads (which only carried avg/min/max/count) still parse." - } - } - }, - "MetricDataPoint": { - "type": "object", - "description": "A single `(timestamp, value)` data point in a metric series.", - "required": [ - "time", - "value" - ], - "properties": { - "time": { - "type": "string", - "description": "ISO 8601 timestamp with `Z` suffix." - }, - "value": { - "type": "number", - "format": "double", - "description": "Metric value at this bucket." - } - } - }, - "MetricType": { - "type": "string", - "description": "The type of an OTel metric.", - "enum": [ - "gauge", - "sum", - "histogram", - "exponential_histogram", - "summary" - ] - }, - "MetricsOverTimeResponse": { - "type": "object", - "required": [ - "timestamps", - "ttfb", - "lcp", - "fid", - "fcp", - "cls", - "inp" - ], - "properties": { - "cls": { - "type": "array", - "items": { - "type": [ - "number", - "null" - ], - "format": "float" - } - }, - "cls_p75": { - "type": [ - "number", - "null" - ], - "format": "float" - }, - "cls_p90": { - "type": [ - "number", - "null" - ], - "format": "float" - }, - "cls_p95": { - "type": [ - "number", - "null" - ], - "format": "float" - }, - "cls_p99": { - "type": [ - "number", - "null" - ], - "format": "float" - }, - "fcp": { - "type": "array", - "items": { - "type": [ - "number", - "null" - ], - "format": "float" - } - }, - "fcp_p75": { - "type": [ - "number", - "null" - ], - "format": "float" - }, - "fcp_p90": { - "type": [ - "number", - "null" - ], - "format": "float" - }, - "fcp_p95": { - "type": [ - "number", - "null" - ], - "format": "float" - }, - "fcp_p99": { - "type": [ - "number", - "null" - ], - "format": "float" - }, - "fid": { - "type": "array", - "items": { - "type": [ - "number", - "null" - ], - "format": "float" - } - }, - "fid_p75": { - "type": [ - "number", - "null" - ], - "format": "float" - }, - "fid_p90": { - "type": [ - "number", - "null" - ], - "format": "float" - }, - "fid_p95": { - "type": [ - "number", - "null" - ], - "format": "float" - }, - "fid_p99": { - "type": [ - "number", - "null" - ], - "format": "float" - }, - "inp": { - "type": "array", - "items": { - "type": [ - "number", - "null" - ], - "format": "float" - } - }, - "inp_p75": { - "type": [ - "number", - "null" - ], - "format": "float" - }, - "inp_p90": { - "type": [ - "number", - "null" - ], - "format": "float" - }, - "inp_p95": { - "type": [ - "number", - "null" - ], - "format": "float" - }, - "inp_p99": { - "type": [ - "number", - "null" - ], - "format": "float" - }, - "lcp": { - "type": "array", - "items": { - "type": [ - "number", - "null" - ], - "format": "float" - } - }, - "lcp_p75": { - "type": [ - "number", - "null" - ], - "format": "float" - }, - "lcp_p90": { - "type": [ - "number", - "null" - ], - "format": "float" - }, - "lcp_p95": { - "type": [ - "number", - "null" - ], - "format": "float" - }, - "lcp_p99": { - "type": [ - "number", - "null" - ], - "format": "float" - }, - "timestamps": { - "type": "array", - "items": { - "type": "string" - } - }, - "ttfb": { - "type": "array", - "items": { - "type": [ - "number", - "null" - ], - "format": "float" - } - }, - "ttfb_p75": { - "type": [ - "number", - "null" - ], - "format": "float" - }, - "ttfb_p90": { - "type": [ - "number", - "null" - ], - "format": "float" - }, - "ttfb_p95": { - "type": [ - "number", - "null" - ], - "format": "float" - }, - "ttfb_p99": { - "type": [ - "number", - "null" - ], - "format": "float" - } - } - }, - "MetricsQuery": { - "type": "object", - "required": [ - "start_date", - "end_date", - "project_id" - ], - "properties": { - "deployment_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "end_date": { - "type": "string", - "format": "date-time" - }, - "environment_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "project_id": { - "type": "integer", - "format": "int32" - }, - "start_date": { - "type": "string", - "format": "date-time" - } - } - }, - "MetricsRangeQuery": { - "type": "object", - "description": "Query params for range metric queries.", - "required": [ - "metric" - ], - "properties": { - "metric": { - "type": "string", - "description": "Metric name, e.g. `\"pg.connections_active\"`." - }, - "percentile": { - "type": [ - "number", - "null" - ], - "format": "double", - "description": "Optional histogram percentile (0\u2013100). When provided, the endpoint\nfetches histogram buckets and computes the requested quantile." - }, - "range": { - "type": "string", - "description": "Time window: `\"1h\"` | `\"6h\"` | `\"24h\"` | `\"7d\"`." - } - } - }, - "MetricsStatusResponse": { - "type": "object", - "description": "Freshness status: when metrics were last received for this service.", - "properties": { - "last_received_at": { - "type": [ - "string", - "null" - ], - "description": "ISO 8601 timestamp of the most recent metric row, or null if none yet." - } - } - }, - "MetricsStoreKind": { - "type": "string", - "description": "Which storage backend to use for the MetricsStore.", - "enum": [ - "timescale_db", - "click_house" - ] - }, - "MetricsSummaryResponse": { - "type": "object", - "required": [ - "currency", - "current_mrr_minor", - "current_arr_minor", - "active_subscriptions", - "active_customers", - "churned_last_30d", - "arpu_minor" - ], - "properties": { - "active_customers": { - "type": "integer", - "format": "int64" - }, - "active_subscriptions": { - "type": "integer", - "format": "int64" - }, - "arpu_minor": { - "type": "integer", - "format": "int64" - }, - "churned_last_30d": { - "type": "integer", - "format": "int64" - }, - "currency": { - "type": "string" - }, - "current_arr_minor": { - "type": "integer", - "format": "int64" - }, - "current_mrr_minor": { - "type": "integer", - "format": "int64" - } - } - }, - "MfaRequiredResponse": { - "type": "object", - "required": [ - "requires_mfa", - "session_token" - ], - "properties": { - "requires_mfa": { - "type": "boolean" - }, - "session_token": { - "type": "string" - } - } - }, - "MfaSetupResponse": { - "type": "object", - "required": [ - "secret_key", - "qr_code", - "recovery_codes" - ], - "properties": { - "qr_code": { - "type": "string" - }, - "recovery_codes": { - "type": "array", - "items": { - "type": "string" - } - }, - "secret_key": { - "type": "string" - } - } - }, - "MfaVerificationRequest": { - "type": "object", - "required": [ - "code" - ], - "properties": { - "code": { - "type": "string" - } - } - }, - "MigrationStep": { - "type": "object", - "description": "A single step in the migration execution plan.\n\nSteps are presented to the user before execution so they know exactly\nwhat will happen. During execution, each step runs in order and reports\nits outcome before proceeding to the next.", - "required": [ - "order", - "id", - "title", - "description", - "resource_type", - "risk", - "skippable", - "reversible" - ], - "properties": { - "data_implications": { - "type": "array", - "items": { - "$ref": "#/components/schemas/DataImplication" - }, - "description": "Data implications \u2014 what could go wrong or what the user needs to know" - }, - "description": { - "type": "string", - "description": "Detailed description of what this step does" - }, - "estimated_duration": { - "type": [ - "string", - "null" - ], - "description": "Estimated duration hint (e.g., \"< 1 second\", \"10-30 seconds\")" - }, - "id": { - "type": "string", - "description": "Machine-readable step identifier (e.g., \"create-project\", \"create-service-postgres\")" - }, - "order": { - "type": "integer", - "description": "Step number (1-based, for display)", - "minimum": 0 - }, - "post_conditions": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Things the user should verify AFTER this step completes" - }, - "pre_conditions": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Things the user should verify BEFORE this step runs" - }, - "resource_type": { - "$ref": "#/components/schemas/StepResourceType", - "description": "What kind of resource this step creates/modifies" - }, - "reversible": { - "type": "boolean", - "description": "Whether this step is reversible (can be cleaned up on failure)" - }, - "risk": { - "$ref": "#/components/schemas/RiskLevel", - "description": "Risk level for this step" - }, - "skippable": { - "type": "boolean", - "description": "Whether this step can be skipped by the user" - }, - "skipped": { - "type": "boolean", - "description": "Whether the user has chosen to skip this step (set during review)" - }, - "title": { - "type": "string", - "description": "Human-readable title (e.g., \"Create project 'my-app'\")" - } - } - }, - "MigrationSummary": { - "type": "object", - "description": "Human-readable summary of the entire migration plan", - "required": [ - "headline", - "overall_risk", - "resource_counts" - ], - "properties": { - "critical_warnings": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Critical warnings that must be acknowledged before proceeding.\nThese are the most important things the user needs to know." - }, - "headline": { - "type": "string", - "description": "One-line summary (e.g., \"Migrate 'my-app' from Vercel with 1 database, 2 domains\")" - }, - "manual_actions_required": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ManualAction" - }, - "description": "Manual actions the user must perform (before or after migration)" - }, - "overall_risk": { - "$ref": "#/components/schemas/RiskLevel", - "description": "Overall risk assessment for the migration" - }, - "resource_counts": { - "$ref": "#/components/schemas/ResourceCounts", - "description": "Resource counts for quick overview" - }, - "unsupported_features": { - "type": "array", - "items": { - "$ref": "#/components/schemas/UnsupportedFeature" - }, - "description": "Features from the source platform that cannot be migrated" - } - } - }, - "MintEnrollmentTokenRequest": { - "type": "object", - "properties": { - "bound_node_name": { - "type": [ - "string", - "null" - ], - "description": "Optional: restrict the token to register one specific node name." - }, - "max_uses": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Maximum registrations this token may authorize (default 1)." - }, - "ttl_secs": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "description": "Time-to-live in seconds (default 3600 = 1h)." - } - } - }, - "MintEnrollmentTokenResponse": { - "type": "object", - "required": [ - "id", - "token", - "expires_at", - "max_uses", - "message" - ], - "properties": { - "ca_fingerprint": { - "type": [ - "string", - "null" - ], - "description": "SHA-256 fingerprint of the cluster CA (if mTLS is set up). Pass it to the\nworker as `temps join --ca-fingerprint ` to verify the CA on join." - }, - "expires_at": { - "type": "string" - }, - "id": { - "type": "integer", - "format": "int32" - }, - "max_uses": { - "type": "integer", - "format": "int32" - }, - "message": { - "type": "string" - }, - "token": { - "type": "string", - "description": "The plaintext enrollment token \u2014 shown only once, save it now." - } - } - }, - "MiscResult": { - "type": "object", - "description": "Miscellaneous validation result", - "required": [ - "is_disposable", - "is_role_account", - "is_b2c" - ], - "properties": { - "gravatar_url": { - "type": [ - "string", - "null" - ], - "description": "Gravatar URL if available" - }, - "is_b2c": { - "type": "boolean", - "description": "Whether the email provider is a B2C (consumer) email provider" - }, - "is_disposable": { - "type": "boolean", - "description": "Whether the email is from a disposable email provider" - }, - "is_role_account": { - "type": "boolean", - "description": "Whether the email is a role-based account (e.g., admin@, info@)" - } - } - }, - "MkdirBody": { - "type": "object", - "required": [ - "path" - ], - "properties": { - "path": { - "type": "string" - } - }, - "additionalProperties": false - }, - "ModelInfo": { - "type": "object", - "required": [ - "id", - "object", - "owned_by" - ], - "properties": { - "id": { - "type": "string" - }, - "object": { - "type": "string" - }, - "owned_by": { - "type": "string" - } - } - }, - "ModelListResponse": { - "type": "object", - "required": [ - "object", - "data" - ], - "properties": { - "data": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ModelInfo" - } - }, - "object": { - "type": "string" - } - } - }, - "ModelPricing": { - "type": "object", - "description": "Pricing for a single model, all values in USD per 1M tokens.\nFields are optional because not every provider supports every pricing tier.", - "required": [ - "model", - "display_name", - "provider", - "input_per_million", - "output_per_million" - ], - "properties": { - "batch_input_per_million": { - "type": [ - "number", - "null" - ], - "format": "double", - "description": "Batch API input cost per 1M tokens (if provider offers batch pricing)" - }, - "batch_output_per_million": { - "type": [ - "number", - "null" - ], - "format": "double", - "description": "Batch API output cost per 1M tokens" - }, - "cache_hit_per_million": { - "type": [ - "number", - "null" - ], - "format": "double", - "description": "Cache hit / refresh cost per 1M tokens" - }, - "cache_write_1h_per_million": { - "type": [ - "number", - "null" - ], - "format": "double", - "description": "1-hour cache write cost per 1M tokens" - }, - "cache_write_5m_per_million": { - "type": [ - "number", - "null" - ], - "format": "double", - "description": "5-minute cache write cost per 1M tokens (Anthropic-style prompt caching)" - }, - "deprecated": { - "type": "boolean", - "description": "Whether the model is deprecated" - }, - "display_name": { - "type": "string", - "description": "Human-readable model name (e.g. \"Claude Sonnet 4.6\")" - }, - "input_per_million": { - "type": "number", - "format": "double", - "description": "Base input token cost per 1M tokens" - }, - "model": { - "type": "string", - "description": "Model identifier (e.g. \"gpt-5.4\", \"claude-sonnet-4-6\")" - }, - "output_per_million": { - "type": "number", - "format": "double", - "description": "Output token cost per 1M tokens" - }, - "provider": { - "type": "string", - "description": "Provider ID (e.g. \"openai\", \"anthropic\")" - } - } - }, - "ModelUsage": { - "type": "object", - "required": [ - "model", - "provider", - "request_count", - "input_tokens", - "output_tokens", - "total_tokens", - "avg_latency_ms" - ], - "properties": { - "avg_latency_ms": { - "type": "number", - "format": "double" - }, - "input_tokens": { - "type": "integer", - "format": "int64" - }, - "model": { - "type": "string" - }, - "output_tokens": { - "type": "integer", - "format": "int64" - }, - "provider": { - "type": "string" - }, - "request_count": { - "type": "integer", - "format": "int64" - }, - "total_tokens": { - "type": "integer", - "format": "int64" - } - } - }, - "MonitorResponse": { - "type": "object", - "required": [ - "id", - "project_id", - "name", - "monitor_type", - "monitor_url", - "check_interval_seconds", - "is_active", - "created_at", - "updated_at" - ], - "properties": { - "check_interval_seconds": { - "type": "integer", - "format": "int32" - }, - "check_path": { - "type": [ - "string", - "null" - ] - }, - "created_at": { - "type": "string", - "format": "date-time" - }, - "environment_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "id": { - "type": "integer", - "format": "int32" - }, - "is_active": { - "type": "boolean" - }, - "monitor_type": { - "type": "string" - }, - "monitor_url": { - "type": "string" - }, - "name": { - "type": "string" - }, - "project_id": { - "type": "integer", - "format": "int32" - }, - "updated_at": { - "type": "string", - "format": "date-time" - } - } - }, - "MonitorStatus": { - "type": "object", - "required": [ - "monitor", - "current_status", - "uptime_percentage" - ], - "properties": { - "avg_response_time_ms": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "current_status": { - "type": "string" - }, - "monitor": { - "$ref": "#/components/schemas/MonitorResponse" - }, - "uptime_percentage": { - "type": "number", - "format": "double" - } - } - }, - "MonitoringSettings": { - "type": "object", - "description": "Global metrics observability configuration.\n\nControls whether the MetricsScraper and AlertEvaluator background tasks\nare active, which storage backend they write to, and how long data is kept\nat each retention tier.", - "properties": { - "clickhouse_url": { - "type": [ - "string", - "null" - ], - "description": "ClickHouse DSN (legacy, optional). The runtime metrics store is built\nfrom the `TEMPS_CLICKHOUSE_*` env vars, never from this field; it is\nretained for compatibility and operator reference only.\nExample: `\"http://localhost:8123\"`.", - "default": null - }, - "enabled": { - "type": "boolean", - "description": "Enable or disable all metrics collection (scraping + alerting).\nDefaults to `false` so new installs don't write to TimescaleDB until\nan operator explicitly enables the feature.", - "default": false - }, - "retention_daily_years": { - "type": "integer", - "format": "int32", - "description": "How many years of daily-aggregate data to keep (converted to days internally).", - "default": 2, - "example": 2, - "maximum": 10, - "minimum": 1 - }, - "retention_hourly_days": { - "type": "integer", - "format": "int32", - "description": "How many days of hourly-aggregate data to keep.", - "default": 90, - "example": 90, - "minimum": 1 - }, - "retention_raw_days": { - "type": "integer", - "format": "int32", - "description": "How many days of raw (30 s resolution) metric data to keep.", - "default": 7, - "example": 7, - "minimum": 1 - }, - "scrape_interval_secs": { - "type": "integer", - "format": "int64", - "description": "How often the MetricsScraper collects data from all sources, in seconds.\nMinimum effective value is 10 s; values below that are clamped at runtime.", - "default": 30, - "example": 30, - "minimum": 10 - }, - "store": { - "oneOf": [ - { - "$ref": "#/components/schemas/MetricsStoreKind", - "description": "Storage backend for metric data." - } - ], - "default": "timescale_db" - } - } - }, - "MonitoringSettingsMasked": { - "type": "object", - "description": "Monitoring settings with the ClickHouse DSN masked.\n\n`clickhouse_url` can embed credentials (`http://user:pass@host`), so it is\nreported only as a boolean (`clickhouse_url_set`) rather than echoed back \u2014\nconsistent with how the DNS API key and Docker registry password are masked.", - "required": [ - "enabled", - "store", - "scrape_interval_secs", - "retention_raw_days", - "retention_hourly_days", - "retention_daily_years", - "clickhouse_url_set" - ], - "properties": { - "clickhouse_url_set": { - "type": "boolean", - "description": "True when a ClickHouse DSN is configured. The DSN itself is never\nreturned over HTTP because it may contain credentials." - }, - "enabled": { - "type": "boolean" - }, - "retention_daily_years": { - "type": "integer", - "format": "int32", - "minimum": 0 - }, - "retention_hourly_days": { - "type": "integer", - "format": "int32", - "minimum": 0 - }, - "retention_raw_days": { - "type": "integer", - "format": "int32", - "minimum": 0 - }, - "scrape_interval_secs": { - "type": "integer", - "format": "int64", - "minimum": 0 - }, - "store": { - "$ref": "#/components/schemas/MetricsStoreKind" - } - } - }, - "MrrBucketResponse": { - "type": "object", - "required": [ - "bucket", - "mrr_minor", - "charge_total_minor", - "refund_total_minor", - "charge_count" - ], - "properties": { - "bucket": { - "type": "string", - "format": "date-time" - }, - "charge_count": { - "type": "integer", - "format": "int64" - }, - "charge_total_minor": { - "type": "integer", - "format": "int64" - }, - "mrr_minor": { - "type": "integer", - "format": "int64" - }, - "refund_total_minor": { - "type": "integer", - "format": "int64" - } - } - }, - "MultiNodeSettings": { - "type": "object", - "description": "Multi-node cluster settings", - "properties": { - "cluster_ca_cert_pem": { - "type": [ - "string", - "null" - ], - "description": "Per-cluster CA certificate (PEM) for multi-node mTLS (ADR-020 WS-2.1).\nPublic \u2014 distributed to nodes as the trust root and used by the control\nplane as the root for verifying agent server certs. Minted lazily on the\nfirst CSR-bearing registration.", - "default": null - }, - "cluster_ca_key_encrypted": { - "type": [ - "string", - "null" - ], - "description": "Per-cluster CA private key, AES-256-GCM ciphertext (EncryptionService).\nSECRET \u2014 never returned over HTTP (elided in the masked response).", - "default": null - }, - "join_token_hash": { - "type": [ - "string", - "null" - ], - "description": "SHA-256 hash of the join token (never store plaintext)", - "default": null - }, - "legacy_shared_token_enabled": { - "type": "boolean", - "description": "Whether the legacy single shared join token is still accepted for node\nregistration (ADR-020 WS-1.1). Defaults to `true` so existing clusters\nkeep working on upgrade; fresh installs should set it `false` and rely on\nshort-lived, single-use enrollment tokens instead.", - "default": true - }, - "node_cpu_alert_percent": { - "type": [ - "number", - "null" - ], - "format": "double", - "description": "CPU-usage percent above which a worker node raises a resource alert\n(ADR-020 / monitoring). `None` disables CPU alerting. Default 90.", - "default": 90.0 - }, - "node_disk_alert_percent": { - "type": [ - "number", - "null" - ], - "format": "double", - "description": "Disk-usage percent above which a worker node raises a resource alert.\n`None` disables disk alerting. Default 90.", - "default": 90.0 - }, - "node_memory_alert_percent": { - "type": [ - "number", - "null" - ], - "format": "double", - "description": "Memory-usage percent above which a worker node raises a resource alert.\n`None` disables memory alerting. Default 90.", - "default": 90.0 - }, - "private_address": { - "type": [ - "string", - "null" - ], - "description": "Private/WireGuard IP address of the control plane node.\nUsed by remote worker nodes to reach services (databases, etc.) running on the control plane.\nSet via `--private-address` or `TEMPS_PRIVATE_ADDRESS`.", - "default": null - }, - "require_mtls": { - "type": "boolean", - "description": "Whether to enforce multi-node mTLS (ADR-020 WS-2.1). When `false`\n(default), the control plane ignores join-time CSRs and nodes keep\nserving plaintext HTTP \u2014 zero behavior change. When `true`, the CP signs\nnode CSRs, nodes serve mutual TLS, and every CP\u2192agent call uses the\ncluster client cert. Observe-then-enforce: flip this on only once all\nworkers have re-enrolled with certs.", - "default": false - } - } - }, - "MultiNodeSettingsMasked": { - "type": "object", - "description": "Multi-node settings with `join_token_hash` elided.", - "required": [ - "has_join_token", - "require_mtls", - "legacy_shared_token_enabled" - ], - "properties": { - "cluster_ca_fingerprint": { - "type": [ - "string", - "null" - ], - "description": "SHA-256 fingerprint of the cluster CA certificate (public \u2014 operators can\nverify it out of band; the CA private key is never exposed)." - }, - "has_join_token": { - "type": "boolean" - }, - "legacy_shared_token_enabled": { - "type": "boolean", - "description": "Whether the deprecated shared join token is still accepted." - }, - "node_cpu_alert_percent": { - "type": [ - "number", - "null" - ], - "format": "double", - "description": "Node resource-alert thresholds (percent); `None` = that alert disabled." - }, - "node_disk_alert_percent": { - "type": [ - "number", - "null" - ], - "format": "double" - }, - "node_memory_alert_percent": { - "type": [ - "number", - "null" - ], - "format": "double" - }, - "private_address": { - "type": [ - "string", - "null" - ] - }, - "require_mtls": { - "type": "boolean", - "description": "Whether control-plane\u2194agent mutual TLS is enforced." - } - } - }, - "MxResult": { - "type": "object", - "description": "MX (Mail Exchange) validation result", - "required": [ - "accepts_mail", - "records" - ], - "properties": { - "accepts_mail": { - "type": "boolean", - "description": "Whether the domain accepts mail" - }, - "error": { - "type": [ - "string", - "null" - ], - "description": "Error message if MX lookup failed" - }, - "records": { - "type": "array", - "items": { - "type": "string" - }, - "description": "List of MX records for the domain", - "example": [ - "alt1.gmail-smtp-in.l.google.com.", - "gmail-smtp-in.l.google.com." - ] - } - } - }, - "NavEntry": { - "type": "object", - "description": "A navigation entry that the plugin contributes to the Temps UI.", - "required": [ - "label", - "icon", - "section", - "path", - "order" - ], - "properties": { - "icon": { - "type": "string", - "description": "Lucide icon name (e.g., \"puzzle\", \"database\", \"activity\")" - }, - "label": { - "type": "string", - "description": "Display label in the sidebar" - }, - "order": { - "type": "integer", - "format": "int32", - "description": "Sort order within the section (lower = higher in list)", - "minimum": 0 - }, - "path": { - "type": "string", - "description": "Client-side route path (e.g., \"/my-plugin\")" - }, - "section": { - "$ref": "#/components/schemas/NavSection", - "description": "Which sidebar section this entry belongs to" - } - } - }, - "NavSection": { - "type": "string", - "description": "Where the plugin's nav entry appears in the Temps UI sidebar.", - "enum": [ - "platform", - "settings", - "project" - ] - }, - "NetworkConfiguration": { - "type": "object", - "description": "Network configuration", - "required": [ - "mode", - "dns_servers" - ], - "properties": { - "dns_servers": { - "type": "array", - "items": { - "type": "string" - }, - "description": "DNS servers" - }, - "hostname": { - "type": [ - "string", - "null" - ], - "description": "Hostname" - }, - "mode": { - "$ref": "#/components/schemas/NetworkMode", - "description": "Network mode" - } - } - }, - "NetworkMode": { - "oneOf": [ - { - "type": "string", - "enum": [ - "bridge" - ] - }, - { - "type": "string", - "enum": [ - "host" - ] - }, - { - "type": "string", - "enum": [ - "none" - ] - }, - { - "type": "object", - "required": [ - "custom" - ], - "properties": { - "custom": { - "type": "string" - } - } - } - ], - "description": "Network mode" - }, - "NixpacksPresetConfig": { - "type": "object", - "description": "Configuration for Nixpacks preset\nNixpacks provider and inline build-plan configuration.", - "properties": { - "nixpacksConfig": { - "type": [ - "string", - "null" - ], - "description": "Optional inline nixpacks.toml contents." - }, - "providers": { - "type": "array", - "items": { - "$ref": "#/components/schemas/NixpacksProvider" - }, - "description": "Ordered Nixpacks providers. Empty means repository config or auto-detect;\ninclude `...` to combine auto-detection with explicit providers." - } - } - }, - "NixpacksProvider": { - "type": "string", - "description": "A Nixpacks build provider.\n\n`Auto` serializes as the native Nixpacks `...` marker, which includes the\nprovider detected from the project alongside any explicitly listed\nproviders.", - "enum": [ - "...", - "node", - "python", - "rust", - "go", - "java", - "php", - "ruby", - "deno", - "elixir", - "csharp", - "fsharp", - "dart", - "swift", - "zig", - "scala", - "haskell", - "clojure", - "crystal", - "cobol", - "gleam", - "lunatic", - "scheme", - "static" - ] - }, - "NodeContainerListResponse": { - "type": "object", - "required": [ - "containers", - "total" - ], - "properties": { - "containers": { - "type": "array", - "items": { - "$ref": "#/components/schemas/NodeContainerResponse" - } - }, - "total": { - "type": "integer", - "minimum": 0 - } - } - }, - "NodeContainerResponse": { - "type": "object", - "description": "A container running on a specific node, enriched with project/environment context.", - "required": [ - "container_id", - "container_name", - "image_name", - "status", - "created_at", - "deployment_id", - "project_id", - "project_name", - "environment_id", - "environment_name" - ], - "properties": { - "container_id": { - "type": "string" - }, - "container_name": { - "type": "string" - }, - "created_at": { - "type": "string" - }, - "deployment_id": { - "type": "integer", - "format": "int32" - }, - "environment_id": { - "type": "integer", - "format": "int32" - }, - "environment_name": { - "type": "string" - }, - "image_name": { - "type": "string" - }, - "project_id": { - "type": "integer", - "format": "int32" - }, - "project_name": { - "type": "string" - }, - "status": { - "type": "string" - } - } - }, - "NodeCostInfo": { - "type": "object", - "description": "One cluster node with capacity and (when priceable) a cost estimate", - "required": [ - "name", - "cpu_millis", - "memory_mb" - ], - "properties": { - "cpu_millis": { - "type": "integer", - "format": "int64", - "description": "CPU capacity in millicores" - }, - "instance_type": { - "type": [ - "string", - "null" - ], - "description": "Instance type from `node.kubernetes.io/instance-type` (e.g. \"m5.xlarge\")" - }, - "memory_mb": { - "type": "integer", - "format": "int64", - "description": "Memory capacity in MB" - }, - "monthly_usd": { - "type": [ - "number", - "null" - ], - "format": "double", - "description": "Estimated on-demand monthly price in USD. `None` when the instance\ntype is unknown or not in the price table." - }, - "name": { - "type": "string", - "description": "Node name" - }, - "region": { - "type": [ - "string", - "null" - ], - "description": "Region from `topology.kubernetes.io/region`" - } - } - }, - "NodeInfoResponse": { - "type": "object", - "required": [ - "id", - "name", - "address", - "private_address", - "role", - "status", - "labels", - "capacity", - "created_at" - ], - "properties": { - "address": { - "type": "string" - }, - "architecture": { - "type": [ - "string", - "null" - ], - "description": "Container platform this node runs (`linux/amd64`, `linux/arm64`).\n`None` until an agent that reports it has heartbeated." - }, - "capacity": { - "description": "Resource capacity/usage metrics from the latest heartbeat" - }, - "created_at": { - "type": "string" - }, - "id": { - "type": "integer", - "format": "int32" - }, - "labels": {}, - "last_heartbeat": { - "type": [ - "string", - "null" - ] - }, - "name": { - "type": "string" - }, - "private_address": { - "type": "string" - }, - "role": { - "type": "string" - }, - "status": { - "type": "string" - } - } - }, - "NodeListResponse": { - "type": "object", - "required": [ - "nodes", - "total" - ], - "properties": { - "nodes": { - "type": "array", - "items": { - "$ref": "#/components/schemas/NodeInfoResponse" - } - }, - "total": { - "type": "integer", - "minimum": 0 - } - } - }, - "NotificationPreferencesResponse": { - "type": "object", - "required": [ - "email_enabled", - "slack_enabled", - "batch_similar_notifications", - "minimum_severity", - "deployment_failures_enabled", - "build_errors_enabled", - "runtime_errors_enabled", - "error_threshold", - "error_time_window", - "ssl_expiration_enabled", - "ssl_days_before_expiration", - "domain_expiration_enabled", - "dns_changes_enabled", - "backup_failures_enabled", - "backup_successes_enabled", - "s3_connection_issues_enabled", - "retention_policy_violations_enabled", - "route_downtime_enabled", - "load_balancer_issues_enabled", - "weekly_digest_enabled", - "digest_send_day", - "digest_send_time", - "digest_sections" - ], - "properties": { - "backup_failures_enabled": { - "type": "boolean" - }, - "backup_successes_enabled": { - "type": "boolean" - }, - "batch_similar_notifications": { - "type": "boolean" - }, - "build_errors_enabled": { - "type": "boolean" - }, - "deployment_failures_enabled": { - "type": "boolean" - }, - "digest_sections": { - "$ref": "#/components/schemas/DigestSections" - }, - "digest_send_day": { - "type": "string" - }, - "digest_send_time": { - "type": "string" - }, - "dns_changes_enabled": { - "type": "boolean" - }, - "domain_expiration_enabled": { - "type": "boolean" - }, - "email_enabled": { - "type": "boolean" - }, - "error_threshold": { - "type": "integer", - "format": "int32" - }, - "error_time_window": { - "type": "integer", - "format": "int32" - }, - "load_balancer_issues_enabled": { - "type": "boolean" - }, - "minimum_severity": { - "type": "string" - }, - "retention_policy_violations_enabled": { - "type": "boolean" - }, - "route_downtime_enabled": { - "type": "boolean" - }, - "runtime_errors_enabled": { - "type": "boolean" - }, - "s3_connection_issues_enabled": { - "type": "boolean" - }, - "slack_enabled": { - "type": "boolean" - }, - "ssl_days_before_expiration": { - "type": "integer", - "format": "int32" - }, - "ssl_expiration_enabled": { - "type": "boolean" - }, - "weekly_digest_enabled": { - "type": "boolean" - } - } - }, - "NotificationProviderResponse": { - "type": "object", - "required": [ - "id", - "name", - "provider_type", - "config", - "enabled", - "created_at", - "updated_at" - ], - "properties": { - "config": {}, - "created_at": { - "type": "integer", - "format": "int64" - }, - "enabled": { - "type": "boolean" - }, - "id": { - "type": "integer", - "format": "int32" - }, - "name": { - "type": "string" - }, - "provider_type": { - "type": "string" - }, - "updated_at": { - "type": "integer", - "format": "int64" - } - } - }, - "ObservabilityCompressionSettings": { - "type": "object", - "description": "TimescaleDB compression policy configuration for append-only observability\ntables. Values are expressed in hours so operators can choose sub-day\nwindows while keeping the API representation unambiguous.", - "properties": { - "otel_spans_after_hours": { - "type": "integer", - "format": "int32", - "description": "Compress OpenTelemetry span chunks after this many hours. Defaults to\n24 hours.", - "default": 24, - "example": 24, - "maximum": 2160, - "minimum": 1 - }, - "proxy_logs_after_hours": { - "type": "integer", - "format": "int32", - "description": "Compress proxy-log chunks after this many hours. Defaults to 24 hours.", - "default": 24, - "example": 24, - "maximum": 720, - "minimum": 1 - } - } - }, - "ObservabilityEvent": { - "oneOf": [ - { - "allOf": [ - { - "$ref": "#/components/schemas/RequestRow" - }, - { - "type": "object", - "required": [ - "type" - ], - "properties": { - "type": { - "type": "string", - "enum": [ - "request" - ] - } - } - } - ] - }, - { - "allOf": [ - { - "$ref": "#/components/schemas/SpanRow" - }, - { - "type": "object", - "required": [ - "type" - ], - "properties": { - "type": { - "type": "string", - "enum": [ - "span" - ] - } - } - } - ] - }, - { - "allOf": [ - { - "$ref": "#/components/schemas/ErrorRow" - }, - { - "type": "object", - "required": [ - "type" - ], - "properties": { - "type": { - "type": "string", - "enum": [ - "error" - ] - } - } - } - ] - }, - { - "allOf": [ - { - "$ref": "#/components/schemas/RevenueRow" - }, - { - "type": "object", - "required": [ - "type" - ], - "properties": { - "type": { - "type": "string", - "enum": [ - "revenue" - ] - } - } - } - ] - } - ], - "description": "Discriminated union of every row that can appear in the Observe list.\n\nSerializes to `{ \"type\": \"request\" | \"span\" | ... , ...rest }` so the UI\ncan switch on `event.type` without ambiguity.\n\n**No `Log` variant**: runtime stdout/stderr lines live on a dedicated\nLogs page rather than Observe. Logs are too high-volume to interleave\nwith business signals (requests, errors, revenue) without dominating\nthe timeline, and they have their own retention/storage constraints\n(TimescaleDB hypertable + chunked file/S3 store) that don't compose\nwith the merge service's per-kind LIMIT strategy." - }, - "ObservabilityRetentionSettings": { - "type": "object", - "description": "Retention policy configuration for raw observability tables. Values are in\ndays. The Settings API applies them to TimescaleDB; ClickHouse-backed proxy\nlogs and spans retain their storage-level per-row TTL behavior.", - "properties": { - "otel_logs_days": { - "type": "integer", - "format": "int32", - "description": "Retain OpenTelemetry log events for this many days.", - "default": 90, - "example": 90, - "maximum": 3650, - "minimum": 1 - }, - "otel_metrics_days": { - "type": "integer", - "format": "int32", - "description": "Retain OpenTelemetry metric points for this many days.", - "default": 90, - "example": 90, - "maximum": 3650, - "minimum": 1 - }, - "otel_spans_days": { - "type": "integer", - "format": "int32", - "description": "Retain OpenTelemetry spans (traces) for this many days.", - "default": 90, - "example": 90, - "maximum": 3650, - "minimum": 1 - }, - "proxy_logs_days": { - "type": "integer", - "format": "int32", - "description": "Retain proxy request logs for this many days.", - "default": 30, - "example": 30, - "maximum": 3650, - "minimum": 1 - } - } - }, - "OidcProviderResponse": { - "type": "object", - "required": [ - "id", - "name", - "issuer_url", - "client_id", - "client_secret", - "scopes", - "jit_provisioning", - "enabled", - "template", - "group_claim", - "role_claim", - "default_role", - "trust_idp_email" - ], - "properties": { - "client_id": { - "type": "string" - }, - "client_secret": { - "type": "string", - "description": "Always masked \u2014 the secret is never returned after creation." - }, - "default_role": { - "type": "string" - }, - "enabled": { - "type": "boolean" - }, - "group_claim": { - "type": "string" - }, - "id": { - "type": "integer", - "format": "int32" - }, - "issuer_url": { - "type": "string" - }, - "jit_provisioning": { - "type": "boolean" - }, - "name": { - "type": "string" - }, - "role_claim": { - "type": "string" - }, - "scopes": { - "type": "string" - }, - "template": { - "type": "string" - }, - "trust_idp_email": { - "type": "boolean", - "description": "When true, the resolver skips the `email_verified` claim gate\nduring SSO login. Only safe for IdPs where an admin controls\nuser provisioning \u2014 see `oidc_providers::Model::trust_idp_email`." - } - } - }, - "OidcProviderSummary": { - "type": "object", - "required": [ - "slug", - "name", - "template" - ], - "properties": { - "name": { - "type": "string" - }, - "slug": { - "type": "string", - "description": "Stable opaque slug \u2014 use this as the path parameter when initiating\nOIDC login (`/auth/oidc/login/{slug}`). The integer database ID is\nintentionally omitted from this public endpoint to prevent provider\nenumeration." - }, - "template": { - "type": "string", - "description": "The template the provider was created from \u2014 e.g. `keycloak`,\n`okta`, `auth0`, `google`, `azure-ad`, or `generic`. Surfaced on\nthe public login endpoint so the unauthenticated login page can\nrender the right brand logo on the \"Sign in with X\" button.\nNever sensitive \u2014 the template name is part of the provider's\npublic identity, not configuration." - } - } - }, - "OidcProviderUserResponse": { - "type": "object", - "description": "A user that has logged in via a given OIDC provider. Used by the\nadmin \"Users for provider\" panel \u2014 the `oidc_subject` is the\nIdP-side identifier we matched on, useful when diagnosing why a\nuser can or can't log in.", - "required": [ - "id", - "name", - "email", - "email_verified", - "mfa_enabled", - "created_at", - "updated_at" - ], - "properties": { - "created_at": { - "type": "string", - "format": "date-time", - "example": "2024-01-15T14:30:00Z" - }, - "email": { - "type": "string" - }, - "email_verified": { - "type": "boolean" - }, - "id": { - "type": "integer", - "format": "int32" - }, - "mfa_enabled": { - "type": "boolean" - }, - "name": { - "type": "string" - }, - "oidc_subject": { - "type": [ - "string", - "null" - ] - }, - "updated_at": { - "type": "string", - "format": "date-time", - "example": "2024-01-15T14:30:00Z" - } - } - }, - "OidcProvidersListResponse": { - "type": "object", - "required": [ - "providers" - ], - "properties": { - "providers": { - "type": "array", - "items": { - "$ref": "#/components/schemas/OidcProviderSummary" - } - } - } - }, - "OidcRoleMappingResponse": { - "type": "object", - "required": [ - "id", - "provider_id", - "priority", - "idp_group", - "role" - ], - "properties": { - "id": { - "type": "integer", - "format": "int32" - }, - "idp_group": { - "type": "string" - }, - "priority": { - "type": "integer", - "format": "int32" - }, - "provider_id": { - "type": "integer", - "format": "int32" - }, - "role": { - "type": "string" - } - } - }, - "OidcTestConnectionResponse": { - "type": "object", - "required": [ - "success", - "message" - ], - "properties": { - "message": { - "type": "string" - }, - "success": { - "type": "boolean" - } - } - }, - "OnDemandCertAttemptResponse": { - "type": "object", - "description": "A single on-demand HTTP-01 issuance attempt from the append-only\n`on_demand_cert_attempts` audit log. Carries the full forensic detail for one\nattempt; the current cert state lives on the enclosing row's domain fields.\n\nContains no private-key or certificate material \u2014 only audit metadata \u2014 so it\nis safe to return without masking.", - "required": [ - "id", - "hostname", - "trigger", - "outcome", - "created_at" - ], - "properties": { - "acme_request_sent": { - "type": [ - "boolean", - "null" - ], - "description": "Did we reach the Let's Encrypt API?" - }, - "acme_response_status": { - "type": [ - "string", - "null" - ], - "description": "HTTP status or ACME error type returned by Let's Encrypt, when known." - }, - "challenge_served": { - "type": [ - "boolean", - "null" - ], - "description": "Did the proxy serve the `/.well-known/acme-challenge/` request?" - }, - "created_at": { - "type": "integer", - "format": "int64", - "description": "When the attempt was recorded (epoch millis)." - }, - "duration_ms": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "End-to-end issuance duration in milliseconds (0/None for skipped)." - }, - "error_category": { - "type": [ - "string", - "null" - ], - "description": "Coarse error category for UI labelling: `\"rate_limited\"`, `\"dns_failure\"`,\n`\"acme_order_expired\"`, `\"challenge_mismatch\"`, `\"timeout\"`, `\"internal\"`." - }, - "error_chain": { - "type": [ - "string", - "null" - ], - "description": "Full `Display` chain of the error (all `source()` levels), when failed." - }, - "hostname": { - "type": "string", - "description": "SNI hostname that triggered the attempt." - }, - "id": { - "type": "integer", - "format": "int32" - }, - "outcome": { - "type": "string", - "description": "Final outcome: `\"issued\"`, `\"failed\"`, `\"skipped_duplicate\"`,\n`\"skipped_gate\"`, `\"skipped_rate_limit\"`, or `\"skipped_no_route\"`." - }, - "trigger": { - "type": "string", - "description": "What triggered the attempt (always `\"tls_callback\"` today)." - } - } - }, - "OnDemandCertRow": { - "type": "object", - "description": "One row of the on-demand certificates list: the most-recent attempt for a\nhostname plus the current authoritative cert state from its `domains` row.", - "required": [ - "hostname", - "attempt" - ], - "properties": { - "attempt": { - "$ref": "#/components/schemas/OnDemandCertAttemptResponse", - "description": "The audit record for the attempt this row represents (newest first in\nthe list)." - }, - "backoff_until": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "description": "On-demand negative-cache deadline (epoch millis), when in backoff." - }, - "expiration_time": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "description": "Certificate expiration (epoch millis), when an active cert exists." - }, - "hostname": { - "type": "string", - "description": "SNI hostname." - }, - "status": { - "type": [ - "string", - "null" - ], - "description": "Current cert lifecycle status from the `domains` row, when one exists:\n`on_demand_pending`, `on_demand_issuing`, `active`, `on_demand_failed`,\netc. `None` when no `domains` row exists yet for this hostname." - } - } - }, - "OnDemandTlsSettings": { - "type": "object", - "description": "On-demand (lazy) HTTP-01 TLS issuance settings (ADR-018).\n\nWhen `enabled`, the proxy's `certificate_callback` triggers ACME HTTP-01\nissuance for allowlisted, STABLE hostnames (per-environment aliases and the\nconsole host) that have no active cert, rather than silently failing the\nhandshake. Ephemeral per-deployment hostnames are NEVER certed (ADR \u00a72).\n\nOff by default \u2014 operators opt in explicitly, except QuickStart (`sslip.io`)\ninstalls where `temps setup` auto-enables it and derives `zone`.", - "properties": { - "deployment_url_mode": { - "type": "string", - "description": "How ephemeral per-deployment hostnames behave when they have no cert\n(they are NEVER certed \u2014 see ADR \u00a72). One of:\n - `\"http\"` (default): serve plain HTTP on :80.\n - `\"redirect_to_env\"`: 308-redirect to the stable per-environment URL,\n which IS certed.", - "default": "http", - "example": "http" - }, - "enabled": { - "type": "boolean", - "description": "Master switch. When `false` (default) the proxy's on-demand cert gate\nrejects every SNI and no issuance is ever triggered.", - "default": false, - "example": false - }, - "hourly_cap": { - "type": "integer", - "format": "int32", - "description": "Global cap on total on-demand issuances per hour across all hostnames\n(ADR \u00a74 Layer 3). The operator's self-imposed safety net, separate from\nthe Let's Encrypt rate limit.", - "default": 10, - "example": 10, - "minimum": 1 - }, - "max_concurrent": { - "type": "integer", - "format": "int32", - "description": "Maximum number of ACME issuance flows allowed to run simultaneously\n(the concurrent-issuance semaphore, ADR \u00a74 Layer 1). Min 1.", - "default": 3, - "example": 3, - "minimum": 1 - }, - "zone": { - "type": [ - "string", - "null" - ], - "description": "Zone suffix for the allowlist gate. A hostname passes the gate only if\nit is a direct subdomain of this zone (e.g. zone `1.2.3.4.sslip.io`\nadmits `myapp.1.2.3.4.sslip.io` but not `deep.sub.1.2.3.4.sslip.io`).\n`None` (default) means \"auto-derive from `external_url`\"; if no zone can\nbe derived the gate rejects all SNI, disabling the feature.", - "default": null, - "example": "1.2.3.4.sslip.io" - } - } - }, - "OpenAiError": { - "type": "object", - "required": [ - "message", - "type" - ], - "properties": { - "code": { - "type": [ - "string", - "null" - ] - }, - "message": { - "type": "string" - }, - "type": { - "type": "string" - } - } - }, - "OpenAiErrorResponse": { - "type": "object", - "required": [ - "error" - ], - "properties": { - "error": { - "$ref": "#/components/schemas/OpenAiError" - } - } - }, - "OperatingSystemCount": { - "type": "object", - "required": [ - "operating_system", - "count", - "percentage" - ], - "properties": { - "count": { - "type": "integer", - "format": "int64" - }, - "operating_system": { - "type": "string" - }, - "percentage": { - "type": "number", - "format": "double" - } - } - }, - "OperationResultResponse": { - "type": "object", - "required": [ - "operation", - "success", - "message", - "executed_at" - ], - "properties": { - "data": {}, - "executed_at": { - "type": "string", - "format": "date-time", - "example": "2025-10-12T12:15:47.609192Z" - }, - "message": { - "type": "string" - }, - "operation": { - "type": "string" - }, - "success": { - "type": "boolean" - } - } - }, - "OperationResultsResponse": { - "type": "object", - "required": [ - "deployment_id", - "operations" - ], - "properties": { - "deployment_id": { - "type": "string" - }, - "operations": { - "type": "array", - "items": { - "$ref": "#/components/schemas/OperationResultResponse" - } - } - } - }, - "OtelDashboardResponse": { - "type": "object", - "required": [ - "id", - "project_id", - "name", - "layout", - "created_at", - "updated_at" - ], - "properties": { - "created_at": { - "type": "string", - "example": "2025-10-12T12:15:47.609192Z" - }, - "id": { - "type": "integer", - "format": "int32" - }, - "layout": { - "$ref": "#/components/schemas/DashboardLayout" - }, - "name": { - "type": "string" - }, - "project_id": { - "type": "integer", - "format": "int32" - }, - "updated_at": { - "type": "string", - "example": "2025-10-12T12:15:47.609192Z" - } - } - }, - "OtelDashboardsResponse": { - "type": "object", - "required": [ - "data", - "total" - ], - "properties": { - "data": { - "type": "array", - "items": { - "$ref": "#/components/schemas/OtelDashboardResponse" - } - }, - "total": { - "type": "integer", - "format": "int64", - "minimum": 0 - } - } - }, - "OtelMetricAlertRuleResponse": { - "type": "object", - "required": [ - "id", - "project_id", - "name", - "metric_name", - "aggregation", - "detection_kind", - "detection_config", - "window_secs", - "for_duration_secs", - "severity", - "enabled", - "last_state", - "label_filters", - "group_by", - "dynamic_alerts", - "max_series", - "grouped_notification_threshold", - "last_dropped_series_count", - "series_states", - "created_at", - "updated_at" - ], - "properties": { - "aggregation": { - "type": "string" - }, - "created_at": { - "type": "string", - "example": "2025-10-12T12:15:47.609192Z" - }, - "detection_config": { - "$ref": "#/components/schemas/DetectionConfig", - "description": "The typed detector definition (discriminated union keyed by `kind`)." - }, - "detection_kind": { - "type": "string", - "description": "Coarse detector discriminator: `static|anomaly|forecast|outlier|auto_watch`." - }, - "dynamic_alerts": { - "type": "boolean", - "description": "Whether per-series (\"dynamic\") alerting is enabled for this rule." - }, - "enabled": { - "type": "boolean" - }, - "firing_series": { - "type": "array", - "items": { - "$ref": "#/components/schemas/FiringSeriesEntry" - }, - "description": "Currently-firing series for a dynamic rule, snapshotted from the evaluator's\nin-memory firing map at read time. Empty for static/aggregate rules or when\nnothing is firing." - }, - "for_duration_secs": { - "type": "integer", - "format": "int32" - }, - "group_by": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Label keys the rule breaks the metric down by. Empty = one aggregate stream." - }, - "grouped_notification_threshold": { - "type": "integer", - "format": "int32", - "description": "Notification-grouping threshold: when more than this many series fire in the\nsame tick, only the first gets chart/AI enrichment (1\u20131000)." - }, - "id": { - "type": "integer", - "format": "int32" - }, - "label_filters": { - "type": "array", - "items": { - "type": "array", - "items": false, - "prefixItems": [ - { - "type": "string" - }, - { - "type": "string" - } - ] - }, - "description": "AND-combined label equality filters applied when evaluating this rule.\nEmpty = no filtering (matches all series)." - }, - "last_dropped_series_count": { - "type": "integer", - "format": "int32", - "description": "Number of series dropped by the cardinality cap on the latest dynamic tick\n(0 when nothing was dropped or for static/aggregate rules). Lets a UI warn\n\"N series were dropped this tick\" without reading server logs." - }, - "last_evaluated_at": { - "type": [ - "string", - "null" - ], - "example": "2025-10-12T12:15:47.609192Z" - }, - "last_state": { - "type": "string", - "description": "One of `ok|firing|unknown`." - }, - "last_value": { - "type": [ - "number", - "null" - ], - "format": "double" - }, - "max_series": { - "type": "integer", - "format": "int32", - "description": "Cardinality cap for dynamic alerting (1\u2013100)." - }, - "metric_name": { - "type": "string" - }, - "name": { - "type": "string" - }, - "project_id": { - "type": "integer", - "format": "int32" - }, - "series_states": { - "type": "object", - "description": "Full per-series state snapshot persisted after the latest dynamic-rule tick,\nkeyed by the human-readable series label (`endpoint=/checkout`). Empty for\nstatic/aggregate rules. Unlike `firing_series` (a live in-memory snapshot),\nthis is decoded from the persisted `series_states` jsonb column, so an\nexternal consumer that only reads the rule row still sees per-series detail.", - "additionalProperties": { - "$ref": "#/components/schemas/SeriesStateEntry" - }, - "propertyNames": { - "type": "string" - } - }, - "severity": { - "type": "string" - }, - "updated_at": { - "type": "string", - "example": "2025-10-12T12:15:47.609192Z" - }, - "window_secs": { - "type": "integer", - "format": "int32" - } - } - }, - "OtelMetricAlertsResponse": { - "type": "object", - "required": [ - "data", - "total" - ], - "properties": { - "data": { - "type": "array", - "items": { - "$ref": "#/components/schemas/OtelMetricAlertRuleResponse" - } - }, - "total": { - "type": "integer", - "format": "int64", - "minimum": 0 - } - } - }, - "OtelMetricLabelKeysResponse": { - "type": "object", - "required": [ - "keys" - ], - "properties": { - "keys": { - "type": "array", - "items": { - "type": "string" - } - } - } - }, - "OtelMetricLabelValuesResponse": { - "type": "object", - "required": [ - "values" - ], - "properties": { - "values": { - "type": "array", - "items": { - "type": "string" - } - } - } - }, - "OtelMetricNamesResponse": { - "type": "object", - "required": [ - "names" - ], - "properties": { - "names": { - "type": "array", - "items": { - "type": "string" - } - } - } - }, - "OtelMetricsResponse": { - "type": "object", - "required": [ - "data", - "count" - ], - "properties": { - "count": { - "type": "integer", - "minimum": 0 - }, - "data": { - "type": "array", - "items": { - "$ref": "#/components/schemas/MetricBucket" - } - } - } - }, - "OutlierAlgorithm": { - "type": "string", - "description": "Outlier detection algorithm.", - "enum": [ - "dbscan", - "scaled_dbscan", - "mad", - "scaled_mad" - ] - }, - "OutlierParams": { - "type": "object", - "description": "Outlier (cross-series population) detector parameters (stub \u2014 not evaluated).", - "required": [ - "peer_group_key" - ], - "properties": { - "algorithm": { - "$ref": "#/components/schemas/OutlierAlgorithm" - }, - "peer_group_key": { - "type": "string", - "description": "Label key defining the peer population compared across series (e.g. `host`)." - }, - "tolerance": { - "type": "number", - "format": "double", - "description": "Sensitivity; higher tolerates larger spread before flagging." - } - } - }, - "OverprovisioningAssessment": { - "type": "object", - "description": "Requests-vs-capacity-vs-usage assessment", - "required": [ - "verdict", - "explanation" - ], - "properties": { - "cpu_request_inflation_ratio": { - "type": [ - "number", - "null" - ], - "format": "double", - "description": "Ratio of requested CPU to measured CPU usage (e.g. 40.0 = requests\nreserve 40\u00d7 what the workloads actually use). `None` without metrics." - }, - "cpu_requested_pct": { - "type": [ - "number", - "null" - ], - "format": "double", - "description": "Requested CPU as % of cluster capacity" - }, - "cpu_utilization_pct": { - "type": [ - "number", - "null" - ], - "format": "double", - "description": "Measured CPU usage as % of cluster capacity (`None` without metrics)" - }, - "explanation": { - "type": "string", - "description": "Human-readable explanation of the verdict, e.g. \"Cluster capacity is\n8 vCPU but measured usage is 0.3 vCPU (3.7%) \u2014 severely overprovisioned\"" - }, - "memory_request_inflation_ratio": { - "type": [ - "number", - "null" - ], - "format": "double", - "description": "Ratio of requested memory to measured memory usage" - }, - "memory_requested_pct": { - "type": [ - "number", - "null" - ], - "format": "double", - "description": "Requested memory as % of cluster capacity" - }, - "memory_utilization_pct": { - "type": [ - "number", - "null" - ], - "format": "double", - "description": "Measured memory usage as % of cluster capacity (`None` without metrics)" - }, - "verdict": { - "$ref": "#/components/schemas/OverprovisioningVerdict", - "description": "Overall verdict" - } - } - }, - "OverprovisioningVerdict": { - "type": "string", - "description": "Overall overprovisioning verdict", - "enum": [ - "severe", - "moderate", - "reasonable", - "unknown" - ] - }, - "PageActivityBucket": { - "type": "object", - "description": "Time bucket data point for page activity graph", - "required": [ - "timestamp", - "visitors", - "page_views", - "avg_time_seconds" - ], - "properties": { - "avg_time_seconds": { - "type": "number", - "format": "double", - "description": "Average time on page in seconds" - }, - "page_views": { - "type": "integer", - "format": "int64", - "description": "Number of page views in this bucket" - }, - "timestamp": { - "type": "string", - "description": "Timestamp for this bucket (ISO 8601)" - }, - "visitors": { - "type": "integer", - "format": "int64", - "description": "Number of unique visitors in this bucket" - } - } - }, - "PageCountryStats": { - "type": "object", - "description": "Geographic distribution of visitors for a page", - "required": [ - "country", - "visitors", - "page_views", - "percentage" - ], - "properties": { - "country": { - "type": "string", - "description": "Country name" - }, - "country_code": { - "type": [ - "string", - "null" - ], - "description": "ISO country code (2-letter)" - }, - "page_views": { - "type": "integer", - "format": "int64", - "description": "Number of page views from this country" - }, - "percentage": { - "type": "number", - "format": "double", - "description": "Percentage of total visitors" - }, - "visitors": { - "type": "integer", - "format": "int64", - "description": "Number of unique visitors from this country" - } - } - }, - "PageFlowEntry": { - "type": "object", - "description": "A single page with its entry/exit/bounce statistics", - "required": [ - "page_path", - "entry_count", - "exit_count", - "bounce_count", - "total_views", - "entry_rate", - "exit_rate", - "bounce_rate" - ], - "properties": { - "avg_time_on_page": { - "type": [ - "number", - "null" - ], - "format": "double", - "description": "Average time spent on this page in seconds" - }, - "bounce_count": { - "type": "integer", - "format": "int64", - "description": "Number of times visitors bounced on this page" - }, - "bounce_rate": { - "type": "number", - "format": "double", - "description": "Bounce rate: bounce_count / entry_count (only meaningful for entry pages)" - }, - "entry_count": { - "type": "integer", - "format": "int64", - "description": "Number of times this page was the entry page of a session" - }, - "entry_rate": { - "type": "number", - "format": "double", - "description": "Entry rate: entry_count / total_views" - }, - "exit_count": { - "type": "integer", - "format": "int64", - "description": "Number of times this page was the exit page of a session" - }, - "exit_rate": { - "type": "number", - "format": "double", - "description": "Exit rate: exit_count / total_views" - }, - "page_path": { - "type": "string", - "description": "The page path (e.g. \"/pricing\", \"/docs/getting-started\")" - }, - "total_views": { - "type": "integer", - "format": "int64", - "description": "Total page views for this page" - } - } - }, - "PageFlowQuery": { - "type": "object", - "description": "Query parameters for page flow analytics", - "required": [ - "project_id", - "start_date", - "end_date" - ], - "properties": { - "end_date": { - "type": "string", - "format": "date-time" - }, - "environment_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "limit": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Maximum number of entry/exit pages to return (default: 20)" - }, - "min_views_for_dropoff": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Minimum views for drop-off analysis (default: 5)" - }, - "project_id": { - "type": "integer", - "format": "int32" - }, - "start_date": { - "type": "string", - "format": "date-time" - }, - "transitions_limit": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Maximum number of transitions to return (default: 50)" - } - } - }, - "PageFlowResponse": { - "type": "object", - "description": "Complete page flow analytics response", - "required": [ - "top_entry_pages", - "top_exit_pages", - "drop_off_points", - "transitions", - "total_pages", - "total_sessions" - ], - "properties": { - "drop_off_points": { - "type": "array", - "items": { - "$ref": "#/components/schemas/DropOffPoint" - }, - "description": "Top drop-off points (highest exit rates with meaningful traffic)" - }, - "top_entry_pages": { - "type": "array", - "items": { - "$ref": "#/components/schemas/PageFlowEntry" - }, - "description": "Top entry pages (where visitors land), sorted by entry_count DESC" - }, - "top_exit_pages": { - "type": "array", - "items": { - "$ref": "#/components/schemas/PageFlowEntry" - }, - "description": "Top exit pages (where visitors leave), sorted by exit_count DESC" - }, - "total_pages": { - "type": "integer", - "format": "int64", - "description": "Total unique pages seen in the period" - }, - "total_sessions": { - "type": "integer", - "format": "int64", - "description": "Total sessions in the period" - }, - "transitions": { - "type": "array", - "items": { - "$ref": "#/components/schemas/PageTransition" - }, - "description": "Page-to-page transitions (most common navigation paths)" - } - } - }, - "PageHourlySessionsQuery": { - "type": "object", - "description": "Query parameters for page hourly sessions endpoint", - "required": [ - "page_path", - "project_id", - "start_time", - "end_time" - ], - "properties": { - "bucket_interval": { - "type": [ - "string", - "null" - ] - }, - "end_time": { - "type": "string", - "format": "date-time" - }, - "environment_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "page_path": { - "type": "string" - }, - "project_id": { - "type": "integer", - "format": "int32" - }, - "start_time": { - "type": "string", - "format": "date-time" - } - } - }, - "PageHourlySessionsResponse": { - "type": "object", - "required": [ - "page_path", - "hourly_data", - "total_sessions", - "hours" - ], - "properties": { - "hourly_data": { - "type": "array", - "items": { - "$ref": "#/components/schemas/HourlyPageSessions" - } - }, - "hours": { - "type": "integer", - "format": "int32" - }, - "page_path": { - "type": "string" - }, - "total_sessions": { - "type": "integer", - "format": "int64" - } - } - }, - "PagePathDetailQuery": { - "type": "object", - "description": "Query parameters for page path detail analytics", - "required": [ - "page_path", - "project_id", - "start_date", - "end_date" - ], - "properties": { - "bucket_interval": { - "type": [ - "string", - "null" - ], - "description": "Bucket interval for time series: 'hour', 'day', 'week', 'month' (default: auto)" - }, - "end_date": { - "type": "string", - "format": "date-time" - }, - "environment_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "page_path": { - "type": "string", - "description": "The specific page path to get details for (URL-encoded)" - }, - "project_id": { - "type": "integer", - "format": "int32" - }, - "start_date": { - "type": "string", - "format": "date-time" - } - } - }, - "PagePathDetailResponse": { - "type": "object", - "description": "Detailed analytics response for a specific page path", - "required": [ - "page_path", - "unique_visitors", - "total_page_views", - "avg_time_on_page", - "bounce_rate", - "entry_rate", - "exit_rate", - "activity_over_time", - "countries", - "referrers", - "bucket_interval" - ], - "properties": { - "activity_over_time": { - "type": "array", - "items": { - "$ref": "#/components/schemas/PageActivityBucket" - }, - "description": "Time series data for activity graph" - }, - "avg_time_on_page": { - "type": "number", - "format": "double", - "description": "Average time on page in seconds" - }, - "bounce_rate": { - "type": "number", - "format": "double", - "description": "Bounce rate percentage (0-100)" - }, - "bucket_interval": { - "type": "string", - "description": "Bucket interval used for time series ('hour', 'day', etc.)" - }, - "countries": { - "type": "array", - "items": { - "$ref": "#/components/schemas/PageCountryStats" - }, - "description": "Geographic distribution of visitors" - }, - "entry_rate": { - "type": "number", - "format": "double", - "description": "Entry rate - percentage of sessions that started on this page" - }, - "exit_rate": { - "type": "number", - "format": "double", - "description": "Exit rate - percentage of sessions that ended on this page" - }, - "page_path": { - "type": "string", - "description": "The page path being analyzed" - }, - "referrers": { - "type": "array", - "items": { - "$ref": "#/components/schemas/PageReferrerStats" - }, - "description": "Top referrers to this page" - }, - "total_page_views": { - "type": "integer", - "format": "int64", - "description": "Total page views in the date range" - }, - "unique_visitors": { - "type": "integer", - "format": "int64", - "description": "Total unique visitors to this page in the date range" - } - } - }, - "PagePathInfo": { - "type": "object", - "required": [ - "page_path", - "session_count", - "page_view_count", - "first_seen", - "last_seen" - ], - "properties": { - "avg_time_seconds": { - "type": [ - "number", - "null" - ], - "format": "double" - }, - "first_seen": { - "type": "string" - }, - "last_seen": { - "type": "string" - }, - "page_path": { - "type": "string" - }, - "page_view_count": { - "type": "integer", - "format": "int64" - }, - "session_count": { - "type": "integer", - "format": "int64" - } - } - }, - "PagePathSparkline": { - "type": "object", - "required": [ - "page_path", - "points" - ], - "properties": { - "page_path": { - "type": "string" - }, - "points": { - "type": "array", - "items": { - "$ref": "#/components/schemas/PagePathSparklinePoint" - } - } - } - }, - "PagePathSparklinePoint": { - "type": "object", - "required": [ - "timestamp", - "session_count" - ], - "properties": { - "session_count": { - "type": "integer", - "format": "int64" - }, - "timestamp": { - "type": "string" - } - } - }, - "PagePathVisitorsQuery": { - "type": "object", - "description": "Query parameters for page path visitors", - "required": [ - "page_path", - "project_id", - "start_date", - "end_date" - ], - "properties": { - "end_date": { - "type": "string", - "format": "date-time" - }, - "environment_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "page": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "description": "Page number (1-based, default: 1)", - "minimum": 0 - }, - "page_path": { - "type": "string", - "description": "The specific page path to get visitors for" - }, - "per_page": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "description": "Items per page (default: 50, max: 100)", - "minimum": 0 - }, - "project_id": { - "type": "integer", - "format": "int32" - }, - "start_date": { - "type": "string", - "format": "date-time" - } - } - }, - "PagePathVisitorsResponse": { - "type": "object", - "description": "Response for page path visitors endpoint", - "required": [ - "page_path", - "total_count", - "page", - "per_page", - "sessions" - ], - "properties": { - "page": { - "type": "integer", - "format": "int64", - "description": "Current page number", - "minimum": 0 - }, - "page_path": { - "type": "string", - "description": "The page path" - }, - "per_page": { - "type": "integer", - "format": "int64", - "description": "Items per page", - "minimum": 0 - }, - "sessions": { - "type": "array", - "items": { - "$ref": "#/components/schemas/PageVisitorSession" - }, - "description": "Individual visitor sessions" - }, - "total_count": { - "type": "integer", - "format": "int64", - "description": "Total number of visitor sessions matching the query" - } - } - }, - "PagePathsQuery": { - "type": "object", - "required": [ - "project_id" - ], - "properties": { - "end_date": { - "type": [ - "string", - "null" - ], - "format": "date-time" - }, - "environment_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "limit": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "project_id": { - "type": "integer", - "format": "int32" - }, - "start_date": { - "type": [ - "string", - "null" - ], - "format": "date-time" - } - } - }, - "PagePathsResponse": { - "type": "object", - "required": [ - "page_paths", - "total_count" - ], - "properties": { - "page_paths": { - "type": "array", - "items": { - "$ref": "#/components/schemas/PagePathInfo" - } - }, - "total_count": { - "type": "integer", - "minimum": 0 - } - } - }, - "PagePathsSparklineQuery": { - "type": "object", - "description": "Query parameters for batch page paths sparkline endpoint", - "required": [ - "project_id", - "start_time", - "end_time", - "page_paths" - ], - "properties": { - "end_time": { - "type": "string", - "format": "date-time" - }, - "environment_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "page_paths": { - "type": "string", - "description": "Comma-separated list of page paths" - }, - "project_id": { - "type": "integer", - "format": "int32" - }, - "start_time": { - "type": "string", - "format": "date-time" - } - } - }, - "PagePathsSparklineResponse": { - "type": "object", - "required": [ - "sparklines" - ], - "properties": { - "sparklines": { - "type": "array", - "items": { - "$ref": "#/components/schemas/PagePathSparkline" - } - } - } - }, - "PageReferrerStats": { - "type": "object", - "description": "Referrer source for the page", - "required": [ - "referrer", - "visits", - "percentage" - ], - "properties": { - "percentage": { - "type": "number", - "format": "double", - "description": "Percentage of total visits" - }, - "referrer": { - "type": "string", - "description": "Referrer URL or domain" - }, - "visits": { - "type": "integer", - "format": "int64", - "description": "Number of visits from this referrer" - } - } - }, - "PageSessionComparison": { - "type": "object", - "required": [ - "page_path", - "date", - "session_count", - "event_count", - "avg_duration_seconds" - ], - "properties": { - "avg_duration_seconds": { - "type": "number", - "format": "double" - }, - "date": { - "type": "string" - }, - "event_count": { - "type": "integer", - "format": "int64" - }, - "page_path": { - "type": "string" - }, - "session_count": { - "type": "integer", - "format": "int64" - } - } - }, - "PageSessionStats": { - "type": "object", - "required": [ - "page_path", - "total_sessions", - "avg_time_seconds", - "min_time_seconds", - "max_time_seconds", - "total_page_views", - "avg_page_views_per_session" - ], - "properties": { - "avg_page_views_per_session": { - "type": "number", - "format": "double" - }, - "avg_time_seconds": { - "type": "number", - "format": "double" - }, - "max_time_seconds": { - "type": "number", - "format": "double" - }, - "min_time_seconds": { - "type": "number", - "format": "double" - }, - "page_path": { - "type": "string" - }, - "total_page_views": { - "type": "integer", - "format": "int64" - }, - "total_sessions": { - "type": "integer", - "format": "int64" - } - } - }, - "PageSessionStatsQuery": { - "type": "object", - "required": [ - "page_path", - "project_id", - "start_date", - "end_date" - ], - "properties": { - "end_date": { - "type": "string", - "format": "date-time" - }, - "environment_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "page_path": { - "type": "string" - }, - "project_id": { - "type": "integer", - "format": "int32" - }, - "start_date": { - "type": "string", - "format": "date-time" - } - } - }, - "PageTransition": { - "type": "object", - "description": "A page-to-page transition with count", - "required": [ - "from_page", - "to_page", - "transition_count", - "percentage" - ], - "properties": { - "from_page": { - "type": "string", - "description": "The source page path" - }, - "percentage": { - "type": "number", - "format": "double", - "description": "Percentage of transitions from the source page that go to this destination" - }, - "to_page": { - "type": "string", - "description": "The destination page path" - }, - "transition_count": { - "type": "integer", - "format": "int64", - "description": "Number of times this transition occurred" - } - } - }, - "PageVisit": { - "type": "object", - "required": [ - "path", - "visits" - ], - "properties": { - "path": { - "type": "string" - }, - "visits": { - "type": "integer", - "format": "int64" - } - } - }, - "PageVisitorSession": { - "type": "object", - "description": "Individual visitor session that viewed a specific page", - "required": [ - "visitor_id", - "visitor_uuid", - "viewed_at", - "is_entry", - "is_exit", - "is_bounce" - ], - "properties": { - "browser": { - "type": [ - "string", - "null" - ], - "description": "Browser name" - }, - "city": { - "type": [ - "string", - "null" - ], - "description": "Visitor's city" - }, - "country": { - "type": [ - "string", - "null" - ], - "description": "Visitor's country" - }, - "country_code": { - "type": [ - "string", - "null" - ], - "description": "Visitor's country code" - }, - "device_type": { - "type": [ - "string", - "null" - ], - "description": "Device type (Desktop, Mobile, Tablet)" - }, - "is_bounce": { - "type": "boolean", - "description": "Whether this was a bounce" - }, - "is_entry": { - "type": "boolean", - "description": "Whether this was the entry page for the session" - }, - "is_exit": { - "type": "boolean", - "description": "Whether this was the exit page for the session" - }, - "operating_system": { - "type": [ - "string", - "null" - ], - "description": "Operating system" - }, - "referrer": { - "type": [ - "string", - "null" - ], - "description": "Referrer URL" - }, - "session_id": { - "type": [ - "string", - "null" - ], - "description": "Session ID" - }, - "session_page_number": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Page number in session flow" - }, - "time_on_page": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Time spent on this page in seconds" - }, - "viewed_at": { - "type": "string", - "format": "date-time", - "description": "When the page was viewed" - }, - "visitor_id": { - "type": "integer", - "format": "int32", - "description": "Visitor numeric ID" - }, - "visitor_uuid": { - "type": "string", - "description": "Visitor UUID" - } - } - }, - "PagesComparisonResponse": { - "type": "object", - "required": [ - "comparisons", - "page_paths" - ], - "properties": { - "comparisons": { - "type": "array", - "items": { - "$ref": "#/components/schemas/PageSessionComparison" - } - }, - "page_paths": { - "type": "array", - "items": { - "type": "string" - } - } - } - }, - "PaginatedEmailsResponse": { - "type": "object", - "required": [ - "data", - "total", - "page", - "page_size" - ], - "properties": { - "data": { - "type": "array", - "items": { - "$ref": "#/components/schemas/EmailResponse" - } - }, - "page": { - "type": "integer", - "format": "int64", - "minimum": 0 - }, - "page_size": { - "type": "integer", - "format": "int64", - "minimum": 0 - }, - "total": { - "type": "integer", - "format": "int64", - "minimum": 0 - } - } - }, - "PaginatedEntitiesResponse": { - "type": "object", - "required": [ - "entities", - "count", - "limit", - "has_more" - ], - "properties": { - "count": { - "type": "integer", - "description": "Number of entities returned", - "minimum": 0 - }, - "entities": { - "type": "array", - "items": { - "$ref": "#/components/schemas/EntityResponse" - }, - "description": "List of entities" - }, - "has_more": { - "type": "boolean", - "description": "Whether there are more entities available" - }, - "limit": { - "type": "integer", - "description": "Limit used for this request", - "minimum": 0 - }, - "next_token": { - "type": [ - "string", - "null" - ], - "description": "Continuation token for next page (S3, etc.)" - }, - "total": { - "type": [ - "integer", - "null" - ], - "description": "Total number of entities (if available)", - "minimum": 0 - } - } - }, - "PaginatedErrorEventsResponse": { - "type": "object", - "required": [ - "data", - "pagination" - ], - "properties": { - "data": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ErrorEventResponse" - } - }, - "pagination": { - "$ref": "#/components/schemas/PaginationMeta" - } - } - }, - "PaginatedErrorGroupsResponse": { - "type": "object", - "required": [ - "data", - "pagination" - ], - "properties": { - "data": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ErrorGroupResponse" - } - }, - "pagination": { - "$ref": "#/components/schemas/PaginationMeta" - } - } - }, - "PaginatedEventsResponse": { - "type": "object", - "required": [ - "events", - "total", - "page", - "page_size" - ], - "properties": { - "events": { - "type": "array", - "items": { - "$ref": "#/components/schemas/TrackingEventResponse" - } - }, - "page": { - "type": "integer", - "format": "int64", - "minimum": 0 - }, - "page_size": { - "type": "integer", - "format": "int64", - "minimum": 0 - }, - "total": { - "type": "integer", - "format": "int64", - "minimum": 0 - } - } - }, - "PaginatedExternalImagesResponse": { - "type": "object", - "required": [ - "data", - "total", - "page", - "page_size" - ], - "properties": { - "data": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ExternalImageResponse" - } - }, - "page": { - "type": "integer", - "format": "int64", - "minimum": 0 - }, - "page_size": { - "type": "integer", - "format": "int64", - "minimum": 0 - }, - "total": { - "type": "integer", - "format": "int64", - "minimum": 0 - } - } - }, - "PaginatedProjectList": { - "type": "object", - "required": [ - "projects", - "total", - "page", - "per_page" - ], - "properties": { - "page": { - "type": "integer", - "format": "int64" - }, - "per_page": { - "type": "integer", - "format": "int64" - }, - "projects": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ProjectResponse" - } - }, - "total": { - "type": "integer", - "format": "int64" - } - } - }, - "PaginatedStaticBundlesResponse": { - "type": "object", - "required": [ - "data", - "total", - "page", - "page_size" - ], - "properties": { - "data": { - "type": "array", - "items": { - "$ref": "#/components/schemas/StaticBundleResponse" - } - }, - "page": { - "type": "integer", - "format": "int64", - "minimum": 0 - }, - "page_size": { - "type": "integer", - "format": "int64", - "minimum": 0 - }, - "total": { - "type": "integer", - "format": "int64", - "minimum": 0 - } - } - }, - "Pagination": { - "type": "object", - "description": "SDK pagination cursor. We use opaque page numbers internally but\nexpose `count`/`next`/`prev` the way `@vercel/sandbox` expects.", - "required": [ - "count" - ], - "properties": { - "count": { - "type": "integer", - "format": "int64", - "minimum": 0 - }, - "next": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "minimum": 0 - }, - "prev": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "minimum": 0 - } - } - }, - "PaginationMeta": { - "type": "object", - "required": [ - "page", - "page_size", - "total_count", - "total_pages" - ], - "properties": { - "page": { - "type": "integer", - "format": "int64", - "minimum": 0 - }, - "page_size": { - "type": "integer", - "format": "int64", - "minimum": 0 - }, - "total_count": { - "type": "integer", - "format": "int64", - "minimum": 0 - }, - "total_pages": { - "type": "integer", - "format": "int64", - "minimum": 0 - } - } - }, - "PaginationParams": { - "type": "object", - "properties": { - "page": { - "type": "integer", - "format": "int64" - }, - "per_page": { - "type": "integer", - "format": "int64" - } - } - }, - "PasswordProtectionConfig": { - "type": "object", - "description": "Password protection configuration\n\nWhen enabled, the proxy shows an HTML password form before allowing access.\nAfter the user enters the correct password, an HMAC-signed cookie is set\nso subsequent requests pass through without re-entering the password.", - "required": [ - "enabled", - "passwordHash" - ], - "properties": { - "enabled": { - "type": "boolean", - "description": "Whether password protection is enabled" - }, - "passwordHash": { - "type": "string", - "description": "The bcrypt-hashed password (never stored or returned in plaintext)" - } - } - }, - "PatchSettingsRequest": { - "type": "object", - "properties": { - "auto_upgrade": { - "type": [ - "boolean", - "null" - ] - }, - "host_port": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "minimum": 0 - }, - "image": { - "type": [ - "string", - "null" - ] - } - } - }, - "PathVisitors": { - "type": "object", - "required": [ - "name", - "visitors", - "percentage" - ], - "properties": { - "name": { - "type": "string" - }, - "percentage": { - "type": "number", - "format": "double" - }, - "visitors": { - "type": "integer", - "format": "int64" - } - } - }, - "PathVisitorsAnalyticsQuery": { - "type": "object", - "required": [ - "start_date", - "end_date", - "project_id" - ], - "properties": { - "deployment_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "end_date": { - "type": "string", - "format": "date-time" - }, - "environment_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "limit": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "project_id": { - "type": "integer", - "format": "int32" - }, - "start_date": { - "type": "string", - "format": "date-time" - } - } - }, - "PathVisitorsResponse": { - "type": "object", - "required": [ - "results" - ], - "properties": { - "results": { - "type": "array", - "items": { - "$ref": "#/components/schemas/PathVisitors" - } - } - } - }, - "PeerEntry": { - "type": "object", - "description": "Wire-format peer entry. Matches `temps_network::config::Peer` but\nuses strings on the wire to keep the API stable across underlying\ntype evolution.", - "required": [ - "node_id", - "compute_cidr", - "underlay_address" - ], - "properties": { - "compute_cidr": { - "type": "string", - "description": "Per-node CIDR (e.g. `\"172.20.5.0/24\"`)." - }, - "node_id": { - "type": "string", - "description": "Stable v5 UUID derived from the database node id. Workers use\nthis as the kernel-layer identifier when calling\n`NetworkManager::reconcile_peers`." - }, - "underlay_address": { - "type": "string", - "description": "Address the local node should use to reach this peer over the\nunderlay (private VPC IP for same-DC, public IP for cross-DC)." - } - } - }, - "PeerListResponse": { - "type": "object", - "description": "Response body for `GET /internal/nodes/{node_id}/network/peers`.", - "required": [ - "peers", - "cluster_dns_enabled" - ], - "properties": { - "alloc": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/AllocEntry", - "description": "Caller's own allocation, or `null` if multi-host networking has\nnot been enabled for this node yet." - } - ] - }, - "cluster_dns_enabled": { - "type": "boolean", - "description": "Whether the cluster-DNS resolver is enabled on this control plane\n(`AppSettings.cluster_dns.enabled`). Workers should start their\nper-node resolver and write `overlay_bridge_address` only when this\nis `true`. Always serialized (never `skip_serializing_if`) so older\nand newer version skew degrades to the safe default of `false`." - }, - "peers": { - "type": "array", - "items": { - "$ref": "#/components/schemas/PeerEntry" - }, - "description": "All other nodes with a `compute_cidr` set, excluding the caller." - } - } - }, - "PendingActionResponse": { - "type": "object", - "description": "A proposed AI write action awaiting human confirmation.", - "required": [ - "public_id", - "operation_id", - "method", - "summary", - "status", - "step_index", - "params", - "created_at" - ], - "properties": { - "confirmed_at": { - "type": [ - "string", - "null" - ] - }, - "created_at": { - "type": "string" - }, - "error": { - "type": [ - "string", - "null" - ] - }, - "executed_at": { - "type": [ - "string", - "null" - ] - }, - "method": { - "type": "string" - }, - "operation_id": { - "type": "string" - }, - "params": { - "description": "The flat params to be replayed at execute time (shown pre-execution for review)." - }, - "plan_public_id": { - "type": [ - "string", - "null" - ], - "description": "Set when this action is one step of a multi-step plan (chained actions);\nall steps of the plan share this id. Absent for standalone single actions." - }, - "public_id": { - "type": "string" - }, - "required_permission": { - "type": [ - "string", - "null" - ] - }, - "result": {}, - "status": { - "type": "string" - }, - "step_index": { - "type": "integer", - "format": "int32", - "description": "0-based order of this step within its plan (0 for standalone actions)." - }, - "summary": { - "type": "string" - } - } - }, - "PerformanceMetricsQuery": { - "allOf": [ - { - "$ref": "#/components/schemas/SpeedSegmentFilters", - "description": "Segment filters (filter_path, filter_country, filter_region,\nfilter_city, filter_browser, filter_operating_system) \u2014 flattened so\neach remains a top-level query string param." - }, - { - "type": "object", - "required": [ - "start_date", - "end_date", - "project_id" - ], - "properties": { - "deployment_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "device_type": { - "type": [ - "string", - "null" - ], - "description": "Device type filter: \"desktop\" or \"mobile\"" - }, - "end_date": { - "type": "string", - "format": "date-time" - }, - "environment_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "include_bots": { - "type": [ - "boolean", - "null" - ], - "description": "Include crawler/datacenter (bot) samples. Defaults to false \u2014 bots\nare excluded from the read view but always stored at ingest." - }, - "project_id": { - "type": "integer", - "format": "int32" - }, - "start_date": { - "type": "string", - "format": "date-time" - } - } - } - ] - }, - "PerformanceMetricsResponse": { - "type": "object", - "properties": { - "cls": { - "type": [ - "number", - "null" - ], - "format": "float" - }, - "cls_p75": { - "type": [ - "number", - "null" - ], - "format": "float" - }, - "cls_p90": { - "type": [ - "number", - "null" - ], - "format": "float" - }, - "cls_p95": { - "type": [ - "number", - "null" - ], - "format": "float" - }, - "cls_p99": { - "type": [ - "number", - "null" - ], - "format": "float" - }, - "fcp": { - "type": [ - "number", - "null" - ], - "format": "float" - }, - "fcp_p75": { - "type": [ - "number", - "null" - ], - "format": "float" - }, - "fcp_p90": { - "type": [ - "number", - "null" - ], - "format": "float" - }, - "fcp_p95": { - "type": [ - "number", - "null" - ], - "format": "float" - }, - "fcp_p99": { - "type": [ - "number", - "null" - ], - "format": "float" - }, - "fid": { - "type": [ - "number", - "null" - ], - "format": "float" - }, - "fid_p75": { - "type": [ - "number", - "null" - ], - "format": "float" - }, - "fid_p90": { - "type": [ - "number", - "null" - ], - "format": "float" - }, - "fid_p95": { - "type": [ - "number", - "null" - ], - "format": "float" - }, - "fid_p99": { - "type": [ - "number", - "null" - ], - "format": "float" - }, - "inp": { - "type": [ - "number", - "null" - ], - "format": "float" - }, - "inp_p75": { - "type": [ - "number", - "null" - ], - "format": "float" - }, - "inp_p90": { - "type": [ - "number", - "null" - ], - "format": "float" - }, - "inp_p95": { - "type": [ - "number", - "null" - ], - "format": "float" - }, - "inp_p99": { - "type": [ - "number", - "null" - ], - "format": "float" - }, - "lcp": { - "type": [ - "number", - "null" - ], - "format": "float" - }, - "lcp_p75": { - "type": [ - "number", - "null" - ], - "format": "float" - }, - "lcp_p90": { - "type": [ - "number", - "null" - ], - "format": "float" - }, - "lcp_p95": { - "type": [ - "number", - "null" - ], - "format": "float" - }, - "lcp_p99": { - "type": [ - "number", - "null" - ], - "format": "float" - }, - "ttfb": { - "type": [ - "number", - "null" - ], - "format": "float" - }, - "ttfb_p75": { - "type": [ - "number", - "null" - ], - "format": "float" - }, - "ttfb_p90": { - "type": [ - "number", - "null" - ], - "format": "float" - }, - "ttfb_p95": { - "type": [ - "number", - "null" - ], - "format": "float" - }, - "ttfb_p99": { - "type": [ - "number", - "null" - ], - "format": "float" - } - } - }, - "PermissionInfo": { - "type": "object", - "description": "Information about a single permission", - "required": [ - "name", - "description", - "category" - ], - "properties": { - "category": { - "type": "string", - "description": "Category of the permission (e.g., \"Projects\", \"Deployments\")" - }, - "description": { - "type": "string", - "description": "Human-readable description of the permission" - }, - "name": { - "type": "string", - "description": "The permission identifier (e.g., \"projects:read\")" - } - } - }, - "PgUpgradeLogResponse": { - "type": "object", - "required": [ - "log_id", - "content" - ], - "properties": { - "content": { - "type": "string" - }, - "log_id": { - "type": "string" - } - } - }, - "PgUpgradeResponse": { - "type": "object", - "required": [ - "id", - "service_id", - "from_version", - "to_version", - "from_image", - "to_image", - "status", - "phase", - "log_id", - "attempt", - "created_at" - ], - "properties": { - "attempt": { - "type": "integer", - "format": "int32" - }, - "created_at": { - "type": "string" - }, - "error_message": { - "type": [ - "string", - "null" - ] - }, - "finished_at": { - "type": [ - "string", - "null" - ] - }, - "from_image": { - "type": "string" - }, - "from_version": { - "type": "string" - }, - "id": { - "type": "integer", - "format": "int32" - }, - "log_id": { - "type": "string" - }, - "phase": { - "type": "string" - }, - "pre_upgrade_backup_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "rollback_volume_name": { - "type": [ - "string", - "null" - ] - }, - "service_id": { - "type": "integer", - "format": "int32" - }, - "started_at": { - "type": [ - "string", - "null" - ] - }, - "status": { - "type": "string" - }, - "to_image": { - "type": "string" - }, - "to_version": { - "type": "string" - } - } - }, - "PipelineStats": { - "type": "object", - "description": "Internal pipeline statistics for self-observability.", - "required": [ - "metrics_received", - "metrics_stored", - "metrics_dropped", - "spans_received", - "spans_stored", - "spans_dropped", - "logs_received", - "logs_stored_db", - "logs_stored_s3", - "logs_dropped", - "ingest_errors" - ], - "properties": { - "ingest_errors": { - "type": "integer", - "format": "int64", - "minimum": 0 - }, - "logs_dropped": { - "type": "integer", - "format": "int64", - "minimum": 0 - }, - "logs_received": { - "type": "integer", - "format": "int64", - "minimum": 0 - }, - "logs_stored_db": { - "type": "integer", - "format": "int64", - "minimum": 0 - }, - "logs_stored_s3": { - "type": "integer", - "format": "int64", - "minimum": 0 - }, - "metrics_dropped": { - "type": "integer", - "format": "int64", - "minimum": 0 - }, - "metrics_received": { - "type": "integer", - "format": "int64", - "minimum": 0 - }, - "metrics_stored": { - "type": "integer", - "format": "int64", - "minimum": 0 - }, - "spans_dropped": { - "type": "integer", - "format": "int64", - "minimum": 0 - }, - "spans_received": { - "type": "integer", - "format": "int64", - "minimum": 0 - }, - "spans_stored": { - "type": "integer", - "format": "int64", - "minimum": 0 - } - } - }, - "PipelineStatsResponse": { - "type": "object", - "required": [ - "stats" - ], - "properties": { - "stats": { - "$ref": "#/components/schemas/PipelineStats" - } - } - }, - "PlanComplexity": { - "type": "string", - "description": "Plan complexity indicator", - "enum": [ - "low", - "medium", - "high" - ] - }, - "PlanMetadata": { - "type": "object", - "description": "Plan metadata", - "required": [ - "generated_at", - "generator_version", - "complexity", - "warnings" - ], - "properties": { - "complexity": { - "$ref": "#/components/schemas/PlanComplexity", - "description": "Estimated complexity (low, medium, high)" - }, - "generated_at": { - "type": "string", - "format": "date-time", - "description": "When the plan was generated" - }, - "generator_version": { - "type": "string", - "description": "Generator (importer) version" - }, - "warnings": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Warnings detected during planning" - } - } - }, - "PlanSourceBackup": { - "type": "object", - "required": [ - "location", - "location_was_resolved", - "format" - ], - "properties": { - "created_at": { - "type": [ - "string", - "null" - ] - }, - "format": { - "type": "string", - "description": "\"walg\", \"pg_dump\", \"unknown\"." - }, - "id": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "DB id, absent for orphan (S3-scan) backups." - }, - "location": { - "type": "string", - "description": "Resolved S3 location the orchestrator will actually use." - }, - "location_was_resolved": { - "type": "boolean", - "description": "True when the original row's `s3_location` was empty and we resolved\na location by probing S3. The UI shows this as a warning." - }, - "origin_service_name": { - "type": [ - "string", - "null" - ], - "description": "Service that originally produced the backup, if known." - }, - "size_bytes": { - "type": [ - "integer", - "null" - ], - "format": "int64" - } - } - }, - "PlanTarget": { - "type": "object", - "required": [ - "id", - "name", - "container" - ], - "properties": { - "container": { - "type": "string", - "description": "Expected Docker container name." - }, - "id": { - "type": "integer", - "format": "int32" - }, - "name": { - "type": "string" - } - } - }, - "PlatformInfo": { - "type": "object", - "description": "Platform compatibility information", - "required": [ - "os_type", - "architecture", - "platforms" - ], - "properties": { - "architecture": { - "type": "string", - "description": "System architecture (e.g., \"x86_64\", \"aarch64\")" - }, - "os_type": { - "type": "string", - "description": "Operating system type (e.g., \"linux\", \"windows\", \"darwin\")" - }, - "platforms": { - "type": "array", - "items": { - "type": "string" - }, - "description": "List of supported platforms in \"os/arch\" format (e.g., [\"linux/amd64\"])" - } - } - }, - "PluginManifest": { - "type": "object", - "description": "The complete plugin manifest \u2014 the handshake contract.", - "required": [ - "name", - "version" - ], - "properties": { - "description": { - "type": [ - "string", - "null" - ], - "description": "Short description of what the plugin does" - }, - "display_name": { - "type": [ - "string", - "null" - ], - "description": "Human-readable display name" - }, - "events": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Platform event types the plugin subscribes to.\n\nWhen specified, Temps will POST matching events to the plugin's\n`/_events` endpoint. Uses dot-notation event names matching the\nwebhook event types (e.g., \"deployment.succeeded\", \"project.created\").\n\nAvailable events:\n- `deployment.created`, `deployment.succeeded`, `deployment.failed`,\n `deployment.cancelled`, `deployment.ready`\n- `project.created`, `project.deleted`\n- `domain.created`, `domain.provisioned`" - }, - "health_path": { - "type": "string", - "description": "Health check endpoint path (relative to plugin root)" - }, - "name": { - "type": "string", - "description": "Unique plugin identifier (kebab-case, e.g., \"backup-manager\")" - }, - "nav": { - "type": "array", - "items": { - "$ref": "#/components/schemas/NavEntry" - }, - "description": "Navigation entries for the UI sidebar" - }, - "requires_db": { - "type": "boolean", - "description": "Whether the plugin needs database access" - }, - "ui": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/UiManifest", - "description": "UI bundle manifest (if the plugin has a UI)" - } - ] - }, - "version": { - "type": "string", - "description": "SemVer version string" - } - } - }, - "PortMapping": { - "type": "object", - "description": "Port mapping", - "required": [ - "container_port", - "protocol", - "is_primary" - ], - "properties": { - "container_port": { - "type": "integer", - "format": "int32", - "description": "Container port", - "minimum": 0 - }, - "host_port": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Host port (optional - can be assigned dynamically)", - "minimum": 0 - }, - "is_primary": { - "type": "boolean", - "description": "Whether this is the primary HTTP port" - }, - "protocol": { - "$ref": "#/components/schemas/Protocol", - "description": "Protocol (tcp, udp)" - } - } - }, - "PostgresWalHealth": { - "type": "object", - "required": [ - "probed_at", - "pg_wal_bytes", - "max_wal_size_bytes", - "archive_mode", - "archive_backlog", - "stale_slots", - "oldest_wal_age_secs", - "warnings" - ], - "properties": { - "archive_backlog": { - "type": "integer", - "format": "int64", - "description": "Number of `archive_status/*.ready` files \u2014 un-shipped WAL segments." - }, - "archive_command": { - "type": [ - "string", - "null" - ], - "description": "The literal `archive_command` setting. May be empty or `/bin/true`\nwhen archiving is effectively disabled despite `archive_mode = on`." - }, - "archive_mode": { - "$ref": "#/components/schemas/ArchiveMode" - }, - "archiver_failed_count": { - "type": [ - "integer", - "null" - ], - "format": "int64" - }, - "archiver_last_failed_at": { - "type": [ - "string", - "null" - ], - "format": "date-time" - }, - "max_wal_size_bytes": { - "type": "integer", - "format": "int64", - "description": "`max_wal_size` setting in bytes (parsed from `pg_settings`)." - }, - "oldest_wal_age_secs": { - "type": "integer", - "format": "int64", - "description": "Age of the oldest WAL file in `pg_wal/` (seconds)." - }, - "pg_wal_bytes": { - "type": "integer", - "format": "int64", - "description": "Total size of files under `pg_wal/`, from `pg_ls_waldir()`." - }, - "probed_at": { - "type": "string", - "format": "date-time", - "description": "When the snapshot was taken." - }, - "stale_slots": { - "type": "array", - "items": { - "$ref": "#/components/schemas/StaleSlot" - } - }, - "warnings": { - "type": "array", - "items": { - "$ref": "#/components/schemas/WalWarning" - }, - "description": "Computed warnings, ordered by severity (critical first)." - } - } - }, - "PresetConfigSchema": { - "oneOf": [ - { - "$ref": "#/components/schemas/DockerfilePresetConfig", - "description": "Configuration for Dockerfile preset" - }, - { - "$ref": "#/components/schemas/DockerComposePresetConfig", - "description": "Configuration for Docker Compose" - }, - { - "$ref": "#/components/schemas/NixpacksPresetConfig", - "description": "Configuration for Nixpacks provider selection and inline build plan" - }, - { - "$ref": "#/components/schemas/StaticPresetConfig", - "description": "Configuration for static site presets (Vite, Next.js, etc.)" - } - ], - "description": "Union type for preset configurations\nUse the appropriate configuration type based on your preset" - }, - "PresetInfo": { - "type": "object", - "description": "Detected preset information", - "required": [ - "path", - "preset", - "preset_label", - "project_type" - ], - "properties": { - "compose_files": { - "type": [ - "array", - "null" - ], - "items": { - "type": "string" - }, - "description": "Compose file paths found in the repository (only for docker-compose preset)" - }, - "exposed_port": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Default exposed port for this preset" - }, - "icon_url": { - "type": [ - "string", - "null" - ], - "description": "Icon URL for this preset" - }, - "path": { - "type": "string", - "description": "Path where preset was detected (empty for root)" - }, - "preset": { - "type": "string", - "description": "Preset slug (e.g., \"nextjs\", \"fastapi\")" - }, - "preset_label": { - "type": "string", - "description": "Human-readable preset label" - }, - "project_type": { - "type": "string", - "description": "Project type (e.g., \"frontend\", \"backend\", \"fullstack\")" - } - } - }, - "PresetResponse": { - "type": "object", - "required": [ - "slug", - "label", - "icon_url", - "project_type", - "description" - ], - "properties": { - "default_port": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Default port the application listens on (None for static sites)", - "example": 3000, - "minimum": 0 - }, - "description": { - "type": "string", - "description": "Description of what this preset does" - }, - "icon_url": { - "type": "string", - "description": "Icon URL for the preset" - }, - "label": { - "type": "string", - "description": "Display name/label for the preset" - }, - "project_type": { - "type": "string", - "description": "Project type (server or static)" - }, - "slug": { - "type": "string", - "description": "Unique identifier slug for the preset" - } - } - }, - "PreviewGatewaySettings": { - "type": "object", - "description": "Workspace preview gateway settings.\n\nThe preview gateway is a single shared Docker container that lives on the\n`temps-sandbox-net` network and routes requests to workspace sandbox dev\nservers based on the `Host` header (`ws--.`).\n`temps serve` reconciles this container on startup; these settings let an\noperator override the image, host port, and auto-upgrade behavior.", - "properties": { - "auto_upgrade": { - "type": "boolean", - "description": "When true (default), the supervisor will pull and apply the image\npinned in the Temps binary on every startup. When false, the\ncurrently-running image is left alone \u2014 operators upgrade manually\nfrom the settings UI.", - "default": true, - "example": true - }, - "host_port": { - "type": "integer", - "format": "int32", - "description": "Host port to publish the gateway on (always bound to 127.0.0.1).\nPingora forwards `ws-*` traffic to this port after authenticating.", - "default": 8090, - "example": 8090, - "minimum": 0 - }, - "image": { - "type": "string", - "description": "Docker image reference for the gateway. Pinned per Temps release.\nOperators can override this to test a custom build.", - "default": "ghcr.io/gotempsh/temps-preview-gateway:latest", - "example": "ghcr.io/gotempsh/temps-preview-gateway:latest" - }, - "shared_secret": { - "type": "string", - "description": "Shared secret the host-side Pingora sends on every forwarded preview\nrequest via `X-Temps-Preview-Token`; the gateway rejects requests\nwithout it. Auto-generated on first boot, persisted in DB so the\nsecret is stable across `temps serve` restarts regardless of cwd,\n`TEMPS_DATA_DIR`, or data-dir changes. MUST be masked (`***`) in any\nAPI response \u2014 never expose it over HTTP.", - "default": "", - "example": "" - } - } - }, - "PreviewGatewaySettingsMasked": { - "type": "object", - "description": "Preview gateway settings with `shared_secret` elided.", - "required": [ - "image", - "host_port", - "auto_upgrade", - "shared_secret_set" - ], - "properties": { - "auto_upgrade": { - "type": "boolean" - }, - "host_port": { - "type": "integer", - "format": "int32", - "minimum": 0 - }, - "image": { - "type": "string" - }, - "shared_secret_set": { - "type": "boolean" - } - } - }, - "PreviewGatewaySettingsResponse": { - "type": "object", - "required": [ - "image", - "host_port", - "auto_upgrade", - "default_image", - "default_host_port" - ], - "properties": { - "auto_upgrade": { - "type": "boolean" - }, - "default_host_port": { - "type": "integer", - "format": "int32", - "description": "The compile-time default host port.", - "minimum": 0 - }, - "default_image": { - "type": "string", - "description": "The compile-time default image \u2014 exposed so the UI can offer a\n\"Reset to default\" link without round-tripping." - }, - "host_port": { - "type": "integer", - "format": "int32", - "minimum": 0 - }, - "image": { - "type": "string" - } - } - }, - "PreviewShareLinkBody": { - "type": "object", - "description": "Request body for minting a preview share link.", - "required": [ - "port" - ], - "properties": { - "path": { - "type": [ - "string", - "null" - ], - "description": "Path the recipient lands on. Must be same-origin (start with a single\n`/`); anything else is replaced with `/` so a share link can never be\nturned into an open redirect." - }, - "port": { - "type": "integer", - "format": "int32", - "description": "Port inside the sandbox the preview serves on.", - "minimum": 0 - }, - "ttl_seconds": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "description": "How long the link stays usable, in seconds. Clamped to 24 hours.\nDefaults to one hour \u2014 long enough to send to a reviewer, short enough\nthat a link pasted in a ticket does not stay live indefinitely.", - "minimum": 0 - } - } - }, - "PreviewShareLinkResponse": { - "type": "object", - "required": [ - "url", - "expires_at" - ], - "properties": { - "expires_at": { - "type": "integer", - "format": "int64", - "description": "Unix seconds after which the link stops working.", - "minimum": 0 - }, - "url": { - "type": "string", - "description": "The full link. Its fragment contains the grant and must be treated as a\ncredential; URL fragments are not sent to servers or in Referer headers." - } - } - }, - "PricingResponse": { - "type": "object", - "required": [ - "models" - ], - "properties": { - "models": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ModelPricing" - } - } - } - }, - "ProblemDetails": { - "type": "object", - "description": "Representation of a Problem error to return to the client.\nFollows RFC 7807 - Problem Details for HTTP APIs", - "required": [ - "title", - "extensions" - ], - "properties": { - "detail": { - "type": [ - "string", - "null" - ], - "description": "A human-readable explanation specific to this occurrence of the problem", - "example": "The server encountered an unexpected condition" - }, - "extensions": { - "type": "object", - "description": "Additional properties of the problem", - "additionalProperties": true - }, - "instance": { - "type": [ - "string", - "null" - ], - "description": "A URI reference that identifies the specific occurrence of the problem", - "example": "/account/12345/msgs/abc" - }, - "title": { - "type": "string", - "description": "A short, human-readable summary of the problem type", - "example": "Internal Server Error" - }, - "type": { - "type": [ - "string", - "null" - ], - "description": "A URI reference that identifies the problem type", - "example": "https://example.com/probs/out-of-memory" - } - }, - "example": { - "type": "https://example.com/probs/out-of-memory", - "title": "Internal Server Error", - "detail": "The server encountered an unexpected condition", - "instance": "/account/12345/msgs/abc", - "additional_info": "Custom field with additional details" - } - }, - "ProjectAccessResponse": { - "type": "object", - "required": [ - "id", - "project_id", - "team_id", - "role", - "granted_by", - "created_at", - "updated_at" - ], - "properties": { - "created_at": { - "type": "string", - "format": "date-time", - "example": "2026-07-30T12:15:47.609192Z" - }, - "granted_by": { - "type": "integer", - "format": "int32" - }, - "id": { - "type": "integer", - "format": "int32" - }, - "project_id": { - "type": "integer", - "format": "int32" - }, - "role": { - "$ref": "#/components/schemas/TeamRole" - }, - "team_id": { - "type": "integer", - "format": "int32" - }, - "updated_at": { - "type": "string", - "format": "date-time", - "example": "2026-07-30T12:15:47.609192Z" - } - } - }, - "ProjectConfiguration": { - "type": "object", - "description": "Project-level configuration", - "required": [ - "name", - "slug", - "project_type", - "is_web_app" - ], - "properties": { - "is_web_app": { - "type": "boolean", - "description": "Whether this is a web application" - }, - "name": { - "type": "string", - "description": "Proposed project name" - }, - "project_type": { - "$ref": "#/components/schemas/ProjectType", - "description": "Project type" - }, - "slug": { - "type": "string", - "description": "Proposed slug (URL-safe identifier)" - } - } - }, - "ProjectDSNResponse": { - "type": "object", - "required": [ - "id", - "project_id", - "name", - "public_key", - "dsn", - "created_at", - "is_active", - "event_count" - ], - "properties": { - "created_at": { - "type": "string" - }, - "deployment_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "dsn": { - "type": "string" - }, - "environment_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "event_count": { - "type": "integer", - "format": "int64" - }, - "id": { - "type": "integer", - "format": "int32" - }, - "is_active": { - "type": "boolean" - }, - "name": { - "type": "string" - }, - "project_id": { - "type": "integer", - "format": "int32" - }, - "public_key": { - "type": "string" - } - } - }, - "ProjectDashboardAnalytics": { - "type": "object", - "description": "Analytics data for a single project in the dashboard batch response", - "required": [ - "project_id", - "unique_visitors", - "previous_unique_visitors", - "hourly_visits" - ], - "properties": { - "hourly_visits": { - "type": "array", - "items": { - "$ref": "#/components/schemas/EventTimeline" - }, - "description": "Hourly sparkline data points" - }, - "previous_unique_visitors": { - "type": "integer", - "format": "int64", - "description": "Unique visitor count in the previous period (same duration, shifted back)" - }, - "project_id": { - "type": "integer", - "format": "int32" - }, - "trend_percentage": { - "type": [ - "number", - "null" - ], - "format": "double", - "description": "Percentage change from previous period (positive = growth, negative = decline)\nNull when previous period had zero visitors (no baseline to compare)" - }, - "unique_visitors": { - "type": "integer", - "format": "int64", - "description": "Unique visitor count in the current time range" - } - } - }, - "ProjectHealthSummary": { - "type": "object", - "description": "Health summary for a single project (last 1 hour)", - "required": [ - "project_id", - "total_requests", - "total_errors", - "avg_response_time_ms", - "error_rate", - "status" - ], - "properties": { - "avg_response_time_ms": { - "type": "number", - "format": "double", - "description": "Average response time in ms" - }, - "error_rate": { - "type": "number", - "format": "double", - "description": "Error rate as a percentage (0-100)" - }, - "project_id": { - "type": "integer", - "format": "int32" - }, - "status": { - "type": "string", - "description": "Health status: \"healthy\", \"degraded\", \"down\", \"unknown\"" - }, - "total_errors": { - "type": "integer", - "format": "int64", - "description": "Total server errors (status >= 500) in the period" - }, - "total_requests": { - "type": "integer", - "format": "int64", - "description": "Total requests in the period" - } - } - }, - "ProjectInfo": { - "type": "object", - "required": [ - "id", - "slug", - "created_at" - ], - "properties": { - "created_at": { - "type": "string", - "example": "2025-10-12T12:15:47.609192Z" - }, - "id": { - "type": "integer", - "format": "int32" - }, - "slug": { - "type": "string" - } - } - }, - "ProjectMonitorHealth": { - "type": "object", - "description": "Health summary for a single project based on its production monitors", - "required": [ - "project_id", - "status" - ], - "properties": { - "project_id": { - "type": "integer", - "format": "int32" - }, - "status": { - "type": "string", - "description": "Overall status: \"operational\", \"degraded\", \"down\", or \"no_monitors\"" - } - } - }, - "ProjectPresetResponse": { - "type": "object", - "required": [ - "path", - "preset", - "presetLabel", - "projectType" - ], - "properties": { - "composeFiles": { - "type": [ - "array", - "null" - ], - "items": { - "type": "string" - }, - "description": "Compose file paths found in the repository (only for docker-compose preset)" - }, - "exposedPort": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Default exposed port for this preset (e.g., 3000 for Next.js, 8000 for FastAPI)" - }, - "iconUrl": { - "type": [ - "string", - "null" - ], - "description": "Icon URL for the preset" - }, - "path": { - "type": "string" - }, - "preset": { - "type": "string" - }, - "presetLabel": { - "type": "string" - }, - "projectType": { - "type": "string", - "description": "Project type category (e.g., \"frontend\", \"backend\", \"fullstack\")" - } - } - }, - "ProjectQuery": { - "type": "object", - "required": [ - "project_id" - ], - "properties": { - "environment_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "project_id": { - "type": "integer", - "format": "int32" - } - } - }, - "ProjectRef": { - "type": "object", - "description": "A lightweight project descriptor included in `UnifiedTrace`.", - "required": [ - "project_id", - "project_name", - "project_slug" - ], - "properties": { - "project_id": { - "type": "integer", - "format": "int32" - }, - "project_name": { - "type": "string" - }, - "project_slug": { - "type": "string", - "description": "URL slug used to link a span back into its owning project's trace view." - } - } - }, - "ProjectResponse": { - "type": "object", - "required": [ - "id", - "slug", - "name", - "directory", - "main_branch", - "created_at", - "updated_at", - "deployment_config", - "attack_mode", - "ai_write_actions_enabled", - "error_source_context_enabled", - "enable_preview_environments", - "preview_envs_on_demand", - "preview_envs_idle_timeout_seconds", - "preview_envs_wake_timeout_seconds", - "source_type", - "cross_project_trace_sharing" - ], - "properties": { - "ai_alert_summaries_enabled": { - "type": [ - "boolean", - "null" - ], - "description": "Opt-in to AI summarization of metric alert notifications (NULL/false = off)." - }, - "ai_debug_chat_enabled": { - "type": [ - "boolean", - "null" - ], - "description": "Opt-in to AI debugging chat, e.g. on deployment failures (NULL/false = off)." - }, - "ai_write_actions_enabled": { - "type": "boolean", - "description": "Opt-in to AI propose-then-confirm write capability (false = off)." - }, - "attack_mode": { - "type": "boolean", - "description": "Attack mode - when enabled, requires CAPTCHA verification for all project environments" - }, - "created_at": { - "type": "integer", - "format": "int64" - }, - "cross_project_trace_sharing": { - "type": "boolean", - "description": "ADR-027 Phase 3 opt-out: when false, this project's traces are suppressed\nfrom cross-project discovery results. Default true (consistent with the\nOSS global-observability model where any OtelRead holder can query any\nproject's telemetry)." - }, - "deployment_config": { - "$ref": "#/components/schemas/DeploymentConfig", - "description": "Deployment configuration (resources, autoscaling, features)" - }, - "directory": { - "type": "string" - }, - "enable_preview_environments": { - "type": "boolean", - "description": "Enable automatic preview environment creation for each branch" - }, - "error_source_context_enabled": { - "type": "boolean", - "description": "Opt-in to native error-tracking source context (false = off). When on,\nTemps stores uploaded source files and shows source code in stack traces." - }, - "error_source_root": { - "type": [ - "string", - "null" - ], - "description": "Where auto-capture reads source from (relative to the checkout). Null =\nthe deployment's Docker build context." - }, - "git_provider_connection_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "git_url": { - "type": [ - "string", - "null" - ], - "description": "Git clone URL for the repository (used for public repos without a provider connection)" - }, - "gitlab_webhook_id": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "GitLab webhook ID installed on the connected repository.\n`null` when no GitLab webhook is installed (not connected to GitLab,\nor webhook was removed / never created).", - "example": 42 - }, - "id": { - "type": "integer", - "format": "int32" - }, - "last_deployment": { - "type": [ - "integer", - "null" - ], - "format": "int64" - }, - "main_branch": { - "type": "string" - }, - "name": { - "type": "string" - }, - "preset": { - "type": [ - "string", - "null" - ] - }, - "preset_config": { - "description": "Preset-specific configuration (Dockerfile path, build context, etc.)" - }, - "preview_envs_idle_timeout_seconds": { - "type": "integer", - "format": "int32", - "description": "Idle timeout (seconds) for on-demand preview environments." - }, - "preview_envs_on_demand": { - "type": "boolean", - "description": "When true, newly-created preview environments default to on-demand mode\n(containers stop after the configured idle timeout to save resources)." - }, - "preview_envs_wake_timeout_seconds": { - "type": "integer", - "format": "int32", - "description": "Wake timeout (seconds) for on-demand preview environments." - }, - "repo_name": { - "type": [ - "string", - "null" - ] - }, - "repo_owner": { - "type": [ - "string", - "null" - ] - }, - "slug": { - "type": "string" - }, - "source_type": { - "$ref": "#/components/schemas/SourceType", - "description": "Source type for deployments (git, docker_image, or static_files)" - }, - "updated_at": { - "type": "integer", - "format": "int64" - } - } - }, - "ProjectSecretEnvironmentInfo": { - "type": "object", - "required": [ - "id", - "name", - "main_url" - ], - "properties": { - "id": { - "type": "integer", - "format": "int32" - }, - "main_url": { - "type": "string" - }, - "name": { - "type": "string" - } - } - }, - "ProjectSecretResponse": { - "type": "object", - "description": "Project secret metadata. There is deliberately no `value` field \u2014 secret\nplaintext is never returned after creation. Callers that need the value\nmust read it from the mounted file inside the container.", - "required": [ - "id", - "project_id", - "key", - "include_in_preview", - "created_at", - "updated_at", - "environments" - ], - "properties": { - "created_at": { - "type": "integer", - "format": "int64" - }, - "environments": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ProjectSecretEnvironmentInfo" - } - }, - "id": { - "type": "integer", - "format": "int32" - }, - "include_in_preview": { - "type": "boolean" - }, - "key": { - "type": "string" - }, - "project_id": { - "type": "integer", - "format": "int32" - }, - "updated_at": { - "type": "integer", - "format": "int64" - } - } - }, - "ProjectServiceInfo": { - "type": "object", - "required": [ - "id", - "project", - "service" - ], - "properties": { - "id": { - "type": "integer", - "format": "int32" - }, - "project": { - "$ref": "#/components/schemas/ProjectInfo" - }, - "service": { - "$ref": "#/components/schemas/ExternalServiceInfo" - } - } - }, - "ProjectStatisticsResponse": { - "type": "object", - "required": [ - "total_count" - ], - "properties": { - "total_count": { - "type": "integer", - "format": "int64" - } - } - }, - "ProjectStatsBreakdown": { - "type": "object", - "required": [ - "project_id", - "unique_visitors", - "total_visits", - "total_page_views", - "bounce_rate", - "engagement_rate" - ], - "properties": { - "bounce_rate": { - "type": "number", - "format": "double" - }, - "engagement_rate": { - "type": "number", - "format": "double" - }, - "project_id": { - "type": "integer", - "format": "int32" - }, - "project_name": { - "type": [ - "string", - "null" - ] - }, - "total_page_views": { - "type": "integer", - "format": "int64" - }, - "total_visits": { - "type": "integer", - "format": "int64" - }, - "unique_visitors": { - "type": "integer", - "format": "int64" - } - } - }, - "ProjectType": { - "type": "string", - "description": "Project type enumeration", - "enum": [ - "static", - "docker", - "buildpack", - "git" - ] - }, - "ProjectUsageInfoResponse": { - "type": "object", - "required": [ - "id", - "name", - "slug", - "connection_id", - "connection_name" - ], - "properties": { - "connection_id": { - "type": "integer", - "format": "int32" - }, - "connection_name": { - "type": "string" - }, - "id": { - "type": "integer", - "format": "int32" - }, - "name": { - "type": "string" - }, - "slug": { - "type": "string" - } - } - }, - "ProjectsHealthResponse": { - "type": "object", - "description": "Batch health summary response", - "required": [ - "projects" - ], - "properties": { - "projects": { - "type": "object", - "description": "Health summaries keyed by project ID", - "additionalProperties": { - "$ref": "#/components/schemas/ProjectHealthSummary" - }, - "propertyNames": { - "type": "string" - } - } - } - }, - "ProjectsMonitorHealthResponse": { - "type": "object", - "description": "Batch response for projects health", - "required": [ - "projects" - ], - "properties": { - "projects": { - "type": "object", - "additionalProperties": { - "$ref": "#/components/schemas/ProjectMonitorHealth" - }, - "propertyNames": { - "type": "string" - } - } - } - }, - "PromoteDeploymentRequest": { - "type": "object", - "required": [ - "target_environment_id" - ], - "properties": { - "target_environment_id": { - "type": "integer", - "format": "int32", - "description": "Target environment ID to promote the deployment to" - } - } - }, - "PropertyBreakdownItem": { - "type": "object", - "required": [ - "value", - "count", - "percentage" - ], - "properties": { - "count": { - "type": "integer", - "format": "int64" - }, - "percentage": { - "type": "number", - "format": "double" - }, - "value": { - "type": "string" - } - } - }, - "PropertyBreakdownQuery": { - "type": "object", - "description": "Query parameters for property breakdown (group by column)", - "required": [ - "start_date", - "end_date", - "group_by" - ], - "properties": { - "aggregation_level": { - "$ref": "#/components/schemas/AggregationLevel", - "description": "Aggregation level" - }, - "deployment_id": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Optional deployment filter" - }, - "end_date": { - "type": "string", - "format": "date-time", - "description": "End date for the query range" - }, - "environment_id": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Optional environment filter" - }, - "event_name": { - "type": [ - "string", - "null" - ], - "description": "Optional event name filter (e.g., \"page_view\", \"click\")" - }, - "filter_browser": { - "type": [ - "string", - "null" - ], - "description": "Filter by browser name (for browser version drill-downs)" - }, - "filter_channel": { - "type": [ - "string", - "null" - ], - "description": "Filter by channel name (for channel -> referrer drill-downs)" - }, - "filter_country": { - "type": [ - "string", - "null" - ], - "description": "Filter by country (for region/city drill-downs). Requires geolocation join." - }, - "filter_os": { - "type": [ - "string", - "null" - ], - "description": "Filter by operating system name (for OS version drill-downs)" - }, - "filter_referrer": { - "type": [ - "string", - "null" - ], - "description": "Filter by referrer hostname (for referrer -> pages drill-downs)" - }, - "filter_region": { - "type": [ - "string", - "null" - ], - "description": "Filter by region (for city drill-downs). Requires geolocation join." - }, - "group_by": { - "$ref": "#/components/schemas/PropertyColumn", - "description": "Property column to group by" - }, - "limit": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Maximum number of results to return (default: 20, max: 100)" - }, - "start_date": { - "type": "string", - "format": "date-time", - "description": "Start date for the query range" - } - } - }, - "PropertyBreakdownResponse": { - "type": "object", - "required": [ - "property", - "items", - "total" - ], - "properties": { - "items": { - "type": "array", - "items": { - "$ref": "#/components/schemas/PropertyBreakdownItem" - } - }, - "property": { - "type": "string" - }, - "total": { - "type": "integer", - "format": "int64" - } - } - }, - "PropertyColumn": { - "type": "string", - "enum": [ - "channel", - "device_type", - "browser", - "browser_version", - "operating_system", - "operating_system_version", - "utm_source", - "utm_medium", - "utm_campaign", - "utm_term", - "utm_content", - "referrer_hostname", - "language", - "event_type", - "event_name", - "page_path", - "pathname", - "country", - "region", - "city" - ] - }, - "PropertyTimelineItem": { - "type": "object", - "required": [ - "timestamp", - "value", - "count" - ], - "properties": { - "count": { - "type": "integer", - "format": "int64" - }, - "timestamp": { - "type": "string" - }, - "value": { - "type": "string" - } - } - }, - "PropertyTimelineQuery": { - "type": "object", - "description": "Query parameters for property timeline (group by column over time)", - "required": [ - "start_date", - "end_date", - "group_by" - ], - "properties": { - "aggregation_level": { - "$ref": "#/components/schemas/AggregationLevel", - "description": "Aggregation level" - }, - "bucket_size": { - "type": [ - "string", - "null" - ], - "description": "Time bucket size: \"hour\", \"day\", \"week\", \"month\" (default: auto-detect)" - }, - "deployment_id": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Optional deployment filter" - }, - "end_date": { - "type": "string", - "format": "date-time", - "description": "End date for the query range" - }, - "environment_id": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Optional environment filter" - }, - "event_name": { - "type": [ - "string", - "null" - ], - "description": "Optional event name filter" - }, - "group_by": { - "$ref": "#/components/schemas/PropertyColumn", - "description": "Property column to group by" - }, - "start_date": { - "type": "string", - "format": "date-time", - "description": "Start date for the query range" - } - } - }, - "PropertyTimelineResponse": { - "type": "object", - "required": [ - "property", - "bucket_size", - "items" - ], - "properties": { - "bucket_size": { - "type": "string" - }, - "items": { - "type": "array", - "items": { - "$ref": "#/components/schemas/PropertyTimelineItem" - } - }, - "property": { - "type": "string" - } - } - }, - "Protocol": { - "type": "string", - "description": "Network protocol", - "enum": [ - "tcp", - "udp" - ] - }, - "ProviderCatalogDto": { - "type": "object", - "description": "One catalog entry rendered for the settings UI.", - "required": [ - "id", - "name", - "install_command", - "auth_command", - "auth_flavors", - "models", - "credential_saved", - "supports_max_turns" - ], - "properties": { - "auth_command": { - "type": "string" - }, - "auth_flavors": { - "type": "array", - "items": { - "$ref": "#/components/schemas/AuthFlavorDto" - } - }, - "credential_saved": { - "type": "boolean", - "description": "True when a credential is currently saved for this provider in the\nsettings JSON. Lets the UI render \"Configured\" badges without the\nfrontend having to inspect the encrypted blob." - }, - "current_auth_type": { - "type": [ - "string", - "null" - ], - "description": "Currently saved auth flavor id (when `credential_saved` is true).\n`None` when no credential is saved yet." - }, - "default_model": { - "type": [ - "string", - "null" - ], - "description": "Currently saved default model id for this provider, if one was\npicked. `None` means \"use the CLI's own default\" \u2014 the UI renders\nthat as \"Use provider default\"." - }, - "id": { - "type": "string" - }, - "install_command": { - "type": "string" - }, - "max_turns_analysis": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Default max turns for the autofixer analysis phase. `None` = built-in\ndefault (10). Only enforced for CLIs with a turn flag (Claude Code)." - }, - "max_turns_feedback": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Default max turns for autofixer feedback rounds. `None` = built-in\ndefault (10)." - }, - "max_turns_fix": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Default max turns for the autofixer fix phase. `None` = built-in\ndefault (20)." - }, - "models": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Model ids this provider accepts, in display order. The first entry is\nthe recommended default. Empty when the provider doesn't expose model\nselection (e.g. OpenCode), which the UI uses to hide the dropdown." - }, - "name": { - "type": "string" - }, - "supports_max_turns": { - "type": "boolean", - "description": "True when this provider's CLI supports enforcing a turn cap. False\nfor Codex/OpenCode, which run to completion \u2014 the UI labels their\nmax-turns inputs accordingly." - } - } - }, - "ProviderCatalogResponse": { - "type": "object", - "required": [ - "default_provider", - "providers" - ], - "properties": { - "default_provider": { - "type": "string", - "description": "Active provider id from `agent_sandbox.default_provider`. The settings\nUI uses this to highlight which card is the active one." - }, - "providers": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ProviderCatalogDto" - } - } - } - }, - "ProviderConfig": { - "oneOf": [ - { - "allOf": [ - { - "$ref": "#/components/schemas/StripeConfig" - }, - { - "type": "object", - "required": [ - "provider" - ], - "properties": { - "provider": { - "type": "string", - "enum": [ - "stripe" - ] - } - } - } - ] - }, - { - "allOf": [ - { - "$ref": "#/components/schemas/LemonSqueezyConfig" - }, - { - "type": "object", - "required": [ - "provider" - ], - "properties": { - "provider": { - "type": "string", - "enum": [ - "lemon_squeezy" - ] - } - } - } - ] - } - ], - "description": "Provider-specific integration settings persisted in\n`revenue_integrations.config`.\n\nThe tag is the lowercase provider name, so adding a new provider\nmeans adding a new variant and the existing rows are untouched.\nOld rows (pre-config) and rows with `NULL` config are treated as\n\"accept all events, no filtering\" via [`ProviderConfig::default_for`]." - }, - "ProviderConfigMasked": { - "type": "object", - "required": [ - "auth_type", - "credential_saved", - "extra" - ], - "properties": { - "auth_type": { - "type": "string" - }, - "credential_saved": { - "type": "boolean", - "description": "True if a credential is stored for this provider. The encrypted blob\nis never returned over HTTP." - }, - "default_model": { - "type": [ - "string", - "null" - ] - }, - "extra": {} - } - }, - "ProviderDeletionCheckResponse": { - "type": "object", - "required": [ - "can_delete", - "projects_in_use", - "message" - ], - "properties": { - "can_delete": { - "type": "boolean" - }, - "message": { - "type": "string" - }, - "projects_in_use": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ProjectUsageInfoResponse" - } - } - } - }, - "ProviderDescriptor": { - "type": "object", - "required": [ - "name", - "display_name", - "recommended_events" - ], - "properties": { - "display_name": { - "type": "string" - }, - "name": { - "type": "string" - }, - "recommended_events": { - "type": "array", - "items": { - "type": "string" - } - } - } - }, - "ProviderKeyResponse": { - "type": "object", - "required": [ - "id", - "provider", - "display_name", - "api_key_masked", - "is_active", - "created_at", - "updated_at" - ], - "properties": { - "api_key_masked": { - "type": "string", - "description": "Masked API key (only last 4 chars visible)" - }, - "base_url": { - "type": [ - "string", - "null" - ] - }, - "created_at": { - "type": "string" - }, - "default_model": { - "type": [ - "string", - "null" - ], - "description": "Model id this provider serves (NULL \u2192 per-provider default)." - }, - "display_name": { - "type": "string" - }, - "id": { - "type": "integer", - "format": "int32" - }, - "is_active": { - "type": "boolean" - }, - "provider": { - "type": "string" - }, - "updated_at": { - "type": "string" - } - } - }, - "ProviderMetadata": { - "type": "object", - "required": [ - "service_type", - "display_name", - "description", - "icon_url", - "color" - ], - "properties": { - "color": { - "type": "string", - "example": "#336791" - }, - "description": { - "type": "string", - "example": "Relational database management system" - }, - "display_name": { - "type": "string", - "example": "PostgreSQL" - }, - "icon_url": { - "type": "string", - "example": "https://cdn.simpleicons.org/postgresql" - }, - "service_type": { - "$ref": "#/components/schemas/ServiceTypeRoute" - } - } - }, - "ProviderResponse": { - "type": "object", - "required": [ - "id", - "name", - "provider_type", - "auth_method", - "is_active", - "is_default", - "created_at", - "updated_at" - ], - "properties": { - "auth_method": { - "type": "string" - }, - "base_url": { - "type": [ - "string", - "null" - ] - }, - "created_at": { - "type": "string", - "format": "date-time" - }, - "id": { - "type": "integer", - "format": "int32" - }, - "is_active": { - "type": "boolean" - }, - "is_default": { - "type": "boolean" - }, - "name": { - "type": "string" - }, - "provider_type": { - "type": "string" - }, - "updated_at": { - "type": "string", - "format": "date-time" - } - } - }, - "ProviderUsage": { - "type": "object", - "required": [ - "provider", - "request_count", - "input_tokens", - "output_tokens", - "avg_latency_ms", - "error_count" - ], - "properties": { - "avg_latency_ms": { - "type": "number", - "format": "double" - }, - "error_count": { - "type": "integer", - "format": "int64" - }, - "input_tokens": { - "type": "integer", - "format": "int64" - }, - "output_tokens": { - "type": "integer", - "format": "int64" - }, - "provider": { - "type": "string" - }, - "request_count": { - "type": "integer", - "format": "int64" - } - } - }, - "ProvisionResponse": { - "oneOf": [ - { - "allOf": [ - { - "$ref": "#/components/schemas/DomainError" - }, - { - "type": "object", - "required": [ - "type" - ], - "properties": { - "type": { - "type": "string", - "enum": [ - "error" - ] - } - } - } - ] - }, - { - "allOf": [ - { - "$ref": "#/components/schemas/DomainResponse" - }, - { - "type": "object", - "required": [ - "type" - ], - "properties": { - "type": { - "type": "string", - "enum": [ - "complete" - ] - } - } - } - ] - }, - { - "allOf": [ - { - "$ref": "#/components/schemas/DomainChallengeResponse" - }, - { - "type": "object", - "required": [ - "type" - ], - "properties": { - "type": { - "type": "string", - "enum": [ - "pending" - ] - } - } - } - ] - } - ] - }, - "ProxyLogResponse": { - "type": "object", - "description": "Response model for proxy logs", - "required": [ - "id", - "timestamp", - "method", - "path", - "host", - "status_code", - "request_source", - "is_system_request", - "routing_status", - "request_id" - ], - "properties": { - "bot_name": { - "type": [ - "string", - "null" - ] - }, - "browser": { - "type": [ - "string", - "null" - ] - }, - "browser_version": { - "type": [ - "string", - "null" - ] - }, - "cache_status": { - "type": [ - "string", - "null" - ] - }, - "client_ip": { - "type": [ - "string", - "null" - ] - }, - "container_id": { - "type": [ - "string", - "null" - ] - }, - "deployment_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "device_type": { - "type": [ - "string", - "null" - ] - }, - "environment_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "error_message": { - "type": [ - "string", - "null" - ] - }, - "host": { - "type": "string" - }, - "id": { - "type": "integer", - "format": "int32" - }, - "ip_geolocation_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "is_bot": { - "type": [ - "boolean", - "null" - ] - }, - "is_system_request": { - "type": "boolean" - }, - "method": { - "type": "string" - }, - "operating_system": { - "type": [ - "string", - "null" - ] - }, - "path": { - "type": "string" - }, - "project_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "query_string": { - "type": [ - "string", - "null" - ] - }, - "referrer": { - "type": [ - "string", - "null" - ] - }, - "request_id": { - "type": "string" - }, - "request_size_bytes": { - "type": [ - "integer", - "null" - ], - "format": "int64" - }, - "request_source": { - "type": "string" - }, - "response_size_bytes": { - "type": [ - "integer", - "null" - ], - "format": "int64" - }, - "response_time_ms": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "routing_status": { - "type": "string" - }, - "session_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "status_code": { - "type": "integer", - "format": "int32" - }, - "timestamp": { - "type": "string" - }, - "upstream_host": { - "type": [ - "string", - "null" - ] - }, - "user_agent": { - "type": [ - "string", - "null" - ] - }, - "visitor_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - } - } - }, - "ProxyLogsPaginatedResponse": { - "type": "object", - "description": "Paginated response for proxy logs", - "required": [ - "logs", - "total", - "page", - "page_size", - "total_pages" - ], - "properties": { - "logs": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ProxyLogResponse" - } - }, - "page": { - "type": "integer", - "format": "int64", - "minimum": 0 - }, - "page_size": { - "type": "integer", - "format": "int64", - "minimum": 0 - }, - "total": { - "type": "integer", - "format": "int64", - "minimum": 0 - }, - "total_pages": { - "type": "integer", - "format": "int64", - "minimum": 0 - } - } - }, - "PublicHostnameStrategy": { - "type": "string", - "description": "Public hostname generation mode for Temps-managed preview routes.\n\nThe mode is stored per managed domain (`dns_managed_domains.generated_hostname_mode`)\nrather than globally, so a provider such as Cloudflare can offer the flat layout\nrequired by its Universal SSL wildcard cert without changing every domain's behaviour.", - "enum": [ - "standard", - "flat" - ] - }, - "PublicPresetResponse": { - "type": "object", - "description": "Response for preset detection", - "required": [ - "branch", - "presets" - ], - "properties": { - "branch": { - "type": "string", - "description": "Branch name where presets were detected" - }, - "presets": { - "type": "array", - "items": { - "$ref": "#/components/schemas/PresetInfo" - }, - "description": "List of detected presets" - } - } - }, - "PublicRepositoryInfo": { - "type": "object", - "description": "Public repository information", - "required": [ - "owner", - "name", - "full_name", - "default_branch", - "stars", - "forks" - ], - "properties": { - "default_branch": { - "type": "string", - "description": "Default branch name" - }, - "description": { - "type": [ - "string", - "null" - ], - "description": "Repository description" - }, - "forks": { - "type": "integer", - "format": "int32", - "description": "Fork count" - }, - "full_name": { - "type": "string", - "description": "Full repository name (owner/repo)" - }, - "language": { - "type": [ - "string", - "null" - ], - "description": "Primary programming language" - }, - "name": { - "type": "string", - "description": "Repository name" - }, - "owner": { - "type": "string", - "description": "Repository owner" - }, - "stars": { - "type": "integer", - "format": "int32", - "description": "Star count" - } - } - }, - "PurgeLogsRequest": { - "type": "object", - "required": [ - "before" - ], - "properties": { - "before": { - "type": "string", - "description": "Delete all logs before this timestamp (ISO 8601)" - } - } - }, - "PushImageRequest": { - "type": "object", - "description": "Request to push an external image", - "required": [ - "image_ref" - ], - "properties": { - "image_ref": { - "type": "string" - }, - "metadata": {} - } - }, - "PushedExternalImageResponse": { - "type": "object", - "description": "Response for in-memory external image operations (legacy push flow).\n\nRenamed to avoid shadowing the richer database-backed `ExternalImageResponse`\nin `handlers/remote_deployments.rs`. The two types serve different routes\n(`/images` ephemeral push vs `/external-images` registered images).", - "required": [ - "id", - "image_ref", - "pushed_at" - ], - "properties": { - "digest": { - "type": [ - "string", - "null" - ] - }, - "id": { - "type": "string" - }, - "image_ref": { - "type": "string" - }, - "pushed_at": { - "type": "string", - "format": "date-time", - "example": "2025-10-12T12:15:47.609192Z" - }, - "size": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "minimum": 0 - } - } - }, - "QueryDataRequest": { - "type": "object", - "properties": { - "filters": { - "description": "JSON filters (backend-specific format)" - }, - "limit": { - "type": "integer", - "description": "Maximum number of rows to return", - "example": 100, - "minimum": 0 - }, - "offset": { - "type": "integer", - "description": "Number of rows to skip", - "example": 0, - "minimum": 0 - }, - "sort_by": { - "type": [ - "string", - "null" - ], - "description": "Sort by field name" - }, - "sort_order": { - "type": [ - "string", - "null" - ], - "description": "Sort order (asc/desc)" - } - } - }, - "QueryDataResponse": { - "type": "object", - "required": [ - "fields", - "rows", - "total_count", - "returned_count", - "execution_time_ms" - ], - "properties": { - "execution_time_ms": { - "type": "integer", - "format": "int64", - "description": "Query execution time in milliseconds", - "example": 45, - "minimum": 0 - }, - "fields": { - "type": "array", - "items": { - "$ref": "#/components/schemas/FieldResponse" - }, - "description": "Field definitions" - }, - "returned_count": { - "type": "integer", - "description": "Number of rows returned in this response", - "example": 100, - "minimum": 0 - }, - "rows": { - "type": "array", - "items": {}, - "description": "Data rows (array of JSON objects)" - }, - "total_count": { - "type": "integer", - "format": "int64", - "description": "Total number of rows matching the query (before limit/offset)", - "example": 1234, - "minimum": 0 - } - } - }, - "QuotaResponse": { - "type": "object", - "required": [ - "quota" - ], - "properties": { - "quota": { - "$ref": "#/components/schemas/StorageQuota" - } - } - }, - "RateLimitConfig": { - "type": "object", - "description": "Rate limiting configuration (subset of global RateLimitSettings)", - "properties": { - "blacklistIps": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Blacklist specific IPs for this project/environment" - }, - "maxRequestsPerHour": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Override rate limit per hour", - "minimum": 0 - }, - "maxRequestsPerMinute": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Override rate limit per minute", - "minimum": 0 - }, - "whitelistIps": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Whitelist specific IPs for this project/environment" - } - } - }, - "RateLimitSettings": { - "type": "object", - "properties": { - "blacklist_ips": { - "type": "array", - "items": { - "type": "string" - }, - "default": [] - }, - "enabled": { - "type": "boolean", - "default": false - }, - "max_requests_per_hour": { - "type": "integer", - "format": "int32", - "default": 1000, - "minimum": 0 - }, - "max_requests_per_minute": { - "type": "integer", - "format": "int32", - "default": 60, - "minimum": 0 - }, - "whitelist_ips": { - "type": "array", - "items": { - "type": "string" - }, - "default": [] - } - } - }, - "ReachabilityStatus": { - "type": "string", - "description": "Email reachability status", - "enum": [ - "safe", - "risky", - "invalid", - "unknown" - ] - }, - "ReadFileResponse": { - "type": "object", - "required": [ - "path", - "contents_b64", - "size" - ], - "properties": { - "contents_b64": { - "type": "string", - "description": "File contents, base64-encoded. Symmetric with `WriteFileBody`." - }, - "path": { - "type": "string" - }, - "size": { - "type": "integer", - "format": "int64", - "minimum": 0 - } - } - }, - "RecentActivityQuery": { - "type": "object", - "description": "Query parameters for recent activity endpoint", - "required": [ - "project_id" - ], - "properties": { - "environment_id": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Environment ID (optional)" - }, - "limit": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Max number of events to return (default: 50, max: 100)" - }, - "project_id": { - "type": "integer", - "format": "int32", - "description": "Project ID" - }, - "since_id": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "description": "Return events with ID greater than this (for cursor-based polling)" - } - } - }, - "RecentActivityResponse": { - "type": "object", - "description": "Response for recent activity events endpoint", - "required": [ - "events", - "count" - ], - "properties": { - "count": { - "type": "integer", - "description": "Total events returned", - "minimum": 0 - }, - "events": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ActivityEvent" - }, - "description": "Recent events, newest first" - } - } - }, - "RecentEventResponse": { - "type": "object", - "required": [ - "occurred_at", - "event_type" - ], - "properties": { - "amount_minor": { - "type": [ - "integer", - "null" - ], - "format": "int64" - }, - "currency": { - "type": [ - "string", - "null" - ] - }, - "customer_ref": { - "type": [ - "string", - "null" - ] - }, - "event_type": { - "type": "string" - }, - "mrr_minor": { - "type": [ - "integer", - "null" - ], - "format": "int64" - }, - "occurred_at": { - "type": "string", - "format": "date-time" - } - } - }, - "RecentQueryParams": { - "type": "object", - "properties": { - "conversation_id": { - "type": [ - "string", - "null" - ], - "description": "Filter by conversation ID" - }, - "cost_gt": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "description": "Cost strictly greater-than, in microcents" - }, - "cost_gte": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "description": "Cost greater-than-or-equal, in microcents" - }, - "cost_lt": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "description": "Cost strictly less-than, in microcents" - }, - "cost_lte": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "description": "Cost less-than-or-equal, in microcents" - }, - "limit": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "description": "Page size (defaults to 20, max 50)", - "minimum": 0 - }, - "model": { - "type": [ - "string", - "null" - ], - "description": "Filter by model name" - }, - "offset": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "description": "Number of results to skip for pagination (defaults to 0)", - "minimum": 0 - }, - "provider": { - "type": [ - "string", - "null" - ], - "description": "Filter by provider name" - }, - "status": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Filter by HTTP status code (exact match)" - }, - "tags": { - "type": [ - "string", - "null" - ], - "description": "Filter by tags (comma-separated, AND logic)" - }, - "tokens_gt": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "description": "Total tokens (input + output) strictly greater-than" - }, - "tokens_gte": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "description": "Total tokens (input + output) greater-than-or-equal" - }, - "tokens_lt": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "description": "Total tokens (input + output) strictly less-than" - }, - "tokens_lte": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "description": "Total tokens (input + output) less-than-or-equal" - }, - "user_id": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Filter by user ID" - } - } - }, - "RecordExposureRequest": { - "type": "object", - "description": "Keys a running app actually evaluated since its last report.", - "required": [ - "keys" - ], - "properties": { - "keys": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Flag keys evaluated since the last report. Unknown keys are ignored.", - "example": [ - "checkout.v2", - "api.rate_limit" - ] - } - } - }, - "RecordExposureResponse": { - "type": "object", - "required": [ - "recorded" - ], - "properties": { - "recorded": { - "type": "integer", - "format": "int64", - "description": "How many keys were accepted for processing.\n\nDeliberately not the number of rows updated: echoing that back would\nlet a caller post a single candidate key and read the result as \"this\nflag exists\", turning the endpoint into an existence oracle.", - "minimum": 0 - } - } - }, - "RecordListResponse": { - "type": "object", - "description": "Record list response", - "required": [ - "records" - ], - "properties": { - "records": { - "type": "array", - "items": { - "$ref": "#/components/schemas/DnsRecord" - } - } - } - }, - "RecoveryTarget": { - "oneOf": [ - { - "type": "object", - "description": "Recover to a specific timestamp.", - "required": [ - "time", - "kind" - ], - "properties": { - "kind": { - "type": "string", - "enum": [ - "time" - ] - }, - "time": { - "type": "string", - "format": "date-time" - } - } - }, - { - "type": "object", - "description": "Recover to a specific transaction id (Postgres).", - "required": [ - "xid", - "kind" - ], - "properties": { - "kind": { - "type": "string", - "enum": [ - "xid" - ] - }, - "xid": { - "type": "string" - } - } - }, - { - "type": "object", - "description": "Recover to a specific log sequence number (Postgres).", - "required": [ - "lsn", - "kind" - ], - "properties": { - "kind": { - "type": "string", - "enum": [ - "lsn" - ] - }, - "lsn": { - "type": "string" - } - } - }, - { - "type": "object", - "description": "Recover to a named restore point created via `pg_create_restore_point` (Postgres).", - "required": [ - "name", - "kind" - ], - "properties": { - "kind": { - "type": "string", - "enum": [ - "name" - ] - }, - "name": { - "type": "string" - } - } - } - ], - "description": "Engine-specific recovery target for PITR.\n\nPostgres honors all variants; Redis/Mongo/S3 will likely reject non-Time\nvariants or define their own semantics when they grow PITR support." - }, - "ReferrerCount": { - "type": "object", - "required": [ - "referrer", - "count", - "percentage" - ], - "properties": { - "count": { - "type": "integer", - "format": "int64" - }, - "percentage": { - "type": "number", - "format": "double" - }, - "referrer": { - "type": "string" - } - } - }, - "ReferrersAnalyticsQuery": { - "type": "object", - "required": [ - "start_date", - "end_date", - "project_id" - ], - "properties": { - "end_date": { - "type": "string", - "format": "date-time" - }, - "environment_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "project_id": { - "type": "integer", - "format": "int32" - }, - "start_date": { - "type": "string", - "format": "date-time" - } - } - }, - "RegenerateDSNRequest": { - "type": "object", - "properties": { - "base_url": { - "type": [ - "string", - "null" - ] - } - } - }, - "RegisterImageRequest": { - "type": "object", - "required": [ - "image_ref" - ], - "properties": { - "digest": { - "type": [ - "string", - "null" - ], - "description": "Image digest (sha256:...)", - "example": "sha256:abc123def456" - }, - "image_ref": { - "type": "string", - "description": "Docker image reference (e.g., \"ghcr.io/org/app:v1.0\")", - "example": "ghcr.io/myorg/myapp:v1.0" - }, - "metadata": { - "description": "Additional metadata" - }, - "tag": { - "type": [ - "string", - "null" - ], - "description": "Image tag", - "example": "v1.0" - } - } - }, - "RegisterNodeApiRequest": { - "type": "object", - "required": [ - "name", - "token", - "address", - "private_address" - ], - "properties": { - "address": { - "type": "string", - "description": "Node's reachable address (e.g., \"10.100.0.2\" or \"192.168.1.50\")" - }, - "architecture": { - "type": [ - "string", - "null" - ], - "description": "Container platform of this node's Docker daemon (`linux/amd64`,\n`linux/arm64`). Optional: agents older than multi-arch support omit it\nand the value is learned from the first heartbeat instead." - }, - "csr_pem": { - "type": [ - "string", - "null" - ], - "description": "Node-generated certificate signing request (PEM) for multi-node mTLS\n(ADR-020 WS-2.1). When present, the control plane signs it with the\ncluster CA and returns the leaf + CA cert. Optional \u2014 token-only nodes\n(legacy / edge) still register without one." - }, - "edge_public_key": { - "type": [ - "string", - "null" - ], - "description": "X25519 public key for ECIES certificate encryption (base64-encoded, edge nodes only)" - }, - "join_token": { - "type": [ - "string", - "null" - ], - "description": "Join token to authorize this registration (must match the token generated in Settings)" - }, - "labels": { - "description": "Labels for scheduling (e.g., {\"region\": \"us-east\", \"gpu\": \"true\"})" - }, - "name": { - "type": "string", - "description": "Unique name for this node" - }, - "prior_token": { - "type": [ - "string", - "null" - ], - "description": "The node's *current* token, supplied to prove possession when\nre-registering (changing the identity of) a node that already exists.\nOptional; only needed to rebind a still-live node. (ADR-020 WS-1.2.)" - }, - "private_address": { - "type": "string", - "description": "Private/WireGuard address for inter-node communication" - }, - "public_endpoint": { - "type": [ - "string", - "null" - ], - "description": "Public endpoint for WireGuard (e.g., \"203.0.113.1:51820\")" - }, - "role": { - "type": [ - "string", - "null" - ], - "description": "Node role (default: \"worker\")" - }, - "token": { - "type": "string", - "description": "Registration token (plaintext, will be hashed before storage)" - }, - "wg_public_key": { - "type": [ - "string", - "null" - ], - "description": "WireGuard public key" - } - } - }, - "RegisterNodeResponse": { - "type": "object", - "required": [ - "id", - "name", - "status", - "message" - ], - "properties": { - "ca_cert_pem": { - "type": [ - "string", - "null" - ], - "description": "The cluster CA certificate (PEM) the node pins as its trust root.\nPresent only when a `csr_pem` was supplied. (ADR-020 WS-2.1.)" - }, - "cert_pem": { - "type": [ - "string", - "null" - ], - "description": "The signed per-node leaf certificate (PEM) the agent serves as its TLS\nserver cert. Present only when a `csr_pem` was supplied. (ADR-020 WS-2.1.)" - }, - "id": { - "type": "integer", - "format": "int32" - }, - "message": { - "type": "string" - }, - "name": { - "type": "string" - }, - "status": { - "type": "string" - } - } - }, - "RegisterRequest": { - "type": "object", - "required": [ - "email", - "password", - "name" - ], - "properties": { - "email": { - "type": "string" - }, - "name": { - "type": "string" - }, - "password": { - "type": "string" - } - } - }, - "ReinstallWebhookResponse": { - "type": "object", - "description": "Response for `POST /projects/{project_id}/gitlab/reinstall-webhook`", - "required": [ - "hook_id", - "message" - ], - "properties": { - "hook_id": { - "type": "integer", - "format": "int32", - "description": "The new GitLab hook ID that was installed." - }, - "message": { - "type": "string", - "description": "Human-readable status message." - } - } - }, - "ReleaseListResponse": { - "type": "object", - "required": [ - "releases" - ], - "properties": { - "releases": { - "type": "array", - "items": { - "type": "string" - } - } - } - }, - "ReloadResponse": { - "type": "object", - "description": "Response from the reload endpoint.", - "required": [ - "loaded", - "plugins", - "message" - ], - "properties": { - "loaded": { - "type": "integer", - "description": "Number of plugins successfully loaded after reload", - "minimum": 0 - }, - "message": { - "type": "string", - "description": "Human-readable status message" - }, - "plugins": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Names of loaded plugins" - } - } - }, - "RemoteDeploymentResponse": { - "type": "object", - "required": [ - "id", - "project_id", - "environment_id", - "slug", - "state", - "source_type", - "created_at" - ], - "properties": { - "created_at": { - "type": "string", - "format": "date-time", - "example": "2025-10-12T12:15:47.609192Z" - }, - "environment_id": { - "type": "integer", - "format": "int32" - }, - "id": { - "type": "integer", - "format": "int32" - }, - "project_id": { - "type": "integer", - "format": "int32" - }, - "slug": { - "type": "string" - }, - "source_type": { - "type": "string" - }, - "state": { - "type": "string" - } - } - }, - "RemoveNodeResponse": { - "type": "object", - "required": [ - "id", - "message" - ], - "properties": { - "id": { - "type": "integer", - "format": "int32" - }, - "message": { - "type": "string" - } - } - }, - "RenameConversationRequest": { - "type": "object", - "required": [ - "title" - ], - "properties": { - "title": { - "type": "string", - "description": "New human-facing title. Trimmed; must be non-empty after trimming." - } - } - }, - "RepositoryListQuery": { - "type": "object", - "properties": { - "direction": { - "type": [ - "string", - "null" - ] - }, - "language": { - "type": [ - "string", - "null" - ] - }, - "owner": { - "type": [ - "string", - "null" - ] - }, - "page": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "minimum": 0 - }, - "per_page": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "minimum": 0 - }, - "private": { - "type": [ - "boolean", - "null" - ] - }, - "search": { - "type": [ - "string", - "null" - ] - }, - "sort": { - "type": [ - "string", - "null" - ] - } - } - }, - "RepositoryListResponse": { - "type": "object", - "required": [ - "repositories", - "total_count" - ], - "properties": { - "repositories": { - "type": "array", - "items": { - "$ref": "#/components/schemas/RepositoryResponse" - } - }, - "total_count": { - "type": "integer", - "minimum": 0 - } - } - }, - "RepositoryPresetResponse": { - "type": "object", - "required": [ - "repository_id", - "owner", - "name", - "presets", - "calculated_at" - ], - "properties": { - "calculated_at": { - "type": "string", - "format": "date-time" - }, - "name": { - "type": "string" - }, - "owner": { - "type": "string" - }, - "presets": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ProjectPresetResponse" - } - }, - "repository_id": { - "type": "integer", - "format": "int32" - } - } - }, - "RepositoryResponse": { - "type": "object", - "required": [ - "id", - "owner", - "name", - "full_name", - "private", - "default_branch", - "created_at", - "updated_at", - "pushed_at", - "git_provider_connection_id" - ], - "properties": { - "clone_url": { - "type": [ - "string", - "null" - ], - "description": "HTTPS clone URL (e.g., https://github.com/owner/repo.git)" - }, - "created_at": { - "type": "string", - "format": "date-time" - }, - "default_branch": { - "type": "string" - }, - "description": { - "type": [ - "string", - "null" - ] - }, - "full_name": { - "type": "string" - }, - "git_provider_connection_id": { - "type": "integer", - "format": "int32", - "description": "ID of the git provider connection this repository was synced from." - }, - "id": { - "type": "integer", - "format": "int32" - }, - "language": { - "type": [ - "string", - "null" - ] - }, - "name": { - "type": "string" - }, - "owner": { - "type": "string" - }, - "preset": { - "type": [ - "array", - "null" - ], - "items": { - "$ref": "#/components/schemas/ProjectPresetResponse" - } - }, - "private": { - "type": "boolean" - }, - "pushed_at": { - "type": "string", - "format": "date-time" - }, - "ssh_url": { - "type": [ - "string", - "null" - ], - "description": "SSH clone URL (e.g., git@github.com:owner/repo.git)" - }, - "updated_at": { - "type": "string", - "format": "date-time" - } - } - }, - "RepositorySyncStartedResponse": { - "type": "object", - "description": "Returned by `POST /git-connections/{id}/sync` to acknowledge that a\nsync has been kicked off in the background. Clients should poll the\nconnection's `syncing` and `synced_repository_count` fields to track\nprogress rather than waiting on this response.", - "required": [ - "connection_id", - "syncing", - "started_at" - ], - "properties": { - "connection_id": { - "type": "integer", - "format": "int32" - }, - "started_at": { - "type": "string", - "format": "date-time" - }, - "syncing": { - "type": "boolean" - } - } - }, - "RequestRow": { - "type": "object", - "required": [ - "id", - "ts", - "method", - "host", - "path", - "status", - "request_headers", - "response_headers", - "headers_truncated" - ], - "properties": { - "client_ip": { - "type": [ - "string", - "null" - ] - }, - "country": { - "type": [ - "string", - "null" - ] - }, - "deployment_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "environment_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "error_group_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "headers_truncated": { - "type": "boolean" - }, - "host": { - "type": "string" - }, - "id": { - "type": "string", - "description": "The request's unique `request_id` (assigned by the proxy). Used as the\nrow identity instead of the storage PK because the ClickHouse backend\nhas no serial id (rows come back with `id = 0`) while `request_id` is\nunique and present on both backends." - }, - "latency_ms": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "method": { - "type": "string" - }, - "path": { - "type": "string" - }, - "query_string": { - "type": [ - "string", - "null" - ] - }, - "referrer": { - "type": [ - "string", - "null" - ] - }, - "request_headers": {}, - "response_headers": {}, - "status": { - "type": "integer", - "format": "int32" - }, - "trace_id": { - "type": [ - "string", - "null" - ] - }, - "ts": { - "type": "string", - "format": "date-time" - }, - "user_agent": { - "type": [ - "string", - "null" - ] - } - } - }, - "ResetPasswordRequest": { - "type": "object", - "required": [ - "token", - "new_password" - ], - "properties": { - "new_password": { - "type": "string" - }, - "token": { - "type": "string" - } - } - }, - "ResetPgStatStatementsRequest": { - "type": "object", - "description": "Explicit confirmation required for the destructive statistics reset.\n\nRequiring JSON makes the endpoint non-simple for browsers, preventing a\ndeployed same-site application from triggering it with a plain HTML form.", - "required": [ - "confirm" - ], - "properties": { - "confirm": { - "type": "boolean", - "description": "Must be `true` to acknowledge the global, irreversible reset." - } - } - }, - "ResetPgStatStatementsResponse": { - "type": "object", - "description": "Response for the pg_stat_statements reset endpoint.", - "required": [ - "message" - ], - "properties": { - "message": { - "type": "string", - "description": "Human-readable message confirming the destructive action." - } - } - }, - "ResizeSandboxBody": { - "type": "object", - "required": [ - "disk_size_mb" - ], - "properties": { - "disk_size_mb": { - "type": "integer", - "format": "int64", - "description": "New root disk size in MB. Grow-only; must exceed the current size.", - "minimum": 0 - } - }, - "additionalProperties": false - }, - "ResolvedEnvVarResponse": { - "type": "object", - "description": "One entry in the computed env-var view that merges manual and integration\nsources and tags each result with its origin. `value_preview` is always\nmasked \u2014 plaintext must be fetched per-key via the existing reveal endpoint,\nwhich is audit-logged.", - "required": [ - "key", - "value_preview", - "source", - "environments", - "include_in_preview" - ], - "properties": { - "environments": { - "type": "array", - "items": { - "$ref": "#/components/schemas/EnvironmentInfo" - }, - "description": "Environments this var applies to. For integration-sourced vars this\nreflects every environment of the project (integrations are global)." - }, - "include_in_preview": { - "type": "boolean", - "description": "Whether the var would be auto-applied to preview environments.\nIntegration vars always surface in preview; manual vars follow the flag." - }, - "key": { - "type": "string" - }, - "source": { - "$ref": "#/components/schemas/ResolvedEnvVarSource" - }, - "value_preview": { - "type": "string", - "description": "Masked or truncated preview. Never the raw value." - } - } - }, - "ResolvedEnvVarSource": { - "oneOf": [ - { - "type": "object", - "description": "Manually-defined env var. If `overrides_service` is set, this key would\notherwise have been supplied by an integration \u2014 the UI should show the\nintegration icon plus an \"overridden\" indicator.", - "required": [ - "var_id", - "type" - ], - "properties": { - "overrides_service": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/EnvVarIntegrationInfo" - } - ] - }, - "type": { - "type": "string", - "enum": [ - "manual" - ] - }, - "var_id": { - "type": "integer", - "format": "int32" - } - } - }, - { - "type": "object", - "description": "Supplied by a linked external service (Postgres, Redis, S3, etc.).", - "required": [ - "service", - "type" - ], - "properties": { - "service": { - "$ref": "#/components/schemas/EnvVarIntegrationInfo" - }, - "type": { - "type": "string", - "enum": [ - "integration" - ] - } - } - } - ], - "description": "Where a resolved env var comes from. Integration-sourced vars may be\n\"shadowed\" by a manual entry with the same key, in which case the response\ncarries `Manual` with `overrides_service` populated so the UI can still show\nthe integration icon." - }, - "ResourceCounts": { - "type": "object", - "description": "Quick count of resources involved in the migration", - "required": [ - "projects", - "environments", - "deployments", - "environment_variables", - "services", - "domains" - ], - "properties": { - "deployments": { - "type": "integer", - "minimum": 0 - }, - "domains": { - "type": "integer", - "minimum": 0 - }, - "environment_variables": { - "type": "integer", - "minimum": 0 - }, - "environments": { - "type": "integer", - "minimum": 0 - }, - "projects": { - "type": "integer", - "minimum": 0 - }, - "services": { - "type": "integer", - "minimum": 0 - } - } - }, - "ResourceFootprint": { - "type": "object", - "description": "A CPU + memory footprint (requests or measured usage)", - "required": [ - "cpu_millis", - "memory_mb" - ], - "properties": { - "cpu_millis": { - "type": "integer", - "format": "int64", - "description": "CPU in millicores" - }, - "memory_mb": { - "type": "integer", - "format": "int64", - "description": "Memory in MB" - } - } - }, - "ResourceInfo": { - "type": "object", - "description": "Resource attributes extracted from OTel resource descriptors.", - "required": [ - "service_name", - "attributes" - ], - "properties": { - "attributes": { - "type": "object" - }, - "deployment_environment": { - "type": [ - "string", - "null" - ] - }, - "service_name": { - "type": "string" - }, - "service_version": { - "type": [ - "string", - "null" - ] - } - } - }, - "ResourceLimitApplyResult": { - "type": "object", - "description": "Per-container outcome of a live `docker update` call. Surfaced from the\nPATCH /resources endpoint so the UI can tell the operator whether the\nnew caps are already in effect or whether they only apply on next\nrecreate (e.g., container was missing).", - "required": [ - "role", - "container_name", - "outcome" - ], - "properties": { - "container_name": { - "type": "string" - }, - "error": { - "type": [ - "string", - "null" - ], - "description": "Populated only when `outcome == \"failed\"`." - }, - "outcome": { - "type": "string", - "description": "One of:\n- \"applied\" \u2014 Docker accepted the update; caps are live now.\n- \"missing\" \u2014 container does not exist; caps stored, will apply on next start.\n- \"stopped\" \u2014 container exists but isn't running; Docker still\n accepts the update (the new caps apply on next start).\n- \"failed\" \u2014 `docker update` returned an error (see `error`)." - }, - "role": { - "type": "string", - "description": "`service_members.role` for cluster members; \"standalone\" otherwise." - } - } - }, - "ResourceLimits": { - "type": "object", - "description": "Resource limits and requests", - "properties": { - "cpu_limit": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "CPU limit (millicores)" - }, - "cpu_request": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "CPU request (millicores)" - }, - "memory_limit": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Memory limit (MB)" - }, - "memory_request": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Memory request (MB)" - } - } - }, - "ResourceLimitsResponse": { - "type": "object", - "description": "Container resource limits", - "properties": { - "cpu_limit": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "cpu_request": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "memory_limit": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "memory_request": { - "type": [ - "integer", - "null" - ], - "format": "int32" - } - } - }, - "ResourceLimitsUpdateResponse": { - "type": "object", - "description": "Response from PATCH /external-services/{id}/resources.", - "required": [ - "limits", - "applied" - ], - "properties": { - "applied": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ResourceLimitApplyResult" - }, - "description": "Per-container result of trying to apply the limits live." - }, - "limits": { - "$ref": "#/components/schemas/ServiceResourceLimits", - "description": "The limits that were persisted to the encrypted config." - } - } - }, - "ResourcesBody": { - "type": "object", - "description": "Nested `resources: { memory, vcpus }` as sent by `@vercel/sandbox`.\n`memory` is in MB, `vcpus` is fractional CPU count.", - "properties": { - "memory": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "minimum": 0 - }, - "vcpus": { - "type": [ - "number", - "null" - ], - "format": "double" - } - } - }, - "RestoreCapabilities": { - "type": "object", - "description": "Capabilities a service exposes for the generic restore framework.\n\nEach engine overrides `ExternalService::restore_capabilities` to declare\nwhat it supports. The handler layer uses this to validate requests and\nthe UI uses it to conditionally show options (e.g., PITR picker).", - "required": [ - "restore_in_place", - "restore_to_new_service", - "pitr" - ], - "properties": { - "earliest_pitr_time": { - "type": [ - "string", - "null" - ], - "format": "date-time", - "description": "Earliest recoverable timestamp, if `pitr` is true. Derived from\nengine-specific archive metadata (e.g., `pg_stat_archiver`)." - }, - "latest_pitr_time": { - "type": [ - "string", - "null" - ], - "format": "date-time", - "description": "Latest recoverable timestamp, if `pitr` is true." - }, - "pitr": { - "type": "boolean", - "description": "Point-in-time recovery using engine-specific continuous archives\n(WAL for Postgres, AOF for Redis, oplog for MongoDB, object versions for S3)." - }, - "restore_in_place": { - "type": "boolean", - "description": "Restore a backup onto the same running service (destructive)." - }, - "restore_to_new_service": { - "type": "boolean", - "description": "Restore a backup into a freshly provisioned service." - } - } - }, - "RestoreCapabilitiesResponse": { - "allOf": [ - { - "$ref": "#/components/schemas/RestoreCapabilities", - "description": "Trait-declared capabilities." - }, - { - "type": "object", - "required": [ - "suggested_new_service_name" - ], - "properties": { - "suggested_new_service_name": { - "type": "string", - "description": "Suggested name for the new service when creating a clone. Safe to\npre-fill into the UI dialog; the user can edit before submitting." - } - } - } - ] - }, - "RestorePlan": { - "type": "object", - "description": "Preview of a restore operation. Answers \"what will happen if I click\nstart?\" with engine-level specificity so the user can confirm before\ncommitting to a destructive action.", - "required": [ - "engine", - "target_service", - "source_backup", - "strategy", - "steps", - "warnings", - "errors", - "destructive", - "mode" - ], - "properties": { - "destructive": { - "type": "boolean", - "description": "Whether any step overwrites existing data on the target service." - }, - "engine": { - "type": "string", - "description": "Target engine (\"postgres\", etc.)." - }, - "errors": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Blocking problems. The UI disables the Start button when non-empty." - }, - "mode": { - "type": "string", - "description": "Echo of the requested mode for the UI." - }, - "source_backup": { - "$ref": "#/components/schemas/PlanSourceBackup", - "description": "Backup we'll read from." - }, - "steps": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Ordered list of human-readable actions the orchestrator will take." - }, - "strategy": { - "type": "string", - "description": "How the restore will be performed: \"walg_restore\", \"pg_dump_restore\",\nor \"unsupported\"." - }, - "target_service": { - "$ref": "#/components/schemas/PlanTarget", - "description": "Service we'll operate on (or provision a sibling of)." - }, - "warnings": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Non-blocking caveats the user should see (cross-service, empty\nlocation that will be auto-resolved, missing engine metadata, ...)." - } - } - }, - "RestoreRequestMode": { - "oneOf": [ - { - "type": "object", - "description": "Restore the backup onto the existing service (destructive).", - "required": [ - "mode" - ], - "properties": { - "mode": { - "type": "string", - "enum": [ - "in_place" - ] - } - } - }, - { - "type": "object", - "description": "Provision a new service and restore into it.", - "required": [ - "name", - "mode" - ], - "properties": { - "mode": { - "type": "string", - "enum": [ - "new_service" - ] - }, - "name": { - "type": "string", - "description": "Name for the new service. Orchestrator auto-suggests\n`{source}-restore-{yyyymmdd-hhmm}` if caller omits, but we require\nan explicit value at the API boundary." - }, - "parameter_overrides": { - "description": "Optional parameter overrides (port, docker_image, database)." - } - } - }, - { - "type": "object", - "description": "Point-in-time recovery. Only valid on WAL-G backups (Postgres).", - "required": [ - "to_new_service", - "target", - "mode" - ], - "properties": { - "mode": { - "type": "string", - "enum": [ - "pitr" - ] - }, - "new_service_name": { - "type": [ - "string", - "null" - ], - "description": "Required when `to_new_service` is true." - }, - "target": { - "$ref": "#/components/schemas/RecoveryTarget", - "description": "Recovery target kind + value." - }, - "to_new_service": { - "type": "boolean", - "description": "Whether PITR restores in place or creates a new service." - } - } - } - ], - "description": "What the caller wants to do. Mirrors `externalsvc::RestoreMode` but\nflattened for JSON over the wire." - }, - "RestoreRunView": { - "type": "object", - "required": [ - "id", - "source_backup_id", - "source_service_id", - "mode", - "status", - "phase", - "created_at" - ], - "properties": { - "created_at": { - "type": "string" - }, - "error_message": { - "type": [ - "string", - "null" - ] - }, - "finished_at": { - "type": [ - "string", - "null" - ] - }, - "id": { - "type": "integer", - "format": "int32" - }, - "mode": { - "type": "string" - }, - "phase": { - "type": "string" - }, - "recovery_target": {}, - "source_backup_id": { - "type": "integer", - "format": "int32" - }, - "source_service_id": { - "type": "integer", - "format": "int32" - }, - "started_at": { - "type": [ - "string", - "null" - ] - }, - "status": { - "type": "string" - }, - "target_service_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "target_service_name": { - "type": [ - "string", - "null" - ] - } - } - }, - "RetentionCleanupFailure": { - "type": "object", - "required": [ - "backup_id", - "reason", - "partial", - "deleted_objects" - ], - "properties": { - "backup_id": { - "type": "string" - }, - "deleted_objects": { - "type": "integer", - "format": "int64", - "minimum": 0 - }, - "partial": { - "type": "boolean" - }, - "reason": { - "type": "string" - } - } - }, - "RetentionCleanupReport": { - "type": "object", - "required": [ - "dry_run", - "expired", - "deleted", - "failed", - "failures", - "deleted_backup_ids", - "deleted_backup_ids_truncated", - "partially_deleted_backup_ids", - "partially_deleted_backup_ids_truncated", - "candidate_backup_ids", - "candidate_backup_ids_truncated" - ], - "properties": { - "candidate_backup_ids": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Capped sample of backups selected by the retention policy." - }, - "candidate_backup_ids_truncated": { - "type": "boolean" - }, - "deleted": { - "type": "integer", - "format": "int64", - "minimum": 0 - }, - "deleted_backup_ids": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Capped sample of deleted backup UUIDs for audit attribution." - }, - "deleted_backup_ids_truncated": { - "type": "boolean" - }, - "dry_run": { - "type": "boolean", - "description": "True when this report is a non-destructive preview." - }, - "expired": { - "type": "integer", - "format": "int64", - "minimum": 0 - }, - "failed": { - "type": "integer", - "format": "int64", - "minimum": 0 - }, - "failures": { - "type": "array", - "items": { - "$ref": "#/components/schemas/RetentionCleanupFailure" - }, - "description": "Capped diagnostic sample; `failed` remains the authoritative total." - }, - "partially_deleted_backup_ids": { - "type": "array", - "items": { - "type": "string" - } - }, - "partially_deleted_backup_ids_truncated": { - "type": "boolean" - }, - "schedule_id": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Schedule scope, or `None` when every schedule was considered." - } - } - }, - "RetryClusterRequest": { - "type": "object", - "description": "Request body for retrying a failed cluster initialization.", - "properties": { - "members": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ClusterMemberRequest" - }, - "description": "Cluster member specifications (same format as create).\nIf omitted, the original member configuration is reconstructed from\nthe preserved service_members records." - } - } - }, - "RevenueRow": { - "type": "object", - "required": [ - "id", - "ts", - "provider", - "event_type" - ], - "properties": { - "amount_minor": { - "type": [ - "integer", - "null" - ], - "format": "int64" - }, - "currency": { - "type": [ - "string", - "null" - ] - }, - "customer_ref": { - "type": [ - "string", - "null" - ] - }, - "deployment_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "environment_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "event_type": { - "type": "string" - }, - "id": { - "type": "integer", - "format": "int64" - }, - "provider": { - "type": "string" - }, - "trace_id": { - "type": [ - "string", - "null" - ] - }, - "ts": { - "type": "string", - "format": "date-time" - } - } - }, - "RiskLevel": { - "type": "string", - "description": "Risk level for a migration step", - "enum": [ - "none", - "low", - "medium", - "high", - "critical" - ] - }, - "RoleInfo": { - "type": "object", - "description": "Information about a role", - "required": [ - "name", - "description", - "permissions" - ], - "properties": { - "description": { - "type": "string", - "description": "Human-readable description of the role" - }, - "name": { - "type": "string", - "description": "The role identifier (e.g., \"admin\")" - }, - "permissions": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Permissions included in this role" - } - } - }, - "RootfsCacheEntry": { - "type": "object", - "description": "A cached rootfs image (Firecracker backend). Digest-keyed build artifact\nshared by all VMs created from the same image.", - "required": [ - "digest", - "bytes", - "referenced_by" - ], - "properties": { - "bytes": { - "type": "integer", - "format": "int64", - "description": "Actual on-disk size in bytes (sparse-aware).", - "minimum": 0 - }, - "digest": { - "type": "string", - "description": "Image digest this rootfs was built from (the cache key)." - }, - "referenced_by": { - "type": "array", - "items": { - "type": "string" - }, - "description": "IDs of live sandboxes whose per-VM disk was cloned from this entry.\nEmpty means the entry is reclaimable \u2014 no sandbox needs it." - } - } - }, - "RootfsGcReport": { - "type": "object", - "description": "Outcome of a rootfs garbage-collection pass.", - "required": [ - "removed_digests", - "freed_bytes" - ], - "properties": { - "freed_bytes": { - "type": "integer", - "format": "int64", - "minimum": 0 - }, - "removed_digests": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Digests of cache entries removed because no sandbox referenced them." - } - } - }, - "RootfsReport": { - "type": "object", - "description": "Snapshot of a backend's rootfs storage for the management API. Backends\nwithout a rootfs concept (Docker, local) return an empty report.", - "required": [ - "cache_bytes", - "cache", - "vm_bytes", - "vms" - ], - "properties": { - "cache": { - "type": "array", - "items": { - "$ref": "#/components/schemas/RootfsCacheEntry" - } - }, - "cache_bytes": { - "type": "integer", - "format": "int64", - "minimum": 0 - }, - "vm_bytes": { - "type": "integer", - "format": "int64", - "minimum": 0 - }, - "vms": { - "type": "array", - "items": { - "$ref": "#/components/schemas/RootfsVmEntry" - } - } - } - }, - "RootfsVmEntry": { - "type": "object", - "description": "A per-sandbox rootfs disk (Firecracker backend). One per non-destroyed\nsandbox \u2014 the authoritative storage, independent of the cache.", - "required": [ - "sandbox_name", - "bytes", - "running" - ], - "properties": { - "bytes": { - "type": "integer", - "format": "int64", - "minimum": 0 - }, - "running": { - "type": "boolean" - }, - "sandbox_name": { - "type": "string" - } - } - }, - "RouteRefreshResponse": { - "type": "object", - "required": [ - "route_count", - "message" - ], - "properties": { - "message": { - "type": "string", - "description": "Human-readable message" - }, - "route_count": { - "type": "integer", - "description": "Number of routes loaded", - "minimum": 0 - } - } - }, - "RouteResponse": { - "type": "object", - "required": [ - "id", - "domain", - "host", - "port", - "enabled", - "route_type", - "created_at", - "updated_at" - ], - "properties": { - "created_at": { - "type": "integer", - "format": "int64" - }, - "domain": { - "type": "string" - }, - "enabled": { - "type": "boolean" - }, - "host": { - "type": "string" - }, - "id": { - "type": "integer", - "format": "int32" - }, - "port": { - "type": "integer", - "format": "int32" - }, - "route_type": { - "type": "string", - "description": "Route type: \"http\" or \"tls\"" - }, - "updated_at": { - "type": "integer", - "format": "int64" - } - } - }, - "RouteRole": { - "type": "object", - "required": [ - "id", - "name", - "created_at", - "updated_at" - ], - "properties": { - "created_at": { - "type": "integer", - "format": "int64", - "example": "1683900000000" - }, - "id": { - "type": "integer", - "format": "int32" - }, - "name": { - "type": "string" - }, - "updated_at": { - "type": "integer", - "format": "int64", - "example": "1683900000000" - } - } - }, - "RouteUser": { - "type": "object", - "required": [ - "id", - "name", - "username", - "email", - "image", - "mfa_enabled", - "email_verified", - "created_at", - "updated_at" - ], - "properties": { - "created_at": { - "type": "integer", - "format": "int64", - "example": "1683900000000" - }, - "deleted_at": { - "type": [ - "integer", - "null" - ], - "format": "int64" - }, - "email": { - "type": "string" - }, - "email_verified": { - "type": "boolean" - }, - "id": { - "type": "integer", - "format": "int32" - }, - "image": { - "type": "string" - }, - "mfa_enabled": { - "type": "boolean" - }, - "name": { - "type": "string" - }, - "updated_at": { - "type": "integer", - "format": "int64", - "example": "1683900000000" - }, - "username": { - "type": "string" - } - } - }, - "RouteUserWithRoles": { - "type": "object", - "required": [ - "user", - "roles" - ], - "properties": { - "roles": { - "type": "array", - "items": { - "$ref": "#/components/schemas/RouteRole" - } - }, - "user": { - "$ref": "#/components/schemas/RouteUser" - } - } - }, - "RunBackupRequest": { - "type": "object", - "required": [ - "backup_type" - ], - "properties": { - "backup_type": { - "type": "string", - "description": "Type of backup to perform", - "example": "full" - } - } - }, - "RunExternalServiceBackupRequest": { - "type": "object", - "properties": { - "backup_type": { - "type": [ - "string", - "null" - ], - "description": "Type of backup to perform (e.g., \"full\", \"incremental\")", - "example": "full" - }, - "s3_source_id": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "ID of the S3 source to store the backup. If omitted, the current default S3 source is used.", - "example": 1 - } - } - }, - "S3ConnectionTestResponse": { - "type": "object", - "description": "Response body for an S3 connection test.", - "required": [ - "ok", - "message" - ], - "properties": { - "message": { - "type": "string", - "description": "Human-readable message (success confirmation or error detail)." - }, - "ok": { - "type": "boolean", - "description": "Whether the connection and credentials worked." - } - } - }, - "S3CredentialsResponse": { - "type": "object", - "description": "S3 credentials distributed to agents for backup/restore operations.", - "required": [ - "access_key_id", - "secret_key", - "region", - "bucket_name", - "force_path_style" - ], - "properties": { - "access_key_id": { - "type": "string" - }, - "bucket_name": { - "type": "string" - }, - "endpoint": { - "type": [ - "string", - "null" - ] - }, - "force_path_style": { - "type": "boolean" - }, - "region": { - "type": "string" - }, - "secret_key": { - "type": "string" - } - } - }, - "S3SourceResponse": { - "type": "object", - "description": "Response type for S3 source", - "required": [ - "id", - "name", - "bucket_name", - "bucket_path", - "access_key_id", - "secret_key", - "region", - "is_default", - "created_at", - "updated_at" - ], - "properties": { - "access_key_id": { - "type": "string", - "example": "AKIAXXXXXXXXXXXXXXXX" - }, - "bucket_name": { - "type": "string" - }, - "bucket_path": { - "type": "string" - }, - "created_at": { - "type": "integer", - "format": "int64" - }, - "endpoint": { - "type": [ - "string", - "null" - ], - "example": "http://minio.example.com:9000" - }, - "force_path_style": { - "type": [ - "boolean", - "null" - ] - }, - "id": { - "type": "integer", - "format": "int32" - }, - "is_default": { - "type": "boolean" - }, - "name": { - "type": "string" - }, - "region": { - "type": "string" - }, - "secret_key": { - "type": "string", - "writeOnly": true - }, - "updated_at": { - "type": "integer", - "format": "int64" - } - } - }, - "SandboxDomainResponse": { - "type": "object", - "required": [ - "url" - ], - "properties": { - "url": { - "type": "string" - } - } - }, - "SandboxEvent": { - "type": "object", - "description": "One entry in a sandbox's operations timeline.", - "required": [ - "event_type", - "at" - ], - "properties": { - "at": { - "type": "integer", - "format": "int64", - "description": "Unix epoch milliseconds." - }, - "detail": { - "description": "Optional structured context (shape depends on `event_type`)." - }, - "event_type": { - "type": "string", - "description": "Machine-readable operation (`created`, `stopped`, `resumed`,\n`restarted`, `timeout_extended`, `resized`, `preview_password_set`,\n`preview_password_cleared`, `preview_share_link_created`, `source_seeded`,\n`destroyed`)." - } - } - }, - "SandboxEventsResponse": { - "type": "object", - "required": [ - "events" - ], - "properties": { - "events": { - "type": "array", - "items": { - "$ref": "#/components/schemas/SandboxEvent" - } - } - } - }, - "SandboxInner": { - "type": "object", - "description": "Inner `sandbox` object in `@vercel/sandbox` responses. Strict shape \u2014\nthe SDK's zod validator rejects missing required fields.", - "required": [ - "id", - "memory", - "vcpus", - "region", - "runtime", - "timeout", - "status", - "requestedAt", - "createdAt", - "updatedAt", - "cwd", - "name", - "preview_url_template" - ], - "properties": { - "agent_run_id": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Agent run this sandbox executes (autofixer / workflow agent).\n`None` for sandboxes created via this API." - }, - "backend": { - "type": [ - "string", - "null" - ], - "description": "Isolation backend: \"docker\" | \"firecracker\". `None` on legacy rows\ncreated before the backend was recorded." - }, - "createdAt": { - "type": "integer", - "format": "int64" - }, - "cwd": { - "type": "string" - }, - "disk_size_mb": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "description": "Configured root disk size in MB (Firecracker). `None` when unknown or\nthe default.", - "minimum": 0 - }, - "id": { - "type": "string" - }, - "image": { - "type": [ - "string", - "null" - ] - }, - "memory": { - "type": "integer", - "format": "int64", - "minimum": 0 - }, - "name": { - "type": "string" - }, - "preview_password_hint": { - "type": [ - "string", - "null" - ] - }, - "preview_url_template": { - "type": "string" - }, - "region": { - "type": "string" - }, - "requestedAt": { - "type": "integer", - "format": "int64", - "description": "Creation time as Unix epoch milliseconds." - }, - "runtime": { - "type": "string" - }, - "status": { - "type": "string" - }, - "timeout": { - "type": "integer", - "format": "int64", - "description": "Idle timeout in milliseconds (SDK convention).", - "minimum": 0 - }, - "updatedAt": { - "type": "integer", - "format": "int64" - }, - "vcpus": { - "type": "number", - "format": "double" - } - } - }, - "SandboxResponse": { - "type": "object", - "description": "`@vercel/sandbox` wraps every single-sandbox response as\n`{ sandbox: {...}, routes: [...] }`. The SDK reads both.", - "required": [ - "sandbox", - "routes" - ], - "properties": { - "routes": { - "type": "array", - "items": { - "$ref": "#/components/schemas/SandboxRoute" - } - }, - "sandbox": { - "$ref": "#/components/schemas/SandboxInner" - } - } - }, - "SandboxRoute": { - "type": "object", - "description": "A single preview route, one per declared port. We don't know ports\nupfront, so we surface an empty array by default \u2014 SDK clients use\ntheir own port when calling `sandbox.domain(port)`.", - "required": [ - "url", - "subdomain", - "port" - ], - "properties": { - "port": { - "type": "integer", - "format": "int32", - "minimum": 0 - }, - "subdomain": { - "type": "string" - }, - "url": { - "type": "string" - } - } - }, - "SandboxStatusResponse": { - "type": "object", - "required": [ - "docker_available", - "image_ready", - "image_name", - "firecracker_available" - ], - "properties": { - "docker_available": { - "type": "boolean" - }, - "error": { - "type": [ - "string", - "null" - ] - }, - "firecracker_available": { - "type": "boolean" - }, - "image_name": { - "type": "string" - }, - "image_ready": { - "type": "boolean" - } - } - }, - "SaveAgentTokenRequest": { - "type": "object", - "required": [ - "token" - ], - "properties": { - "token": { - "type": "string", - "description": "The OAuth token from `claude setup-token` or an API key.\nWill be encrypted before storage." - } - } - }, - "SaveAgentTokenResponse": { - "type": "object", - "required": [ - "saved" - ], - "properties": { - "saved": { - "type": "boolean" - } - } - }, - "SaveCredentialRequest": { - "type": "object", - "required": [ - "auth_type", - "credential" - ], - "properties": { - "auth_type": { - "type": "string", - "description": "Auth flavor id (must match one of the provider's catalog entries)." - }, - "credential": { - "type": "string", - "description": "Plaintext credential body (API key, OAuth token, or full config file\ncontents). Encrypted with `EncryptionService` before being persisted\ninside the `agent_sandbox.providers` JSON map." - } - } - }, - "SaveCredentialResponse": { - "type": "object", - "required": [ - "saved", - "provider_id", - "auth_type" - ], - "properties": { - "auth_type": { - "type": "string" - }, - "provider_id": { - "type": "string" - }, - "saved": { - "type": "boolean" - } - } - }, - "ScalewayCredentialsRequest": { - "type": "object", - "required": [ - "api_key", - "project_id" - ], - "properties": { - "api_key": { - "type": "string", - "example": "scw-secret-key-12345" - }, - "project_id": { - "type": "string", - "example": "12345678-1234-1234-1234-123456789012" - } - } - }, - "ScanResponse": { - "type": "object", - "required": [ - "id", - "project_id", - "scanner_type", - "status", - "total_count", - "critical_count", - "high_count", - "medium_count", - "low_count", - "unknown_count", - "started_at", - "created_at", - "updated_at" - ], - "properties": { - "branch": { - "type": [ - "string", - "null" - ] - }, - "commit_hash": { - "type": [ - "string", - "null" - ] - }, - "completed_at": { - "type": [ - "string", - "null" - ], - "example": "2025-12-08T12:15:47.609192Z" - }, - "created_at": { - "type": "string", - "example": "2025-12-08T12:15:47.609192Z" - }, - "critical_count": { - "type": "integer", - "format": "int32" - }, - "deployment_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "environment_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "error_message": { - "type": [ - "string", - "null" - ] - }, - "high_count": { - "type": "integer", - "format": "int32" - }, - "id": { - "type": "integer", - "format": "int32" - }, - "low_count": { - "type": "integer", - "format": "int32" - }, - "medium_count": { - "type": "integer", - "format": "int32" - }, - "project_id": { - "type": "integer", - "format": "int32" - }, - "scanner_type": { - "type": "string" - }, - "scanner_version": { - "type": [ - "string", - "null" - ] - }, - "started_at": { - "type": "string", - "example": "2025-12-08T12:15:47.609192Z" - }, - "status": { - "type": "string" - }, - "total_count": { - "type": "integer", - "format": "int32" - }, - "unknown_count": { - "type": "integer", - "format": "int32" - }, - "updated_at": { - "type": "string", - "example": "2025-12-08T12:15:47.609192Z" - } - } - }, - "ScheduleRunEntry": { - "type": "object", - "description": "A single run-history entry for the schedule detail page (deliverable 1).\n\nCombines one `backups` row with the most-recent `backup_jobs` row for that\nbackup via a lateral JOIN. Fields from `backup_jobs` are `None` for legacy\nbackup rows that pre-date ADR-014.", - "required": [ - "backup_id", - "backup_uuid", - "state", - "started_at", - "s3_location" - ], - "properties": { - "attempts": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Number of claim-and-run attempts so far. `None` for legacy rows." - }, - "backup_id": { - "type": "integer", - "format": "int32", - "description": "DB id of the `backups` row." - }, - "backup_uuid": { - "type": "string", - "description": "UUID string (`backups.backup_id`)." - }, - "current_step": { - "type": [ - "string", - "null" - ], - "description": "Last completed step reported by the engine (e.g. `\"upload\"`).\n`None` when no step has been persisted yet." - }, - "error_message": { - "type": [ - "string", - "null" - ], - "description": "Engine-reported error message when `state = \"failed\"`." - }, - "finished_at": { - "type": [ - "string", - "null" - ], - "description": "When the backup finished, if known." - }, - "job_id": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "description": "Most recent `backup_jobs.id` for this backup. `None` for legacy rows." - }, - "s3_location": { - "type": "string", - "description": "S3 object key or URL where the backup data lives." - }, - "size_bytes": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "description": "Final size in bytes once completed. `None` while running." - }, - "started_at": { - "type": "string", - "description": "When the backup was started (ISO 8601 / RFC 3339)." - }, - "state": { - "type": "string", - "description": "Current state: `\"pending\"`, `\"running\"`, `\"completed\"`, `\"failed\"`." - } - } - }, - "ScheduleRunJobEntry": { - "type": "object", - "description": "A single job entry inside an expanded schedule run, returned by\n[`BackupService::list_schedule_run_jobs`].", - "required": [ - "backup_id", - "backup_uuid", - "engine", - "service_name", - "state", - "started_at", - "s3_source_id" - ], - "properties": { - "backup_id": { - "type": "integer", - "format": "int32", - "description": "`backups.id` for this job." - }, - "backup_uuid": { - "type": "string", - "description": "`backups.backup_id` UUID string." - }, - "engine": { - "type": "string", - "description": "Engine key (e.g. `\"control_plane\"`, `\"redis\"`)." - }, - "error_message": { - "type": [ - "string", - "null" - ], - "description": "Engine-reported error message when `state = \"failed\"`." - }, - "finished_at": { - "type": [ - "string", - "null" - ], - "description": "When this child backup finished, if known." - }, - "s3_source_id": { - "type": "integer", - "format": "int32", - "description": "FK to `s3_sources.id` \u2014 needed for the backup detail link." - }, - "service_id": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "`external_services.id` \u2014 `NULL` for the control-plane job." - }, - "service_name": { - "type": "string", - "description": "Name of the external service, or `\"control plane\"` for the\ncontrol-plane job." - }, - "size_bytes": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "description": "Size in bytes once completed; `None` while running." - }, - "started_at": { - "type": "string", - "description": "When this child backup started (ISO 8601 / RFC 3339)." - }, - "state": { - "type": "string", - "description": "Current state of this child backup." - } - } - }, - "ScheduleRunListResponse": { - "type": "object", - "description": "Paginated run-history response for a backup schedule (deliverable 1).", - "required": [ - "runs", - "total", - "page", - "page_size" - ], - "properties": { - "page": { - "type": "integer", - "format": "int64", - "description": "Current page (1-based)." - }, - "page_size": { - "type": "integer", - "format": "int64", - "description": "Number of items per page (clamped to 1\u2013100)." - }, - "runs": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ScheduleRunEntry" - }, - "description": "Run entries, newest first." - }, - "total": { - "type": "integer", - "format": "int64", - "description": "Total number of runs across all pages." - } - } - }, - "ScheduleRunResponse": { - "type": "object", - "description": "HTTP response body for `POST /api/backups/schedules/{id}/run` (fan-out).", - "required": [ - "schedule_run_id", - "jobs" - ], - "properties": { - "jobs": { - "type": "array", - "items": { - "$ref": "#/components/schemas/EnqueuedJob" - }, - "description": "All jobs that were enqueued in this fan-out." - }, - "schedule_run_id": { - "type": "integer", - "format": "int64", - "description": "The `schedule_runs.id` of the newly created run." - } - } - }, - "ScheduleRunSummary": { - "type": "object", - "description": "Summary of one scheduler tick (or one \"Run now\" click), returned by\n[`BackupService::list_schedule_runs`].\n\nThe `aggregate_state` is computed at read time from child backup counts:\n- `\"running\"` \u2014 at least one child is `\"pending\"` or `\"running\"`.\n- `\"failed\"` \u2014 at least one child is `\"failed\"` and none are running.\n- `\"completed\"` \u2014 all children are `\"completed\"`.", - "required": [ - "run_id", - "schedule_id", - "triggered_by", - "started_at", - "aggregate_state", - "total_jobs", - "completed_jobs", - "failed_jobs", - "running_jobs", - "pending_jobs" - ], - "properties": { - "aggregate_state": { - "type": "string", - "description": "Aggregate state computed from child counts (see struct docs)." - }, - "completed_jobs": { - "type": "integer", - "format": "int64", - "description": "Number of children in `state = \"completed\"`." - }, - "failed_jobs": { - "type": "integer", - "format": "int64", - "description": "Number of children in `state = \"failed\"`." - }, - "finished_at": { - "type": [ - "string", - "null" - ], - "description": "When all children reached a terminal state. `None` while any child is\nstill `\"pending\"` or `\"running\"`." - }, - "pending_jobs": { - "type": "integer", - "format": "int64", - "description": "Number of children in `state = \"pending\"`." - }, - "run_id": { - "type": "integer", - "format": "int64", - "description": "`schedule_runs.id` for this tick." - }, - "running_jobs": { - "type": "integer", - "format": "int64", - "description": "Number of children in `state = \"running\"`." - }, - "schedule_id": { - "type": "integer", - "format": "int32", - "description": "FK to `backup_schedules.id`." - }, - "started_at": { - "type": "string", - "description": "When the fan-out started (ISO 8601 / RFC 3339)." - }, - "total_jobs": { - "type": "integer", - "format": "int64", - "description": "Total number of child backup jobs in this run." - }, - "triggered_by": { - "type": "string", - "description": "How the run was triggered: `\"cron\"` or `\"manual\"`." - } - } - }, - "ScheduleRunSummaryList": { - "type": "object", - "description": "Paginated list of schedule run summaries returned by the new\n[`BackupService::list_schedule_runs`].", - "required": [ - "runs", - "total", - "page", - "page_size" - ], - "properties": { - "page": { - "type": "integer", - "format": "int64", - "description": "Current page (1-based)." - }, - "page_size": { - "type": "integer", - "format": "int64", - "description": "Number of items per page." - }, - "runs": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ScheduleRunSummary" - }, - "description": "Run summaries, newest first. Includes synthetic single-job rows for\nlegacy `backups` rows that have `schedule_id` set but no\n`schedule_run_id` (pre-fan-out history)." - }, - "total": { - "type": "integer", - "format": "int64", - "description": "Total number of run entries across all pages." - } - } - }, - "ScreenshotSettings": { - "type": "object", - "properties": { - "enabled": { - "type": "boolean", - "default": false - }, - "provider": { - "type": "string", - "default": "local" - }, - "url": { - "type": "string", - "default": "" - } - } - }, - "SearchLogsRequest": { - "type": "object", - "required": [ - "project_id" - ], - "properties": { - "container_ids": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Filter to specific containers (Docker container IDs). Empty = all\ncontainers. Drives \"filter by container / show all\" in a project's\nhistory, which spans multiple deployments and containers." - }, - "context_lines": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "grep -C: number of raw context lines to include before and after each\nmatch (0 = none, default). Clamped to 50 server-side. The surrounding\nlines ignore the level/text filters \u2014 they are the actual adjacent log\nlines, merged across overlapping matches.", - "minimum": 0 - }, - "cursor": { - "type": [ - "string", - "null" - ], - "description": "Pagination cursor" - }, - "deploy_id": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Filter by deployment ID (deployments.id)" - }, - "end_time": { - "type": [ - "string", - "null" - ], - "description": "End of time range (ISO 8601). Defaults to now." - }, - "envs": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Filter by environments" - }, - "external_service_id": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "When set, search an imported/managed external service's logs instead\nof a project's. `project_id` is ignored in this mode." - }, - "levels": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Filter by log levels" - }, - "node_ids": { - "type": "array", - "items": { - "type": "integer", - "format": "int32" - }, - "description": "Filter to specific worker nodes (node_id). Empty = all nodes, including\ncontrol-plane-local logs." - }, - "page_size": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Page size (default: 100, max: 500)", - "minimum": 0 - }, - "project_id": { - "type": "integer", - "format": "int32", - "description": "Project ID (integer, as used by the rest of the platform)" - }, - "services": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Filter by services" - }, - "start_time": { - "type": [ - "string", - "null" - ], - "description": "Start of time range (ISO 8601). Defaults to 1 hour ago." - }, - "text": { - "type": [ - "string", - "null" - ], - "description": "Full text search query" - } - } - }, - "SearchLogsResponse": { - "type": "object", - "required": [ - "lines", - "search_mode", - "total_scanned" - ], - "properties": { - "available_sources": { - "type": "array", - "items": { - "$ref": "#/components/schemas/LogSource" - }, - "description": "Distinct containers/nodes/services available in the queried scope, for\nthe filter dropdowns. Populated on the first page (no cursor)." - }, - "lines": { - "type": "array", - "items": { - "$ref": "#/components/schemas/LogSearchLine" - } - }, - "next_cursor": { - "type": [ - "string", - "null" - ] - }, - "search_mode": { - "$ref": "#/components/schemas/SearchMode" - }, - "total_scanned": { - "type": "integer", - "format": "int64", - "minimum": 0 - } - } - }, - "SearchMode": { - "type": "string", - "description": "Search execution mode", - "enum": [ - "index", - "archive" - ] - }, - "Seasonality": { - "type": "string", - "description": "Seasonality model for an anomaly baseline.", - "enum": [ - "none", - "hourly", - "daily", - "weekly" - ] - }, - "SecretResponse": { - "type": "object", - "required": [ - "id", - "name", - "secret_type", - "value", - "created_at", - "updated_at" - ], - "properties": { - "created_at": { - "type": "string" - }, - "description": { - "type": [ - "string", - "null" - ] - }, - "id": { - "type": "integer", - "format": "int32" - }, - "mount_path": { - "type": [ - "string", - "null" - ] - }, - "name": { - "type": "string" - }, - "secret_type": { - "type": "string" - }, - "updated_at": { - "type": "string" - }, - "value": { - "type": "string", - "description": "Always masked in responses" - } - } - }, - "SecurityConfig": { - "type": "object", - "description": "Security configuration for projects and environments\n\nThis configuration can be set at three levels:\n1. Global (in settings table) - applies to all projects\n2. Project level - overrides global settings for specific project\n3. Environment level - overrides project settings for specific environment\n\nThe inheritance chain: Environment > Project > Global", - "properties": { - "attackMode": { - "type": [ - "string", - "null" - ], - "description": "Attack mode configuration (future: \"off\", \"challenge\", \"block\")\nPlaceholder for DDoS protection, bot detection, etc." - }, - "challengeConfig": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/ChallengeConfig", - "description": "Challenge configuration (future: CAPTCHA, JS challenge, etc.)" - } - ] - }, - "enabled": { - "type": [ - "boolean", - "null" - ], - "description": "Enable/disable security features at this level\nIf None, inherits from parent level" - }, - "geoRestrictions": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/GeoRestrictionsConfig", - "description": "Geographic restrictions (future: country blocking, etc.)" - } - ] - }, - "headers": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/SecurityHeadersConfig", - "description": "Security headers configuration" - } - ] - }, - "passwordProtection": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/PasswordProtectionConfig", - "description": "Password protection: shows an HTML password form before allowing access" - } - ] - }, - "rateLimiting": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/RateLimitConfig", - "description": "Rate limiting configuration" - } - ] - } - } - }, - "SecurityHeadersConfig": { - "type": "object", - "description": "Security headers configuration (subset of global SecurityHeadersSettings)", - "properties": { - "contentSecurityPolicy": { - "type": [ - "string", - "null" - ], - "description": "Custom CSP (only used if preset is \"custom\")" - }, - "preset": { - "type": [ - "string", - "null" - ], - "description": "Use a preset: \"strict\", \"moderate\", \"permissive\", \"disabled\", \"custom\"" - }, - "referrerPolicy": { - "type": [ - "string", - "null" - ], - "description": "Referrer-Policy override" - }, - "strictTransportSecurity": { - "type": [ - "string", - "null" - ], - "description": "HSTS override" - }, - "xFrameOptions": { - "type": [ - "string", - "null" - ], - "description": "X-Frame-Options override" - } - } - }, - "SecurityHeadersSettings": { - "type": "object", - "properties": { - "content_security_policy": { - "type": [ - "string", - "null" - ], - "default": "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' data:; connect-src 'self'; frame-ancestors 'self'" - }, - "enabled": { - "type": "boolean", - "default": false - }, - "permissions_policy": { - "type": [ - "string", - "null" - ], - "default": "geolocation=(), microphone=(), camera=()" - }, - "preset": { - "type": "string", - "default": "moderate" - }, - "referrer_policy": { - "type": "string", - "default": "strict-origin-when-cross-origin" - }, - "strict_transport_security": { - "type": "string", - "default": "max-age=31536000; includeSubDomains" - }, - "x_content_type_options": { - "type": "string", - "default": "nosniff" - }, - "x_frame_options": { - "type": "string", - "default": "SAMEORIGIN" - }, - "x_xss_protection": { - "type": "string", - "default": "1; mode=block" - } - } - }, - "SendEmailRequestBody": { - "type": "object", - "required": [ - "from", - "to", - "subject" - ], - "properties": { - "bcc": { - "type": [ - "array", - "null" - ], - "items": { - "type": "string" - }, - "description": "BCC recipients" - }, - "cc": { - "type": [ - "array", - "null" - ], - "items": { - "type": "string" - }, - "description": "CC recipients" - }, - "from": { - "type": "string", - "description": "Sender email address (domain will be auto-extracted for lookup)", - "example": "hello@updates.example.com" - }, - "from_name": { - "type": [ - "string", - "null" - ], - "description": "Sender display name", - "example": "My App" - }, - "headers": { - "type": [ - "object", - "null" - ], - "description": "Custom headers", - "additionalProperties": { - "type": "string" - }, - "propertyNames": { - "type": "string" - } - }, - "html": { - "type": [ - "string", - "null" - ], - "description": "HTML body content", - "example": "

Hello World

" - }, - "reply_to": { - "type": [ - "string", - "null" - ], - "description": "Reply-to address" - }, - "subject": { - "type": "string", - "description": "Email subject", - "example": "Welcome to our platform!" - }, - "tags": { - "type": [ - "array", - "null" - ], - "items": { - "type": "string" - }, - "description": "Tags for categorization", - "example": [ - "welcome", - "onboarding" - ] - }, - "text": { - "type": [ - "string", - "null" - ], - "description": "Plain text body content", - "example": "Hello World" - }, - "to": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Recipient email addresses", - "example": [ - "user@example.com" - ] - }, - "track_clicks": { - "type": [ - "boolean", - "null" - ], - "description": "Enable click tracking (link rewriting). Defaults to false." - }, - "track_opens": { - "type": [ - "boolean", - "null" - ], - "description": "Enable open tracking (tracking pixel injection). Defaults to false." - } - } - }, - "SendEmailResponseBody": { - "type": "object", - "required": [ - "id", - "status" - ], - "properties": { - "id": { - "type": "string", - "description": "Email ID", - "example": "550e8400-e29b-41d4-a716-446655440000" - }, - "provider_message_id": { - "type": [ - "string", - "null" - ], - "description": "Provider message ID" - }, - "status": { - "type": "string", - "description": "Email status", - "example": "sent" - } - } - }, - "SendMessageRequest": { - "type": "object", - "required": [ - "content" - ], - "properties": { - "content": { - "type": "string" - }, - "page_context": { - "type": [ - "string", - "null" - ], - "description": "Optional, client-supplied description of the page/entity the user is\ncurrently viewing (e.g. a trace in a project). Injected into the model's\nview of this turn only \u2014 never stored or shown in history. Capped server\nside; oversized values are ignored rather than rejected." - } - } - }, - "SensitiveConfigValueResponse": { - "type": "object", - "required": [ - "value" - ], - "properties": { - "value": { - "type": "string" - } - } - }, - "SensitiveMcpConfigValueResponse": { - "type": "object", - "required": [ - "value" - ], - "properties": { - "value": { - "type": "string" - } - } - }, - "SensitiveValueResponse": { - "type": "object", - "required": [ - "value" - ], - "properties": { - "value": { - "type": "string" - } - } - }, - "SentryChunkUploadResponse": { - "type": "object", - "required": [ - "url", - "chunkSize", - "chunksPerRequest", - "maxFileSize", - "maxRequestSize", - "concurrency", - "hashAlgorithm", - "compression", - "accept" - ], - "properties": { - "accept": { - "type": "array", - "items": { - "type": "string" - } - }, - "chunkSize": { - "type": "integer", - "format": "int64", - "minimum": 0 - }, - "chunksPerRequest": { - "type": "integer", - "format": "int32", - "minimum": 0 - }, - "compression": { - "type": "array", - "items": { - "type": "string" - } - }, - "concurrency": { - "type": "integer", - "format": "int32", - "minimum": 0 - }, - "hashAlgorithm": { - "type": "string" - }, - "maxFileSize": { - "type": "integer", - "format": "int64", - "minimum": 0 - }, - "maxRequestSize": { - "type": "integer", - "format": "int64", - "minimum": 0 - }, - "url": { - "type": "string" - } - } - }, - "SentryCreateReleaseRequest": { - "type": "object", - "required": [ - "version" - ], - "properties": { - "projects": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Project slugs this release belongs to" - }, - "version": { - "type": "string", - "description": "Release version identifier" - } - } - }, - "SentryEventRequest": { - "type": "object", - "properties": { - "event_id": { - "type": [ - "string", - "null" - ] - }, - "message": { - "type": [ - "string", - "null" - ] - }, - "platform": { - "type": [ - "string", - "null" - ] - }, - "timestamp": { - "type": [ - "string", - "null" - ] - } - } - }, - "SentryEventResponse": { - "type": "object", - "required": [ - "id" - ], - "properties": { - "id": { - "type": "string" - } - } - }, - "SentryReleaseFileResponse": { - "type": "object", - "required": [ - "id", - "name", - "headers", - "size", - "sha1", - "dateCreated" - ], - "properties": { - "dateCreated": { - "type": "string" - }, - "dist": { - "type": [ - "string", - "null" - ] - }, - "headers": {}, - "id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "sha1": { - "type": "string" - }, - "size": { - "type": "integer", - "format": "int64" - } - } - }, - "SentryReleaseProjectRef": { - "type": "object", - "required": [ - "name", - "slug" - ], - "properties": { - "name": { - "type": "string" - }, - "slug": { - "type": "string" - } - } - }, - "SentryReleaseResponse": { - "type": "object", - "required": [ - "version", - "dateCreated", - "shortVersion", - "projects" - ], - "properties": { - "dateCreated": { - "type": "string" - }, - "dateReleased": { - "type": [ - "string", - "null" - ] - }, - "projects": { - "type": "array", - "items": { - "$ref": "#/components/schemas/SentryReleaseProjectRef" - } - }, - "shortVersion": { - "type": "string" - }, - "version": { - "type": "string" - } - } - }, - "SeriesStateEntry": { - "type": "object", - "description": "One series' persisted state snapshot for a dynamic rule (ADR-026 follow-up):\nthe state after the latest tick, the value evaluated this tick, and the open\nalarm id (when firing). Serialized into the `series_states` jsonb column keyed\nby the human-readable [`series_label`]; the alert response decodes it back.", - "required": [ - "state", - "value" - ], - "properties": { - "alarm_id": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "The open alarm's id when the series is firing; `null` when ok." - }, - "state": { - "type": "string", - "description": "`firing` or `ok` for this series after the latest tick." - }, - "value": { - "type": "number", - "format": "double", - "description": "The value the rule evaluated for this series this tick." - } - } - }, - "ServiceAccessInfo": { - "type": "object", - "description": "Response containing information about how the service is being accessed", - "required": [ - "access_mode", - "can_create_domains" - ], - "properties": { - "access_mode": { - "type": "string", - "description": "Mode of access: \"local\", \"direct\", \"nat\", or \"cloudflare_tunnel\"" - }, - "can_create_domains": { - "type": "boolean", - "description": "Whether domain creation is allowed in this mode" - }, - "domain_creation_error": { - "type": [ - "string", - "null" - ], - "description": "Error message if domain creation is not allowed" - }, - "private_ip": { - "type": [ - "string", - "null" - ], - "description": "Server's private/local IP address (always returned if available)" - }, - "public_ip": { - "type": [ - "string", - "null" - ], - "description": "Server's public IP address (always returned if available)" - } - } - }, - "ServiceAction": { - "type": "string", - "description": "What to do with a service during migration", - "enum": [ - "create", - "link-external", - "skip" - ] - }, - "ServiceAlertRuleResponse": { - "type": "object", - "description": "Wire representation of a monitoring alert rule.\n\nRegistered under a domain-prefixed OpenAPI schema name to avoid colliding\nwith `temps-error-tracking`'s unrelated `AlertRuleResponse` (utoipa keys\nschemas by their bare struct name, so without `as = ...` the last crate to\nregister would silently shadow this one in the merged spec / generated SDK).", - "required": [ - "id", - "name", - "metric_name", - "threshold", - "comparator", - "severity", - "for_duration_secs", - "enabled" - ], - "properties": { - "comparator": { - "type": "string" - }, - "deployment_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "enabled": { - "type": "boolean" - }, - "for_duration_secs": { - "type": "integer", - "format": "int32" - }, - "id": { - "type": "integer", - "format": "int32" - }, - "metric_name": { - "type": "string" - }, - "name": { - "type": "string" - }, - "service_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "severity": { - "type": "string" - }, - "silenced_until": { - "type": [ - "string", - "null" - ] - }, - "threshold": { - "type": "number", - "format": "double" - } - } - }, - "ServiceBackupEntryResponse": { - "type": "object", - "description": "A single backup entry in the per-service backup list.", - "required": [ - "id", - "backup_id", - "name", - "state", - "backup_type", - "started_at", - "s3_location", - "compression_type", - "s3_source_id", - "s3_source_name", - "external_service_backup_id" - ], - "properties": { - "backup_id": { - "type": "string", - "description": "UUID string assigned at backup creation time." - }, - "backup_type": { - "type": "string", - "description": "Backup variant (e.g. \"full\", \"incremental\")." - }, - "compression_type": { - "type": "string", - "description": "Compression algorithm used (e.g. \"gzip\")." - }, - "error_message": { - "type": [ - "string", - "null" - ], - "description": "Engine-reported error message, populated when `state = \"failed\"`." - }, - "external_service_backup_id": { - "type": "integer", - "format": "int32", - "description": "Row ID from `external_service_backups`." - }, - "finished_at": { - "type": [ - "string", - "null" - ], - "description": "ISO 8601 timestamp when the backup finished, if known.", - "example": "2025-01-15T14:35:00Z" - }, - "id": { - "type": "integer", - "format": "int32", - "description": "Row ID from the `backups` table." - }, - "name": { - "type": "string", - "description": "Human-friendly display name." - }, - "s3_location": { - "type": "string", - "description": "Object key or `s3://` URL for the backup data." - }, - "s3_source_id": { - "type": "integer", - "format": "int32", - "description": "FK to `s3_sources.id`." - }, - "s3_source_name": { - "type": "string", - "description": "Human-readable name of the S3 source." - }, - "size_bytes": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "description": "Size of the backup in bytes, if available." - }, - "started_at": { - "type": "string", - "description": "ISO 8601 timestamp when the backup started.", - "example": "2025-01-15T14:30:00Z" - }, - "state": { - "type": "string", - "description": "Current state: \"completed\", \"running\", \"failed\"." - } - } - }, - "ServiceBackupListResponse": { - "type": "object", - "description": "Paginated list of backups for a specific external service.\n\nReturned by `GET /backups/external-services/{service_id}/backups`.", - "required": [ - "backups", - "total", - "page", - "page_size" - ], - "properties": { - "backups": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ServiceBackupEntryResponse" - }, - "description": "Backups belonging to this service, newest first." - }, - "page": { - "type": "integer", - "format": "int64", - "description": "Current page (1-based)." - }, - "page_size": { - "type": "integer", - "format": "int64", - "description": "Number of items per page." - }, - "total": { - "type": "integer", - "format": "int64", - "description": "Total number of backups for this service across all pages." - } - } - }, - "ServiceCreateAlertRuleRequest": { - "type": "object", - "description": "Request body for creating an alert rule on an external service.\n\nDomain-prefixed schema name \u2014 see [`AlertRuleResponse`] for why.", - "required": [ - "name", - "metric_name", - "threshold", - "comparator", - "severity" - ], - "properties": { - "comparator": { - "type": "string", - "description": "One of `>`, `<`, `>=`, `<=`." - }, - "enabled": { - "type": "boolean" - }, - "for_duration_secs": { - "type": "integer", - "format": "int32", - "description": "Seconds the breach must persist before the alarm fires (0 = immediate)." - }, - "metric_name": { - "type": "string" - }, - "name": { - "type": "string" - }, - "severity": { - "type": "string", - "description": "`\"warning\"` or `\"critical\"`." - }, - "threshold": { - "type": "number", - "format": "double" - } - } - }, - "ServiceHealthResponse": { - "type": "object", - "required": [ - "service_id", - "consecutive_failures", - "recent_checks" - ], - "properties": { - "consecutive_failures": { - "type": "integer", - "format": "int32", - "description": "Consecutive failed probes. Alert fires at 3." - }, - "last_checked_at": { - "type": [ - "string", - "null" - ] - }, - "last_error": { - "type": [ - "string", - "null" - ] - }, - "recent_checks": { - "type": "array", - "items": { - "$ref": "#/components/schemas/HealthCheckEntryResponse" - }, - "description": "Most recent checks, newest-first (capped at `limit`)." - }, - "response_time_ms": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "service_id": { - "type": "integer", - "format": "int32" - }, - "status": { - "type": [ - "string", - "null" - ], - "description": "Current health. `null` if the service has not been probed yet.", - "example": "operational" - }, - "uptime_24h_percent": { - "type": [ - "number", - "null" - ], - "format": "double", - "description": "Uptime percentage over the last 24 hours (0.0 \u2014 100.0).\n`null` when there is not enough history." - } - } - }, - "ServiceHealthStatusBatchResponse": { - "type": "object", - "required": [ - "statuses" - ], - "properties": { - "statuses": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ServiceHealthStatusEntryResponse" - } - } - } - }, - "ServiceHealthStatusEntryResponse": { - "type": "object", - "required": [ - "service_id", - "consecutive_failures" - ], - "properties": { - "consecutive_failures": { - "type": "integer", - "format": "int32" - }, - "last_checked_at": { - "type": [ - "string", - "null" - ] - }, - "service_id": { - "type": "integer", - "format": "int32" - }, - "status": { - "type": [ - "string", - "null" - ], - "description": "\"operational\" | \"degraded\" | \"down\". `null` when the service has not\nbeen probed yet.", - "example": "operational" - } - } - }, - "ServiceMemberInfo": { - "type": "object", - "description": "Public info about a cluster member.", - "required": [ - "id", - "role", - "container_name", - "status", - "ordinal" - ], - "properties": { - "compute_ip": { - "type": [ - "string", - "null" - ], - "description": "Container's IP on the `temps-overlay` multi-host network. Populated\nby the lifecycle hook (ADR-011 Phase 3); `None` on single-host\nclusters where the overlay isn't attached." - }, - "container_name": { - "type": "string" - }, - "hostname": { - "type": [ - "string", - "null" - ] - }, - "id": { - "type": "integer", - "format": "int32" - }, - "live_state": { - "type": [ - "string", - "null" - ], - "description": "Live FSM state from the pg_auto_failover monitor (`primary`,\n`secondary`, `catchingup`, `report_lsn`, \u2026). `None` when the\nmonitor is unreachable, the service is not a cluster, or the row\nis the monitor itself.\n\n**The UI must render the role badge from this field**, falling\nback to `role` only when `live_state` is null. `role` is now\nconfig-only (`monitor` or `replica`); flipping the badge to\n\"primary\" when the monitor elects a new one used to require a\nreconciler that lagged ~5s behind real failovers \u2014 and during\nthat window the UI showed two primaries. `live_state` is read\ndirectly from the monitor on every list, so it can never lag." - }, - "node_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "ordinal": { - "type": "integer", - "format": "int32" - }, - "port": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "provisioning_error": { - "type": [ - "string", - "null" - ], - "description": "Most recent provisioning failure message, when `status='failed'`.\nSet by the background task so the UI can show *why* the new\nreplica didn't come up." - }, - "provisioning_step": { - "type": [ - "string", - "null" - ], - "description": "Last-attempted phase of the async `add_cluster_member` background\ntask (e.g. `validating`, `provisioning_container`, `done`,\n`failed`). `None` for members not created through that flow \u2014\nthe UI falls back to the `status` column for those." - }, - "role": { - "type": "string" - }, - "status": { - "type": "string" - } - } - }, - "ServiceParameter": { - "type": "object", - "required": [ - "name", - "required", - "encrypted", - "description" - ], - "properties": { - "choices": { - "type": [ - "array", - "null" - ], - "items": { - "type": "string" - } - }, - "default_value": { - "type": [ - "string", - "null" - ] - }, - "description": { - "type": "string" - }, - "encrypted": { - "type": "boolean" - }, - "name": { - "type": "string" - }, - "required": { - "type": "boolean" - }, - "validation_pattern": { - "type": [ - "string", - "null" - ] - } - } - }, - "ServicePlan": { - "type": "object", - "description": "Plan for migrating a single service (database, cache, etc.)", - "required": [ - "name", - "service_type", - "action", - "action_description" - ], - "properties": { - "action": { - "$ref": "#/components/schemas/ServiceAction", - "description": "What to do with this service" - }, - "action_description": { - "type": "string", - "description": "Human-readable explanation of what this action means" - }, - "data_implications": { - "type": "array", - "items": { - "$ref": "#/components/schemas/DataImplication" - }, - "description": "Data implications specific to this service" - }, - "env_var_mappings": { - "type": "object", - "description": "Environment variable key mappings: source_key -> temps_key\n\nFor example, Vercel's `POSTGRES_URL` might map to Temps' `DATABASE_URL`.\nBoth keys will be set during migration so the app works with either.", - "additionalProperties": { - "type": "string" - }, - "propertyNames": { - "type": "string" - } - }, - "name": { - "type": "string", - "description": "Human-readable service name" - }, - "parameters": { - "type": "object", - "description": "Parameters for creating the service in Temps", - "additionalProperties": {}, - "propertyNames": { - "type": "string" - } - }, - "service_type": { - "type": "string", - "description": "Service type (maps to temps-providers ServiceType)" - }, - "version": { - "type": [ - "string", - "null" - ], - "description": "Service version to create (e.g., \"16\" for Postgres 16)" - } - } - }, - "ServiceResourceLimits": { - "type": "object", - "description": "Optional cgroup resource limits applied to a service container.\n\nAll fields are `Option`: `None` means \"no limit\" (the kernel default),\nmatching Docker's behavior when the corresponding `HostConfig` field is\nleft at zero. Operators opt in to limits explicitly through the\n`PATCH /external-services/{id}/resources` endpoint or by writing the\n`resources` block into `ServiceConfig::parameters` at create time.\n\nThese map directly onto bollard fields:\n- `memory_mb` \u2192 `HostConfig.memory` (bytes)\n- `memory_swap_mb`\u2192 `HostConfig.memory_swap` (bytes; \u2265 memory)\n- `nano_cpus` \u2192 `HostConfig.nano_cpus` (1e9 = 1 full CPU)\n- `cpu_shares` \u2192 `HostConfig.cpu_shares` (relative weight, default 1024)\n- `shm_size_mb` \u2192 `HostConfig.shm_size` (bytes; default 64 MiB)\n\nIMPORTANT: enabling hard memory limits causes the kernel OOM killer to\nterminate the container when the working set exceeds the limit. The\ncontainer will restart (RestartPolicy::ALWAYS) but in-flight queries\nfail. Surface this clearly in any UI that lets users set limits.", - "properties": { - "cpu_shares": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "description": "Relative CPU weight (default 1024). Only used when `nano_cpus` is None." - }, - "memory_mb": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "description": "Hard memory limit in MiB. None = unlimited." - }, - "memory_swap_mb": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "description": "Memory + swap limit in MiB. None = unlimited.\nMUST be >= memory_mb when both are set; Docker rejects the request otherwise.\nSet equal to `memory_mb` to disable swap entirely." - }, - "nano_cpus": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "description": "CPU quota in nano-cpus. 1_000_000_000 = 1 full CPU core. None = unlimited." - }, - "shm_size_mb": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "description": "Shared memory (/dev/shm) size in MiB. None = Docker default (64 MiB).\nMaps to HostConfig.shm_size (bytes). PostgreSQL uses /dev/shm for parallel\nquery workers and large work_mem; the 64 MiB default causes \"could not\nresize shared memory segment ... No space left on device\" under load.\nNOTE: shm_size is fixed at container-create time \u2014 Docker's live update\nAPI cannot change it, so changing this value recreates the container." - } - } - }, - "ServiceRuntimeReport": { - "type": "object", - "description": "Aggregate runtime info for an external service. For standalone services,\n`members` has exactly one entry. For clusters, one entry per member.", - "required": [ - "service_id", - "topology", - "members" - ], - "properties": { - "members": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ContainerRuntimeInfo" - } - }, - "service_id": { - "type": "integer", - "format": "int32" - }, - "topology": { - "type": "string" - } - } - }, - "ServiceStatsReport": { - "type": "object", - "required": [ - "service_id", - "topology", - "members" - ], - "properties": { - "members": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ContainerStatsSample" - } - }, - "service_id": { - "type": "integer", - "format": "int32" - }, - "topology": { - "type": "string" - } - } - }, - "ServiceTypeInfo": { - "type": "object", - "required": [ - "service_type", - "parameters" - ], - "properties": { - "parameters": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ServiceParameter" - }, - "example": "[{\"name\": \"host\", \"required\": true, \"encrypted\": false, \"description\": \"Database host\"}]" - }, - "service_type": { - "$ref": "#/components/schemas/ServiceTypeRoute" - } - } - }, - "ServiceTypeRoute": { - "type": "string", - "enum": [ - "mariadb", - "mongodb", - "postgres", - "redis", - "s3", - "kv", - "blob", - "rustfs", - "minio" - ] - }, - "ServiceUpdateAlertRuleRequest": { - "type": "object", - "description": "Request body for updating an existing alert rule.\n\nDomain-prefixed schema name \u2014 see [`AlertRuleResponse`] for why.", - "properties": { - "comparator": { - "type": [ - "string", - "null" - ] - }, - "enabled": { - "type": [ - "boolean", - "null" - ] - }, - "for_duration_secs": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "metric_name": { - "type": [ - "string", - "null" - ] - }, - "name": { - "type": [ - "string", - "null" - ] - }, - "severity": { - "type": [ - "string", - "null" - ] - }, - "threshold": { - "type": [ - "number", - "null" - ], - "format": "double" - } - } - }, - "SesCredentialsRequest": { - "type": "object", - "required": [ - "access_key_id", - "secret_access_key" - ], - "properties": { - "access_key_id": { - "type": "string", - "example": "AKIAIOSFODNN7EXAMPLE" - }, - "secret_access_key": { - "type": "string", - "example": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY" - } - } - }, - "SessionDetails": { - "type": "object", - "required": [ - "session_id", - "visitor_id", - "started_at", - "duration_seconds", - "is_bounced", - "is_engaged", - "page_views" - ], - "properties": { - "duration_seconds": { - "type": "integer", - "format": "int64" - }, - "ended_at": { - "type": [ - "string", - "null" - ], - "format": "date-time", - "example": "2024-01-01T00:00:00" - }, - "entry_path": { - "type": [ - "string", - "null" - ] - }, - "exit_path": { - "type": [ - "string", - "null" - ] - }, - "is_bounced": { - "type": "boolean" - }, - "is_engaged": { - "type": "boolean" - }, - "page_views": { - "type": "integer", - "format": "int64" - }, - "referrer": { - "type": [ - "string", - "null" - ] - }, - "session_id": { - "type": "integer", - "format": "int32" - }, - "started_at": { - "type": "string", - "format": "date-time", - "example": "2024-01-01T00:00:00" - }, - "visitor_id": { - "type": "string" - } - } - }, - "SessionDetailsQuery": { - "type": "object", - "required": [ - "project_id" - ], - "properties": { - "environment_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "project_id": { - "type": "integer", - "format": "int32" - } - } - }, - "SessionEvent": { - "type": "object", - "required": [ - "id", - "timestamp" - ], - "properties": { - "event_data": {}, - "event_name": { - "type": [ - "string", - "null" - ] - }, - "event_type": { - "type": [ - "string", - "null" - ] - }, - "id": { - "type": "integer", - "format": "int32" - }, - "page_title": { - "type": [ - "string", - "null" - ] - }, - "page_url": { - "type": [ - "string", - "null" - ] - }, - "timestamp": { - "type": "string" - } - } - }, - "SessionEventDto": { - "type": "object", - "required": [ - "id", - "session_id", - "data", - "timestamp" - ], - "properties": { - "data": {}, - "event_type": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "id": { - "type": "integer", - "format": "int32" - }, - "session_id": { - "type": "integer", - "format": "int32" - }, - "timestamp": { - "type": "integer", - "format": "int64" - } - } - }, - "SessionEventsQuery": { - "type": "object", - "required": [ - "project_id" - ], - "properties": { - "environment_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "project_id": { - "type": "integer", - "format": "int32" - } - } - }, - "SessionEventsResponse": { - "type": "object", - "required": [ - "session_id", - "events", - "total_count", - "offset", - "limit" - ], - "properties": { - "events": { - "type": "array", - "items": { - "$ref": "#/components/schemas/SessionEvent" - } - }, - "limit": { - "type": "integer", - "format": "int32" - }, - "offset": { - "type": "integer", - "format": "int32" - }, - "session_id": { - "type": "integer", - "format": "int32" - }, - "total_count": { - "type": "integer", - "format": "int64" - } - } - }, - "SessionLogsQuery": { - "type": "object", - "required": [ - "project_id" - ], - "properties": { - "end_date": { - "type": [ - "string", - "null" - ], - "format": "date-time" - }, - "environment_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "limit": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "offset": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "project_id": { - "type": "integer", - "format": "int32" - }, - "sort_order": { - "type": [ - "string", - "null" - ] - }, - "start_date": { - "type": [ - "string", - "null" - ], - "format": "date-time" - }, - "visitor_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - } - } - }, - "SessionLogsResponse": { - "type": "object", - "required": [ - "session_id", - "logs", - "total_count", - "offset", - "limit" - ], - "properties": { - "limit": { - "type": "integer", - "format": "int32" - }, - "logs": { - "type": "array", - "items": { - "$ref": "#/components/schemas/SessionRequestLog" - } - }, - "offset": { - "type": "integer", - "format": "int32" - }, - "session_id": { - "type": "integer", - "format": "int32" - }, - "total_count": { - "type": "integer", - "format": "int64" - } - } - }, - "SessionReplayEventsRequest": { - "type": "object", - "required": [ - "sessionId", - "events" - ], - "properties": { - "events": { - "type": "string" - }, - "sessionId": { - "type": "string" - } - } - }, - "SessionReplayInfoDto": { - "type": "object", - "required": [ - "id", - "visitor_id" - ], - "properties": { - "created_at": { - "type": [ - "string", - "null" - ] - }, - "duration": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "id": { - "type": "string" - }, - "language": { - "type": [ - "string", - "null" - ] - }, - "screen_height": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "screen_width": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "timezone": { - "type": [ - "string", - "null" - ] - }, - "url": { - "type": [ - "string", - "null" - ] - }, - "user_agent": { - "type": [ - "string", - "null" - ] - }, - "viewport_height": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "viewport_width": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "visitor_id": { - "type": "integer", - "format": "int32" - } - } - }, - "SessionReplayInitRequest": { - "type": "object", - "required": [ - "sessionId" - ], - "properties": { - "colorDepth": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "minimum": 0 - }, - "language": { - "type": [ - "string", - "null" - ] - }, - "screenHeight": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "minimum": 0 - }, - "screenWidth": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "minimum": 0 - }, - "sessionId": { - "type": "string" - }, - "timestamp": { - "type": [ - "string", - "null" - ] - }, - "timezone": { - "type": [ - "string", - "null" - ] - }, - "url": { - "type": [ - "string", - "null" - ] - }, - "userAgent": { - "type": [ - "string", - "null" - ] - }, - "viewportHeight": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "minimum": 0 - }, - "viewportWidth": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "minimum": 0 - } - } - }, - "SessionReplayInitResponse": { - "type": "object", - "required": [ - "session_id", - "message" - ], - "properties": { - "message": { - "type": "string" - }, - "session_id": { - "type": "string" - } - } - }, - "SessionReplayWithEventsDto": { - "type": "object", - "required": [ - "session", - "events" - ], - "properties": { - "events": { - "type": "array", - "items": { - "$ref": "#/components/schemas/SessionEventDto" - } - }, - "session": { - "$ref": "#/components/schemas/SessionReplayWithVisitorDto" - } - } - }, - "SessionReplayWithVisitorDto": { - "type": "object", - "required": [ - "id", - "session_replay_id", - "visitor_id", - "visitor_uuid", - "visitor_project_id", - "visitor_environment_id", - "visitor_first_seen", - "visitor_last_seen", - "visitor_is_crawler" - ], - "properties": { - "browser": { - "type": [ - "string", - "null" - ] - }, - "browser_version": { - "type": [ - "string", - "null" - ] - }, - "created_at": { - "type": [ - "string", - "null" - ] - }, - "device_type": { - "type": [ - "string", - "null" - ] - }, - "duration": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "id": { - "type": "integer", - "format": "int32" - }, - "language": { - "type": [ - "string", - "null" - ] - }, - "operating_system": { - "type": [ - "string", - "null" - ] - }, - "operating_system_version": { - "type": [ - "string", - "null" - ] - }, - "screen_height": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "screen_width": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "session_replay_id": { - "type": "string" - }, - "timezone": { - "type": [ - "string", - "null" - ] - }, - "url": { - "type": [ - "string", - "null" - ] - }, - "user_agent": { - "type": [ - "string", - "null" - ] - }, - "viewport_height": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "viewport_width": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "visitor_city": { - "type": [ - "string", - "null" - ] - }, - "visitor_country": { - "type": [ - "string", - "null" - ] - }, - "visitor_country_code": { - "type": [ - "string", - "null" - ] - }, - "visitor_crawler_name": { - "type": [ - "string", - "null" - ] - }, - "visitor_custom_data": {}, - "visitor_environment_id": { - "type": "integer", - "format": "int32" - }, - "visitor_first_seen": { - "type": "string" - }, - "visitor_id": { - "type": "integer", - "format": "int32" - }, - "visitor_is_crawler": { - "type": "boolean" - }, - "visitor_last_seen": { - "type": "string" - }, - "visitor_project_id": { - "type": "integer", - "format": "int32" - }, - "visitor_region": { - "type": [ - "string", - "null" - ] - }, - "visitor_uuid": { - "type": "string" - } - } - }, - "SessionRequestLog": { - "type": "object", - "required": [ - "id", - "method", - "path", - "status_code", - "created_at" - ], - "properties": { - "created_at": { - "type": "string", - "format": "date-time", - "example": "2024-01-01T00:00:00" - }, - "id": { - "type": "integer", - "format": "int32" - }, - "method": { - "type": "string" - }, - "path": { - "type": "string" - }, - "referrer": { - "type": [ - "string", - "null" - ] - }, - "request_headers": { - "type": [ - "string", - "null" - ] - }, - "response_headers": { - "type": [ - "string", - "null" - ] - }, - "response_time_ms": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "status_code": { - "type": "integer", - "format": "int32" - }, - "user_agent": { - "type": [ - "string", - "null" - ] - } - } - }, - "SessionSummary": { - "type": "object", - "required": [ - "session_id", - "started_at", - "duration_seconds", - "page_views", - "events_count", - "requests_count", - "is_bounced", - "is_engaged" - ], - "properties": { - "duration_seconds": { - "type": "integer", - "format": "int64" - }, - "ended_at": { - "type": [ - "string", - "null" - ], - "format": "date-time", - "example": "2024-01-01T00:00:00" - }, - "entry_path": { - "type": [ - "string", - "null" - ] - }, - "events_count": { - "type": "integer", - "format": "int64" - }, - "exit_path": { - "type": [ - "string", - "null" - ] - }, - "is_bounced": { - "type": "boolean" - }, - "is_engaged": { - "type": "boolean" - }, - "page_views": { - "type": "integer", - "format": "int64" - }, - "referrer": { - "type": [ - "string", - "null" - ] - }, - "requests_count": { - "type": "integer", - "format": "int64" - }, - "session_id": { - "type": "integer", - "format": "int32" - }, - "started_at": { - "type": "string", - "format": "date-time", - "example": "2024-01-01T00:00:00" - } - } - }, - "SetFlagEnvironmentRequest": { - "type": "object", - "properties": { - "enabled": { - "type": [ - "boolean", - "null" - ], - "description": "The kill switch. `false` makes the flag serve its default regardless of\nany override \u2014 and, once targeting exists, regardless of any rule." - }, - "value": { - "description": "Tri-state: absent leaves the override, `null` clears it (inherit the\nflag default), anything else sets it. Must match `value_type`." - } - } - }, - "SetPreviewPasswordBody": { - "type": "object", - "required": [ - "password" - ], - "properties": { - "password": { - "type": "string", - "description": "Plaintext password to protect the sandbox's preview URLs. Hashed\nserver-side with argon2id \u2014 we never persist or echo this back.\nMust be between 8 and 256 characters." - } - } - }, - "SetPreviewPasswordResponse": { - "type": "object", - "required": [ - "preview_password_hint" - ], - "properties": { - "preview_password_hint": { - "type": "string", - "description": "Last 4 chars of the password we just stored. Surface in the UI so\nusers can confirm which password is live without re-entering it." - } - } - }, - "SetRequest": { - "type": "object", - "description": "Request to set a value", - "required": [ - "key", - "value" - ], - "properties": { - "ex": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "description": "Expire in seconds", - "example": 3600 - }, - "key": { - "type": "string", - "description": "The key to set", - "example": "user:123" - }, - "nx": { - "type": "boolean", - "description": "Only set if key does not exist" - }, - "project_id": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Project ID (required for API key/session auth, optional for deployment tokens)", - "example": 1 - }, - "px": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "description": "Expire in milliseconds" - }, - "value": { - "description": "The value to store (can be any JSON value)" - }, - "xx": { - "type": "boolean", - "description": "Only set if key exists" - } - } - }, - "SetResponse": { - "type": "object", - "description": "Response for set operation", - "required": [ - "result" - ], - "properties": { - "result": { - "type": "string", - "description": "Always \"OK\" on success", - "example": "OK" - } - } - }, - "SettingsUpdateResponse": { - "type": "object", - "description": "Response for successful settings update", - "required": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - }, - "SetupDnsChallengeRequest": { - "type": "object", - "description": "Request to setup DNS challenge records using a configured DNS provider", - "required": [ - "dns_provider_id" - ], - "properties": { - "dns_provider_id": { - "type": "integer", - "format": "int32", - "description": "The ID of the DNS provider to use for creating the TXT records" - } - } - }, - "SetupDnsChallengeResponse": { - "type": "object", - "description": "Response from DNS challenge setup operation", - "required": [ - "success", - "records_created", - "total_records", - "results", - "message" - ], - "properties": { - "message": { - "type": "string", - "description": "Human-readable summary message" - }, - "records_created": { - "type": "integer", - "format": "int32", - "description": "Number of TXT records that were successfully created", - "minimum": 0 - }, - "results": { - "type": "array", - "items": { - "$ref": "#/components/schemas/DnsChallengeRecordResult" - }, - "description": "Results for each individual TXT record" - }, - "success": { - "type": "boolean", - "description": "Overall success status (true if all records were created)" - }, - "total_records": { - "type": "integer", - "format": "int32", - "description": "Total number of TXT records required for the challenge", - "minimum": 0 - } - } - }, - "SetupDnsRequest": { - "type": "object", - "description": "Request to setup DNS records using a configured DNS provider", - "required": [ - "dns_provider_id" - ], - "properties": { - "dns_provider_id": { - "type": "integer", - "format": "int32", - "description": "The ID of the DNS provider to use for creating records" - } - } - }, - "SetupDnsResponse": { - "type": "object", - "description": "Response from DNS setup operation", - "required": [ - "success", - "records_created", - "total_records", - "results", - "message" - ], - "properties": { - "message": { - "type": "string", - "description": "Human-readable summary message" - }, - "records_created": { - "type": "integer", - "format": "int32", - "description": "Number of records that were successfully created", - "minimum": 0 - }, - "results": { - "type": "array", - "items": { - "$ref": "#/components/schemas/DnsRecordSetupResult" - }, - "description": "Results for each individual record" - }, - "success": { - "type": "boolean", - "description": "Overall success status" - }, - "total_records": { - "type": "integer", - "format": "int32", - "description": "Total number of records attempted", - "minimum": 0 - } - } - }, - "SiblingRef": { - "type": "object", - "description": "A sibling project that shares the same `trace_id` and has opted in to\ncross-project trace sharing (`cross_project_trace_sharing = TRUE`).\n\nReturned by `CrossProjectTraceService::find_sibling_projects` and exposed\nby the Phase 1 `GET /otel/traces/cross-project/{trace_id}` endpoint.", - "required": [ - "project_id", - "project_name", - "project_slug", - "first_seen" - ], - "properties": { - "first_seen": { - "type": "string", - "format": "date-time" - }, - "project_id": { - "type": "integer", - "format": "int32" - }, - "project_name": { - "type": "string" - }, - "project_slug": { - "type": "string", - "description": "URL slug used to link into the sibling project's single-project trace view." - } - } - }, - "SkillDefinitionResponse": { - "type": "object", - "required": [ - "id", - "slug", - "name", - "content", - "has_archive", - "created_at", - "updated_at" - ], - "properties": { - "content": { - "type": "string" - }, - "created_at": { - "type": "string" - }, - "description": { - "type": [ - "string", - "null" - ] - }, - "has_archive": { - "type": "boolean" - }, - "id": { - "type": "integer", - "format": "int32" - }, - "name": { - "type": "string" - }, - "project_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "slug": { - "type": "string" - }, - "updated_at": { - "type": "string" - } - } - }, - "SlackConfig": { - "type": "object", - "required": [ - "webhook_url" - ], - "properties": { - "channel": { - "type": [ - "string", - "null" - ] - }, - "webhook_url": { - "type": "string" - } - } - }, - "SlowQueriesResponse": { - "type": "object", - "description": "Response envelope for the slow-queries list endpoint.", - "required": [ - "queries", - "page", - "page_size", - "total_count" - ], - "properties": { - "page": { - "type": "integer", - "format": "int32", - "description": "Current page number (1-based).", - "minimum": 0 - }, - "page_size": { - "type": "integer", - "format": "int32", - "description": "Number of rows per page used for this request.", - "minimum": 0 - }, - "queries": { - "type": "array", - "items": { - "$ref": "#/components/schemas/SlowQueryRow" - }, - "description": "Ordered list of query stats, slowest first by mean_exec_time_ms." - }, - "total_count": { - "type": "integer", - "format": "int64", - "description": "Total number of qualifying rows across all pages.", - "minimum": 0 - } - } - }, - "SlowQueryRow": { - "type": "object", - "description": "A single entry from `pg_stat_statements`, representing one normalized\nquery fingerprint and its aggregate execution stats.", - "required": [ - "query", - "database", - "calls", - "total_exec_time_ms", - "mean_exec_time_ms", - "rows" - ], - "properties": { - "cache_hit_ratio": { - "type": [ - "number", - "null" - ], - "format": "double", - "description": "Shared block cache hit ratio (0.0\u20131.0).\n`None` when total block accesses are zero (e.g. function-only queries)." - }, - "calls": { - "type": "integer", - "format": "int64", - "description": "Number of times this query was executed." - }, - "database": { - "type": "string", - "description": "Name of the database this query ran against. `(dropped database)`\nwhen the originating database no longer exists but\n`pg_stat_statements` still holds stats for it." - }, - "mean_exec_time_ms": { - "type": "number", - "format": "double", - "description": "Average wall-clock time per execution, in milliseconds." - }, - "query": { - "type": "string", - "description": "Normalized query text (parameter literals replaced with `$N`)." - }, - "rows": { - "type": "integer", - "format": "int64", - "description": "Total number of rows returned or affected." - }, - "total_exec_time_ms": { - "type": "number", - "format": "double", - "description": "Total wall-clock time spent executing this query, in milliseconds." - } - } - }, - "SmartFilter": { - "oneOf": [ - { - "type": "object", - "description": "Match specific page path", - "required": [ - "value", - "type" - ], - "properties": { - "type": { - "type": "string", - "enum": [ - "page_path" - ] - }, - "value": { - "type": "string", - "description": "Match specific page path" - } - } - }, - { - "type": "object", - "description": "Match specific hostname", - "required": [ - "value", - "type" - ], - "properties": { - "type": { - "type": "string", - "enum": [ - "hostname" - ] - }, - "value": { - "type": "string", - "description": "Match specific hostname" - } - } - }, - { - "type": "object", - "description": "Match UTM source", - "required": [ - "value", - "type" - ], - "properties": { - "type": { - "type": "string", - "enum": [ - "utm_source" - ] - }, - "value": { - "type": "string", - "description": "Match UTM source" - } - } - }, - { - "type": "object", - "description": "Match UTM campaign", - "required": [ - "value", - "type" - ], - "properties": { - "type": { - "type": "string", - "enum": [ - "utm_campaign" - ] - }, - "value": { - "type": "string", - "description": "Match UTM campaign" - } - } - }, - { - "type": "object", - "description": "Match UTM medium", - "required": [ - "value", - "type" - ], - "properties": { - "type": { - "type": "string", - "enum": [ - "utm_medium" - ] - }, - "value": { - "type": "string", - "description": "Match UTM medium" - } - } - }, - { - "type": "object", - "description": "Match referrer hostname", - "required": [ - "value", - "type" - ], - "properties": { - "type": { - "type": "string", - "enum": [ - "referrer_hostname" - ] - }, - "value": { - "type": "string", - "description": "Match referrer hostname" - } - } - }, - { - "type": "object", - "description": "Match specific channel (organic, paid, direct, referral, etc.)", - "required": [ - "value", - "type" - ], - "properties": { - "type": { - "type": "string", - "enum": [ - "channel" - ] - }, - "value": { - "type": "string", - "description": "Match specific channel (organic, paid, direct, referral, etc.)" - } - } - }, - { - "type": "object", - "description": "Match device type (mobile, desktop, tablet)", - "required": [ - "value", - "type" - ], - "properties": { - "type": { - "type": "string", - "enum": [ - "device_type" - ] - }, - "value": { - "type": "string", - "description": "Match device type (mobile, desktop, tablet)" - } - } - }, - { - "type": "object", - "description": "Match browser", - "required": [ - "value", - "type" - ], - "properties": { - "type": { - "type": "string", - "enum": [ - "browser" - ] - }, - "value": { - "type": "string", - "description": "Match browser" - } - } - }, - { - "type": "object", - "description": "Match operating system", - "required": [ - "value", - "type" - ], - "properties": { - "type": { - "type": "string", - "enum": [ - "operating_system" - ] - }, - "value": { - "type": "string", - "description": "Match operating system" - } - } - }, - { - "type": "object", - "description": "Match language", - "required": [ - "value", - "type" - ], - "properties": { - "type": { - "type": "string", - "enum": [ - "language" - ] - }, - "value": { - "type": "string", - "description": "Match language" - } - } - }, - { - "type": "object", - "description": "Match custom event_data by JSON path\nFormat: {\"path\": \"user.plan\", \"value\": \"premium\"}\nThis will match events where event_data->'user'->>'plan' = 'premium'", - "required": [ - "value", - "type" - ], - "properties": { - "type": { - "type": "string", - "enum": [ - "custom_data" - ] - }, - "value": { - "type": "object", - "description": "Match custom event_data by JSON path\nFormat: {\"path\": \"user.plan\", \"value\": \"premium\"}\nThis will match events where event_data->'user'->>'plan' = 'premium'", - "required": [ - "path", - "value" - ], - "properties": { - "path": { - "type": "string" - }, - "value": { - "type": "string" - } - } - } - } - } - ], - "description": "Smart filter presets for common funnel patterns" - }, - "SmokeTestResponse": { - "type": "object", - "required": [ - "passed", - "environment", - "cli_installed", - "cli_authenticated" - ], - "properties": { - "auth_info": { - "type": [ - "string", - "null" - ], - "description": "Auth email / method" - }, - "cli_authenticated": { - "type": "boolean", - "description": "Claude CLI authenticated?" - }, - "cli_installed": { - "type": "boolean", - "description": "Claude CLI installed?" - }, - "cli_version": { - "type": [ - "string", - "null" - ], - "description": "Claude CLI version" - }, - "detail": { - "type": [ - "string", - "null" - ], - "description": "Full output for debugging" - }, - "environment": { - "type": "string", - "description": "Where the test ran: \"host\" or \"sandbox\"" - }, - "passed": { - "type": "boolean", - "description": "Whether the smoke test passed" - }, - "setup_hint": { - "type": [ - "string", - "null" - ], - "description": "What the user needs to do if the test failed" - } - } - }, - "SmtpCredentialsRequest": { - "type": "object", - "description": "Generic SMTP credentials request body.\n\nWorks with any SMTP relay \u2014 AWS SES SMTP endpoints, Sendgrid, Mailgun,\nPostmark, or a self-hosted Postfix. Use this when you only have SMTP\ncredentials (i.e. you cannot create identities via the upstream API).", - "required": [ - "host", - "port" - ], - "properties": { - "accept_invalid_certs": { - "type": "boolean", - "description": "Accept self-signed certificates. Only safe for local testing." - }, - "encryption": { - "$ref": "#/components/schemas/SmtpEncryptionRoute", - "description": "TLS mode. Defaults to STARTTLS." - }, - "host": { - "type": "string", - "description": "SMTP host, e.g. `email-smtp.eu-west-1.amazonaws.com`.", - "example": "email-smtp.eu-west-1.amazonaws.com" - }, - "password": { - "type": [ - "string", - "null" - ], - "description": "SMTP password / API token. Required when `username` is set." - }, - "port": { - "type": "integer", - "format": "int32", - "description": "SMTP port (587 for STARTTLS, 465 for implicit TLS, 25/1025 for plain).", - "example": 587, - "minimum": 0 - }, - "username": { - "type": [ - "string", - "null" - ], - "description": "SMTP username. Leave empty for unauthenticated relays.", - "example": "AKIAIOSFODNN7EXAMPLE" - } - } - }, - "SmtpEncryptionRoute": { - "type": "string", - "description": "TLS mode for the SMTP relay.", - "enum": [ - "starttls", - "tls", - "none" - ] - }, - "SmtpResult": { - "type": "object", - "description": "SMTP validation result", - "required": [ - "can_connect_smtp", - "has_full_inbox", - "is_catch_all", - "is_deliverable", - "is_disabled" - ], - "properties": { - "can_connect_smtp": { - "type": "boolean", - "description": "Whether we could connect to the SMTP server" - }, - "error": { - "type": [ - "string", - "null" - ], - "description": "Error message if SMTP check failed" - }, - "has_full_inbox": { - "type": "boolean", - "description": "Whether the mailbox appears to have a full inbox" - }, - "is_catch_all": { - "type": "boolean", - "description": "Whether this is a catch-all domain" - }, - "is_deliverable": { - "type": "boolean", - "description": "Whether the email is deliverable" - }, - "is_disabled": { - "type": "boolean", - "description": "Whether the mailbox is disabled" - } - } - }, - "SourceBackupEntry": { - "type": "object", - "description": "Entry in the source backup index. Covers both DB-tracked backups\n(have a row in `backups`) and S3-scan discoveries (raw S3 objects with\nno DB row \u2014 used for disaster-recovery from another Temps instance).", - "required": [ - "id", - "backup_id", - "name", - "backup_type", - "created_at", - "location", - "metadata_location", - "source", - "state" - ], - "properties": { - "backup_id": { - "type": "string", - "description": "UUID identifier from the DB row. Empty for S3-scan entries.", - "example": "550e8400-e29b-41d4-a716-446655440000" - }, - "backup_type": { - "type": "string", - "description": "Backup variant as recorded by the backup pipeline (e.g. \"full\").", - "example": "full" - }, - "created_at": { - "type": "string", - "description": "When the backup was created. For S3-scan entries this is the\nobject's LastModified time.", - "example": "2024-01-15T14:30:00.123Z" - }, - "engine": { - "type": [ - "string", - "null" - ], - "description": "Engine that produced the backup (\"postgres\", \"redis\", \"mongodb\",\n\"s3\", \"rustfs\"). Used by the UI to mark engine-compat with the\ntarget service.", - "example": "postgres" - }, - "format": { - "type": [ - "string", - "null" - ], - "description": "Storage format: \"walg\" for continuous-archive (PITR-capable),\n\"pg_dump\" for point-in-time dumps, \"\" for non-postgres.", - "example": "walg" - }, - "id": { - "type": "integer", - "format": "int32", - "description": "DB row id. Zero for S3-scan entries that have no DB row.", - "example": 1 - }, - "location": { - "type": "string", - "description": "Raw S3 URL / key where the backup sits. For Postgres WAL-G backups\nthis starts with `s3://`; for pg_dump-style backups it's the\nrelative object key.", - "example": "s3://bucket/external_services/postgres/svc-name/walg" - }, - "metadata_location": { - "type": "string", - "description": "Sidecar metadata.json location, if any. Empty when none.", - "example": "" - }, - "name": { - "type": "string", - "description": "Human-friendly display name (\"postgres backup (svc-name)\" for DB\nrows, or a synthesized label derived from the S3 path for scans).", - "example": "postgres backup (postgres-n4ea)" - }, - "origin_service_name": { - "type": [ - "string", - "null" - ], - "description": "Name of the service that produced the backup. For S3-scan entries\nthis is parsed from the S3 path.", - "example": "postgres-n4ea" - }, - "size_bytes": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "description": "Size of the backup in bytes, if known.", - "example": 1024000 - }, - "source": { - "type": "string", - "description": "Provenance: \"db\" for rows in this Temps, \"s3_scan\" for objects\ndiscovered by the S3 bucket walk (e.g., backups made by another\nTemps instance).", - "example": "db" - }, - "state": { - "type": "string", - "description": "Observed state (\"completed\", \"running\", \"failed\") \u2014 DB only.\nEmpty string for S3-scan entries.", - "example": "completed" - } - } - }, - "SourceBackupIndexResponse": { - "type": "object", - "description": "Response type for source backup index", - "required": [ - "backups", - "last_updated" - ], - "properties": { - "backups": { - "type": "array", - "items": { - "$ref": "#/components/schemas/SourceBackupEntry" - }, - "description": "List of backups in the source" - }, - "last_updated": { - "type": "string", - "description": "When the index was last updated", - "example": "2024-01-15T14:30:00.123Z" - } - } - }, - "SourceBody": { - "oneOf": [ - { - "type": "object", - "required": [ - "url", - "type" - ], - "properties": { - "depth": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "minimum": 0 - }, - "git_connection_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "password": { - "type": [ - "string", - "null" - ] - }, - "revision": { - "type": [ - "string", - "null" - ] - }, - "type": { - "type": "string", - "enum": [ - "git" - ] - }, - "url": { - "type": "string" - }, - "username": { - "type": [ - "string", - "null" - ] - } - } - }, - { - "type": "object", - "required": [ - "url", - "type" - ], - "properties": { - "type": { - "type": "string", - "enum": [ - "tarball" - ] - }, - "url": { - "type": "string" - } - } - } - ], - "description": "Initial content to seed into the sandbox work dir. Mirrors the\n`@vercel/sandbox` `source` option. `type` is one of:\n- `git` \u2014 clone `url`; optionally check out `revision`\n- `tarball` \u2014 download `url` (must be tar or tar.gz) and extract\n\nFor private git repos, pass credentials one of two ways:\n1. **Inline (SDK-compatible):** `username` + `password`. GitHub\n tokens use `username: \"x-access-token\"`.\n2. **Stored connection (temps-native):** `git_connection_id`\n references a row in the caller's git provider connections. Temps\n resolves the token server-side and injects it safely.\n\n`git_connection_id` is mutually exclusive with `username`/`password`." - }, - "SourceFileListResponse": { - "type": "object", - "required": [ - "source_files", - "total" - ], - "properties": { - "source_files": { - "type": "array", - "items": { - "$ref": "#/components/schemas/SourceFileResponse" - } - }, - "total": { - "type": "integer", - "minimum": 0 - } - } - }, - "SourceFileResponse": { - "type": "object", - "required": [ - "id", - "project_id", - "release", - "file_path", - "size_bytes", - "created_at" - ], - "properties": { - "checksum": { - "type": [ - "string", - "null" - ] - }, - "created_at": { - "type": "string", - "example": "2025-10-12T12:15:47.609192Z" - }, - "file_path": { - "type": "string" - }, - "id": { - "type": "integer", - "format": "int32" - }, - "project_id": { - "type": "integer", - "format": "int32" - }, - "release": { - "type": "string" - }, - "size_bytes": { - "type": "integer", - "format": "int64" - } - } - }, - "SourceMapListResponse": { - "type": "object", - "required": [ - "source_maps", - "total" - ], - "properties": { - "source_maps": { - "type": "array", - "items": { - "$ref": "#/components/schemas/SourceMapResponse" - } - }, - "total": { - "type": "integer", - "minimum": 0 - } - } - }, - "SourceMapResponse": { - "type": "object", - "required": [ - "id", - "project_id", - "release", - "file_path", - "size_bytes", - "created_at" - ], - "properties": { - "checksum": { - "type": [ - "string", - "null" - ] - }, - "created_at": { - "type": "string", - "example": "2025-10-12T12:15:47.609192Z" - }, - "dist": { - "type": [ - "string", - "null" - ] - }, - "file_path": { - "type": "string" - }, - "id": { - "type": "integer", - "format": "int32" - }, - "project_id": { - "type": "integer", - "format": "int32" - }, - "release": { - "type": "string" - }, - "size_bytes": { - "type": "integer", - "format": "int64" - } - } - }, - "SourceType": { - "type": "string", - "description": "Source type for project deployments\n\nDetermines where the deployment artifacts come from:\n- `Git`: Source code from a Git repository (traditional flow)\n- `DockerImage`: Pre-built Docker image from external registry\n- `StaticFiles`: Pre-built static files uploaded as a bundle\n- `Manual`: Flexible type that accepts any deployment method", - "enum": [ - "git", - "docker_image", - "static_files", - "manual" - ] - }, - "SpanEvent": { - "type": "object", - "description": "A span event (log-like annotation on a span).", - "required": [ - "timestamp", - "name", - "attributes" - ], - "properties": { - "attributes": { - "type": "object", - "additionalProperties": { - "type": "string" - }, - "propertyNames": { - "type": "string" - } - }, - "name": { - "type": "string" - }, - "timestamp": { - "type": "string", - "format": "date-time" - } - } - }, - "SpanKind": { - "type": "string", - "description": "Span kind.", - "enum": [ - "UNSPECIFIED", - "INTERNAL", - "SERVER", - "CLIENT", - "PRODUCER", - "CONSUMER" - ] - }, - "SpanRecord": { - "type": "object", - "description": "A single trace span ready for storage.", - "required": [ - "project_id", - "resource", - "trace_id", - "span_id", - "name", - "kind", - "start_time", - "end_time", - "duration_ms", - "status_code", - "status_message", - "attributes", - "events" - ], - "properties": { - "attributes": { - "type": "object", - "description": "Raw key/value pairs exactly as reported by the instrumenting library.\nNumeric values are NOT guaranteed to share `duration_ms`'s unit \u2014 they\nmay be seconds, milliseconds, microseconds, or nanoseconds depending on\nthe exporter's own convention, and the unit is not labeled here.", - "additionalProperties": { - "type": "string" - }, - "propertyNames": { - "type": "string" - } - }, - "deployment_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "duration_ms": { - "type": "number", - "format": "double", - "description": "Span duration in milliseconds. The only field on this struct guaranteed\nto be in milliseconds." - }, - "end_time": { - "type": "string", - "format": "date-time" - }, - "events": { - "type": "array", - "items": { - "$ref": "#/components/schemas/SpanEvent" - } - }, - "kind": { - "$ref": "#/components/schemas/SpanKind" - }, - "name": { - "type": "string" - }, - "parent_span_id": { - "type": [ - "string", - "null" - ] - }, - "project_id": { - "type": "integer", - "format": "int32" - }, - "resource": { - "$ref": "#/components/schemas/ResourceInfo" - }, - "span_id": { - "type": "string" - }, - "start_time": { - "type": "string", - "format": "date-time" - }, - "status_code": { - "$ref": "#/components/schemas/SpanStatusCode" - }, - "status_message": { - "type": "string" - }, - "trace_id": { - "type": "string" - } - } - }, - "SpanRow": { - "type": "object", - "required": [ - "id", - "ts", - "trace_id", - "span_id", - "service", - "operation", - "attributes", - "attributes_truncated" - ], - "properties": { - "attributes": {}, - "attributes_truncated": { - "type": "boolean" - }, - "deployment_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "duration_ms": { - "type": [ - "number", - "null" - ], - "format": "double" - }, - "environment_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "id": { - "type": "string" - }, - "operation": { - "type": "string" - }, - "parent_span_id": { - "type": [ - "string", - "null" - ] - }, - "service": { - "type": "string" - }, - "span_id": { - "type": "string" - }, - "status": { - "type": [ - "string", - "null" - ] - }, - "trace_id": { - "type": "string" - }, - "ts": { - "type": "string", - "format": "date-time" - } - } - }, - "SpanStatusCode": { - "type": "string", - "description": "Span status code.", - "enum": [ - "UNSET", - "OK", - "ERROR" - ] - }, - "SpeedMetricsPayload": { - "type": "object", - "description": "Speed metrics payload for recording web vitals", - "properties": { - "cls": { - "type": [ - "number", - "null" - ], - "format": "float", - "description": "Cumulative Layout Shift (score)" - }, - "fcp": { - "type": [ - "number", - "null" - ], - "format": "float", - "description": "First Contentful Paint (milliseconds)" - }, - "fid": { - "type": [ - "number", - "null" - ], - "format": "float", - "description": "First Input Delay (milliseconds)" - }, - "inp": { - "type": [ - "number", - "null" - ], - "format": "float", - "description": "Interaction to Next Paint (milliseconds)" - }, - "language": { - "type": [ - "string", - "null" - ], - "description": "Browser language" - }, - "lcp": { - "type": [ - "number", - "null" - ], - "format": "float", - "description": "Largest Contentful Paint (milliseconds)" - }, - "pathname": { - "type": [ - "string", - "null" - ], - "description": "Page pathname" - }, - "query": { - "type": [ - "string", - "null" - ], - "description": "Query string" - }, - "screenHeight": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Screen height in pixels" - }, - "screenWidth": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Screen width in pixels" - }, - "ttfb": { - "type": [ - "number", - "null" - ], - "format": "float", - "description": "Time to First Byte (milliseconds)" - }, - "viewportHeight": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Viewport height in pixels" - }, - "viewportWidth": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Viewport width in pixels" - } - } - }, - "SpeedSegmentFilters": { - "type": "object", - "description": "Optional segment filters for the performance read endpoints, mirroring\nanalytics' `VisitorSegmentFilters`. Each filter narrows results to samples\nmatching the dimension value, so metrics can be scoped to e.g. one page,\none browser, or one country. Geographic filters resolve via\n`ip_geolocations`; the rest live directly on `performance_metrics`.", - "properties": { - "filter_browser": { - "type": [ - "string", - "null" - ], - "description": "Browser name (matches `performance_metrics.browser`)" - }, - "filter_city": { - "type": [ - "string", - "null" - ], - "description": "Geolocation city (matches `ip_geolocations.city`)" - }, - "filter_country": { - "type": [ - "string", - "null" - ], - "description": "Geolocation country (matches `ip_geolocations.country`)" - }, - "filter_operating_system": { - "type": [ - "string", - "null" - ], - "description": "Operating system (matches `performance_metrics.operating_system`)" - }, - "filter_path": { - "type": [ - "string", - "null" - ], - "description": "Page pathname (matches `performance_metrics.pathname`)" - }, - "filter_region": { - "type": [ - "string", - "null" - ], - "description": "Geolocation region (matches `ip_geolocations.region`)" - } - } - }, - "StaleSlot": { - "type": "object", - "required": [ - "slot_name", - "active", - "retained_bytes" - ], - "properties": { - "active": { - "type": "boolean" - }, - "retained_bytes": { - "type": "integer", - "format": "int64" - }, - "slot_name": { - "type": "string" - } - } - }, - "StartAnalysisRequest": { - "type": "object", - "required": [ - "error_group_id" - ], - "properties": { - "branch": { - "type": [ - "string", - "null" - ], - "description": "Branch to clone instead of the project's main branch." - }, - "error_group_id": { - "type": "integer", - "format": "int32" - }, - "max_turns": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Per-run turn cap applied to every phase (1\u2013200). Only enforced for\nCLIs with a turn flag (Claude Code). `None` uses the provider's\nconfigured defaults." - }, - "model": { - "type": [ - "string", - "null" - ], - "description": "Model id for the chosen provider. `None` uses the provider's saved\ndefault model." - }, - "provider": { - "type": [ - "string", - "null" - ], - "description": "AI provider id (\"claude_cli\", \"codex_cli\", \"opencode\"). `None` uses\nthe platform default provider." - }, - "user_context": { - "type": [ - "string", - "null" - ], - "description": "Free-text notes for the model (extra context about the error, retry\nguidance, constraints). Included verbatim in the analysis prompt." - } - } - }, - "StartPgUpgradeRequest": { - "type": "object", - "required": [ - "from_version", - "to_version", - "from_image", - "to_image" - ], - "properties": { - "from_image": { - "type": "string", - "example": "postgres:16-bookworm" - }, - "from_version": { - "type": "string", - "example": "16" - }, - "to_image": { - "type": "string", - "example": "postgres:17-bookworm" - }, - "to_version": { - "type": "string", - "example": "17" - } - } - }, - "StartRestoreRequest": { - "allOf": [ - { - "$ref": "#/components/schemas/RestoreRequestMode", - "description": "Requested restore mode. See `RestoreRequestMode`." - }, - { - "type": "object", - "properties": { - "backup_engine": { - "type": [ - "string", - "null" - ], - "description": "Engine of the backup when specified by `backup_location`\n(\"postgres\", \"redis\", \"mongodb\", \"s3\"). Ignored when `backup_id`\nis used \u2014 we infer from the DB row." - }, - "backup_id": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "DB id of the backup to restore from. Either `backup_id` or\n`backup_location` MUST be provided. Use `backup_id` when restoring\na backup this Temps instance recorded." - }, - "backup_location": { - "type": [ - "string", - "null" - ], - "description": "Raw S3 URL / key of the backup \u2014 used when restoring a backup\ndiscovered by S3 scan (i.e., produced by another Temps instance).\nRequires `backup_engine` and `s3_source_id` to also be set." - }, - "s3_source_id": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "S3 source the `backup_location` lives in. Ignored when `backup_id`\nis used." - } - } - } - ] - }, - "StatResponse": { - "type": "object", - "required": [ - "path", - "exists", - "is_dir", - "is_file", - "size" - ], - "properties": { - "exists": { - "type": "boolean" - }, - "is_dir": { - "type": "boolean" - }, - "is_file": { - "type": "boolean" - }, - "path": { - "type": "string" - }, - "size": { - "type": "integer", - "format": "int64", - "minimum": 0 - } - } - }, - "StaticBundleResponse": { - "type": "object", - "required": [ - "id", - "project_id", - "blob_path", - "content_type", - "size_bytes", - "uploaded_at", - "created_at" - ], - "properties": { - "blob_path": { - "type": "string" - }, - "checksum": { - "type": [ - "string", - "null" - ] - }, - "content_type": { - "type": "string" - }, - "created_at": { - "type": "string", - "format": "date-time", - "example": "2025-10-12T12:15:47.609192Z" - }, - "format": { - "type": [ - "string", - "null" - ] - }, - "id": { - "type": "integer", - "format": "int32" - }, - "metadata": {}, - "original_filename": { - "type": [ - "string", - "null" - ] - }, - "project_id": { - "type": "integer", - "format": "int32" - }, - "size_bytes": { - "type": "integer", - "format": "int64" - }, - "uploaded_at": { - "type": "string", - "format": "date-time", - "example": "2025-10-12T12:15:47.609192Z" - } - } - }, - "StaticParams": { - "type": "object", - "description": "Static threshold detector: compare the aggregated `value` against `threshold`.", - "required": [ - "comparator", - "threshold" - ], - "properties": { - "comparator": { - "$ref": "#/components/schemas/Comparator", - "description": "How `value` is compared against `threshold`." - }, - "threshold": { - "type": "number", - "format": "double", - "description": "The threshold the aggregated value is compared against." - } - } - }, - "StaticPresetConfig": { - "type": "object", - "description": "Configuration for static site presets (Vite, Next.js, Docusaurus, etc.)\nThese presets build static sites that are served via a web server", - "properties": { - "buildCommand": { - "type": [ - "string", - "null" - ], - "description": "Custom build command (overrides preset default)", - "example": "npm run build:production" - }, - "buildContext": { - "type": [ - "string", - "null" - ], - "description": "Custom build context path (relative to repository root)\nUseful for monorepo setups where the app is in a subdirectory", - "example": "./apps/frontend" - }, - "installCommand": { - "type": [ - "string", - "null" - ], - "description": "Custom install command (overrides auto-detected package manager)", - "example": "npm ci" - }, - "outputDir": { - "type": [ - "string", - "null" - ], - "description": "Custom output directory (overrides preset default)\nCommon values: \"dist\", \"build\", \".next\", \"out\"", - "example": "dist" - } - } - }, - "StatsFilters": { - "type": "object", - "description": "Filters for statistics queries", - "properties": { - "client_ip": { - "type": [ - "string", - "null" - ] - }, - "deployment_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "device_type": { - "type": [ - "string", - "null" - ] - }, - "environment_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "has_project": { - "type": [ - "boolean", - "null" - ], - "description": "When true, only count requests that matched a project (project_id IS NOT NULL).\nUsed by the health dashboard so totals match the per-project cards." - }, - "host": { - "type": [ - "string", - "null" - ] - }, - "is_bot": { - "type": [ - "boolean", - "null" - ] - }, - "method": { - "type": [ - "string", - "null" - ] - }, - "project_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "request_source": { - "type": [ - "string", - "null" - ] - }, - "routing_status": { - "type": [ - "string", - "null" - ] - }, - "status_code": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "status_code_class": { - "type": [ - "string", - "null" - ], - "description": "Filter by status code class (e.g. \"2xx\", \"3xx\", \"4xx\", \"5xx\")" - } - } - }, - "StatusBucket": { - "type": "object", - "required": [ - "bucket_start", - "status", - "total_checks", - "operational_count", - "degraded_count", - "down_count", - "uptime_percentage" - ], - "properties": { - "avg_response_time_ms": { - "type": [ - "number", - "null" - ], - "format": "double" - }, - "bucket_start": { - "type": "string", - "format": "date-time" - }, - "degraded_count": { - "type": "integer", - "format": "int64" - }, - "down_count": { - "type": "integer", - "format": "int64" - }, - "max_response_time_ms": { - "type": [ - "number", - "null" - ], - "format": "double" - }, - "min_response_time_ms": { - "type": [ - "number", - "null" - ], - "format": "double" - }, - "operational_count": { - "type": "integer", - "format": "int64" - }, - "p50_response_time_ms": { - "type": [ - "number", - "null" - ], - "format": "double" - }, - "p95_response_time_ms": { - "type": [ - "number", - "null" - ], - "format": "double" - }, - "p99_response_time_ms": { - "type": [ - "number", - "null" - ], - "format": "double" - }, - "status": { - "type": "string" - }, - "total_checks": { - "type": "integer", - "format": "int64" - }, - "uptime_percentage": { - "type": "number", - "format": "double" - } - } - }, - "StatusBucketedResponse": { - "type": "object", - "required": [ - "monitor_id", - "interval", - "buckets" - ], - "properties": { - "buckets": { - "type": "array", - "items": { - "$ref": "#/components/schemas/StatusBucket" - } - }, - "interval": { - "type": "string" - }, - "monitor_id": { - "type": "integer", - "format": "int32" - } - } - }, - "StatusCodeCount": { - "type": "object", - "required": [ - "status_code", - "count", - "percentage" - ], - "properties": { - "count": { - "type": "integer", - "format": "int64" - }, - "percentage": { - "type": "number", - "format": "double" - }, - "status_code": { - "type": "integer", - "format": "int32" - } - } - }, - "StatusCodesQuery": { - "type": "object", - "required": [ - "start_date", - "end_date", - "project_id" - ], - "properties": { - "deployment_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "end_date": { - "type": "string", - "format": "date-time" - }, - "environment_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "limit": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "project_id": { - "type": "integer", - "format": "int32" - }, - "start_date": { - "type": "string", - "format": "date-time" - } - } - }, - "StatusPageOverview": { - "type": "object", - "required": [ - "status", - "monitors", - "recent_incidents" - ], - "properties": { - "monitors": { - "type": "array", - "items": { - "$ref": "#/components/schemas/MonitorStatus" - } - }, - "recent_incidents": { - "type": "array", - "items": { - "$ref": "#/components/schemas/IncidentResponse" - } - }, - "status": { - "type": "string" - } - } - }, - "StepConversionResponse": { - "type": "object", - "required": [ - "step_id", - "step_name", - "step_order", - "completions", - "conversion_rate", - "drop_off_rate", - "average_time_to_complete_seconds" - ], - "properties": { - "average_time_to_complete_seconds": { - "type": "number", - "format": "double" - }, - "completions": { - "type": "integer", - "format": "int64", - "minimum": 0 - }, - "conversion_rate": { - "type": "number", - "format": "double" - }, - "drop_off_rate": { - "type": "number", - "format": "double" - }, - "step_id": { - "type": "integer", - "format": "int32" - }, - "step_name": { - "type": "string" - }, - "step_order": { - "type": "integer", - "format": "int32" - } - } - }, - "StepResourceType": { - "type": "string", - "description": "What kind of resource a migration step operates on", - "enum": [ - "project", - "environment", - "deployment", - "environment-variable", - "service", - "domain", - "git-link", - "other" - ] - }, - "StepResult": { - "type": "object", - "description": "Result of executing a single migration step", - "required": [ - "step_id", - "step_title", - "success", - "skipped", - "message", - "created_resources", - "duration_seconds" - ], - "properties": { - "created_resources": { - "type": "array", - "items": { - "$ref": "#/components/schemas/CreatedResource" - }, - "description": "Resources created by this step" - }, - "duration_seconds": { - "type": "number", - "format": "double", - "description": "Duration of this step" - }, - "message": { - "type": "string", - "description": "Human-readable message about what happened" - }, - "skipped": { - "type": "boolean", - "description": "Whether this step was skipped" - }, - "step_id": { - "type": "string", - "description": "Step ID (matches `MigrationStep.id`)" - }, - "step_title": { - "type": "string", - "description": "Step title (for display)" - }, - "success": { - "type": "boolean", - "description": "Whether this step succeeded" - } - } - }, - "StepUpResponse": { - "type": "object", - "required": [ - "expires_at" - ], - "properties": { - "expires_at": { - "type": "string", - "format": "date-time", - "description": "ISO 8601 timestamp after which sensitive actions require verification\nagain." - } - } - }, - "StopSequence": { - "oneOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ] - }, - "StorageQuota": { - "type": "object", - "description": "Quota usage information for a project.", - "required": [ - "project_id", - "metrics_bytes", - "traces_bytes", - "logs_bytes", - "total_bytes", - "limit_bytes", - "usage_pct" - ], - "properties": { - "limit_bytes": { - "type": "integer", - "format": "int64", - "minimum": 0 - }, - "logs_bytes": { - "type": "integer", - "format": "int64", - "minimum": 0 - }, - "metrics_bytes": { - "type": "integer", - "format": "int64", - "minimum": 0 - }, - "project_id": { - "type": "integer", - "format": "int32" - }, - "total_bytes": { - "type": "integer", - "format": "int64", - "minimum": 0 - }, - "traces_bytes": { - "type": "integer", - "format": "int64", - "minimum": 0 - }, - "usage_pct": { - "type": "number", - "format": "double" - } - } - }, - "StripeConfig": { - "type": "object", - "properties": { - "include_unpriced_charges": { - "type": "boolean", - "description": "When an allowlist is set, should we still ingest charges that\nlack a price reference (e.g. standalone `charge.succeeded` without\na subscription)? Default true \u2014 charges don't belong to a SKU." - }, - "metered_mode": { - "$ref": "#/components/schemas/MeteredMode", - "description": "How to compute MRR for metered / tiered / hybrid subscriptions." - }, - "price_allowlist": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Only events tagged with one of these Stripe price IDs are ingested.\nEmpty = accept all prices." - }, - "product_allowlist": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Only events tagged with one of these Stripe product IDs are\ningested. Empty = accept all products. Combined with\n`price_allowlist` via OR \u2014 if either list has a match, accept." - } - } - }, - "SyncedRepositoryListQuery": { - "type": "object", - "properties": { - "direction": { - "type": [ - "string", - "null" - ] - }, - "git_provider_connection_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "language": { - "type": [ - "string", - "null" - ] - }, - "owner": { - "type": [ - "string", - "null" - ] - }, - "page": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "minimum": 0 - }, - "per_page": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "minimum": 0 - }, - "private": { - "type": [ - "boolean", - "null" - ] - }, - "search": { - "type": [ - "string", - "null" - ] - }, - "sort": { - "type": [ - "string", - "null" - ] - } - } - }, - "SyntaxResult": { - "type": "object", - "description": "Syntax validation result", - "required": [ - "is_valid_syntax" - ], - "properties": { - "domain": { - "type": [ - "string", - "null" - ], - "description": "The domain part of the email", - "example": "gmail.com" - }, - "is_valid_syntax": { - "type": "boolean", - "description": "Whether the email syntax is valid" - }, - "suggestion": { - "type": [ - "string", - "null" - ], - "description": "Suggested email correction if available" - }, - "username": { - "type": [ - "string", - "null" - ], - "description": "The username part of the email", - "example": "someone" - } - } - }, - "TagInfo": { - "type": "object", - "required": [ - "name", - "commit_sha" - ], - "properties": { - "commit_sha": { - "type": "string" - }, - "name": { - "type": "string" - } - } - }, - "TagListResponse": { - "type": "object", - "required": [ - "tags" - ], - "properties": { - "tags": { - "type": "array", - "items": { - "$ref": "#/components/schemas/TagInfo" - } - } - } - }, - "TailLogsRequest": { - "type": "object", - "required": [ - "project_id", - "service", - "env" - ], - "properties": { - "env": { - "type": "string" - }, - "external_service_id": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "When set, tail an imported/managed external service's logs instead of\na project's (`project_id` is ignored in this mode)." - }, - "levels": { - "type": "array", - "items": { - "type": "string" - } - }, - "project_id": { - "type": "integer", - "format": "int32", - "description": "Project ID (integer, as used by the rest of the platform)" - }, - "service": { - "type": "string" - }, - "text": { - "type": [ - "string", - "null" - ] - } - } - }, - "TargetRecommendation": { - "type": "object", - "description": "The temps/Hetzner target sizing and savings estimate", - "required": [ - "server_type", - "vcpus", - "memory_gb", - "monthly_eur", - "fits_single_node", - "sizing_basis", - "rationale" - ], - "properties": { - "fits_single_node": { - "type": "boolean", - "description": "Whether the workloads fit a single recommended server. When `false`,\nthe rationale explains the multi-node option (temps worker nodes)." - }, - "memory_gb": { - "type": "integer", - "format": "int32", - "description": "Memory (GB) of the recommended server" - }, - "monthly_eur": { - "type": "number", - "format": "double", - "description": "Estimated monthly price of the recommended server in EUR" - }, - "monthly_savings_usd": { - "type": [ - "number", - "null" - ], - "format": "double", - "description": "Estimated monthly savings in USD (current cost minus target cost,\ntreating EUR\u2248USD for the rough comparison \u2014 disclaimed in `notes`).\n`None` when the current cost is unknown." - }, - "rationale": { - "type": "string", - "description": "Human-readable recommendation summary" - }, - "server_type": { - "type": "string", - "description": "Recommended Hetzner server type (e.g. \"cpx32\")" - }, - "sizing_basis": { - "type": "string", - "description": "What the sizing was based on, e.g. \"2\u00d7 measured usage + temps\nplatform overhead\" or \"resource requests (no metrics available)\"" - }, - "vcpus": { - "type": "integer", - "format": "int32", - "description": "vCPUs of the recommended server" - }, - "yearly_savings_usd": { - "type": [ - "number", - "null" - ], - "format": "double", - "description": "`monthly_savings_usd \u00d7 12`" - } - } - }, - "TeamListResponse": { - "type": "object", - "required": [ - "teams", - "total", - "page", - "page_size" - ], - "properties": { - "page": { - "type": "integer", - "format": "int64", - "minimum": 0 - }, - "page_size": { - "type": "integer", - "format": "int64", - "minimum": 0 - }, - "teams": { - "type": "array", - "items": { - "$ref": "#/components/schemas/TeamResponse" - } - }, - "total": { - "type": "integer", - "format": "int64", - "minimum": 0 - } - } - }, - "TeamMemberResponse": { - "type": "object", - "required": [ - "id", - "team_id", - "user_id", - "role", - "added_by", - "created_at", - "updated_at" - ], - "properties": { - "added_by": { - "type": "integer", - "format": "int32" - }, - "created_at": { - "type": "string", - "format": "date-time", - "example": "2026-07-30T12:15:47.609192Z" - }, - "id": { - "type": "integer", - "format": "int32" - }, - "role": { - "$ref": "#/components/schemas/TeamRole", - "description": "The source of this member's project-scoped permissions, intersected\nwith `project_team_access.role`." - }, - "team_id": { - "type": "integer", - "format": "int32" - }, - "updated_at": { - "type": "string", - "format": "date-time", - "example": "2026-07-30T12:15:47.609192Z" - }, - "user_email": { - "type": [ - "string", - "null" - ], - "description": "The member's email, joined from `users`." - }, - "user_id": { - "type": "integer", - "format": "int32" - }, - "user_name": { - "type": [ - "string", - "null" - ], - "description": "The member's display name, joined from `users`. `None` if the\nreferenced user no longer exists." - } - } - }, - "TeamResponse": { - "type": "object", - "required": [ - "id", - "name", - "slug", - "created_by", - "created_at", - "updated_at" - ], - "properties": { - "created_at": { - "type": "string", - "format": "date-time", - "example": "2026-07-30T12:15:47.609192Z" - }, - "created_by": { - "type": "integer", - "format": "int32" - }, - "description": { - "type": [ - "string", - "null" - ] - }, - "id": { - "type": "integer", - "format": "int32" - }, - "name": { - "type": "string" - }, - "slug": { - "type": "string" - }, - "updated_at": { - "type": "string", - "format": "date-time", - "example": "2026-07-30T12:15:47.609192Z" - } - } - }, - "TeamRole": { - "type": "string", - "description": "Role a user holds within a team, or that a team holds on a project.\n\nNamed `TeamRole` rather than `Role` to keep it distinct from\n`temps_auth::permissions::Role`, which is the instance-wide role\n(Admin/User/\u2026) attached to a session. The two are orthogonal: the\ninstance-wide role decides whether you may touch a resource *kind* at\nall, `TeamRole` decides what you may do *within a project* you have\nteam access to. See `temps_teams::fixed_role_permissions` for the\nproject-scoped permission set each variant maps to.\n\nStored as a `varchar(32)` rather than a Postgres enum so the role set\ncan evolve in pure migration code without a schema-level enum\nalteration blocking a downgrade.", - "enum": [ - "owner", - "admin", - "deployer", - "viewer" - ] - }, - "TemplateResponse": { - "type": "object", - "description": "Response type for a single template", - "required": [ - "slug", - "name", - "git", - "preset", - "tags", - "features", - "services", - "env_vars", - "is_featured" - ], - "properties": { - "description": { - "type": [ - "string", - "null" - ], - "description": "Short description" - }, - "env_vars": { - "type": "array", - "items": { - "$ref": "#/components/schemas/EnvVarTemplateResponse" - }, - "description": "Environment variables template" - }, - "exposed_port": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Container port the prebuilt image listens on (image deploys only)." - }, - "features": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Feature highlights" - }, - "git": { - "$ref": "#/components/schemas/GitRefResponse", - "description": "Git repository reference" - }, - "health_check_path": { - "type": [ - "string", - "null" - ], - "description": "HTTP health-check path probed after the container starts (image deploys)." - }, - "image": { - "type": [ - "string", - "null" - ], - "description": "Prebuilt Docker image reference. When set, the one-click deploy pulls and\nruns this image directly (no build); when absent it builds from `git`." - }, - "image_url": { - "type": [ - "string", - "null" - ], - "description": "URL to template image/icon" - }, - "is_featured": { - "type": "boolean", - "description": "Whether the template is featured/promoted" - }, - "name": { - "type": "string", - "description": "Display name" - }, - "preset": { - "type": "string", - "description": "Framework/preset to use" - }, - "screenshot_url": { - "type": [ - "string", - "null" - ], - "description": "URL to a wide screenshot/banner preview of the deployed template.\nAbsent for templates that don't have one captured yet." - }, - "services": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Required external services" - }, - "slug": { - "type": "string", - "description": "Unique identifier for the template (used in URLs)" - }, - "tags": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Tags/categories for filtering" - } - } - }, - "TestEmailRequest": { - "type": "object", - "description": "Request body for testing an email provider", - "required": [ - "from" - ], - "properties": { - "from": { - "type": "string", - "description": "Sender email address (must be verified with the provider)", - "example": "test@example.com" - }, - "from_name": { - "type": [ - "string", - "null" - ], - "description": "Sender display name", - "example": "My App" - } - } - }, - "TestEmailResponse": { - "type": "object", - "description": "Response for test email endpoint", - "required": [ - "success", - "sent_to" - ], - "properties": { - "error": { - "type": [ - "string", - "null" - ], - "description": "Error message if the test failed" - }, - "provider_message_id": { - "type": [ - "string", - "null" - ], - "description": "Provider message ID if successful" - }, - "sent_to": { - "type": "string", - "description": "The email address the test was sent to", - "example": "user@example.com" - }, - "success": { - "type": "boolean", - "description": "Whether the test email was sent successfully" - } - } - }, - "TestProviderKeyRequest": { - "type": "object", - "required": [ - "provider", - "api_key" - ], - "properties": { - "api_key": { - "type": "string", - "description": "The raw API key to test" - }, - "base_url": { - "type": [ - "string", - "null" - ], - "description": "Optional custom base URL" - }, - "provider": { - "type": "string", - "description": "Provider ID: \"openai\", \"anthropic\", \"xai\", \"gemini\"" - } - } - }, - "TestProviderKeyResponse": { - "type": "object", - "required": [ - "success", - "provider", - "latency_ms" - ], - "properties": { - "error": { - "type": [ - "string", - "null" - ], - "description": "Error message if the test failed" - }, - "latency_ms": { - "type": "integer", - "format": "int64", - "description": "Response time in milliseconds", - "minimum": 0 - }, - "provider": { - "type": "string" - }, - "success": { - "type": "boolean" - } - } - }, - "TestProviderResponse": { - "type": "object", - "required": [ - "success" - ], - "properties": { - "message": { - "type": [ - "string", - "null" - ] - }, - "success": { - "type": "boolean" - } - } - }, - "TimeBucketStats": { - "type": "object", - "description": "Time bucket statistics response", - "required": [ - "bucket", - "request_count", - "avg_response_time_ms", - "error_count", - "total_request_bytes", - "total_response_bytes" - ], - "properties": { - "avg_response_time_ms": { - "type": "number", - "format": "double", - "description": "Average response time in milliseconds" - }, - "bucket": { - "type": "string", - "description": "Bucket timestamp in RFC3339 format", - "example": "2025-10-23T12:00:00Z" - }, - "error_count": { - "type": "integer", - "format": "int64", - "description": "Number of errors (status >= 400)" - }, - "request_count": { - "type": "integer", - "format": "int64", - "description": "Total number of requests in this bucket" - }, - "total_request_bytes": { - "type": "integer", - "format": "int64", - "description": "Total request bytes" - }, - "total_response_bytes": { - "type": "integer", - "format": "int64", - "description": "Total response bytes" - } - } - }, - "TimeBucketStatsResponse": { - "type": "object", - "description": "Response for time bucket stats", - "required": [ - "stats", - "start_time", - "end_time", - "bucket_interval" - ], - "properties": { - "bucket_interval": { - "type": "string" - }, - "end_time": { - "type": "string" - }, - "start_time": { - "type": "string" - }, - "stats": { - "type": "array", - "items": { - "$ref": "#/components/schemas/TimeBucketStats" - } - } - } - }, - "TimeseriesBucket": { - "type": "object", - "required": [ - "bucket", - "request_count", - "input_tokens", - "output_tokens", - "avg_latency_ms" - ], - "properties": { - "avg_latency_ms": { - "type": "number", - "format": "double" - }, - "bucket": { - "type": "string", - "description": "ISO 8601 timestamp" - }, - "input_tokens": { - "type": "integer", - "format": "int64" - }, - "output_tokens": { - "type": "integer", - "format": "int64" - }, - "request_count": { - "type": "integer", - "format": "int64" - } - } - }, - "TimeseriesQueryParams": { - "type": "object", - "properties": { - "bucket": { - "type": [ - "string", - "null" - ], - "description": "Bucket size: \"hour\", \"day\", \"week\" (defaults to \"day\")" - }, - "conversation_id": { - "type": [ - "string", - "null" - ], - "description": "Filter by conversation ID" - }, - "from": { - "type": [ - "string", - "null" - ], - "description": "ISO 8601 start time (defaults to 24h ago)" - }, - "model": { - "type": [ - "string", - "null" - ], - "description": "Filter by model name" - }, - "provider": { - "type": [ - "string", - "null" - ], - "description": "Filter by provider name" - }, - "tags": { - "type": [ - "string", - "null" - ], - "description": "Filter by tags (comma-separated, AND logic)" - }, - "to": { - "type": [ - "string", - "null" - ], - "description": "ISO 8601 end time (defaults to now)" - }, - "user_id": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Filter by user ID" - } - } - }, - "TlsMode": { - "type": "string", - "enum": [ - "None", - "Starttls", - "Tls" - ] - }, - "TodayStatsResponse": { - "type": "object", - "description": "Today's stats response", - "required": [ - "total_requests", - "date" - ], - "properties": { - "date": { - "type": "string", - "description": "Date for which stats are returned", - "example": "2025-10-23" - }, - "total_requests": { - "type": "integer", - "format": "int64", - "description": "Total requests today" - } - } - }, - "ToggleDeploymentMetricsRequest": { - "type": "object", - "description": "Request body to toggle OTLP metric ingestion for a deployment.", - "required": [ - "enabled" - ], - "properties": { - "enabled": { - "type": "boolean", - "description": "Whether to enable (`true`) or disable (`false`) metric ingestion." - }, - "path": { - "type": [ - "string", - "null" - ], - "description": "Prometheus scrape path (optional, defaults to `/metrics`)." - }, - "port": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Prometheus scrape port (optional).", - "minimum": 0 - } - } - }, - "ToggleServiceMetricsRequest": { - "type": "object", - "description": "Request body to toggle metric collection for an external service.", - "required": [ - "enabled" - ], - "properties": { - "enabled": { - "type": "boolean", - "description": "Whether to enable (`true`) or disable (`false`) metric collection." - } - } - }, - "TokenRenewalRequest": { - "type": "object", - "required": [ - "refresh_token" - ], - "properties": { - "refresh_token": { - "type": "string" - } - } - }, - "ToolCallEvent": { - "type": "object", - "description": "Payload for the `tool_call` SSE event: the model is about to run a tool.\nSerialized as compact single-line JSON onto one `data:` line.", - "required": [ - "id", - "name", - "arguments" - ], - "properties": { - "arguments": { - "type": "string", - "description": "The raw JSON-args string the model emitted." - }, - "id": { - "type": "string" - }, - "name": { - "type": "string" - } - } - }, - "ToolInfo": { - "type": "object", - "description": "One persisted tool invocation + its result, attached to an assistant message.", - "required": [ - "id", - "name", - "arguments" - ], - "properties": { - "arguments": { - "type": "string" - }, - "id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "result": { - "type": [ - "string", - "null" - ] - } - } - }, - "ToolResultEvent": { - "type": "object", - "description": "Payload for the `tool_result` SSE event: a tool finished running. Serialized\nas compact single-line JSON; `content` is JSON-string-escaped so it stays on\none `data:` line even when long.", - "required": [ - "id", - "name", - "content" - ], - "properties": { - "content": { - "type": "string" - }, - "id": { - "type": "string" - }, - "name": { - "type": "string" - } - } - }, - "TopModelsQueryParams": { - "type": "object", - "properties": { - "from": { - "type": [ - "string", - "null" - ], - "description": "ISO 8601 start time (defaults to 24h ago)" - }, - "limit": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "description": "Max results (defaults to 10)", - "minimum": 0 - }, - "tags": { - "type": [ - "string", - "null" - ], - "description": "Filter by tags (comma-separated, AND logic)" - }, - "to": { - "type": [ - "string", - "null" - ], - "description": "ISO 8601 end time (defaults to now)" - }, - "user_id": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Filter by user ID" - } - } - }, - "TraceProjectRef": { - "type": "object", - "description": "All projects that contributed spans to a trace, including their sharing flag.\n\nReturned by `CrossProjectTraceService::find_trace_projects`.", - "required": [ - "project_id", - "project_name", - "project_slug", - "first_seen", - "sharing" - ], - "properties": { - "first_seen": { - "type": "string", - "format": "date-time" - }, - "project_id": { - "type": "integer", - "format": "int32" - }, - "project_name": { - "type": "string" - }, - "project_slug": { - "type": "string", - "description": "URL slug used to link into the project's single-project trace view." - }, - "sharing": { - "type": "boolean", - "description": "Whether this project has `cross_project_trace_sharing = true`." - } - } - }, - "TraceSummariesResponse": { - "type": "object", - "required": [ - "data" - ], - "properties": { - "data": { - "type": "array", - "items": { - "$ref": "#/components/schemas/TraceSummary" - } - }, - "total": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "description": "Total traces matching the filters, ignoring pagination. Omitted when\nthe request passed `include_total=false`, in which case the caller\nasked not to pay for the count \u2014 treat its absence as \"unknown\", not\nas zero.", - "minimum": 0 - } - } - }, - "TraceSummary": { - "type": "object", - "description": "A trace summary for the list view \u2014 one row per trace, aggregated from spans.", - "required": [ - "trace_id", - "root_span_name", - "service_name", - "kind", - "status_code", - "start_time", - "duration_ms", - "span_count", - "error_count" - ], - "properties": { - "deployment_environment": { - "type": [ - "string", - "null" - ], - "description": "The deployment environment from the root span's resource attributes (e.g. \"production\")." - }, - "duration_ms": { - "type": "number", - "format": "double" - }, - "error_count": { - "type": "integer", - "format": "int64" - }, - "kind": { - "$ref": "#/components/schemas/SpanKind" - }, - "root_span_name": { - "type": "string" - }, - "service_name": { - "type": "string" - }, - "span_count": { - "type": "integer", - "format": "int64" - }, - "start_time": { - "type": "string", - "format": "date-time" - }, - "status_code": { - "$ref": "#/components/schemas/SpanStatusCode" - }, - "trace_id": { - "type": "string" - } - } - }, - "TracesResponse": { - "type": "object", - "required": [ - "data", - "count" - ], - "properties": { - "count": { - "type": "integer", - "minimum": 0 - }, - "data": { - "type": "array", - "items": { - "$ref": "#/components/schemas/SpanRecord" - } - } - } - }, - "TrackedLinkResponse": { - "type": "object", - "description": "Tracked link with click count", - "required": [ - "link_index", - "original_url", - "click_count" - ], - "properties": { - "click_count": { - "type": "integer", - "format": "int32" - }, - "link_index": { - "type": "integer", - "format": "int32" - }, - "original_url": { - "type": "string" - } - } - }, - "TrackingEventResponse": { - "type": "object", - "description": "Email tracking event", - "required": [ - "id", - "email_id", - "event_type", - "created_at" - ], - "properties": { - "created_at": { - "type": "string" - }, - "email_id": { - "type": "string" - }, - "event_type": { - "type": "string" - }, - "id": { - "type": "integer", - "format": "int64" - }, - "ip_address": { - "type": [ - "string", - "null" - ] - }, - "link_index": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "link_url": { - "type": [ - "string", - "null" - ] - }, - "user_agent": { - "type": [ - "string", - "null" - ] - } - } - }, - "TriggerAgentRequest": { - "type": "object", - "properties": { - "trigger_source_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "trigger_source_type": { - "type": [ - "string", - "null" - ] - }, - "user_context": { - "type": [ - "string", - "null" - ], - "description": "Optional context from the user (e.g. a research topic, bug description, or instructions)." - } - } - }, - "TriggerDigestResponse": { - "type": "object", - "required": [ - "success", - "message" - ], - "properties": { - "message": { - "type": "string" - }, - "success": { - "type": "boolean" - } - } - }, - "TriggerPipelinePayload": { - "type": "object", - "properties": { - "branch": { - "type": [ - "string", - "null" - ] - }, - "commit": { - "type": [ - "string", - "null" - ] - }, - "environment_id": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Optional environment ID - if not provided, will use the project's preview environment" - }, - "tag": { - "type": [ - "string", - "null" - ] - } - } - }, - "TriggerPipelineResponse": { - "type": "object", - "required": [ - "message", - "project_id", - "environment_id" - ], - "properties": { - "branch": { - "type": [ - "string", - "null" - ] - }, - "commit": { - "type": [ - "string", - "null" - ] - }, - "environment_id": { - "type": "integer", - "format": "int32" - }, - "message": { - "type": "string" - }, - "project_id": { - "type": "integer", - "format": "int32" - }, - "tag": { - "type": [ - "string", - "null" - ] - } - } - }, - "TriggerScanRequest": { - "type": "object", - "required": [ - "environment_id" - ], - "properties": { - "environment_id": { - "type": "integer", - "format": "int32", - "description": "Environment ID to scan (uses the current deployment for this environment)", - "example": 1 - } - } - }, - "TriggerScanResponse": { - "type": "object", - "required": [ - "scan_id", - "status", - "message" - ], - "properties": { - "message": { - "type": "string" - }, - "scan_id": { - "type": "integer", - "format": "int32" - }, - "status": { - "type": "string" - } - } - }, - "TtlRequest": { - "type": "object", - "description": "Request to get TTL for a key", - "required": [ - "key" - ], - "properties": { - "key": { - "type": "string", - "description": "The key to check TTL for", - "example": "session:abc" - }, - "project_id": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Project ID (required for API key/session auth, optional for deployment tokens)", - "example": 1 - } - } - }, - "TtlResponse": { - "type": "object", - "description": "Response for TTL operation", - "required": [ - "ttl" - ], - "properties": { - "ttl": { - "type": "integer", - "format": "int64", - "description": "TTL in seconds, -1 if no expiration, -2 if key doesn't exist", - "example": 3600 - } - } - }, - "TxtRecord": { - "type": "object", - "required": [ - "name", - "value" - ], - "properties": { - "name": { - "type": "string" - }, - "value": { - "type": "string" - } - } - }, - "UiManifest": { - "type": "object", - "description": "Describes the plugin's embedded UI bundle.", - "required": [ - "entry_js" - ], - "properties": { - "css": { - "type": "array", - "items": { - "type": "string" - }, - "description": "CSS files to load" - }, - "entry_js": { - "type": "string", - "description": "JavaScript entry point filename relative to the bundle root" - }, - "routes": { - "type": "array", - "items": { - "$ref": "#/components/schemas/UiRoute" - }, - "description": "Client-side routes the plugin handles" - } - } - }, - "UiRoute": { - "type": "object", - "description": "A client-side route provided by the plugin UI.", - "required": [ - "path", - "title" - ], - "properties": { - "path": { - "type": "string", - "description": "Route path pattern (e.g., \"/my-plugin\", \"/my-plugin/:id\")" - }, - "title": { - "type": "string", - "description": "Page title for breadcrumbs" - } - } - }, - "UndrainNodeResponse": { - "type": "object", - "description": "Response after undraining (reactivating) a node.", - "required": [ - "id", - "name", - "status", - "message" - ], - "properties": { - "id": { - "type": "integer", - "format": "int32" - }, - "message": { - "type": "string" - }, - "name": { - "type": "string" - }, - "status": { - "type": "string" - } - } - }, - "UnifiedTrace": { - "type": "object", - "description": "Merged cross-project trace result (Phase 2 unified waterfall).\n\nSpans are sorted by `start_time ASC`. At most 20 projects and 10,000\nspans total are included; `truncated` / `truncated_projects` signal when\nthe caps were hit.", - "required": [ - "trace_id", - "projects", - "spans", - "start_time", - "end_time", - "total_duration_ms", - "span_count", - "error_count", - "has_redacted_spans", - "truncated", - "truncated_projects" - ], - "properties": { - "end_time": { - "type": "string", - "format": "date-time" - }, - "error_count": { - "type": "integer", - "minimum": 0 - }, - "has_redacted_spans": { - "type": "boolean", - "description": "`true` when at least one project has `cross_project_trace_sharing = false`\nand its spans were therefore excluded from the result set." - }, - "projects": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ProjectRef" - }, - "description": "Projects that contributed spans to this result set." - }, - "span_count": { - "type": "integer", - "minimum": 0 - }, - "spans": { - "type": "array", - "items": { - "$ref": "#/components/schemas/AnnotatedSpan" - }, - "description": "Annotated, merged span list sorted by `start_time ASC`." - }, - "start_time": { - "type": "string", - "format": "date-time" - }, - "total_duration_ms": { - "type": "number", - "format": "double", - "description": "Trace wall-clock duration in milliseconds (`end_time \u2013 start_time`)." - }, - "trace_id": { - "type": "string" - }, - "truncated": { - "type": "boolean", - "description": "`true` when the 20-project or 10,000-span cap was hit." - }, - "truncated_projects": { - "type": "array", - "items": { - "type": "integer", - "format": "int32" - }, - "description": "project_ids excluded due to truncation (most-recent first_seen dropped first)." - } - } - }, - "UniqueCountsQuery": { - "type": "object", - "description": "Query parameters for unique counts over time frame", - "required": [ - "start_date", - "end_date" - ], - "properties": { - "deployment_id": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Optional deployment filter" - }, - "end_date": { - "type": "string", - "format": "date-time", - "description": "End date for the query range" - }, - "environment_id": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Optional environment filter" - }, - "metric": { - "type": "string", - "description": "Metric to count: \"sessions\" (unique sessions), \"visitors\" (unique visitors),\n\"returning_visitors\" (visitors seen before the range), or \"page_views\"\n(total page views) (default: \"sessions\")" - }, - "start_date": { - "type": "string", - "format": "date-time", - "description": "Start date for the query range" - } - } - }, - "UniqueCountsResponse": { - "type": "object", - "required": [ - "count" - ], - "properties": { - "count": { - "type": "integer", - "format": "int64" - } - } - }, - "UnsupportedFeature": { - "type": "object", - "description": "A feature from the source platform that cannot be migrated", - "required": [ - "feature", - "reason" - ], - "properties": { - "alternative": { - "type": [ - "string", - "null" - ], - "description": "Suggested alternative in Temps (if any)" - }, - "feature": { - "type": "string", - "description": "Feature name (e.g., \"Edge Middleware\", \"Serverless Functions\", \"Cron Jobs\")" - }, - "reason": { - "type": "string", - "description": "Why it can't be migrated" - } - } - }, - "UpdateAdminGateRequest": { - "type": "object", - "required": [ - "allowed_ips", - "allowed_hosts", - "trust_forwarded_for" - ], - "properties": { - "allowed_hosts": { - "type": "array", - "items": { - "type": "string" - } - }, - "allowed_ips": { - "type": "array", - "items": { - "type": "string" - } - }, - "trust_forwarded_for": { - "type": "boolean" - } - } - }, - "UpdateAiProviderRequest": { - "type": "object", - "description": "Body for `PATCH /settings/ai-providers/{provider_id}` \u2014 updates\nprovider-scoped settings (just the default model for now) without\ntouching the credential. Keeping credentials out of this shape means\nthe UI can auto-save model changes on select, without forcing the user\nto re-paste their token or config file.\nName-spaced schema name avoids an OpenAPI collision with\n`temps-notifications::UpdateProviderRequest`, which has different fields.\nBoth are exposed as `utoipa::ToSchema`; without the override the merged\nOpenAPI doc would silently shadow one struct with the other and break\ngenerated CLI/web clients.", - "properties": { - "default_model": { - "type": [ - "string", - "null" - ], - "description": "New default model id. `None` or an empty string clears the stored\nvalue so the CLI falls back to its own default." - }, - "max_turns_analysis": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Default max turns for the autofixer analysis phase (1\u2013200). `0`\nclears the stored value (built-in default applies); omitted/`None`\nleaves the current value unchanged \u2014 so a PATCH that only updates\n`default_model` doesn't wipe the turn settings." - }, - "max_turns_feedback": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Default max turns for autofixer feedback rounds (1\u2013200). `0` clears;\nomitted leaves unchanged." - }, - "max_turns_fix": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Default max turns for the autofixer fix phase (1\u2013200). `0` clears;\nomitted leaves unchanged." - } - } - }, - "UpdateAiProviderResponse": { - "type": "object", - "required": [ - "provider_id" - ], - "properties": { - "default_model": { - "type": [ - "string", - "null" - ] - }, - "max_turns_analysis": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "max_turns_feedback": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "max_turns_fix": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "provider_id": { - "type": "string" - } - } - }, - "UpdateAlertRuleRequest": { - "type": "object", - "properties": { - "cooldown_minutes": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "enabled": { - "type": [ - "boolean", - "null" - ] - }, - "environment_filter": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "error_level_filter": { - "type": [ - "string", - "null" - ] - }, - "name": { - "type": [ - "string", - "null" - ] - }, - "notification_priority": { - "type": [ - "string", - "null" - ] - }, - "trigger_config": {}, - "trigger_type": { - "type": [ - "string", - "null" - ] - } - } - }, - "UpdateApiKeyRequest": { - "type": "object", - "properties": { - "expires_at": { - "type": [ - "string", - "null" - ], - "format": "date-time", - "example": "2024-12-31T23:59:59Z" - }, - "is_active": { - "type": [ - "boolean", - "null" - ] - }, - "name": { - "type": [ - "string", - "null" - ] - }, - "permissions": { - "type": [ - "array", - "null" - ], - "items": { - "type": "string" - }, - "example": [ - "projects:read", - "deployments:read" - ] - } - } - }, - "UpdateAutomaticDeployRequest": { - "type": "object", - "required": [ - "automatic_deploy" - ], - "properties": { - "automatic_deploy": { - "type": "boolean" - } - } - }, - "UpdateBackupScheduleRequest": { - "type": "object", - "description": "Request body for updating an existing backup schedule via `PATCH /api/backups/schedules/{id}`.\n\nAll fields are optional; only present fields are updated. Absent fields\nleave the corresponding column unchanged.", - "properties": { - "description": { - "type": [ - "string", - "null" - ], - "description": "New human-readable description. Pass an empty string `\"\"` to clear." - }, - "enabled": { - "type": [ - "boolean", - "null" - ], - "description": "Enable or disable the schedule. Skipped when `None`." - }, - "include_control_plane": { - "type": [ - "boolean", - "null" - ], - "description": "Toggle whether the control-plane backup is produced on every run." - }, - "max_runtime_secs": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "description": "Per-schedule wall-clock timeout override (seconds).\n\n- `None` (field absent) \u2014 leave current value unchanged\n- `Some(None)` (field present, JSON `null`) \u2014 clear override; fall back to engine default\n- `Some(Some(n))` \u2014 set to `n` seconds (must be >= 60)" - }, - "name": { - "type": [ - "string", - "null" - ], - "description": "New schedule name. Skipped when `None`. Must not be empty if provided." - }, - "retention_period": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Days to retain backups produced by this schedule. Must be >= 1." - }, - "schedule_expression": { - "type": [ - "string", - "null" - ], - "description": "New cron expression. When changed, `next_run` is recomputed." - }, - "tags": { - "type": [ - "array", - "null" - ], - "items": { - "type": "string" - }, - "description": "Replace the full tag list. Skipped when `None`." - }, - "target_all_services": { - "type": [ - "boolean", - "null" - ], - "description": "Toggle between \"back up every database\" (`true`) and \"back up only\nthe explicit list\" (`false`). When set to `true`, the server clears\nthe explicit membership rows for this schedule." - } - } - }, - "UpdateBlobRequest": { - "type": "object", - "description": "Request to update Blob service configuration", - "properties": { - "docker_image": { - "type": [ - "string", - "null" - ], - "description": "Docker image to use (e.g., \"rustfs/rustfs:1.0.0-alpha.98\")", - "example": "rustfs/rustfs:1.0.0-alpha.98" - } - } - }, - "UpdateBlobResponse": { - "type": "object", - "description": "Response after updating Blob service", - "required": [ - "success", - "message", - "status" - ], - "properties": { - "message": { - "type": "string", - "description": "Human-readable message", - "example": "Blob service updated successfully" - }, - "status": { - "$ref": "#/components/schemas/BlobStatusResponse", - "description": "Current status" - }, - "success": { - "type": "boolean", - "description": "Whether the operation succeeded", - "example": true - } - } - }, - "UpdateCloudflareProviderRequest": { - "type": "object", - "required": [ - "config" - ], - "properties": { - "config": { - "$ref": "#/components/schemas/CloudflareConfig" - }, - "enabled": { - "type": [ - "boolean", - "null" - ] - }, - "name": { - "type": [ - "string", - "null" - ] - } - } - }, - "UpdateConfigBody": { - "type": "object", - "properties": { - "config": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/ProviderConfig", - "description": "Typed provider configuration. Setting `config` to `null` clears\nthe stored config back to the accept-everything default. The\nconfig's `provider` tag must match the integration's provider." - } - ] - } - } - }, - "UpdateCustomDomainRequest": { - "type": "object", - "properties": { - "branch": { - "type": [ - "string", - "null" - ] - }, - "domain": { - "type": [ - "string", - "null" - ] - }, - "environment_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "redirect_to": { - "type": [ - "string", - "null" - ] - }, - "service_name": { - "type": [ - "string", - "null" - ], - "description": "Docker Compose service name this domain routes to (empty string clears it)" - }, - "status_code": { - "type": [ - "integer", - "null" - ], - "format": "int32" - } - } - }, - "UpdateDashboardRequest": { - "type": "object", - "properties": { - "layout": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/DashboardLayout" - } - ] - }, - "name": { - "type": [ - "string", - "null" - ] - } - } - }, - "UpdateDeploymentConfigRequest": { - "type": "object", - "properties": { - "automaticDeploy": { - "type": [ - "boolean", - "null" - ] - }, - "cpuLimit": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "cpuRequest": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "crossArchitectureBuilds": { - "type": [ - "boolean", - "null" - ], - "description": "Build one image per architecture the eligible nodes run. Off by\ndefault; environments inherit this and may override it. Cross-builds\nare emulated on the control plane and substantially slower, so they are\nopted into rather than triggered by cluster topology." - }, - "exposedPort": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "memoryLimit": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "memoryRequest": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "performanceMetricsEnabled": { - "type": [ - "boolean", - "null" - ] - }, - "replicas": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "security": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/SecurityConfig" - } - ] - }, - "sessionRecordingEnabled": { - "type": [ - "boolean", - "null" - ] - } - } - }, - "UpdateDeploymentTokenRequest": { - "type": "object", - "properties": { - "expires_at": { - "type": [ - "string", - "null" - ], - "format": "date-time", - "example": "2024-12-31T23:59:59Z" - }, - "is_active": { - "type": [ - "boolean", - "null" - ] - }, - "name": { - "type": [ - "string", - "null" - ] - }, - "permissions": { - "type": [ - "array", - "null" - ], - "items": { - "type": "string" - }, - "example": [ - "visitors:enrich", - "emails:send" - ] - } - } - }, - "UpdateDnsProviderRequest": { - "type": "object", - "description": "Request to update a DNS provider", - "properties": { - "credentials": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/DnsProviderCredentials", - "description": "New credentials" - } - ] - }, - "description": { - "type": [ - "string", - "null" - ], - "description": "New description" - }, - "is_active": { - "type": [ - "boolean", - "null" - ], - "description": "Active status" - }, - "name": { - "type": [ - "string", - "null" - ], - "description": "New name" - } - } - }, - "UpdateEmailProviderRequest": { - "type": "object", - "description": "Request body for `PATCH /email-providers/{id}`.\n\nAll fields are optional. Omit any field to leave it unchanged. The\n`provider_type` is immutable \u2014 to switch providers, delete the row and\ncreate a new one. For credentials, supplying any credential variant\nre-encrypts the stored blob; omitting them preserves the existing secret\n(so operators can rename without re-typing passwords).", - "properties": { - "is_active": { - "type": [ - "boolean", - "null" - ] - }, - "name": { - "type": [ - "string", - "null" - ], - "example": "My AWS SES" - }, - "region": { - "type": [ - "string", - "null" - ], - "example": "us-east-1" - }, - "scaleway_credentials": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/ScalewayCredentialsRequest" - } - ] - }, - "ses_credentials": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/SesCredentialsRequest" - } - ] - }, - "smtp_credentials": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/SmtpCredentialsRequest" - } - ] - }, - "sns_topic_arn": { - "type": [ - "string", - "null" - ], - "description": "Rotate or clear the exact SNS topic allowed for this SES provider.\nOmit to preserve it, send `null` to clear it, or send a string to set it." - } - } - }, - "UpdateEnvironmentSettingsRequest": { - "type": "object", - "properties": { - "anti_affinity": { - "type": [ - "boolean", - "null" - ], - "description": "Anti-affinity: spread replicas across different nodes.\nWhen enabled, the scheduler avoids placing two replicas of the same\nenvironment on the same node. Defaults to `true`." - }, - "attack_mode": { - "type": [ - "boolean", - "null" - ], - "description": "Per-environment CAPTCHA attack-mode override (tri-state):\n- absent \u2192 leave the current override unchanged\n- JSON `null` \u2192 clear the override (inherit the project-level setting)\n- `true`/`false` \u2192 override the project setting for this environment" - }, - "automatic_deploy": { - "type": [ - "boolean", - "null" - ], - "description": "Enable/disable automatic deployments for this environment" - }, - "branch": { - "type": [ - "string", - "null" - ] - }, - "cpu_limit": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Maximum (limit) CPU in microcores. Send JSON `null` to clear \u2192 \"no limit\".\nAbsent leaves the current value unchanged." - }, - "cpu_request": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Minimum (request) CPU in microcores. Send JSON `null` to clear (no request).\nAbsent leaves the current value unchanged." - }, - "cross_architecture_builds": { - "type": [ - "boolean", - "null" - ], - "description": "Build one image per architecture the eligible nodes run (overrides the\nproject-level setting). Off by default: cross-architecture builds are\nemulated on the control plane and substantially slower, so they are\nopted into per environment rather than triggered by cluster topology." - }, - "exposed_port": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Port exposed by the container (overrides project-level port for this environment)\n\nPriority order for port resolution:\n1. Image EXPOSE directive (auto-detected from built image)\n2. This environment-level exposed_port (overrides project setting)\n3. Project-level exposed_port (fallback)\n4. Default: 3000", - "example": 8080 - }, - "force_https": { - "type": [ - "boolean", - "null" - ], - "description": "Per-environment HTTP\u2192HTTPS redirect override (tri-state):\n- absent \u2192 leave the current override unchanged\n- JSON `null` \u2192 clear the override (inherit the proxy default, which\n redirects only when the host has an active TLS certificate)\n- `true` \u2192 always redirect plain HTTP to HTTPS for this environment,\n even when no local certificate exists (TLS terminated upstream)\n- `false` \u2192 never redirect this environment, even when a certificate does\n exist\n\nRequests under `/.well-known/acme-challenge/` are never redirected\nregardless of this setting, so ACME HTTP-01 validation always completes." - }, - "idle_timeout_seconds": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Seconds of inactivity before stopping containers (60-86400). Default: 300." - }, - "memory_limit": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Maximum (limit) memory in MB. Send JSON `null` to clear \u2192 \"no limit\".\nAbsent leaves the current value unchanged." - }, - "memory_request": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Minimum (request) memory in MB. Send JSON `null` to clear (no request).\nAbsent leaves the current value unchanged." - }, - "on_demand": { - "type": [ - "boolean", - "null" - ], - "description": "Enable on-demand mode (scale-to-zero). Containers are stopped after\nidle_timeout_seconds of no traffic and started on the next request." - }, - "password": { - "type": [ - "string", - "null" - ], - "description": "Set a password to protect this environment. The proxy will show an HTML\npassword form before allowing access. The password is bcrypt-hashed\nserver-side and never stored in plaintext.\nSend an empty string to remove password protection." - }, - "performance_metrics_enabled": { - "type": [ - "boolean", - "null" - ], - "description": "Enable/disable performance metrics collection" - }, - "protected": { - "type": [ - "boolean", - "null" - ], - "description": "When true, git pushes do NOT auto-deploy to this environment.\nDeployments must be promoted from another environment." - }, - "replicas": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "security": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/SecurityConfig", - "description": "Security configuration for this environment (overrides project-level settings)" - } - ] - }, - "session_recording_enabled": { - "type": [ - "boolean", - "null" - ], - "description": "Enable/disable session recording" - }, - "target_labels": { - "description": "Label selector for node-based scheduling (overrides project-level setting).\nSame key with array value -> OR, different keys -> AND.\nExample: `{\"region\": [\"us\", \"asia\"], \"gpu\": \"true\"}`" - }, - "target_nodes": { - "type": [ - "array", - "null" - ], - "items": { - "type": "integer", - "format": "int32" - }, - "description": "Optional list of node IDs to deploy to (overrides project-level setting)" - }, - "wake_timeout_seconds": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Max seconds to wait for containers to start on wake (5-120). Default: 30." - } - } - }, - "UpdateEnvironmentSubdomainRequest": { - "type": "object", - "description": "Request to rename an environment's auto-managed subdomain.\n\nThe subdomain is the host label inserted in front of the platform's\npreview domain (e.g. `myapp` in `myapp.preview.temps.sh`). Renaming\nreplaces the previous subdomain entirely \u2014 the old hostname stops\nresolving immediately after this request succeeds.", - "required": [ - "subdomain" - ], - "properties": { - "subdomain": { - "type": "string", - "description": "New subdomain label. Must be a DNS-safe slug (lowercase letters,\ndigits, and hyphens, 1-63 characters). The value is slugified\nserver-side, so casing and disallowed characters are normalized.", - "example": "myapp" - } - } - }, - "UpdateEnvironmentVariableRequest": { - "type": "object", - "required": [ - "key", - "environment_ids" - ], - "properties": { - "environment_ids": { - "type": "array", - "items": { - "type": "integer", - "format": "int32" - } - }, - "include_in_preview": { - "type": "boolean" - }, - "is_secret": { - "type": [ - "boolean", - "null" - ], - "description": "Optional secret-flag transition.\n- `Some(true)` promotes a regular var to a secret.\n- `Some(false)` is rejected if the row is already secret (one-way flag).\n- `None` (omitted) leaves the flag unchanged." - }, - "key": { - "type": "string" - }, - "value": { - "type": [ - "string", - "null" - ], - "description": "New plaintext value. `None` (omitted) keeps the existing ciphertext,\nwhich is the only way to edit a secret env var without re-typing its\nvalue (e.g. changing which environments it applies to)." - } - } - }, - "UpdateErrorGroupRequest": { - "type": "object", - "required": [ - "status" - ], - "properties": { - "assigned_to": { - "type": [ - "string", - "null" - ] - }, - "status": { - "type": "string" - } - } - }, - "UpdateExternalServiceRequest": { - "type": "object", - "required": [ - "parameters" - ], - "properties": { - "docker_image": { - "type": [ - "string", - "null" - ], - "description": "Docker image to use for the service (e.g., \"gotempsh/postgres-walg:18-bookworm\", \"timescale/timescaledb-ha:pg18\")\nWhen provided, the service will be recreated with the new image while preserving data" - }, - "parameters": { - "type": "object", - "additionalProperties": {}, - "propertyNames": { - "type": "string" - } - } - } - }, - "UpdateFlagRequest": { - "type": "object", - "properties": { - "client_visible": { - "type": [ - "boolean", - "null" - ] - }, - "default_value": { - "description": "Must match the flag's existing `value_type`." - }, - "description": { - "type": [ - "string", - "null" - ], - "description": "Tri-state: absent leaves it, `null` clears it, a string sets it." - } - } - }, - "UpdateGitSettingsRequest": { - "type": "object", - "required": [ - "main_branch", - "repo_owner", - "repo_name", - "directory" - ], - "properties": { - "directory": { - "type": "string" - }, - "git_provider_connection_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "git_url": { - "type": [ - "string", - "null" - ], - "description": "Git clone URL for public repositories" - }, - "is_public_repo": { - "type": [ - "boolean", - "null" - ], - "description": "Whether this is a public repository (no git provider connection needed)" - }, - "main_branch": { - "type": "string" - }, - "preset": { - "type": [ - "string", - "null" - ] - }, - "preset_config": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/PresetConfigSchema", - "description": "Preset-specific configuration (e.g., Dockerfile path for Docker preset)\n\nExample for Dockerfile preset:\n```json\n{\n \"dockerfilePath\": \"docker/Dockerfile\",\n \"buildContext\": \"./api\"\n}\n```" - } - ] - }, - "repo_name": { - "type": "string" - }, - "repo_owner": { - "type": "string" - } - } - }, - "UpdateIncidentStatusRequest": { - "type": "object", - "required": [ - "status", - "message" - ], - "properties": { - "message": { - "type": "string" - }, - "status": { - "type": "string" - } - } - }, - "UpdateIpAccessControlRequest": { - "type": "object", - "description": "Request to update an IP access control rule", - "properties": { - "action": { - "type": [ - "string", - "null" - ], - "description": "Optional new action" - }, - "ip_address": { - "type": [ - "string", - "null" - ], - "description": "Optional new IP address" - }, - "reason": { - "type": [ - "string", - "null" - ], - "description": "Optional new reason" - } - } - }, - "UpdateKvRequest": { - "type": "object", - "description": "Request to update KV service configuration", - "properties": { - "docker_image": { - "type": [ - "string", - "null" - ], - "description": "Docker image to use (e.g., \"gotempsh/redis-walg:8-bookworm\")", - "example": "gotempsh/redis-walg:8-bookworm" - } - } - }, - "UpdateKvResponse": { - "type": "object", - "description": "Response after updating KV service", - "required": [ - "success", - "message", - "status" - ], - "properties": { - "message": { - "type": "string", - "description": "Status message", - "example": "KV service updated successfully" - }, - "status": { - "$ref": "#/components/schemas/KvStatusResponse", - "description": "Current service status" - }, - "success": { - "type": "boolean", - "description": "Whether the operation succeeded" - } - } - }, - "UpdateManagedDomainApiRequest": { - "type": "object", - "description": "Request to update a managed domain's settings.", - "properties": { - "auto_manage": { - "type": [ - "boolean", - "null" - ], - "description": "Toggle automatic DNS management for this domain." - }, - "generated_hostname_mode": { - "type": [ - "string", - "null" - ], - "description": "`\"standard\"` or `\"flat\"`. Persisted as-is; switching to `\"flat\"` does not\nrecompute existing hostnames \u2014 use the apply endpoint for that." - }, - "sync_generated_records": { - "type": [ - "boolean", - "null" - ], - "description": "Toggle DNS record sync for this domain." - } - } - }, - "UpdateMcpRequest": { - "type": "object", - "required": [ - "config" - ], - "properties": { - "config": { - "type": "object" - }, - "description": { - "type": [ - "string", - "null" - ] - }, - "name": { - "type": [ - "string", - "null" - ] - } - } - }, - "UpdateMemberRoleRequest": { - "type": "object", - "description": "The new fixed role for an existing membership.", - "required": [ - "role" - ], - "properties": { - "role": { - "$ref": "#/components/schemas/TeamRole" - } - } - }, - "UpdateMetricAlertRequest": { - "type": "object", - "properties": { - "aggregation": { - "type": [ - "string", - "null" - ] - }, - "detection_config": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/DetectionConfig", - "description": "Replaces the detector wholesale when present (absent = leave unchanged)." - } - ] - }, - "dynamic_alerts": { - "type": [ - "boolean", - "null" - ], - "description": "Toggles per-series (\"dynamic\") alerting (absent = leave unchanged)." - }, - "enabled": { - "type": [ - "boolean", - "null" - ] - }, - "for_duration_secs": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "group_by": { - "type": [ - "array", - "null" - ], - "items": { - "type": "string" - }, - "description": "Replaces the group_by keys wholesale when present (absent = leave unchanged)." - }, - "grouped_notification_threshold": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Updates the notification-grouping threshold (absent = leave unchanged)." - }, - "label_filters": { - "type": [ - "array", - "null" - ], - "items": { - "type": "array", - "items": false, - "prefixItems": [ - { - "type": "string" - }, - { - "type": "string" - } - ] - }, - "description": "Replaces the label filters wholesale when present (absent = leave unchanged)." - }, - "max_series": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Updates the dynamic-alerting cardinality cap (absent = leave unchanged)." - }, - "metric_name": { - "type": [ - "string", - "null" - ] - }, - "name": { - "type": [ - "string", - "null" - ] - }, - "severity": { - "type": [ - "string", - "null" - ] - }, - "window_secs": { - "type": [ - "integer", - "null" - ], - "format": "int32" - } - } - }, - "UpdateNotificationEmailProviderRequest": { - "type": "object", - "required": [ - "config" - ], - "properties": { - "config": { - "$ref": "#/components/schemas/EmailConfig" - }, - "enabled": { - "type": [ - "boolean", - "null" - ] - }, - "name": { - "type": [ - "string", - "null" - ] - } - } - }, - "UpdateOidcProviderRequest": { - "type": "object", - "properties": { - "client_id": { - "type": [ - "string", - "null" - ] - }, - "client_secret": { - "type": [ - "string", - "null" - ] - }, - "default_role": { - "type": [ - "string", - "null" - ] - }, - "enabled": { - "type": [ - "boolean", - "null" - ] - }, - "group_claim": { - "type": [ - "string", - "null" - ] - }, - "issuer_url": { - "type": [ - "string", - "null" - ] - }, - "jit_provisioning": { - "type": [ - "boolean", - "null" - ] - }, - "name": { - "type": [ - "string", - "null" - ] - }, - "role_claim": { - "type": [ - "string", - "null" - ] - }, - "scopes": { - "type": [ - "string", - "null" - ] - }, - "template": { - "type": [ - "string", - "null" - ] - }, - "trust_idp_email": { - "type": [ - "boolean", - "null" - ] - } - } - }, - "UpdatePreferencesRequest": { - "type": "object", - "required": [ - "preferences" - ], - "properties": { - "preferences": { - "$ref": "#/components/schemas/NotificationPreferencesResponse" - } - } - }, - "UpdateProjectSecretRequest": { - "type": "object", - "description": "Request to update a project secret. The `value` field is optional \u2014 omit it\nto rotate only the environment scoping / preview flag without touching the\nciphertext.", - "properties": { - "environment_ids": { - "type": "array", - "items": { - "type": "integer", - "format": "int32" - } - }, - "include_in_preview": { - "type": "boolean" - }, - "value": { - "type": [ - "string", - "null" - ], - "description": "New plaintext value, <= 1 MiB. Omit to keep the existing value." - } - } - }, - "UpdateProjectSettingsRequest": { - "type": "object", - "properties": { - "ai_alert_summaries_enabled": { - "type": [ - "boolean", - "null" - ], - "description": "Opt in to AI summarization of metric alert notifications (ADR-021)." - }, - "ai_debug_chat_enabled": { - "type": [ - "boolean", - "null" - ], - "description": "Opt in to AI debugging chat, e.g. on deployment failures (ADR-023)." - }, - "ai_write_actions_enabled": { - "type": [ - "boolean", - "null" - ], - "description": "Opt in to AI propose-then-confirm write capability." - }, - "attack_mode": { - "type": [ - "boolean", - "null" - ], - "description": "Enable/disable attack mode (CAPTCHA protection) for all project environments" - }, - "cross_project_trace_sharing": { - "type": [ - "boolean", - "null" - ], - "description": "ADR-027 Phase 3 opt-out: set to false to suppress this project's traces\nfrom appearing in cross-project discovery results. Default true (consistent\nwith the OSS global-observability model). Omit to leave unchanged." - }, - "directory": { - "type": [ - "string", - "null" - ] - }, - "enable_preview_environments": { - "type": [ - "boolean", - "null" - ], - "description": "Enable automatic preview environment creation for each branch" - }, - "error_source_context_enabled": { - "type": [ - "boolean", - "null" - ], - "description": "Opt in to native error-tracking source context (source-file upload +\nsource code shown in stack traces)." - }, - "error_source_root": { - "type": [ - "string", - "null" - ], - "description": "Set the auto-capture source root (relative to the checkout). Send an\nempty string to clear it back to the build-context default. Omit to\nleave unchanged." - }, - "git_provider_connection_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "main_branch": { - "type": [ - "string", - "null" - ] - }, - "preset": { - "type": [ - "string", - "null" - ] - }, - "preset_config": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/PresetConfigSchema", - "description": "Preset-specific configuration (e.g., Dockerfile path for Docker preset)\n\nExample for Dockerfile preset:\n```json\n{\n \"dockerfilePath\": \"docker/Dockerfile\",\n \"buildContext\": \"./api\"\n}\n```" - } - ] - }, - "preview_envs_idle_timeout_seconds": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Idle timeout (seconds, 60..=86400) for on-demand preview environments." - }, - "preview_envs_on_demand": { - "type": [ - "boolean", - "null" - ], - "description": "When true, newly-created preview environments default to on-demand mode." - }, - "preview_envs_wake_timeout_seconds": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Wake timeout (seconds, 5..=120) for on-demand preview environments." - }, - "repo_name": { - "type": [ - "string", - "null" - ] - }, - "repo_owner": { - "type": [ - "string", - "null" - ] - }, - "slug": { - "type": [ - "string", - "null" - ] - } - } - }, - "UpdateProviderCredentialsRequest": { - "type": "object", - "description": "Partial-update payload for provider credentials. Every field is optional;\nonly the fields the user re-enters are applied. The server validates that\nthe fields supplied make sense for the provider's current auth_method\n(e.g. `app_id` + `private_key` only apply to GitHub Apps).", - "properties": { - "app_id": { - "type": [ - "string", - "null" - ], - "description": "Application ID (GitHub App integer as string; GitLab App string)." - }, - "app_secret": { - "type": [ - "string", - "null" - ], - "description": "GitLab App secret (not used by GitHub App \u2014 use `client_secret`)." - }, - "client_id": { - "type": [ - "string", - "null" - ], - "description": "OAuth client ID (GitLab OAuth, GitHub App)." - }, - "client_secret": { - "type": [ - "string", - "null" - ], - "description": "OAuth client secret (GitLab OAuth, GitHub App)." - }, - "private_key": { - "type": [ - "string", - "null" - ], - "description": "GitHub App private key (PEM)." - }, - "redirect_uri": { - "type": [ - "string", - "null" - ], - "description": "OAuth redirect URI (GitLab OAuth / GitLab App)." - }, - "token": { - "type": [ - "string", - "null" - ], - "description": "PAT for PAT-type providers." - }, - "webhook_secret": { - "type": [ - "string", - "null" - ], - "description": "GitHub App webhook secret." - } - } - }, - "UpdateProviderKeyRequest": { - "type": "object", - "properties": { - "api_key": { - "type": [ - "string", - "null" - ] - }, - "base_url": { - "type": [ - "string", - "null" - ], - "description": "Double-Option: absent = leave unchanged, present-null = clear (revert to\nthe provider's default endpoint), present-value = set." - }, - "default_model": { - "type": [ - "string", - "null" - ], - "description": "Double-Option: absent = leave unchanged, present-null = clear the pinned\nmodel (revert to the per-provider default), present-value = set." - }, - "display_name": { - "type": [ - "string", - "null" - ] - }, - "is_active": { - "type": [ - "boolean", - "null" - ] - } - } - }, - "UpdateProviderRequest": { - "type": "object", - "properties": { - "config": {}, - "enabled": { - "type": [ - "boolean", - "null" - ] - }, - "name": { - "type": [ - "string", - "null" - ] - } - } - }, - "UpdateRouteRequest": { - "type": "object", - "required": [ - "host", - "port", - "enabled" - ], - "properties": { - "enabled": { - "type": "boolean" - }, - "host": { - "type": "string" - }, - "port": { - "type": "integer", - "format": "int32" - }, - "route_type": { - "type": [ - "string", - "null" - ], - "description": "Route type: \"http\" (default) matches on HTTP Host header,\n\"tls\" matches on TLS SNI hostname for TCP passthrough" - } - } - }, - "UpdateS3SourceRequest": { - "type": "object", - "properties": { - "access_key_id": { - "type": [ - "string", - "null" - ], - "description": "Optional new access key ID", - "example": "AKIAXXXXXXXXXXXXXXXX" - }, - "bucket_name": { - "type": [ - "string", - "null" - ], - "description": "Optional new bucket name" - }, - "bucket_path": { - "type": [ - "string", - "null" - ], - "description": "Optional new bucket path" - }, - "endpoint": { - "type": [ - "string", - "null" - ], - "description": "Optional new endpoint URL for S3-compatible services", - "example": "http://minio.example.com:9000" - }, - "force_path_style": { - "type": [ - "boolean", - "null" - ], - "description": "Optional new path-style addressing setting", - "example": true - }, - "name": { - "type": [ - "string", - "null" - ], - "description": "Optional new name for the source" - }, - "region": { - "type": [ - "string", - "null" - ], - "description": "Optional new region" - }, - "secret_key": { - "type": [ - "string", - "null" - ], - "description": "Optional new secret key" - } - } - }, - "UpdateSecretBody": { - "type": "object", - "required": [ - "signing_secret" - ], - "properties": { - "signing_secret": { - "type": "string", - "description": "New signing secret from the provider's dashboard. Encrypted at\nrest; never returned in any API response." - } - } - }, - "UpdateSelfRequest": { - "type": "object", - "properties": { - "email": { - "type": [ - "string", - "null" - ], - "example": "john.doe@example.com" - }, - "name": { - "type": [ - "string", - "null" - ], - "example": "John Doe" - } - } - }, - "UpdateSessionDurationRequest": { - "type": "object", - "required": [ - "duration" - ], - "properties": { - "duration": { - "type": "integer", - "format": "int32" - } - } - }, - "UpdateSessionDurationResponse": { - "type": "object", - "required": [ - "message" - ], - "properties": { - "message": { - "type": "string" - } - } - }, - "UpdateSkillRequest": { - "type": "object", - "properties": { - "content": { - "type": [ - "string", - "null" - ] - }, - "description": { - "type": [ - "string", - "null" - ] - }, - "name": { - "type": [ - "string", - "null" - ] - } - } - }, - "UpdateSlackProviderRequest": { - "type": "object", - "required": [ - "config" - ], - "properties": { - "config": { - "$ref": "#/components/schemas/SlackConfig" - }, - "enabled": { - "type": [ - "boolean", - "null" - ] - }, - "name": { - "type": [ - "string", - "null" - ] - } - } - }, - "UpdateSpeedMetricsPayload": { - "type": "object", - "description": "Update speed metrics payload for late-loading metrics", - "properties": { - "cls": { - "type": [ - "number", - "null" - ], - "format": "float", - "description": "Cumulative Layout Shift (score)" - }, - "inp": { - "type": [ - "number", - "null" - ], - "format": "float", - "description": "Interaction to Next Paint (milliseconds)" - } - } - }, - "UpdateStatusResponse": { - "type": "object", - "description": "Result of the background release-update check, driving the web console's\nupgrade banner. All optional fields are set together iff\n`update_available` is true.", - "required": [ - "update_available", - "docs_url" - ], - "properties": { - "channel": { - "type": [ - "string", - "null" - ], - "description": "Channel the install tracks: `stable` or `beta`." - }, - "checked_at": { - "type": [ - "string", - "null" - ], - "description": "When the check that found the update ran (ISO 8601, UTC)." - }, - "current_version": { - "type": [ - "string", - "null" - ], - "description": "Version tag of the running binary, e.g. `v0.1.0-beta.45`." - }, - "docs_url": { - "type": "string", - "description": "Docs page with upgrade instructions. Always present so the UI links\nthe same page regardless of update state." - }, - "latest_version": { - "type": [ - "string", - "null" - ], - "description": "Newest published tag on this install's channel." - }, - "release_url": { - "type": [ - "string", - "null" - ], - "description": "Release-notes page (GitHub release) for the newer version." - }, - "update_available": { - "type": "boolean", - "description": "True when a newer release than the running binary has been published\non this install's channel." - } - } - }, - "UpdateTeamRequest": { - "type": "object", - "properties": { - "description": { - "type": [ - "string", - "null" - ] - }, - "name": { - "type": [ - "string", - "null" - ] - } - } - }, - "UpdateTokenRequest": { - "type": "object", - "required": [ - "access_token" - ], - "properties": { - "access_token": { - "type": "string" - }, - "refresh_token": { - "type": [ - "string", - "null" - ] - } - } - }, - "UpdateTokenResponse": { - "type": "object", - "required": [ - "connection_id", - "message", - "is_active" - ], - "properties": { - "connection_id": { - "type": "integer", - "format": "int32" - }, - "is_active": { - "type": "boolean" - }, - "message": { - "type": "string" - } - } - }, - "UpdateUserRequest": { - "type": "object", - "properties": { - "email": { - "type": [ - "string", - "null" - ], - "example": "john.doe@example.com" - }, - "name": { - "type": [ - "string", - "null" - ], - "example": "John Doe" - } - } - }, - "UpdateWebhookProviderRequest": { - "type": "object", - "required": [ - "config" - ], - "properties": { - "config": { - "$ref": "#/components/schemas/WebhookConfig" - }, - "enabled": { - "type": [ - "boolean", - "null" - ] - }, - "name": { - "type": [ - "string", - "null" - ] - } - } - }, - "UpdateWebhookRequestBody": { - "type": "object", - "properties": { - "enabled": { - "type": [ - "boolean", - "null" - ], - "description": "Whether the webhook is enabled" - }, - "events": { - "type": [ - "array", - "null" - ], - "items": { - "type": "string" - }, - "description": "Event types to subscribe to" - }, - "secret": { - "type": [ - "string", - "null" - ], - "description": "Secret for HMAC signature verification" - }, - "url": { - "type": [ - "string", - "null" - ], - "description": "Target URL for webhook delivery" - } - } - }, - "UpgradeExternalServiceRequest": { - "type": "object", - "required": [ - "docker_image" - ], - "properties": { - "docker_image": { - "type": "string", - "description": "Docker image to upgrade to (e.g., \"gotempsh/postgres-walg:18-bookworm\")\nThis will trigger pg_upgrade for PostgreSQL or equivalent upgrade procedures for other services", - "example": "gotempsh/postgres-walg:18-bookworm" - } - } - }, - "UpgradeRequest": { - "type": "object", - "required": [ - "image" - ], - "properties": { - "image": { - "type": "string", - "description": "Image reference to pull and run (e.g.\n`ghcr.io/gotempsh/temps-preview-gateway:latest`). Empty resets to default." - } - } - }, - "UpsertAgentRequest": { - "type": "object", - "properties": { - "ai_model": { - "type": [ - "string", - "null" - ], - "description": "Preferred model identifier for the CLI. `Some(\"\")` clears the stored value." - }, - "ai_provider": { - "type": [ - "string", - "null" - ] - }, - "ai_provider_key_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "api_key": { - "type": [ - "string", - "null" - ], - "description": "Plain-text API key \u2014 will be encrypted before storage" - }, - "branch_prefix": { - "type": [ - "string", - "null" - ] - }, - "config_repo_branch": { - "type": [ - "string", - "null" - ], - "description": "Branch of the config repo to use (default: \"main\")." - }, - "config_repo_url": { - "type": [ - "string", - "null" - ], - "description": "Private config repo containing .claude/ directory (skills, MCP, plugins)." - }, - "cooldown_minutes": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "daily_budget_cents": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "deliverable": { - "type": [ - "string", - "null" - ] - }, - "description": { - "type": [ - "string", - "null" - ] - }, - "enabled": { - "type": [ - "boolean", - "null" - ] - }, - "max_turns": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "mcp_servers_config": { - "description": "MCP servers config (Claude Code settings.json mcpServers format).\nCredential-bearing legacy inline objects are write-only: normal reads\nmask them, and updates must omit this field to preserve existing values." - }, - "name": { - "type": [ - "string", - "null" - ] - }, - "prompt": { - "type": [ - "string", - "null" - ] - }, - "sandbox_enabled": { - "type": [ - "boolean", - "null" - ] - }, - "skills_config": { - "description": "Skills config as JSON array." - }, - "slug": { - "type": [ - "string", - "null" - ] - }, - "timeout_seconds": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "tools_config": { - "description": "Tools config as JSON array. Custom-tool webhook URLs and headers are\nwrite-only; omit this field on update to preserve them." - }, - "trigger_config": { - "description": "Trigger configuration JSON: { \"error\": { \"new_issue\": true, \"regression\": true }, \"manual\": true }" - } - } - }, - "UpsertSecretRequest": { - "type": "object", - "required": [ - "name", - "value" - ], - "properties": { - "description": { - "type": [ - "string", - "null" - ] - }, - "mount_path": { - "type": [ - "string", - "null" - ], - "description": "Required for \"file\" type secrets \u2014 absolute path inside the sandbox" - }, - "name": { - "type": "string" - }, - "secret_type": { - "type": "string", - "description": "\"env\" (environment variable) or \"file\" (written to mount_path)" - }, - "value": { - "type": "string" - } - } - }, - "UptimeDataPoint": { - "type": "object", - "required": [ - "timestamp", - "status" - ], - "properties": { - "error_message": { - "type": [ - "string", - "null" - ] - }, - "response_time_ms": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "status": { - "type": "string" - }, - "timestamp": { - "type": "string", - "format": "date-time" - } - } - }, - "UptimeHistoryResponse": { - "type": "object", - "required": [ - "monitor_id", - "uptime_data" - ], - "properties": { - "monitor_id": { - "type": "integer", - "format": "int32" - }, - "uptime_data": { - "type": "array", - "items": { - "$ref": "#/components/schemas/UptimeDataPoint" - } - } - } - }, - "UsageFilter": { - "type": "object", - "description": "Filters for querying AI usage data.\n\nCost bounds are expressed in microcents (the unit stored in\n`estimated_cost_microcents`). At most one of `gte`/`gt` and one of\n`lte`/`lt` is meaningful per query; if both are set the stricter wins\nnaturally because they are ANDead together.", - "properties": { - "conversation_id": { - "type": [ - "string", - "null" - ] - }, - "cost_gt": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "description": "Cost strictly greater-than, in microcents." - }, - "cost_gte": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "description": "Cost greater-than-or-equal, in microcents." - }, - "cost_lt": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "description": "Cost strictly less-than, in microcents." - }, - "cost_lte": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "description": "Cost less-than-or-equal, in microcents." - }, - "model": { - "type": [ - "string", - "null" - ] - }, - "provider": { - "type": [ - "string", - "null" - ] - }, - "status": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Filter by HTTP status code (exact match)." - }, - "tags": { - "type": [ - "string", - "null" - ], - "description": "Comma-separated tags to filter by (AND logic)." - }, - "tokens_gt": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "description": "Total tokens (input + output) strictly greater-than." - }, - "tokens_gte": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "description": "Total tokens (input + output) greater-than-or-equal." - }, - "tokens_lt": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "description": "Total tokens (input + output) strictly less-than." - }, - "tokens_lte": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "description": "Total tokens (input + output) less-than-or-equal." - }, - "user_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - } - } - }, - "UsageInfo": { - "type": "object", - "required": [ - "prompt_tokens", - "completion_tokens", - "total_tokens" - ], - "properties": { - "completion_tokens": { - "type": "integer", - "format": "int64" - }, - "prompt_tokens": { - "type": "integer", - "format": "int64" - }, - "total_tokens": { - "type": "integer", - "format": "int64" - } - } - }, - "UsageLogEntry": { - "type": "object", - "required": [ - "id", - "timestamp", - "provider", - "model", - "input_tokens", - "output_tokens", - "latency_ms", - "estimated_cost_microcents", - "status", - "is_streaming", - "is_byok", - "tags" - ], - "properties": { - "conversation_id": { - "type": [ - "string", - "null" - ] - }, - "estimated_cost_microcents": { - "type": "integer", - "format": "int64" - }, - "id": { - "type": "integer", - "format": "int64" - }, - "input_tokens": { - "type": "integer", - "format": "int64" - }, - "is_byok": { - "type": "boolean" - }, - "is_streaming": { - "type": "boolean" - }, - "latency_ms": { - "type": "integer", - "format": "int32" - }, - "model": { - "type": "string" - }, - "output_tokens": { - "type": "integer", - "format": "int64" - }, - "provider": { - "type": "string" - }, - "request_id": { - "type": [ - "string", - "null" - ] - }, - "status": { - "type": "integer", - "format": "int32" - }, - "tags": { - "type": "array", - "items": { - "type": "string" - } - }, - "timestamp": { - "type": "string" - }, - "trace_id": { - "type": [ - "string", - "null" - ] - } - } - }, - "UsageLogPage": { - "type": "object", - "description": "A page of recent usage log entries plus the total count for pagination.", - "required": [ - "entries", - "total" - ], - "properties": { - "entries": { - "type": "array", - "items": { - "$ref": "#/components/schemas/UsageLogEntry" - }, - "description": "The usage log entries for the requested page." - }, - "total": { - "type": "integer", - "format": "int64", - "description": "Total number of entries matching the filter (across all pages)." - } - } - }, - "UsageQueryParams": { - "type": "object", - "properties": { - "conversation_id": { - "type": [ - "string", - "null" - ], - "description": "Filter by conversation ID" - }, - "from": { - "type": [ - "string", - "null" - ], - "description": "ISO 8601 start time (defaults to 24h ago)" - }, - "model": { - "type": [ - "string", - "null" - ], - "description": "Filter by model name" - }, - "provider": { - "type": [ - "string", - "null" - ], - "description": "Filter by provider name" - }, - "tags": { - "type": [ - "string", - "null" - ], - "description": "Filter by tags (comma-separated, AND logic)" - }, - "to": { - "type": [ - "string", - "null" - ], - "description": "ISO 8601 end time (defaults to now)" - }, - "user_id": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Filter by user ID" - } - } - }, - "UsageSource": { - "type": "string", - "description": "How the \"actual usage\" numbers were obtained", - "enum": [ - "metrics-api", - "requests-only", - "unavailable" - ] - }, - "UsageSummary": { - "type": "object", - "required": [ - "total_requests", - "total_input_tokens", - "total_output_tokens", - "total_tokens", - "avg_latency_ms", - "total_cost_microcents", - "error_count", - "streaming_count", - "byok_count" - ], - "properties": { - "avg_latency_ms": { - "type": "number", - "format": "double" - }, - "byok_count": { - "type": "integer", - "format": "int64" - }, - "error_count": { - "type": "integer", - "format": "int64" - }, - "streaming_count": { - "type": "integer", - "format": "int64" - }, - "total_cost_microcents": { - "type": "integer", - "format": "int64" - }, - "total_input_tokens": { - "type": "integer", - "format": "int64" - }, - "total_output_tokens": { - "type": "integer", - "format": "int64" - }, - "total_requests": { - "type": "integer", - "format": "int64" - }, - "total_tokens": { - "type": "integer", - "format": "int64" - } - } - }, - "UserResponse": { - "type": "object", - "required": [ - "id", - "username", - "name", - "avatar_url", - "mfa_enabled", - "role" - ], - "properties": { - "avatar_url": { - "type": "string" - }, - "email": { - "type": [ - "string", - "null" - ] - }, - "id": { - "type": "integer", - "format": "int32" - }, - "mfa_enabled": { - "type": "boolean" - }, - "name": { - "type": "string" - }, - "role": { - "type": "string", - "description": "User's role (e.g., \"admin\", \"user\", \"demo\")" - }, - "username": { - "type": "string" - } - } - }, - "ValidateEmailRequest": { - "type": "object", - "description": "Request body for validating an email address", - "required": [ - "email" - ], - "properties": { - "email": { - "type": "string", - "description": "Email address to validate", - "example": "someone@gmail.com" - } - }, - "additionalProperties": false - }, - "ValidateEmailResponse": { - "type": "object", - "description": "Complete email validation response", - "required": [ - "email", - "is_reachable", - "syntax", - "mx", - "misc", - "smtp" - ], - "properties": { - "email": { - "type": "string", - "description": "The email address that was validated", - "example": "someone@gmail.com" - }, - "is_reachable": { - "$ref": "#/components/schemas/ReachabilityStatus", - "description": "Overall reachability status: safe, risky, invalid, or unknown" - }, - "misc": { - "$ref": "#/components/schemas/MiscResult", - "description": "Miscellaneous validation result" - }, - "mx": { - "$ref": "#/components/schemas/MxResult", - "description": "MX record validation result" - }, - "smtp": { - "$ref": "#/components/schemas/SmtpResult", - "description": "SMTP validation result" - }, - "syntax": { - "$ref": "#/components/schemas/SyntaxResult", - "description": "Syntax validation result" - } - } - }, - "ValidationLevel": { - "type": "string", - "description": "Validation severity level", - "enum": [ - "info", - "warning", - "error", - "critical" - ] - }, - "ValidationReport": { - "type": "object", - "description": "Complete validation report", - "required": [ - "results", - "overall_status", - "summary" - ], - "properties": { - "overall_status": { - "$ref": "#/components/schemas/ValidationStatus", - "description": "Overall status" - }, - "results": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ValidationResult" - }, - "description": "All validation results" - }, - "summary": { - "$ref": "#/components/schemas/ValidationSummary", - "description": "Summary statistics" - } - } - }, - "ValidationResponse": { - "type": "object", - "required": [ - "connection_id", - "is_valid", - "message" - ], - "properties": { - "connection_id": { - "type": "integer", - "format": "int32" - }, - "is_valid": { - "type": "boolean" - }, - "message": { - "type": "string" - } - } - }, - "ValidationResult": { - "type": "object", - "description": "Result of a validation check", - "required": [ - "rule_id", - "rule_name", - "level", - "passed", - "message", - "affected_resources" - ], - "properties": { - "affected_resources": { - "type": "array", - "items": { - "type": "string" - }, - "description": "Affected resources/fields" - }, - "level": { - "$ref": "#/components/schemas/ValidationLevel", - "description": "Validation level" - }, - "message": { - "type": "string", - "description": "Message describing the result" - }, - "passed": { - "type": "boolean", - "description": "Whether the validation passed" - }, - "remediation": { - "type": [ - "string", - "null" - ], - "description": "Suggested remediation (if failed)" - }, - "rule_id": { - "type": "string", - "description": "Rule that was checked" - }, - "rule_name": { - "type": "string", - "description": "Human-readable rule name" - } - } - }, - "ValidationStatus": { - "type": "string", - "description": "Overall validation status", - "enum": [ - "passed", - "passed-with-warnings", - "failed-with-warnings", - "failed" - ] - }, - "ValidationSummary": { - "type": "object", - "description": "Validation summary statistics", - "required": [ - "total_count", - "passed_count", - "failed_count", - "info_count", - "warning_count", - "error_count", - "critical_count" - ], - "properties": { - "critical_count": { - "type": "integer", - "description": "Critical-level results", - "minimum": 0 - }, - "error_count": { - "type": "integer", - "description": "Error-level results", - "minimum": 0 - }, - "failed_count": { - "type": "integer", - "description": "Validations that failed", - "minimum": 0 - }, - "info_count": { - "type": "integer", - "description": "Info-level results", - "minimum": 0 - }, - "passed_count": { - "type": "integer", - "description": "Validations that passed", - "minimum": 0 - }, - "total_count": { - "type": "integer", - "description": "Total validations run", - "minimum": 0 - }, - "warning_count": { - "type": "integer", - "description": "Warning-level results", - "minimum": 0 - } - } - }, - "VerifyMfaRequest": { - "type": "object", - "required": [ - "code" - ], - "properties": { - "code": { - "type": "string" - } - } - }, - "VerifyStepUpRequest": { - "type": "object", - "required": [ - "code" - ], - "properties": { - "code": { - "type": "string", - "description": "Current TOTP value or an unused recovery code." - } - } - }, - "ViewItem": { - "type": "object", - "required": [ - "label", - "value" - ], - "properties": { - "label": { - "type": "string", - "format": "date-time" - }, - "value": { - "type": "integer", - "format": "int64" - } - } - }, - "ViewsOverTime": { - "type": "object", - "required": [ - "items", - "metric", - "present_index" - ], - "properties": { - "comparison_labels": { - "type": [ - "array", - "null" - ], - "items": { - "type": "string" - } - }, - "comparison_plot": { - "type": [ - "array", - "null" - ], - "items": { - "type": "integer", - "format": "int64" - } - }, - "full_intervals": { - "type": [ - "array", - "null" - ], - "items": { - "type": "string" - } - }, - "items": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ViewItem" - } - }, - "metric": { - "type": "string" - }, - "present_index": { - "type": "integer", - "minimum": 0 - } - } - }, - "ViewsOverTimeQuery": { - "type": "object", - "required": [ - "start_date", - "end_date", - "project_id" - ], - "properties": { - "deployment_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "end_date": { - "type": "string", - "format": "date-time" - }, - "environment_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "project_id": { - "type": "integer", - "format": "int32" - }, - "start_date": { - "type": "string", - "format": "date-time" - } - } - }, - "VisitorDetails": { - "type": "object", - "required": [ - "id", - "visitor_id", - "project_id", - "environment_id", - "first_seen", - "last_seen", - "is_crawler" - ], - "properties": { - "city": { - "type": [ - "string", - "null" - ] - }, - "country": { - "type": [ - "string", - "null" - ] - }, - "country_code": { - "type": [ - "string", - "null" - ] - }, - "crawler_name": { - "type": [ - "string", - "null" - ] - }, - "custom_data": {}, - "environment_id": { - "type": "integer", - "format": "int32" - }, - "first_channel": { - "type": [ - "string", - "null" - ], - "description": "Marketing channel from the first visit (e.g. \"Organic Search\", \"Direct\")" - }, - "first_referrer": { - "type": [ - "string", - "null" - ], - "description": "Full referrer URL from the visitor's first session" - }, - "first_referrer_hostname": { - "type": [ - "string", - "null" - ], - "description": "Hostname extracted from first_referrer" - }, - "first_seen": { - "type": "string", - "format": "date-time", - "example": "2024-01-01T00:00:00" - }, - "id": { - "type": "integer", - "format": "int32" - }, - "ip_address": { - "type": [ - "string", - "null" - ] - }, - "ip_address_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "is_crawler": { - "type": "boolean" - }, - "is_eu": { - "type": [ - "boolean", - "null" - ] - }, - "last_seen": { - "type": "string", - "format": "date-time", - "example": "2024-01-01T00:00:00" - }, - "latitude": { - "type": [ - "number", - "null" - ], - "format": "double" - }, - "longitude": { - "type": [ - "number", - "null" - ], - "format": "double" - }, - "project_id": { - "type": "integer", - "format": "int32" - }, - "region": { - "type": [ - "string", - "null" - ] - }, - "timezone": { - "type": [ - "string", - "null" - ] - }, - "user_agent": { - "type": [ - "string", - "null" - ] - }, - "visitor_id": { - "type": "string" - } - } - }, - "VisitorFacetValue": { - "type": "object", - "description": "A single facet value with its visitor count. Used to populate filter\ndropdowns on the visitors page (e.g. \"Germany \u2014 1,234 visitors\").", - "required": [ - "value", - "count" - ], - "properties": { - "code": { - "type": [ - "string", - "null" - ], - "description": "Optional secondary code for the value. Currently only populated for\nthe `country` facet, where it carries the 2-letter ISO country code\nso the UI can render a flag without re-mapping." - }, - "count": { - "type": "integer", - "format": "int64", - "description": "Distinct visitor count matching this value in the current segment." - }, - "value": { - "type": "string", - "description": "The dimension value (e.g. \"United States\", \"Chrome\", \"google.com\").\n`None` is encoded as the literal string \"Direct\" for referrer and as\nthe empty string for the rest." - } - } - }, - "VisitorFacets": { - "type": "object", - "description": "All filter dropdown contents in one response. Each list is the top N\nvalues for that dimension within the current date range and segment\n(excluding the dimension being queried so the dropdown still shows\nalternatives when a value is already selected).", - "required": [ - "country", - "region", - "city", - "channel", - "referrer" - ], - "properties": { - "channel": { - "type": "array", - "items": { - "$ref": "#/components/schemas/VisitorFacetValue" - } - }, - "city": { - "type": "array", - "items": { - "$ref": "#/components/schemas/VisitorFacetValue" - } - }, - "country": { - "type": "array", - "items": { - "$ref": "#/components/schemas/VisitorFacetValue" - } - }, - "referrer": { - "type": "array", - "items": { - "$ref": "#/components/schemas/VisitorFacetValue" - } - }, - "region": { - "type": "array", - "items": { - "$ref": "#/components/schemas/VisitorFacetValue" - } - } - } - }, - "VisitorFacetsQuery": { - "allOf": [ - { - "$ref": "#/components/schemas/VisitorSegmentFilters" - }, - { - "type": "object", - "required": [ - "start_date", - "end_date", - "project_id" - ], - "properties": { - "end_date": { - "type": "string", - "format": "date-time" - }, - "environment_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "has_activity_only": { - "type": [ - "boolean", - "null" - ] - }, - "include_crawlers": { - "type": [ - "boolean", - "null" - ] - }, - "per_facet_limit": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Maximum number of values returned per dimension (default: 50, max: 200)." - }, - "project_id": { - "type": "integer", - "format": "int32" - }, - "start_date": { - "type": "string", - "format": "date-time" - } - } - } - ], - "description": "Query parameters for the visitor-facets endpoint. Mirrors the shape of\n`VisitorsListQuery` so the same segment filters apply \u2014 facet counts are\nalways computed against the *currently filtered* visitor pool, minus the\ndimension being aggregated." - }, - "VisitorInfo": { - "type": "object", - "required": [ - "id", - "visitor_id", - "project_id", - "environment_id", - "first_seen", - "last_seen", - "is_crawler" - ], - "properties": { - "city": { - "type": [ - "string", - "null" - ] - }, - "country": { - "type": [ - "string", - "null" - ] - }, - "country_code": { - "type": [ - "string", - "null" - ] - }, - "crawler_name": { - "type": [ - "string", - "null" - ] - }, - "current_page": { - "type": [ - "string", - "null" - ], - "description": "Most recent page path visited by this visitor" - }, - "custom_data": {}, - "environment_id": { - "type": "integer", - "format": "int32" - }, - "first_channel": { - "type": [ - "string", - "null" - ], - "description": "Marketing channel from the first visit (e.g. \"Organic Search\", \"Direct\")" - }, - "first_referrer": { - "type": [ - "string", - "null" - ], - "description": "Full referrer URL from the visitor's first session" - }, - "first_referrer_hostname": { - "type": [ - "string", - "null" - ], - "description": "Hostname extracted from first_referrer" - }, - "first_seen": { - "type": "string", - "format": "date-time", - "example": "2024-01-01T00:00:00" - }, - "id": { - "type": "integer", - "format": "int32" - }, - "ip_address": { - "type": [ - "string", - "null" - ] - }, - "ip_address_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "is_crawler": { - "type": "boolean" - }, - "is_eu": { - "type": [ - "boolean", - "null" - ] - }, - "last_seen": { - "type": "string", - "format": "date-time", - "example": "2024-01-01T00:00:00" - }, - "latitude": { - "type": [ - "number", - "null" - ], - "format": "double" - }, - "longitude": { - "type": [ - "number", - "null" - ], - "format": "double" - }, - "project_id": { - "type": "integer", - "format": "int32" - }, - "region": { - "type": [ - "string", - "null" - ] - }, - "timezone": { - "type": [ - "string", - "null" - ] - }, - "user_agent": { - "type": [ - "string", - "null" - ] - }, - "visitor_id": { - "type": "string" - } - } - }, - "VisitorJourneyQuery": { - "type": "object", - "required": [ - "project_id" - ], - "properties": { - "limit_sessions": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "project_id": { - "type": "integer", - "format": "int32" - } - } - }, - "VisitorJourneyResponse": { - "type": "object", - "description": "Complete visitor journey response", - "required": [ - "visitor_id", - "total_sessions", - "total_events", - "sessions" - ], - "properties": { - "sessions": { - "type": "array", - "items": { - "$ref": "#/components/schemas/JourneySession" - }, - "description": "Sessions with their events, ordered newest first" - }, - "total_events": { - "type": "integer", - "format": "int64", - "description": "Total number of events across all sessions" - }, - "total_sessions": { - "type": "integer", - "format": "int64", - "description": "Total number of sessions" - }, - "visitor_id": { - "type": "integer", - "format": "int32", - "description": "Visitor internal ID" - } - } - }, - "VisitorLocationsQuery": { - "type": "object", - "required": [ - "start_date", - "end_date", - "project_id" - ], - "properties": { - "end_date": { - "type": "string", - "format": "date-time" - }, - "environment_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "granularity": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/components/schemas/LocationGranularity" - } - ] - }, - "limit": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "project_id": { - "type": "integer", - "format": "int32" - }, - "start_date": { - "type": "string", - "format": "date-time" - } - } - }, - "VisitorRecord": { - "type": "object", - "required": [ - "id", - "visitor_id", - "project_id", - "created_at" - ], - "properties": { - "created_at": { - "type": "string", - "format": "date-time", - "example": "2024-01-01T00:00:00" - }, - "custom_data": {}, - "id": { - "type": "integer", - "format": "int32" - }, - "project_id": { - "type": "integer", - "format": "int32" - }, - "visitor_id": { - "type": "string" - } - } - }, - "VisitorSegmentFilters": { - "type": "object", - "description": "Optional segment filters for [`VisitorsListQuery`]. Each filter narrows the\nresult set to visitors who match the given dimension value within the date\nrange. All filters resolve against `visitor` / `ip_geolocations` \u2014 by\ndesign we never touch the events hypertable here so filtering stays fast\nregardless of event volume.", - "properties": { - "filter_channel": { - "type": [ - "string", - "null" - ], - "description": "First-touch marketing channel (matches `visitor.first_channel`)" - }, - "filter_city": { - "type": [ - "string", - "null" - ], - "description": "Geolocation city (matches `ip_geolocations.city`)" - }, - "filter_country": { - "type": [ - "string", - "null" - ], - "description": "Geolocation country (matches `ip_geolocations.country`)" - }, - "filter_referrer": { - "type": [ - "string", - "null" - ], - "description": "First-touch referrer hostname (matches `visitor.first_referrer_hostname`)" - }, - "filter_region": { - "type": [ - "string", - "null" - ], - "description": "Geolocation region (matches `ip_geolocations.region`)" - } - } - }, - "VisitorSessionsQuery": { - "type": "object", - "required": [ - "project_id" - ], - "properties": { - "environment_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "limit": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "project_id": { - "type": "integer", - "format": "int32" - } - } - }, - "VisitorSessionsResponse": { - "type": "object", - "required": [ - "visitor_id", - "sessions", - "total_sessions" - ], - "properties": { - "sessions": { - "type": "array", - "items": { - "$ref": "#/components/schemas/SessionSummary" - } - }, - "total_sessions": { - "type": "integer", - "format": "int64" - }, - "visitor_id": { - "type": "string" - } - } - }, - "VisitorStats": { - "type": "object", - "required": [ - "visitor_id", - "first_seen", - "last_seen", - "total_sessions", - "total_page_views", - "total_events", - "average_session_duration", - "bounce_rate", - "engagement_rate", - "top_pages", - "top_referrers", - "devices_used", - "locations" - ], - "properties": { - "average_session_duration": { - "type": "number", - "format": "double" - }, - "bounce_rate": { - "type": "number", - "format": "double" - }, - "devices_used": { - "type": "array", - "items": { - "type": "string" - } - }, - "engagement_rate": { - "type": "number", - "format": "double" - }, - "first_seen": { - "type": "string", - "format": "date-time", - "example": "2024-01-01T00:00:00" - }, - "last_seen": { - "type": "string", - "format": "date-time", - "example": "2024-01-01T00:00:00" - }, - "locations": { - "type": "array", - "items": { - "$ref": "#/components/schemas/LocationInfo" - } - }, - "top_pages": { - "type": "array", - "items": { - "$ref": "#/components/schemas/PageVisit" - } - }, - "top_referrers": { - "type": "array", - "items": { - "type": "string" - } - }, - "total_events": { - "type": "integer", - "format": "int64" - }, - "total_page_views": { - "type": "integer", - "format": "int64" - }, - "total_sessions": { - "type": "integer", - "format": "int64" - }, - "visitor_id": { - "type": "integer", - "format": "int32" - } - } - }, - "VisitorWithGeolocation": { - "type": "object", - "required": [ - "id", - "visitor_id", - "project_id", - "environment_id", - "first_seen", - "last_seen", - "is_crawler" - ], - "properties": { - "city": { - "type": [ - "string", - "null" - ] - }, - "country": { - "type": [ - "string", - "null" - ] - }, - "country_code": { - "type": [ - "string", - "null" - ] - }, - "crawler_name": { - "type": [ - "string", - "null" - ] - }, - "custom_data": {}, - "environment_id": { - "type": "integer", - "format": "int32" - }, - "first_channel": { - "type": [ - "string", - "null" - ], - "description": "Marketing channel from the first visit (e.g. \"Organic Search\", \"Direct\")" - }, - "first_referrer": { - "type": [ - "string", - "null" - ], - "description": "Full referrer URL from the visitor's first session" - }, - "first_referrer_hostname": { - "type": [ - "string", - "null" - ], - "description": "Hostname extracted from first_referrer" - }, - "first_seen": { - "type": "string", - "format": "date-time", - "example": "2024-01-01T00:00:00" - }, - "id": { - "type": "integer", - "format": "int32" - }, - "ip_address": { - "type": [ - "string", - "null" - ] - }, - "is_crawler": { - "type": "boolean" - }, - "is_eu": { - "type": [ - "boolean", - "null" - ] - }, - "last_seen": { - "type": "string", - "format": "date-time", - "example": "2024-01-01T00:00:00" - }, - "latitude": { - "type": [ - "number", - "null" - ], - "format": "double" - }, - "longitude": { - "type": [ - "number", - "null" - ], - "format": "double" - }, - "project_id": { - "type": "integer", - "format": "int32" - }, - "region": { - "type": [ - "string", - "null" - ] - }, - "timezone": { - "type": [ - "string", - "null" - ] - }, - "user_agent": { - "type": [ - "string", - "null" - ] - }, - "visitor_id": { - "type": "string" - } - } - }, - "VisitorsListQuery": { - "allOf": [ - { - "$ref": "#/components/schemas/VisitorSegmentFilters" - }, - { - "type": "object", - "required": [ - "start_date", - "end_date", - "project_id" - ], - "properties": { - "end_date": { - "type": "string", - "format": "date-time" - }, - "environment_id": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "has_activity_only": { - "type": [ - "boolean", - "null" - ], - "description": "Filter to only include visitors with recorded activity (events/sessions).\nWhen true, excludes \"ghost\" visitors that have no events." - }, - "include_crawlers": { - "type": [ - "boolean", - "null" - ] - }, - "limit": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "offset": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "project_id": { - "type": "integer", - "format": "int32" - }, - "start_date": { - "type": "string", - "format": "date-time" - } - } - } - ] - }, - "VisitorsResponse": { - "type": "object", - "required": [ - "visitors", - "total_count", - "filtered_count" - ], - "properties": { - "filtered_count": { - "type": "integer", - "format": "int64" - }, - "total_count": { - "type": "integer", - "format": "int64" - }, - "visitors": { - "type": "array", - "items": { - "$ref": "#/components/schemas/VisitorInfo" - } - } - } - }, - "VolumeMount": { - "type": "object", - "description": "Volume mount in deployment", - "required": [ - "source", - "destination", - "read_only", - "type" - ], - "properties": { - "destination": { - "type": "string", - "description": "Destination path in container" - }, - "read_only": { - "type": "boolean", - "description": "Read-only flag" - }, - "source": { - "type": "string", - "description": "Source (volume name or path)" - }, - "type": { - "$ref": "#/components/schemas/VolumeType", - "description": "Volume type" - } - } - }, - "VolumeType": { - "type": "string", - "description": "Volume type", - "enum": [ - "bind", - "volume", - "tmpfs" - ] - }, - "VulnerabilityResponse": { - "type": "object", - "required": [ - "id", - "scan_id", - "vulnerability_id", - "package_name", - "installed_version", - "severity", - "title", - "created_at" - ], - "properties": { - "class": { - "type": [ - "string", - "null" - ], - "example": "os-pkgs" - }, - "created_at": { - "type": "string", - "example": "2025-12-08T12:15:47.609192Z" - }, - "cvss_score": { - "type": [ - "number", - "null" - ], - "format": "float" - }, - "description": { - "type": [ - "string", - "null" - ] - }, - "fixed_version": { - "type": [ - "string", - "null" - ] - }, - "id": { - "type": "integer", - "format": "int32" - }, - "installed_version": { - "type": "string" - }, - "last_modified_date": { - "type": [ - "string", - "null" - ], - "example": "2025-12-08T12:15:47.609192Z" - }, - "package_name": { - "type": "string" - }, - "primary_url": { - "type": [ - "string", - "null" - ] - }, - "published_date": { - "type": [ - "string", - "null" - ], - "example": "2025-12-08T12:15:47.609192Z" - }, - "references": {}, - "scan_id": { - "type": "integer", - "format": "int32" - }, - "severity": { - "type": "string" - }, - "target": { - "type": [ - "string", - "null" - ], - "example": "alpine:3.18 (alpine 3.18.0)" - }, - "title": { - "type": "string" - }, - "type": { - "type": [ - "string", - "null" - ], - "example": "alpine" - }, - "vulnerability_id": { - "type": "string" - } - } - }, - "WalWarning": { - "oneOf": [ - { - "type": "object", - "description": "`pg_wal` is significantly larger than `max_wal_size`.", - "required": [ - "pg_wal_bytes", - "max_wal_size_bytes", - "ratio", - "kind" - ], - "properties": { - "kind": { - "type": "string", - "enum": [ - "wal_bloat" - ] - }, - "max_wal_size_bytes": { - "type": "integer", - "format": "int64" - }, - "pg_wal_bytes": { - "type": "integer", - "format": "int64" - }, - "ratio": { - "type": "number", - "format": "double" - } - } - }, - { - "type": "object", - "description": "A replication slot is holding WAL it's not consuming.", - "required": [ - "slot_name", - "retained_bytes", - "active", - "kind" - ], - "properties": { - "active": { - "type": "boolean" - }, - "kind": { - "type": "string", - "enum": [ - "stale_slot" - ] - }, - "retained_bytes": { - "type": "integer", - "format": "int64" - }, - "slot_name": { - "type": "string" - } - } - }, - { - "type": "object", - "description": "`archive_status/*.ready` count exceeds threshold \u2014 `archive_command`\nis either failing or running slower than WAL generation.", - "required": [ - "ready_count", - "kind" - ], - "properties": { - "kind": { - "type": "string", - "enum": [ - "archive_backlog" - ] - }, - "ready_count": { - "type": "integer", - "format": "int64" - } - } - }, - { - "type": "object", - "description": "`archive_mode = on` but `archive_command` is empty / `/bin/true`.\nWAL accumulates forever waiting for a destination that never accepts.", - "required": [ - "kind" - ], - "properties": { - "kind": { - "type": "string", - "enum": [ - "archive_mode_without_command" - ] - } - } - }, - { - "type": "object", - "description": "Oldest WAL segment is older than `WAL_NOT_RECYCLED_AGE_SECS`.\nIndependent signal: something is blocking recycling even if total\nsize hasn't exploded yet.", - "required": [ - "oldest_age_secs", - "kind" - ], - "properties": { - "kind": { - "type": "string", - "enum": [ - "wal_not_recycled" - ] - }, - "oldest_age_secs": { - "type": "integer", - "format": "int64" - } - } - } - ], - "description": "One actionable warning surfaced to the UI.\n\nEach variant carries the data needed to render a remediation hint without\nthe frontend re-querying anything." - }, - "WalWarningSeverity": { - "type": "string", - "enum": [ - "warning", - "critical" - ] - }, - "WebhookConfig": { - "type": "object", - "description": "Configuration for a generic webhook notification provider", - "required": [ - "url" - ], - "properties": { - "headers": { - "type": "object", - "description": "Custom headers to include in the request (e.g., for authentication tokens)", - "additionalProperties": { - "type": "string" - }, - "propertyNames": { - "type": "string" - }, - "example": { - "Authorization": "Bearer your-token", - "X-Custom-Header": "custom-value" - } - }, - "method": { - "type": "string", - "description": "HTTP method to use (POST, PUT, PATCH). Defaults to POST.", - "example": "POST" - }, - "timeout_secs": { - "type": "integer", - "format": "int64", - "description": "Request timeout in seconds. Defaults to 30.", - "example": 30, - "minimum": 0 - }, - "url": { - "type": "string", - "description": "The URL to send webhook requests to", - "example": "https://api.example.com/notifications" - } - } - }, - "WebhookDeliveryResponse": { - "type": "object", - "required": [ - "id", - "webhook_id", - "event_type", - "event_id", - "payload", - "success", - "attempt_number", - "created_at" - ], - "properties": { - "attempt_number": { - "type": "integer", - "format": "int32" - }, - "created_at": { - "type": "string", - "format": "date-time", - "example": "2025-10-12T12:15:47.609192Z" - }, - "delivered_at": { - "type": [ - "string", - "null" - ], - "format": "date-time" - }, - "error_message": { - "type": [ - "string", - "null" - ] - }, - "event_id": { - "type": "string" - }, - "event_type": { - "type": "string" - }, - "id": { - "type": "integer", - "format": "int32" - }, - "payload": { - "type": "string", - "description": "JSON payload that was sent to the webhook endpoint", - "example": { - "event_type": "deployment.succeeded", - "data": { - "deployment_id": 123 - } - } - }, - "status_code": { - "type": [ - "integer", - "null" - ], - "format": "int32" - }, - "success": { - "type": "boolean" - }, - "webhook_id": { - "type": "integer", - "format": "int32" - } - } - }, - "WebhookResponse": { - "type": "object", - "required": [ - "id", - "project_id", - "url", - "events", - "enabled", - "has_secret", - "created_at", - "updated_at" - ], - "properties": { - "created_at": { - "type": "string", - "format": "date-time", - "example": "2025-10-12T12:15:47.609192Z" - }, - "enabled": { - "type": "boolean" - }, - "events": { - "type": "array", - "items": { - "type": "string" - } - }, - "has_secret": { - "type": "boolean" - }, - "id": { - "type": "integer", - "format": "int32" - }, - "project_id": { - "type": "integer", - "format": "int32" - }, - "updated_at": { - "type": "string", - "format": "date-time", - "example": "2025-10-12T12:15:47.609192Z" - }, - "url": { - "type": "string" - } - } - }, - "WebhookTriggerRequest": { - "allOf": [ - { - "description": "Arbitrary JSON payload from the caller. Passed to the agent as user_context." - } - ] - }, - "WebhookTriggerResponse": { - "type": "object", - "required": [ - "run_id", - "status" - ], - "properties": { - "run_id": { - "type": "integer", - "format": "int32" - }, - "status": { - "type": "string" - } - } - }, - "WorkflowDryRunRequest": { - "type": "object", - "required": [ - "yaml" - ], - "properties": { - "cpu_limit": { - "type": [ - "number", - "null" - ], - "format": "double", - "description": "Optional CPU override applied after parsing YAML (clamped server-side).\nWhen `Some`, this takes precedence over `cpu_limit` inside the YAML \u2014\nlets the CLI pass `--cpu` without rewriting the YAML text." - }, - "error_group_id": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Optional error group to link this dry-run to. When set, the executor's\n`load_error_context` path injects `{{error_type}}` / `{{error_message}}`\n/ `{{stack_trace}}` into the prompt \u2014 same behaviour as a committed\nworkflow triggered with `trigger_source_type = \"error_group\"`. Must\nbelong to `project_id` (handler enforces)." - }, - "memory_limit_mb": { - "type": [ - "integer", - "null" - ], - "format": "int64", - "description": "Optional memory override in MB (clamped server-side). Same precedence\nrule as `cpu_limit`.", - "minimum": 0 - }, - "user_context": { - "type": [ - "string", - "null" - ], - "description": "Optional context appended to the prompt (e.g. \"test against staging\nonly\"). Mirrors `TriggerAgentRequest.user_context`." - }, - "yaml": { - "type": "string", - "description": "Full WorkflowYamlConfig as YAML text. Server validates and re-serializes\nbefore storing on the run row." - } - } - }, - "WorkloadDescriptor": { - "type": "object", - "description": "Brief descriptor for discovered workloads (used in listing)", - "required": [ - "id", - "workload_type", - "status", - "labels" - ], - "properties": { - "created_at": { - "type": [ - "string", - "null" - ], - "format": "date-time", - "description": "Creation timestamp" - }, - "id": { - "$ref": "#/components/schemas/WorkloadId", - "description": "Unique ID in source system" - }, - "image": { - "type": [ - "string", - "null" - ], - "description": "Image/build reference (for containers)" - }, - "labels": { - "type": "object", - "description": "Labels/tags from source system", - "additionalProperties": { - "type": "string" - }, - "propertyNames": { - "type": "string" - } - }, - "name": { - "type": [ - "string", - "null" - ], - "description": "Workload name (if any)" - }, - "status": { - "$ref": "#/components/schemas/WorkloadStatus", - "description": "Current status" - }, - "workload_type": { - "$ref": "#/components/schemas/WorkloadType", - "description": "Workload type (container, function, static-site, etc.)" - } - } - }, - "WorkloadId": { - "type": "string", - "description": "Unique identifier for a workload in the source system" - }, - "WorkloadStatus": { - "type": "string", - "description": "Workload status in source system", - "enum": [ - "running", - "paused", - "stopped", - "exited", - "failed", - "deployed", - "building", - "unknown" - ] - }, - "WorkloadType": { - "type": "string", - "description": "Workload type", - "enum": [ - "container", - "function", - "static-site", - "server-side-app", - "worker", - "database", - "message-queue", - "cache", - "cron-job", - "other" - ] - }, - "WriteFileBody": { - "type": "object", - "required": [ - "path", - "contents_b64" - ], - "properties": { - "contents_b64": { - "type": "string", - "description": "File contents, base64-encoded. Required \u2014 lets callers ship binary\ndata over JSON without charset games." - }, - "mode": { - "type": [ - "integer", - "null" - ], - "format": "int32", - "description": "Unix permission mask (e.g. 0o644). Defaults to 0o644 when absent.", - "minimum": 0 - }, - "path": { - "type": "string", - "description": "Absolute path inside the sandbox. Must start with `/`." - } - }, - "additionalProperties": false - }, - "WriteFilesBody": { - "type": "object", - "required": [ - "files" - ], - "properties": { - "files": { - "type": "array", - "items": { - "$ref": "#/components/schemas/WriteFileBody" - }, - "description": "List of files to write. Each entry must include an absolute\n`path` and base64-encoded `contents_b64`. Empty list is a no-op." - } - }, - "additionalProperties": false - }, - "WriteFilesResponse": { - "type": "object", - "required": [ - "written" - ], - "properties": { - "written": { - "type": "integer", - "description": "Number of files successfully written before the first failure\n(if any). On full success this equals `files.len()`.", - "minimum": 0 - } - } - }, - "ZoneListResponse": { - "type": "object", - "description": "Zone list response", - "required": [ - "zones" - ], - "properties": { - "zones": { - "type": "array", - "items": { - "$ref": "#/components/schemas/DnsZone" - } - } - } - } - }, - "securitySchemes": { - "bearer_auth": { - "type": "http", - "scheme": "bearer", - "description": "Bearer token authentication. Use format: `Bearer `. Supports API keys (starting with `tk_`), CLI tokens, and session tokens." - } - } - }, - "tags": [ - { - "name": "Events", - "description": "Analytics events tracking endpoints" - }, - { - "name": "Metrics", - "description": "Analytics metrics collection endpoints including performance web vitals" - }, - { - "name": "Funnels", - "description": "Funnel management endpoints" - }, - { - "name": "Analytics", - "description": "Analytics and session replay management" - }, - { - "name": "Performance", - "description": "Performance metrics management" - }, - { - "name": "geo", - "description": "Geolocation API endpoints" - }, - { - "name": "Platform", - "description": "Platform information and compatibility" - }, - { - "name": "Teams", - "description": "Teams and project-scoped access" - }, - { - "name": "Git Providers", - "description": "Git provider management endpoints" - }, - { - "name": "Repositories", - "description": "Repository management endpoints" - }, - { - "name": "Public Repositories", - "description": "Endpoints for accessing public repositories without authentication. Supports GitHub and GitLab." - }, - { - "name": "Notification Providers", - "description": "Notification provider management endpoints" - }, - { - "name": "Notification Preferences", - "description": "User notification preferences and settings" - }, - { - "name": "DNS Providers", - "description": "DNS provider management endpoints" - }, - { - "name": "Internal DNS", - "description": "Per-node DNS resolver sync (ADR-011)" - }, - { - "name": "Domains", - "description": "Domain management endpoints" - }, - { - "name": "Email Providers", - "description": "Email provider management endpoints" - }, - { - "name": "Email Domains", - "description": "Email domain management and verification" - }, - { - "name": "Emails", - "description": "Email sending and retrieval" - }, - { - "name": "Email Tracking", - "description": "Email open and click tracking" - }, - { - "name": "Email Validation", - "description": "Email address validation and verification" - }, - { - "name": "Webhooks", - "description": "Webhook management endpoints" - }, - { - "name": "Webhook Deliveries", - "description": "Webhook delivery history and retry endpoints" - }, - { - "name": "External Services", - "description": "External service integration endpoints" - }, - { - "name": "External Services - Query", - "description": "Data querying and exploration endpoints" - }, - { - "name": "Metrics", - "description": "Time-series metrics and alert rule endpoints" - }, - { - "name": "KV Store", - "description": "Key-Value storage operations" - }, - { - "name": "KV Management", - "description": "KV service management operations" - }, - { - "name": "Blob", - "description": "Blob storage operations" - }, - { - "name": "Blob Management", - "description": "Blob service management operations" - }, - { - "name": "Feature Flags", - "description": "Runtime configuration that changes without a redeploy" - }, - { - "name": "Environments", - "description": "Environment management operations" - }, - { - "name": "Secrets", - "description": "File-mounted secrets (/run/secrets/)" - }, - { - "name": "Projects", - "description": "Project management endpoints" - }, - { - "name": "Presets", - "description": "Available deployment presets" - }, - { - "name": "Templates", - "description": "Project template endpoints" - }, - { - "name": "Custom Domains", - "description": "Custom domain management for projects" - }, - { - "name": "error-tracking", - "description": "Error tracking data fetching endpoints" - }, - { - "name": "Vulnerability Scans", - "description": "Vulnerability scan management endpoints" - }, - { - "name": "Agents", - "description": "Autonomous AI agents, autofixer (interactive AI debugging), skills/MCP definitions, and preview gateway management." - }, - { - "name": "Crons", - "description": "Cron jobs management API" - }, - { - "name": "Sandboxes", - "description": "Standalone sandbox API (`/v1/sandboxes/*`) for running isolated containers." - }, - { - "name": "Logs", - "description": "Log search, context, live tail, and retention management" - }, - { - "name": "Imports", - "description": "Import workloads from external sources" - }, - { - "name": "Status Page", - "description": "Status page and monitoring endpoints" - }, - { - "name": "OTel Ingest", - "description": "OTLP/HTTP ingest endpoints (protobuf)" - }, - { - "name": "OTel", - "description": "Query endpoints for the monitoring UI" - }, - { - "name": "GenAI", - "description": "GenAI agent activity tracing endpoints" - }, - { - "name": "Alarms", - "description": "Unified alarm history \u2014 list, summarise, acknowledge, resolve" - }, - { - "name": "Authentication", - "description": "Authentication and authorization endpoints" - }, - { - "name": "Users", - "description": "User management endpoints" - }, - { - "name": "Backups", - "description": "Backup management endpoints" - }, - { - "name": "Restore", - "description": "External service restore operations" - }, - { - "name": "Revenue", - "description": "Per-project revenue tracking integrations and analytics" - }, - { - "name": "Observability", - "description": "Unified observability event stream \u2014 runtime logs, requests, spans, errors, revenue" - }, - { - "name": "AI Gateway", - "description": "OpenAI-compatible chat, embeddings, and model endpoints" - }, - { - "name": "AI Gateway Admin", - "description": "Provider key management endpoints" - }, - { - "name": "AI Gateway Usage", - "description": "Usage analytics and reporting endpoints" - }, - { - "name": "AI Gateway Pricing", - "description": "Model pricing endpoints" - }, - { - "name": "API Keys", - "description": "API key management endpoints" - }, - { - "name": "Load Balancer", - "description": "Load balancer management endpoints" - }, - { - "name": "IP Access Control", - "description": "IP access control management endpoints" - }, - { - "name": "Files", - "description": "Static file serving endpoints" - }, - { - "name": "External Plugins", - "description": "External plugin management and discovery" - } - ] -} \ No newline at end of file +{"openapi":"3.1.0","info":{"title":"Temps","description":"An API for managing projects, deployments, and infrastructure resources","contact":{"name":"Temps Support","url":"https://temps.sh"},"version":"1.0.0"},"servers":[{"url":"/api","description":"Base path for all API endpoints"}],"paths":{"/.well-known/temps.json":{"get":{"tags":["Platform"],"summary":"Get platform information","operationId":"get_platform_info","responses":{"200":{"description":"Successfully retrieved platform information","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PlatformInfo"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"}},"security":[{"bearer_auth":[]}]}},"/0/organizations/{org_slug}/chunk-upload/":{"get":{"tags":["sentry-compat"],"summary":"Chunk upload options (stub for sentry-cli compatibility).","description":"sentry-cli checks this endpoint to determine if chunk-based upload is supported.\nWe return a response indicating that chunk upload is NOT supported, which forces\nsentry-cli to fall back to the standard file-by-file upload.","operationId":"chunk_upload_options","parameters":[{"name":"org_slug","in":"path","description":"Organization slug (ignored)","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Chunk upload options","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SentryChunkUploadResponse"}}}}}}},"/0/organizations/{org_slug}/releases/":{"post":{"tags":["sentry-compat"],"summary":"Create a release (stub for sentry-cli compatibility).","description":"sentry-cli calls this before uploading files. Since Temps implicitly creates\nreleases when source maps are uploaded, this is a no-op that returns the\nexpected response format.","operationId":"create_release","parameters":[{"name":"org_slug","in":"path","description":"Organization slug (ignored in single-tenant mode)","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SentryCreateReleaseRequest"}}},"required":true},"responses":{"201":{"description":"Release created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SentryReleaseResponse"}}}},"401":{"description":"Unauthorized"}}}},"/0/projects/{org_slug}/{project_slug}/releases/":{"post":{"tags":["sentry-compat"],"summary":"Create a release for a specific project (stub for sentry-cli compatibility).","description":"sentry-cli calls this endpoint (instead of /organizations/.../releases/) when\nboth SENTRY_ORG and SENTRY_PROJECT env vars are set. Behaves identically to\nthe organizations endpoint but validates the project slug.","operationId":"create_project_release","parameters":[{"name":"org_slug","in":"path","description":"Organization slug (ignored in single-tenant mode)","required":true,"schema":{"type":"string"}},{"name":"project_slug","in":"path","description":"Project slug or numeric ID","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SentryCreateReleaseRequest"}}},"required":true},"responses":{"201":{"description":"Release created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SentryReleaseResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Project not found"}}}},"/0/projects/{org_slug}/{project_slug}/releases/{version}/":{"put":{"tags":["sentry-compat"],"summary":"Finalize a release (stub for sentry-cli compatibility).","description":"sentry-cli calls `releases finalize` after uploading source maps. This sets\nthe dateReleased on the release. Since Temps stores source maps independently\nof releases, this is a no-op that returns the expected response.","operationId":"finalize_project_release","parameters":[{"name":"org_slug","in":"path","description":"Organization slug (ignored)","required":true,"schema":{"type":"string"}},{"name":"project_slug","in":"path","description":"Project slug or numeric ID","required":true,"schema":{"type":"string"}},{"name":"version","in":"path","description":"Release version to finalize","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Release finalized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SentryReleaseResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Project not found"}}}},"/0/projects/{org_slug}/{project_slug}/releases/{version}/files/":{"get":{"tags":["sentry-compat"],"summary":"List files for a release.","description":"Returns all source maps stored for a specific release in sentry-cli compatible format.","operationId":"list_release_files","parameters":[{"name":"org_slug","in":"path","description":"Organization slug (ignored)","required":true,"schema":{"type":"string"}},{"name":"project_slug","in":"path","description":"Project slug or numeric ID","required":true,"schema":{"type":"string"}},{"name":"version","in":"path","description":"Release version","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"List of release files","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/SentryReleaseFileResponse"}}}}},"401":{"description":"Unauthorized"},"404":{"description":"Project not found"}}},"post":{"tags":["sentry-compat"],"summary":"Upload a source map file for a release.","description":"Accepts the same multipart format as the Sentry release files API.\nThe `name` field should be the URL path of the file (e.g., `~/dist/bundle.js.map`).\n\nThe route has a 50 MiB body limit applied at the router level (Fix #4).\nA per-field size check provides an additional defense-in-depth layer.","operationId":"upload_release_file","parameters":[{"name":"org_slug","in":"path","description":"Organization slug (ignored)","required":true,"schema":{"type":"string"}},{"name":"project_slug","in":"path","description":"Project slug or numeric ID","required":true,"schema":{"type":"string"}},{"name":"version","in":"path","description":"Release version","required":true,"schema":{"type":"string"}}],"responses":{"201":{"description":"File uploaded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SentryReleaseFileResponse"}}}},"400":{"description":"Bad request"},"401":{"description":"Unauthorized"},"404":{"description":"Project not found"},"413":{"description":"Source map file exceeds the 50 MiB per-field limit"}}}},"/_temps/event":{"post":{"tags":["Metrics"],"summary":"Record analytics event","operationId":"record_event_metrics","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EventMetricsPayload"}}},"required":true},"responses":{"204":{"description":"Event recorded successfully"},"400":{"description":"Bad request"},"500":{"description":"Internal server error"}}}},"/_temps/session-replay/events":{"post":{"tags":["Analytics"],"summary":"Add events to existing session replay","operationId":"add_session_replay_events","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionReplayEventsRequest"}}},"required":true},"responses":{"200":{"description":"Events added successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddEventsResponse"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Session not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/_temps/session-replay/init":{"post":{"tags":["Analytics"],"summary":"Initialize session replay with metadata","operationId":"init_session_replay","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionReplayInitRequest"}}},"required":true},"responses":{"201":{"description":"Session initialized successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionReplayInitResponse"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/_temps/speed":{"post":{"tags":["Performance"],"summary":"Record performance metrics from client","operationId":"record_speed_metrics","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SpeedMetricsPayload"}}},"required":true},"responses":{"204":{"description":"Metrics recorded successfully"},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Host not found in route table","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/_temps/speed/update":{"post":{"tags":["Performance"],"summary":"Update late performance metrics","operationId":"update_speed_metrics","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateSpeedMetricsPayload"}}},"required":true},"responses":{"204":{"description":"Metrics updated successfully"},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Host not found or metrics not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/admin/gate-settings":{"get":{"tags":["AdminGate"],"operationId":"get_admin_gate","responses":{"200":{"description":"Current admin gate config","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminGateResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"}},"security":[{"bearer_auth":[]}]},"patch":{"tags":["AdminGate"],"operationId":"patch_admin_gate","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateAdminGateRequest"}}},"required":true},"responses":{"200":{"description":"Updated admin gate config","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminGateResponse"}}}},"400":{"description":"Invalid IP/CIDR/host"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"409":{"description":"Env-overridden or would lock out caller"}},"security":[{"bearer_auth":[]}]}},"/admin/oidc/providers":{"get":{"tags":["Authentication"],"operationId":"list_oidc_providers","responses":{"200":{"description":"OIDC providers","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/OidcProviderResponse"}}}}}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Authentication"],"operationId":"create_oidc_provider","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateOidcProviderRequest"}}},"required":true},"responses":{"201":{"description":"OIDC provider created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OidcProviderResponse"}}}},"409":{"description":"Another OIDC provider already uses that name"}},"security":[{"bearer_auth":[]}]}},"/admin/oidc/providers/{provider_id}":{"delete":{"tags":["Authentication"],"operationId":"delete_oidc_provider","parameters":[{"name":"provider_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"OIDC provider deleted"}},"security":[{"bearer_auth":[]}]},"patch":{"tags":["Authentication"],"operationId":"update_oidc_provider","parameters":[{"name":"provider_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateOidcProviderRequest"}}},"required":true},"responses":{"200":{"description":"OIDC provider updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OidcProviderResponse"}}}}},"security":[{"bearer_auth":[]}]}},"/admin/oidc/providers/{provider_id}/role-mappings":{"get":{"tags":["Authentication"],"operationId":"list_oidc_role_mappings","parameters":[{"name":"provider_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"OIDC role mappings","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/OidcRoleMappingResponse"}}}}}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Authentication"],"operationId":"create_oidc_role_mapping","parameters":[{"name":"provider_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateOidcRoleMappingRequest"}}},"required":true},"responses":{"201":{"description":"Role mapping created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OidcRoleMappingResponse"}}}}},"security":[{"bearer_auth":[]}]}},"/admin/oidc/providers/{provider_id}/test":{"post":{"tags":["Authentication"],"operationId":"test_oidc_provider","parameters":[{"name":"provider_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Connection test result","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OidcTestConnectionResponse"}}}}},"security":[{"bearer_auth":[]}]}},"/admin/oidc/providers/{provider_id}/users":{"get":{"tags":["Authentication"],"operationId":"list_oidc_provider_users","parameters":[{"name":"provider_id","in":"path","description":"OIDC provider ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Users authenticated via this OIDC provider","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/OidcProviderUserResponse"}}}}},"404":{"description":"Provider not found"}},"security":[{"bearer_auth":[]}]}},"/admin/oidc/role-mappings/{mapping_id}":{"delete":{"tags":["Authentication"],"operationId":"delete_oidc_role_mapping","parameters":[{"name":"mapping_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"Role mapping deleted"}},"security":[{"bearer_auth":[]}]}},"/agents/webhook/{webhook_id}":{"post":{"tags":["Agents"],"summary":"Public webhook endpoint. Authenticated via `X-Webhook-Token` header.","description":"`POST /api/agents/webhook/{webhook_id}`\nHeader: `X-Webhook-Token: `\n\nThe `webhook_id` in the URL is a short non-secret identifier (safe to log).\nThe actual credential is the secret token in the header.\n\nAccepts any JSON body, which is passed as `user_context` to the agent run.","operationId":"webhook_trigger","parameters":[{"name":"webhook_id","in":"path","description":"Webhook ID (non-secret)","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookTriggerRequest"}}},"required":true},"responses":{"202":{"description":"Agent run created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookTriggerResponse"}}}},"401":{"description":"Missing or invalid X-Webhook-Token header"},"404":{"description":"Invalid webhook ID"},"422":{"description":"Agent disabled"}}}},"/ai/conversations":{"get":{"tags":["AI Chat"],"summary":"List every active conversation across all projects, most-recently-active\nfirst, annotated with project name/slug. Powers the unified \"all chats\"\nswitcher in the AI assistant dock.","operationId":"list_all_conversations","responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/GlobalConversationResponse"}}}}},"401":{"description":""},"403":{"description":""}},"security":[{"bearer_auth":[]}]}},"/ai/pricing":{"get":{"tags":["AI Gateway Pricing"],"operationId":"get_pricing","responses":{"200":{"description":"Model pricing information","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PricingResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/ai/providers":{"get":{"tags":["AI Gateway Admin"],"operationId":"list_provider_keys","responses":{"200":{"description":"List of provider keys","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ProviderKeyResponse"}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]},"post":{"tags":["AI Gateway Admin"],"operationId":"create_provider_key","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateProviderKeyRequest"}}},"required":true},"responses":{"201":{"description":"Provider key created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProviderKeyResponse"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/ai/providers/test":{"post":{"tags":["AI Gateway Admin"],"operationId":"test_provider_key_inline","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TestProviderKeyRequest"}}},"required":true},"responses":{"200":{"description":"Test result","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TestProviderKeyResponse"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/ai/providers/{id}":{"delete":{"tags":["AI Gateway Admin"],"operationId":"delete_provider_key","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"Provider key deleted"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]},"patch":{"tags":["AI Gateway Admin"],"operationId":"update_provider_key","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateProviderKeyRequest"}}},"required":true},"responses":{"200":{"description":"Provider key updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProviderKeyResponse"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/ai/providers/{id}/test":{"post":{"tags":["AI Gateway Admin"],"operationId":"test_provider_key_by_id","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Test result","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TestProviderKeyResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Provider key not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/ai/usage/by-provider":{"get":{"tags":["AI Gateway Usage"],"operationId":"get_usage_by_provider","parameters":[{"name":"from","in":"query","description":"ISO 8601 start time (defaults to 24h ago)","required":false,"schema":{"type":"string"}},{"name":"to","in":"query","description":"ISO 8601 end time (defaults to now)","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Usage broken down by provider","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ProviderUsage"}}}}},"400":{"description":"Invalid query parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/ai/usage/conversations":{"get":{"tags":["AI Gateway Usage"],"operationId":"get_conversations","parameters":[{"name":"from","in":"query","description":"ISO 8601 start time (defaults to 24h ago)","required":false,"schema":{"type":"string"}},{"name":"to","in":"query","description":"ISO 8601 end time (defaults to now)","required":false,"schema":{"type":"string"}},{"name":"limit","in":"query","description":"Max results (defaults to 50, max 100)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"user_id","in":"query","description":"Filter by user ID","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"tags","in":"query","description":"Filter by tags (comma-separated)","required":false,"schema":{"type":"string"}},{"name":"model","in":"query","description":"Filter by model name","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Conversation summaries","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ConversationSummary"}}}}},"400":{"description":"Invalid query parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/ai/usage/conversations/{conversation_id}":{"get":{"tags":["AI Gateway Usage"],"operationId":"get_conversation_detail","parameters":[{"name":"conversation_id","in":"path","description":"Conversation ID","required":true,"schema":{"type":"string"}},{"name":"limit","in":"query","description":"Max results (defaults to 100)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}}],"responses":{"200":{"description":"Invocations within a conversation","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/UsageLogEntry"}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/ai/usage/recent":{"get":{"tags":["AI Gateway Usage"],"operationId":"get_usage_recent","parameters":[{"name":"limit","in":"query","description":"Page size (defaults to 20, max 50)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"offset","in":"query","description":"Number of results to skip for pagination (defaults to 0)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"provider","in":"query","description":"Filter by provider name","required":false,"schema":{"type":"string"}},{"name":"model","in":"query","description":"Filter by model name","required":false,"schema":{"type":"string"}},{"name":"status","in":"query","description":"Filter by HTTP status code (exact match)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"cost_gte","in":"query","description":"Cost greater-than-or-equal, in microcents","required":false,"schema":{"type":"integer","format":"int64"}},{"name":"cost_gt","in":"query","description":"Cost strictly greater-than, in microcents","required":false,"schema":{"type":"integer","format":"int64"}},{"name":"cost_lte","in":"query","description":"Cost less-than-or-equal, in microcents","required":false,"schema":{"type":"integer","format":"int64"}},{"name":"cost_lt","in":"query","description":"Cost strictly less-than, in microcents","required":false,"schema":{"type":"integer","format":"int64"}},{"name":"tokens_gte","in":"query","description":"Total tokens greater-than-or-equal","required":false,"schema":{"type":"integer","format":"int64"}},{"name":"tokens_gt","in":"query","description":"Total tokens strictly greater-than","required":false,"schema":{"type":"integer","format":"int64"}},{"name":"tokens_lte","in":"query","description":"Total tokens less-than-or-equal","required":false,"schema":{"type":"integer","format":"int64"}},{"name":"tokens_lt","in":"query","description":"Total tokens strictly less-than","required":false,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"Page of recent usage log entries","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UsageLogPage"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/ai/usage/summary":{"get":{"tags":["AI Gateway Usage"],"operationId":"get_usage_summary","parameters":[{"name":"from","in":"query","description":"ISO 8601 start time (defaults to 24h ago)","required":false,"schema":{"type":"string"}},{"name":"to","in":"query","description":"ISO 8601 end time (defaults to now)","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Usage summary for the time range","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UsageSummary"}}}},"400":{"description":"Invalid query parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/ai/usage/timeseries":{"get":{"tags":["AI Gateway Usage"],"operationId":"get_usage_timeseries","parameters":[{"name":"from","in":"query","description":"ISO 8601 start time (defaults to 24h ago)","required":false,"schema":{"type":"string"}},{"name":"to","in":"query","description":"ISO 8601 end time (defaults to now)","required":false,"schema":{"type":"string"}},{"name":"bucket","in":"query","description":"Bucket size: hour, day, week (defaults to day)","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Time-series usage data","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/TimeseriesBucket"}}}}},"400":{"description":"Invalid query parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/ai/usage/top-models":{"get":{"tags":["AI Gateway Usage"],"operationId":"get_usage_top_models","parameters":[{"name":"from","in":"query","description":"ISO 8601 start time (defaults to 24h ago)","required":false,"schema":{"type":"string"}},{"name":"to","in":"query","description":"ISO 8601 end time (defaults to now)","required":false,"schema":{"type":"string"}},{"name":"limit","in":"query","description":"Max results (defaults to 10)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}}],"responses":{"200":{"description":"Top models by request count","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ModelUsage"}}}}},"400":{"description":"Invalid query parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/ai/v1/chat/completions":{"post":{"tags":["AI Gateway"],"operationId":"chat_completions","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatCompletionRequest"}}},"required":true},"responses":{"200":{"description":"Chat completion response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatCompletionResponse"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpenAiErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpenAiErrorResponse"}}}},"404":{"description":"Model not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpenAiErrorResponse"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpenAiErrorResponse"}}}}},"security":[{"bearer_auth":[]}]}},"/ai/v1/embeddings":{"post":{"tags":["AI Gateway"],"operationId":"embeddings","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmbeddingRequest"}}},"required":true},"responses":{"200":{"description":"Embedding response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmbeddingResponse"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpenAiErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpenAiErrorResponse"}}}},"404":{"description":"Model not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpenAiErrorResponse"}}}}},"security":[{"bearer_auth":[]}]}},"/ai/v1/models":{"get":{"tags":["AI Gateway"],"operationId":"list_models","responses":{"200":{"description":"List of available models","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ModelListResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OpenAiErrorResponse"}}}}},"security":[{"bearer_auth":[]}]}},"/analytics/active-visitors":{"get":{"tags":["Analytics"],"summary":"Get detailed active visitors","operationId":"get_analytics_active_visitors","parameters":[{"name":"project_id","in":"query","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Environment ID (optional)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"deployment_id","in":"query","description":"Deployment ID (optional)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"window_minutes","in":"query","description":"Time window in minutes for active visitors (default: 5)","required":false,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Successfully retrieved active visitors","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActiveVisitorsResponse"}}}},"400":{"description":"Invalid parameters or project not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/analytics/event-detail":{"get":{"tags":["Analytics"],"summary":"Get detailed analytics for a specific event","operationId":"get_event_detail","parameters":[{"name":"event_name","in":"query","description":"Event name to get details for","required":true,"schema":{"type":"string"}},{"name":"project_id","in":"query","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Environment ID (optional)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"start_date","in":"query","description":"Start date (ISO 8601)","required":true,"schema":{"type":"string"}},{"name":"end_date","in":"query","description":"End date (ISO 8601)","required":true,"schema":{"type":"string"}},{"name":"bucket_interval","in":"query","description":"Bucket interval: hour, day, week, month (default: auto)","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successfully retrieved event details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EventDetailResponse"}}}},"400":{"description":"Invalid parameters"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/analytics/event-entries":{"get":{"tags":["Analytics"],"summary":"Get paginated list of raw occurrences of a specific event, including custom JSON properties","operationId":"get_event_entries","parameters":[{"name":"event_name","in":"query","description":"Event name to list occurrences for","required":true,"schema":{"type":"string"}},{"name":"project_id","in":"query","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Environment ID (optional)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"start_date","in":"query","description":"Start date (ISO 8601)","required":true,"schema":{"type":"string"}},{"name":"end_date","in":"query","description":"End date (ISO 8601)","required":true,"schema":{"type":"string"}},{"name":"page","in":"query","description":"Page number (1-based, default: 1)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"per_page","in":"query","description":"Items per page (default: 20, max: 100)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}}],"responses":{"200":{"description":"Successfully retrieved event entries","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EventEntriesResponse"}}}},"400":{"description":"Invalid parameters"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/analytics/event-visitors":{"get":{"tags":["Analytics"],"summary":"Get paginated list of visitors who triggered a specific event","operationId":"get_event_visitors","parameters":[{"name":"event_name","in":"query","description":"Event name to list visitors for","required":true,"schema":{"type":"string"}},{"name":"project_id","in":"query","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Environment ID (optional)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"start_date","in":"query","description":"Start date (ISO 8601)","required":true,"schema":{"type":"string"}},{"name":"end_date","in":"query","description":"End date (ISO 8601)","required":true,"schema":{"type":"string"}},{"name":"page","in":"query","description":"Page number (1-based, default: 1)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"per_page","in":"query","description":"Items per page (default: 20, max: 100)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}}],"responses":{"200":{"description":"Successfully retrieved event visitors","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EventVisitorsResponse"}}}},"400":{"description":"Invalid parameters"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/analytics/events":{"get":{"tags":["Analytics"],"operationId":"get_analytics_events_count","parameters":[{"name":"start_date","in":"query","description":"Start date in format YYYY-MM-DD HH:MM:SS","required":true,"schema":{"type":"string"}},{"name":"end_date","in":"query","description":"End date in format YYYY-MM-DD HH:MM:SS","required":true,"schema":{"type":"string"}},{"name":"project_id","in":"query","description":"Project ID or slug","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"limit","in":"query","description":"Maximum number of results to return","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Environment ID (optional)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"custom_events_only","in":"query","description":"Only return custom events, excluding system events like page_view, page_leave, heartbeat (default: true)","required":false,"schema":{"type":"boolean"}},{"name":"breakdown","in":"query","description":"Breakdown by geography: 'country', 'region', or 'city' (optional)","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successfully retrieved event counts","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/EventCount"}}}}},"400":{"description":"Invalid date format, missing required parameters, or project not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/analytics/general-stats":{"get":{"tags":["Analytics"],"summary":"Get general statistics across all projects for a time frame","operationId":"get_general_stats","parameters":[{"name":"start_date","in":"query","description":"Start date in format YYYY-MM-DD HH:MM:SS","required":true,"schema":{"type":"string"}},{"name":"end_date","in":"query","description":"End date in format YYYY-MM-DD HH:MM:SS","required":true,"schema":{"type":"string"}},{"name":"project_ids","in":"query","description":"Optional: Filter by specific project IDs (comma-separated)","required":false,"schema":{"type":"array","items":{"type":"integer","format":"int32"}}},{"name":"environment_id","in":"query","description":"Environment ID (optional)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"include_project_breakdown","in":"query","description":"Whether to include per-project breakdown (default: false)","required":false,"schema":{"type":"boolean"}}],"responses":{"200":{"description":"Successfully retrieved general statistics","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GeneralStatsResponse"}}}},"400":{"description":"Invalid date format or parameters"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/analytics/has-events":{"get":{"tags":["Analytics"],"operationId":"check_analytics_has_events","parameters":[{"name":"project_id","in":"query","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Environment ID (optional)","required":false,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Analytics events existence check","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HasAnalyticsEventsResponse"}}}},"400":{"description":"Bad request"},"401":{"description":"Unauthorized"},"404":{"description":"Project not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/analytics/live-visitors":{"get":{"tags":["Analytics"],"summary":"Get list of currently live visitors from visitor table","operationId":"get_live_visitors_list","parameters":[{"name":"project_id","in":"query","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Environment ID (optional)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"window_minutes","in":"query","description":"Time window in minutes for live visitors (default: 5)","required":false,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Successfully retrieved live visitors list","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LiveVisitorsListResponse"}}}},"400":{"description":"Invalid parameters or project not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/analytics/page-flow":{"get":{"tags":["Analytics"],"summary":"Get page flow analytics: entry pages, exit pages, drop-off points, and page transitions","operationId":"get_page_flow","parameters":[{"name":"project_id","in":"query","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Environment ID (optional)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"start_date","in":"query","description":"Start date in ISO 8601 format","required":true,"schema":{"type":"string"}},{"name":"end_date","in":"query","description":"End date in ISO 8601 format","required":true,"schema":{"type":"string"}},{"name":"limit","in":"query","description":"Max entry/exit pages to return (default: 20, max: 100)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"transitions_limit","in":"query","description":"Max page transitions to return (default: 50, max: 200)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"min_views_for_dropoff","in":"query","description":"Minimum views for drop-off analysis (default: 5)","required":false,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Successfully retrieved page flow analytics","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PageFlowResponse"}}}},"400":{"description":"Invalid parameters"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/analytics/page-hourly-sessions":{"get":{"tags":["Analytics"],"operationId":"get_page_hourly_sessions","parameters":[{"name":"page_path","in":"query","description":"The page path to get sessions for","required":true,"schema":{"type":"string"}},{"name":"project_id","in":"query","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Environment ID (optional)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"start_time","in":"query","description":"Start time in format YYYY-MM-DD HH:MM:SS","required":true,"schema":{"type":"string"}},{"name":"end_time","in":"query","description":"End time in format YYYY-MM-DD HH:MM:SS","required":true,"schema":{"type":"string"}},{"name":"bucket_interval","in":"query","description":"Bucket interval: 'hour', 'day', 'week', or 'month' (default: auto-determined based on range)","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successfully retrieved page sessions with time buckets","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PageHourlySessionsResponse"}}}},"400":{"description":"Invalid parameters or project not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/analytics/page-path-detail":{"get":{"tags":["Analytics"],"summary":"Get detailed analytics for a specific page path\nReturns visitors, page views, activity over time, geographic distribution, and referrers","operationId":"get_page_path_detail","parameters":[{"name":"page_path","in":"query","description":"The page path to get details for (URL-encoded)","required":true,"schema":{"type":"string"}},{"name":"project_id","in":"query","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Environment ID (optional)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"start_date","in":"query","description":"Start date in ISO 8601 format","required":true,"schema":{"type":"string"}},{"name":"end_date","in":"query","description":"End date in ISO 8601 format","required":true,"schema":{"type":"string"}},{"name":"bucket_interval","in":"query","description":"Bucket interval for time series: 'hour', 'day', 'week', 'month' (default: auto based on date range)","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successfully retrieved page path detail analytics","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PagePathDetailResponse"}}}},"400":{"description":"Invalid parameters or project not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/analytics/page-path-visitors":{"get":{"tags":["Analytics"],"summary":"Get individual visitor sessions for a specific page path","operationId":"get_page_path_visitors","parameters":[{"name":"page_path","in":"query","description":"The page path to get visitors for (URL-encoded)","required":true,"schema":{"type":"string"}},{"name":"project_id","in":"query","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Environment ID (optional)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"start_date","in":"query","description":"Start date in ISO 8601 format","required":true,"schema":{"type":"string"}},{"name":"end_date","in":"query","description":"End date in ISO 8601 format","required":true,"schema":{"type":"string"}},{"name":"page","in":"query","description":"Page number (1-based, default: 1)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"per_page","in":"query","description":"Items per page (default: 50, max: 100)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}}],"responses":{"200":{"description":"Successfully retrieved page path visitors","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PagePathVisitorsResponse"}}}},"400":{"description":"Invalid parameters"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/analytics/page-paths":{"get":{"tags":["Analytics"],"operationId":"get_page_paths","parameters":[{"name":"project_id","in":"query","description":"Project ID or slug","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Environment ID (optional)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"start_date","in":"query","description":"Start date in format YYYY-MM-DD HH:MM:SS (optional)","required":false,"schema":{"type":"string"}},{"name":"end_date","in":"query","description":"End date in format YYYY-MM-DD HH:MM:SS (optional)","required":false,"schema":{"type":"string"}},{"name":"limit","in":"query","description":"Maximum number of page paths to return (default: 100, max: 1000)","required":false,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Successfully retrieved page paths","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PagePathsResponse"}}}},"400":{"description":"Invalid parameters or project not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/analytics/page-paths-sparklines":{"get":{"tags":["Analytics"],"operationId":"get_page_paths_sparklines","parameters":[{"name":"project_id","in":"query","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Environment ID (optional)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"start_time","in":"query","description":"Start time in ISO 8601 format","required":true,"schema":{"type":"string"}},{"name":"end_time","in":"query","description":"End time in ISO 8601 format","required":true,"schema":{"type":"string"}},{"name":"page_paths","in":"query","description":"Comma-separated list of page paths","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Sparkline data for all requested page paths","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PagePathsSparklineResponse"}}}},"400":{"description":"Invalid parameters"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/analytics/recent-activity":{"get":{"tags":["Analytics"],"summary":"Get recent activity events for real-time activity feed","operationId":"get_recent_activity","parameters":[{"name":"project_id","in":"query","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Environment ID (optional)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"since_id","in":"query","description":"Return events with ID greater than this (cursor-based polling)","required":false,"schema":{"type":"integer","format":"int64"}},{"name":"limit","in":"query","description":"Max events to return (default: 50, max: 100)","required":false,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Successfully retrieved recent activity events","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecentActivityResponse"}}}},"400":{"description":"Invalid parameters"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/analytics/sessions/{session_id}":{"get":{"tags":["Analytics"],"summary":"Get detailed information about a specific session including events and request logs","operationId":"get_session_details","parameters":[{"name":"session_id","in":"path","description":"Session ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"project_id","in":"query","description":"Project ID or slug","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Environment ID (optional)","required":false,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Successfully retrieved session details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionDetails"}}}},"400":{"description":"Invalid parameters or project not found"},"404":{"description":"Session not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/analytics/sessions/{session_id}/events":{"get":{"tags":["Analytics"],"operationId":"get_analytics_session_events","parameters":[{"name":"session_id","in":"path","description":"Session ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"project_id","in":"query","description":"Project ID or slug","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Environment ID (optional)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"start_date","in":"query","description":"Start date in format YYYY-MM-DD HH:MM:SS","required":false,"schema":{"type":"string"}},{"name":"end_date","in":"query","description":"End date in format YYYY-MM-DD HH:MM:SS","required":false,"schema":{"type":"string"}},{"name":"limit","in":"query","description":"Number of results to return (default: 100)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"offset","in":"query","description":"Number of results to skip (default: 0)","required":false,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Successfully retrieved session events","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionEventsResponse"}}}},"400":{"description":"Invalid parameters or project not found"},"404":{"description":"Session not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/analytics/sessions/{session_id}/logs":{"get":{"tags":["Analytics"],"operationId":"get_session_logs","parameters":[{"name":"session_id","in":"path","description":"Session ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"project_id","in":"query","description":"Project ID or slug","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Environment ID (optional)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"start_date","in":"query","description":"Start date in format YYYY-MM-DD HH:MM:SS","required":false,"schema":{"type":"string"}},{"name":"end_date","in":"query","description":"End date in format YYYY-MM-DD HH:MM:SS","required":false,"schema":{"type":"string"}},{"name":"limit","in":"query","description":"Number of results to return (default: 100)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"offset","in":"query","description":"Number of results to skip (default: 0)","required":false,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Successfully retrieved session logs","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionLogsResponse"}}}},"400":{"description":"Invalid parameters or project not found"},"404":{"description":"Session not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/analytics/visitor-facets":{"get":{"tags":["Analytics"],"summary":"Get filter dropdown contents for the visitors page. Returns the top\nvalues per dimension with distinct visitor counts so the UI can render\n\"Country — 1,234 visitors\" rows. Each dimension is computed against the\nsegment minus its own filter, so a selected value never collapses its\nown dropdown.","operationId":"get_visitor_facets","parameters":[{"name":"start_date","in":"query","description":"Start date in format YYYY-MM-DD HH:MM:SS","required":true,"schema":{"type":"string"}},{"name":"end_date","in":"query","description":"End date in format YYYY-MM-DD HH:MM:SS","required":true,"schema":{"type":"string"}},{"name":"project_id","in":"query","description":"Project ID or slug","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Environment ID (optional)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"include_crawlers","in":"query","description":"Include crawlers (default: false)","required":false,"schema":{"type":"boolean"}},{"name":"has_activity_only","in":"query","description":"Hide ghost visitors (default: true)","required":false,"schema":{"type":"boolean"}},{"name":"per_facet_limit","in":"query","description":"Top N values per dimension (default: 50, max: 200)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"filter_country","in":"query","description":"Geolocation country","required":false,"schema":{"type":"string"}},{"name":"filter_region","in":"query","description":"Geolocation region","required":false,"schema":{"type":"string"}},{"name":"filter_city","in":"query","description":"Geolocation city","required":false,"schema":{"type":"string"}},{"name":"filter_channel","in":"query","description":"First-touch channel","required":false,"schema":{"type":"string"}},{"name":"filter_referrer","in":"query","description":"First-touch referrer hostname (use 'Direct' for null)","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Top values per dimension","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VisitorFacets"}}}},"400":{"description":"Invalid date format or project not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/analytics/visitors":{"get":{"tags":["Analytics"],"summary":"Get list of visitors with summary information","operationId":"get_visitors","parameters":[{"name":"start_date","in":"query","description":"Start date in format YYYY-MM-DD HH:MM:SS","required":true,"schema":{"type":"string"}},{"name":"end_date","in":"query","description":"End date in format YYYY-MM-DD HH:MM:SS","required":true,"schema":{"type":"string"}},{"name":"project_id","in":"query","description":"Project ID or slug","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Environment ID (optional)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"include_crawlers","in":"query","description":"Include crawlers (default: false)","required":false,"schema":{"type":"boolean"}},{"name":"limit","in":"query","description":"Maximum number of visitors to return (default: 50)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"offset","in":"query","description":"Number of visitors to skip (default: 0)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"has_activity_only","in":"query","description":"Filter to only include visitors with recorded activity (events/sessions). When true, excludes ghost visitors (default: true)","required":false,"schema":{"type":"boolean"}},{"name":"filter_country","in":"query","description":"Geolocation country","required":false,"schema":{"type":"string"}},{"name":"filter_region","in":"query","description":"Geolocation region","required":false,"schema":{"type":"string"}},{"name":"filter_city","in":"query","description":"Geolocation city","required":false,"schema":{"type":"string"}},{"name":"filter_channel","in":"query","description":"First-touch channel","required":false,"schema":{"type":"string"}},{"name":"filter_referrer","in":"query","description":"First-touch referrer hostname (use 'Direct' for null)","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successfully retrieved visitors","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VisitorsResponse"}}}},"400":{"description":"Invalid date format, missing required parameters, or project not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/analytics/visitors/guid/{visitor_id}":{"get":{"tags":["Analytics"],"summary":"Get visitor by GUID with geolocation data","operationId":"get_visitor_by_guid","parameters":[{"name":"visitor_id","in":"path","description":"Visitor GUID (supports enc_ prefix for encrypted IDs)","required":true,"schema":{"type":"string"}},{"name":"project_id","in":"query","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Environment ID (optional)","required":false,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Successfully retrieved visitor with geolocation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VisitorWithGeolocation"}}}},"400":{"description":"Invalid parameters or project not found"},"404":{"description":"Visitor not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/analytics/visitors/id/{id}":{"get":{"tags":["Analytics"],"summary":"Get visitor by numeric ID with geolocation data","operationId":"get_visitor_by_id","parameters":[{"name":"id","in":"path","description":"Visitor numeric ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"project_id","in":"query","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Environment ID (optional)","required":false,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Successfully retrieved visitor with geolocation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VisitorWithGeolocation"}}}},"400":{"description":"Invalid parameters or project not found"},"404":{"description":"Visitor not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/analytics/visitors/{visitor_id}":{"get":{"tags":["Analytics"],"summary":"Get detailed information about a specific visitor by numeric ID","operationId":"get_visitor_details","parameters":[{"name":"visitor_id","in":"path","description":"Visitor numeric ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"project_id","in":"query","description":"Project ID or slug","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Environment ID (optional)","required":false,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Successfully retrieved visitor details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VisitorDetails"}}}},"400":{"description":"Invalid parameters or project not found"},"404":{"description":"Visitor not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/analytics/visitors/{visitor_id}/enrich":{"put":{"tags":["Analytics"],"operationId":"enrich_visitor","parameters":[{"name":"visitor_id","in":"path","description":"Visitor ID - can be numeric ID, GUID, or encrypted GUID (enc_xxx)","required":true,"schema":{"type":"string"}},{"name":"project_id","in":"query","description":"Project ID or slug","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnrichVisitorRequest"}}},"required":true},"responses":{"200":{"description":"Successfully enriched visitor data","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnrichVisitorResponse"}}}},"400":{"description":"Invalid parameters or project not found"},"404":{"description":"Visitor not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/analytics/visitors/{visitor_id}/info":{"get":{"tags":["Analytics"],"summary":"Get visitor record from database","operationId":"get_visitor_info","parameters":[{"name":"visitor_id","in":"path","description":"Visitor numeric ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"project_id","in":"query","description":"Project ID or slug","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Successfully retrieved visitor info","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VisitorRecord"}}}},"400":{"description":"Invalid parameters or project not found"},"404":{"description":"Visitor not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/analytics/visitors/{visitor_id}/journey":{"get":{"tags":["Analytics"],"summary":"Get the complete visitor journey: all events across all sessions, grouped by session","operationId":"get_visitor_journey","parameters":[{"name":"visitor_id","in":"path","description":"Visitor numeric ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"project_id","in":"query","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"limit_sessions","in":"query","description":"Maximum number of sessions to return (default: 50)","required":false,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Successfully retrieved visitor journey","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VisitorJourneyResponse"}}}},"400":{"description":"Invalid parameters"},"404":{"description":"Visitor not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/analytics/visitors/{visitor_id}/sessions":{"get":{"tags":["Analytics"],"summary":"Get all sessions for a specific visitor by numeric ID","operationId":"get_analytics_visitor_sessions","parameters":[{"name":"visitor_id","in":"path","description":"Visitor numeric ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"project_id","in":"query","description":"Project ID or slug","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Environment ID (optional)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"limit","in":"query","description":"Maximum number of sessions to return (default: 100)","required":false,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Successfully retrieved visitor sessions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VisitorSessionsResponse"}}}},"400":{"description":"Invalid parameters or project not found"},"404":{"description":"Visitor not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/analytics/visitors/{visitor_id}/stats":{"get":{"tags":["Analytics"],"summary":"Get visitor statistics","operationId":"get_visitor_stats","parameters":[{"name":"visitor_id","in":"path","description":"Visitor numeric ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"project_id","in":"query","description":"Project ID or slug","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Successfully retrieved visitor statistics","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VisitorStats"}}}},"400":{"description":"Invalid parameters or project not found"},"404":{"description":"Visitor not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/api-keys":{"get":{"tags":["API Keys"],"operationId":"list_api_keys","parameters":[{"name":"page","in":"query","description":"Page number (default: 1)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"page_size","in":"query","description":"Items per page (default: 20)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}}],"responses":{"200":{"description":"API keys retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyListResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"post":{"tags":["API Keys"],"operationId":"create_api_key","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateApiKeyRequest"}}},"required":true},"responses":{"201":{"description":"API key created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateApiKeyResponse"}}}},"400":{"description":"Bad request"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"409":{"description":"Conflict - API key name already exists"},"428":{"description":"Recent MFA verification required"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/api-keys/permissions":{"get":{"tags":["API Keys"],"operationId":"get_api_key_permissions","responses":{"200":{"description":"Available permissions and roles retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AvailablePermissions"}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/api-keys/{id}":{"get":{"tags":["API Keys"],"operationId":"get_api_key","parameters":[{"name":"id","in":"path","description":"API key ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"API key retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"put":{"tags":["API Keys"],"operationId":"update_api_key","parameters":[{"name":"id","in":"path","description":"API key ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateApiKeyRequest"}}},"required":true},"responses":{"200":{"description":"API key updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyResponse"}}}},"400":{"description":"Bad request"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Not found"},"409":{"description":"Conflict - API key name already exists"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["API Keys"],"operationId":"delete_api_key","parameters":[{"name":"id","in":"path","description":"API key ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"API key deleted successfully"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/api-keys/{id}/activate":{"post":{"tags":["API Keys"],"operationId":"activate_api_key","parameters":[{"name":"id","in":"path","description":"API key ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"API key activated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/api-keys/{id}/deactivate":{"post":{"tags":["API Keys"],"operationId":"deactivate_api_key","parameters":[{"name":"id","in":"path","description":"API key ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"API key deactivated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/api-keys/{id}/rotate":{"post":{"tags":["API Keys"],"operationId":"rotate_api_key","parameters":[{"name":"id","in":"path","description":"API key ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"API key rotated successfully; the response contains the new plaintext secret, shown only once","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateApiKeyResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Not found"},"428":{"description":"Recent MFA verification required"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/auth/cli/device/approve":{"post":{"tags":["Authentication"],"operationId":"cli_device_approve","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CliDeviceApproveRequest"}}},"required":true},"responses":{"200":{"description":"Session approved; CLI can now claim the API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CliDeviceApproveResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Browser session required"},"404":{"description":"Unknown user_code"},"409":{"description":"Already resolved"},"410":{"description":"Session expired"},"428":{"description":"Recent MFA verification required"},"500":{"description":"Internal server error"}},"security":[{"session_token":[]}]}},"/auth/cli/device/deny":{"post":{"tags":["Authentication"],"operationId":"cli_device_deny","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CliDeviceApproveRequest"}}},"required":true},"responses":{"200":{"description":"Session denied","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CliDeviceApproveResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Unknown user_code"},"409":{"description":"Already resolved"},"410":{"description":"Session expired"},"500":{"description":"Internal server error"}},"security":[{"session_token":[]}]}},"/auth/cli/device/lookup":{"get":{"tags":["Authentication"],"operationId":"cli_device_lookup","parameters":[{"name":"user_code","in":"query","description":"`user_code` as displayed in the CLI / pasted into the URL.","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Device session metadata","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CliDeviceLookupResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Unknown user_code"},"410":{"description":"Device session expired"},"500":{"description":"Internal server error"}},"security":[{"session_token":[]}]}},"/auth/cli/device/poll":{"post":{"tags":["Authentication"],"operationId":"cli_device_poll","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CliDevicePollRequest"}}},"required":true},"responses":{"200":{"description":"Poll result; check `status` field","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CliDevicePollResponse"}}}},"404":{"description":"Unknown device_code"},"500":{"description":"Internal server error"}}}},"/auth/cli/device/start":{"post":{"tags":["Authentication"],"operationId":"cli_device_start","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CliDeviceStartRequest"}}},"required":true},"responses":{"200":{"description":"Device session created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CliDeviceStartResponse"}}}},"500":{"description":"Internal server error"}}}},"/auth/cli/logout":{"post":{"tags":["Authentication"],"operationId":"cli_logout","responses":{"204":{"description":"API key revoked"},"401":{"description":"Not authenticated"},"403":{"description":"Endpoint requires API key authentication"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/auth/email-status":{"get":{"tags":["Authentication"],"operationId":"email_status","responses":{"200":{"description":"Email configuration status","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailStatusResponse"}}}},"500":{"description":"Internal server error"}}}},"/auth/login":{"post":{"tags":["Authentication"],"operationId":"login","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoginRequest"}}},"required":true},"responses":{"200":{"description":"Login successful, session cookie set","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthResponse"}}}},"401":{"description":"Invalid credentials, or the account's role requires MFA enrollment that has not been completed"},"500":{"description":"Internal server error"}}}},"/auth/oidc/callback":{"get":{"tags":["Authentication"],"operationId":"oidc_callback","parameters":[{"name":"code","in":"query","required":false,"schema":{"type":["string","null"]}},{"name":"state","in":"query","required":false,"schema":{"type":["string","null"]}},{"name":"error","in":"query","required":false,"schema":{"type":["string","null"]}},{"name":"error_description","in":"query","required":false,"schema":{"type":["string","null"]}}],"responses":{"302":{"description":"Redirect to app with session cookie or login error"}}}},"/auth/oidc/login/{slug}":{"get":{"tags":["Authentication"],"operationId":"start_oidc_login_by_slug","parameters":[{"name":"slug","in":"path","description":"OIDC provider slug (from /email-status or /auth/oidc/providers)","required":true,"schema":{"type":"string"}},{"name":"return_to","in":"query","required":false,"schema":{"type":["string","null"]}}],"responses":{"302":{"description":"Redirect to IdP authorize URL"},"404":{"description":"Provider not found"},"503":{"description":"OIDC provider unreachable"}}}},"/auth/oidc/providers":{"get":{"tags":["Authentication"],"operationId":"list_public_providers","responses":{"200":{"description":"Enabled OIDC providers for login page","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OidcProvidersListResponse"}}}}}}},"/auth/password-reset/request":{"post":{"tags":["Authentication"],"operationId":"request_password_reset","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailRequest"}}},"required":true},"responses":{"200":{"description":"Reset email sent if account exists","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthResponse"}}}},"503":{"description":"Email service not configured"}}}},"/auth/password-reset/verify":{"post":{"tags":["Authentication"],"operationId":"reset_password","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResetPasswordRequest"}}},"required":true},"responses":{"200":{"description":"Password reset successful","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthResponse"}}}},"400":{"description":"Invalid or expired token"},"500":{"description":"Internal server error"}}}},"/auth/step-up":{"post":{"tags":["Authentication"],"operationId":"verify_step_up","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VerifyStepUpRequest"}}},"required":true},"responses":{"200":{"description":"Session elevated for sensitive actions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StepUpResponse"}}}},"400":{"description":"Verification code is empty"},"401":{"description":"Invalid code or expired session"},"403":{"description":"Browser session required"},"428":{"description":"MFA setup required"},"429":{"description":"Too many verification attempts"},"500":{"description":"Verification infrastructure failed"}},"security":[{"session_token":[]}]}},"/auth/verify-email":{"get":{"tags":["Authentication"],"operationId":"verify_email","parameters":[{"name":"token","in":"query","description":"Email verification token","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Email verified successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthResponse"}}}},"400":{"description":"Invalid or expired token"},"500":{"description":"Internal server error"}}}},"/auth/verify-mfa":{"post":{"tags":["Authentication"],"operationId":"verify_mfa_challenge","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MfaVerificationRequest"}}},"required":true},"responses":{"204":{"description":"MFA verification successful"},"400":{"description":"Invalid request"},"401":{"description":"Invalid MFA code"},"500":{"description":"Internal server error"}}}},"/backups/alerts":{"get":{"tags":["Backups"],"summary":"List open backup alerts.","description":"Returns all alerts that have not yet been resolved, ordered by `opened_at`\ndescending (newest first). The UI renders these as a banner above the\nBackups page content. Alerts are auto-opened by the watcher and\nauto-resolved when the triggering condition clears.\n\n**Schedule overdue** — the backup scheduler did not enqueue a job within\nthe expected window (1 hour past `next_run`). Usually means the scheduler\ntask is dead or wedged.\n\n**Job stalled** — a `backup_jobs` row has been in `state='pending'` for\nmore than 1 hour. The runner never claimed the job. Usually means the\nrunner task is dead or the runner concurrency cap is too low.","operationId":"list_backup_alerts","responses":{"200":{"description":"List of open backup alerts","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BackupAlertListResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/backups/cleanup":{"post":{"tags":["Backups"],"summary":"Preview or run retention using each selected schedule's configured retention days.","operationId":"cleanup_expired_backups","parameters":[{"name":"dry_run","in":"query","description":"Return the backups selected by retention without deleting anything.","required":false,"schema":{"type":"boolean"}},{"name":"schedule_id","in":"query","description":"Limit cleanup to one backup schedule.","required":false,"schema":{"type":["integer","null"],"format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CleanupExpiredBackupsRequest"}}},"required":true},"responses":{"200":{"description":"Retention cleanup completed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RetentionCleanupReport"}}}},"400":{"description":"Missing or invalid preview candidate list","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Schedule or backup not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Cleanup preview is stale","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Cleanup could not be started","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/backups/external-services/{id}/run":{"post":{"tags":["Backups"],"summary":"Run a backup for an external service manually.","description":"Enqueues the backup for asynchronous execution via the `BackupRunner`\n(ADR-014). Returns `202 Accepted` immediately: pending parent and child\nrows are inserted, and a `backup_jobs` row is enqueued for the resolved\nengine. Poll `GET /backups/{id}` to observe `pending → running → completed`.","operationId":"run_external_service_backup","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RunExternalServiceBackupRequest"}}},"required":true},"responses":{"202":{"description":"Backup enqueued for async execution","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExternalServiceBackupResponse"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"External service or S3 source not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/backups/external-services/{service_id}/backups":{"get":{"tags":["Backups"],"summary":"List all backups for a specific external service (DB-only, no S3 scan).","description":"Returns a paginated list of backups that belong to this service.\nCompletes in <100 ms regardless of S3 endpoint latency because it\nnever touches S3.","operationId":"list_external_service_backups","parameters":[{"name":"service_id","in":"path","description":"External service ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"page","in":"query","description":"Page number (1-based). Defaults to 1.","required":false,"schema":{"type":"integer","format":"int64"}},{"name":"page_size","in":"query","description":"Items per page. Defaults to 20, max 100.","required":false,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"Paginated list of backups for this service","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceBackupListResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/backups/external-services/{service_id}/schedules":{"get":{"tags":["Backups"],"summary":"List the schedules that target a specific external service. Useful for\nthe service detail page (\"which schedules back this DB up?\").","operationId":"list_service_schedules","parameters":[{"name":"service_id","in":"path","description":"External service ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Schedules backing up this service","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/BackupScheduleResponse"}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Service not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/backups/s3-sources":{"get":{"tags":["Backups"],"summary":"List all S3 sources","operationId":"list_s3_sources","responses":{"200":{"description":"List of S3 sources","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/S3SourceResponse"}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Backups"],"summary":"Create a new S3 source","operationId":"create_s3_source","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateS3SourceRequest"}}},"required":true},"responses":{"201":{"description":"S3 source created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/S3SourceResponse"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/backups/s3-sources/test":{"post":{"tags":["Backups"],"summary":"Test S3 connectivity against a prospective source configuration (before creating it).\nThe credentials are NOT persisted. Useful for validating the form in the UI.","operationId":"test_s3_connection_preview","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateS3SourceRequest"}}},"required":true},"responses":{"200":{"description":"Connection test result","content":{"application/json":{"schema":{"$ref":"#/components/schemas/S3ConnectionTestResponse"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/backups/s3-sources/{id}":{"get":{"tags":["Backups"],"summary":"Get an S3 source by ID","operationId":"get_s3_source","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"S3 source details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/S3SourceResponse"}}}},"404":{"description":"S3 source not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["Backups"],"summary":"Delete an S3 source","operationId":"delete_s3_source","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"S3 source deleted"},"404":{"description":"S3 source not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]},"patch":{"tags":["Backups"],"summary":"Update an S3 source","operationId":"update_s3_source","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateS3SourceRequest"}}},"required":true},"responses":{"200":{"description":"S3 source updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/S3SourceResponse"}}}},"404":{"description":"S3 source not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/backups/s3-sources/{id}/backups":{"get":{"tags":["Backups"],"summary":"List all backups in an S3 source","operationId":"list_source_backups","parameters":[{"name":"include_s3_scan","in":"query","description":"When `true`, scan the S3 bucket for backups not tracked in the\nlocal database (useful after disaster-recovery from another Temps\ninstance). Defaults to `false` — the fast DB-only path.","required":false,"schema":{"type":"boolean"}},{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"List of all backups in the source","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SourceBackupIndexResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"S3 source not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/backups/s3-sources/{id}/run":{"post":{"tags":["Backups"],"summary":"Run a backup immediately for an S3 source.","description":"Enqueues the backup for asynchronous execution via the `BackupRunner`\n(ADR-014). Returns `202 Accepted` immediately: a `backups` row is inserted\nwith `state='pending'` and a `backup_jobs` row is enqueued for the\n`ControlPlaneEngine`. Poll `GET /backups/{id}` to observe\n`pending → running → completed`.","operationId":"run_backup_for_source","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RunBackupRequest"}}},"required":true},"responses":{"202":{"description":"Backup enqueued for async execution","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BackupResponse"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"S3 source not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/backups/s3-sources/{id}/set-default":{"post":{"tags":["Backups"],"summary":"Mark an S3 source as the default. All new backups/schedules/services that do not\nexplicitly reference a source will use the default. Returns the updated source.","operationId":"set_default_s3_source","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"S3 source marked as default","content":{"application/json":{"schema":{"$ref":"#/components/schemas/S3SourceResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"S3 source not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/backups/s3-sources/{id}/test":{"post":{"tags":["Backups"],"summary":"Test connectivity to an existing S3 source using its stored credentials.","operationId":"test_s3_source_connection","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Connection test result","content":{"application/json":{"schema":{"$ref":"#/components/schemas/S3ConnectionTestResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"S3 source not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/backups/schedule-runs/{id}/cancel":{"post":{"tags":["Backups"],"summary":"Cancel every non-terminal child backup belonging to a schedule run.","description":"Loops over `state IN ('pending','running')` children and flips each via\nthe same path as the per-backup cancel endpoint. The parent\n`schedule_runs.finished_at` is stamped automatically once no live\nchildren remain. Idempotent: cancelling a run with no live children is\na 200 with `cancelled = 0`.","operationId":"cancel_schedule_run","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"Cancel processed (idempotent)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CancelBackupResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Schedule run not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/backups/schedule-runs/{id}/jobs":{"get":{"tags":["Backups"],"summary":"List the individual backup jobs for a single scheduler run.","description":"Returns each child `backups` row joined with its external service name and\nthe most-recent `backup_jobs` engine key. Used by the schedule detail\naccordion to show per-job detail on row expand.\n\n`page_size` defaults to 50 and is capped at 200.","operationId":"list_schedule_run_jobs","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"Jobs for this scheduler run","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ScheduleRunJobEntry"}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/backups/schedules":{"get":{"tags":["Backups"],"summary":"List all backup schedules","operationId":"list_backup_schedules","responses":{"200":{"description":"List of backup schedules","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/BackupScheduleResponse"}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Backups"],"summary":"Create a new backup schedule","operationId":"create_backup_schedule","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateBackupScheduleRequest"}}},"required":true},"responses":{"201":{"description":"Backup schedule created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BackupScheduleResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/backups/schedules/{id}":{"get":{"tags":["Backups"],"summary":"Get a backup schedule by ID","operationId":"get_backup_schedule","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Backup schedule details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BackupScheduleResponse"}}}},"404":{"description":"Backup schedule not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["Backups"],"summary":"Delete a backup schedule","operationId":"delete_backup_schedule","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"Backup schedule deleted"},"404":{"description":"Backup schedule not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]},"patch":{"tags":["Backups"],"summary":"Update a backup schedule (partial update).","description":"All request fields are optional; only fields that are present in the\nJSON body are updated. Absent fields leave the corresponding column\nunchanged. If `schedule_expression` is changed, `next_run` is\nrecomputed automatically.","operationId":"update_backup_schedule","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateBackupScheduleRequest"}}},"required":true},"responses":{"200":{"description":"Schedule updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BackupScheduleResponse"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Schedule not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/backups/schedules/{id}/backups":{"get":{"tags":["Backups"],"summary":"List backups for a schedule","operationId":"list_backups_for_schedule","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"List of backups for the schedule","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/BackupResponse"}}}}},"404":{"description":"Backup schedule not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/backups/schedules/{id}/disable":{"patch":{"tags":["Backups"],"summary":"Disable a backup schedule","operationId":"disable_backup_schedule","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Backup schedule disabled","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BackupScheduleResponse"}}}},"404":{"description":"Backup schedule not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/backups/schedules/{id}/enable":{"patch":{"tags":["Backups"],"summary":"Enable a backup schedule","operationId":"enable_backup_schedule","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Backup schedule enabled","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BackupScheduleResponse"}}}},"404":{"description":"Backup schedule not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/backups/schedules/{id}/run":{"post":{"tags":["Backups"],"summary":"Immediately fan-out a run for the given schedule (Run Now).","description":"Creates one `schedule_runs` row, one control-plane backup job, and one\nbackup job per supported external service — all in a single transaction.\nReturns `202 Accepted` with a [`ScheduleRunResponse`] containing the new\n`schedule_run_id` and the list of enqueued jobs. Returns `409 Conflict` if\na run for this schedule is already in flight or if the schedule is disabled.","operationId":"run_schedule_now","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"202":{"description":"Fan-out run enqueued for async execution","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScheduleRunResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Schedule not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Run already in flight or schedule disabled","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/backups/schedules/{id}/runs":{"get":{"tags":["Backups"],"summary":"Paginated run history for a backup schedule (one row per scheduler tick).","description":"Returns one [`ScheduleRunSummary`] per scheduler tick, with child backup\ncounts aggregated in a single SQL round-trip. Legacy `backups` rows (pre-\nfan-out) are surfaced as synthetic single-job runs so history does not\ndisappear. Ordered by `started_at DESC` (newest first).\n\nUse `GET /backups/schedule-runs/{run_id}/jobs` to drill into a single run.","operationId":"list_schedule_runs","parameters":[{"name":"page","in":"query","description":"Page number (1-based, defaults to 1, clamped to 1 if < 1).","required":false,"schema":{"type":"integer","format":"int64"}},{"name":"page_size","in":"query","description":"Items per page (defaults to 20, clamped to 100 if > 100).","required":false,"schema":{"type":"integer","format":"int64"}},{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Paginated run history for the schedule","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScheduleRunSummaryList"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Schedule not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/backups/schedules/{id}/services":{"get":{"tags":["Backups"],"summary":"List the external services attached to a backup schedule.","operationId":"list_schedule_services","parameters":[{"name":"id","in":"path","description":"Schedule ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Services attached to this schedule","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ExternalServiceSummary"}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Schedule not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Backups"],"summary":"Attach one or more external services to a backup schedule. Idempotent —\nservices that are already attached are silently skipped (`ON CONFLICT\nDO NOTHING`). Returns the count of newly inserted rows + the total\nmembership after the operation.","operationId":"attach_schedule_services","parameters":[{"name":"id","in":"path","description":"Schedule ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AttachScheduleServicesRequest"}}},"required":true},"responses":{"200":{"description":"Services attached","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AttachScheduleServicesResponse"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Schedule not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/backups/schedules/{id}/services/{service_id}":{"delete":{"tags":["Backups"],"summary":"Detach a single external service from a backup schedule. Idempotent —\nreturns `204` whether or not a row was actually removed.","operationId":"detach_schedule_service","parameters":[{"name":"id","in":"path","description":"Schedule ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"service_id","in":"path","description":"External service ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"Service detached (or was not attached)"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/backups/{id}":{"get":{"tags":["Backups"],"summary":"Get a backup by ID","operationId":"get_backup","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Backup details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BackupResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Backup not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["Backups"],"summary":"Permanently delete one terminal backup from object storage and the database.","operationId":"delete_backup","parameters":[{"name":"id","in":"path","description":"Backup UUID","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Backup deleted"},"400":{"description":"Backup artifact cannot be safely attributed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Backup not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Backup is running, referenced, or lacks safe artifact identity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Object storage or database error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/backups/{id}/cancel":{"post":{"tags":["Backups"],"summary":"Cancel a single in-flight backup.","description":"Flips the parent `backups` row + its latest `backup_jobs` row to\n`failed` with reason `\"cancelled by user \"`. The in-process\n`CancellationToken` is observed on the next heartbeat tick (≤5s), so the\nengine exits cleanly and rollback reaps the sidecar. Idempotent: cancelling\nan already-terminal backup is a 200 with `cancelled = 0`.","operationId":"cancel_backup","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Cancel processed (idempotent)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CancelBackupResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Backup not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/backups/{id}/children":{"get":{"tags":["Backups"],"summary":"List the external-service child backups that belong to a parent backup.","description":"Each entry in `children` corresponds to one `external_service_backups` row,\njoined with `external_services` so the caller receives the service name and\ntype without a second request.\n\nReturns an empty `{ \"children\": [] }` — **not 404** — when the parent\nbackup exists but has no children (e.g. control-plane backups).\nReturns 404 when the parent backup itself does not exist.","operationId":"list_backup_children","parameters":[{"name":"id","in":"path","description":"Integer row id of the parent backup","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Child backup list (may be empty)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChildBackupListResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Parent backup not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/blob":{"get":{"tags":["Blob"],"summary":"List blobs","operationId":"blob_list","parameters":[{"name":"limit","in":"query","description":"Maximum number of items to return","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"prefix","in":"query","description":"Prefix to filter by","required":false,"schema":{"type":"string"}},{"name":"cursor","in":"query","description":"Continuation token for pagination","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"List of blobs","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListBlobsResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Blob"],"summary":"Upload a blob","operationId":"blob_put","requestBody":{"description":"Binary blob data","content":{"application/octet-stream":{"schema":{"type":"string"}}},"required":true},"responses":{"201":{"description":"Blob uploaded successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BlobResponse"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["Blob"],"summary":"Delete blobs","operationId":"blob_delete","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteBlobRequest"}}},"required":true},"responses":{"200":{"description":"Blobs deleted successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteBlobResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/blob/copy":{"post":{"tags":["Blob"],"summary":"Copy a blob to a new location","operationId":"blob_copy","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CopyBlobRequest"}}},"required":true},"responses":{"200":{"description":"Blob copied successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BlobResponse"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Source blob not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/blob/disable":{"delete":{"tags":["Blob Management"],"summary":"Disable Blob service","operationId":"blob_disable","responses":{"200":{"description":"Blob service disabled","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DisableBlobResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Blob service not enabled"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/blob/enable":{"post":{"tags":["Blob Management"],"summary":"Enable Blob service","operationId":"blob_enable","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnableBlobRequest"}}},"required":true},"responses":{"200":{"description":"Blob service enabled","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnableBlobResponse"}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/blob/status":{"get":{"tags":["Blob Management"],"summary":"Get Blob service status","operationId":"blob_status","responses":{"200":{"description":"Blob service status","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BlobStatusResponse"}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/blob/update":{"patch":{"tags":["Blob Management"],"summary":"Update Blob service configuration","operationId":"blob_update","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateBlobRequest"}}},"required":true},"responses":{"200":{"description":"Blob service updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateBlobResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Blob service not enabled"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/blob/{project_id}/{path}":{"get":{"tags":["Blob"],"summary":"Download a blob","operationId":"blob_download","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"path","in":"path","description":"Blob path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Blob content"},"404":{"description":"Blob not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]},"head":{"tags":["Blob"],"summary":"Get blob metadata","operationId":"blob_head","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"path","in":"path","description":"Blob path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Blob metadata in headers"},"404":{"description":"Blob not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/dashboard/projects-analytics":{"get":{"tags":["Events"],"summary":"Get dashboard analytics for multiple projects in a single batch request","description":"Returns unique visitor counts and hourly sparkline data for all requested projects\nusing only 2 SQL queries instead of 2×N per-project queries.","operationId":"get_dashboard_projects_analytics","parameters":[{"name":"project_ids","in":"query","description":"Comma-separated list of project IDs","required":true,"schema":{"type":"string"}},{"name":"start_date","in":"query","description":"Start date for filtering","required":true,"schema":{"type":"string"}},{"name":"end_date","in":"query","description":"End date for filtering","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successfully retrieved batch analytics","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DashboardProjectsAnalyticsResponse"}}}},"400":{"description":"Bad request"},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/deployments/activity-graph":{"get":{"tags":["Deployments"],"summary":"Get deployment activity graph showing daily deployment counts\nSimilar to GitHub's contribution graph","operationId":"get_activity_graph","parameters":[{"name":"project_id","in":"query","description":"Filter by project ID (optional)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Filter by environment ID (optional)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"days","in":"query","description":"Number of days to include (default: 365)","required":false,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Successfully retrieved activity graph","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActivityGraphResponse"}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/deployments/{deployment_id}/vulnerability-scan":{"get":{"tags":["Vulnerability Scans"],"operationId":"get_scan_by_deployment","parameters":[{"name":"deployment_id","in":"path","description":"Deployment ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Scan for the specified deployment","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScanResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"No scan found for deployment","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/deployments/{id}/metrics":{"get":{"tags":["Metrics"],"summary":"Fetch a time-series range for a single metric on a deployment.","operationId":"DeploymentMetricsGetRange","parameters":[{"name":"id","in":"path","description":"Deployment ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"metric","in":"query","description":"Metric name, e.g. `\"pg.connections_active\"`.","required":true,"schema":{"type":"string"}},{"name":"range","in":"query","description":"Time window: `\"1h\"` | `\"6h\"` | `\"24h\"` | `\"7d\"`.","required":false,"schema":{"type":"string"}},{"name":"percentile","in":"query","description":"Optional histogram percentile (0–100). When provided, the endpoint\nfetches histogram buckets and computes the requested quantile.","required":false,"schema":{"type":["number","null"],"format":"double"}}],"responses":{"200":{"description":"Metric time series data points","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/MetricDataPoint"}}}}},"400":{"description":"Invalid query parameters"},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"},"503":{"description":"Metrics store not available"}},"security":[{"bearer_auth":[]}]}},"/deployments/{id}/metrics/enable":{"patch":{"tags":["Metrics"],"summary":"Enable or disable OTLP metric ingestion for a deployment.","description":"When `enabled=true`, seeds the default container alert rules for the\ndeployment via [`temps_monitoring::seed_default_container_rules`] (idempotent).","operationId":"DeploymentMetricsToggle","parameters":[{"name":"id","in":"path","description":"Deployment ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ToggleDeploymentMetricsRequest"}}},"required":true},"responses":{"200":{"description":"Metrics toggle applied"},"400":{"description":"Invalid request"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/deployments/{id}/metrics/latest":{"get":{"tags":["Metrics"],"summary":"Fetch the most-recent metric values for a deployment.","operationId":"DeploymentMetricsGetLatest","parameters":[{"name":"id","in":"path","description":"Deployment ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Map of metric name to latest value","content":{"application/json":{"schema":{"type":"object","additionalProperties":{"type":"number","format":"double"},"propertyNames":{"type":"string"}}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"},"503":{"description":"Metrics store not available"}},"security":[{"bearer_auth":[]}]}},"/dns-providers":{"get":{"tags":["DNS Providers"],"summary":"List all DNS providers","operationId":"list_dns_providers","responses":{"200":{"description":"List of DNS providers","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/DnsProviderResponse"}}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"}},"security":[{"bearer_auth":[]}]},"post":{"tags":["DNS Providers"],"summary":"Create a new DNS provider","description":"The provider's credentials will be tested before creation.\nIf the connection test fails, the provider will not be created.","operationId":"create_dns_provider","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateDnsProviderRequest"}}},"required":true},"responses":{"201":{"description":"DNS provider created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DnsProviderResponse"}}}},"400":{"description":"Invalid request or connection test failed"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"}},"security":[{"bearer_auth":[]}]}},"/dns-providers/{id}":{"get":{"tags":["DNS Providers"],"summary":"Get a DNS provider by ID","operationId":"get_dns_provider","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"DNS provider details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DnsProviderResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Provider not found"}},"security":[{"bearer_auth":[]}]},"put":{"tags":["DNS Providers"],"summary":"Update a DNS provider","description":"If new credentials are supplied, they are tested before the update is\npersisted (same as creation) -- otherwise a provider's credentials (and,\nfor Pebble, its target URL) could be swapped for something invalid or\nunsafe without ever going through validation.","operationId":"update_provider","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateDnsProviderRequest"}}},"required":true},"responses":{"200":{"description":"DNS provider updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DnsProviderResponse"}}}},"400":{"description":"Invalid request"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Provider not found"}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["DNS Providers"],"summary":"Delete a DNS provider","operationId":"delete_dns_provider","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"DNS provider deleted"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Provider not found"}},"security":[{"bearer_auth":[]}]}},"/dns-providers/{id}/domains":{"get":{"tags":["DNS Providers"],"summary":"List managed domains for a provider","operationId":"list_managed_domains","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"List of managed domains","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ManagedDomainResponse"}}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Provider not found"}},"security":[{"bearer_auth":[]}]},"post":{"tags":["DNS Providers"],"summary":"Add a managed domain to a provider","operationId":"add_managed_domain","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddManagedDomainApiRequest"}}},"required":true},"responses":{"201":{"description":"Managed domain added","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ManagedDomainResponse"}}}},"400":{"description":"Invalid request"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Provider not found"}},"security":[{"bearer_auth":[]}]}},"/dns-providers/{id}/test":{"post":{"tags":["DNS Providers"],"summary":"Test provider connection","operationId":"test_provider_connection","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Connection test result","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConnectionTestResult"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Provider not found"}},"security":[{"bearer_auth":[]}]}},"/dns-providers/{id}/zones":{"get":{"tags":["DNS Providers"],"summary":"List zones available in a provider","operationId":"list_provider_zones","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"List of zones","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ZoneListResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Provider not found"}},"security":[{"bearer_auth":[]}]}},"/dns-providers/{provider_id}/domains/{domain}":{"delete":{"tags":["DNS Providers"],"summary":"Remove a managed domain","operationId":"remove_managed_domain","parameters":[{"name":"provider_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"domain","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Managed domain removed"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Domain not found"}},"security":[{"bearer_auth":[]}]},"patch":{"tags":["DNS Providers"],"summary":"Update a managed domain's settings (hostname mode, sync opt-in, auto-manage).","operationId":"update_managed_domain","parameters":[{"name":"provider_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"domain","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateManagedDomainApiRequest"}}},"required":true},"responses":{"200":{"description":"Managed domain updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ManagedDomainResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Domain not found"}},"security":[{"bearer_auth":[]}]}},"/dns-providers/{provider_id}/domains/{domain}/apply-hostname-mode":{"post":{"tags":["DNS Providers"],"summary":"Apply a hostname mode to a managed domain (persist + optional DNS sync +\nroute reload).","operationId":"apply_hostname_mode","parameters":[{"name":"provider_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"domain","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApplyHostnameModeRequest"}}},"required":true},"responses":{"200":{"description":"Hostname mode applied","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HostnamePreviewResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions or token lacks zone access"},"404":{"description":"Domain not found"}},"security":[{"bearer_auth":[]}]}},"/dns-providers/{provider_id}/domains/{domain}/hostname-preview":{"get":{"tags":["DNS Providers"],"summary":"Preview the impact of switching a managed domain's hostname mode.","operationId":"preview_hostname_mode","parameters":[{"name":"mode","in":"query","description":"Target mode: standard|flat","required":true,"schema":{"type":"string"}},{"name":"sync","in":"query","description":"Include DNS record changes","required":false,"schema":{"type":"boolean"}},{"name":"provider_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"domain","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Hostname mode preview","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HostnamePreviewResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Domain not found"}},"security":[{"bearer_auth":[]}]}},"/dns-providers/{provider_id}/domains/{domain}/verify":{"post":{"tags":["DNS Providers"],"summary":"Verify a managed domain","operationId":"verify_managed_domain","parameters":[{"name":"provider_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"domain","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Domain verification result","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ManagedDomainResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Domain not found"}},"security":[{"bearer_auth":[]}]}},"/dns/lookup":{"get":{"tags":["DNS"],"summary":"Lookup DNS A records for a domain","operationId":"lookup_dns_a_records","parameters":[{"name":"domain","in":"query","description":"Domain name to lookup","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successfully retrieved DNS A records","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DnsLookupResponse"}}}},"400":{"description":"Invalid domain name or lookup failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DnsLookupError"}}}}}}},"/domains":{"get":{"tags":["Domains"],"summary":"List all domains","operationId":"list_domains","parameters":[{"name":"page","in":"query","description":"Page number (1-indexed)","required":false,"schema":{"type":["integer","null"],"format":"int64","minimum":0},"example":1},{"name":"page_size","in":"query","description":"Number of items per page (max 100)","required":false,"schema":{"type":["integer","null"],"format":"int64","minimum":0},"example":20},{"name":"search","in":"query","description":"Search domains by name (substring match)","required":false,"schema":{"type":["string","null"]},"example":"example.com"}],"responses":{"200":{"description":"Domains retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListDomainsResponse"}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Domains"],"summary":"Create a new domain","description":"Creates a new domain and automatically requests a Let's Encrypt challenge.\nYou can specify the challenge type (HTTP-01 or DNS-01) in the request.\n\n- **HTTP-01**: Validates domain ownership by placing a file on your web server at `/.well-known/acme-challenge/`\n- **DNS-01**: Validates domain ownership by adding a TXT record to your DNS (required for wildcard domains)","operationId":"create_domain","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateDomainRequest"}}},"required":true},"responses":{"201":{"description":"Domain created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DomainResponse"}}}},"400":{"description":"Invalid input"},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/domains/by-host/{hostname}":{"get":{"tags":["Domains"],"summary":"Get domain details by hostname","operationId":"get_domain_by_host","parameters":[{"name":"hostname","in":"path","description":"Domain hostname","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Domain details retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DomainResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Domain not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/domains/by-host/{hostname}/cert-status":{"get":{"tags":["Domains"],"summary":"Get on-demand TLS certificate status for a hostname","description":"Returns the current cert lifecycle state for a single hostname (from the\n`domains` row) plus the most recent on-demand issuance attempt (from the\n`on_demand_cert_attempts` audit log). This is the operator's first-line\ndiagnostic, surfaced by `temps domain cert-status` (ADR-018 §5). Returns the\nhostname with `None` fields when no on-demand activity exists for it (never a\n404, so the CLI can render \"no attempts recorded\").","operationId":"get_on_demand_cert_status","parameters":[{"name":"hostname","in":"path","description":"Domain hostname","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"On-demand cert status retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CertStatusResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/domains/on-demand-certs":{"get":{"tags":["Domains"],"summary":"List on-demand TLS certificate attempts","description":"Returns rows from the append-only `on_demand_cert_attempts` audit log\n(ADR-018 §5), newest first, each joined with the current authoritative cert\nstate (`status`, `expiration_time`, `backoff_until`) from the `domains` row.\nThis backs the console \"Certificates\" surface. No certificate or private-key\nmaterial is returned — only audit metadata.","operationId":"list_on_demand_certs","parameters":[{"name":"page","in":"query","description":"Page number (1-indexed)","required":false,"schema":{"type":["integer","null"],"format":"int64","minimum":0},"example":1},{"name":"page_size","in":"query","description":"Number of items per page (max 100)","required":false,"schema":{"type":["integer","null"],"format":"int64","minimum":0},"example":20}],"responses":{"200":{"description":"On-demand cert attempts retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListOnDemandCertsResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/domains/{domain_id}/order":{"get":{"tags":["Domains"],"summary":"Get ACME order for a domain","operationId":"get_domain_order","parameters":[{"name":"domain_id","in":"path","description":"Domain ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Order retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AcmeOrderResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Order not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Domains"],"summary":"Create or recreate ACME order for a domain","description":"Creates a new ACME order with Let's Encrypt for the specified domain.\nIf an order already exists, you should cancel it first using the cancel-order endpoint.\nReturns the challenge details that need to be fulfilled (DNS record or HTTP token).","operationId":"create_or_recreate_order","parameters":[{"name":"domain_id","in":"path","description":"Domain ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Order created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DomainChallengeResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Domain not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["Domains"],"summary":"Cancel ACME order for a domain","description":"Cancels the current ACME order for a domain and clears all challenge data.\nThis allows you to start over with a new order if the previous one failed or got stuck.","operationId":"cancel_domain_order","parameters":[{"name":"domain_id","in":"path","description":"Domain ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Order cancelled successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DomainResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Domain not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/domains/{domain_id}/order/finalize":{"post":{"tags":["Domains"],"summary":"Finalize ACME order for a domain","description":"Finalizes the ACME order by completing the challenge validation and requesting the certificate.\nThis should be called after the challenge has been set up (DNS record added or HTTP token served).","operationId":"finalize_order","parameters":[{"name":"domain_id","in":"path","description":"Domain ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Order finalized successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DomainResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Domain or order not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/domains/{domain_id}/setup-dns":{"post":{"tags":["Domains"],"summary":"Setup DNS challenge records automatically using a DNS provider","description":"This endpoint automatically creates the required DNS TXT records for ACME DNS-01 challenge\nvalidation using a configured DNS provider. The domain must have an active DNS challenge\npending (created via POST /domains/{id}/order with dns-01 challenge type).\n\nThis is similar to how email domain DNS records are auto-provisioned.","operationId":"setup_dns_challenge","parameters":[{"name":"domain_id","in":"path","description":"Domain ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetupDnsChallengeRequest"}}},"required":true},"responses":{"200":{"description":"DNS records created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetupDnsChallengeResponse"}}}},"400":{"description":"Bad request - DNS provider not configured or no challenge pending"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Domain or DNS provider not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/domains/{domain}":{"get":{"tags":["Domains"],"summary":"Get domain by ID","operationId":"get_domain_by_id","parameters":[{"name":"domain","in":"path","description":"Domain ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Domain retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DomainResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Domain not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["Domains"],"summary":"Delete a domain","operationId":"delete_domain","parameters":[{"name":"domain","in":"path","description":"Domain name","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Domain deleted successfully"},"401":{"description":"Unauthorized"},"404":{"description":"Domain not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/domains/{domain}/challenge-token":{"get":{"tags":["Domains"],"summary":"Get challenge token for a domain (returns plain text token)","operationId":"get_challenge_token","parameters":[{"name":"domain","in":"path","description":"Domain name","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Challenge token retrieved successfully","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Challenge not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/domains/{domain}/http-challenge-debug":{"get":{"tags":["Domains"],"summary":"Get HTTP challenge debug information","description":"Returns detailed debug information for HTTP-01 challenge including:\n- Whether a challenge exists for the domain\n- The challenge token and URL that Let's Encrypt will access\n- DNS resolution information showing where the domain currently points\n\nThis is useful for debugging why HTTP-01 challenges fail.","operationId":"get_http_challenge_debug","parameters":[{"name":"domain","in":"path","description":"Domain name","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Debug information retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpChallengeDebugResponse"}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/domains/{domain}/provision":{"post":{"tags":["Domains"],"summary":"Provision a domain certificate","operationId":"provision_domain","parameters":[{"name":"domain","in":"path","description":"Domain name","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Certificate provisioning initiated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProvisionResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Domain not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/domains/{domain}/renew":{"post":{"tags":["Domains"],"summary":"Renew domain certificate","description":"For HTTP-01 domains: Automatically renews the certificate\nFor DNS-01 domains (wildcards): Creates a new ACME order and returns challenge data","operationId":"renew_domain","parameters":[{"name":"domain","in":"path","description":"Domain name","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Certificate renewal initiated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProvisionResponse"}}}},"202":{"description":"DNS challenge created - manual action required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DomainChallengeResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Domain not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/domains/{domain}/status":{"get":{"tags":["Domains"],"summary":"Check domain status","operationId":"check_domain_status","parameters":[{"name":"domain","in":"path","description":"Domain ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Domain status retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DomainResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Domain not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/drop/inspect":{"post":{"tags":["Projects"],"summary":"Inspect a source ZIP without creating a project or retaining the upload.","operationId":"inspect_drop_archive","requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/DropArchiveUpload"}}},"required":true},"responses":{"200":{"description":"Detected deployable project roots","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DropInspectionResponse"}}}},"400":{"description":"Invalid or unsupported archive"}},"security":[{"bearer_auth":[]}]}},"/email-domains":{"get":{"tags":["Email Domains"],"summary":"List all email domains","operationId":"list_email_domains","parameters":[{"name":"provider_id","in":"query","description":"Only return domains belonging to this provider","required":false,"schema":{"type":["integer","null"],"format":"int32"}}],"responses":{"200":{"description":"List of email domains","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/EmailDomainResponse"}}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Email Domains"],"summary":"Create a new email domain","operationId":"create_email_domain","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateEmailDomainRequest"}}},"required":true},"responses":{"201":{"description":"Domain created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailDomainWithDnsResponse"}}}},"400":{"description":"Invalid request"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/email-domains/by-domain/{domain}":{"get":{"tags":["Email Domains"],"summary":"Get an email domain by domain name with DNS records","operationId":"get_domain_by_name","parameters":[{"name":"domain","in":"path","description":"Domain name (e.g., 'mail.example.com')","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Email domain details with DNS records","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailDomainWithDnsResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Domain not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/email-domains/{id}":{"get":{"tags":["Email Domains"],"summary":"Get an email domain by ID with DNS records","operationId":"get_domain","parameters":[{"name":"id","in":"path","description":"Domain ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Email domain details with DNS records","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailDomainWithDnsResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Domain not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["Email Domains"],"summary":"Delete an email domain","operationId":"delete_email_domain","parameters":[{"name":"id","in":"path","description":"Domain ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"Domain deleted"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Domain not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/email-domains/{id}/dns-records":{"get":{"tags":["Email Domains"],"summary":"Get DNS records for an email domain","operationId":"get_domain_dns_records","parameters":[{"name":"id","in":"path","description":"Domain ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"DNS records for the domain","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/DnsRecordResponse"}}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Domain not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/email-domains/{id}/setup-dns":{"post":{"tags":["Email Domains"],"summary":"Setup DNS records for an email domain using a configured DNS provider","operationId":"setup_dns","parameters":[{"name":"id","in":"path","description":"Email Domain ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetupDnsRequest"}}},"required":true},"responses":{"200":{"description":"DNS records setup result","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetupDnsResponse"}}}},"400":{"description":"Invalid request or DNS provider not configured"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Domain not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/email-domains/{id}/verify":{"post":{"tags":["Email Domains"],"summary":"Verify an email domain's DNS configuration","operationId":"verify_domain","parameters":[{"name":"id","in":"path","description":"Domain ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Domain verification result with DNS records","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailDomainWithDnsResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Domain not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/email-providers":{"get":{"tags":["Email Providers"],"summary":"List all email providers","operationId":"list_email_providers","responses":{"200":{"description":"List of email providers","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/EmailProviderResponse"}}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Email Providers"],"summary":"Create a new email provider","operationId":"create_email_provider","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateEmailProviderRequest"}}},"required":true},"responses":{"201":{"description":"Provider created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailProviderResponse"}}}},"400":{"description":"Invalid request"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/email-providers/{id}":{"get":{"tags":["Email Providers"],"summary":"Get an email provider by ID","operationId":"get_email_provider","parameters":[{"name":"id","in":"path","description":"Provider ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Email provider details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailProviderResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Provider not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["Email Providers"],"summary":"Delete an email provider","operationId":"delete_email_provider","parameters":[{"name":"id","in":"path","description":"Provider ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"Provider deleted"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Provider not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"patch":{"tags":["Email Providers"],"summary":"Update an email provider","description":"Partial update — any field left out keeps its current value. Most importantly,\nomitting the credential block (`ses_credentials`/`scaleway_credentials`/`smtp_credentials`)\npreserves the stored secret, so operators can rename a provider without re-typing\npasswords. `provider_type` is immutable; to switch providers, delete and recreate.","operationId":"update_email_provider","parameters":[{"name":"id","in":"path","description":"Provider ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateEmailProviderRequest"}}},"required":true},"responses":{"200":{"description":"Provider updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailProviderResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Provider not found"},"409":{"description":"Provider type mismatch"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/email-providers/{id}/test":{"post":{"tags":["Email Providers"],"summary":"Test an email provider by sending a test email to the logged-in user","operationId":"test_provider","parameters":[{"name":"id","in":"path","description":"Provider ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TestEmailRequest"}}},"required":true},"responses":{"200":{"description":"Test email result","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TestEmailResponse"}}}},"400":{"description":"Invalid request"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Provider not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/email-providers/{id}/tracking/setup":{"post":{"tags":["Email Providers"],"summary":"One-click AWS-side setup of SES event tracking (SNS topic + webhook\nsubscription + SESv2 event destination), using the provider's stored\ncredentials.","operationId":"setup_email_tracking","parameters":[{"name":"id","in":"path","description":"Provider ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Setup completed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailTrackingSetupResponse"}}}},"400":{"description":"Provider does not support event tracking"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Provider not found"},"502":{"description":"An AWS call failed — the response detail names the failed step"}},"security":[{"bearer_auth":[]}]}},"/email-providers/{id}/tracking/status":{"get":{"tags":["Email Providers"],"summary":"Live status of SES event tracking for a provider","operationId":"get_email_tracking_status","parameters":[{"name":"id","in":"path","description":"Provider ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Event tracking status","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailTrackingStatusResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Provider not found"}},"security":[{"bearer_auth":[]}]}},"/emails":{"get":{"tags":["Emails"],"summary":"List emails with optional filtering","operationId":"list_emails","parameters":[{"name":"domain_id","in":"query","required":false,"schema":{"type":["integer","null"],"format":"int32"}},{"name":"project_id","in":"query","required":false,"schema":{"type":["integer","null"],"format":"int32"}},{"name":"status","in":"query","required":false,"schema":{"type":["string","null"]}},{"name":"from_address","in":"query","required":false,"schema":{"type":["string","null"]}},{"name":"page","in":"query","required":false,"schema":{"type":["integer","null"],"format":"int64","minimum":0}},{"name":"page_size","in":"query","required":false,"schema":{"type":["integer","null"],"format":"int64","minimum":0}}],"responses":{"200":{"description":"List of emails","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedEmailsResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Emails"],"summary":"Send an email","operationId":"send_email","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendEmailRequestBody"}}},"required":true},"responses":{"201":{"description":"Email sent successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendEmailResponseBody"}}}},"400":{"description":"Invalid request or domain not verified"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/emails/events":{"get":{"tags":["Email Tracking"],"summary":"GET /emails/events","operationId":"get_global_events","parameters":[{"name":"event_type","in":"query","description":"Filter by event type (open, click)","required":false,"schema":{"type":"string"}},{"name":"page","in":"query","description":"Page number (default: 1)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"page_size","in":"query","description":"Page size (default: 20, max: 100)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}}],"responses":{"200":{"description":"Paginated tracking events","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedEventsResponse"}}}},"401":{"description":"Unauthorized"}},"security":[{"bearer_auth":[]}]}},"/emails/events/stats":{"get":{"tags":["Email Tracking"],"summary":"GET /emails/events/stats","operationId":"get_global_event_stats","responses":{"200":{"description":"Global tracking statistics","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GlobalEventStatsResponse"}}}},"401":{"description":"Unauthorized"}},"security":[{"bearer_auth":[]}]}},"/emails/stats":{"get":{"tags":["Emails"],"summary":"Get email statistics","operationId":"get_email_stats","parameters":[{"name":"domain_id","in":"query","description":"Optional domain ID to filter stats","required":false,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Email statistics","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailStatsResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/emails/validate":{"post":{"tags":["Email Validation"],"summary":"Validate an email address","operationId":"validate_email","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidateEmailRequest"}}},"required":true},"responses":{"200":{"description":"Email validation result","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidateEmailResponse"}}}},"400":{"description":"Invalid request"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/emails/{email_id}/track/click/{link_index}":{"get":{"tags":["Email Tracking"],"summary":"Track email link click - redirects to original URL","description":"This endpoint replaces original links in tracked emails.\nNo authentication required - it's called when the recipient clicks a link.","operationId":"track_click","parameters":[{"name":"email_id","in":"path","description":"Email ID (UUID)","required":true,"schema":{"type":"string"}},{"name":"link_index","in":"path","description":"Link index","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"302":{"description":"Redirect to original URL"},"404":{"description":"Link not found"}}}},"/emails/{email_id}/track/open":{"get":{"tags":["Email Tracking"],"summary":"Track email open - returns a 1x1 transparent GIF","description":"This endpoint is embedded as an tag in emails.\nNo authentication required - it's called by the email client.","operationId":"track_open","parameters":[{"name":"email_id","in":"path","description":"Email ID (UUID)","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"1x1 transparent tracking pixel"},"404":{"description":"Email not found"}}}},"/emails/{id}":{"get":{"tags":["Emails"],"summary":"Get an email by ID","operationId":"get_email","parameters":[{"name":"id","in":"path","description":"Email ID (UUID)","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Email details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Email not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/emails/{id}/tracking":{"get":{"tags":["Email Tracking"],"summary":"Get email tracking summary","operationId":"get_email_tracking","parameters":[{"name":"id","in":"path","description":"Email ID (UUID)","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Tracking summary","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailTrackingResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Email not found"}},"security":[{"bearer_auth":[]}]}},"/emails/{id}/tracking/events":{"get":{"tags":["Email Tracking"],"summary":"Get email tracking events","operationId":"get_email_events","parameters":[{"name":"id","in":"path","description":"Email ID (UUID)","required":true,"schema":{"type":"string"}},{"name":"event_type","in":"query","description":"Filter by event type (open, click)","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Tracking events","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/TrackingEventResponse"}}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Email not found"}},"security":[{"bearer_auth":[]}]}},"/emails/{id}/tracking/links":{"get":{"tags":["Email Tracking"],"summary":"Get tracked links for an email","operationId":"get_email_links","parameters":[{"name":"id","in":"path","description":"Email ID (UUID)","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Tracked links","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/TrackedLinkResponse"}}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Email not found"}},"security":[{"bearer_auth":[]}]}},"/external-services":{"get":{"tags":["External Services"],"summary":"Get all external services","operationId":"list_services","parameters":[{"name":"page","in":"query","description":"Page number (1-indexed)","required":false,"schema":{"type":["integer","null"],"format":"int64","minimum":0},"example":1},{"name":"page_size","in":"query","description":"Number of items per page (max 100)","required":false,"schema":{"type":["integer","null"],"format":"int64","minimum":0},"example":20},{"name":"sort_by","in":"query","required":false,"schema":{"type":["string","null"]}},{"name":"sort_order","in":"query","required":false,"schema":{"type":["string","null"]}}],"responses":{"200":{"description":"List of external services","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ExternalServiceInfo"}}}}},"500":{"description":"Internal server error"}}},"post":{"tags":["External Services"],"summary":"Create new external service","operationId":"create_service","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateExternalServiceRequest"}}},"required":true},"responses":{"201":{"description":"Service created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExternalServiceInfo"}}}},"400":{"description":"Invalid request"},"500":{"description":"Internal server error"}}}},"/external-services/available-containers":{"get":{"tags":["External Services"],"summary":"List available Docker containers that can be imported as services","operationId":"list_available_containers","responses":{"200":{"description":"List of available containers","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/AvailableContainerInfo"}}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/external-services/by-slug/{slug}":{"get":{"tags":["External Services"],"summary":"Get external service details by slug","operationId":"get_service_by_slug","parameters":[{"name":"slug","in":"path","description":"External service slug","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"External service details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExternalServiceDetails"}}}},"404":{"description":"Service not found"},"500":{"description":"Internal server error"}}}},"/external-services/health-status-batch":{"get":{"tags":["External Services"],"summary":"Current health status for many services at once","description":"Powers the status dot on the Storage list page. Pass a comma-separated\nlist of service IDs via `?ids=1,2,3`. Omit to get every service.","operationId":"list_service_health_statuses","parameters":[{"name":"ids","in":"query","description":"Comma-separated service IDs. Omit for all services.","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Batch of current health statuses","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceHealthStatusBatchResponse"}}}},"500":{"description":"Internal server error"}}}},"/external-services/import":{"post":{"tags":["External Services"],"summary":"Import an existing Docker container as a managed external service","operationId":"import_external_service","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImportExternalServiceRequest"}}},"required":true},"responses":{"201":{"description":"Service imported successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExternalServiceInfo"}}}},"400":{"description":"Invalid request"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/external-services/projects/{project_id}":{"get":{"tags":["External Services"],"summary":"List services linked to a project","operationId":"list_project_services","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"page","in":"query","description":"Page number (1-indexed)","required":false,"schema":{"type":["integer","null"],"format":"int64","minimum":0},"example":1},{"name":"page_size","in":"query","description":"Number of items per page (max 100)","required":false,"schema":{"type":["integer","null"],"format":"int64","minimum":0},"example":20},{"name":"sort_by","in":"query","required":false,"schema":{"type":["string","null"]}},{"name":"sort_order","in":"query","required":false,"schema":{"type":["string","null"]}}],"responses":{"200":{"description":"List of services linked to project","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ProjectServiceInfo"}}}}},"404":{"description":"Project not found"},"500":{"description":"Internal server error"}}}},"/external-services/projects/{project_id}/environment":{"get":{"tags":["External Services"],"summary":"Get all environment variables for all services linked to a project","operationId":"get_project_service_environment_variables","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Map of service IDs to their environment variables","content":{"application/json":{"schema":{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"string"},"propertyNames":{"type":"string"}},"propertyNames":{"type":"integer","format":"int32"}}}}},"404":{"description":"Project not found"},"500":{"description":"Internal server error"}}}},"/external-services/providers/metadata":{"get":{"tags":["External Services"],"summary":"Get provider metadata (display names, icons, descriptions)","operationId":"get_providers_metadata","responses":{"200":{"description":"List of provider metadata","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ProviderMetadata"}}}}},"500":{"description":"Internal server error"}}}},"/external-services/providers/metadata/{service_type}":{"get":{"tags":["External Services"],"summary":"Get metadata for a specific provider","operationId":"get_provider_metadata","parameters":[{"name":"service_type","in":"path","description":"Service type (mongodb, postgres, redis, s3)","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Provider metadata","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProviderMetadata"}}}},"404":{"description":"Provider not found"},"500":{"description":"Internal server error"}}}},"/external-services/types":{"get":{"tags":["External Services"],"summary":"Get available service types","operationId":"get_service_types","responses":{"200":{"description":"List of available service types","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ServiceTypeRoute"}}}}},"500":{"description":"Internal server error"}}}},"/external-services/types/{service_type}/parameters":{"get":{"tags":["External Services"],"summary":"Get parameter schema for a specific service type","operationId":"get_service_type_parameters","parameters":[{"name":"service_type","in":"path","description":"Service type","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Service type parameter schema"},"404":{"description":"Service type not found"},"500":{"description":"Internal server error"}}}},"/external-services/{id}":{"get":{"tags":["External Services"],"summary":"Get external service details","operationId":"get_service","parameters":[{"name":"id","in":"path","description":"External service ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"External service details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExternalServiceDetails"}}}},"404":{"description":"Service not found"},"500":{"description":"Internal server error"}}},"put":{"tags":["External Services"],"summary":"Update external service","operationId":"update_service","parameters":[{"name":"id","in":"path","description":"External service ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateExternalServiceRequest"}}},"required":true},"responses":{"200":{"description":"Service updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExternalServiceInfo"}}}},"400":{"description":"Invalid request"},"404":{"description":"Service not found"},"409":{"description":"A major upgrade is in progress for this service"},"500":{"description":"Internal server error"}}},"delete":{"tags":["External Services"],"summary":"Delete external service","operationId":"delete_service","parameters":[{"name":"id","in":"path","description":"External service ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"Service deleted successfully"},"400":{"description":"Cannot delete: service is still linked to projects"},"404":{"description":"Service not found"},"500":{"description":"Internal server error"}}}},"/external-services/{id}/cluster-health":{"get":{"tags":["External Services"],"summary":"Per-member health for a Postgres HA cluster.","description":"Reads pg_auto_failover's `pgautofailover.node` table from the cluster's\nmonitor (TLS, autoctl_node) and joins each member with its\n`pg_stat_replication` row from the current primary. Returns one row per\ndata member with role/state, sync state, and replay lag.\n\nReturns `200` with `monitor_error` set when the monitor is briefly\nunreachable (UI surfaces it as a banner above the table); the table\nitself is empty in that case. Returns `400` for non-cluster services.","operationId":"get_cluster_health","parameters":[{"name":"id","in":"path","description":"External service ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Per-member cluster health report","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClusterHealthReportResponse"}}}},"400":{"description":"Service is not a cluster"},"401":{"description":"Unauthorized"},"404":{"description":"Service not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/external-services/{id}/health-check":{"post":{"tags":["External Services"],"summary":"Run a health check for one service right now","description":"Triggers the same engine-specific probe as the background monitor, writes\na history row, updates the denormalized fields on `external_services`, and\nfires alerts on the Nth consecutive failure (so consecutive-failure state\nstays honest). Returns the fresh snapshot the UI can display immediately.","operationId":"trigger_service_health_check","parameters":[{"name":"id","in":"path","description":"External service ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Fresh health snapshot after probing","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceHealthResponse"}}}},"404":{"description":"Service not found"},"500":{"description":"Internal server error"},"503":{"description":"Health monitor not running on this node"}}}},"/external-services/{id}/health-status":{"get":{"tags":["External Services"],"summary":"Persisted health status for an external service","description":"Returns the latest health probe result recorded by\n`ExternalServiceHealthMonitor`, plus recent check history for sparklines\nand a 24-hour uptime percentage. Safe to poll from the UI every 30s.","operationId":"get_service_health_status","parameters":[{"name":"id","in":"path","description":"External service ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"limit","in":"query","description":"Max number of recent checks (default 50, max 200)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}}],"responses":{"200":{"description":"Current health + recent history","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceHealthResponse"}}}},"404":{"description":"Service not found"},"500":{"description":"Internal server error"}}}},"/external-services/{id}/members":{"post":{"tags":["External Services"],"summary":"Begin adding a single new member to a running cluster.","description":"Currently only `replica` members can be added at runtime. The\nresponse is **202 Accepted** as soon as the validation passes and\nthe placeholder `service_members` row is inserted. The actual\ncontainer provisioning + DNS registration runs in the background;\npoll `GET /external-services/{id}/members/{member_id}` to watch\n`provisioning_step` advance through the phases.","operationId":"add_cluster_member","parameters":[{"name":"id","in":"path","description":"External service ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddClusterMemberRequest"}}},"required":true},"responses":{"202":{"description":"Cluster member provisioning started","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceMemberInfo"}}}},"400":{"description":"Validation failed (wrong topology, status, or role)"},"404":{"description":"Service not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/external-services/{id}/members/{member_id}":{"get":{"tags":["External Services"],"summary":"Get a single cluster member's current state.","description":"Used by the add-member page to poll the row every second while the\nbackground provisioning task walks through its phases. The\n`provisioning_step` field advances through `inserting_row` →\n`provisioning_container` → `registering_dns` → `done` (or `failed`\nwith `provisioning_error` set).","operationId":"get_cluster_member","parameters":[{"name":"id","in":"path","description":"External service ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"member_id","in":"path","description":"Cluster member ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Cluster member details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceMemberInfo"}}}},"404":{"description":"Service or member not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["External Services"],"summary":"Remove a single member from a running cluster.","description":"Refuses to remove the monitor (singleton), the current primary\n(failover first), or any member if the cluster would drop below the\n2-data-member quorum required for HA. Stops + removes the container,\ndeletes the row, and drops the Tier-2 DNS record.","operationId":"remove_cluster_member","parameters":[{"name":"id","in":"path","description":"External service ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"member_id","in":"path","description":"Cluster member ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"Cluster member removed"},"400":{"description":"Validation failed (monitor, primary, or quorum violation)"},"404":{"description":"Service or member not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/external-services/{id}/members/{member_id}/promote":{"post":{"tags":["External Services"],"summary":"Promote a replica to primary by triggering a pg_auto_failover\nfailover. The monitor demotes the current primary and the chosen\nreplica transitions to primary; the role reconciler then refreshes\nthe role-aliased VIPs (≤30s).","operationId":"promote_cluster_member","parameters":[{"name":"id","in":"path","description":"External service ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"member_id","in":"path","description":"Cluster member ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"202":{"description":"Promotion initiated"},"400":{"description":"Validation failed (monitor, already primary, not running, etc.)"},"404":{"description":"Service or member not found"},"500":{"description":"pg_autoctl perform promotion failed"}},"security":[{"bearer_auth":[]}]}},"/external-services/{id}/metrics":{"get":{"tags":["Metrics"],"summary":"Fetch a time-series range for a single metric on an external service.","description":"Pass `percentile` to compute a histogram quantile instead of a plain\ngauge/counter average.","operationId":"ExternalServiceMetricsGetRange","parameters":[{"name":"id","in":"path","description":"External service ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"metric","in":"query","description":"Metric name, e.g. `\"pg.connections_active\"`.","required":true,"schema":{"type":"string"}},{"name":"range","in":"query","description":"Time window: `\"1h\"` | `\"6h\"` | `\"24h\"` | `\"7d\"`.","required":false,"schema":{"type":"string"}},{"name":"percentile","in":"query","description":"Optional histogram percentile (0–100). When provided, the endpoint\nfetches histogram buckets and computes the requested quantile.","required":false,"schema":{"type":["number","null"],"format":"double"}}],"responses":{"200":{"description":"Metric time series data points","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/MetricDataPoint"}}}}},"400":{"description":"Invalid query parameters"},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"},"503":{"description":"Metrics store not available"}},"security":[{"bearer_auth":[]}]}},"/external-services/{id}/metrics/alert-rules":{"get":{"tags":["Metrics"],"summary":"List all monitoring alert rules for an external service.","operationId":"ExternalServiceMetricsGetAlertRules","parameters":[{"name":"id","in":"path","description":"External service ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"List of alert rules","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ServiceAlertRuleResponse"}}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Metrics"],"summary":"Create a monitoring alert rule for an external service.","description":"If metric collection is enabled and the service engine has default rules,\nseeding is idempotent (ON CONFLICT DO NOTHING).","operationId":"ExternalServiceMetricsCreateAlertRule","parameters":[{"name":"id","in":"path","description":"External service ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceCreateAlertRuleRequest"}}},"required":true},"responses":{"201":{"description":"Alert rule created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceAlertRuleResponse"}}}},"400":{"description":"Invalid request"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/external-services/{id}/metrics/alert-rules/{rule_id}":{"put":{"tags":["Metrics"],"summary":"Update an existing monitoring alert rule for an external service.","operationId":"ExternalServiceMetricsUpdateAlertRule","parameters":[{"name":"id","in":"path","description":"External service ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"rule_id","in":"path","description":"Alert rule ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceUpdateAlertRuleRequest"}}},"required":true},"responses":{"200":{"description":"Updated alert rule","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceAlertRuleResponse"}}}},"400":{"description":"Invalid request"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Alert rule not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["Metrics"],"summary":"Delete a monitoring alert rule for an external service.","operationId":"ExternalServiceMetricsDeleteAlertRule","parameters":[{"name":"id","in":"path","description":"External service ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"rule_id","in":"path","description":"Alert rule ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"Alert rule deleted"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Alert rule not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/external-services/{id}/metrics/by-database":{"get":{"tags":["Metrics"],"summary":"Return the latest per-database metric values for a Postgres service.","description":"Groups `pg_stat_database` / size metrics by `datname` so the UI can show a\nbreakdown table (each database with its own size, cache-hit ratio, etc.)\nrather than collapsing every database into one value.","operationId":"ExternalServiceMetricsByDatabase","parameters":[{"name":"id","in":"path","description":"External service ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Per-database metric breakdown","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DatabaseMetricsResponse"}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"},"503":{"description":"Metrics not available"}},"security":[{"bearer_auth":[]}]}},"/external-services/{id}/metrics/enable":{"patch":{"tags":["Metrics"],"summary":"Enable or disable metric collection for an external service.","description":"When `enabled=true`, seeds the default alert rules for the service's engine\nvia [`temps_monitoring::seed_default_rules`] (idempotent).","operationId":"ExternalServiceMetricsToggle","parameters":[{"name":"id","in":"path","description":"External service ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ToggleServiceMetricsRequest"}}},"required":true},"responses":{"200":{"description":"Metrics toggle applied"},"400":{"description":"Invalid request"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Service not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/external-services/{id}/metrics/latest":{"get":{"tags":["Metrics"],"summary":"Fetch the most-recent value for every tracked metric on an external service.","operationId":"ExternalServiceMetricsGetLatest","parameters":[{"name":"id","in":"path","description":"External service ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Map of metric name to latest value","content":{"application/json":{"schema":{"type":"object","additionalProperties":{"type":"number","format":"double"},"propertyNames":{"type":"string"}}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"},"503":{"description":"Metrics store not available"}},"security":[{"bearer_auth":[]}]}},"/external-services/{id}/metrics/status":{"get":{"tags":["Metrics"],"summary":"Return the freshness status (last-received timestamp) for a service.","description":"Cheap O(1) lookup against `service_metrics_status` — used by the UI to show\n\"last received at …\" without scanning the metrics hypertable.","operationId":"ExternalServiceMetricsStatus","parameters":[{"name":"id","in":"path","description":"External service ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Metrics freshness status","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MetricsStatusResponse"}}}},"503":{"description":"Metrics not available"}},"security":[{"bearer_auth":[]}]}},"/external-services/{id}/parameters/{param_name}":{"get":{"tags":["External Services"],"summary":"Reveal one sensitive service parameter. Service detail responses never\ncontain plaintext values; every successful reveal is recorded separately.","operationId":"reveal_service_parameter","parameters":[{"name":"id","in":"path","description":"External service ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"param_name","in":"path","description":"Sensitive parameter name","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Sensitive parameter value","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SensitiveValueResponse"}}}},"400":{"description":"Parameter is not sensitive"},"403":{"description":"Caller cannot access a project linked to this service"},"404":{"description":"Service or parameter not found"},"500":{"description":"Internal server error"}}}},"/external-services/{id}/preview-environment-masked":{"get":{"tags":["External Services"],"summary":"Get environment variables preview with masked sensitive values","operationId":"get_service_preview_environment_variables_masked","parameters":[{"name":"id","in":"path","description":"External service ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Preview of environment variables with sensitive values masked as ***","content":{"application/json":{"schema":{"type":"object","additionalProperties":{"type":"string"},"propertyNames":{"type":"string"}}}}},"404":{"description":"Service not found"},"500":{"description":"Internal server error"}}}},"/external-services/{id}/preview-environment-names":{"get":{"tags":["External Services"],"summary":"Get environment variable names preview (safe - no sensitive values)","operationId":"get_service_preview_environment_variable_names","parameters":[{"name":"id","in":"path","description":"External service ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"List of environment variable names that would be provided","content":{"application/json":{"schema":{"type":"array","items":{"type":"string"}}}}},"404":{"description":"Service not found"},"500":{"description":"Internal server error"}}}},"/external-services/{id}/projects":{"get":{"tags":["External Services"],"summary":"List projects linked to service","operationId":"list_service_projects","parameters":[{"name":"id","in":"path","description":"External service ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"page","in":"query","description":"Page number (1-indexed)","required":false,"schema":{"type":["integer","null"],"format":"int64","minimum":0},"example":1},{"name":"page_size","in":"query","description":"Number of items per page (max 100)","required":false,"schema":{"type":["integer","null"],"format":"int64","minimum":0},"example":20},{"name":"sort_by","in":"query","required":false,"schema":{"type":["string","null"]}},{"name":"sort_order","in":"query","required":false,"schema":{"type":["string","null"]}}],"responses":{"200":{"description":"List of linked projects","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ProjectServiceInfo"}}}}},"404":{"description":"Service not found"},"500":{"description":"Internal server error"}}},"post":{"tags":["External Services"],"summary":"Link service to project","operationId":"link_service_to_project","parameters":[{"name":"id","in":"path","description":"External service ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LinkServiceRequest"}}},"required":true},"responses":{"201":{"description":"Service linked to project successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectServiceInfo"}}}},"404":{"description":"Service or project not found"},"500":{"description":"Internal server error"}}}},"/external-services/{id}/projects/{project_id}":{"delete":{"tags":["External Services"],"summary":"Unlink service from project","operationId":"unlink_service_from_project","parameters":[{"name":"id","in":"path","description":"External service ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"Service unlinked from project successfully"},"404":{"description":"Service link not found"},"500":{"description":"Internal server error"}}}},"/external-services/{id}/projects/{project_id}/environment":{"get":{"tags":["External Services"],"summary":"Get all environment variables for a service-project pair","operationId":"get_service_environment_variables","parameters":[{"name":"id","in":"path","description":"External service ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"List of environment variables","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/EnvironmentVariableInfo"}}}}},"404":{"description":"Service or project not found"},"500":{"description":"Internal server error"}}}},"/external-services/{id}/projects/{project_id}/environment/{var_name}":{"get":{"tags":["External Services"],"summary":"Get specific environment variable for a service-project pair","operationId":"get_service_environment_variable","parameters":[{"name":"id","in":"path","description":"External service ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"var_name","in":"path","description":"Environment variable name","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Environment variable value","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnvironmentVariableInfo"}}}},"403":{"description":"Plaintext secret access is not permitted"},"404":{"description":"Service, project, or variable not found"},"500":{"description":"Internal server error"}}}},"/external-services/{id}/resources":{"patch":{"tags":["External Services"],"summary":"Update a service's resource limits (memory, CPU caps).","description":"Persists the new caps to the encrypted config AND live-applies them\nvia Docker's update API. Memory and CPU can be hot-changed without a\nrestart on running containers; stopped containers also accept the\nupdate and pick up the new caps on next start.\n\nPass `null` (or omit) any field to leave it unlimited. A request where\nevery field is `null` removes any existing limits.\n\nThe response includes a per-container `applied[]` list so the caller\ncan tell which members got the update and which were skipped (e.g.,\ncontainer not yet created, or `docker update` rejected because the\nnew memory cap is below current usage).","operationId":"update_service_resources","parameters":[{"name":"id","in":"path","description":"External service ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceResourceLimits"}}},"required":true},"responses":{"200":{"description":"Updated resource limits","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResourceLimitsUpdateResponse"}}}},"400":{"description":"Invalid resource limits"},"404":{"description":"Service not found"},"500":{"description":"Internal server error"}}}},"/external-services/{id}/restore":{"post":{"tags":["Restore"],"operationId":"start_restore","parameters":[{"name":"id","in":"path","description":"External service id (source for the restore)","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StartRestoreRequest"}}},"required":true},"responses":{"202":{"description":"Restore run started","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RestoreRunView"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Backup or service not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/external-services/{id}/restore-capabilities":{"get":{"tags":["Restore"],"operationId":"get_restore_capabilities","parameters":[{"name":"id","in":"path","description":"External service id","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Capabilities declared by the service","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RestoreCapabilitiesResponse"}}}},"404":{"description":"Service not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/external-services/{id}/restore-plan":{"post":{"tags":["Restore"],"operationId":"plan_restore","parameters":[{"name":"id","in":"path","description":"Target service id","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StartRestoreRequest"}}},"required":true},"responses":{"200":{"description":"Preview of what the restore will do","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RestorePlan"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Backup or service not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/external-services/{id}/restore-runs":{"get":{"tags":["Restore"],"operationId":"list_restore_runs_for_service","parameters":[{"name":"id","in":"path","description":"External service id","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Recent restore runs for the service","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/RestoreRunView"}}}}}},"security":[{"bearer_auth":[]}]}},"/external-services/{id}/retry":{"post":{"tags":["External Services"],"summary":"Retry a failed cluster service initialization.","description":"Cleans up any leftover containers from the previous attempt and\nre-runs cluster initialization with the provided member specifications.","operationId":"retry_cluster","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RetryClusterRequest"}}},"required":true},"responses":{"200":{"description":"Cluster retry initiated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExternalServiceInfo"}}}},"400":{"description":"Service is not a failed cluster"},"404":{"description":"Service not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/external-services/{id}/runtime":{"get":{"tags":["External Services"],"summary":"Inspect a service's container(s): status, restart count, OOM-killed flag,\nexit code, and the cgroup limits actually applied.","operationId":"get_service_runtime","parameters":[{"name":"id","in":"path","description":"External service ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Container runtime snapshot","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceRuntimeReport"}}}},"404":{"description":"Service not found"},"500":{"description":"Internal server error"}}}},"/external-services/{id}/start":{"post":{"tags":["External Services"],"summary":"Start an external service","operationId":"start_service","parameters":[{"name":"id","in":"path","description":"External service ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Service started successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExternalServiceInfo"}}}},"404":{"description":"Service not found"},"409":{"description":"A Postgres major upgrade is in progress for this service"},"500":{"description":"Internal server error"}}}},"/external-services/{id}/stats":{"get":{"tags":["External Services"],"summary":"Sample current CPU/memory usage from each of a service's containers.\nOne-shot sample, no streaming. Cheap to call (single Docker round-trip\nper member) so the UI can poll on a 5–10s interval.","operationId":"get_service_stats","parameters":[{"name":"id","in":"path","description":"External service ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Container stats snapshot","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceStatsReport"}}}},"404":{"description":"Service not found"},"500":{"description":"Internal server error"}}}},"/external-services/{id}/stop":{"post":{"tags":["External Services"],"summary":"Stop an external service","operationId":"stop_service","parameters":[{"name":"id","in":"path","description":"External service ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Service stopped successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExternalServiceInfo"}}}},"404":{"description":"Service not found"},"500":{"description":"Internal server error"}}}},"/external-services/{id}/upgrade":{"post":{"tags":["External Services"],"summary":"Upgrade external service to new Docker image with data migration\nThis endpoint uses service-specific upgrade procedures (e.g., pg_upgrade for PostgreSQL)","operationId":"upgrade_service","parameters":[{"name":"id","in":"path","description":"External service ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpgradeExternalServiceRequest"}}},"required":true},"responses":{"200":{"description":"Service upgraded successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExternalServiceInfo"}}}},"400":{"description":"Invalid request or upgrade not supported"},"404":{"description":"Service not found"},"409":{"description":"A major upgrade is already in progress for this service"},"500":{"description":"Internal server error"}}}},"/external-services/{id}/wal-health":{"get":{"tags":["External Services"],"summary":"Postgres WAL & archive health snapshot","description":"Returns the latest WAL/archive health snapshot recorded by the background\nhealth monitor for a Postgres external service. Powers the warning banner\non the service detail page when the disk is filling up due to stale\nreplication slots, archive backlog, or misconfigured `archive_command`.\n\nReturns 404 when no snapshot exists yet (probe hasn't run, or the service\nisn't Postgres).","operationId":"getPostgresWalHealth","parameters":[{"name":"id","in":"path","description":"External service ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Latest WAL health snapshot","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PostgresWalHealth"}}}},"404":{"description":"Service not found, or no WAL snapshot available"},"500":{"description":"Internal server error"}}}},"/external-services/{service_id}/pg-stat-statements/enable":{"post":{"tags":["External Services"],"summary":"Enable `pg_stat_statements` on a standalone Postgres service.","description":"Stops the container and restarts it so that the\n`shared_preload_libraries=pg_stat_statements` CMD flag (baked into every\nnew standalone Postgres container) takes effect. The named data volume is\nreused unchanged — no data is lost.\n\n**Clustered (HA) services are rejected** with 422 — a blind single-container\nrestart bypasses controlled failover. For clustered services the response\nbody describes the manual rolling-restart steps.\n\nConfirmation is the caller's responsibility (UI dialog / CLI `--yes` flag)\nbefore invoking this endpoint.","operationId":"ExternalServiceEnablePgStatStatements","parameters":[{"name":"service_id","in":"path","description":"ID of the provisioned standalone Postgres service","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Container restarted; pg_stat_statements now active","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnablePgStatStatementsResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions (requires external_services:write)"},"404":{"description":"Service not found"},"422":{"description":"Service is not standalone Postgres (cluster or wrong type)"},"500":{"description":"Restart failed"}},"security":[{"bearer_auth":[]}]}},"/external-services/{service_id}/pg-stat-statements/reset":{"post":{"tags":["External Services"],"summary":"Reset all statistics accumulated by `pg_stat_statements` for a Postgres\nservice. This affects every user, database, and normalized query tracked by\nthe target Postgres instance and cannot be undone.","operationId":"ExternalServiceResetPgStatStatements","parameters":[{"name":"service_id","in":"path","description":"ID of the provisioned Postgres service","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"description":"Explicit confirmation of the global, irreversible reset","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResetPgStatStatementsRequest"}}},"required":true},"responses":{"200":{"description":"All accumulated pg_stat_statements statistics cleared","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResetPgStatStatementsResponse"}}}},"400":{"description":"Missing or invalid reset confirmation"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions (requires external_services:write)"},"404":{"description":"Service not found"},"422":{"description":"Service is not Postgres"},"502":{"description":"Target Postgres rejected or failed the reset operation"}},"security":[{"bearer_auth":[]}]}},"/external-services/{service_id}/pg-stat-statements/slow-queries":{"get":{"tags":["External Services"],"operationId":"get_slow_queries","parameters":[{"name":"service_id","in":"path","description":"ID of the provisioned Postgres service","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"page","in":"query","description":"Page number (1-based). Defaults to 1.","required":false,"schema":{"type":["integer","null"],"format":"int32","minimum":0}},{"name":"page_size","in":"query","description":"Number of rows per page (1–100). Defaults to 20.","required":false,"schema":{"type":["integer","null"],"format":"int32","minimum":0}},{"name":"sort_by","in":"query","description":"Column to sort by: one of `calls`, `total_exec_time_ms`,\n`mean_exec_time_ms`, `rows`, `cache_hit_ratio`. Defaults to\n`mean_exec_time_ms`. Applied server-side so ordering stays\nconsistent across pages.","required":false,"schema":{"type":["string","null"]}},{"name":"sort_order","in":"query","description":"Sort direction: `asc` or `desc`. Defaults to `desc`.","required":false,"schema":{"type":["string","null"]}}],"responses":{"200":{"description":"Paginated slow queries from pg_stat_statements","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SlowQueriesResponse"}}}},"400":{"description":"Invalid pagination or sort parameters"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions (requires external_services:read)"},"404":{"description":"Service not found"},"422":{"description":"Service is not a Postgres service"},"503":{"description":"pg_stat_statements extension not available (container restart required)"}},"security":[{"bearer_auth":[]}]}},"/external-services/{service_id}/query/containers":{"get":{"tags":["External Services - Query"],"summary":"List containers at the root level (databases, keyspaces, etc.)","operationId":"list_root_containers","parameters":[{"name":"service_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"List of root containers","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ContainerResponse"}}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Service not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/external-services/{service_id}/query/containers/{path}":{"get":{"tags":["External Services - Query"],"summary":"List containers at a specific path\nPath segments are separated by forward slashes\nExample: /external-services/1/query/containers/mydb lists schemas in database \"mydb\"","operationId":"list_containers_at_path","parameters":[{"name":"service_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"path","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"List of containers","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ContainerResponse"}}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Service or container not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/external-services/{service_id}/query/containers/{path}/entities":{"get":{"tags":["External Services - Query"],"summary":"List entities (tables, collections, etc.) in a container\nExample: /external-services/1/query/containers/mydb/public/entities lists tables in the public schema","operationId":"list_entities","parameters":[{"name":"limit","in":"query","description":"Maximum number of entities to return (default: 100, max: 1000)","required":false,"schema":{"type":"integer","minimum":0}},{"name":"token","in":"query","description":"Continuation token for pagination","required":false,"schema":{"type":"string"}},{"name":"service_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"path","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Paginated list of entities","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedEntitiesResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Service or container not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/external-services/{service_id}/query/containers/{path}/entities/{entity}":{"get":{"tags":["External Services - Query"],"summary":"Get detailed information about an entity (table schema)","operationId":"get_entity_info","parameters":[{"name":"service_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"path","in":"path","required":true,"schema":{"type":"string"}},{"name":"entity","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Entity details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EntityInfoResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Service, container, or entity not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/external-services/{service_id}/query/containers/{path}/entities/{entity}/data":{"post":{"tags":["External Services - Query"],"summary":"Query data from an entity with optional filters, pagination, and sorting","operationId":"query_data","parameters":[{"name":"service_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"path","in":"path","required":true,"schema":{"type":"string"}},{"name":"entity","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/QueryDataRequest"}}},"required":true},"responses":{"200":{"description":"Query results","content":{"application/json":{"schema":{"$ref":"#/components/schemas/QueryDataResponse"}}}},"400":{"description":"Invalid query"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Service, container, or entity not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/external-services/{service_id}/query/containers/{path}/entities/{entity}/download":{"get":{"tags":["External Services - Query"],"summary":"Download an object (S3 only) as a streaming response","operationId":"download_object","parameters":[{"name":"service_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"path","in":"path","required":true,"schema":{"type":"string"}},{"name":"entity","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Object data stream","content":{"application/octet-stream":{}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Object not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/external-services/{service_id}/query/containers/{path}/info":{"get":{"tags":["External Services - Query"],"summary":"Get information about a specific container","operationId":"get_container_info","parameters":[{"name":"service_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"path","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Container information","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContainerResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Service or container not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/external-services/{service_id}/query/explorer-support":{"get":{"tags":["External Services - Query"],"summary":"Check if a service supports query explorer functionality","operationId":"check_explorer_support","parameters":[{"name":"service_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Explorer support information","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExplorerSupportResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Service not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/external-services/{service_id}/upgrades":{"get":{"tags":["Postgres Upgrades"],"summary":"List recent upgrades for a single service (newest first, page size 50).","operationId":"list_pg_upgrades","parameters":[{"name":"service_id","in":"path","description":"External service id","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Recent upgrades","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/PgUpgradeResponse"}}}}},"500":{"description":"Internal error"}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Postgres Upgrades"],"summary":"Start a new PostgreSQL major-version upgrade for a service.","operationId":"start_pg_upgrade","parameters":[{"name":"service_id","in":"path","description":"External service id","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StartPgUpgradeRequest"}}},"required":true},"responses":{"201":{"description":"Upgrade started","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PgUpgradeResponse"}}}},"400":{"description":"Invalid request"},"409":{"description":"An upgrade is already running for this service"},"412":{"description":"No default S3 source configured"},"500":{"description":"Internal error"}},"security":[{"bearer_auth":[]}]}},"/external-services/{service_id}/upgrades/{id}":{"get":{"tags":["Postgres Upgrades"],"summary":"Get a single upgrade by id, scoped to a service.","operationId":"get_pg_upgrade","parameters":[{"name":"service_id","in":"path","description":"External service id","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"id","in":"path","description":"Upgrade id","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Upgrade","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PgUpgradeResponse"}}}},"404":{"description":"Not found"},"500":{"description":"Internal error"}},"security":[{"bearer_auth":[]}]}},"/external-services/{service_id}/upgrades/{id}/cancel":{"post":{"tags":["Postgres Upgrades"],"summary":"Cancel an in-flight upgrade. The orchestrator stops at its next phase\nboundary; already-terminal upgrades return 409.","operationId":"cancel_pg_upgrade","parameters":[{"name":"service_id","in":"path","description":"External service id","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"id","in":"path","description":"Upgrade id","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Cancellation requested","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PgUpgradeResponse"}}}},"404":{"description":"Not found"},"409":{"description":"Upgrade already terminal"},"500":{"description":"Internal error"}},"security":[{"bearer_auth":[]}]}},"/external-services/{service_id}/upgrades/{id}/logs":{"get":{"tags":["Postgres Upgrades"],"summary":"Get the accumulated JSONL log content for an upgrade (for dashboard display).","operationId":"get_pg_upgrade_logs","parameters":[{"name":"service_id","in":"path","description":"External service id","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"id","in":"path","description":"Upgrade id","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Log content","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PgUpgradeLogResponse"}}}},"404":{"description":"Not found"},"500":{"description":"Internal error"}},"security":[{"bearer_auth":[]}]}},"/external-services/{service_id}/upgrades/{id}/retry":{"post":{"tags":["Postgres Upgrades"],"summary":"Retry a failed upgrade. The phase is preserved, so the state machine\nresumes from where it failed.","operationId":"retry_pg_upgrade","parameters":[{"name":"service_id","in":"path","description":"External service id","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"id","in":"path","description":"Upgrade id","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Retry scheduled","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PgUpgradeResponse"}}}},"400":{"description":"Upgrade is not in a retriable state"},"404":{"description":"Not found"},"500":{"description":"Internal error"}},"security":[{"bearer_auth":[]}]}},"/external-services/{service_id}/upgrades/{id}/rollback":{"post":{"tags":["Postgres Upgrades"],"summary":"Roll a completed upgrade back to its pre-upgrade PGDATA volume and old image.\nOnly valid while the rollback retention window is still open (see\n`ROLLBACK_RETENTION_DAYS`) and the rollback volume has not been swept.","operationId":"rollback_pg_upgrade","parameters":[{"name":"service_id","in":"path","description":"External service id","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"id","in":"path","description":"Upgrade id","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Rollback complete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PgUpgradeResponse"}}}},"404":{"description":"Not found"},"409":{"description":"Upgrade is not in a rollbackable state (not completed, volume swept, or retention expired)"},"500":{"description":"Internal error"}},"security":[{"bearer_auth":[]}]}},"/files/{file_path}":{"get":{"tags":["Files"],"operationId":"get_file","parameters":[{"name":"file_path","in":"path","description":"Relative path to the file from static directory","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"File content retrieved successfully","content":{"application/octet-stream":{}}},"401":{"description":"Authentication required"},"403":{"description":"Access denied - path outside static directory or insufficient permissions"},"404":{"description":"File not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/flags/exposure":{"post":{"tags":["Feature Flags"],"summary":"Record which flags a running app actually evaluated.","description":"This is what makes `last_evaluated_at` mean something. The snapshot\nendpoint hands the SDK every flag in the environment and evaluation then\nhappens locally, so the control plane cannot otherwise tell a flag that is\nreferenced by live code from one nothing has called in a year. Stamping on\nsnapshot fetch would mark every flag as freshly used and defeat the point.\n\nScope comes from the deployment token, never the body. The endpoint writes\nonly `last_evaluated_at` — never a flag's value — so \"a deployment token\ncannot change what a flag serves\" still holds despite this being a write.","operationId":"record_flag_exposure","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecordExposureRequest"}}},"required":true},"responses":{"200":{"description":"Exposure recorded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecordExposureResponse"}}}},"400":{"description":"Deployment token required"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/flags/snapshot":{"get":{"tags":["Feature Flags"],"summary":"Every flag for the caller's environment, collapsed to what the evaluator\nneeds.","description":"Scope comes from the deployment token, never from the URL: a container's\nbaked-in `TEMPS_API_TOKEN` identifies exactly one project (and usually one\nenvironment), so a compromised app cannot read another tenant's flags by\nchanging a path parameter.\n\nSupports `If-None-Match`, so the SDK's background poll is a 304 in the\ncommon case.","operationId":"get_flag_snapshot","parameters":[{"name":"environment_id","in":"query","description":"Required only when the calling token is project-wide rather than scoped\nto a single environment.","required":false,"schema":{"type":["integer","null"],"format":"int32"}}],"responses":{"200":{"description":"Snapshot for the environment","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FlagSnapshotResponse"}}}},"304":{"description":"Snapshot unchanged"},"400":{"description":"Environment could not be determined"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/geo/{ip}":{"get":{"tags":["geo"],"summary":"Get geolocation information for an IP address","operationId":"get_ip_geolocation","parameters":[{"name":"ip","in":"path","description":"IP address to geolocate (IPv4 or IPv6)","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Geolocation information retrieved","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GeoLocationResponse"}}}},"400":{"description":"Invalid IP address","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Authentication required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"IP address not found in database","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/git-connections":{"get":{"tags":["Git Providers"],"summary":"List user's git provider connections","operationId":"list_connections","parameters":[{"name":"page","in":"query","description":"Page number for pagination (default: 1)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"per_page","in":"query","description":"Number of items per page (default: 30, max: 100)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"sort","in":"query","description":"Sort field (created_at, updated_at, account_name)","required":false,"schema":{"type":"string"}},{"name":"direction","in":"query","description":"Sort direction (asc, desc), default: desc","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"List of connections","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConnectionListResponse"}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/git-connections/{connection_id}":{"delete":{"tags":["Git Providers"],"summary":"Permanently delete a git provider connection","operationId":"delete_connection","parameters":[{"name":"connection_id","in":"path","description":"Connection ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"Connection deleted successfully"},"400":{"description":"Connection is in use by projects and cannot be deleted"},"401":{"description":"Unauthorized"},"404":{"description":"Connection not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/git-connections/{connection_id}/activate":{"post":{"tags":["Git Providers"],"summary":"Activate a git provider connection","operationId":"activate_connection","parameters":[{"name":"connection_id","in":"path","description":"Connection ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Connection activated successfully"},"400":{"description":"Provider is deactivated and connection cannot be activated"},"401":{"description":"Unauthorized"},"404":{"description":"Connection not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/git-connections/{connection_id}/deactivate":{"post":{"tags":["Git Providers"],"summary":"Deactivate a git provider connection","operationId":"deactivate_connection","parameters":[{"name":"connection_id","in":"path","description":"Connection ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Connection deactivated successfully"},"400":{"description":"Connection is in use by projects and cannot be deactivated"},"401":{"description":"Unauthorized"},"404":{"description":"Connection not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/git-connections/{connection_id}/health-check":{"post":{"tags":["Git Provider Connections"],"summary":"Run an on-demand health check for a git connection.","description":"Probes the upstream (GitHub App, PAT, or OAuth token), persists the result,\nand fires admin notifications on status transitions. Returns the updated\nconnection.","operationId":"run_connection_health_check","parameters":[{"name":"connection_id","in":"path","description":"Connection ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Health check completed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConnectionResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Connection not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/git-connections/{connection_id}/repositories":{"get":{"tags":["Git Providers"],"summary":"List repositories for a specific connection","description":"Fetches repositories from the connected git provider with support for pagination, search, and filtering.\nThis endpoint calls the provider's API directly to get the most up-to-date repository list.","operationId":"list_repositories_by_connection","parameters":[{"name":"connection_id","in":"path","description":"Connection ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"page","in":"query","description":"Page number for pagination","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"per_page","in":"query","description":"Number of items per page (max 100)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"sort","in":"query","description":"Sort field (name, created_at, updated_at, stars, etc.)","required":false,"schema":{"type":"string"}},{"name":"direction","in":"query","description":"Sort direction (asc, desc)","required":false,"schema":{"type":"string"}},{"name":"search","in":"query","description":"Search term to filter repositories","required":false,"schema":{"type":"string"}},{"name":"owner","in":"query","description":"Filter by repository owner","required":false,"schema":{"type":"string"}},{"name":"language","in":"query","description":"Filter by programming language","required":false,"schema":{"type":"string"}},{"name":"private","in":"query","description":"Filter by private status (true/false)","required":false,"schema":{"type":"boolean"}}],"responses":{"200":{"description":"List of repositories","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RepositoryListResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Connection not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/git-connections/{connection_id}/sync":{"post":{"tags":["Git Providers"],"summary":"Start a repository sync for a connection","description":"Kicks off a background sync of the connection's repositories from the\nprovider. Returns `202 Accepted` immediately — the caller should poll\nthe connection endpoint for `syncing` / `synced_repository_count`\nupdates rather than waiting on this response. The sync is guarded by\na hard deadline and always releases the `syncing` flag on exit, so a\nclient that disconnects mid-sync will not leave the connection stuck.","operationId":"sync_repositories","parameters":[{"name":"connection_id","in":"path","description":"Connection ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"202":{"description":"Repository sync started in background","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RepositorySyncStartedResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Connection not found"},"409":{"description":"Sync already in progress"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/git-connections/{connection_id}/update-token":{"post":{"tags":["Git Provider Connections"],"summary":"Update access token for a connection (when tokens expire or are rotated)","operationId":"update_connection_token","parameters":[{"name":"connection_id","in":"path","description":"Connection ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateTokenRequest"}}},"required":true},"responses":{"200":{"description":"Token updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateTokenResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Connection not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/git-connections/{connection_id}/validate":{"get":{"tags":["Git Provider Connections"],"summary":"Validate a connection by testing the access token","operationId":"validate_connection","parameters":[{"name":"connection_id","in":"path","description":"Connection ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Connection validation result","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Connection not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/git-providers":{"get":{"tags":["Git Providers"],"summary":"List all git providers","operationId":"list_git_providers","responses":{"200":{"description":"List of providers","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ProviderResponse"}}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Git Providers"],"summary":"Create a new git provider configuration","operationId":"create_git_provider","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateProviderRequest"}}},"required":true},"responses":{"201":{"description":"Provider created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProviderResponse"}}}},"400":{"description":"Bad request"},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/git-providers/bitbucket":{"post":{"tags":["Git Providers"],"summary":"Create a Bitbucket Cloud provider with access token or app password authentication","operationId":"create_bitbucket_provider","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateBitbucketRequest"}}},"required":true},"responses":{"201":{"description":"Bitbucket provider created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProviderResponse"}}}},"400":{"description":"Bad request — missing or invalid auth fields"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/git-providers/generic":{"post":{"tags":["Git Providers"],"summary":"Create a Generic git provider for self-hosted or arbitrary HTTPS git hosts.\nSupports public repositories (no token) and private repositories (token-based).","operationId":"create_generic_provider","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateGenericRequest"}}},"required":true},"responses":{"201":{"description":"Generic git provider created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProviderResponse"}}}},"400":{"description":"Bad request — invalid clone URL or missing fields"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/git-providers/gitea/pat":{"post":{"tags":["Git Providers"],"summary":"Create a Gitea Personal Access Token provider","operationId":"create_gitea_pat_provider","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateGiteaPATRequest"}}},"required":true},"responses":{"201":{"description":"Gitea PAT provider created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProviderResponse"}}}},"400":{"description":"Bad request — invalid URL or missing fields"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/git-providers/github/pat":{"post":{"tags":["Git Providers"],"summary":"Create a GitHub Personal Access Token provider","operationId":"create_github_pat_provider","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateGitHubPATRequest"}}},"required":true},"responses":{"201":{"description":"GitHub PAT provider created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProviderResponse"}}}},"400":{"description":"Bad request"},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/git-providers/gitlab/oauth":{"post":{"tags":["Git Providers"],"summary":"Create a GitLab OAuth provider","operationId":"create_gitlab_oauth_provider","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateGitLabOAuthRequest"}}},"required":true},"responses":{"201":{"description":"GitLab OAuth provider created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProviderResponse"}}}},"400":{"description":"Bad request"},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/git-providers/gitlab/pat":{"post":{"tags":["Git Providers"],"summary":"Create a GitLab PAT provider","operationId":"create_gitlab_pat_provider","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateGitLabPATRequest"}}},"required":true},"responses":{"201":{"description":"GitLab PAT provider created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProviderResponse"}}}},"400":{"description":"Bad request"},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/git-providers/{provider_id}":{"get":{"tags":["Git Providers"],"summary":"Get a specific git provider","operationId":"get_git_provider","parameters":[{"name":"provider_id","in":"path","description":"Provider ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Provider details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProviderResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Provider not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["Git Providers"],"summary":"Permanently delete a git provider","operationId":"delete_git_provider","parameters":[{"name":"provider_id","in":"path","description":"Provider ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"Provider deleted successfully"},"400":{"description":"Provider has connections and cannot be deleted"},"401":{"description":"Unauthorized"},"404":{"description":"Provider not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/git-providers/{provider_id}/activate":{"post":{"tags":["Git Providers"],"summary":"Activate a git provider","operationId":"activate_provider","parameters":[{"name":"provider_id","in":"path","description":"Provider ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Provider activated successfully"},"401":{"description":"Unauthorized"},"404":{"description":"Provider not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/git-providers/{provider_id}/callback":{"get":{"tags":["Git Providers"],"summary":"Handle OAuth callback for a git provider","operationId":"handle_git_provider_oauth_callback","parameters":[{"name":"provider_id","in":"path","description":"Git provider ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"code","in":"query","description":"OAuth authorization code","required":true,"schema":{"type":"string"}},{"name":"state","in":"query","description":"CSRF state token","required":true,"schema":{"type":"string"}}],"responses":{"302":{"description":"Redirect to success page"},"400":{"description":"Bad request"},"404":{"description":"Provider not found"},"500":{"description":"Internal server error"}}}},"/git-providers/{provider_id}/connections":{"get":{"tags":["Git Providers"],"summary":"Get connections for a specific git provider","operationId":"get_provider_connections","parameters":[{"name":"provider_id","in":"path","description":"Provider ID to get connections for","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"List of connections for the provider","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ConnectionResponse"}}}}},"401":{"description":"Unauthorized"},"404":{"description":"Provider not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/git-providers/{provider_id}/credentials":{"patch":{"tags":["Git Providers"],"summary":"Partially update credentials for an existing git provider. Only the fields\nyou send are replaced; omitted fields keep their stored values. Fields that\ndon't apply to the provider's auth method are ignored on the service side.","operationId":"update_git_provider_credentials","parameters":[{"name":"provider_id","in":"path","description":"Git provider ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateProviderCredentialsRequest"}}},"required":true},"responses":{"200":{"description":"Credentials updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProviderResponse"}}}},"400":{"description":"Bad request"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Provider not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/git-providers/{provider_id}/deactivate":{"post":{"tags":["Git Providers"],"summary":"Deactivate a git provider","operationId":"deactivate_provider","parameters":[{"name":"provider_id","in":"path","description":"Provider ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Provider deactivated successfully"},"401":{"description":"Unauthorized"},"404":{"description":"Provider not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/git-providers/{provider_id}/deletion-check":{"get":{"tags":["Git Providers"],"summary":"Check if a git provider can be safely deleted","operationId":"check_provider_deletion_safety","parameters":[{"name":"provider_id","in":"path","description":"Git provider ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Deletion check result","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProviderDeletionCheckResponse"}}}},"404":{"description":"Provider not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/git-providers/{provider_id}/oauth/authorize":{"get":{"tags":["Git Providers"],"summary":"Start OAuth flow for a git provider","operationId":"start_git_provider_oauth","parameters":[{"name":"provider_id","in":"path","description":"Git provider ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"302":{"description":"Redirect to OAuth provider"},"404":{"description":"Provider not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/git-providers/{provider_id}/repositories":{"get":{"tags":["Git Providers"],"summary":"List all repositories for a specific provider","description":"Lists repositories synced to the database across every connection under\nthis provider, with the same pagination/filtering as `/repositories`.","operationId":"list_repositories_by_provider","parameters":[{"name":"provider_id","in":"path","description":"Provider ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"page","in":"query","description":"Page number for pagination","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"per_page","in":"query","description":"Number of items per page (max 100)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"sort","in":"query","description":"Sort field (name, created_at, updated_at, stars, watchers, size, issues)","required":false,"schema":{"type":"string"}},{"name":"direction","in":"query","description":"Sort direction (asc, desc)","required":false,"schema":{"type":"string"}},{"name":"search","in":"query","description":"Search term to filter repositories","required":false,"schema":{"type":"string"}},{"name":"owner","in":"query","description":"Filter by repository owner","required":false,"schema":{"type":"string"}},{"name":"language","in":"query","description":"Filter by programming language","required":false,"schema":{"type":"string"}},{"name":"private","in":"query","description":"Filter by private status (true/false)","required":false,"schema":{"type":"boolean"}}],"responses":{"200":{"description":"List of repositories","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RepositoryListResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Provider not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/git-providers/{provider_id}/safe-delete":{"delete":{"tags":["Git Providers"],"summary":"Safely delete a git provider (only if no projects are using it)","operationId":"delete_provider_safely","parameters":[{"name":"provider_id","in":"path","description":"Git provider ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"Provider successfully deleted"},"400":{"description":"Cannot delete provider because it's in use"},"404":{"description":"Provider not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/git/public/{provider}/{owner}/{repo}":{"get":{"tags":["Public Repositories"],"summary":"Get information about a public repository (supports GitHub and GitLab)","operationId":"get_public_repository","parameters":[{"name":"provider","in":"path","description":"Git provider (github or gitlab)","required":true,"schema":{"type":"string"}},{"name":"owner","in":"path","description":"Repository owner","required":true,"schema":{"type":"string"}},{"name":"repo","in":"path","description":"Repository name","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Repository information","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicRepositoryInfo"}}}},"400":{"description":"Provider not supported"},"404":{"description":"Repository not found"},"429":{"description":"API rate limit exceeded"},"500":{"description":"Internal server error"}}}},"/git/public/{provider}/{owner}/{repo}/branches":{"get":{"tags":["Public Repositories"],"summary":"Get branches for a public repository (supports GitHub and GitLab)","operationId":"get_public_branches","parameters":[{"name":"provider","in":"path","description":"Git provider (github or gitlab)","required":true,"schema":{"type":"string"}},{"name":"owner","in":"path","description":"Repository owner","required":true,"schema":{"type":"string"}},{"name":"repo","in":"path","description":"Repository name","required":true,"schema":{"type":"string"}},{"name":"fresh","in":"query","description":"Force fetch fresh data, bypassing cache (default: false)","required":false,"schema":{"type":"boolean"}}],"responses":{"200":{"description":"List of branches","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BranchListResponse"}}}},"400":{"description":"Provider not supported"},"404":{"description":"Repository not found"},"429":{"description":"API rate limit exceeded"},"500":{"description":"Internal server error"}}}},"/git/public/{provider}/{owner}/{repo}/presets":{"get":{"tags":["Public Repositories"],"summary":"Detect presets for a public repository (supports GitHub and GitLab)","operationId":"detect_public_presets","parameters":[{"name":"provider","in":"path","description":"Git provider (github or gitlab)","required":true,"schema":{"type":"string"}},{"name":"owner","in":"path","description":"Repository owner","required":true,"schema":{"type":"string"}},{"name":"repo","in":"path","description":"Repository name","required":true,"schema":{"type":"string"}},{"name":"branch","in":"query","description":"Branch name to detect presets for (default: repository's default branch)","required":false,"schema":{"type":["string","null"]}},{"name":"fresh","in":"query","description":"Force fetch fresh data, bypassing cache (default: false)","required":false,"schema":{"type":"boolean"}}],"responses":{"200":{"description":"Detected presets","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicPresetResponse"}}}},"400":{"description":"Provider not supported"},"404":{"description":"Repository or branch not found"},"429":{"description":"API rate limit exceeded"},"500":{"description":"Internal server error"}}}},"/imports/discover":{"post":{"tags":["Imports"],"summary":"Discover workloads from a source","operationId":"discover_workloads","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DiscoverRequest"}}},"required":true},"responses":{"200":{"description":"List of discovered workloads","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DiscoverResponse"}}}},"400":{"description":"Invalid request"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"}},"security":[{"bearer_auth":[]}]}},"/imports/execute":{"post":{"tags":["Imports"],"summary":"Execute an import","operationId":"execute_import","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExecuteImportRequest"}}},"required":true},"responses":{"202":{"description":"Import execution started","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExecuteImportResponse"}}}},"400":{"description":"Invalid request"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"}},"security":[{"bearer_auth":[]}]}},"/imports/plan":{"post":{"tags":["Imports"],"summary":"Create an import plan","operationId":"create_plan","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatePlanRequest"}}},"required":true},"responses":{"200":{"description":"Import plan created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatePlanResponse"}}}},"400":{"description":"Invalid request"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"}},"security":[{"bearer_auth":[]}]}},"/imports/sources":{"get":{"tags":["Imports"],"summary":"List available import sources","operationId":"list_sources","responses":{"200":{"description":"List of available import sources","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ImportSourceInfo"}}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"}},"security":[{"bearer_auth":[]}]}},"/imports/{session_id}":{"get":{"tags":["Imports"],"summary":"Get import status","operationId":"get_import_status","parameters":[{"name":"session_id","in":"path","description":"Import session ID","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Import status","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImportStatusResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Import session not found"}},"security":[{"bearer_auth":[]}]}},"/incidents/{incident_id}":{"get":{"tags":["Status Page"],"summary":"Get an incident by ID","operationId":"get_incident","parameters":[{"name":"incident_id","in":"path","description":"Incident ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Successfully retrieved incident","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IncidentResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Incident not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/incidents/{incident_id}/status":{"patch":{"tags":["Status Page"],"summary":"Update incident status","operationId":"update_incident_status","parameters":[{"name":"incident_id","in":"path","description":"Incident ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateIncidentStatusRequest"}}},"required":true},"responses":{"200":{"description":"Incident status updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IncidentResponse"}}}},"400":{"description":"Invalid request"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Incident not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/incidents/{incident_id}/updates":{"get":{"tags":["Status Page"],"summary":"Get incident updates","operationId":"get_incident_updates","parameters":[{"name":"incident_id","in":"path","description":"Incident ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Successfully retrieved incident updates","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/IncidentUpdateResponse"}}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Incident not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/internal/nodes":{"get":{"tags":["Nodes"],"summary":"List all registered nodes (admin — session auth via RequireAuth)","operationId":"admin_list_nodes","responses":{"200":{"description":"List of nodes","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NodeListResponse"}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/internal/nodes/register":{"post":{"tags":["Nodes"],"summary":"Register a new worker node or reconnect an existing one","operationId":"register_node","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RegisterNodeApiRequest"}}},"required":true},"responses":{"200":{"description":"Node reconnected successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RegisterNodeResponse"}}}},"201":{"description":"Node registered successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RegisterNodeResponse"}}}},"400":{"description":"Validation error"},"500":{"description":"Internal server error"}}}},"/internal/nodes/{node_id}":{"get":{"tags":["Nodes"],"summary":"Get a specific node by ID (admin — session auth via RequireAuth)","operationId":"admin_get_node","parameters":[{"name":"node_id","in":"path","description":"Node ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Node details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NodeInfoResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Node not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["Nodes"],"summary":"Remove a node from the cluster entirely. The node should be drained first\nto ensure containers have been rescheduled. If the node still has active\ncontainers, it will be drained automatically before removal.","operationId":"admin_remove_node","parameters":[{"name":"node_id","in":"path","description":"Node ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Node removed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RemoveNodeResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Node not found"},"409":{"description":"Node still has active containers"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/internal/nodes/{node_id}/containers":{"get":{"tags":["Nodes"],"summary":"List all containers running on a specific node","operationId":"admin_list_node_containers","parameters":[{"name":"node_id","in":"path","description":"Node ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Containers on this node","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NodeContainerListResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Node not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/internal/nodes/{node_id}/dns/ack":{"post":{"tags":["Internal DNS"],"summary":"`POST /internal/nodes/{node_id}/dns/ack`","operationId":"post_dns_ack","parameters":[{"name":"node_id","in":"path","description":"Node id, must match the bearer token's node","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DnsAckRequest"}}},"required":true},"responses":{"200":{"description":"ACK accepted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DnsAckResponse"}}}},"400":{"description":"ACK higher than server generation"},"401":{"description":"Missing or invalid bearer token"},"404":{"description":"Node not found"},"500":{"description":"Internal server error"}}}},"/internal/nodes/{node_id}/dns/changes":{"get":{"tags":["Internal DNS"],"summary":"`GET /internal/nodes/{node_id}/dns/changes?since=N`","operationId":"get_dns_changes","parameters":[{"name":"node_id","in":"path","description":"Node id, must match the bearer token's node","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"since","in":"query","description":"Highest generation the agent has already applied. Pass `0` to\nrequest a full zone snapshot. Defaults to `0` if omitted.","required":false,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"Diff or full snapshot","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DnsChangesResponse"}}}},"401":{"description":"Missing or invalid bearer token"},"404":{"description":"Node not found"},"500":{"description":"Internal server error"}}}},"/internal/nodes/{node_id}/drain":{"get":{"tags":["Nodes"],"summary":"Get the drain status for a node, including migration progress.","description":"Returns container counts and whether the drain is complete.\nCan be polled to track drain progress.","operationId":"admin_drain_status","parameters":[{"name":"node_id","in":"path","description":"Node ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Drain status","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DrainStatusResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Node not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Nodes"],"summary":"Drain a node: mark it as \"draining\" so no new replicas are scheduled on it,\nand trigger redeployment of all affected environments so their containers\nare rescheduled to healthy nodes.","operationId":"admin_drain_node","parameters":[{"name":"node_id","in":"path","description":"Node ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Node drain initiated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DrainNodeResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Node not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["Nodes"],"summary":"Undrain (reactivate) a node so it can accept new deployments again.\nOnly works for nodes in \"draining\" or \"drained\" status.","operationId":"admin_undrain_node","parameters":[{"name":"node_id","in":"path","description":"Node ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Node reactivated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UndrainNodeResponse"}}}},"400":{"description":"Node not in drainable state"},"401":{"description":"Unauthorized"},"404":{"description":"Node not found"}},"security":[{"bearer_auth":[]}]}},"/internal/nodes/{node_id}/heartbeat":{"post":{"tags":["Nodes"],"summary":"Receive a heartbeat from a worker node","operationId":"node_heartbeat","parameters":[{"name":"node_id","in":"path","description":"Node ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HeartbeatApiRequest"}}},"required":true},"responses":{"200":{"description":"Heartbeat received","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HeartbeatResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Node not found"},"500":{"description":"Internal server error"}}}},"/internal/nodes/{node_id}/network/peers":{"get":{"tags":["Nodes"],"summary":"`GET /internal/nodes/{node_id}/network/peers`","operationId":"list_peers","parameters":[{"name":"node_id","in":"path","description":"Node id, must match the bearer token's node","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Peer list and self-allocation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PeerListResponse"}}}},"401":{"description":"Missing or invalid bearer token"},"404":{"description":"Node not found"},"500":{"description":"Internal server error"}}}},"/internal/nodes/{node_id}/s3-credentials/{s3_source_id}":{"get":{"tags":["Nodes"],"summary":"Get decrypted S3 credentials for a backup/restore operation.","description":"Agents call this endpoint to receive the S3 credentials they need to upload\nor download backups. The credentials are decrypted from the stored S3 source\nand returned over the authenticated TLS/WireGuard channel.","operationId":"get_s3_credentials","parameters":[{"name":"node_id","in":"path","description":"Node ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"s3_source_id","in":"path","description":"S3 source ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"S3 credentials","content":{"application/json":{"schema":{"$ref":"#/components/schemas/S3CredentialsResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"S3 source not found"},"500":{"description":"Internal server error"}}}},"/ip-access-control":{"get":{"tags":["IP Access Control"],"summary":"List all IP access control rules","operationId":"list_ip_access_control","parameters":[{"name":"action","in":"query","description":"Filter by action (\"block\" or \"allow\")","required":false,"schema":{"type":["string","null"]}}],"responses":{"200":{"description":"List of IP access control rules","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/IpAccessControlResponse"}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]},"post":{"tags":["IP Access Control"],"summary":"Create a new IP access control rule","operationId":"create_ip_access_control","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateIpAccessControlRequest"}}},"required":true},"responses":{"201":{"description":"IP access control rule created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IpAccessControlResponse"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"409":{"description":"Duplicate IP address","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/ip-access-control/check/{ip}":{"get":{"tags":["IP Access Control"],"summary":"Check if an IP address is blocked","operationId":"check_ip_blocked","parameters":[{"name":"ip","in":"path","description":"IP address to check","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"IP block status"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/ip-access-control/{id}":{"get":{"tags":["IP Access Control"],"summary":"Get a single IP access control rule by ID","operationId":"get_ip_access_control","parameters":[{"name":"id","in":"path","description":"IP access control rule ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"IP access control rule details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IpAccessControlResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"IP access control rule not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["IP Access Control"],"summary":"Delete an IP access control rule","operationId":"delete_ip_access_control","parameters":[{"name":"id","in":"path","description":"IP access control rule ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"IP access control rule deleted"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"IP access control rule not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]},"patch":{"tags":["IP Access Control"],"summary":"Update an IP access control rule","operationId":"update_ip_access_control","parameters":[{"name":"id","in":"path","description":"IP access control rule ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateIpAccessControlRequest"}}},"required":true},"responses":{"200":{"description":"IP access control rule updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IpAccessControlResponse"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"IP access control rule not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/kv/del":{"post":{"tags":["KV Store"],"summary":"Delete one or more keys","operationId":"kv_del","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DelRequest"}}},"required":true},"responses":{"200":{"description":"Keys deleted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DelResponse"}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/kv/disable":{"delete":{"tags":["KV Management"],"summary":"Disable KV service","operationId":"kv_disable","responses":{"200":{"description":"KV service disabled","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DisableKvResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"KV service not enabled"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/kv/enable":{"post":{"tags":["KV Management"],"summary":"Enable KV service","operationId":"kv_enable","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnableKvRequest"}}},"required":true},"responses":{"200":{"description":"KV service enabled","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnableKvResponse"}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/kv/expire":{"post":{"tags":["KV Store"],"summary":"Set expiration on a key","operationId":"kv_expire","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExpireRequest"}}},"required":true},"responses":{"200":{"description":"Expiration set","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExpireResponse"}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/kv/get":{"post":{"tags":["KV Store"],"summary":"Get a value by key","operationId":"kv_get","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetRequest"}}},"required":true},"responses":{"200":{"description":"Value retrieved","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetResponse"}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/kv/incr":{"post":{"tags":["KV Store"],"summary":"Increment a numeric value","operationId":"kv_incr","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/IncrRequest"}}},"required":true},"responses":{"200":{"description":"Value incremented","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IncrResponse"}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/kv/keys":{"post":{"tags":["KV Store"],"summary":"Get keys matching a pattern","operationId":"kv_keys","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/KeysRequest"}}},"required":true},"responses":{"200":{"description":"Keys retrieved","content":{"application/json":{"schema":{"$ref":"#/components/schemas/KeysResponse"}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/kv/set":{"post":{"tags":["KV Store"],"summary":"Set a value with optional expiration","operationId":"kv_set","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetRequest"}}},"required":true},"responses":{"200":{"description":"Value set","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetResponse"}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/kv/status":{"get":{"tags":["KV Management"],"summary":"Get KV service status","operationId":"kv_status","responses":{"200":{"description":"KV service status","content":{"application/json":{"schema":{"$ref":"#/components/schemas/KvStatusResponse"}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/kv/ttl":{"post":{"tags":["KV Store"],"summary":"Get time-to-live for a key","operationId":"kv_ttl","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TtlRequest"}}},"required":true},"responses":{"200":{"description":"TTL retrieved","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TtlResponse"}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/kv/update":{"patch":{"tags":["KV Management"],"summary":"Update KV service configuration","operationId":"kv_update","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateKvRequest"}}},"required":true},"responses":{"200":{"description":"KV service updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateKvResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"KV service not enabled"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/lb/routes":{"get":{"tags":["Load Balancer"],"operationId":"list_routes","responses":{"200":{"description":"List of routes","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/RouteResponse"}}}}},"500":{"description":"Internal server error"}}},"post":{"tags":["Load Balancer"],"operationId":"create_route","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateRouteRequest"}}},"required":true},"responses":{"201":{"description":"Route created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RouteResponse"}}}},"400":{"description":"Invalid request"}}}},"/lb/routes/{domain}":{"get":{"tags":["Load Balancer"],"operationId":"get_route","parameters":[{"name":"domain","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Route found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RouteResponse"}}}},"404":{"description":"Route not found"}}},"put":{"tags":["Load Balancer"],"operationId":"update_route","parameters":[{"name":"domain","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateRouteRequest"}}},"required":true},"responses":{"200":{"description":"Route updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RouteResponse"}}}},"404":{"description":"Route not found"}}},"delete":{"tags":["Load Balancer"],"operationId":"delete_route","parameters":[{"name":"domain","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Route deleted successfully"},"404":{"description":"Route not found"}}}},"/logout":{"post":{"tags":["Authentication"],"operationId":"logout","responses":{"200":{"description":"Successfully logged out"},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"session_token":[]}]}},"/logs/context":{"get":{"tags":["Logs"],"summary":"Get context lines surrounding a specific log line","operationId":"get_log_context","parameters":[{"name":"chunk_id","in":"query","description":"Chunk ID","required":true,"schema":{"type":"string"}},{"name":"line_offset","in":"query","description":"Line offset within the chunk","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"lines","in":"query","description":"Context lines before and after (default: 25)","required":false,"schema":{"type":"integer","format":"int32","minimum":0}}],"responses":{"200":{"description":"Context lines","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContextLogsResponse"}}}},"400":{"description":"Invalid parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Chunk not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/logs/search":{"post":{"tags":["Logs"],"summary":"Search logs with structured filters and full text search","operationId":"search_logs","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchLogsRequest"}}},"required":true},"responses":{"200":{"description":"Search results","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchLogsResponse"}}}},"400":{"description":"Invalid search parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/logs/tail":{"get":{"tags":["Logs"],"summary":"Live tail logs via Server-Sent Events","operationId":"tail_logs","parameters":[{"name":"project_id","in":"query","description":"Project ID","required":true,"schema":{"type":"string"}},{"name":"service","in":"query","description":"Service name","required":true,"schema":{"type":"string"}},{"name":"env","in":"query","description":"Environment","required":true,"schema":{"type":"string"}},{"name":"levels","in":"query","description":"Optional level filters","required":true,"schema":{"type":"array","items":{"type":"string"}}},{"name":"text","in":"query","description":"Optional text filter","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"SSE stream of log lines"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/monitors-health/projects":{"get":{"tags":["Status Page"],"summary":"Get monitor-based health summaries for multiple projects in a single query","operationId":"get_projects_monitor_health","parameters":[{"name":"project_ids","in":"query","description":"Comma-separated list of project IDs","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Health summaries per project","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectsMonitorHealthResponse"}}}},"400":{"description":"Invalid parameters"},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/monitors/{monitor_id}":{"get":{"tags":["Status Page"],"summary":"Get a monitor by ID","operationId":"get_monitor","parameters":[{"name":"monitor_id","in":"path","description":"Monitor ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Successfully retrieved monitor","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MonitorResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Monitor not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["Status Page"],"summary":"Delete a monitor","operationId":"delete_monitor","parameters":[{"name":"monitor_id","in":"path","description":"Monitor ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"Monitor deleted successfully"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Monitor not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/monitors/{monitor_id}/bucketed":{"get":{"tags":["Status Page"],"summary":"Get bucketed status data for a monitor using TimescaleDB","operationId":"get_bucketed_status","parameters":[{"name":"monitor_id","in":"path","description":"Monitor ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"interval","in":"query","description":"Bucket interval: '5min', 'hourly', or 'daily' (default: hourly)","required":false,"schema":{"type":"string"}},{"name":"start_time","in":"query","description":"Start time (ISO 8601) (default: 24 hours ago)","required":false,"schema":{"type":"string"}},{"name":"end_time","in":"query","description":"End time (ISO 8601) (default: now)","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successfully retrieved bucketed status data","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusBucketedResponse"}}}},"400":{"description":"Invalid parameters"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Monitor not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/monitors/{monitor_id}/current-status":{"get":{"tags":["Status Page"],"summary":"Get current status and uptime metrics for a monitor","operationId":"get_current_monitor_status","parameters":[{"name":"monitor_id","in":"path","description":"Monitor ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"start_time","in":"query","description":"Custom start time (ISO 8601) - overrides timeframe","required":false,"schema":{"type":"string"}},{"name":"end_time","in":"query","description":"Custom end time (ISO 8601)","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successfully retrieved current status","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CurrentStatusResponse"}}}},"400":{"description":"Invalid time parameters"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Monitor not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/monitors/{monitor_id}/uptime":{"get":{"tags":["Status Page"],"summary":"Get uptime history for a monitor","operationId":"get_uptime_history","parameters":[{"name":"monitor_id","in":"path","description":"Monitor ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"days","in":"query","description":"Number of days of history (default: 60) - ignored if start_time/end_time provided","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"start_time","in":"query","description":"Start time (ISO 8601) - overrides days parameter","required":true,"schema":{"type":"string"}},{"name":"end_time","in":"query","description":"End time (ISO 8601) - defaults to now","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successfully retrieved uptime history","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UptimeHistoryResponse"}}}},"400":{"description":"Invalid time parameters"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Monitor not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/nodes/{id}/metrics":{"get":{"tags":["Metrics"],"summary":"Fetch a time-series range for a single metric on a node.","operationId":"NodeMetricsGetRange","parameters":[{"name":"id","in":"path","description":"Node ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"metric","in":"query","description":"Metric name, e.g. `\"pg.connections_active\"`.","required":true,"schema":{"type":"string"}},{"name":"range","in":"query","description":"Time window: `\"1h\"` | `\"6h\"` | `\"24h\"` | `\"7d\"`.","required":false,"schema":{"type":"string"}},{"name":"percentile","in":"query","description":"Optional histogram percentile (0–100). When provided, the endpoint\nfetches histogram buckets and computes the requested quantile.","required":false,"schema":{"type":["number","null"],"format":"double"}}],"responses":{"200":{"description":"Metric time series data points","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/MetricDataPoint"}}}}},"400":{"description":"Invalid query parameters"},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"},"503":{"description":"Metrics store not available"}},"security":[{"bearer_auth":[]}]}},"/notification-preferences":{"get":{"tags":["Notification Preferences"],"summary":"Get notification preferences","operationId":"get_preferences","responses":{"200":{"description":"Successfully retrieved preferences","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotificationPreferencesResponse"}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"put":{"tags":["Notification Preferences"],"summary":"Update notification preferences","operationId":"update_preferences","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdatePreferencesRequest"}}},"required":true},"responses":{"200":{"description":"Successfully updated preferences","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotificationPreferencesResponse"}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["Notification Preferences"],"summary":"Delete notification preferences","operationId":"delete_preferences","responses":{"204":{"description":"Successfully deleted preferences"},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/notification-providers":{"get":{"tags":["Notification Providers"],"summary":"List all notification providers","operationId":"list_notification_providers","parameters":[{"name":"page","in":"query","description":"Page number (1-indexed)","required":false,"schema":{"type":["integer","null"],"format":"int64","minimum":0},"example":1},{"name":"page_size","in":"query","description":"Number of items per page (max 100)","required":false,"schema":{"type":["integer","null"],"format":"int64","minimum":0},"example":20},{"name":"sort_by","in":"query","required":false,"schema":{"type":["string","null"]}},{"name":"sort_order","in":"query","required":false,"schema":{"type":["string","null"]}}],"responses":{"200":{"description":"Successfully retrieved providers","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/NotificationProviderResponse"}}}}},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Notification Providers"],"summary":"Create a new notification provider","operationId":"create_notification_provider","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateProviderRequest"}}},"required":true},"responses":{"201":{"description":"Successfully created provider","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotificationProviderResponse"}}}},"400":{"description":"Invalid request"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/notification-providers/cloudflare":{"post":{"tags":["Notification Providers"],"summary":"Create a new Cloudflare Email Sending notification provider","operationId":"create_cloudflare_provider","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateCloudflareProviderRequest"}}},"required":true},"responses":{"201":{"description":"Successfully created Cloudflare provider","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotificationProviderResponse"}}}},"400":{"description":"Invalid request"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/notification-providers/cloudflare/{id}":{"put":{"tags":["Notification Providers"],"summary":"Update a Cloudflare Email Sending notification provider","operationId":"update_cloudflare_provider","parameters":[{"name":"id","in":"path","description":"Provider ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateCloudflareProviderRequest"}}},"required":true},"responses":{"200":{"description":"Successfully updated Cloudflare provider","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotificationProviderResponse"}}}},"404":{"description":"Provider not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/notification-providers/email":{"post":{"tags":["Notification Providers"],"summary":"Create a new Email notification provider","operationId":"create_notification_email_provider","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateNotificationEmailProviderRequest"}}},"required":true},"responses":{"201":{"description":"Successfully created Email provider","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotificationProviderResponse"}}}},"400":{"description":"Invalid request"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/notification-providers/email/{id}":{"put":{"tags":["Notification Providers"],"summary":"Update an Email notification provider","operationId":"update_notification_email_provider","parameters":[{"name":"id","in":"path","description":"Provider ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateNotificationEmailProviderRequest"}}},"required":true},"responses":{"200":{"description":"Successfully updated Email provider","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotificationProviderResponse"}}}},"404":{"description":"Provider not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/notification-providers/slack":{"post":{"tags":["Notification Providers"],"summary":"Create a new Slack notification provider","operationId":"create_slack_provider","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateSlackProviderRequest"}}},"required":true},"responses":{"201":{"description":"Successfully created Slack provider","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotificationProviderResponse"}}}},"400":{"description":"Invalid request"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/notification-providers/slack/{id}":{"put":{"tags":["Notification Providers"],"summary":"Update a Slack notification provider","operationId":"update_slack_provider","parameters":[{"name":"id","in":"path","description":"Provider ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateSlackProviderRequest"}}},"required":true},"responses":{"200":{"description":"Successfully updated Slack provider","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotificationProviderResponse"}}}},"404":{"description":"Provider not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/notification-providers/webhook":{"post":{"tags":["Notification Providers"],"summary":"Create a new Webhook notification provider","description":"Webhook providers send notifications as JSON payloads to any HTTP endpoint.\nYou can configure custom headers for authentication (Bearer tokens, API keys, etc.).\nThe webhook will receive a JSON payload with notification details including:\nid, title, message, type, priority, severity, timestamp, and metadata.","operationId":"create_webhook_provider","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateWebhookProviderRequest"}}},"required":true},"responses":{"201":{"description":"Successfully created Webhook provider","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotificationProviderResponse"}}}},"400":{"description":"Invalid request"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/notification-providers/webhook/{id}":{"put":{"tags":["Notification Providers"],"summary":"Update a Webhook notification provider","operationId":"update_webhook_provider","parameters":[{"name":"id","in":"path","description":"Provider ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateWebhookProviderRequest"}}},"required":true},"responses":{"200":{"description":"Successfully updated Webhook provider","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotificationProviderResponse"}}}},"404":{"description":"Provider not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/notification-providers/{id}":{"get":{"tags":["Notification Providers"],"summary":"Get a single notification provider","operationId":"get_notification_provider","parameters":[{"name":"id","in":"path","description":"Provider ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Successfully retrieved provider","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotificationProviderResponse"}}}},"404":{"description":"Provider not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"put":{"tags":["Notification Providers"],"summary":"Update a notification provider","operationId":"update_notification_provider","parameters":[{"name":"id","in":"path","description":"Provider ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateProviderRequest"}}},"required":true},"responses":{"200":{"description":"Successfully updated provider","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotificationProviderResponse"}}}},"400":{"description":"Invalid masked provider configuration"},"404":{"description":"Provider not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["Notification Providers"],"summary":"Delete a notification provider","operationId":"delete_notification_provider","parameters":[{"name":"id","in":"path","description":"Provider ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"Successfully deleted provider"},"404":{"description":"Provider not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/notification-providers/{id}/config/{field}":{"get":{"tags":["Notification Providers"],"operationId":"reveal_notification_provider_config","parameters":[{"name":"id","in":"path","description":"Provider ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"field","in":"path","description":"Sensitive field, such as password or headers.Authorization","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Sensitive provider configuration value","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SensitiveConfigValueResponse"}}}},"400":{"description":"Field is not revealable"},"403":{"description":"Missing secrets:read permission"},"404":{"description":"Provider or field not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/notification-providers/{id}/test":{"post":{"tags":["Notification Providers"],"summary":"Test a notification provider","operationId":"test_notification_provider","parameters":[{"name":"id","in":"path","description":"Provider ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Test result","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TestProviderResponse"}}}},"404":{"description":"Provider not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/orders":{"get":{"tags":["Domains"],"summary":"List all ACME orders","operationId":"list_orders","parameters":[{"name":"page","in":"query","description":"Page number (1-indexed)","required":false,"schema":{"type":["integer","null"],"format":"int64","minimum":0},"example":1},{"name":"page_size","in":"query","description":"Number of items per page (max 100)","required":false,"schema":{"type":["integer","null"],"format":"int64","minimum":0},"example":20},{"name":"sort_by","in":"query","required":false,"schema":{"type":["string","null"]}},{"name":"sort_order","in":"query","required":false,"schema":{"type":["string","null"]}}],"responses":{"200":{"description":"Orders retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListOrdersResponse"}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/otel/alerts":{"get":{"tags":["Alerts"],"summary":"List alert rules for a project (newest first, paginated).","operationId":"list_alerts","parameters":[{"name":"project_id","in":"query","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"page","in":"query","description":"Page number (default: 1)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"page_size","in":"query","description":"Page size (default: 20, max: 100)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}}],"responses":{"200":{"description":"Alert rules for the project","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OtelMetricAlertsResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Alerts"],"summary":"Create a new alert rule for a project.","operationId":"create_alert","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateMetricAlertRequest"}}},"required":true},"responses":{"201":{"description":"Alert rule created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OtelMetricAlertRuleResponse"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/otel/alerts/preview":{"post":{"tags":["Alerts"],"summary":"Backtest an anomaly detector over a time range without saving a rule.","description":"Replays the metric against the same band the evaluator would use, returning\nthe per-bucket band + which points would have fired. Powers the form's\n\"would this have fired?\" preview and the explorer band overlay. Read-only.","operationId":"preview_alert","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AnomalyPreviewRequest"}}},"required":true},"responses":{"200":{"description":"Per-bucket band + breach points","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AnomalyPreviewResponse"}}}},"400":{"description":"Not an anomaly detector / bad input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/otel/alerts/{id}":{"get":{"tags":["Alerts"],"summary":"Fetch a single alert rule by id.","operationId":"get_alert","parameters":[{"name":"id","in":"path","description":"Alert rule ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"project_id","in":"query","description":"Owning project ID (scopes the lookup)","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Alert rule","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OtelMetricAlertRuleResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Alert rule not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["Alerts"],"summary":"Delete an alert rule.","operationId":"delete_alert","parameters":[{"name":"id","in":"path","description":"Alert rule ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"project_id","in":"query","description":"Owning project ID (scopes the delete)","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"Alert rule deleted"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Alert rule not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]},"patch":{"tags":["Alerts"],"summary":"Update an alert rule's fields.","operationId":"update_alert","parameters":[{"name":"id","in":"path","description":"Alert rule ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"project_id","in":"query","description":"Owning project ID (scopes the update)","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateMetricAlertRequest"}}},"required":true},"responses":{"200":{"description":"Alert rule updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OtelMetricAlertRuleResponse"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Alert rule not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/otel/dashboards":{"get":{"tags":["Dashboards"],"summary":"List dashboards for a project (newest first, paginated).","operationId":"list_dashboards","parameters":[{"name":"project_id","in":"query","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"page","in":"query","description":"Page number (default: 1)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"page_size","in":"query","description":"Page size (default: 20, max: 100)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}}],"responses":{"200":{"description":"Dashboards for the project","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OtelDashboardsResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Dashboards"],"summary":"Create a new dashboard for a project.","operationId":"create_dashboard","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateDashboardRequest"}}},"required":true},"responses":{"201":{"description":"Dashboard created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OtelDashboardResponse"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/otel/dashboards/{id}":{"get":{"tags":["Dashboards"],"summary":"Fetch a single dashboard by id.","operationId":"get_dashboard","parameters":[{"name":"id","in":"path","description":"Dashboard ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"project_id","in":"query","description":"Owning project ID (scopes the lookup)","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Dashboard","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OtelDashboardResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Dashboard not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["Dashboards"],"summary":"Delete a dashboard.","operationId":"delete_dashboard","parameters":[{"name":"id","in":"path","description":"Dashboard ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"project_id","in":"query","description":"Owning project ID (scopes the delete)","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"Dashboard deleted"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Dashboard not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]},"patch":{"tags":["Dashboards"],"summary":"Update a dashboard's name and/or layout.","operationId":"update_dashboard","parameters":[{"name":"id","in":"path","description":"Dashboard ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"project_id","in":"query","description":"Owning project ID (scopes the update)","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateDashboardRequest"}}},"required":true},"responses":{"200":{"description":"Dashboard updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OtelDashboardResponse"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Dashboard not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/otel/genai/traces":{"get":{"tags":["GenAI"],"summary":"Query GenAI trace summaries — traces containing spans with `gen_ai.*` attributes.","description":"`duration_ms` is the only field guaranteed to be milliseconds. `gen_ai.*`\nspan attributes (e.g. time-to-first-token, token latency) often follow the\nOTel GenAI semantic conventions, which use **seconds** (a fractional\ndouble), not milliseconds — do not read them as ms without converting.","operationId":"query_genai_traces","parameters":[{"name":"project_id","in":"query","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"service_name","in":"query","description":"Filter by service name","required":false,"schema":{"type":"string"}},{"name":"gen_ai_system","in":"query","description":"Filter by AI system (openai, anthropic, etc.)","required":false,"schema":{"type":"string"}},{"name":"gen_ai_model","in":"query","description":"Filter by model (gpt-4, claude-sonnet-4-20250514, etc.)","required":false,"schema":{"type":"string"}},{"name":"start_time","in":"query","description":"Start time (RFC 3339)","required":false,"schema":{"type":"string"}},{"name":"end_time","in":"query","description":"End time (RFC 3339)","required":false,"schema":{"type":"string"}},{"name":"limit","in":"query","description":"Max traces to return (default: 50, max: 100)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"offset","in":"query","description":"Offset for pagination","required":false,"schema":{"type":"integer","format":"int64","minimum":0}}],"responses":{"200":{"description":"GenAI trace summaries","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenAiTraceSummariesResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/otel/genai/traces/{project_id}/{trace_id}":{"get":{"tags":["GenAI"],"summary":"Get GenAI span details for a specific trace.","description":"`duration_ms` is the only field guaranteed to be milliseconds. `gen_ai.*`\nspan attributes (e.g. time-to-first-token, token latency) often follow the\nOTel GenAI semantic conventions, which use **seconds** (a fractional\ndouble), not milliseconds — do not read them as ms without converting.","operationId":"get_genai_trace","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"trace_id","in":"path","description":"Trace ID (hex)","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"GenAI trace span details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenAiTraceDetailResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/otel/global/traces/{trace_id}":{"get":{"tags":["Traces"],"summary":"Assemble a unified cross-project span waterfall (Phase 2).","description":"Fans out to every project that holds spans for `trace_id` (up to 20\nprojects, 10,000 total spans). Spans are annotated with\n`project_id`/`project_name` and sorted by `start_time ASC`.\n`truncated: true` signals a hit on either cap; `truncated_projects`\nlists the dropped project IDs. See ADR-027 §4 for the full design.","operationId":"getUnifiedTrace","parameters":[{"name":"trace_id","in":"path","description":"Trace ID (32 lowercase hex characters)","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Unified cross-project trace waterfall","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnifiedTrace"}}}},"400":{"description":"trace_id is not 32 lowercase hex characters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions or deployment token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/otel/health/{project_id}":{"get":{"tags":["OTel"],"summary":"Get health summaries for a project.","operationId":"get_health","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Filter by environment ID","required":false,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Health summaries","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HealthResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/otel/insights/{project_id}":{"get":{"tags":["Insights"],"summary":"List anomaly insights for a project.","operationId":"list_insights","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"status","in":"query","description":"Filter by status (active, resolved)","required":false,"schema":{"type":"string"}},{"name":"limit","in":"query","description":"Max insights to return (default: 20, max: 100)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"offset","in":"query","description":"Offset for pagination","required":false,"schema":{"type":"integer","format":"int64","minimum":0}}],"responses":{"200":{"description":"Insights list","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InsightsResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/otel/logs":{"get":{"tags":["Telemetry Logs"],"summary":"Query log records with optional filters.","operationId":"query_logs","parameters":[{"name":"project_id","in":"query","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"severity","in":"query","description":"Filter by severity (TRACE, DEBUG, INFO, WARN, ERROR, FATAL)","required":false,"schema":{"type":"string"}},{"name":"service_name","in":"query","description":"Filter by service name","required":false,"schema":{"type":"string"}},{"name":"search","in":"query","description":"Full-text search in log body (ILIKE)","required":false,"schema":{"type":"string"}},{"name":"trace_id","in":"query","description":"Filter by correlated trace ID","required":false,"schema":{"type":"string"}},{"name":"start_time","in":"query","description":"Start time (RFC 3339)","required":false,"schema":{"type":"string"}},{"name":"end_time","in":"query","description":"End time (RFC 3339)","required":false,"schema":{"type":"string"}},{"name":"limit","in":"query","description":"Max logs to return (default: 100, max: 1000)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"offset","in":"query","description":"Offset for pagination","required":false,"schema":{"type":"integer","format":"int64","minimum":0}}],"responses":{"200":{"description":"Log records","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LogsResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/otel/metric-label-keys":{"get":{"tags":["Telemetry Metrics"],"summary":"List the attribute (label) keys observed on a metric — powers the\nlabel-filter key autocomplete.","operationId":"list_metric_label_keys","parameters":[{"name":"project_id","in":"query","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"metric_name","in":"query","description":"Metric to inspect","required":true,"schema":{"type":"string"}},{"name":"start_time","in":"query","description":"Window start (RFC 3339); defaults to 24h before end","required":false,"schema":{"type":"string"}},{"name":"end_time","in":"query","description":"Window end (RFC 3339); defaults to now","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Distinct label keys","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OtelMetricLabelKeysResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/otel/metric-label-values":{"get":{"tags":["Telemetry Metrics"],"summary":"List the distinct values seen for a label key on a metric — powers value\nautocomplete once a key is chosen.","operationId":"list_metric_label_values","parameters":[{"name":"project_id","in":"query","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"metric_name","in":"query","description":"Metric to inspect","required":true,"schema":{"type":"string"}},{"name":"label_key","in":"query","description":"Label key whose values to list (must match [a-zA-Z0-9_.:-])","required":true,"schema":{"type":"string"}},{"name":"start_time","in":"query","description":"Window start (RFC 3339); defaults to 24h before end","required":false,"schema":{"type":"string"}},{"name":"end_time","in":"query","description":"Window end (RFC 3339); defaults to now","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Distinct label values","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OtelMetricLabelValuesResponse"}}}},"400":{"description":"Invalid label key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/otel/metric-names/{project_id}":{"get":{"tags":["Telemetry Metrics"],"summary":"List distinct metric names for a project.","operationId":"list_metric_names","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"List of metric names","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OtelMetricNamesResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/otel/metrics":{"get":{"tags":["Telemetry Metrics"],"summary":"Query metrics with time bucketing.","operationId":"query_metrics","parameters":[{"name":"project_id","in":"query","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"metric_name","in":"query","description":"Filter by metric name","required":false,"schema":{"type":"string"}},{"name":"service_name","in":"query","description":"Filter by service name","required":false,"schema":{"type":"string"}},{"name":"environment","in":"query","description":"Filter by deployment environment","required":false,"schema":{"type":"string"}},{"name":"start_time","in":"query","description":"Start time (RFC 3339)","required":false,"schema":{"type":"string"}},{"name":"end_time","in":"query","description":"End time (RFC 3339)","required":false,"schema":{"type":"string"}},{"name":"bucket_interval","in":"query","description":"Bucket interval (e.g. '1 hour', '5 minutes')","required":false,"schema":{"type":"string"}},{"name":"limit","in":"query","description":"Max buckets to return (default: 1000)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"metric_type","in":"query","description":"Filter by metric type (gauge, sum, histogram, exponential_histogram, summary)","required":false,"schema":{"type":"string"}},{"name":"aggregation","in":"query","description":"Per-bucket aggregation: avg (default), sum, min, max, count, rate, p50/p95/p99, quantile:0.95","required":false,"schema":{"type":"string"}},{"name":"label_filters","in":"query","description":"Comma-separated key=value data-point label filters (keys must match [a-zA-Z0-9_.:-])","required":false,"schema":{"type":"string"}},{"name":"group_by","in":"query","description":"Comma-separated label keys to group series by","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Metrics data","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OtelMetricsResponse"}}}},"400":{"description":"Invalid label key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/otel/pipeline-stats":{"get":{"tags":["OTel"],"summary":"Get OTel pipeline statistics (admin/system view).","operationId":"get_pipeline_stats","responses":{"200":{"description":"Pipeline statistics","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PipelineStatsResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/otel/quota/{project_id}":{"get":{"tags":["OTel"],"summary":"Get storage quota for a project.","operationId":"get_quota","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Storage quota","content":{"application/json":{"schema":{"$ref":"#/components/schemas/QuotaResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/otel/trace-summaries":{"get":{"tags":["Traces"],"summary":"Query trace summaries — one row per trace with span count, error count,\nroot span info, and proper trace-level pagination.","operationId":"query_trace_summaries","parameters":[{"name":"project_id","in":"query","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"trace_id","in":"query","description":"Filter by trace ID","required":false,"schema":{"type":"string"}},{"name":"service_name","in":"query","description":"Filter by service name","required":false,"schema":{"type":"string"}},{"name":"status","in":"query","description":"Filter by status (OK, ERROR)","required":false,"schema":{"type":"string"}},{"name":"min_duration_ms","in":"query","description":"Minimum trace duration in ms","required":false,"schema":{"type":"number","format":"double"}},{"name":"start_time","in":"query","description":"Start time (RFC 3339)","required":false,"schema":{"type":"string"}},{"name":"end_time","in":"query","description":"End time (RFC 3339)","required":false,"schema":{"type":"string"}},{"name":"environment_id","in":"query","description":"Filter by environment ID","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"deployment_id","in":"query","description":"Filter by deployment ID","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"name_pattern","in":"query","description":"Filter by span name pattern (ILIKE)","required":false,"schema":{"type":"string"}},{"name":"sort_by","in":"query","description":"Sort field: 'start_time' (default) or 'duration'","required":false,"schema":{"type":"string"}},{"name":"sort_order","in":"query","description":"Sort direction: 'asc' or 'desc' (default)","required":false,"schema":{"type":"string"}},{"name":"include_total","in":"query","description":"Compute the `total` count (default: true). Set false to skip the second aggregation when only the page is needed","required":false,"schema":{"type":"boolean"}},{"name":"limit","in":"query","description":"Max traces to return (default: 50, max: 100)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"offset","in":"query","description":"Offset for pagination","required":false,"schema":{"type":"integer","format":"int64","minimum":0}}],"responses":{"200":{"description":"Trace summaries","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TraceSummariesResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/otel/traces":{"get":{"tags":["Traces"],"summary":"Query trace spans with optional filters.","description":"Each returned span has a `duration_ms` field (float, milliseconds) — this is\nthe ONLY field guaranteed to be in milliseconds. Spans also carry an\n`attributes` map of raw key/value pairs exactly as reported by the\ninstrumenting library: numeric attribute values may be seconds, milliseconds,\nmicroseconds, or nanoseconds depending on that library's convention, and\nnothing in this response labels the unit. Never assume an attribute's\nnumeric value shares `duration_ms`'s unit, and never state a duration in\nmilliseconds unless it came from a `duration_ms` field.","operationId":"query_traces","parameters":[{"name":"project_id","in":"query","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"trace_id","in":"query","description":"Filter by trace ID","required":false,"schema":{"type":"string"}},{"name":"service_name","in":"query","description":"Filter by service name","required":false,"schema":{"type":"string"}},{"name":"status","in":"query","description":"Filter by status (OK, ERROR, UNSET)","required":false,"schema":{"type":"string"}},{"name":"min_duration_ms","in":"query","description":"Minimum span duration in ms","required":false,"schema":{"type":"number","format":"double"}},{"name":"start_time","in":"query","description":"Start time (RFC 3339)","required":false,"schema":{"type":"string"}},{"name":"end_time","in":"query","description":"End time (RFC 3339)","required":false,"schema":{"type":"string"}},{"name":"environment_id","in":"query","description":"Filter by environment ID","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"deployment_id","in":"query","description":"Filter by deployment ID","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"limit","in":"query","description":"Max spans to return (default: 100, max: 1000)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"offset","in":"query","description":"Offset for pagination","required":false,"schema":{"type":"integer","format":"int64","minimum":0}}],"responses":{"200":{"description":"Trace spans","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TracesResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/otel/traces/cross-project/{trace_id}":{"get":{"tags":["Traces"],"summary":"Discover sibling projects that share the same `trace_id` (Phase 1 banner).","description":"Returns an empty `siblings` list when the trace is single-project — never\n404. Project names are included so the UI can render navigation links\nwithout a second round-trip. See ADR-027 §3 for the full auth model and\ntopology-disclosure trade-offs.","operationId":"getCrossProjectTraceSiblings","parameters":[{"name":"trace_id","in":"path","description":"Trace ID (32 lowercase hex characters)","required":true,"schema":{"type":"string"}},{"name":"exclude_project_id","in":"query","description":"Project ID to exclude (the caller's own project) so the UI does not render a self-link","required":false,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Sibling projects sharing this trace","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrossProjectTraceResponse"}}}},"400":{"description":"trace_id is not 32 lowercase hex characters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions or deployment token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/otel/traces/{project_id}/{trace_id}":{"get":{"tags":["Traces"],"summary":"Get all spans for a specific trace.","description":"Each span has a `duration_ms` field (float, milliseconds) — the ONLY field\nguaranteed to be in milliseconds — plus an `attributes` map of raw\nkey/value pairs exactly as the instrumenting library reported them.\nNumeric attribute values (e.g. connection-pool wait times, queue delays)\nmay be in seconds, milliseconds, microseconds, or nanoseconds depending on\nthat library's own convention; this response never labels the unit. When\nexplaining what a span spent time on, only quote milliseconds from\n`duration_ms` (or from `start_time`/`end_time` deltas) — never assume a raw\nattribute number is already in milliseconds.","operationId":"get_trace","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"trace_id","in":"path","description":"Trace ID (hex)","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Trace spans tree","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TracesResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/otel/v1/logs":{"post":{"tags":["OTel Ingest"],"summary":"Ingest log records via OTLP/HTTP protobuf.","description":"Authenticates via API key in header, decompresses, decodes protobuf,\nchecks rate limit and storage quota, routes high-severity logs\nto DB and all logs to S3.","operationId":"ingest_logs","requestBody":{"description":"OTLP ExportLogsServiceRequest (protobuf, optionally gzip/zstd compressed)","content":{"application/x-protobuf":{"schema":{"type":"string"}}},"required":true},"responses":{"200":{"description":"Logs accepted (OTLP protobuf response)"},"400":{"description":"Invalid payload","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Storage quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"api_key":[]}]}},"/otel/v1/metrics":{"post":{"tags":["OTel Ingest"],"summary":"Ingest metrics via OTLP/HTTP protobuf.","description":"Authenticates via API key in header, decompresses, decodes protobuf,\nchecks rate limit and storage quota, then stores.","operationId":"ingest_metrics","requestBody":{"description":"OTLP ExportMetricsServiceRequest (protobuf, optionally gzip/zstd compressed)","content":{"application/x-protobuf":{"schema":{"type":"string"}}},"required":true},"responses":{"200":{"description":"Metrics accepted (OTLP protobuf response)"},"400":{"description":"Invalid payload","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Storage quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"api_key":[]}]}},"/otel/v1/traces":{"post":{"tags":["OTel Ingest"],"summary":"Ingest trace spans via OTLP/HTTP protobuf.","description":"Authenticates via API key in header, decompresses, decodes protobuf,\nchecks rate limit and storage quota, then stores spans.","operationId":"ingest_traces","requestBody":{"description":"OTLP ExportTraceServiceRequest (protobuf, optionally gzip/zstd compressed)","content":{"application/x-protobuf":{"schema":{"type":"string"}}},"required":true},"responses":{"200":{"description":"Traces accepted (OTLP protobuf response)"},"400":{"description":"Invalid payload","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Storage quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"api_key":[]}]}},"/otel/v1/{project_id}/{environment_id}/{deployment_id}/logs":{"post":{"tags":["OTel Ingest"],"summary":"Ingest log records with project/environment/deployment in the URL path.","operationId":"ingest_logs_by_path","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"path","description":"Environment ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"deployment_id","in":"path","description":"Deployment ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"description":"OTLP ExportLogsServiceRequest (protobuf, optionally gzip/zstd compressed)","content":{"application/x-protobuf":{"schema":{"type":"string"}}},"required":true},"responses":{"200":{"description":"Logs accepted (OTLP protobuf response)"},"400":{"description":"Invalid payload","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Storage quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"api_key":[]}]}},"/otel/v1/{project_id}/{environment_id}/{deployment_id}/metrics":{"post":{"tags":["OTel Ingest"],"summary":"Ingest metrics with project/environment/deployment in the URL path.","operationId":"ingest_metrics_by_path","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"path","description":"Environment ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"deployment_id","in":"path","description":"Deployment ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"description":"OTLP ExportMetricsServiceRequest (protobuf, optionally gzip/zstd compressed)","content":{"application/x-protobuf":{"schema":{"type":"string"}}},"required":true},"responses":{"200":{"description":"Metrics accepted (OTLP protobuf response)"},"400":{"description":"Invalid payload","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Storage quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"api_key":[]}]}},"/otel/v1/{project_id}/{environment_id}/{deployment_id}/traces":{"post":{"tags":["OTel Ingest"],"summary":"Ingest trace spans with project/environment/deployment in the URL path.","operationId":"ingest_traces_by_path","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"path","description":"Environment ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"deployment_id","in":"path","description":"Deployment ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"description":"OTLP ExportTraceServiceRequest (protobuf, optionally gzip/zstd compressed)","content":{"application/x-protobuf":{"schema":{"type":"string"}}},"required":true},"responses":{"200":{"description":"Traces accepted (OTLP protobuf response)"},"400":{"description":"Invalid payload","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"413":{"description":"Storage quota exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"api_key":[]}]}},"/performance/has-metrics":{"get":{"tags":["Performance"],"summary":"Check if performance metrics exist for a project","operationId":"has_performance_metrics","parameters":[{"name":"project_id","in":"query","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Successfully checked performance metrics availability","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HasMetricsResponse"}}}},"401":{"description":"Authentication required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearer_auth":[]}]}},"/performance/metrics":{"get":{"tags":["Performance"],"summary":"Get performance metrics","operationId":"get_performance_metrics","parameters":[{"name":"start_date","in":"query","description":"Start date in format YYYY-MM-DD HH:MM:SS","required":true,"schema":{"type":"string"}},{"name":"end_date","in":"query","description":"End date in format YYYY-MM-DD HH:MM:SS","required":true,"schema":{"type":"string"}},{"name":"project_id","in":"query","description":"Project ID or slug","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Environment ID (optional)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"deployment_id","in":"query","description":"Deployment ID (optional)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"device_type","in":"query","description":"Device type filter: desktop or mobile (optional)","required":false,"schema":{"type":"string"}},{"name":"include_bots","in":"query","description":"Include crawler/datacenter bot samples (default false)","required":false,"schema":{"type":"boolean"}},{"name":"filter_path","in":"query","description":"Filter to one page pathname (optional)","required":false,"schema":{"type":"string"}},{"name":"filter_country","in":"query","description":"Filter to one country (optional)","required":false,"schema":{"type":"string"}},{"name":"filter_region","in":"query","description":"Filter to one region (optional)","required":false,"schema":{"type":"string"}},{"name":"filter_city","in":"query","description":"Filter to one city (optional)","required":false,"schema":{"type":"string"}},{"name":"filter_browser","in":"query","description":"Filter to one browser (optional)","required":false,"schema":{"type":"string"}},{"name":"filter_operating_system","in":"query","description":"Filter to one operating system (optional)","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successfully retrieved performance metrics","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PerformanceMetricsResponse"}}}},"400":{"description":"Invalid date format or missing parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Authentication required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearer_auth":[]}]}},"/performance/metrics-over-time":{"get":{"tags":["Performance"],"summary":"Get metrics over time","operationId":"get_metrics_over_time","parameters":[{"name":"start_date","in":"query","description":"Start date in format YYYY-MM-DDTHH:MM:SSZ","required":true,"schema":{"type":"string"}},{"name":"end_date","in":"query","description":"End date in format YYYY-MM-DDTHH:MM:SSZ","required":true,"schema":{"type":"string"}},{"name":"project_id","in":"query","description":"Project ID or slug","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Environment ID (optional)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"deployment_id","in":"query","description":"Deployment ID (optional)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"device_type","in":"query","description":"Device type filter: desktop or mobile (optional)","required":false,"schema":{"type":"string"}},{"name":"include_bots","in":"query","description":"Include crawler/datacenter bot samples (default false)","required":false,"schema":{"type":"boolean"}},{"name":"filter_path","in":"query","description":"Filter to one page pathname (optional)","required":false,"schema":{"type":"string"}},{"name":"filter_country","in":"query","description":"Filter to one country (optional)","required":false,"schema":{"type":"string"}},{"name":"filter_region","in":"query","description":"Filter to one region (optional)","required":false,"schema":{"type":"string"}},{"name":"filter_city","in":"query","description":"Filter to one city (optional)","required":false,"schema":{"type":"string"}},{"name":"filter_browser","in":"query","description":"Filter to one browser (optional)","required":false,"schema":{"type":"string"}},{"name":"filter_operating_system","in":"query","description":"Filter to one operating system (optional)","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successfully retrieved metrics over time","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MetricsOverTimeResponse"}}}},"400":{"description":"Invalid date format or missing parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Authentication required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearer_auth":[]}]}},"/performance/page-metrics":{"get":{"tags":["Performance"],"summary":"Get grouped page metrics","operationId":"get_grouped_page_metrics","parameters":[{"name":"start_date","in":"query","description":"Start date in format YYYY-MM-DDTHH:MM:SSZ","required":true,"schema":{"type":"string"}},{"name":"end_date","in":"query","description":"End date in format YYYY-MM-DDTHH:MM:SSZ","required":true,"schema":{"type":"string"}},{"name":"project_id","in":"query","description":"Project ID or slug","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Environment ID (optional)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"deployment_id","in":"query","description":"Deployment ID (optional)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"group_by","in":"query","description":"Group by: path, country, region, city, device_type, browser, operating_system","required":true,"schema":{"type":"string"}},{"name":"device_type","in":"query","description":"Device type filter: desktop or mobile (optional)","required":false,"schema":{"type":"string"}},{"name":"include_bots","in":"query","description":"Include crawler/datacenter bot samples (default false)","required":false,"schema":{"type":"boolean"}},{"name":"filter_path","in":"query","description":"Filter to one page pathname (optional)","required":false,"schema":{"type":"string"}},{"name":"filter_country","in":"query","description":"Filter to one country (optional)","required":false,"schema":{"type":"string"}},{"name":"filter_region","in":"query","description":"Filter to one region (optional)","required":false,"schema":{"type":"string"}},{"name":"filter_city","in":"query","description":"Filter to one city (optional)","required":false,"schema":{"type":"string"}},{"name":"filter_browser","in":"query","description":"Filter to one browser (optional)","required":false,"schema":{"type":"string"}},{"name":"filter_operating_system","in":"query","description":"Filter to one operating system (optional)","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successfully retrieved grouped page metrics","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GroupedPageMetricsResponse"}}}},"400":{"description":"Invalid date format, missing parameters, or invalid group_by value","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Authentication required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearer_auth":[]}]}},"/platform/access-info":{"get":{"tags":["Platform"],"summary":"Get information about how the service is being accessed","description":"Returns details about the server's access mode, public IP address, private IP address,\nand domain creation capabilities. Both IP addresses are always included when available.","operationId":"get_access_info","responses":{"200":{"description":"Service access information","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceAccessInfo"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/platform/private-ip":{"get":{"tags":["Platform"],"summary":"Get private/local IP address of the server","operationId":"get_private_ip","responses":{"200":{"description":"Successfully retrieved private IP address"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"}},"security":[{"bearer_auth":[]}]}},"/platform/public-ip":{"get":{"tags":["Platform"],"summary":"Get public IP address of the server","operationId":"get_public_ip","responses":{"200":{"description":"Successfully retrieved public IP address"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"}},"security":[{"bearer_auth":[]}]}},"/presets":{"get":{"tags":["Presets"],"summary":"List all available presets","operationId":"list_presets","responses":{"200":{"description":"List of available presets","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListPresetsResponse"}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/presets/{slug}/dockerfile":{"post":{"tags":["Presets"],"summary":"Generate a Dockerfile from a preset","description":"Returns the Dockerfile content and build arguments for a given preset slug.\nThe CLI can use this to build Docker images locally without needing a Dockerfile\nin the project directory, enabling zero-config deployments.","operationId":"generate_preset_dockerfile","parameters":[{"name":"slug","in":"path","description":"Preset slug (e.g., nextjs, vite, python)","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenerateDockerfileRequest"}}},"required":true},"responses":{"200":{"description":"Generated Dockerfile","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenerateDockerfileResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Preset not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/preview-gateway/logs":{"get":{"tags":["Preview Gateway"],"operationId":"get_preview_gateway_logs","parameters":[{"name":"tail","in":"query","description":"Lines to tail (default 200, max 2000)","required":false,"schema":{"type":"integer","minimum":0}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LogsResponse"}}}}},"security":[{"bearer_auth":[]}]}},"/preview-gateway/restart":{"post":{"tags":["Preview Gateway"],"operationId":"restart_preview_gateway","responses":{"204":{"description":"Gateway restarted"}},"security":[{"bearer_auth":[]}]}},"/preview-gateway/settings":{"get":{"tags":["Preview Gateway"],"operationId":"get_preview_gateway_settings","responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PreviewGatewaySettingsResponse"}}}}},"security":[{"bearer_auth":[]}]},"patch":{"tags":["Preview Gateway"],"operationId":"patch_preview_gateway_settings","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PatchSettingsRequest"}}},"required":true},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PreviewGatewaySettingsResponse"}}}}},"security":[{"bearer_auth":[]}]}},"/preview-gateway/status":{"get":{"tags":["Preview Gateway"],"operationId":"get_preview_gateway_status","responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayStatus"}}}}},"security":[{"bearer_auth":[]}]}},"/preview-gateway/upgrade":{"post":{"tags":["Preview Gateway"],"operationId":"upgrade_preview_gateway","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpgradeRequest"}}},"required":true},"responses":{"204":{"description":"Gateway upgraded"}},"security":[{"bearer_auth":[]}]}},"/projects":{"get":{"tags":["Projects"],"summary":"Get a list of all projects","operationId":"get_projects","parameters":[{"name":"page","in":"query","description":"Page number (1-based)","required":false,"schema":{"type":"integer","format":"int64"}},{"name":"per_page","in":"query","description":"Number of items per page","required":false,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"List of projects","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedProjectList"}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Projects"],"summary":"Create a new project","operationId":"create_project","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateProjectRequest"}}},"required":true},"responses":{"200":{"description":"Project created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectResponse"}}}},"400":{"description":"Invalid input"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/by-slug/{slug}":{"get":{"tags":["Projects"],"summary":"Get details of a specific project by slug","operationId":"get_project_by_slug","parameters":[{"name":"slug","in":"path","description":"Project slug","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Project details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectResponse"}}}},"404":{"description":"Project not found"}},"security":[{"bearer_auth":[]}]}},"/projects/from-template":{"post":{"tags":["Projects"],"summary":"Create a new project from a template","description":"Creates a new repository from a template and sets up the project with the\nspecified configuration. The template is cloned to a new repository under\nthe authenticated user's account or specified organization.","operationId":"create_project_from_template","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateProjectFromTemplateRequest"}}},"required":true},"responses":{"201":{"description":"Project created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateProjectFromTemplateResponse"}}}},"400":{"description":"Invalid input"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Template not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/statistics":{"get":{"tags":["Projects"],"summary":"Get project statistics","operationId":"get_project_statistics","responses":{"200":{"description":"Project statistics","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectStatisticsResponse"}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{id}":{"get":{"tags":["Projects"],"summary":"Get details of a specific project","operationId":"get_project","parameters":[{"name":"id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Project details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectResponse"}}}},"404":{"description":"Project not found"}},"security":[{"bearer_auth":[]}]},"put":{"tags":["Projects"],"operationId":"update_project","parameters":[{"name":"id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateProjectRequest"}}},"required":true},"responses":{"200":{"description":"Project updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Project not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["Projects"],"operationId":"delete_project","parameters":[{"name":"id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"Project deleted successfully"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Project not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{id}/deployments":{"get":{"tags":["Projects"],"operationId":"get_project_deployments","parameters":[{"name":"id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"page","in":"query","description":"Page number","required":false,"schema":{"type":"integer","format":"int64"}},{"name":"per_page","in":"query","description":"Items per page","required":false,"schema":{"type":"integer","format":"int64"}},{"name":"environment_id","in":"query","description":"Environment ID filter","required":false,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"List of deployments","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeploymentListResponse"}}}},"404":{"description":"Project not found"}}}},"/projects/{id}/last-deployment":{"get":{"tags":["Deployments"],"summary":"Get the last deployment for a specific project","operationId":"get_last_deployment","parameters":[{"name":"id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Last deployment details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeploymentResponse"}}}},"404":{"description":"Project not found or no deployments"},"500":{"description":"Internal server error"}}}},"/projects/{id}/source":{"patch":{"tags":["Projects"],"summary":"Change a project's source type to a Git-less type (docker_image /\nstatic_files / manual). Switching TO Git is done via the Git settings\nendpoint (`POST /projects/{id}/git`), which also supplies the repository and\nprovider connection.","operationId":"change_project_source","parameters":[{"name":"id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChangeProjectSourceRequest"}}},"required":true},"responses":{"200":{"description":"Source type changed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectResponse"}}}},"400":{"description":"Invalid source type change (e.g. switching to Git here)"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Project not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{id}/trigger-pipeline":{"post":{"tags":["Projects"],"summary":"Trigger pipeline for a specific project","operationId":"trigger_project_pipeline","parameters":[{"name":"id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TriggerPipelinePayload"}}},"required":true},"responses":{"200":{"description":"Pipeline triggered successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TriggerPipelineResponse"}}}},"400":{"description":"Invalid request"},"404":{"description":"Project not found"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/access":{"get":{"tags":["Teams"],"operationId":"list_project_access","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Access grants","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ProjectAccessResponse"}}}}},"403":{"description":"Insufficient permissions or no access to this project"}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Teams"],"operationId":"grant_project_access","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateProjectAccessRequest"}}},"required":true},"responses":{"201":{"description":"Access granted (idempotent upsert)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectAccessResponse"}}}},"403":{"description":"Insufficient permissions or no access to this project"},"404":{"description":"Team not found"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/access/{team_id}":{"delete":{"tags":["Teams"],"operationId":"revoke_project_access","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"team_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"Access revoked"},"403":{"description":"Insufficient permissions or no access to this project"},"404":{"description":"Grant not found"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/active-visitors":{"get":{"tags":["Events"],"summary":"Get active visitors count","operationId":"get_active_visitors","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Filter by environment ID","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"deployment_id","in":"query","description":"Filter by deployment ID","required":false,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Successfully retrieved active visitors count","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActiveVisitorsResponse"}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/agents":{"get":{"tags":["Agents"],"operationId":"list_agents","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"List of agents for project","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListAgentsResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Agents"],"operationId":"create_agent","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpsertAgentRequest"}}},"required":true},"responses":{"201":{"description":"Agent created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentConfigResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/agents/cli-status":{"get":{"tags":["Agents"],"operationId":"get_cli_status","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"provider","in":"query","description":"AI provider: claude_cli or codex_cli","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"CLI status"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/agents/runs":{"get":{"tags":["Agents"],"operationId":"list_all_runs","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"page","in":"query","description":"Page number (1-based)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"page_size","in":"query","description":"Page size (max 100)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}}],"responses":{"200":{"description":"List of all agent runs for a project","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListRunsResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/agents/runs/latest-for-source":{"get":{"tags":["Agents"],"operationId":"latest_run_for_source","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"trigger_source_type","in":"query","description":"Trigger source type, e.g. 'error_group'","required":true,"schema":{"type":"string"}},{"name":"trigger_source_id","in":"query","description":"Trigger source ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Latest matching run, or null if none","content":{"application/json":{"schema":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/AgentRunResponse"}]}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/agents/runs/{run_id}":{"get":{"tags":["Agents"],"operationId":"get_run_with_logs","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"run_id","in":"path","description":"Run ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Run with logs","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentRunWithLogsResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Run not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/agents/runs/{run_id}/cancel":{"post":{"tags":["Agents"],"operationId":"cancel_run","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"run_id","in":"path","description":"Agent run ID to cancel","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Run cancelled","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentRunResponse"}}}},"400":{"description":"Run is already in a terminal state"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Run not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/agents/runs/{run_id}/retry":{"post":{"tags":["Agents"],"summary":"Retry a completed, failed, cancelled, or no_fix run with the same trigger context.\nCreates a new run record and spawns the executor.","operationId":"retry_run","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"run_id","in":"path","description":"Run ID to retry","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"202":{"description":"New run created from retry","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentRunResponse"}}}},"400":{"description":"Run is still active"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Run not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/agents/runs/{run_id}/stream":{"get":{"tags":["Agents"],"summary":"SSE endpoint for real-time streaming of run events.\nPolls the agent_run_logs table every 500ms for new entries and streams them.\nCloses when the run reaches a terminal status.","operationId":"stream_run_events","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"run_id","in":"path","description":"Agent run ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Server-Sent Events stream of run log events and terminal status","content":{"text/event-stream":{}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Run not found"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/agents/sandbox-status":{"get":{"tags":["Agents"],"operationId":"get_sandbox_status","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Project-scoped sandbox readiness (Docker + agent image)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SandboxStatusResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/agents/smoke-test":{"post":{"tags":["Agents"],"summary":"Run a smoke test to verify the selected AI CLI works in the environment\nwhere agents will actually execute (host or sandbox container). If no\n`provider_id` is supplied the globally active provider is tested.","operationId":"smoke_test_agent","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"provider_id","in":"query","description":"Provider id to test; defaults to the globally active provider","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Smoke test result for the AI CLI in the agent's execution environment","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SmokeTestResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/agents/{slug}":{"get":{"tags":["Agents"],"operationId":"get_agent","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"slug","in":"path","description":"Agent slug","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Agent config","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentConfigResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Agent not found"}},"security":[{"bearer_auth":[]}]},"put":{"tags":["Agents"],"operationId":"update_agent","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"slug","in":"path","description":"Agent slug","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpsertAgentRequest"}}},"required":true},"responses":{"200":{"description":"Agent updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentConfigResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Agent not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["Agents"],"operationId":"delete_agent","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"slug","in":"path","description":"Agent slug","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Agent deleted"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Agent not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/agents/{slug}/runs":{"get":{"tags":["Agents"],"operationId":"list_agent_runs","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"slug","in":"path","description":"Agent slug","required":true,"schema":{"type":"string"}},{"name":"page","in":"query","description":"Page number (1-based)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"page_size","in":"query","description":"Page size (max 100)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}}],"responses":{"200":{"description":"List of runs for a specific agent","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListRunsResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Agent not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/agents/{slug}/trigger":{"post":{"tags":["Agents"],"operationId":"trigger_agent","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"slug","in":"path","description":"Agent slug","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TriggerAgentRequest"}}},"required":true},"responses":{"202":{"description":"Agent run created and queued","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentRunResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Unauthorized"},"402":{"description":"Daily budget exceeded"},"403":{"description":"Insufficient permissions"},"404":{"description":"Agent not found"},"422":{"description":"AI CLI not installed"},"429":{"description":"Cooldown active"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/aggregated-buckets":{"get":{"tags":["Events"],"summary":"Get aggregated metrics by time bucket","operationId":"get_aggregated_buckets","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"start_date","in":"query","description":"Start date for the query range","required":true,"schema":{"type":"string"}},{"name":"end_date","in":"query","description":"End date for the query range","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","description":"Optional environment filter","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"deployment_id","in":"query","description":"Optional deployment filter","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"aggregation_level","in":"query","description":"Aggregation level: events, sessions, or visitors (default: events)","required":false,"schema":{"type":"string"}},{"name":"bucket_size","in":"query","description":"Time bucket size: '1 hour', '1 day', '1 week', etc. (default: '1 hour')","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successfully retrieved aggregated buckets","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AggregatedBucketsResponse"}}}},"400":{"description":"Bad request"},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/ai/conversations":{"get":{"tags":["AI Chat"],"summary":"Find the existing chat for a context (returns `null` if none yet). Requires\nthe per-project `ai_debug_chat_enabled` toggle to be on; returns 403 when the\nfeature is disabled so revoking it consistently hides existing chat content.","operationId":"find_conversation","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"context_type","in":"query","required":true,"schema":{"type":"string"}},{"name":"context_id","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/ConversationResponse"}]}}}},"401":{"description":""},"403":{"description":""}},"security":[{"bearer_auth":[]}]},"post":{"tags":["AI Chat"],"summary":"Get-or-create the chat for a context (seeds it on first open).","operationId":"create_conversation","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateConversationRequest"}}},"required":true},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConversationResponse"}}}},"401":{"description":""},"403":{"description":""},"404":{"description":""}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/ai/conversations/list":{"get":{"tags":["AI Chat"],"summary":"List all active conversations for a project, most-recently-active first.\nPowers the conversation switcher in the AI assistant sidebar.","operationId":"list_conversations","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ConversationResponse"}}}}},"401":{"description":""},"403":{"description":""}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/ai/conversations/{public_id}":{"get":{"tags":["AI Chat"],"summary":"Full conversation history (excluding the internal system seed).","operationId":"get_conversation","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"public_id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConversationDetailResponse"}}}},"401":{"description":""},"403":{"description":""},"404":{"description":""}},"security":[{"bearer_auth":[]}]},"patch":{"tags":["AI Chat"],"summary":"Rename a conversation (set its human-facing title).","operationId":"rename_conversation","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"public_id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RenameConversationRequest"}}},"required":true},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConversationResponse"}}}},"400":{"description":""},"401":{"description":""},"403":{"description":""},"404":{"description":""}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/ai/conversations/{public_id}/archive":{"post":{"tags":["AI Chat"],"summary":"Archive (soft-delete) a conversation.","operationId":"archive_conversation","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"public_id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":""},"401":{"description":""},"403":{"description":""},"404":{"description":""}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/ai/conversations/{public_id}/messages":{"post":{"tags":["AI Chat"],"summary":"Send a user message; stream the assistant reply as Server-Sent Events.","operationId":"send_message","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"public_id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendMessageRequest"}}},"required":true},"responses":{"200":{"description":"SSE stream of assistant text deltas","content":{"text/event-stream":{}}},"401":{"description":""},"403":{"description":""},"404":{"description":""}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/ai/conversations/{public_id}/pending-actions":{"get":{"tags":["AI Chat"],"summary":"List all pending actions for a conversation (most-recently-proposed first).","operationId":"list_pending_actions","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"public_id","in":"path","description":"Conversation public id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/PendingActionResponse"}}}}},"401":{"description":""},"403":{"description":""},"404":{"description":""}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/ai/pending-actions/{action_public_id}":{"get":{"tags":["AI Chat"],"summary":"Get a single pending action by its public id (scoped to the project).","operationId":"get_pending_action","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"action_public_id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PendingActionResponse"}}}},"401":{"description":""},"403":{"description":""},"404":{"description":""}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/ai/pending-actions/{action_public_id}/confirm":{"post":{"tags":["AI Chat"],"summary":"Confirm a proposed AI action: validate permission, atomically claim, execute,\npersist outcome. The execution uses the CONFIRMING user's auth — never the model's.","operationId":"confirm_pending_action","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"action_public_id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PendingActionResponse"}}}},"401":{"description":""},"403":{"description":""},"404":{"description":""},"409":{"description":""},"503":{"description":""}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/ai/pending-actions/{action_public_id}/reject":{"post":{"tags":["AI Chat"],"summary":"Reject a proposed AI action (no execution). Status transitions to \"rejected\".","operationId":"reject_pending_action","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"action_public_id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PendingActionResponse"}}}},"401":{"description":""},"403":{"description":""},"404":{"description":""},"409":{"description":""}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/ai/readiness":{"get":{"tags":["AI Chat"],"summary":"Report which AI prerequisites this project satisfies.","description":"Read-only and cheap, so the UI can decide up front whether to show a working\nentry point, an onboarding path, or nothing — instead of letting the user\nclick something that fails with a 409 they can't act on.","operationId":"get_chat_readiness","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Which AI prerequisites are met","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatReadinessResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Project not found"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/alarms":{"get":{"tags":["Alarms"],"summary":"List alarms for a project with optional filters.","operationId":"listProjectAlarms","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"alarm_type","in":"query","description":"Filter by alarm type (e.g. `container_restart`, `outage`).","required":false,"schema":{"type":["string","null"]}},{"name":"status","in":"query","description":"Filter by status: `firing`, `acknowledged`, or `resolved`.","required":false,"schema":{"type":["string","null"]}},{"name":"severity","in":"query","description":"Filter by severity: `info`, `warning`, or `critical`.","required":false,"schema":{"type":["string","null"]}},{"name":"environment_id","in":"query","description":"Filter by environment ID.","required":false,"schema":{"type":["integer","null"],"format":"int32"}},{"name":"deployment_id","in":"query","description":"Filter by deployment ID.","required":false,"schema":{"type":["integer","null"],"format":"int32"}},{"name":"service_id","in":"query","description":"Filter by external service ID.","required":false,"schema":{"type":["integer","null"],"format":"int32"}},{"name":"page","in":"query","description":"Page number (1-based, default 1).","required":false,"schema":{"type":["integer","null"],"format":"int64","minimum":0}},{"name":"page_size","in":"query","description":"Items per page (default 20, max 100).","required":false,"schema":{"type":["integer","null"],"format":"int64","minimum":0}}],"responses":{"200":{"description":"Paginated list of alarms","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlarmListResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/alarms/summary":{"get":{"tags":["Alarms"],"summary":"Get alarm counts by status/severity/type for a project (dashboard summary widget).","operationId":"getProjectAlarmsSummary","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Alarm summary counts","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlarmSummaryResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/alarms/{alarm_id}/acknowledge":{"post":{"tags":["Alarms"],"summary":"Acknowledge a firing alarm (marks it as seen but not resolved).","operationId":"acknowledgeAlarm","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"alarm_id","in":"path","description":"Alarm ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Alarm acknowledged"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Alarm not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/alarms/{alarm_id}/resolve":{"post":{"tags":["Alarms"],"summary":"Resolve an alarm.","operationId":"resolveAlarm","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"alarm_id","in":"path","description":"Alarm ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Alarm resolved"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Alarm not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/autofixer/analyze":{"post":{"tags":["Autofixer"],"summary":"Start an autofixer analysis run for the given error group.\nCreates the run record immediately and spawns analysis in the background.","operationId":"start_analysis","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StartAnalysisRequest"}}},"required":true},"responses":{"202":{"description":"Analysis started; returns run_id for streaming","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutofixerRunResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/autofixer/runs/{run_id}":{"get":{"tags":["Autofixer"],"summary":"Get a single autofixer run with its logs.","operationId":"get_run","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"run_id","in":"path","description":"Run ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Run with logs","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutofixerRunWithLogsResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Run not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/autofixer/runs/{run_id}/add-context":{"post":{"tags":["Autofixer"],"summary":"Append a user message to the run's context field.","operationId":"add_context","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"run_id","in":"path","description":"Run ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddContextRequest"}}},"required":true},"responses":{"200":{"description":"Context appended"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Run not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/autofixer/runs/{run_id}/cancel":{"post":{"tags":["Autofixer"],"summary":"Cancel an autofixer run and clean up the work directory.","operationId":"cancel","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"run_id","in":"path","description":"Run ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Run cancelled"},"400":{"description":"Run is already in a terminal state"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Run not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/autofixer/runs/{run_id}/create-pr":{"post":{"tags":["Autofixer"],"summary":"Push the fix branch and create a pull request.\nRequires phase == \"fix_ready\".","operationId":"create_pr","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"run_id","in":"path","description":"Run ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"201":{"description":"PR created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatePrResponse"}}}},"400":{"description":"Run not in fix_ready phase"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Run not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/autofixer/runs/{run_id}/fix":{"post":{"tags":["Autofixer"],"summary":"Transition from analysis to fix phase.\nRequires phase == \"analyzed\".","operationId":"start_fix","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"run_id","in":"path","description":"Run ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"202":{"description":"Fix generation started"},"400":{"description":"Run not in analyzed phase"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Run not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/autofixer/runs/{run_id}/re-analyze":{"post":{"tags":["Autofixer"],"summary":"Continue the conversation with user feedback.\nUses the same Claude session (--continue) in the existing work directory.\nRequires phase == \"analyzed\".","operationId":"re_analyze","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"run_id","in":"path","description":"Run ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"202":{"description":"Conversation continued with feedback"},"400":{"description":"Run not in analyzed phase"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Run not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/autofixer/runs/{run_id}/stream":{"get":{"tags":["Agents"],"summary":"SSE endpoint: streams run log events in real-time.\nPolls every 500 ms. Keeps the connection open through \"analyzed\" and \"fix_ready\"\nwaiting states; closes only on terminal statuses.","operationId":"stream_events","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"run_id","in":"path","description":"Autofixer run ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Server-Sent Events stream of autofixer run logs and status updates","content":{"text/event-stream":{}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Run not found"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/automatic-deploy":{"post":{"tags":["Projects"],"summary":"Update automatic deployment setting for a project","operationId":"update_automatic_deploy","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateAutomaticDeployRequest"}}},"required":true},"responses":{"200":{"description":"Automatic deployment setting updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Project not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/custom-domains":{"get":{"tags":["Custom Domains"],"summary":"List all custom domains for a project","operationId":"list_custom_domains_for_project","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Custom domains retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListCustomDomainsResponse"}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Custom Domains"],"summary":"Create a custom domain for a project","operationId":"create_custom_domain","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomDomainRequest"}}},"required":true},"responses":{"201":{"description":"Custom domain created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomDomainResponse"}}}},"400":{"description":"Invalid input"},"401":{"description":"Unauthorized"},"409":{"description":"Domain already exists"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/custom-domains/{domain_id}":{"get":{"tags":["Custom Domains"],"summary":"Get a custom domain by ID","operationId":"get_custom_domain","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"domain_id","in":"path","description":"Custom domain ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Custom domain retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomDomainResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Custom domain not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"put":{"tags":["Custom Domains"],"summary":"Update a custom domain","operationId":"update_custom_domain","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"domain_id","in":"path","description":"Custom domain ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateCustomDomainRequest"}}},"required":true},"responses":{"200":{"description":"Custom domain updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomDomainResponse"}}}},"400":{"description":"Invalid input"},"401":{"description":"Unauthorized"},"404":{"description":"Custom domain not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["Custom Domains"],"summary":"Delete a custom domain","operationId":"delete_custom_domain","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"domain_id","in":"path","description":"Custom domain ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"Custom domain deleted successfully"},"401":{"description":"Unauthorized"},"404":{"description":"Custom domain not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/custom-domains/{domain_id}/link-certificate/{certificate_id}":{"post":{"tags":["Custom Domains"],"summary":"Link a custom domain to a certificate","operationId":"link_custom_domain_to_certificate","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"domain_id","in":"path","description":"Custom domain ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"certificate_id","in":"path","description":"Certificate ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Custom domain linked to certificate successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomDomainResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Custom domain or certificate not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/deployment-config":{"patch":{"tags":["Projects"],"summary":"Update deployment configuration for a project","operationId":"update_project_deployment_config","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateDeploymentConfigRequest"}}},"required":true},"responses":{"200":{"description":"Deployment configuration updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectResponse"}}}},"400":{"description":"Invalid deployment configuration"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Project not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/deployment-tokens":{"get":{"tags":["Deployment Tokens"],"summary":"List all deployment tokens for a project","operationId":"list_deployment_tokens","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"page","in":"query","description":"Page number (default: 1)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"page_size","in":"query","description":"Page size (default: 20, max: 100)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}}],"responses":{"200":{"description":"List of deployment tokens","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeploymentTokenListResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Deployment Tokens"],"summary":"Create a new deployment token for a project","operationId":"create_deployment_token","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateDeploymentTokenRequest"}}},"required":true},"responses":{"201":{"description":"Deployment token created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateDeploymentTokenResponse"}}}},"400":{"description":"Invalid request"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"409":{"description":"Token with this name already exists"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/deployment-tokens/{token_id}":{"get":{"tags":["Deployment Tokens"],"summary":"Get a specific deployment token","operationId":"get_deployment_token","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"token_id","in":"path","description":"Deployment token ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Deployment token details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeploymentTokenResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Deployment token not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["Deployment Tokens"],"summary":"Delete a deployment token","operationId":"delete_deployment_token","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"token_id","in":"path","description":"Deployment token ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"Deployment token deleted successfully"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Deployment token not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"patch":{"tags":["Deployment Tokens"],"summary":"Update a deployment token","operationId":"update_deployment_token","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"token_id","in":"path","description":"Deployment token ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateDeploymentTokenRequest"}}},"required":true},"responses":{"200":{"description":"Deployment token updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeploymentTokenResponse"}}}},"400":{"description":"Invalid request"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Deployment token not found"},"409":{"description":"Token with this name already exists"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/deployment-tokens/{token_id}/rotate":{"post":{"tags":["Deployment Tokens"],"summary":"Rotate a deployment token, invalidating its old secret and issuing a new one","operationId":"rotate_deployment_token","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"token_id","in":"path","description":"Deployment token ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Deployment token rotated successfully; the response contains the new plaintext token, shown only once","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateDeploymentTokenResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Deployment token not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/deployments/{deployment_id}":{"get":{"tags":["Deployments"],"summary":"Get a specific deployment by ID for a project (identified by ID or slug)","operationId":"get_deployment","parameters":[{"name":"project_id","in":"path","description":"Project ID or slug","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"deployment_id","in":"path","description":"Deployment ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Deployment details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeploymentResponse"}}}},"404":{"description":"Project or deployment not found"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/deployments/{deployment_id}/cancel":{"post":{"tags":["Projects"],"summary":"Cancel a deployment","operationId":"cancel_deployment","parameters":[{"name":"project_id","in":"path","description":"Project ID or slug","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"deployment_id","in":"path","description":"Deployment ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Deployment cancelled successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeploymentStateResponse"}}}},"400":{"description":"Deployment cannot be cancelled (already completed, failed, or cancelled)"},"404":{"description":"Project or deployment not found"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/deployments/{deployment_id}/container-logs":{"get":{"tags":["Deployments"],"summary":"List the captured (historical) container-log dumps for a deployment.","description":"Container runtime logs are normally only available live from the running\ncontainer. When a deployment is superseded its containers are torn down and\nthose logs would be lost — so just before teardown we capture each\ncontainer's logs to durable storage. This endpoint lists what was captured\nfor a given (often older) deployment, so a user can read the logs of a\ncontainer that no longer exists.","operationId":"list_deployment_container_logs","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"deployment_id","in":"path","description":"Deployment ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Captured container logs for the deployment","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeploymentContainerLogsListResponse"}}}},"404":{"description":"Deployment not found in this project"},"500":{"description":"Internal server error"}},"security":[{"bearer_token":[]}]}},"/projects/{project_id}/deployments/{deployment_id}/container-logs/{log_id}":{"get":{"tags":["Deployments"],"summary":"Get the captured text content of a single historical container-log dump.","operationId":"get_deployment_container_log_content","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"deployment_id","in":"path","description":"Deployment ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"log_id","in":"path","description":"Captured log ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Captured container log content","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeploymentContainerLogContentResponse"}}}},"404":{"description":"Captured log not found in this project"},"500":{"description":"Internal server error"}},"security":[{"bearer_token":[]}]}},"/projects/{project_id}/deployments/{deployment_id}/jobs":{"get":{"tags":["Deployments"],"summary":"Get jobs for a specific deployment","description":"Returns all jobs (workflow tasks) for a deployment, ordered by execution order.\nThis replaces the old deployment stages endpoint.","operationId":"get_deployment_jobs","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"deployment_id","in":"path","description":"Deployment ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Jobs retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeploymentJobsResponse"}}}},"404":{"description":"Deployment not found"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/deployments/{deployment_id}/jobs/{job_id}/logs":{"get":{"tags":["Deployments"],"summary":"Get logs for a specific deployment job","operationId":"get_deployment_job_logs","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"deployment_id","in":"path","description":"Deployment ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"job_id","in":"path","description":"Job ID","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Job logs retrieved successfully","content":{"text/plain":{"schema":{"type":"string"}}}},"404":{"description":"Job or logs not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_token":[]}]}},"/projects/{project_id}/deployments/{deployment_id}/jobs/{job_id}/logs/tail":{"get":{"tags":["Deployments"],"summary":"Tail logs for a specific deployment job in real-time via WebSocket","description":"**WebSocket Streaming**: Logs are sent as raw text, one line per WebSocket message.\n\n**Authentication**: Requires authentication via session cookie (browser clients)\nor API key (API clients). For browser-based WebSocket connections, ensure the user\nis logged in - the browser automatically includes session cookies in the WebSocket\nupgrade request.\n\n**API Client Authentication**: Include API key in Authorization header:\n```text\nAuthorization: Bearer tk_your_api_key_here\n```","operationId":"tail_deployment_job_logs","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"deployment_id","in":"path","description":"Deployment ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"job_id","in":"path","description":"Job ID","required":true,"schema":{"type":"string"}}],"responses":{"101":{"description":"WebSocket connection established for streaming deployment job logs"},"404":{"description":"Job or logs not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_token":[]}]}},"/projects/{project_id}/deployments/{deployment_id}/operations":{"get":{"tags":["Deployments"],"summary":"Get all operations for a deployment","operationId":"get_deployment_operations","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"deployment_id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"List of operations","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OperationResultsResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Deployment not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Deployments"],"summary":"Execute a deployment operation (deploy, mark_complete, take_screenshot)","operationId":"execute_deployment_operation","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"deployment_id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExecuteOperationRequest"}}},"required":true},"responses":{"202":{"description":"Operation executed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OperationResultResponse"}}}},"400":{"description":"Invalid operation"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Deployment not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/deployments/{deployment_id}/operations/{operation_type}":{"get":{"tags":["Deployments"],"summary":"Get the status of a specific operation type","operationId":"get_deployment_operation_status","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"deployment_id","in":"path","required":true,"schema":{"type":"string"}},{"name":"operation_type","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Operation status","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OperationResultResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Operation not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/deployments/{deployment_id}/pause":{"post":{"tags":["Projects"],"summary":"Pause a deployment","operationId":"pause_deployment","parameters":[{"name":"project_id","in":"path","description":"Project ID or slug","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"deployment_id","in":"path","description":"Deployment ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Deployment paused successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeploymentStateResponse"}}}},"404":{"description":"Project or deployment not found"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/deployments/{deployment_id}/promote":{"post":{"tags":["Deployments"],"summary":"Promote a deployment to another environment","description":"Creates a new deployment in the target environment using the source deployment's\nDocker image. Useful for promoting a validated preview/staging deployment to production.","operationId":"promote_deployment","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"deployment_id","in":"path","description":"Source deployment ID to promote","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PromoteDeploymentRequest"}}},"required":true},"responses":{"200":{"description":"Promotion initiated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeploymentResponse"}}}},"400":{"description":"Invalid deployment state for promotion"},"404":{"description":"Project, deployment, or target environment not found"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/deployments/{deployment_id}/resume":{"post":{"tags":["Projects"],"summary":"Resume a deployment","operationId":"resume_deployment","parameters":[{"name":"project_id","in":"path","description":"Project ID or slug","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"deployment_id","in":"path","description":"Deployment ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Deployment resumed successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeploymentStateResponse"}}}},"404":{"description":"Project or deployment not found"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/deployments/{deployment_id}/rollback":{"post":{"tags":["Projects"],"operationId":"rollback_to_deployment","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"deployment_id","in":"path","description":"Deployment ID to rollback to","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Rollback initiated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeploymentResponse"}}}},"404":{"description":"Project or deployment not found"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/deployments/{deployment_id}/teardown":{"delete":{"tags":["Projects"],"summary":"Teardown a specific deployment","operationId":"teardown_deployment","parameters":[{"name":"project_id","in":"path","description":"Project ID or slug","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"deployment_id","in":"path","description":"Deployment ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"Deployment torn down successfully"},"404":{"description":"Project or deployment not found"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/dsns":{"get":{"tags":[],"summary":"List all DSNs for a project","operationId":"list_dsns","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"List of DSNs","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ProjectDSNResponse"}}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"}},"security":[{"bearer_auth":[]}]},"post":{"tags":[],"summary":"Create a new DSN for a project","operationId":"create_dsn","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateDSNRequest"}}},"required":true},"responses":{"201":{"description":"DSN created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectDSNResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Project not found"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/dsns/get-or-create":{"post":{"tags":[],"summary":"Get or create DSN for a project/environment/deployment combination","operationId":"get_or_create_dsn","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetOrCreateDSNRequest"}}},"required":true},"responses":{"200":{"description":"DSN retrieved or created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectDSNResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Project not found"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/dsns/{dsn_id}/regenerate":{"post":{"tags":[],"summary":"Regenerate DSN keys (rotate keys)","operationId":"regenerate_dsn","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"dsn_id","in":"path","description":"DSN ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RegenerateDSNRequest"}}},"required":true},"responses":{"200":{"description":"DSN keys regenerated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectDSNResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"DSN not found"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/dsns/{dsn_id}/revoke":{"post":{"tags":[],"summary":"Revoke (deactivate) a DSN","operationId":"revoke_dsn","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"dsn_id","in":"path","description":"DSN ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"DSN revoked"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"DSN not found"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/env-vars":{"get":{"tags":["Projects"],"summary":"Get environment variables for a project, optionally filtered by environment","operationId":"get_environment_variables","parameters":[{"name":"project_id","in":"path","description":"Project ID or slug","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Optional environment ID to filter by","required":false,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"List of environment variables","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/EnvironmentVariableResponse"}}}}},"404":{"description":"Project not found"},"500":{"description":"Internal server error"}}},"post":{"tags":["Projects"],"summary":"Create a new environment variable","operationId":"create_environment_variable","parameters":[{"name":"project_id","in":"path","description":"Project ID or slug","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateEnvironmentVariableRequest"}}},"required":true},"responses":{"201":{"description":"Environment variables created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnvironmentVariableResponse"}}}},"400":{"description":"Invalid input"},"404":{"description":"Project not found"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/env-vars/resolved":{"get":{"tags":["Projects"],"summary":"Resolved env vars for a project (manual + integration-sourced, merged).","description":"Returns the effective set of environment variables a deployment would see,\ncombining manually-defined vars with those contributed by linked external\nservices (Postgres, Redis, S3, etc.). Each entry is tagged with its source\nso the UI can render an integration icon, and manual entries that shadow an\nintegration key carry a reference to the integration they override.\n\nValues are always returned as a masked preview. Use the per-key reveal\nendpoint for plaintext (audit-logged).","operationId":"get_resolved_environment_variables","parameters":[{"name":"project_id","in":"path","description":"Project ID or slug","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Optional environment ID to filter manual vars by","required":false,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Resolved environment variables","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ResolvedEnvVarResponse"}}}}},"404":{"description":"Project not found"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/env-vars/resolved/{key}/value":{"get":{"tags":["Projects"],"summary":"Reveal the plaintext value of a resolved environment variable.","description":"Mirrors `GET /projects/{id}/env-vars/{key}/value` but handles keys sourced\nfrom linked integrations (which are not stored in the `env_vars` table).\nResolution order mirrors the merged view:\n\n1. Manual env var with this key — this endpoint reads the manual store when\n the key exists there, then writes its own reveal audit event so callers\n can safely use one endpoint regardless of source.\n2. Integration env var supplied by a linked external service.\n\nReturns 404 when neither a manual var nor an integration produces the key.","operationId":"get_resolved_environment_variable_value","parameters":[{"name":"project_id","in":"path","description":"Project ID or slug","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"key","in":"path","description":"Environment variable key","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","description":"Optional environment ID","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"var_id","in":"query","description":"Exact manual environment-variable row ID","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"service_id","in":"query","description":"Integration service ID shown by the resolved list","required":false,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Resolved environment variable value","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnvironmentVariableValueResponse"}}}},"403":{"description":"Plaintext secret access is not permitted"},"404":{"description":"Project, key, or integration not found"},"409":{"description":"Environment variable key is ambiguous"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/env-vars/{key}/value":{"get":{"tags":["Projects"],"summary":"Get environment variable value by key","operationId":"get_environment_variable_value","parameters":[{"name":"project_id","in":"path","description":"Project ID or slug","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"key","in":"path","description":"Environment variable key","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","description":"Optional environment ID","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"var_id","in":"query","description":"Exact environment-variable row ID","required":false,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Environment variable value","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnvironmentVariableValueResponse"}}}},"403":{"description":"Plaintext secret access is not permitted"},"404":{"description":"Project or variable not found"},"409":{"description":"Environment variable key is ambiguous"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/env-vars/{var_id}":{"put":{"tags":["Projects"],"summary":"Update an environment variable","operationId":"update_environment_variable","parameters":[{"name":"project_id","in":"path","description":"Project ID or slug","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"var_id","in":"path","description":"Environment variable ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateEnvironmentVariableRequest"}}},"required":true},"responses":{"200":{"description":"Environment variables updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnvironmentVariableResponse"}}}},"400":{"description":"Invalid input"},"404":{"description":"Project or variable not found"},"500":{"description":"Internal server error"}}},"delete":{"tags":["Projects"],"summary":"Delete an environment variable","operationId":"delete_environment_variable","parameters":[{"name":"project_id","in":"path","description":"Project ID or slug","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"var_id","in":"path","description":"Environment variable ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"Environment variable deleted successfully"},"404":{"description":"Project or variable not found"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/environments":{"get":{"tags":["Projects"],"summary":"Get all environments for a project","operationId":"get_environments","parameters":[{"name":"project_id","in":"path","description":"Project ID or slug","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"List of environments","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/EnvironmentResponse"}}}}},"404":{"description":"Project not found"},"500":{"description":"Internal server error"}}},"post":{"tags":["Projects"],"summary":"Create a new environment for a project","operationId":"create_environment","parameters":[{"name":"project_id","in":"path","description":"Project ID or slug","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateEnvironmentRequest"}}},"required":true},"responses":{"201":{"description":"Environment created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnvironmentResponse"}}}},"400":{"description":"Invalid input"},"404":{"description":"Project not found"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/environments/{env_id}":{"get":{"tags":["Projects"],"summary":"Get a specific environment by ID or slug","operationId":"get_environment","parameters":[{"name":"project_id","in":"path","description":"Project ID or slug","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"env_id","in":"path","description":"Environment ID or slug","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Environment details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnvironmentResponse"}}}},"404":{"description":"Project or environment not found"},"500":{"description":"Internal server error"}}},"delete":{"tags":["Projects"],"summary":"Delete an environment permanently","description":"Permanently deletes an environment and all related data. Cannot delete:\n- Production environments (name = \"Production\")\n\nWarning: This action is permanent and cannot be undone.\nActive deployments are automatically cancelled before deletion.","operationId":"delete_environment","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"env_id","in":"path","description":"Environment ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"Environment permanently deleted"},"400":{"description":"Cannot delete production environment"},"404":{"description":"Project or environment not found"},"428":{"description":"Recent MFA verification required"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/environments/{env_id}/crons":{"get":{"tags":["Crons"],"operationId":"get_environment_crons","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"env_id","in":"path","description":"Environment ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"List of cron jobs","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/CronInfo"}}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/environments/{env_id}/crons/{cron_id}":{"get":{"tags":["Crons"],"operationId":"get_cron_by_id","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"env_id","in":"path","description":"Environment ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"cron_id","in":"path","description":"Cron Job ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Cron job details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CronInfo"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Cron job not found"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/environments/{env_id}/crons/{cron_id}/executions":{"get":{"tags":["Crons"],"operationId":"get_cron_executions","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"env_id","in":"path","description":"Environment ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"cron_id","in":"path","description":"Cron Job ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"page","in":"query","description":"Page number (default: 1)","required":false,"schema":{"type":"integer","format":"int64"}},{"name":"per_page","in":"query","description":"Items per page (default: 20)","required":false,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"List of cron job executions","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/CronExecutionInfo"}}}}},"401":{"description":"Unauthorized"},"404":{"description":"Cron job not found"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/environments/{env_id}/domains":{"get":{"tags":["Projects"],"summary":"Get all environment domains for a specific environment","operationId":"get_environment_domains","parameters":[{"name":"project_id","in":"path","description":"Project ID or slug","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"env_id","in":"path","description":"Environment ID or slug","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"List of environment domains","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/EnvironmentDomainResponse"}}}}},"404":{"description":"Project or environment not found"},"500":{"description":"Internal server error"}}},"post":{"tags":["Projects"],"summary":"Add a new environment domain","operationId":"add_environment_domain","parameters":[{"name":"project_id","in":"path","description":"Project ID or slug","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"env_id","in":"path","description":"Environment ID or slug","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddEnvironmentDomainRequest"}}},"required":true},"responses":{"201":{"description":"Domain added successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnvironmentDomainResponse"}}}},"400":{"description":"Invalid input"},"404":{"description":"Project or environment not found"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/environments/{env_id}/domains/{domain_id}":{"delete":{"tags":["Projects"],"summary":"Delete an environment domain","operationId":"delete_environment_domain","parameters":[{"name":"project_id","in":"path","description":"Project ID or slug","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"env_id","in":"path","description":"Environment ID or slug","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"domain_id","in":"path","description":"Domain ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"Domain deleted successfully"},"404":{"description":"Project, environment, or domain not found"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/environments/{env_id}/settings":{"put":{"tags":["Projects"],"summary":"Update environment settings","operationId":"update_environment_settings","parameters":[{"name":"project_id","in":"path","description":"Project ID or slug","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"env_id","in":"path","description":"Environment ID or slug","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateEnvironmentSettingsRequest"}}},"required":true},"responses":{"200":{"description":"Environment settings updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnvironmentResponse"}}}},"404":{"description":"Project or environment not found"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/environments/{env_id}/sleep":{"post":{"tags":["Environments"],"summary":"Sleep an on-demand environment","description":"Manually put an on-demand environment to sleep. Stops containers and sets\n`sleeping = true`. If no OnDemandWaker is available, falls back to DB flag only.","operationId":"sleep_environment","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"env_id","in":"path","description":"Environment ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Environment put to sleep","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnvironmentResponse"}}}},"400":{"description":"On-demand not enabled for this environment"},"404":{"description":"Environment not found"},"429":{"description":"Too many state transitions, retry after cooldown"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/environments/{env_id}/subdomain":{"patch":{"tags":["Projects"],"summary":"Rename the auto-managed subdomain for an environment.","description":"Replaces the environment's previous subdomain entirely — the old\nhostname stops resolving once the proxy reloads its route table.\nCustom domains attached to the environment are unaffected.","operationId":"update_environment_subdomain","parameters":[{"name":"project_id","in":"path","description":"Project ID or slug","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"env_id","in":"path","description":"Environment ID or slug","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateEnvironmentSubdomainRequest"}}},"required":true},"responses":{"200":{"description":"Subdomain updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnvironmentResponse"}}}},"400":{"description":"Invalid subdomain or conflict with another environment"},"404":{"description":"Project or environment not found"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/environments/{env_id}/teardown":{"delete":{"tags":["Projects"],"summary":"Teardown an environment and all its active deployments","operationId":"teardown_environment","parameters":[{"name":"project_id","in":"path","description":"Project ID or slug","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"env_id","in":"path","description":"Environment ID or slug","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"Environment torn down successfully"},"404":{"description":"Project or environment not found"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/environments/{env_id}/wake":{"post":{"tags":["Environments"],"summary":"Wake a sleeping on-demand environment","description":"Manually wake an environment that has been put to sleep by the on-demand\nidle timeout. Starts containers, waits for health checks, then sets\n`sleeping = false`. If no OnDemandWaker is available (proxy not running\nin same process), falls back to setting the DB flag only.","operationId":"wake_environment","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"env_id","in":"path","description":"Environment ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Environment woken up","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnvironmentResponse"}}}},"400":{"description":"On-demand not enabled for this environment"},"404":{"description":"Environment not found"},"429":{"description":"Too many state transitions, retry after cooldown"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/environments/{environment_id}/container-logs":{"get":{"tags":["Deployments"],"summary":"Get logs for a container in an environment via WebSocket","operationId":"get_container_logs","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"path","description":"Environment ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"start_date","in":"query","description":"Start date for logs","required":false,"schema":{"type":"integer","format":"int64"}},{"name":"end_date","in":"query","description":"End date for logs","required":false,"schema":{"type":"integer","format":"int64"}},{"name":"tail","in":"query","description":"Number of lines to tail (or 'all')","required":false,"schema":{"type":"string"}},{"name":"container_name","in":"query","description":"Optional container name (defaults to first/primary container)","required":false,"schema":{"type":"string"}},{"name":"timestamps","in":"query","description":"Include timestamps in log output (default: false)","required":false,"schema":{"type":"boolean"}},{"name":"follow","in":"query","description":"Follow log output in real-time (default: true)","required":false,"schema":{"type":"boolean"}}],"responses":{"101":{"description":"WebSocket connection established for streaming container logs"},"400":{"description":"Not a server-type project"},"404":{"description":"Project, deployment, or container not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/environments/{environment_id}/containers":{"get":{"tags":["Deployments"],"summary":"List all containers for an environment","operationId":"list_containers","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"path","description":"Environment ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"List of containers","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContainerListResponse"}}}},"400":{"description":"Not a server-type project"},"404":{"description":"Project or environment not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/environments/{environment_id}/containers/{container_id}":{"get":{"tags":["Containers"],"summary":"Get detailed information about a specific container","operationId":"get_container_detail","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"path","description":"Environment ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"container_id","in":"path","description":"Container ID","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Container details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContainerDetailResponse"}}}},"404":{"description":"Container not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/environments/{environment_id}/containers/{container_id}/environment/{variable_name}":{"get":{"tags":["Containers"],"operationId":"get_container_environment_variable","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"path","description":"Environment ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"container_id","in":"path","description":"Container ID","required":true,"schema":{"type":"string"}},{"name":"variable_name","in":"path","description":"Environment variable name","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Environment variable value","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContainerEnvironmentVariableValueResponse"}}}},"403":{"description":"Plaintext secret access is not permitted"},"404":{"description":"Container or environment variable not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/environments/{environment_id}/containers/{container_id}/logs":{"get":{"tags":["Deployments"],"summary":"Get logs for a specific container by container ID via WebSocket","operationId":"get_container_logs_by_id","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"path","description":"Environment ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"container_id","in":"path","description":"Container ID","required":true,"schema":{"type":"string"}},{"name":"start_date","in":"query","description":"Start date for logs","required":false,"schema":{"type":"integer","format":"int64"}},{"name":"end_date","in":"query","description":"End date for logs","required":false,"schema":{"type":"integer","format":"int64"}},{"name":"tail","in":"query","description":"Number of lines to tail (or 'all')","required":false,"schema":{"type":"string"}},{"name":"timestamps","in":"query","description":"Include timestamps in log output (default: false)","required":false,"schema":{"type":"boolean"}},{"name":"follow","in":"query","description":"Follow log output in real-time (default: true)","required":false,"schema":{"type":"boolean"}}],"responses":{"101":{"description":"WebSocket connection established for streaming container logs"},"400":{"description":"Not a server-type project"},"404":{"description":"Project, environment, or container not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/environments/{environment_id}/containers/{container_id}/metrics":{"get":{"tags":["Containers"],"summary":"Get metrics/stats for a specific container","operationId":"get_container_metrics","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"path","description":"Environment ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"container_id","in":"path","description":"Container ID","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Container metrics retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContainerMetricsResponse"}}}},"404":{"description":"Container not found"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/environments/{environment_id}/containers/{container_id}/metrics/history":{"get":{"tags":["Containers"],"summary":"Fetch a time-series range for a single container resource metric\n(recorded by the container health monitor every ~30s).","description":"Useful metric names: `container.cpu_percent`,\n`container.cpu_utilization_percent`, `container.memory_used_bytes`,\n`container.memory_percent`, `container.network_rx_bytes_delta`,\n`container.network_tx_bytes_delta`.","operationId":"ContainerMetricsGetHistory","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"path","description":"Environment ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"container_id","in":"path","description":"Container ID","required":true,"schema":{"type":"string"}},{"name":"metric","in":"query","description":"Dotted metric name, e.g. `container.cpu_percent` or\n`container.memory_used_bytes`.","required":true,"schema":{"type":"string"}},{"name":"range","in":"query","description":"Time window: `1h`, `6h`, `24h`, or `7d` (defaults to `1h`).","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Metric time series data points","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ContainerMetricHistoryPoint"}}}}},"401":{"description":"Unauthorized"},"404":{"description":"Container not found"},"500":{"description":"Internal server error"},"503":{"description":"Metrics store not available"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/environments/{environment_id}/containers/{container_id}/metrics/stream":{"get":{"tags":["Containers"],"summary":"Stream container metrics via Server-Sent Events (SSE)","operationId":"stream_container_metrics","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"path","description":"Environment ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"container_id","in":"path","description":"Container ID","required":true,"schema":{"type":"string"}},{"name":"interval","in":"query","description":"Update interval in milliseconds (default: 1000)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}}],"responses":{"200":{"description":"Metrics stream established (Server-Sent Events)"},"404":{"description":"Container not found"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/environments/{environment_id}/containers/{container_id}/restart":{"post":{"tags":["Containers"],"summary":"Restart a container","operationId":"restart_container","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"path","description":"Environment ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"container_id","in":"path","description":"Container ID","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Container restarted successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContainerActionResponse"}}}},"404":{"description":"Container not found"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/environments/{environment_id}/containers/{container_id}/start":{"post":{"tags":["Containers"],"summary":"Start a container","operationId":"start_container","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"path","description":"Environment ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"container_id","in":"path","description":"Container ID","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Container started successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContainerActionResponse"}}}},"404":{"description":"Container not found"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/environments/{environment_id}/containers/{container_id}/stop":{"post":{"tags":["Containers"],"summary":"Stop a specific container","operationId":"stop_container","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"path","description":"Environment ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"container_id","in":"path","description":"Container ID","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Container stopped successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContainerActionResponse"}}}},"404":{"description":"Container not found"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/environments/{environment_id}/deploy/image":{"post":{"tags":["Deployments"],"summary":"Deploy from an external Docker image","description":"Triggers a deployment using a pre-built Docker image from an external registry.\nThe image will be pulled and deployed to the specified environment.","operationId":"deploy_from_image","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeployFromImageRequest"}}},"required":true},"responses":{"202":{"description":"Deployment started","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RemoteDeploymentResponse"}}}},"400":{"description":"Invalid request"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Project or environment not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/environments/{environment_id}/deploy/image-upload":{"post":{"tags":["Deployments"],"summary":"Deploy from an uploaded Docker image tarball","description":"Uploads a Docker image tarball (from `docker save`) and deploys it directly.\nThe image is imported using `docker load` and then deployed to the specified environment.\nThis is useful when you want to deploy an image without pushing to a registry first.\n\nThe uploaded file should be a tarball created by `docker save myimage:tag > image.tar`\nor `docker save myimage:tag | gzip > image.tar.gz` (gzip compressed tarballs are also supported).","operationId":"deploy_from_image_upload","parameters":[{"name":"tag","in":"query","description":"Tag to apply to the imported image (e.g., \"myapp:v1.0\")\nIf not provided, a unique tag will be generated","required":false,"schema":{"type":["string","null"]}},{"name":"health_check_path","in":"query","description":"Optional HTTP health-check path override (e.g. \"/api/healthz\").\nMust start with '/'. When omitted, defaults to \"/\".","required":false,"schema":{"type":["string","null"]}},{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"202":{"description":"Image imported and deployment started","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RemoteDeploymentResponse"}}}},"400":{"description":"Invalid request or unsupported format"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Project or environment not found"},"413":{"description":"Image tarball too large"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/environments/{environment_id}/deploy/source":{"post":{"tags":["Deployments"],"summary":"Upload source code and immediately start a preset-based deployment.","operationId":"deploy_from_uploaded_source","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/SourceArchiveUpload"}}},"required":true},"responses":{"202":{"description":"Source deployment started","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RemoteDeploymentResponse"}}}},"400":{"description":"Invalid source archive"},"404":{"description":"Project or environment not found"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/environments/{environment_id}/deploy/static":{"post":{"tags":["Deployments"],"summary":"Deploy from an uploaded static bundle","description":"Triggers a deployment using a previously uploaded static file bundle.","operationId":"deploy_from_static","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeployFromStaticRequest"}}},"required":true},"responses":{"202":{"description":"Deployment started","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RemoteDeploymentResponse"}}}},"400":{"description":"Invalid request"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Project, environment, or bundle not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/error-alert-rules":{"get":{"tags":["error-alert-rules"],"summary":"List all alert rules for a project","operationId":"list_alert_rules","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"List of alert rules","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/AlertRuleResponse"}}}}},"500":{"description":"Internal server error"}}},"post":{"tags":["error-alert-rules"],"summary":"Create a new alert rule","operationId":"create_alert_rule","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateAlertRuleRequest"}}},"required":true},"responses":{"201":{"description":"Alert rule created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertRuleResponse"}}}},"400":{"description":"Validation error"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/error-alert-rules/{rule_id}":{"get":{"tags":["error-alert-rules"],"summary":"Get a specific alert rule","operationId":"get_alert_rule","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"rule_id","in":"path","description":"Alert rule ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Alert rule details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertRuleResponse"}}}},"404":{"description":"Alert rule not found"},"500":{"description":"Internal server error"}}},"put":{"tags":["error-alert-rules"],"summary":"Update an existing alert rule","operationId":"update_alert_rule","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"rule_id","in":"path","description":"Alert rule ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateAlertRuleRequest"}}},"required":true},"responses":{"200":{"description":"Alert rule updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertRuleResponse"}}}},"400":{"description":"Validation error"},"404":{"description":"Alert rule not found"},"500":{"description":"Internal server error"}}},"delete":{"tags":["error-alert-rules"],"summary":"Delete an alert rule","operationId":"delete_alert_rule","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"rule_id","in":"path","description":"Alert rule ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"Alert rule deleted"},"404":{"description":"Alert rule not found"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/error-dashboard-stats":{"get":{"tags":["error-tracking"],"summary":"Get error dashboard statistics","operationId":"get_error_dashboard_stats","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"start_time","in":"query","required":true,"schema":{"type":"string","format":"date-time"}},{"name":"end_time","in":"query","required":true,"schema":{"type":"string","format":"date-time"}},{"name":"environment_id","in":"query","required":false,"schema":{"type":["integer","null"],"format":"int32"}},{"name":"compare_to_previous","in":"query","required":false,"schema":{"type":["boolean","null"]}}],"responses":{"200":{"description":"Error dashboard statistics","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDashboardStatsResponse"}}}},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/error-groups":{"get":{"tags":["error-tracking"],"summary":"List error groups for a project","operationId":"list_error_groups","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"page_size","in":"query","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"status","in":"query","required":false,"schema":{"type":["string","null"]}},{"name":"environment_id","in":"query","required":false,"schema":{"type":["integer","null"],"format":"int32"}},{"name":"start_date","in":"query","required":false,"schema":{"type":["string","null"],"format":"date-time"}},{"name":"end_date","in":"query","required":false,"schema":{"type":["string","null"],"format":"date-time"}},{"name":"sort_by","in":"query","required":false,"schema":{"type":["string","null"]}},{"name":"sort_order","in":"query","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Paginated list of error groups","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedErrorGroupsResponse"}}}},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/error-groups/{group_id}":{"get":{"tags":["error-tracking"],"summary":"Get a specific error group","operationId":"get_error_group","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"group_id","in":"path","description":"Error group ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Error group details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorGroupResponse"}}}},"404":{"description":"Error group not found"},"500":{"description":"Internal server error"}}},"put":{"tags":["error-tracking"],"summary":"Update error group status","operationId":"update_error_group","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"group_id","in":"path","description":"Error group ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateErrorGroupRequest"}}},"required":true},"responses":{"200":{"description":"Error group updated successfully"},"404":{"description":"Error group not found"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/error-groups/{group_id}/events":{"get":{"tags":["error-tracking"],"summary":"List error events for a specific group","operationId":"list_error_events","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"group_id","in":"path","description":"Error group ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"page_size","in":"query","required":false,"schema":{"type":"integer","format":"int64","minimum":0}}],"responses":{"200":{"description":"Paginated list of error events","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedErrorEventsResponse"}}}},"404":{"description":"Error group not found"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/error-groups/{group_id}/events/{event_id}":{"get":{"tags":["error-tracking"],"summary":"Get a specific error event","operationId":"get_error_event","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"group_id","in":"path","description":"Error group ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"event_id","in":"path","description":"Error event ID","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"Error event details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEventResponse"}}}},"404":{"description":"Event not found"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/error-stats":{"get":{"tags":["error-tracking"],"summary":"Get error statistics for a project","operationId":"get_error_stats","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Error statistics","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorGroupStatsResponse"}}}},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/error-time-series":{"get":{"tags":["error-tracking"],"summary":"Get error time series data for charts","operationId":"get_error_time_series","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"start_time","in":"query","required":true,"schema":{"type":"string","format":"date-time"}},{"name":"end_time","in":"query","required":true,"schema":{"type":"string","format":"date-time"}},{"name":"bucket","in":"query","description":"Time bucket size (e.g., \"1h\", \"15m\", \"1d\", \"1 hour\", \"30 minutes\")","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Error time series data","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ErrorTimeSeriesDataResponse"}}}}},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/events":{"get":{"tags":["Events"],"summary":"Get event counts with filtering","operationId":"get_events_count","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"start_date","in":"query","description":"Start date for filtering events","required":true,"schema":{"type":"string"}},{"name":"end_date","in":"query","description":"End date for filtering events","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","description":"Filter by environment ID","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"limit","in":"query","description":"Maximum number of events to return (default: 20, max: 100)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"custom_events_only","in":"query","description":"Only return custom events, excluding system events like page_view, page_leave, heartbeat (default: true)","required":false,"schema":{"type":"boolean"}},{"name":"aggregation_level","in":"query","description":"Aggregation level: events, sessions, or visitors (default: events)","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successfully retrieved event counts","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/EventCount"}}}}},"400":{"description":"Bad request"},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/events/breakdown":{"get":{"tags":["Events"],"summary":"Get event type breakdown","operationId":"get_event_type_breakdown","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"start_date","in":"query","description":"Start date for filtering events","required":true,"schema":{"type":"string"}},{"name":"end_date","in":"query","description":"End date for filtering events","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","description":"Filter by environment ID","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"aggregation_level","in":"query","description":"Aggregation level: events, sessions, or visitors (default: events)","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successfully retrieved event type breakdown","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/EventTypeBreakdown"}}}}},"400":{"description":"Bad request"},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/events/ingest":{"post":{"tags":["Events"],"summary":"Record an analytics event via the console API with explicit project ID.","description":"The app backend forwards the user's encrypted Temps cookies, so visitor/session\nidentity is resolved automatically by middleware. No geolocation or user-agent\nenrichment is performed — this is a lightweight server-side ingestion path.","operationId":"record_console_event","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConsoleEventPayload"}}},"required":true},"responses":{"200":{"description":"Event recorded successfully"},"400":{"description":"Bad request"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/events/properties/breakdown":{"get":{"tags":["Events"],"summary":"Get property breakdown by grouping events by a column","operationId":"get_property_breakdown","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"start_date","in":"query","description":"Start date in '%Y-%m-%d %H:%M:%S' format","required":true,"schema":{"type":"string"}},{"name":"end_date","in":"query","description":"End date in '%Y-%m-%d %H:%M:%S' format","required":true,"schema":{"type":"string"}},{"name":"group_by","in":"query","description":"Column to group by (channel, device_type, browser, etc.)","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","description":"Filter by environment ID","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"deployment_id","in":"query","description":"Filter by deployment ID","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"event_name","in":"query","description":"Filter by event name","required":false,"schema":{"type":"string"}},{"name":"aggregation_level","in":"query","description":"Aggregation level: events, sessions, or visitors - default: events","required":false,"schema":{"type":"string"}},{"name":"limit","in":"query","description":"Maximum number of results (default: 20, max: 100)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"filter_country","in":"query","description":"Filter by country (for region/city drill-downs)","required":false,"schema":{"type":"string"}},{"name":"filter_region","in":"query","description":"Filter by region (for city drill-downs)","required":false,"schema":{"type":"string"}},{"name":"filter_browser","in":"query","description":"Filter by browser name (for version drill-downs)","required":false,"schema":{"type":"string"}},{"name":"filter_os","in":"query","description":"Filter by OS name (for version drill-downs)","required":false,"schema":{"type":"string"}},{"name":"filter_channel","in":"query","description":"Filter by channel name (for channel drill-downs)","required":false,"schema":{"type":"string"}},{"name":"filter_referrer","in":"query","description":"Filter by referrer hostname (for referrer drill-downs)","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successfully retrieved property breakdown","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PropertyBreakdownResponse"}}}},"400":{"description":"Bad request"},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/events/properties/timeline":{"get":{"tags":["Events"],"summary":"Get property timeline by grouping events by a column over time","operationId":"get_property_timeline","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"start_date","in":"query","description":"Start date in '%Y-%m-%d %H:%M:%S' format","required":true,"schema":{"type":"string"}},{"name":"end_date","in":"query","description":"End date in '%Y-%m-%d %H:%M:%S' format","required":true,"schema":{"type":"string"}},{"name":"group_by","in":"query","description":"Column to group by (channel, device_type, browser, etc.)","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","description":"Filter by environment ID","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"deployment_id","in":"query","description":"Filter by deployment ID","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"event_name","in":"query","description":"Filter by event name","required":false,"schema":{"type":"string"}},{"name":"aggregation_level","in":"query","description":"Aggregation level: events, sessions, or visitors - default: events","required":false,"schema":{"type":"string"}},{"name":"bucket_size","in":"query","description":"Time bucket: hour, day, week, month (default: auto-detect)","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successfully retrieved property timeline","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PropertyTimelineResponse"}}}},"400":{"description":"Bad request"},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/events/timeline":{"get":{"tags":["Events"],"summary":"Get events timeline","operationId":"get_events_timeline","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"start_date","in":"query","description":"Start date for filtering events","required":true,"schema":{"type":"string"}},{"name":"end_date","in":"query","description":"End date for filtering events","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","description":"Filter by environment ID","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"event_name","in":"query","description":"Filter by specific event name","required":false,"schema":{"type":"string"}},{"name":"bucket_size","in":"query","description":"Bucket size: hour, day, or week (auto-detected if not specified)","required":false,"schema":{"type":"string"}},{"name":"aggregation_level","in":"query","description":"Aggregation level: events, sessions, or visitors (default: events)","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successfully retrieved events timeline","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/EventTimeline"}}}}},"400":{"description":"Bad request"},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/events/unique":{"get":{"tags":["Funnels"],"summary":"Get all unique/distinct event types for a project (paginated)","operationId":"get_unique_events","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"page","in":"query","description":"Page number (default: 1)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"page_size","in":"query","description":"Items per page (default: 50, max: 100)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}}],"responses":{"200":{"description":"Unique event types retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EventTypesResponse"}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/external-images":{"get":{"tags":["External Images"],"summary":"List external images for a project","operationId":"list_remote_external_images","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"page","in":"query","description":"Page number (default: 1)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"page_size","in":"query","description":"Items per page (default: 20)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}}],"responses":{"200":{"description":"List of external images","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedExternalImagesResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"post":{"tags":["External Images"],"summary":"Register an external Docker image","description":"Registers an external Docker image reference without triggering a deployment.\nThe image can be deployed later using the deploy/image endpoint.","operationId":"register_external_image","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RegisterImageRequest"}}},"required":true},"responses":{"201":{"description":"Image registered successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExternalImageResponse"}}}},"400":{"description":"Invalid request"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Project not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/external-images/{image_id}":{"get":{"tags":["External Images"],"summary":"Get details of a specific external image","operationId":"get_remote_external_image","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"image_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Image details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExternalImageResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Image not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["External Images"],"summary":"Delete an external image","operationId":"delete_external_image","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"image_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"Image deleted"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Image not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/flags":{"get":{"tags":["Feature Flags"],"operationId":"list_flags","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"include_archived","in":"query","description":"Include archived flags. Defaults to false.","required":false,"schema":{"type":"boolean"}},{"name":"page","in":"query","description":"1-indexed page number. Defaults to 1.","required":false,"schema":{"type":["integer","null"],"format":"int64","minimum":0}},{"name":"page_size","in":"query","description":"Items per page. Defaults to 20, capped at 100.","required":false,"schema":{"type":["integer","null"],"format":"int64","minimum":0}}],"responses":{"200":{"description":"Flags listed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FlagListResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Feature Flags"],"operationId":"create_flag","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateFlagRequest"}}},"required":true},"responses":{"201":{"description":"Flag created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FlagResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"409":{"description":"Flag key already exists"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/flags/{key}":{"get":{"tags":["Feature Flags"],"operationId":"get_flag","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"key","in":"path","description":"Flag key","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Flag retrieved","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FlagResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Flag not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["Feature Flags"],"operationId":"archive_flag","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"key","in":"path","description":"Flag key","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Flag archived","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ArchiveFlagResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Flag not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"patch":{"tags":["Feature Flags"],"operationId":"update_flag","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"key","in":"path","description":"Flag key","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateFlagRequest"}}},"required":true},"responses":{"200":{"description":"Flag updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FlagResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Flag not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/flags/{key}/environments/{environment_id}":{"put":{"tags":["Feature Flags"],"summary":"Set a flag's value in one environment, and/or flip its kill switch.","operationId":"set_flag_environment","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"key","in":"path","description":"Flag key","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"path","description":"Environment ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetFlagEnvironmentRequest"}}},"required":true},"responses":{"200":{"description":"Environment value set","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FlagEnvironmentResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Flag or environment not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/flags/{key}/restore":{"post":{"tags":["Feature Flags"],"summary":"Bring an archived flag back.","description":"Archiving is otherwise one-way: the key stays reserved so the flag cannot\neven be re-created under the same name, which makes an accidental archive\nunrecoverable through the API.","operationId":"restore_flag","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"key","in":"path","description":"Flag key","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Flag restored","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FlagResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Flag not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/funnels":{"get":{"tags":["Funnels"],"summary":"List all funnels for a project","operationId":"list_funnels","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Funnels retrieved successfully","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/FunnelResponse"}}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Funnels"],"summary":"Create a new funnel","operationId":"create_funnel","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateFunnelRequest"}}},"required":true},"responses":{"201":{"description":"Funnel created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateFunnelResponse"}}}},"400":{"description":"Bad request"},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/funnels/preview":{"post":{"tags":["Funnels"],"summary":"Preview funnel metrics without creating the funnel","operationId":"preview_funnel_metrics","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateFunnelRequest"}}},"required":true},"responses":{"200":{"description":"Funnel metrics preview","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FunnelMetricsResponse"}}}},"400":{"description":"Bad request"},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/funnels/{funnel_id}":{"put":{"tags":["Funnels"],"summary":"Update a funnel","operationId":"update_funnel","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"funnel_id","in":"path","description":"Funnel ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateFunnelRequest"}}},"required":true},"responses":{"200":{"description":"Funnel updated successfully"},"400":{"description":"Bad request"},"401":{"description":"Unauthorized"},"404":{"description":"Funnel not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["Funnels"],"summary":"Delete a funnel","operationId":"delete_funnel","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"funnel_id","in":"path","description":"Funnel ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Funnel deleted successfully"},"401":{"description":"Unauthorized"},"404":{"description":"Funnel not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/funnels/{funnel_id}/metrics":{"get":{"tags":["Funnels"],"summary":"Get funnel metrics","operationId":"get_funnel_metrics","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"funnel_id","in":"path","description":"Funnel ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Environment ID filter","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"country_code","in":"query","description":"Country code filter","required":false,"schema":{"type":"string"}},{"name":"start_date","in":"query","description":"Start date filter (ISO 8601)","required":false,"schema":{"type":"string"}},{"name":"end_date","in":"query","description":"End date filter (ISO 8601)","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Funnel metrics retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FunnelMetricsResponse"}}}},"400":{"description":"Bad request"},"401":{"description":"Unauthorized"},"404":{"description":"Funnel not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/git":{"post":{"tags":["Projects"],"summary":"Update git settings for a project","operationId":"update_git_settings","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateGitSettingsRequest"}}},"required":true},"responses":{"200":{"description":"Git settings updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectResponse"}}}},"400":{"description":"Invalid git configuration or branch does not exist"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Project not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/gitlab/reinstall-webhook":{"post":{"tags":["Projects"],"summary":"Reinstall the GitLab webhook for a project","description":"Removes the existing webhook (if any) and installs a fresh one.\nUse this when a webhook has been manually deleted on the GitLab side\nand automatic deployments have stopped working.","operationId":"reinstall_gitlab_webhook","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Webhook reinstalled","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReinstallWebhookResponse"}}}},"400":{"description":"Project is not connected to a GitLab repository"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Project not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/has-error-groups":{"get":{"tags":["error-tracking"],"summary":"Check if project has any error groups","operationId":"has_error_groups","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Error groups existence check","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HasErrorGroupsResponse"}}}},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/has-events":{"get":{"tags":["Events"],"summary":"Check if project has any analytics events","operationId":"has_analytics_events","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Successfully checked for events","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HasEventsResponse"}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/hourly-visits":{"get":{"tags":["Events"],"summary":"Get hourly visits","operationId":"get_hourly_visits","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"start_date","in":"query","description":"Start date for filtering visits","required":true,"schema":{"type":"string"}},{"name":"end_date","in":"query","description":"End date for filtering visits","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","description":"Filter by environment ID","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"aggregation_level","in":"query","description":"Aggregation level: events (page views), sessions (unique sessions), or visitors (unique visitors) - default: events","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successfully retrieved hourly visits","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/EventTimeline"}}}}},"400":{"description":"Bad request"},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/images":{"get":{"tags":["External Images"],"summary":"List all external images for a project","operationId":"list_external_images","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"List of external images","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/PushedExternalImageResponse"}}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/images/push":{"post":{"tags":["External Images"],"summary":"Push an external Docker image","operationId":"push_external_image","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PushImageRequest"}}},"required":true},"responses":{"201":{"description":"Image pushed successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PushedExternalImageResponse"}}}},"400":{"description":"Invalid request"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/images/{image_id}":{"get":{"tags":["External Images"],"summary":"Get details of a specific external image","operationId":"get_external_image","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"image_id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Image details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PushedExternalImageResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Image not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/incidents":{"get":{"tags":["Status Page"],"summary":"List incidents for a project","operationId":"list_incidents","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Filter by environment ID","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"status","in":"query","description":"Filter by status","required":false,"schema":{"type":"string"}},{"name":"page","in":"query","description":"Page number","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"page_size","in":"query","description":"Items per page","required":false,"schema":{"type":"integer","format":"int64","minimum":0}}],"responses":{"200":{"description":"Successfully retrieved incidents"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Status Page"],"summary":"Create a new incident","operationId":"create_incident","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateIncidentRequest"}}},"required":true},"responses":{"201":{"description":"Incident created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IncidentResponse"}}}},"400":{"description":"Invalid request"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/incidents/bucketed":{"get":{"tags":["Status Page"],"summary":"Get bucketed incident data for a project","operationId":"get_bucketed_incidents","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Filter by environment ID","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"interval","in":"query","description":"Bucket interval: '5min', 'hourly', or 'daily' (default: hourly)","required":false,"schema":{"type":"string"}},{"name":"start_time","in":"query","description":"Start time (ISO 8601) (default: 7 days ago)","required":false,"schema":{"type":"string"}},{"name":"end_time","in":"query","description":"End time (ISO 8601) (default: now)","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successfully retrieved bucketed incident data","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IncidentBucketedResponse"}}}},"400":{"description":"Invalid parameters"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/logs":{"delete":{"tags":["Logs"],"summary":"Purge all logs for a project before a given timestamp","operationId":"purge_project_logs","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PurgeLogsRequest"}}},"required":true},"responses":{"200":{"description":"Purge completed"},"400":{"description":"Invalid parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/mcp-servers":{"get":{"tags":["Agents"],"operationId":"list_mcps","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListMcpsResponse"}}}},"401":{"description":"Unauthorized"}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Agents"],"operationId":"create_mcp","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateMcpRequest"}}},"required":true},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/McpDefinitionResponse"}}}},"401":{"description":"Unauthorized"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/mcp-servers/{slug}":{"get":{"tags":["Agents"],"operationId":"get_mcp","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"slug","in":"path","description":"MCP server slug","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/McpDefinitionResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"MCP server not found"}},"security":[{"bearer_auth":[]}]},"put":{"tags":["Agents"],"operationId":"update_mcp","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"slug","in":"path","description":"MCP server slug","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateMcpRequest"}}},"required":true},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/McpDefinitionResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"MCP server not found"}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["Agents"],"operationId":"delete_mcp","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"slug","in":"path","description":"MCP server slug","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"MCP server deleted"},"401":{"description":"Unauthorized"},"404":{"description":"MCP server not found"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/mcp-servers/{slug}/config/{field}":{"get":{"tags":["Agents"],"operationId":"reveal_mcp_config","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"slug","in":"path","description":"MCP server slug","required":true,"schema":{"type":"string"}},{"name":"field","in":"path","description":"Sensitive field path, such as url or env.API_TOKEN","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SensitiveMcpConfigValueResponse"}}}},"400":{"description":"Field is not revealable"},"401":{"description":"Unauthorized"},"403":{"description":"Missing secrets:read permission"},"404":{"description":"MCP server or field not found"},"500":{"description":"Configuration read or audit failed"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/monitors":{"get":{"tags":["Status Page"],"summary":"List monitors for a project","operationId":"list_monitors","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Filter by environment ID","required":false,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Successfully retrieved monitors","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/MonitorResponse"}}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Status Page"],"summary":"Create a new monitor","operationId":"create_monitor","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateMonitorRequest"}}},"required":true},"responses":{"201":{"description":"Monitor created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MonitorResponse"}}}},"400":{"description":"Invalid request"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/observe/events":{"get":{"tags":["Observability"],"summary":"List a merged page of observability events for a project.","description":"Each row carries everything the side panel needs to render — no\nfollow-up fetch is required for the common case. Heavy fields\n(stacktraces, headers, span attributes) are truncated server-side and\nexpose a `*_truncated` flag; clients fetch the full row from the\n`/full` endpoint only when the user explicitly clicks \"Show full\".","operationId":"observability_list_events","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"kinds","in":"query","description":"Comma-separated kinds: `log,request,span,error,revenue`. Empty or\nmissing returns every kind.","required":false,"schema":{"type":"string"}},{"name":"from","in":"query","description":"Inclusive lower bound on event timestamp (ISO 8601, `Z` suffix).","required":false,"schema":{"type":"string","format":"date-time"}},{"name":"to","in":"query","description":"Inclusive upper bound on event timestamp.","required":false,"schema":{"type":"string","format":"date-time"}},{"name":"deployment_id","in":"query","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"search","in":"query","description":"Free-text substring matched against per-kind summary fields\n(request path / error class / revenue event_type).","required":false,"schema":{"type":"string"}},{"name":"limit","in":"query","description":"Page size (default 50, max 200).","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"hide_bots","in":"query","description":"When `true`, exclude bot/crawler request rows. When `false`, only\ninclude bot rows. Omitted means \"include everything\" (default).\nOnly affects the `Request` kind.","required":false,"schema":{"type":"boolean"}}],"responses":{"200":{"description":"Merged event page","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EventsResponse"}}}},"400":{"description":"Invalid filter (kinds, time range, …)","content":{"text/plain":{"schema":{"type":"string"}}}},"401":{"description":"Unauthorized","content":{"text/plain":{"schema":{"type":"string"}}}},"403":{"description":"Insufficient permissions","content":{"text/plain":{"schema":{"type":"string"}}}},"500":{"description":"Internal server error","content":{"text/plain":{"schema":{"type":"string"}}}}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/observe/events/{kind}/{event_id}/full":{"get":{"tags":["Observability"],"summary":"Fetch the un-truncated form of one event by `(kind, id)`. Side panel\n\"Show full\" action calls this — the list response carries truncated\npreviews + a `*_truncated` flag to let the UI decide whether to fetch.","operationId":"observability_full_event","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"kind","in":"path","description":"Event kind discriminator","required":true,"schema":{"$ref":"#/components/schemas/EventKind"}},{"name":"event_id","in":"path","description":"Per-kind identity: request_id for requests, `{trace_id}:{span_id}` for spans, serial id for errors/revenue","required":true,"schema":{"type":"string"}},{"name":"ts","in":"query","description":"The row's event timestamp as returned by the list endpoint. Optional,\nbut strongly recommended: it bounds the lookup to the storage\npartitions/chunks around that instant instead of scanning the whole\nretention window.","required":false,"schema":{"type":"string","format":"date-time"}}],"responses":{"200":{"description":"Full row","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FullEvent"}}}},"401":{"description":"Unauthorized","content":{"text/plain":{"schema":{"type":"string"}}}},"403":{"description":"Insufficient permissions","content":{"text/plain":{"schema":{"type":"string"}}}},"404":{"description":"Event not found in project","content":{"text/plain":{"schema":{"type":"string"}}}},"500":{"description":"Internal server error","content":{"text/plain":{"schema":{"type":"string"}}}}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/releases/{release}/source-files":{"get":{"tags":["source-maps"],"summary":"List uploaded source files for a release (metadata only).","operationId":"list_source_files","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"release","in":"path","description":"Release version","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"List of source files","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SourceFileListResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"}},"security":[{"bearer_auth":[]}]},"post":{"tags":["source-maps"],"summary":"Upload a raw source file for a release (native symbolication).","description":"Accepts a multipart form with:\n- `file`: the source file bytes (required)\n- `file_path`: the path of the file as it appears in stack frames (required;\n derived from the uploaded filename if omitted). Normalized with the `~`\n prefix convention, matching source-map storage.\n\nRequires the project's `error_source_context_enabled` toggle to be on.\nUpserts on (project, release, file_path).","operationId":"upload_source_file","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"release","in":"path","description":"Release version","required":true,"schema":{"type":"string"}}],"responses":{"201":{"description":"Source file uploaded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SourceFileResponse"}}}},"400":{"description":"Missing fields"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"409":{"description":"Source context disabled for project"},"413":{"description":"Source file too large"}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["source-maps"],"summary":"Delete all uploaded source files for a release.","operationId":"delete_release_source_files","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"release","in":"path","description":"Release version","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Source files deleted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/releases/{release}/source-maps":{"get":{"tags":["source-maps"],"summary":"List all source maps for a specific release","operationId":"list_source_maps","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"release","in":"path","description":"Release version","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"List of source maps","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SourceMapListResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"}},"security":[{"bearer_auth":[]}]},"post":{"tags":["source-maps"],"summary":"Upload a source map for a release.","description":"Accepts a multipart form with:\n- `file`: The .map file (required)\n- `file_path`: The URL path of the minified file as it appears in stack traces (required).\n Uses the ~ prefix convention (e.g., \"~/assets/main.js\").\n If a full URL is provided, it will be normalized automatically.\n- `dist`: Optional distribution identifier\n\nIf a source map already exists for the same (project, release, file_path), it is replaced.","operationId":"upload_source_map","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"release","in":"path","description":"Release version","required":true,"schema":{"type":"string"}}],"responses":{"201":{"description":"Source map uploaded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SourceMapResponse"}}}},"400":{"description":"Invalid source map or missing fields"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"413":{"description":"Source map too large"}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["source-maps"],"summary":"Delete all source maps for a specific release","operationId":"delete_release_source_maps","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"release","in":"path","description":"Release version","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Source maps deleted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/revenue/events":{"get":{"tags":["Revenue"],"summary":"Recent ingested events for the activity feed.","operationId":"revenue_recent_events","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/RecentEventResponse"}}}}}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/revenue/integrations":{"get":{"tags":["Revenue"],"summary":"List revenue integrations for a project.","operationId":"revenue_list_integrations","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/IntegrationResponse"}}}}}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Revenue"],"summary":"Create a new revenue integration. Response contains the generated\nwebhook path that the user must paste into their provider's dashboard.","operationId":"revenue_create_integration","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateIntegrationBody"}}},"required":true},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IntegrationResponse"}}}},"400":{"description":"Validation error"},"409":{"description":"Already connected"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/revenue/integrations/{integration_id}":{"delete":{"tags":["Revenue"],"summary":"Delete a revenue integration (permanent — use rotate_token to refresh\ncredentials without breaking history).","operationId":"revenue_delete_integration","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"integration_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":""}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/revenue/integrations/{integration_id}/config":{"post":{"tags":["Revenue"],"summary":"Replace the typed provider config on an integration. Passing `null`\nclears the config back to the accept-everything default. The config's\nprovider tag must match the integration's provider.","operationId":"revenue_update_config","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"integration_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateConfigBody"}}},"required":true},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IntegrationResponse"}}}},"400":{"description":"Validation error"},"404":{"description":"Integration not found"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/revenue/integrations/{integration_id}/import/invoices":{"post":{"tags":["Revenue"],"summary":"Import a Stripe invoices CSV export. Each paid invoice becomes an\n`invoice.paid` event so historical MRR/charge totals populate the\ntimeseries. Ingestion is idempotent: re-uploading the same file is a\nno-op.","operationId":"revenue_import_invoices_csv","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"integration_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImportOutcomeResponse"}}}},"400":{"description":"Malformed CSV or wrong provider"},"404":{"description":"Integration not found"},"413":{"description":"CSV too large"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/revenue/integrations/{integration_id}/import/subscriptions":{"post":{"tags":["Revenue"],"summary":"Import a Stripe subscriptions CSV export. Use this to backfill MRR /\nactive subscriptions when migrating from Stripe without providing\nAPI keys. Webhooks remain the source of truth for live updates —\nCSV rows never overwrite newer webhook state.","operationId":"revenue_import_subscriptions_csv","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"integration_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImportOutcomeResponse"}}}},"400":{"description":"Malformed CSV or wrong provider"},"404":{"description":"Integration not found"},"413":{"description":"CSV too large"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/revenue/integrations/{integration_id}/rotate-token":{"post":{"tags":["Revenue"],"summary":"Rotate the webhook path token. Returns the new integration state —\nthe user must paste the new URL into their provider's dashboard.","operationId":"revenue_rotate_token","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"integration_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IntegrationResponse"}}}}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/revenue/integrations/{integration_id}/update-secret":{"post":{"tags":["Revenue"],"summary":"Replace the stored signing secret without rotating the webhook URL.\nUse this after rotating the secret in the provider's dashboard.","operationId":"revenue_update_secret","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"integration_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateSecretBody"}}},"required":true},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IntegrationResponse"}}}},"400":{"description":"Validation error"},"404":{"description":"Integration not found"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/revenue/metrics/customers":{"get":{"tags":["Revenue"],"summary":"New + churned customers per bucket.","operationId":"revenue_metrics_customers","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/CustomerMovementResponse"}}}}}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/revenue/metrics/mrr":{"get":{"tags":["Revenue"],"summary":"Bucketed MRR timeseries for the revenue chart.","operationId":"revenue_metrics_mrr","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/MrrBucketResponse"}}}}}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/revenue/metrics/summary":{"get":{"tags":["Revenue"],"summary":"Current MRR / ARR / churn / ARPU for a project, in one currency.","operationId":"revenue_metrics_summary","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MetricsSummaryResponse"}}}}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/secrets":{"get":{"tags":["Secrets"],"summary":"List project secrets (metadata only — values never returned).","operationId":"listProjectSecrets","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Optional environment filter","required":false,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"List of secrets (metadata only, no values)","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ProjectSecretResponse"}}}}},"404":{"description":"Project not found"},"500":{"description":"Internal server error"}}},"post":{"tags":["Secrets"],"summary":"Create a new secret. The value is encrypted before storage and will be\nmounted as a file at `/run/secrets/` on the next deployment.\nThe plaintext value is NOT returned — the response carries only metadata.","operationId":"createProjectSecret","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateProjectSecretRequest"}}},"required":true},"responses":{"201":{"description":"Secret created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectSecretResponse"}}}},"400":{"description":"Invalid key or value too large"},"409":{"description":"Key already exists in project"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/secrets/{secret_id}":{"put":{"tags":["Secrets"],"summary":"Update a project secret. Value rotation requires a redeploy to take effect —\nrunning containers keep their currently-mounted values until the next\ndeployment.","operationId":"updateProjectSecret","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"secret_id","in":"path","description":"Secret ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateProjectSecretRequest"}}},"required":true},"responses":{"200":{"description":"Secret updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectSecretResponse"}}}},"400":{"description":"Value too large"},"404":{"description":"Secret not found"},"500":{"description":"Internal server error"}}},"delete":{"tags":["Secrets"],"summary":"Delete a project secret. Running containers keep their mounted secret files\nuntil they are redeployed.","operationId":"deleteProjectSecret","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"secret_id","in":"path","description":"Secret ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"Secret deleted"},"404":{"description":"Secret not found"},"500":{"description":"Internal server error"}}}},"/projects/{project_id}/settings":{"post":{"tags":["Projects"],"summary":"Update project settings","operationId":"update_project_settings","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateProjectSettingsRequest"}}},"required":true},"responses":{"200":{"description":"Project settings updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Project not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/skills":{"get":{"tags":["Agents"],"operationId":"list_skills","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListSkillsResponse"}}}},"401":{"description":"Unauthorized"}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Agents"],"operationId":"create_skill","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateSkillRequest"}}},"required":true},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SkillDefinitionResponse"}}}},"401":{"description":"Unauthorized"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/skills/upload":{"post":{"tags":["Agents"],"summary":"Upload a skill with an archive (tar.gz) — project-scoped.","operationId":"upload_skill","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"multipart/form-data":{"schema":{"type":"string"}}},"required":true},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SkillDefinitionResponse"}}}},"401":{"description":"Unauthorized"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/skills/{slug}":{"get":{"tags":["Agents"],"operationId":"get_skill","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"slug","in":"path","description":"Skill slug","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SkillDefinitionResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Skill not found"}},"security":[{"bearer_auth":[]}]},"put":{"tags":["Agents"],"operationId":"update_skill","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"slug","in":"path","description":"Skill slug","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateSkillRequest"}}},"required":true},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SkillDefinitionResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Skill not found"}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["Agents"],"operationId":"delete_skill","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"slug","in":"path","description":"Skill slug","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Skill deleted"},"401":{"description":"Unauthorized"},"404":{"description":"Skill not found"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/skills/{slug}/archive":{"get":{"tags":["Agents"],"summary":"Download a skill's archive (tar.gz) — project-scoped.","operationId":"download_skill_archive","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"slug","in":"path","description":"Skill slug","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Skill archive tar.gz","content":{"application/gzip":{}}},"401":{"description":"Unauthorized"},"404":{"description":"Skill not found or has no archive"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/source-map-releases":{"get":{"tags":["source-maps"],"summary":"List all releases that have source maps for a project","operationId":"list_releases","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"List of releases","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReleaseListResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/source-maps/{source_map_id}":{"delete":{"tags":["source-maps"],"summary":"Delete a specific source map by ID","operationId":"delete_source_map","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"source_map_id","in":"path","description":"Source map ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"Source map deleted"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Source map not found"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/static-bundles":{"get":{"tags":["Static Bundles"],"summary":"List static bundles for a project","operationId":"list_static_bundles","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"page","in":"query","description":"Page number (default: 1)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"page_size","in":"query","description":"Items per page (default: 20)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}}],"responses":{"200":{"description":"List of static bundles","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedStaticBundlesResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/static-bundles/{bundle_id}":{"get":{"tags":["Static Bundles"],"summary":"Get details of a specific static bundle","operationId":"get_static_bundle","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"bundle_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Bundle details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StaticBundleResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Bundle not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["Static Bundles"],"summary":"Delete a static bundle","operationId":"delete_static_bundle","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"bundle_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"Bundle deleted"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Bundle not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/status":{"get":{"tags":["Status Page"],"summary":"Get status page overview","operationId":"get_status_overview","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Filter by environment ID","required":false,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Successfully retrieved status overview","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusPageOverview"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/unique-counts":{"get":{"tags":["Events"],"summary":"Get unique counts over time frame","operationId":"get_unique_counts","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"start_date","in":"query","description":"Start date in '%Y-%m-%d %H:%M:%S' format","required":true,"schema":{"type":"string"}},{"name":"end_date","in":"query","description":"End date in '%Y-%m-%d %H:%M:%S' format","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","description":"Filter by environment ID","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"deployment_id","in":"query","description":"Filter by deployment ID","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"metric","in":"query","description":"Metric to count: 'sessions' (unique sessions), 'visitors' (unique visitors), 'returning_visitors' (visitors seen before the range), or 'page_views' (total page views) (default: 'sessions')","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successfully retrieved count","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UniqueCountsResponse"}}}},"400":{"description":"Bad request"},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/upload/static":{"post":{"tags":["Static Bundles"],"summary":"Upload a static bundle for later deployment","description":"Uploads a tar.gz or zip file containing static assets. The bundle can be\ndeployed later using the deploy/static endpoint.","operationId":"upload_static_bundle","parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"201":{"description":"Bundle uploaded successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StaticBundleResponse"}}}},"400":{"description":"Invalid request or unsupported format"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Project not found"},"413":{"description":"Bundle too large"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/vulnerability-scans":{"get":{"tags":["Vulnerability Scans"],"operationId":"list_project_scans","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"page","in":"query","description":"Page number (default: 1)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"page_size","in":"query","description":"Page size (default: 20, max: 100)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}}],"responses":{"200":{"description":"List of vulnerability scans","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ScanResponse"}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Vulnerability Scans"],"operationId":"trigger_scan","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TriggerScanRequest"}}},"required":true},"responses":{"202":{"description":"Scan triggered successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TriggerScanResponse"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/vulnerability-scans/environments":{"get":{"tags":["Vulnerability Scans"],"operationId":"get_latest_scans_per_environment","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Latest scans per environment for current deployments","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ScanResponse"}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/vulnerability-scans/latest":{"get":{"tags":["Vulnerability Scans"],"operationId":"get_latest_scan","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Filter by environment ID","required":false,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Latest scan for project","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScanResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"No scans found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/webhooks":{"get":{"tags":["Webhooks"],"summary":"List all webhooks for a project","operationId":"list_webhooks","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"page","in":"query","description":"Page number (1-indexed)","required":false,"schema":{"type":["integer","null"],"format":"int64","minimum":0},"example":1},{"name":"page_size","in":"query","description":"Number of items per page (max 100)","required":false,"schema":{"type":["integer","null"],"format":"int64","minimum":0},"example":20},{"name":"sort_by","in":"query","required":false,"schema":{"type":["string","null"]}},{"name":"sort_order","in":"query","required":false,"schema":{"type":["string","null"]}}],"responses":{"200":{"description":"List of webhooks","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/WebhookResponse"}}}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Webhooks"],"summary":"Create a new webhook","operationId":"create_webhook","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateWebhookRequestBody"}}},"required":true},"responses":{"201":{"description":"Webhook created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookResponse"}}}},"400":{"description":"Invalid request"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/webhooks/{webhook_id}":{"get":{"tags":["Webhooks"],"summary":"Get a specific webhook","operationId":"get_webhook","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"webhook_id","in":"path","description":"Webhook ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Webhook details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Webhook not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"put":{"tags":["Webhooks"],"summary":"Update a webhook","operationId":"update_webhook","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"webhook_id","in":"path","description":"Webhook ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateWebhookRequestBody"}}},"required":true},"responses":{"200":{"description":"Webhook updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookResponse"}}}},"400":{"description":"Invalid request"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Webhook not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["Webhooks"],"summary":"Delete a webhook","operationId":"delete_webhook","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"webhook_id","in":"path","description":"Webhook ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"Webhook deleted"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Webhook not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/webhooks/{webhook_id}/deliveries":{"get":{"tags":["Webhook Deliveries"],"summary":"List webhook deliveries","operationId":"list_deliveries","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"webhook_id","in":"path","description":"Webhook ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"limit","in":"query","description":"Number of deliveries to return (default: 50)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}}],"responses":{"200":{"description":"List of deliveries","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/WebhookDeliveryResponse"}}}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/webhooks/{webhook_id}/deliveries/{delivery_id}":{"get":{"tags":["Webhook Deliveries"],"summary":"Get a specific webhook delivery by ID","operationId":"get_delivery","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"webhook_id","in":"path","description":"Webhook ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"delivery_id","in":"path","description":"Delivery ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Delivery details including full payload","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookDeliveryResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Delivery not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/webhooks/{webhook_id}/deliveries/{delivery_id}/retry":{"post":{"tags":["Webhook Deliveries"],"summary":"Retry a failed delivery","operationId":"retry_delivery","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"webhook_id","in":"path","description":"Webhook ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"delivery_id","in":"path","description":"Delivery ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Delivery retried","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookDeliveryResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden"},"404":{"description":"Delivery not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/projects/{project_id}/workflows/dry-run":{"post":{"tags":["Workflows"],"operationId":"workflow_dry_run","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkflowDryRunRequest"}}},"required":true},"responses":{"202":{"description":"Ephemeral run created and queued","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentRunResponse"}}}},"400":{"description":"Validation error (bad YAML, oversized payload, capped limits exceeded)"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Project not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/proxy-logs":{"get":{"tags":["Proxy Logs"],"summary":"Get proxy logs with optional filters and pagination","operationId":"get_proxy_logs","parameters":[{"name":"project_id","in":"query","description":"Filter by project ID","required":false,"schema":{"type":["integer","null"],"format":"int32"}},{"name":"environment_id","in":"query","description":"Filter by environment ID","required":false,"schema":{"type":["integer","null"],"format":"int32"}},{"name":"deployment_id","in":"query","description":"Filter by deployment ID","required":false,"schema":{"type":["integer","null"],"format":"int32"}},{"name":"session_id","in":"query","description":"Filter by session ID","required":false,"schema":{"type":["integer","null"],"format":"int32"}},{"name":"visitor_id","in":"query","description":"Filter by visitor ID","required":false,"schema":{"type":["integer","null"],"format":"int32"}},{"name":"start_date","in":"query","description":"Start date for filtering (ISO 8601 format).\n\n**Defaults to 1 hour before `end_date` (or before now) when omitted.**\nThe listing is always time-bounded: an unbounded query would have to\nconsider the entire retention window — 100M+ rows on a busy deployment —\nto return a single page. Pass an explicit `start_date` to widen the\nwindow, up to the configured retention horizon.\n\nThe maximum span between `start_date` and `end_date` is 7 days when\n`project_id` is omitted, or 30 days when a single `project_id` is set —\na project-scoped query is bounded by that project's own row count\nrather than the whole deployment's. A wider request is rejected with a\n400 naming the applicable cap.","required":false,"schema":{"type":["string","null"],"format":"date-time"}},{"name":"end_date","in":"query","description":"End date for filtering (ISO 8601 format). Defaults to now.","required":false,"schema":{"type":["string","null"],"format":"date-time"}},{"name":"method","in":"query","description":"Filter by HTTP method (GET, POST, etc.)","required":false,"schema":{"type":["string","null"]}},{"name":"host","in":"query","description":"Filter by host header","required":false,"schema":{"type":["string","null"]}},{"name":"path","in":"query","description":"Filter by path (supports partial match)","required":false,"schema":{"type":["string","null"]}},{"name":"client_ip","in":"query","description":"Filter by client IP address","required":false,"schema":{"type":["string","null"]}},{"name":"status_code","in":"query","description":"Filter by HTTP status code","required":false,"schema":{"type":["integer","null"],"format":"int32"}},{"name":"response_time_min","in":"query","description":"Filter by minimum response time in ms","required":false,"schema":{"type":["integer","null"],"format":"int32"}},{"name":"response_time_max","in":"query","description":"Filter by maximum response time in ms","required":false,"schema":{"type":["integer","null"],"format":"int32"}},{"name":"routing_status","in":"query","description":"Filter by routing status (routed, no_project, error, pending)","required":false,"schema":{"type":["string","null"]}},{"name":"request_source","in":"query","description":"Filter by request source (proxy, api, console, cli)","required":false,"schema":{"type":["string","null"]}},{"name":"is_system_request","in":"query","description":"Filter by system request flag","required":false,"schema":{"type":["boolean","null"]}},{"name":"user_agent","in":"query","description":"Filter by user agent string (partial match)","required":false,"schema":{"type":["string","null"]}},{"name":"browser","in":"query","description":"Filter by browser name","required":false,"schema":{"type":["string","null"]}},{"name":"operating_system","in":"query","description":"Filter by operating system","required":false,"schema":{"type":["string","null"]}},{"name":"device_type","in":"query","description":"Filter by device type (mobile, desktop, tablet)","required":false,"schema":{"type":["string","null"]}},{"name":"is_bot","in":"query","description":"Filter by bot detection","required":false,"schema":{"type":["boolean","null"]}},{"name":"exclude_bots","in":"query","description":"When `true`, exclude rows flagged as bots while KEEPING rows whose\n`is_bot` is NULL (older rows without detection metadata). This is the\ntri-state complement of `is_bot=false`, which matches only rows\nexplicitly detected as non-bots. `false`/omitted is a no-op.","required":false,"schema":{"type":["boolean","null"]}},{"name":"bot_name","in":"query","description":"Filter by bot name","required":false,"schema":{"type":["string","null"]}},{"name":"ai_provider","in":"query","description":"Filter by AI provider (e.g. `OpenAI`, `Anthropic`, `Perplexity`). Matches\nthe canonical provider returned by the AI agent detector.","required":false,"schema":{"type":["string","null"]}},{"name":"ai_agent","in":"query","description":"Filter by AI agent name (e.g. `GPTBot`, `ChatGPT-User`). Equivalent to\nfiltering `bot_name` against a known AI taxonomy.","required":false,"schema":{"type":["string","null"]}},{"name":"is_ai_agent","in":"query","description":"When `true`, only return requests classified as known AI agents\n(regardless of provider/agent). Mutually compatible with the above.","required":false,"schema":{"type":["boolean","null"]}},{"name":"request_size_min","in":"query","description":"Filter by minimum request size in bytes","required":false,"schema":{"type":["integer","null"],"format":"int64"}},{"name":"request_size_max","in":"query","description":"Filter by maximum request size in bytes","required":false,"schema":{"type":["integer","null"],"format":"int64"}},{"name":"response_size_min","in":"query","description":"Filter by minimum response size in bytes","required":false,"schema":{"type":["integer","null"],"format":"int64"}},{"name":"response_size_max","in":"query","description":"Filter by maximum response size in bytes","required":false,"schema":{"type":["integer","null"],"format":"int64"}},{"name":"cache_status","in":"query","description":"Filter by cache status","required":false,"schema":{"type":["string","null"]}},{"name":"container_id","in":"query","description":"Filter by container ID","required":false,"schema":{"type":["string","null"]}},{"name":"upstream_host","in":"query","description":"Filter by upstream host","required":false,"schema":{"type":["string","null"]}},{"name":"has_error","in":"query","description":"Filter by presence of error message","required":false,"schema":{"type":["boolean","null"]}},{"name":"page","in":"query","description":"Page number (default: 1)","required":false,"schema":{"type":["integer","null"],"format":"int64","minimum":0}},{"name":"page_size","in":"query","description":"Page size (default: 20, max: 100)","required":false,"schema":{"type":["integer","null"],"format":"int64","minimum":0}},{"name":"sort_by","in":"query","description":"Sort by field (default: timestamp)","required":false,"schema":{"type":["string","null"]}},{"name":"sort_order","in":"query","description":"Sort order (asc or desc, default: desc)","required":false,"schema":{"type":["string","null"]}}],"responses":{"200":{"description":"List of proxy logs","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProxyLogsPaginatedResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/proxy-logs/ai-agents/known":{"get":{"tags":["Proxy Logs"],"summary":"List every AI agent the detector knows how to classify.","description":"Returned in the same order as the internal taxonomy so the UI can use it as\na stable dropdown.","operationId":"list_known_ai_agents","responses":{"200":{"description":"Known AI agents","content":{"application/json":{"schema":{"$ref":"#/components/schemas/KnownAiAgentsResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/proxy-logs/request/{request_id}":{"get":{"tags":["Proxy Logs"],"summary":"Get a proxy log by request ID (for tracing)","operationId":"get_proxy_log_by_request_id","parameters":[{"name":"request_id","in":"path","description":"Request ID from pingora","required":true,"schema":{"type":"string"}},{"name":"timestamp","in":"query","description":"Event time of the log row (ISO 8601). When provided, the lookup is\nbounded to the hypertable chunks around this instant instead of\nscanning (and decompressing) the whole retention window. The list\nendpoint already returns this value per row — always pass it when\nnavigating from a list.","required":false,"schema":{"type":["string","null"],"format":"date-time"}}],"responses":{"200":{"description":"Proxy log found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProxyLogResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Proxy log not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/proxy-logs/stats/ai-agent-pages":{"get":{"tags":["Proxy Logs"],"summary":"Get the top pages accessed by a specific AI agent over a time window.","description":"Returns page paths ranked by request count, scoped to a single canonical\nagent name (e.g. `ChatGPT-User`). Use `GET /proxy-logs/ai-agents/known` to\nlist all valid agent names. Unknown agent names return an empty items array.","operationId":"get_ai_agent_pages","parameters":[{"name":"agent","in":"query","description":"Canonical agent name to filter by (e.g. `ChatGPT-User`, `ClaudeBot`).\nMust be a name returned by `GET /proxy-logs/ai-agents/known`.","required":true,"schema":{"type":"string"}},{"name":"project_id","in":"query","description":"Filter by project ID.","required":false,"schema":{"type":["integer","null"],"format":"int32"}},{"name":"environment_id","in":"query","description":"Filter by environment ID.","required":false,"schema":{"type":["integer","null"],"format":"int32"}},{"name":"start_time","in":"query","description":"Start time (ISO 8601). Defaults to `end_time - 7d`.","required":false,"schema":{"type":["string","null"]},"example":"2026-05-22T00:00:00Z"},{"name":"end_time","in":"query","description":"End time (ISO 8601). Defaults to now.","required":false,"schema":{"type":["string","null"]},"example":"2026-05-29T00:00:00Z"},{"name":"limit","in":"query","description":"Maximum rows to return. Capped at 100 server-side.","required":false,"schema":{"type":["integer","null"],"format":"int64","minimum":0}}],"responses":{"200":{"description":"Pages breakdown for the requested agent","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AiAgentPagesResponse"}}}},"400":{"description":"Invalid parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/proxy-logs/stats/ai-agents":{"get":{"tags":["Proxy Logs"],"summary":"Get the per-AI-agent breakdown for a project over a time window.","operationId":"get_ai_agent_breakdown","parameters":[{"name":"project_id","in":"query","description":"Filter by project ID (recommended for per-project analytics).","required":false,"schema":{"type":["integer","null"],"format":"int32"}},{"name":"environment_id","in":"query","description":"Filter by environment ID.","required":false,"schema":{"type":["integer","null"],"format":"int32"}},{"name":"start_time","in":"query","description":"Start time (ISO 8601). Defaults to `end_time - 7d`.","required":false,"schema":{"type":["string","null"]},"example":"2026-05-22T00:00:00Z"},{"name":"end_time","in":"query","description":"End time (ISO 8601). Defaults to now.","required":false,"schema":{"type":["string","null"]},"example":"2026-05-29T00:00:00Z"},{"name":"limit","in":"query","description":"Maximum rows to return. Capped at 100 server-side.","required":false,"schema":{"type":["integer","null"],"format":"int64","minimum":0}},{"name":"path","in":"query","description":"Optional exact path filter. Only used by the AI pages breakdown — when\nset, returns the single matching page so callers can ask \"how many AI\nagents hit this page?\".","required":false,"schema":{"type":["string","null"]}}],"responses":{"200":{"description":"AI agent breakdown","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AiAgentBreakdownResponse"}}}},"400":{"description":"Invalid parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/proxy-logs/stats/ai-agents/timeline":{"get":{"tags":["Proxy Logs"],"summary":"Time-bucketed AI-agent request volume, split by provider or agent.","description":"Powers the \"AI agents over time\" stacked chart. Same data source as the AI\nagent breakdown (request logs), just bucketed.","operationId":"get_ai_agent_timeline","parameters":[{"name":"project_id","in":"query","description":"Filter by project ID.","required":false,"schema":{"type":["integer","null"],"format":"int32"}},{"name":"environment_id","in":"query","description":"Filter by environment ID.","required":false,"schema":{"type":["integer","null"],"format":"int32"}},{"name":"start_time","in":"query","description":"Start time (ISO 8601). Defaults to `end_time - 7d`.","required":false,"schema":{"type":["string","null"]},"example":"2026-05-22T00:00:00Z"},{"name":"end_time","in":"query","description":"End time (ISO 8601). Defaults to now.","required":false,"schema":{"type":["string","null"]},"example":"2026-05-29T00:00:00Z"},{"name":"group_by","in":"query","description":"Grouping dimension: `provider` (default) or `agent`.","required":false,"schema":{"type":["string","null"]},"example":"provider"},{"name":"bucket","in":"query","description":"Bucket interval override (e.g. `1 hour`, `1 day`). Auto-selected from the\nwindow width when omitted.","required":false,"schema":{"type":["string","null"]},"example":"1 hour"}],"responses":{"200":{"description":"AI agent timeline","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AiAgentTimelineResponse"}}}},"400":{"description":"Invalid parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/proxy-logs/stats/ai-pages":{"get":{"tags":["Proxy Logs"],"summary":"Get the top pages crawled by AI agents over a time window.","operationId":"get_ai_page_breakdown","parameters":[{"name":"project_id","in":"query","description":"Filter by project ID (recommended for per-project analytics).","required":false,"schema":{"type":["integer","null"],"format":"int32"}},{"name":"environment_id","in":"query","description":"Filter by environment ID.","required":false,"schema":{"type":["integer","null"],"format":"int32"}},{"name":"start_time","in":"query","description":"Start time (ISO 8601). Defaults to `end_time - 7d`.","required":false,"schema":{"type":["string","null"]},"example":"2026-05-22T00:00:00Z"},{"name":"end_time","in":"query","description":"End time (ISO 8601). Defaults to now.","required":false,"schema":{"type":["string","null"]},"example":"2026-05-29T00:00:00Z"},{"name":"limit","in":"query","description":"Maximum rows to return. Capped at 100 server-side.","required":false,"schema":{"type":["integer","null"],"format":"int64","minimum":0}},{"name":"path","in":"query","description":"Optional exact path filter. Only used by the AI pages breakdown — when\nset, returns the single matching page so callers can ask \"how many AI\nagents hit this page?\".","required":false,"schema":{"type":["string","null"]}}],"responses":{"200":{"description":"AI page breakdown","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AiPageBreakdownResponse"}}}},"400":{"description":"Invalid parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/proxy-logs/stats/ai-status":{"get":{"tags":["Proxy Logs"],"summary":"HTTP status-class breakdown for AI-agent traffic — are bots being served\n(2xx) or hitting broken/blocked pages (4xx/5xx)?","operationId":"get_ai_status_breakdown","parameters":[{"name":"project_id","in":"query","description":"Filter by project ID (recommended for per-project analytics).","required":false,"schema":{"type":["integer","null"],"format":"int32"}},{"name":"environment_id","in":"query","description":"Filter by environment ID.","required":false,"schema":{"type":["integer","null"],"format":"int32"}},{"name":"start_time","in":"query","description":"Start time (ISO 8601). Defaults to `end_time - 7d`.","required":false,"schema":{"type":["string","null"]},"example":"2026-05-22T00:00:00Z"},{"name":"end_time","in":"query","description":"End time (ISO 8601). Defaults to now.","required":false,"schema":{"type":["string","null"]},"example":"2026-05-29T00:00:00Z"},{"name":"limit","in":"query","description":"Maximum rows to return. Capped at 100 server-side.","required":false,"schema":{"type":["integer","null"],"format":"int64","minimum":0}},{"name":"path","in":"query","description":"Optional exact path filter. Only used by the AI pages breakdown — when\nset, returns the single matching page so callers can ask \"how many AI\nagents hit this page?\".","required":false,"schema":{"type":["string","null"]}}],"responses":{"200":{"description":"AI status breakdown","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AiStatusBreakdownResponse"}}}},"400":{"description":"Invalid parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/proxy-logs/stats/projects-health":{"get":{"tags":["Proxy Logs"],"summary":"Get health summaries for multiple projects (last 1 hour)","operationId":"get_projects_health","parameters":[{"name":"project_ids","in":"query","description":"Comma-separated list of project IDs","required":true,"schema":{"type":"string"}},{"name":"start_time","in":"query","description":"Optional start time (ISO 8601). Defaults to `end_time - 1h`.","required":false,"schema":{"type":["string","null"]},"example":"2025-10-23T00:00:00Z"},{"name":"end_time","in":"query","description":"Optional end time (ISO 8601). Defaults to now.","required":false,"schema":{"type":["string","null"]},"example":"2025-10-23T23:59:59Z"},{"name":"is_bot","in":"query","description":"Filter by bot detection. Pass `false` to exclude bots, `true` for bots only.","required":false,"schema":{"type":["boolean","null"]}}],"responses":{"200":{"description":"Health summaries per project","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectsHealthResponse"}}}},"400":{"description":"Invalid parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/proxy-logs/stats/time-buckets":{"get":{"tags":["Proxy Logs"],"summary":"Get time-bucketed statistics with optional filters","operationId":"get_time_bucket_stats","parameters":[{"name":"start_time","in":"query","description":"Start time (ISO 8601 format)","required":true,"schema":{"type":"string"},"example":"2025-10-23T00:00:00Z"},{"name":"end_time","in":"query","description":"End time (ISO 8601 format)","required":true,"schema":{"type":"string"},"example":"2025-10-23T23:59:59Z"},{"name":"bucket_interval","in":"query","description":"Bucket interval (e.g., \"1 hour\", \"1 day\", \"5 minutes\")","required":false,"schema":{"type":"string"}},{"name":"method","in":"query","description":"Filter by HTTP method","required":false,"schema":{"type":"string"}},{"name":"client_ip","in":"query","description":"Filter by client IP","required":false,"schema":{"type":"string"}},{"name":"project_id","in":"query","description":"Filter by project ID","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Filter by environment ID","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"deployment_id","in":"query","description":"Filter by deployment ID","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"host","in":"query","description":"Filter by host","required":false,"schema":{"type":"string"}},{"name":"status_code","in":"query","description":"Filter by status code","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"status_code_class","in":"query","description":"Filter by status code class (e.g. \"2xx\", \"3xx\", \"4xx\", \"5xx\")","required":false,"schema":{"type":"string"}},{"name":"routing_status","in":"query","description":"Filter by routing status","required":false,"schema":{"type":"string"}},{"name":"request_source","in":"query","description":"Filter by request source","required":false,"schema":{"type":"string"}},{"name":"is_bot","in":"query","description":"Filter by bot detection","required":false,"schema":{"type":"boolean"}},{"name":"device_type","in":"query","description":"Filter by device type","required":false,"schema":{"type":"string"}},{"name":"has_project","in":"query","description":"When true, only count requests that matched a project\n(project_id IS NOT NULL). Makes chart totals line up with the\nper-project health cards.","required":false,"schema":{"type":"boolean"}}],"responses":{"200":{"description":"Time-bucketed statistics","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TimeBucketStatsResponse"}}}},"400":{"description":"Invalid parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/proxy-logs/stats/today":{"get":{"tags":["Proxy Logs"],"summary":"Get today's request count with optional filters","operationId":"get_today_stats","parameters":[{"name":"method","in":"query","description":"Filter by HTTP method","required":false,"schema":{"type":["string","null"]}},{"name":"client_ip","in":"query","description":"Filter by client IP","required":false,"schema":{"type":["string","null"]}},{"name":"project_id","in":"query","description":"Filter by project ID","required":false,"schema":{"type":["integer","null"],"format":"int32"}},{"name":"environment_id","in":"query","description":"Filter by environment ID","required":false,"schema":{"type":["integer","null"],"format":"int32"}},{"name":"deployment_id","in":"query","description":"Filter by deployment ID","required":false,"schema":{"type":["integer","null"],"format":"int32"}},{"name":"host","in":"query","description":"Filter by host","required":false,"schema":{"type":["string","null"]}},{"name":"status_code","in":"query","description":"Filter by status code","required":false,"schema":{"type":["integer","null"],"format":"int32"}},{"name":"status_code_class","in":"query","description":"Filter by status code class (e.g. \"2xx\", \"3xx\", \"4xx\", \"5xx\")","required":false,"schema":{"type":["string","null"]}},{"name":"routing_status","in":"query","description":"Filter by routing status","required":false,"schema":{"type":["string","null"]}},{"name":"request_source","in":"query","description":"Filter by request source","required":false,"schema":{"type":["string","null"]}},{"name":"is_bot","in":"query","description":"Filter by bot detection","required":false,"schema":{"type":["boolean","null"]}},{"name":"device_type","in":"query","description":"Filter by device type","required":false,"schema":{"type":["string","null"]}}],"responses":{"200":{"description":"Today's request count","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TodayStatsResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/proxy-logs/{id}":{"get":{"tags":["Proxy Logs"],"summary":"Get a single proxy log by ID","operationId":"get_proxy_log_by_id","parameters":[{"name":"id","in":"path","description":"Proxy log ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"timestamp","in":"query","description":"Event time of the log row (ISO 8601). When provided, the lookup is\nbounded to the hypertable chunks around this instant instead of\nscanning (and decompressing) the whole retention window. The list\nendpoint already returns this value per row — always pass it when\nnavigating from a list.","required":false,"schema":{"type":["string","null"],"format":"date-time"}}],"responses":{"200":{"description":"Proxy log found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProxyLogResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Proxy log not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/repositories":{"get":{"tags":["Git Providers"],"summary":"List synced repositories with advanced filtering","description":"Lists repositories that have been synced to the database with filtering options.\nThis provides fast access to repository metadata with filtering by connection, search, and other criteria.","operationId":"list_synced_repositories","parameters":[{"name":"page","in":"query","description":"Page number for pagination","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"per_page","in":"query","description":"Number of items per page (max 100)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"sort","in":"query","description":"Sort field (name, created_at, updated_at, stars, watchers, size, issues)","required":false,"schema":{"type":"string"}},{"name":"direction","in":"query","description":"Sort direction (asc, desc)","required":false,"schema":{"type":"string"}},{"name":"search","in":"query","description":"Search term to filter repositories","required":false,"schema":{"type":"string"}},{"name":"owner","in":"query","description":"Filter by repository owner","required":false,"schema":{"type":"string"}},{"name":"language","in":"query","description":"Filter by programming language","required":false,"schema":{"type":"string"}},{"name":"private","in":"query","description":"Filter by private status (true/false)","required":false,"schema":{"type":"boolean"}},{"name":"git_provider_connection_id","in":"query","description":"Filter by git provider connection ID","required":false,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"List of synced repositories","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RepositoryListResponse"}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/repositories/{owner}/{name}":{"get":{"tags":["Git Providers"],"summary":"Get repository by owner and name from any connection","operationId":"get_repository_by_name","parameters":[{"name":"owner","in":"path","description":"Repository owner","required":true,"schema":{"type":"string"}},{"name":"name","in":"path","description":"Repository name","required":true,"schema":{"type":"string"}},{"name":"connection_id","in":"query","description":"Optional specific connection ID to search","required":false,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Repository found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RepositoryResponse"}}}},"404":{"description":"Repository not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/repositories/{owner}/{name}/all":{"get":{"tags":["Git Providers"],"summary":"Get all repositories with same owner/name from all git providers","operationId":"get_all_repositories_by_name","parameters":[{"name":"owner","in":"path","description":"Repository owner","required":true,"schema":{"type":"string"}},{"name":"name","in":"path","description":"Repository name","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Repositories found from all providers","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/RepositoryResponse"}}}}},"404":{"description":"No repositories found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/repositories/{owner}/{name}/preset":{"get":{"tags":["Git Providers"],"summary":"Get repository preset by owner and name","operationId":"get_repository_preset_by_name","parameters":[{"name":"owner","in":"path","description":"Repository owner","required":true,"schema":{"type":"string"}},{"name":"name","in":"path","description":"Repository name","required":true,"schema":{"type":"string"}},{"name":"branch","in":"query","description":"Git branch to check (defaults to repository's default branch)","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Repository preset calculated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RepositoryPresetResponse"}}}},"404":{"description":"Repository not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/repositories/{owner}/{repo}/branches":{"get":{"tags":["Repositories"],"summary":"Get repository branches","operationId":"get_repository_branches","parameters":[{"name":"owner","in":"path","description":"Repository owner","required":true,"schema":{"type":"string"}},{"name":"repo","in":"path","description":"Repository name","required":true,"schema":{"type":"string"}},{"name":"connection_id","in":"query","description":"Git provider connection ID (required when multiple connections have the same repo)","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"fresh","in":"query","description":"Force fetch fresh data, bypassing cache (default: false)","required":false,"schema":{"type":"boolean"}}],"responses":{"200":{"description":"List of branches","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BranchListResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Repository not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/repositories/{owner}/{repo}/tags":{"get":{"tags":["Repositories"],"summary":"Get repository tags","operationId":"get_repository_tags","parameters":[{"name":"owner","in":"path","description":"Repository owner","required":true,"schema":{"type":"string"}},{"name":"repo","in":"path","description":"Repository name","required":true,"schema":{"type":"string"}},{"name":"connection_id","in":"query","description":"Git provider connection ID (required when multiple connections have the same repo)","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"fresh","in":"query","description":"Force fetch fresh data, bypassing cache (default: false)","required":false,"schema":{"type":"boolean"}}],"responses":{"200":{"description":"List of tags","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TagListResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Repository not found"},"429":{"description":"Fresh tag lookup rate limit exceeded"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/repositories/{repository_id}/preset/live":{"get":{"tags":["Git Providers"],"operationId":"get_repository_preset_live","parameters":[{"name":"repository_id","in":"path","description":"Repository ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"branch","in":"query","description":"Git branch to check (defaults to repository's default branch)","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Repository presets calculated successfully - includes root preset and projects in subdirectories","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RepositoryPresetResponse"}}}},"400":{"description":"Bad request"},"401":{"description":"The git provider rejected the stored credential - the connection must be re-authorized"},"404":{"description":"Repository not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/repository/{repository_id}":{"get":{"tags":["Git Providers"],"summary":"Get repository by ID","operationId":"get_repository_by_id","parameters":[{"name":"repository_id","in":"path","description":"Repository ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Repository found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RepositoryResponse"}}}},"404":{"description":"Repository not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/repository/{repository_id}/branches":{"get":{"tags":["Repositories"],"summary":"Get repository branches by repository ID","operationId":"get_branches_by_repository_id","parameters":[{"name":"repository_id","in":"path","description":"Repository ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"fresh","in":"query","description":"Force fetch fresh data, bypassing cache (default: false)","required":false,"schema":{"type":"boolean"}}],"responses":{"200":{"description":"List of branches","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BranchListResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Repository not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/repository/{repository_id}/commits":{"get":{"tags":["Repositories"],"summary":"List recent commits for a repository branch","operationId":"list_commits_by_repository_id","parameters":[{"name":"repository_id","in":"path","description":"Repository ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"branch","in":"query","description":"Branch name to list commits for","required":true,"schema":{"type":"string"}},{"name":"per_page","in":"query","description":"Number of commits to return (default: 20, max: 100)","required":false,"schema":{"type":["integer","null"],"format":"int32","minimum":0}}],"responses":{"200":{"description":"List of commits","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CommitListResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Repository not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/repository/{repository_id}/commits/{commit_sha}":{"get":{"tags":["Repositories"],"summary":"Check if a commit exists in a repository","operationId":"check_commit_exists","parameters":[{"name":"repository_id","in":"path","description":"Repository ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"commit_sha","in":"path","description":"Commit SHA to check","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Commit existence check result","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CommitExistsResponse"}}}},"400":{"description":"Invalid commit SHA"},"401":{"description":"Unauthorized"},"404":{"description":"Repository not found"},"429":{"description":"Commit lookup rate limit exceeded"},"500":{"description":"Internal server error"},"502":{"description":"Git provider request failed"}},"security":[{"bearer_auth":[]}]}},"/repository/{repository_id}/tags":{"get":{"tags":["Repositories"],"summary":"Get repository tags by repository ID","operationId":"get_tags_by_repository_id","parameters":[{"name":"repository_id","in":"path","description":"Repository ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"fresh","in":"query","description":"Force fetch fresh data, bypassing cache (default: false)","required":false,"schema":{"type":"boolean"}}],"responses":{"200":{"description":"List of tags","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TagListResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Repository not found"},"429":{"description":"Fresh tag lookup rate limit exceeded"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/restore-runs/{id}":{"get":{"tags":["Restore"],"operationId":"get_restore_run","parameters":[{"name":"id","in":"path","description":"Restore run id","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Restore run progress","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RestoreRunView"}}}},"404":{"description":"Restore run not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/revenue/events":{"get":{"tags":["Revenue"],"summary":"Org-wide revenue events across every project. Powers the revenue\ntransactions page. Supports filtering by project, date range, and\nevent type.","operationId":"revenue_global_events","parameters":[{"name":"project_id","in":"query","description":"Filter to a single project","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"from","in":"query","description":"Lower bound (inclusive), ISO-8601","required":false,"schema":{"type":"string"}},{"name":"to","in":"query","description":"Upper bound (inclusive), ISO-8601","required":false,"schema":{"type":"string"}},{"name":"event_types","in":"query","description":"Comma-separated event types (e.g. `invoice.paid,charge.succeeded`)","required":false,"schema":{"type":"string"}},{"name":"limit","in":"query","description":"Max rows, default 100, max 500","required":false,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/GlobalRecentEventResponse"}}}}}},"security":[{"bearer_auth":[]}]}},"/revenue/metrics/global-mrr":{"get":{"tags":["Revenue"],"summary":"Org-wide MRR total, summed across every project in the install.\nPowers the single-number MRR card on the main dashboard.","operationId":"revenue_metrics_global_mrr","responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GlobalMrrResponse"}}}}},"security":[{"bearer_auth":[]}]}},"/revenue/metrics/global-summary":{"get":{"tags":["Revenue"],"summary":"Org-wide revenue summary: MRR, paid cash (30d + all-time), refunds,\nactive subscriptions/customers, and transaction count. Powers the\nheader on the Revenue transactions page.","operationId":"revenue_metrics_global_summary","parameters":[{"name":"currency","in":"query","description":"ISO-4217 currency code, default USD","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GlobalRevenueSummaryResponse"}}}}},"security":[{"bearer_auth":[]}]}},"/revenue/providers":{"get":{"tags":["Revenue"],"summary":"List registered providers (what the UI needs to render the \"Connect\"\ndropdown + its wizard instructions).","operationId":"revenue_list_providers","responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ProviderDescriptor"}}}}}},"security":[{"bearer_auth":[]}]}},"/session-replays":{"get":{"tags":["Analytics"],"summary":"Get session replays for a project","operationId":"get_project_session_replays","parameters":[{"name":"project_id","in":"query","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"environment_id","in":"query","description":"Environment ID (optional)","required":false,"schema":{"type":"integer","format":"int32"}},{"name":"page","in":"query","description":"Page number (1-based)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"per_page","in":"query","description":"Items per page","required":false,"schema":{"type":"integer","format":"int64","minimum":0}}],"responses":{"200":{"description":"Session replays retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetProjectSessionReplaysResponse"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Authentication required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearer_auth":[]}]}},"/sessions/{session_id}/events":{"get":{"tags":["Events"],"summary":"Get events for a specific session","operationId":"get_session_events","parameters":[{"name":"session_id","in":"path","description":"Session ID","required":true,"schema":{"type":"string"}},{"name":"environment_id","in":"query","description":"Filter by environment ID","required":false,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Successfully retrieved session events","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AnalyticsSessionEventsResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Session not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/settings":{"get":{"tags":["Settings"],"summary":"Get application settings","operationId":"get_settings","responses":{"200":{"description":"Application settings with masked sensitive fields","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppSettingsResponse"}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"put":{"tags":["Settings"],"summary":"Update application settings","operationId":"update_settings","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppSettings"}}},"required":true},"responses":{"200":{"description":"Settings updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SettingsUpdateResponse"}}}},"400":{"description":"Bad request - invalid settings"},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/settings/agent-token":{"post":{"tags":["Agents"],"summary":"Save an encrypted AI provider token for use in sandbox containers.","operationId":"save_agent_token","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SaveAgentTokenRequest"}}},"required":true},"responses":{"200":{"description":"Token encrypted and persisted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SaveAgentTokenResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Encryption or database error"}},"security":[{"bearer_auth":[]}]}},"/settings/ai-providers":{"get":{"tags":["Agents"],"summary":"List the AI provider catalog. Includes per-provider \"is a credential\nconfigured?\" so the settings UI can render configured/not-configured\nbadges without leaking the encrypted credential.","operationId":"list_ai_providers","responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProviderCatalogResponse"}}}},"401":{"description":"Unauthorized"}},"security":[{"bearer_auth":[]}]}},"/settings/ai-providers/{provider_id}":{"patch":{"tags":["Agents"],"summary":"Update provider-scoped settings without touching the saved credential.\nToday that means just `default_model`; future per-provider settings\n(base URL overrides, request headers, etc.) can land here too without\nchanging the shape of `save_credential`.","operationId":"update_ai_provider","parameters":[{"name":"provider_id","in":"path","description":"AI provider ID","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateAiProviderRequest"}}},"required":true},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateAiProviderResponse"}}}},"400":{"description":"Unknown provider"},"401":{"description":"Unauthorized"}},"security":[{"bearer_auth":[]}]}},"/settings/ai-providers/{provider_id}/activate":{"post":{"tags":["Agents"],"summary":"Activate a provider as the platform-wide default. Refuses to activate a\nprovider that doesn't have a credential saved yet — the UI enforces the\nsame rule on the button, but we re-check server-side so a stale tab\ncan't bypass it.","operationId":"activate_ai_provider","parameters":[{"name":"provider_id","in":"path","description":"AI provider ID","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActivateProviderResponse"}}}},"400":{"description":"Provider not configured"},"401":{"description":"Unauthorized"}},"security":[{"bearer_auth":[]}]}},"/settings/ai-providers/{provider_id}/credential":{"post":{"tags":["Agents"],"summary":"Save (or replace) a provider's credential. The credential is encrypted\nwith `EncryptionService` and stored inside\n`agent_sandbox.providers[provider_id].credentials_encrypted`.","description":"The plaintext shape depends on the flavor's `credential_format`:\n - `ApiKey` / `OauthToken`: the key/token string.\n - `ConfigFile`: the full file body (e.g. OpenCode's `auth.json`).","operationId":"save_ai_provider_credential","parameters":[{"name":"provider_id","in":"path","description":"AI provider ID","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SaveCredentialRequest"}}},"required":true},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SaveCredentialResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Unauthorized"}},"security":[{"bearer_auth":[]}]}},"/settings/disk-status":{"get":{"tags":["Settings"],"summary":"Get current disk usage for the control-plane server","description":"Returns live disk usage for the monitored path along with any disks that\nmeet or exceed the configured alert threshold. Read-only — does not send\nnotifications. Used by the dashboard to surface a low-disk-space warning.","operationId":"get_disk_status","responses":{"200":{"description":"Current disk usage and threshold alerts","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DiskSpaceCheckResult"}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/settings/enrollment-tokens":{"get":{"tags":["Settings"],"summary":"List currently-valid node enrollment tokens (hashes elided).","operationId":"list_enrollment_tokens","responses":{"200":{"description":"Active enrollment tokens","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnrollmentTokenListResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Settings"],"summary":"Mint a short-lived, single-use node enrollment token.","operationId":"mint_enrollment_token","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MintEnrollmentTokenRequest"}}},"required":true},"responses":{"200":{"description":"Enrollment token minted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MintEnrollmentTokenResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/settings/enrollment-tokens/{id}":{"delete":{"tags":["Settings"],"summary":"Revoke a node enrollment token by id.","operationId":"revoke_enrollment_token","parameters":[{"name":"id","in":"path","description":"Enrollment token id","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Enrollment token revoked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SettingsUpdateResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Enrollment token not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/settings/join-token":{"delete":{"tags":["Settings"],"summary":"Revoke the current join token","description":"Removes the stored join token hash, allowing any node to register\n(if no other authentication is in place).","operationId":"revoke_join_token","responses":{"200":{"description":"Join token revoked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SettingsUpdateResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/settings/join-token/generate":{"post":{"tags":["Settings"],"summary":"Generate a new join token for multi-node cluster registration","description":"Creates a random 32-byte hex token, stores the SHA-256 hash in settings,\nand returns the plaintext exactly once. If a token already exists, it is replaced.","operationId":"generate_join_token","responses":{"200":{"description":"Join token generated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenerateJoinTokenResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/settings/join-token/status":{"get":{"tags":["Settings"],"summary":"Check whether a join token is currently configured","operationId":"get_join_token_status","responses":{"200":{"description":"Join token status","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JoinTokenStatusResponse"}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/settings/mcp-servers":{"get":{"tags":["Agents"],"operationId":"list_global_mcps","responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListMcpsResponse"}}}},"401":{"description":"Unauthorized"}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Agents"],"operationId":"create_global_mcp","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateMcpRequest"}}},"required":true},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/McpDefinitionResponse"}}}},"401":{"description":"Unauthorized"}},"security":[{"bearer_auth":[]}]}},"/settings/mcp-servers/{slug}":{"get":{"tags":["Agents"],"operationId":"get_global_mcp","parameters":[{"name":"slug","in":"path","description":"MCP server slug","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/McpDefinitionResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"MCP server not found"}},"security":[{"bearer_auth":[]}]},"put":{"tags":["Agents"],"operationId":"update_global_mcp","parameters":[{"name":"slug","in":"path","description":"MCP server slug","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateMcpRequest"}}},"required":true},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/McpDefinitionResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"MCP server not found"}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["Agents"],"operationId":"delete_global_mcp","parameters":[{"name":"slug","in":"path","description":"MCP server slug","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"MCP server deleted"},"401":{"description":"Unauthorized"},"404":{"description":"MCP server not found"}},"security":[{"bearer_auth":[]}]}},"/settings/mcp-servers/{slug}/config/{field}":{"get":{"tags":["Agents"],"operationId":"reveal_global_mcp_config","parameters":[{"name":"slug","in":"path","description":"MCP server slug","required":true,"schema":{"type":"string"}},{"name":"field","in":"path","description":"Sensitive field path, such as url or env.API_TOKEN","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SensitiveMcpConfigValueResponse"}}}},"400":{"description":"Field is not revealable"},"401":{"description":"Unauthorized"},"403":{"description":"Missing secrets:read permission"},"404":{"description":"MCP server or field not found"},"500":{"description":"Configuration read or audit failed"}},"security":[{"bearer_auth":[]}]}},"/settings/routes/refresh":{"post":{"tags":["Settings"],"summary":"Manually refresh the proxy route table","description":"Reloads all routes from the database into the in-memory proxy cache.\nUseful as a workaround when routes are out of sync.","operationId":"refresh_route_table","responses":{"200":{"description":"Route table refreshed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RouteRefreshResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/settings/sandbox-rebuild":{"post":{"tags":["Agents"],"operationId":"rebuild_sandbox_image","responses":{"200":{"description":"Server-Sent Events stream of rebuild progress; final event `{\"type\":\"done\",\"success\":bool,...}`","content":{"text/event-stream":{}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"}},"security":[{"bearer_auth":[]}]}},"/settings/sandbox-status":{"get":{"tags":["Agents"],"operationId":"get_global_sandbox_status","responses":{"200":{"description":"Global sandbox readiness for the settings page","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SandboxStatusResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"}},"security":[{"bearer_auth":[]}]}},"/settings/secrets":{"get":{"tags":["Secrets"],"operationId":"list_secrets","responses":{"200":{"description":"List of global agent secrets","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListSecretsResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Secrets"],"operationId":"upsert_secret","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpsertSecretRequest"}}},"required":true},"responses":{"201":{"description":"Secret created/updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SecretResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"}},"security":[{"bearer_auth":[]}]}},"/settings/secrets/{name}":{"delete":{"tags":["Secrets"],"operationId":"delete_secret","parameters":[{"name":"name","in":"path","description":"Secret name","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Secret deleted"},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Secret not found"}},"security":[{"bearer_auth":[]}]}},"/settings/skills":{"get":{"tags":["Agents"],"operationId":"list_global_skills","responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListSkillsResponse"}}}},"401":{"description":"Unauthorized"}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Agents"],"operationId":"create_global_skill","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateSkillRequest"}}},"required":true},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SkillDefinitionResponse"}}}},"401":{"description":"Unauthorized"}},"security":[{"bearer_auth":[]}]}},"/settings/skills/upload":{"post":{"tags":["Agents"],"summary":"Upload a skill with an archive (tar.gz) — global.","operationId":"upload_global_skill","requestBody":{"content":{"multipart/form-data":{"schema":{"type":"string"}}},"required":true},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SkillDefinitionResponse"}}}},"401":{"description":"Unauthorized"}},"security":[{"bearer_auth":[]}]}},"/settings/skills/{slug}":{"get":{"tags":["Agents"],"operationId":"get_global_skill","parameters":[{"name":"slug","in":"path","description":"Skill slug","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SkillDefinitionResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Skill not found"}},"security":[{"bearer_auth":[]}]},"put":{"tags":["Agents"],"operationId":"update_global_skill","parameters":[{"name":"slug","in":"path","description":"Skill slug","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateSkillRequest"}}},"required":true},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SkillDefinitionResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Skill not found"}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["Agents"],"operationId":"delete_global_skill","parameters":[{"name":"slug","in":"path","description":"Skill slug","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Skill deleted"},"401":{"description":"Unauthorized"},"404":{"description":"Skill not found"}},"security":[{"bearer_auth":[]}]}},"/settings/skills/{slug}/archive":{"get":{"tags":["Agents"],"summary":"Download a skill's archive (tar.gz) — global.","operationId":"download_global_skill_archive","parameters":[{"name":"slug","in":"path","description":"Skill slug","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Skill archive tar.gz","content":{"application/gzip":{}}},"401":{"description":"Unauthorized"},"404":{"description":"Skill not found or has no archive"}},"security":[{"bearer_auth":[]}]}},"/settings/update-status":{"get":{"tags":["Settings"],"summary":"Report whether a newer temps release is available for this install.","operationId":"get_update_status","responses":{"200":{"description":"Release update status for this install","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateStatusResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"}},"security":[{"bearer_auth":[]}]}},"/teams":{"get":{"tags":["Teams"],"operationId":"list_teams","parameters":[{"name":"page","in":"query","description":"1-indexed page","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"page_size","in":"query","description":"default 20, max 100","required":false,"schema":{"type":"integer","format":"int64","minimum":0}}],"responses":{"200":{"description":"Paginated teams","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TeamListResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Teams"],"operationId":"create_team","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateTeamRequest"}}},"required":true},"responses":{"201":{"description":"Team created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TeamResponse"}}}},"400":{"description":"Validation error"},"403":{"description":"Insufficient permissions"},"409":{"description":"Slug already taken"}},"security":[{"bearer_auth":[]}]}},"/teams/{team_id}":{"get":{"tags":["Teams"],"operationId":"get_team","parameters":[{"name":"team_id","in":"path","description":"Team id","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Team","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TeamResponse"}}}},"403":{"description":"Insufficient permissions"},"404":{"description":"Team not found"}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["Teams"],"operationId":"delete_team","parameters":[{"name":"team_id","in":"path","description":"Team id","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"Team deleted"},"403":{"description":"Insufficient permissions"},"404":{"description":"Team not found"}},"security":[{"bearer_auth":[]}]},"patch":{"tags":["Teams"],"operationId":"update_team","parameters":[{"name":"team_id","in":"path","description":"Team id","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateTeamRequest"}}},"required":true},"responses":{"200":{"description":"Updated team","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TeamResponse"}}}},"400":{"description":"Validation error"},"403":{"description":"Insufficient permissions"},"404":{"description":"Team not found"}},"security":[{"bearer_auth":[]}]}},"/teams/{team_id}/members":{"get":{"tags":["Teams"],"operationId":"list_team_members","parameters":[{"name":"team_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Members","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/TeamMemberResponse"}}}}},"403":{"description":"Insufficient permissions"},"404":{"description":"Team not found"}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Teams"],"operationId":"add_team_member","parameters":[{"name":"team_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateTeamMemberRequest"}}},"required":true},"responses":{"201":{"description":"Member added","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TeamMemberResponse"}}}},"403":{"description":"Insufficient permissions"},"404":{"description":"Team not found"},"409":{"description":"User already a member"}},"security":[{"bearer_auth":[]}]}},"/teams/{team_id}/members/{user_id}":{"delete":{"tags":["Teams"],"operationId":"remove_team_member","parameters":[{"name":"team_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"user_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"Member removed"},"403":{"description":"Insufficient permissions"},"404":{"description":"Member not found"}},"security":[{"bearer_auth":[]}]},"patch":{"tags":["Teams"],"operationId":"update_team_member_role","parameters":[{"name":"team_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"user_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateMemberRoleRequest"}}},"required":true},"responses":{"200":{"description":"Updated membership","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TeamMemberResponse"}}}},"403":{"description":"Insufficient permissions"},"404":{"description":"Member not found"}},"security":[{"bearer_auth":[]}]}},"/teams/{team_id}/projects":{"get":{"tags":["Teams"],"operationId":"list_team_projects","parameters":[{"name":"team_id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Projects this team has access to","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ProjectAccessResponse"}}}}},"403":{"description":"Insufficient permissions"},"404":{"description":"Team not found"}},"security":[{"bearer_auth":[]}]}},"/templates":{"get":{"tags":["Templates"],"summary":"List all available templates","description":"Returns a list of all public templates, optionally filtered by tag or featured status.","operationId":"list_project_templates","parameters":[{"name":"tag","in":"query","description":"Filter templates by tag","required":false,"schema":{"type":"string"}},{"name":"featured","in":"query","description":"Only return featured templates","required":false,"schema":{"type":"boolean"}}],"responses":{"200":{"description":"List of templates","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListTemplatesResponse"}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/templates/tags":{"get":{"tags":["Templates"],"summary":"List all available template tags","description":"Returns a list of all unique tags used by public templates.","operationId":"list_project_template_tags","responses":{"200":{"description":"List of tags","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListTagsResponse"}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/templates/{slug}":{"get":{"tags":["Templates"],"summary":"Get a specific template by slug","description":"Returns detailed information about a single template.","operationId":"get_project_template","parameters":[{"name":"slug","in":"path","description":"Template slug","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Template details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplateResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Template not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/user/me":{"get":{"tags":["Authentication"],"operationId":"get_current_user","responses":{"200":{"description":"Successfully retrieved user information","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserResponse"}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"session_token":[]}]}},"/users":{"get":{"tags":["Users"],"operationId":"list_users","parameters":[{"name":"include_deleted","in":"query","description":"Include deleted users in the response","required":true,"schema":{"type":"boolean"}}],"responses":{"200":{"description":"List all users with their roles","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/RouteUserWithRoles"}}}}},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Users"],"summary":"Create a new user with roles","operationId":"create_user","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateUserRequest"}}},"required":true},"responses":{"201":{"description":"User created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RouteUserWithRoles"}}}},"400":{"description":"Invalid input"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/users/me":{"patch":{"tags":["Users"],"summary":"Update current user's information","operationId":"update_self","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateSelfRequest"}}},"required":true},"responses":{"200":{"description":"User updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RouteUserWithRoles"}}}},"400":{"description":"Invalid input"},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/users/me/mfa":{"delete":{"tags":["Users"],"operationId":"disable_mfa","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DisableMfaRequest"}}},"required":true},"responses":{"204":{"description":"MFA disabled"},"400":{"description":"Invalid verification code"},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/users/me/mfa/setup":{"post":{"tags":["Users"],"operationId":"setup_mfa","responses":{"200":{"description":"MFA setup data","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MfaSetupResponse"}}}},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/users/me/mfa/verify":{"post":{"tags":["Users"],"operationId":"verify_and_enable_mfa","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VerifyMfaRequest"}}},"required":true},"responses":{"204":{"description":"MFA verified and enabled"},"400":{"description":"Invalid code"},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/users/me/password":{"post":{"tags":["Users"],"operationId":"change_password_self","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChangePasswordRequest"}}},"required":true},"responses":{"204":{"description":"Password updated"},"400":{"description":"Validation error (weak password, same as current, MFA missing)"},"401":{"description":"Current password incorrect or MFA code invalid"},"403":{"description":"Account has no password set (SSO only)"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/users/{user_id}":{"delete":{"tags":["Users"],"summary":"Delete a user","operationId":"delete_user","parameters":[{"name":"user_id","in":"path","description":"User ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"User deleted successfully"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden - Cannot delete yourself or non-admin attempt"},"404":{"description":"User not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]},"patch":{"tags":["Users"],"summary":"Update user information (admin only)","operationId":"update_user","parameters":[{"name":"user_id","in":"path","description":"User ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateUserRequest"}}},"required":true},"responses":{"200":{"description":"User updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RouteUserWithRoles"}}}},"400":{"description":"Invalid input"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden - Non-admin attempt"},"404":{"description":"User not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/users/{user_id}/restore":{"post":{"tags":["Users"],"operationId":"restore_user","parameters":[{"name":"user_id","in":"path","description":"User ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"User restored successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RouteUserWithRoles"}}}},"400":{"description":"User is not deleted"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden - Non-admin attempt"},"404":{"description":"User not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/users/{user_id}/roles":{"post":{"tags":["Users"],"operationId":"assign_role","parameters":[{"name":"user_id","in":"path","description":"User ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AssignRoleRequest"}}},"required":true},"responses":{"200":{"description":"Role assigned successfully"},"400":{"description":"Invalid role type"},"401":{"description":"Unauthorized"},"403":{"description":"Admin role required or self-modification forbidden"},"404":{"description":"User or role not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/users/{user_id}/roles/{role_type}":{"delete":{"tags":["Users"],"operationId":"remove_role","parameters":[{"name":"user_id","in":"path","description":"User ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"role_type","in":"path","description":"Role type to remove","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Role removed successfully"},"400":{"description":"Invalid role type"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden - Cannot modify own roles or non-admin attempt"},"404":{"description":"User or role not found"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/v1/sandboxes":{"get":{"tags":["Sandboxes"],"operationId":"list_sandboxes","parameters":[{"name":"page","in":"query","description":"Page (1-indexed)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"page_size","in":"query","description":"Items per page (default 20, max 100)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}}],"responses":{"200":{"description":"List sandboxes","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListSandboxesResponse"}}}}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Sandboxes"],"operationId":"create_sandbox","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateSandboxBody"}}},"required":true},"responses":{"201":{"description":"Sandbox created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SandboxResponse"}}}},"400":{"description":"Validation error"},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"bearer_auth":[]}]}},"/v1/sandboxes/rootfs":{"get":{"tags":["Sandboxes"],"summary":"Inspect rootfs storage: the Firecracker digest-keyed cache (with which\nsandboxes reference each entry) and per-VM disks. Empty on Docker-only\nhosts. Admin/read scope — this exposes host storage layout.","operationId":"rootfs_report","responses":{"200":{"description":"Rootfs storage report"}},"security":[{"bearer_auth":[]}]}},"/v1/sandboxes/rootfs/gc":{"post":{"tags":["Sandboxes"],"summary":"Reclaim rootfs cache entries not backing any live sandbox. Idempotent;\nsafe to call any time (live VMs hold their own per-VM disks).","operationId":"rootfs_gc","responses":{"200":{"description":"Reclaimed cache entries"}},"security":[{"bearer_auth":[]}]}},"/v1/sandboxes/{id}":{"get":{"tags":["Sandboxes"],"operationId":"get_sandbox","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Sandbox details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SandboxResponse"}}}},"404":{"description":"Not found"}},"security":[{"bearer_auth":[]}]}},"/v1/sandboxes/{id}/cmd":{"post":{"tags":["Sandboxes"],"summary":"Run a command inside the sandbox (`@vercel/sandbox`-compatible).","description":"`wait=false` (default) returns `{ command: {..., exitCode: null} }`\nimmediately once the background task is spawned.\n\n`wait=true` streams `application/x-ndjson`: the first line is the\nrunning envelope, the second is the finished envelope with `exitCode`.","operationId":"cmd","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CmdBody"}}},"required":true},"responses":{"200":{"description":"Command started (wait=false) or finished (wait=true)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CmdResponse"}}}},"404":{"description":"Sandbox not found"}},"security":[{"bearer_auth":[]}]}},"/v1/sandboxes/{id}/cmd/{cmd_id}":{"get":{"tags":["Sandboxes"],"operationId":"get_cmd","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"cmd_id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Command snapshot","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CmdResponse"}}}},"404":{"description":"Sandbox or command not found"}},"security":[{"bearer_auth":[]}]}},"/v1/sandboxes/{id}/cmd/{cmd_id}/logs":{"get":{"tags":["Sandboxes"],"summary":"Stream a command's stdout/stderr as `application/x-ndjson`\n(`@vercel/sandbox`-compatible). Each line is either\n`{stream:\"stdout\"|\"stderr\", data:\"...\"}` or\n`{stream:\"error\", data:{code, message}}`.","operationId":"cmd_logs","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"cmd_id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"NDJSON stream of log events"},"404":{"description":"Sandbox or command not found"}},"security":[{"bearer_auth":[]}]}},"/v1/sandboxes/{id}/destroy":{"post":{"tags":["Sandboxes"],"operationId":"destroy_sandbox","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Sandbox destroyed (alias for `/stop` with an explicit verb)"},"404":{"description":"Not found"},"409":{"description":"Sandbox belongs to an active agent run — stop the run instead"}},"security":[{"bearer_auth":[]}]}},"/v1/sandboxes/{id}/domain":{"get":{"tags":["Sandboxes"],"operationId":"domain","parameters":[{"name":"port","in":"query","description":"Port inside the sandbox (1..=65535)","required":true,"schema":{"type":"integer","format":"int32","minimum":0}},{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Preview URL for the port","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SandboxDomainResponse"}}}},"400":{"description":"Invalid port"},"404":{"description":"Sandbox not found"}},"security":[{"bearer_auth":[]}]}},"/v1/sandboxes/{id}/events":{"get":{"tags":["Sandboxes"],"summary":"The operations timeline for a sandbox (lifecycle events only — never\nshell/exec activity), newest first.","operationId":"list_events","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Operations timeline","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SandboxEventsResponse"}}}}},"security":[{"bearer_auth":[]}]}},"/v1/sandboxes/{id}/exec":{"post":{"tags":["Sandboxes"],"operationId":"exec","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExecBody"}}},"required":true},"responses":{"200":{"description":"Command finished (non-zero exit is NOT an error)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExecResponse"}}}},"404":{"description":"Sandbox not found"}},"security":[{"bearer_auth":[]}]}},"/v1/sandboxes/{id}/exec-detached":{"post":{"tags":["Sandboxes"],"operationId":"exec_detached","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExecBody"}}},"required":true},"responses":{"202":{"description":"Command accepted; poll /jobs/{job_id}","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExecDetachedResponse"}}}},"404":{"description":"Sandbox not found"}},"security":[{"bearer_auth":[]}]}},"/v1/sandboxes/{id}/extend-timeout":{"post":{"tags":["Sandboxes"],"operationId":"extend_timeout","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExtendTimeoutBody"}}},"required":true},"responses":{"200":{"description":"Timeout extended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SandboxResponse"}}}},"400":{"description":"Validation error"},"404":{"description":"Not found"}},"security":[{"bearer_auth":[]}]}},"/v1/sandboxes/{id}/fs/mkdir":{"post":{"tags":["Sandboxes"],"operationId":"mkdir","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MkdirBody"}}},"required":true},"responses":{"204":{"description":"Directory created (or already existed)"},"400":{"description":"Validation error"}},"security":[{"bearer_auth":[]}]}},"/v1/sandboxes/{id}/fs/read":{"get":{"tags":["Sandboxes"],"operationId":"read_file","parameters":[{"name":"path","in":"query","description":"Absolute file path inside the sandbox","required":true,"schema":{"type":"string"}},{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"File contents (base64)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReadFileResponse"}}}},"400":{"description":"Validation error"},"404":{"description":"Sandbox or file not found"}},"security":[{"bearer_auth":[]}]}},"/v1/sandboxes/{id}/fs/stat":{"get":{"tags":["Sandboxes"],"operationId":"stat_path","parameters":[{"name":"path","in":"query","description":"Absolute path inside the sandbox","required":true,"schema":{"type":"string"}},{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Stat info (exists=false when missing — not an error)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatResponse"}}}},"400":{"description":"Validation error"}},"security":[{"bearer_auth":[]}]}},"/v1/sandboxes/{id}/fs/write":{"post":{"tags":["Sandboxes"],"summary":"Write a file into the sandbox. Accepts two body shapes — the SDK\npicks one based on `Content-Type`:","description":"- **`application/json`** (temps-native): `{path, contents_b64, mode}`\n — one file, base64-encoded.\n- **`application/gzip`** (`@vercel/sandbox`): a gzipped tarball of\n one-or-more entries, with the target extract dir carried in the\n `x-cwd` header. The SDK's `writeFile` and `writeFiles` both post\n here; they differ only in how many entries the tarball contains.\n\nWhy merge them on one route: the SDK is hardcoded to\n`POST /fs/write`, so splitting tar uploads onto a separate path would\nforce us to break SDK compat. Instead we dispatch on Content-Type,\npreserve JSON for native callers, and add tar for SDK callers.","operationId":"write_file","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WriteFileBody"}}},"required":true},"responses":{"204":{"description":"File(s) written"},"400":{"description":"Validation error or invalid base64"},"404":{"description":"Sandbox not found"},"415":{"description":"Unsupported Content-Type (expected application/json or application/gzip)"}},"security":[{"bearer_auth":[]}]}},"/v1/sandboxes/{id}/fs/write-batch":{"post":{"tags":["Sandboxes"],"summary":"Batch-write multiple files in a single request. Mirrors\n`@vercel/sandbox` `writeFiles()`. Semantics are fail-fast: if any\nfile errors, previously-written entries are left in place and the\nerror describes which file broke.","operationId":"write_files","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WriteFilesBody"}}},"required":true},"responses":{"200":{"description":"All files written","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WriteFilesResponse"}}}},"400":{"description":"Validation error or invalid base64"},"404":{"description":"Sandbox not found"}},"security":[{"bearer_auth":[]}]}},"/v1/sandboxes/{id}/jobs":{"get":{"tags":["Sandboxes"],"operationId":"list_jobs","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Detached jobs for this sandbox","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListJobsResponse"}}}},"404":{"description":"Sandbox not found"}},"security":[{"bearer_auth":[]}]}},"/v1/sandboxes/{id}/jobs/{job_id}":{"get":{"tags":["Sandboxes"],"operationId":"job_status","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"job_id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Job status snapshot","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JobStatusResponse"}}}},"404":{"description":"Sandbox or job not found"}},"security":[{"bearer_auth":[]}]}},"/v1/sandboxes/{id}/jobs/{job_id}/kill":{"post":{"tags":["Sandboxes"],"summary":"Terminate a detached job. Aborts the server-side tracking task and\nsends SIGTERM (or SIGKILL if `force=true`) to any matching processes\ninside the sandbox container. Returns 204 on success; 404 if the\nsandbox or job is unknown.","operationId":"kill_job","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"job_id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/KillJobBody"}}},"required":true},"responses":{"204":{"description":"Job killed"},"404":{"description":"Sandbox or job not found"}},"security":[{"bearer_auth":[]}]}},"/v1/sandboxes/{id}/jobs/{job_id}/logs":{"get":{"tags":["Sandboxes"],"summary":"SSE endpoint streaming each stdout/stderr line from a detached job\nas it's produced. Mirrors the `Command.logs()` async iterator shape\non `@vercel/sandbox` — events carry `{ stream, data }`.","description":"Late subscribers only see events produced after they connect. The\nJobState snapshot (`GET /jobs/{job_id}`) covers the history.\n\nA \"done\" sentinel event fires when the broadcast channel closes\n(the exec task has exited and dropped the sender), signalling\ncallers they can stop reading.","operationId":"job_logs","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"job_id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"SSE stream of log events"},"404":{"description":"Sandbox or job not found"}},"security":[{"bearer_auth":[]}]}},"/v1/sandboxes/{id}/pause":{"post":{"tags":["Sandboxes"],"operationId":"pause_sandbox","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Sandbox paused (container stopped, state preserved)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SandboxResponse"}}}},"404":{"description":"Not found"},"409":{"description":"Sandbox is in an incompatible state (e.g. already destroyed)"}},"security":[{"bearer_auth":[]}]}},"/v1/sandboxes/{id}/preview-link":{"post":{"tags":["Sandboxes"],"summary":"Mint a shareable link to a sandbox preview.","description":"`GET /domain` returns the bare preview URL, which is useless to anyone who\ndoes not already hold the sandbox's preview password — so sharing a\nprotected preview meant sharing that password, which is the same secret for\nevery recipient and can only be withdrawn by rotating it for all of them.\n\nThis returns the same URL carrying a short-lived, sandbox-scoped grant. The\nrecipient's browser exchanges it for the ordinary preview cookie and lands\non `path`. The grant never reaches the sandbox, so preview application code\ncannot read it and re-share it.\n\nAnyone holding the returned URL can view the preview until it expires;\nthere is no per-link revocation short of rotating the preview password.","operationId":"sandbox_create_preview_link","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PreviewShareLinkBody"}}},"required":true},"responses":{"200":{"description":"Shareable preview link","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PreviewShareLinkResponse"}}}},"400":{"description":"Invalid port"},"404":{"description":"Sandbox not found"},"409":{"description":"Sandbox has no preview password"},"500":{"description":"Preview grant minting failed"}},"security":[{"bearer_auth":[]}]}},"/v1/sandboxes/{id}/preview-password":{"put":{"tags":["Sandboxes"],"operationId":"set_preview_password","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetPreviewPasswordBody"}}},"required":true},"responses":{"200":{"description":"Preview password set or rotated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetPreviewPasswordResponse"}}}},"400":{"description":"Password too short or too long"},"404":{"description":"Sandbox not found"}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["Sandboxes"],"operationId":"clear_preview_password","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Preview password removed (sandbox is now URL-only protected)"},"404":{"description":"Sandbox not found"}},"security":[{"bearer_auth":[]}]}},"/v1/sandboxes/{id}/resize":{"post":{"tags":["Sandboxes"],"summary":"Grow a Firecracker sandbox's root disk. Offline resize — the VM reboots\n(filesystem/data persist) rather than resizing fully live.","operationId":"resize_sandbox","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResizeSandboxBody"}}},"required":true},"responses":{"200":{"description":"Resized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SandboxResponse"}}}},"400":{"description":"Invalid size or unsupported backend"}},"security":[{"bearer_auth":[]}]}},"/v1/sandboxes/{id}/restart":{"post":{"tags":["Sandboxes"],"operationId":"restart_sandbox","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Sandbox container restarted in place","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SandboxResponse"}}}},"404":{"description":"Not found"},"409":{"description":"Sandbox is stopped (use /resume) or already destroyed"}},"security":[{"bearer_auth":[]}]}},"/v1/sandboxes/{id}/resume":{"post":{"tags":["Sandboxes"],"operationId":"resume_sandbox","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Sandbox resumed; expires_at refreshed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SandboxResponse"}}}},"404":{"description":"Not found"},"409":{"description":"Sandbox is not in a resumable state"}},"security":[{"bearer_auth":[]}]}},"/v1/sandboxes/{id}/source":{"post":{"tags":["Sandboxes"],"operationId":"source_sandbox","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SourceBody"}}},"required":true},"responses":{"200":{"description":"Source content seeded into the sandbox work dir","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SandboxResponse"}}}},"400":{"description":"Validation error (embedded creds, conflicting fields, etc.)"},"404":{"description":"Sandbox not found"},"409":{"description":"Sandbox is not running"},"500":{"description":"Source seed failed inside sandbox"}},"security":[{"bearer_auth":[]}]}},"/v1/sandboxes/{id}/stop":{"post":{"tags":["Sandboxes"],"operationId":"stop_sandbox","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Sandbox stopped and destroyed"},"404":{"description":"Not found"},"409":{"description":"Sandbox belongs to an active agent run — stop the run instead"}},"security":[{"bearer_auth":[]}]}},"/v1/sandboxes/{id}/{cmd_id}/kill":{"post":{"tags":["Sandboxes"],"summary":"Kill a running command (`@vercel/sandbox`-compatible). The SDK\ncalls `POST /v1/sandboxes/{id}/{cmdId}/kill` — note the path has the\ncommand ID directly under the sandbox, NOT under `/jobs/` or `/cmd/`.","operationId":"cmd_kill","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"cmd_id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CmdKillBody"}}}},"responses":{"200":{"description":"Command killed; returns final snapshot","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CmdResponse"}}}},"404":{"description":"Sandbox or command not found"}},"security":[{"bearer_auth":[]}]}},"/visitors/{visitor_id}/session-replays":{"get":{"tags":["Analytics"],"summary":"Get session replays for a visitor","operationId":"get_visitor_sessions","parameters":[{"name":"visitor_id","in":"path","description":"Visitor ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"page","in":"query","description":"Page number (1-based)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"per_page","in":"query","description":"Items per page","required":false,"schema":{"type":"integer","format":"int64","minimum":0}}],"responses":{"200":{"description":"Session replays retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetVisitorSessionsResponse"}}}},"401":{"description":"Authentication required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearer_auth":[]}]}},"/visitors/{visitor_id}/session-replays/{session_id}":{"get":{"tags":["Analytics"],"summary":"Get session replay data with visitor info (without events)","operationId":"get_session_replay","parameters":[{"name":"visitor_id","in":"path","description":"Visitor ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"session_id","in":"path","description":"Session ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Session replay retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetSessionReplayResponse"}}}},"401":{"description":"Authentication required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Session not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["Analytics"],"summary":"Delete a session replay","operationId":"delete_session_replay","parameters":[{"name":"visitor_id","in":"path","description":"Visitor ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"session_id","in":"path","description":"Session ID","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Session replay deleted successfully"},"401":{"description":"Authentication required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Session not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearer_auth":[]}]}},"/visitors/{visitor_id}/session-replays/{session_id}/duration":{"put":{"tags":["Analytics"],"summary":"Update session duration","operationId":"update_session_duration","parameters":[{"name":"visitor_id","in":"path","description":"Visitor ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"session_id","in":"path","description":"Session ID","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateSessionDurationRequest"}}},"required":true},"responses":{"200":{"description":"Session duration updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateSessionDurationResponse"}}}},"401":{"description":"Authentication required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Session not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearer_auth":[]}]}},"/visitors/{visitor_id}/session-replays/{session_id}/events":{"get":{"tags":["Analytics"],"summary":"Get session replay events (with session and visitor metadata)","operationId":"get_session_replay_events","parameters":[{"name":"visitor_id","in":"path","description":"Visitor ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"session_id","in":"path","description":"Session ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Session replay with events retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionReplayWithEventsDto"}}}},"401":{"description":"Authentication required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Session not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearer_auth":[]}]},"post":{"tags":["Analytics"],"summary":"Add events to an existing session","operationId":"add_events","parameters":[{"name":"visitor_id","in":"path","description":"Visitor ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"session_id","in":"path","description":"Session ID","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddEventsRequest"}}},"required":true},"responses":{"200":{"description":"Events added successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddEventsResponse"}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Authentication required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Session not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearer_auth":[]}]}},"/vulnerability-scans/{scan_id}":{"get":{"tags":["Vulnerability Scans"],"operationId":"get_scan","parameters":[{"name":"scan_id","in":"path","description":"Scan ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Scan details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScanResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Scan not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]},"delete":{"tags":["Vulnerability Scans"],"operationId":"delete_scan","parameters":[{"name":"scan_id","in":"path","description":"Scan ID","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"204":{"description":"Scan deleted"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Scan not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/vulnerability-scans/{scan_id}/vulnerabilities":{"get":{"tags":["Vulnerability Scans"],"operationId":"get_scan_vulnerabilities","parameters":[{"name":"scan_id","in":"path","description":"Scan ID","required":true,"schema":{"type":"integer","format":"int32"}},{"name":"page","in":"query","description":"Page number (default: 1)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"page_size","in":"query","description":"Page size (default: 20, max: 100)","required":false,"schema":{"type":"integer","format":"int64","minimum":0}},{"name":"severity","in":"query","description":"Filter by severity (CRITICAL, HIGH, MEDIUM, LOW)","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"List of vulnerabilities","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/VulnerabilityResponse"}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"403":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"404":{"description":"Scan not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}},"security":[{"bearer_auth":[]}]}},"/webhook-event-types":{"get":{"tags":["Webhooks"],"summary":"List available event types","operationId":"list_event_types","responses":{"200":{"description":"List of available event types","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/EventTypeResponse"}}}}}}}},"/weekly-digest/trigger":{"post":{"tags":["Notification Preferences"],"summary":"Trigger weekly digest generation manually","operationId":"trigger_weekly_digest","responses":{"200":{"description":"Weekly digest triggered successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TriggerDigestResponse"}}}},"500":{"description":"Failed to generate digest"}},"security":[{"bearer_auth":[]}]}},"/x/plugins":{"get":{"tags":["External Plugins"],"summary":"List all running external plugins and their manifests.","description":"Requires only a valid session/token (no specific permission) since the\nmanifest drives sidebar navigation rendering for every authenticated\nuser, not just admins.","operationId":"list_external_plugins","responses":{"200":{"description":"List of all running external plugins","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/PluginManifest"}}}}},"401":{"description":"Unauthorized"}},"security":[{"bearer_auth":[]}]}},"/x/plugins/reload":{"post":{"tags":["External Plugins"],"summary":"Reload all external plugins.","description":"Stops all running plugin processes, re-scans the plugins directory,\nstarts any discovered binaries, and hot-swaps the proxy router so new\nand removed plugins take effect immediately without a server restart.\n\nRequires `SystemAdmin` permission.","operationId":"reload_plugins","responses":{"200":{"description":"Plugins reloaded successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReloadResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"}},"security":[{"bearer_auth":[]}]}},"/{project_id}/envelope/":{"post":{"tags":["sentry-ingestor"],"summary":"Ingest a Sentry envelope (binary payload)","operationId":"ingest_sentry_envelope","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"description":"Sentry envelope as binary data","content":{"application/octet-stream":{"schema":{"type":"string"}}},"required":true},"responses":{"200":{"description":"Envelope ingested"},"400":{"description":"Bad request"},"401":{"description":"Unauthorized"},"413":{"description":"Request body too large (exceeds 2 MiB)"}}}},"/{project_id}/store/":{"post":{"tags":["sentry-ingestor"],"summary":"Ingest a Sentry event (JSON payload)","operationId":"ingest_sentry_event","parameters":[{"name":"project_id","in":"path","description":"Project ID","required":true,"schema":{"type":"integer","format":"int32"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SentryEventRequest"}}},"required":true},"responses":{"200":{"description":"Event ingested","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SentryEventResponse"}}}},"400":{"description":"Bad request"},"401":{"description":"Unauthorized"},"413":{"description":"Request body too large (exceeds 2 MiB)"}}}},"audit/logs":{"get":{"tags":["Audit Logs"],"summary":"List audit logs with optional filtering","operationId":"list_audit_logs","parameters":[{"name":"operation_type","in":"query","description":"Filter logs by operation type (omit for all)","required":false,"schema":{"type":"string"},"example":"user.login"},{"name":"user_id","in":"query","description":"Filter logs by user ID (omit for all users)","required":false,"schema":{"type":"integer","format":"int32"},"example":1},{"name":"from","in":"query","description":"Start timestamp (milliseconds since epoch)","required":false,"schema":{"type":"string","format":"date-time"},"example":1},{"name":"to","in":"query","description":"End timestamp (milliseconds since epoch)","required":false,"schema":{"type":"string","format":"date-time"},"example":1},{"name":"limit","in":"query","description":"Maximum number of logs to return","required":false,"schema":{"type":"integer","format":"int32"},"example":100},{"name":"offset","in":"query","description":"Number of logs to skip","required":false,"schema":{"type":"integer","format":"int32"},"example":0}],"responses":{"200":{"description":"List of audit logs","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/AuditLogResponse"}}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"500":{"description":"Internal server error"}},"security":[{"api_key":[]}]}},"audit/logs/{id}":{"get":{"tags":["Audit Logs"],"summary":"Get a specific audit log entry by ID","operationId":"get_audit_log","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"Audit log details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuditLogResponse"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Insufficient permissions"},"404":{"description":"Audit log not found"},"500":{"description":"Internal server error"}},"security":[{"api_key":[]}]}}},"components":{"schemas":{"AcmeOrderResponse":{"type":"object","required":["id","order_url","domain_id","email","status","identifiers","created_at","updated_at"],"properties":{"authorizations":{},"certificate_url":{"type":["string","null"]},"challenge_validation":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/ChallengeValidationStatus","description":"Live challenge validation status fetched from Let's Encrypt"}]},"created_at":{"type":"integer","format":"int64"},"domain_id":{"type":"integer","format":"int32"},"email":{"type":"string"},"error":{"type":["string","null"]},"error_type":{"type":["string","null"]},"expires_at":{"type":["integer","null"],"format":"int64"},"finalize_url":{"type":["string","null"]},"id":{"type":"integer","format":"int32"},"identifiers":{},"order_url":{"type":"string"},"status":{"type":"string"},"updated_at":{"type":"integer","format":"int64"}}},"ActivateProviderResponse":{"type":"object","required":["default_provider"],"properties":{"default_provider":{"type":"string"}}},"ActiveVisitor":{"type":"object","required":["session_id","session_start","last_activity","page_count","event_count","duration_seconds","is_active"],"properties":{"current_page":{"type":["string","null"]},"duration_seconds":{"type":"integer","format":"int64"},"event_count":{"type":"integer","format":"int32"},"is_active":{"type":"boolean"},"last_activity":{"type":"string"},"page_count":{"type":"integer","format":"int32"},"session_id":{"type":"string"},"session_start":{"type":"string"},"visitor_id":{"type":["string","null"]}}},"ActiveVisitorsQuery":{"type":"object","properties":{"deployment_id":{"type":["integer","null"],"format":"int32"},"environment_id":{"type":["integer","null"],"format":"int32"}}},"ActiveVisitorsResponse":{"type":"object","required":["active_visitors","window_minutes"],"properties":{"active_visitors":{"type":"integer","format":"int64"},"window_minutes":{"type":"integer","format":"int32"}}},"ActivityDay":{"type":"object","description":"Daily activity count for a single day","required":["date","count","level"],"properties":{"count":{"type":"integer","format":"int64","description":"Number of deployments on this day"},"date":{"type":"string","description":"Date in YYYY-MM-DD format","example":"2024-06-15"},"level":{"type":"integer","format":"int32","description":"Intensity level (0-4) for visualization\n0: No activity, 1: Low (1-2), 2: Medium (3-5), 3: High (6-10), 4: Very High (11+)","example":2}}},"ActivityEvent":{"type":"object","description":"A single activity event for the real-time activity feed","required":["id","timestamp","event_type","page_path","is_crawler"],"properties":{"browser":{"type":["string","null"],"description":"Browser"},"city":{"type":["string","null"],"description":"Visitor's city (from ip_geolocations)"},"country":{"type":["string","null"],"description":"Visitor's country (from ip_geolocations)"},"country_code":{"type":["string","null"],"description":"Visitor's country code (from ip_geolocations)"},"device_type":{"type":["string","null"],"description":"Device type"},"event_name":{"type":["string","null"],"description":"Event name (for custom events)"},"event_type":{"type":"string","description":"Event type: \"page_view\", \"custom\", etc."},"id":{"type":"integer","format":"int64","description":"Event ID"},"is_crawler":{"type":"boolean","description":"Whether this event was from a crawler"},"latitude":{"type":["number","null"],"format":"double","description":"Latitude"},"longitude":{"type":["number","null"],"format":"double","description":"Longitude"},"operating_system":{"type":["string","null"],"description":"Operating system"},"page_path":{"type":"string","description":"Page path where the event happened"},"page_title":{"type":["string","null"],"description":"Page title"},"referrer":{"type":["string","null"],"description":"Referrer"},"timestamp":{"type":"string","format":"date-time","description":"When the event occurred"},"visitor_id":{"type":["integer","null"],"format":"int32","description":"Visitor numeric ID"}}},"ActivityGraphQuery":{"type":"object","description":"Query parameters for activity graph endpoint","properties":{"days":{"type":"integer","format":"int32","description":"Number of days to include (default: 365 for last year)"},"environment_id":{"type":["integer","null"],"format":"int32","description":"Optional environment ID to filter activity"},"project_id":{"type":["integer","null"],"format":"int32","description":"Optional project ID to filter activity"}}},"ActivityGraphResponse":{"type":"object","description":"Response for activity graph showing daily deployment activity","required":["days","total_count","start_date","end_date"],"properties":{"days":{"type":"array","items":{"$ref":"#/components/schemas/ActivityDay"},"description":"Array of daily activity counts"},"end_date":{"type":"string","description":"Date range end (YYYY-MM-DD)","example":"2024-12-31"},"start_date":{"type":"string","description":"Date range start (YYYY-MM-DD)","example":"2024-01-01"},"total_count":{"type":"integer","format":"int64","description":"Total count of activities across all days"}}},"AddClusterMemberRequest":{"type":"object","description":"Request body for adding a single member to a running cluster.","required":["role"],"properties":{"node_id":{"type":["integer","null"],"format":"int32","description":"Target worker node ID. Omit or null to run on the control plane."},"role":{"type":"string","description":"Member role. Currently only `replica` is accepted at runtime —\nmonitor is a singleton, primary is elected by pg_auto_failover.","example":"replica"}}},"AddContextRequest":{"type":"object","required":["message"],"properties":{"message":{"type":"string"}}},"AddEnvironmentDomainRequest":{"type":"object","required":["domain","is_primary"],"properties":{"domain":{"type":"string"},"is_primary":{"type":"boolean"}}},"AddEventsRequest":{"type":"object","required":["events"],"properties":{"events":{"type":"string"}}},"AddEventsResponse":{"type":"object","required":["event_count","message"],"properties":{"event_count":{"type":"integer","minimum":0},"message":{"type":"string"}}},"AddManagedDomainApiRequest":{"type":"object","description":"Request to add a managed domain","required":["domain"],"properties":{"auto_manage":{"type":"boolean"},"domain":{"type":"string","example":"example.com"},"generated_hostname_mode":{"type":["string","null"],"description":"Generated hostname layout: `\"standard\"` (default) or `\"flat\"`."},"sync_generated_records":{"type":"boolean","description":"Opt in to reconciling generated hostnames into this domain's DNS zone."}}},"AdminGateResponse":{"type":"object","required":["allowed_ips","allowed_hosts","trust_forwarded_for","source","editable"],"properties":{"allowed_hosts":{"type":"array","items":{"type":"string"},"description":"`Host` header values allowed. Empty = any host."},"allowed_ips":{"type":"array","items":{"type":"string"},"description":"IPs / CIDRs allowed to reach the admin listener. Empty = any source."},"editable":{"type":"boolean","description":"True when the config is writable through this API. False when env\nvars are dictating the active config."},"source":{"$ref":"#/components/schemas/AdminGateSource","description":"Where the active config came from."},"trust_forwarded_for":{"type":"boolean","description":"When true, the gate trusts `X-Forwarded-For` from loopback peers."}}},"AdminGateSource":{"type":"string","description":"Where the active gate configuration came from. Env-supplied configs are\nfrozen at the process level — the UI shows them read-only and refuses to\npersist DB writes. DB-supplied configs are editable at runtime.","enum":["default","db","env"]},"AgentConfigResponse":{"type":"object","description":"Response DTO for a single agent — masks the encrypted API key.","required":["id","project_id","slug","name","source","enabled","trigger_config","ai_provider","api_key_set","max_turns","timeout_seconds","daily_budget_cents","cooldown_minutes","branch_prefix","deliverable","created_at","updated_at"],"properties":{"ai_model":{"type":["string","null"],"description":"Preferred model for the CLI (e.g. \"sonnet\", \"gpt-5-codex\"). `None` means default."},"ai_provider":{"type":"string"},"ai_provider_key_id":{"type":["integer","null"],"format":"int32"},"api_key_set":{"type":"boolean","description":"`true` if an API key is set; `false` otherwise."},"branch_prefix":{"type":"string"},"config_repo_branch":{"type":["string","null"],"description":"Branch of the config repo to use."},"config_repo_url":{"type":["string","null"],"description":"Private config repo containing .claude/ directory (skills, MCP, plugins)."},"cooldown_minutes":{"type":"integer","format":"int32"},"created_at":{"type":"string"},"daily_budget_cents":{"type":"integer","format":"int32"},"deliverable":{"type":"string"},"description":{"type":["string","null"]},"enabled":{"type":"boolean"},"id":{"type":"integer","format":"int32"},"max_turns":{"type":"integer","format":"int32"},"mcp_servers_config":{"description":"MCP servers config (Claude Code settings.json mcpServers format).\nCredential-bearing legacy inline values are write-only and appear as\n`***`. Omit this field on update to preserve their stored values."},"name":{"type":"string"},"project_id":{"type":"integer","format":"int32"},"prompt":{"type":["string","null"]},"sandbox_enabled":{"type":["boolean","null"],"description":"None = use global sandbox setting, true = force on, false = force off"},"skills_config":{"description":"Skills config as JSON array."},"slug":{"type":"string"},"source":{"type":"string"},"timeout_seconds":{"type":"integer","format":"int32"},"tools_config":{"description":"Tools config as JSON array. Legacy custom-tool webhook URLs and headers\nare write-only and appear as `***`. Omit this field on update to\npreserve their stored values."},"trigger_config":{},"updated_at":{"type":"string"},"webhook_token":{"type":["string","null"],"description":"Secret token for the `X-Webhook-Token` header. Shown once when created,\nmasked with `***` prefix in subsequent reads."},"webhook_url":{"type":["string","null"],"description":"Public webhook URL for triggering this agent externally.\nOnly set when `on: { webhook: true }` is configured.\nUsage: `POST {webhook_url}` with header `X-Webhook-Token: {webhook_token}`"}}},"AgentRunLogResponse":{"type":"object","required":["id","run_id","level","message","created_at"],"properties":{"created_at":{"type":"string"},"id":{"type":"integer","format":"int64"},"level":{"type":"string"},"message":{"type":"string"},"metadata":{},"run_id":{"type":"integer","format":"int32"}}},"AgentRunResponse":{"type":"object","required":["id","project_id","source","trigger_type","status","tokens_input","tokens_output","estimated_cost_cents","files_changed","created_at","sandbox_enabled"],"properties":{"agent_name":{"type":["string","null"],"description":"Name of the agent that created this run, if available."},"agent_slug":{"type":["string","null"],"description":"Slug of the agent that created this run, if available."},"ai_model":{"type":["string","null"]},"ai_output":{"type":["string","null"]},"ai_provider":{"type":["string","null"],"description":"AI provider slug that executed this run (e.g. claude_cli, codex_cli, opencode)."},"ai_reasoning":{"type":["string","null"]},"ai_session_id":{"type":["string","null"],"description":"Claude CLI session UUID for resuming conversations via `--resume`."},"analysis":{"type":["string","null"],"description":"Report / analysis text produced by the agent (used for report/notification deliverables)."},"branch_name":{"type":["string","null"]},"commit_sha":{"type":["string","null"]},"completed_at":{"type":["string","null"]},"config_id":{"type":["integer","null"],"format":"int32","description":"Optional. NULL for ephemeral CLI runs (`source = \"cli_ephemeral\"`) and\nhistorical autofixer runs that pre-date the agent_id column."},"created_at":{"type":"string"},"ephemeral_yaml":{"type":["string","null"],"description":"Full WorkflowYamlConfig as YAML text. Populated only when\n`source = \"cli_ephemeral\"`. Used by the web UI to show a \"View YAML\"\nmodal so the user can see exactly what the executor ran."},"error_message":{"type":["string","null"]},"estimated_cost_cents":{"type":"integer","format":"int32"},"files_changed":{"type":"integer","format":"int32"},"id":{"type":"integer","format":"int32"},"phase":{"type":["string","null"],"description":"Autofixer phase: \"analyzing\", \"analyzed\", \"fixing\", \"fix_ready\", \"no_fix\",\n\"pr_created\", or NULL for non-autofixer runs."},"pr_number":{"type":["integer","null"],"format":"int32"},"pr_url":{"type":["string","null"]},"preview_url":{"type":["string","null"]},"project_id":{"type":"integer","format":"int32"},"prompt_text":{"type":["string","null"],"description":"Final assembled prompt the AI CLI actually saw (trigger context block +\nYAML prompt, with error-group fields interpolated). Captured once per\nrun. `None` for pre-migration rows."},"run_config":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/AutofixRunConfig","description":"Per-run AI options the user chose when starting an autofixer run\n(provider, model, max_turns, branch). NULL for generic agent runs\nand historical rows. Used to prefill the retry dialog."}]},"sandbox_enabled":{"type":"boolean","description":"Legacy field — all runs now execute in a sandbox. Kept for\nbackwards-compatible JSON shape; always `true`."},"source":{"type":"string","description":"`committed` (the run's config lives in `project_agents`) or\n`cli_ephemeral` (the config was uploaded via the CLI for a one-off\ndry run; see `ephemeral_yaml`)."},"started_at":{"type":["string","null"]},"status":{"type":"string"},"tokens_input":{"type":"integer","format":"int32"},"tokens_output":{"type":"integer","format":"int32"},"trigger_source_id":{"type":["integer","null"],"format":"int32"},"trigger_source_type":{"type":["string","null"]},"trigger_type":{"type":"string"},"user_context":{"type":["string","null"],"description":"User-provided context for this run (e.g. webhook payload, manual instructions)."}}},"AgentRunWithLogsResponse":{"type":"object","required":["run","logs"],"properties":{"logs":{"type":"array","items":{"$ref":"#/components/schemas/AgentRunLogResponse"}},"run":{"$ref":"#/components/schemas/AgentRunResponse"}}},"AgentSandboxSettings":{"type":"object","description":"Global agent sandbox settings. Controls whether agent runs are isolated\ninside Docker containers by default. Individual agents can override this.","properties":{"api_key_encrypted":{"type":["string","null"],"description":"DEPRECATED: use `providers[default_provider].credentials_encrypted` instead.","default":null},"auth_type":{"type":"string","description":"DEPRECATED: use `providers[default_provider].auth_type` instead.","default":"subscription"},"cpu_limit":{"type":"number","format":"double","description":"CPU limit in cores for sandbox containers","default":4.0,"example":4.0},"custom_image":{"type":"string","description":"Custom Docker image (only used when runtime is \"custom\").\nMust have git and claude CLI installed.","default":"","example":""},"default_provider":{"type":"string","description":"Default AI provider for agents: \"claude_cli\", \"opencode\", or \"codex_cli\".\nWorkspaces always use this provider — no per-session override.","default":"claude_cli","example":"claude_cli"},"enabled":{"type":"boolean","description":"Sandbox is always enabled — the executor refuses to run any agent\noutside a sandboxed container. Field is retained so existing settings\nrows still deserialize, but it is ignored at runtime.","default":true},"memory_limit_mb":{"type":"integer","format":"int64","description":"Memory limit in MB for sandbox containers","default":8192,"example":8192,"minimum":0},"network_mode":{"type":"string","description":"Network access level: \"full\" (unrestricted), \"restricted\" (Temps network only), \"none\" (no network)","default":"full","example":"full"},"providers":{"type":"object","description":"Per-provider auth + config. Keyed by provider id (e.g. `claude_cli`,\n`codex_cli`, `opencode`). Adding a new provider only requires a new\ncatalog entry on the Rust side — the JSON column stays migration-free.","default":{},"additionalProperties":{"$ref":"#/components/schemas/ProviderConfig"},"propertyNames":{"type":"string"}},"runtime":{"type":"string","description":"Runtime preset: \"node\", \"bun\", \"python\", \"rust\", \"go\", \"full\", or \"custom\"","default":"node","example":"node"},"sandbox_backend":{"type":["string","null"],"description":"Default isolation backend for sandboxes: \"docker\" (default) or\n\"firecracker\" (ADR-029; requires `temps firecracker setup`). Only\nconsulted when the Firecracker backend probes available — otherwise\nDocker is used regardless.","default":null,"example":"docker"}}},"AgentSandboxSettingsMasked":{"type":"object","description":"Agent sandbox settings with masked per-provider credentials.\nEach provider entry reports only whether a credential is saved, not\nthe encrypted blob itself. Non-sensitive fields (auth_type, default_model,\nextra) are passed through so the UI can render provider-specific state.","required":["default_provider","providers","api_key_saved","auth_type","enabled","runtime","custom_image","cpu_limit","memory_limit_mb","network_mode","sandbox_backend"],"properties":{"api_key_saved":{"type":"boolean"},"auth_type":{"type":"string"},"cpu_limit":{"type":"number","format":"double"},"custom_image":{"type":"string"},"default_provider":{"type":"string"},"enabled":{"type":"boolean"},"memory_limit_mb":{"type":"integer","format":"int64","minimum":0},"network_mode":{"type":"string"},"providers":{"type":"object","additionalProperties":{"$ref":"#/components/schemas/ProviderConfigMasked"},"propertyNames":{"type":"string"}},"runtime":{"type":"string"},"sandbox_backend":{"type":"string"}}},"AggregatedBucketItem":{"type":"object","required":["timestamp","count"],"properties":{"count":{"type":"integer","format":"int64"},"timestamp":{"type":"string"}}},"AggregatedBucketsQuery":{"type":"object","description":"Query parameters for aggregated metrics by time bucket","required":["start_date","end_date"],"properties":{"aggregation_level":{"$ref":"#/components/schemas/AggregationLevel","description":"Aggregation level: events, sessions, or visitors"},"bucket_size":{"type":"string","description":"Time bucket size: \"1 hour\", \"1 day\", \"1 week\", etc. (default: \"1 hour\")"},"deployment_id":{"type":["integer","null"],"format":"int32","description":"Optional deployment filter"},"end_date":{"type":"string","format":"date-time","description":"End date for the query range"},"environment_id":{"type":["integer","null"],"format":"int32","description":"Optional environment filter"},"start_date":{"type":"string","format":"date-time","description":"Start date for the query range"}}},"AggregatedBucketsResponse":{"type":"object","required":["bucket_size","aggregation_level","items","total"],"properties":{"aggregation_level":{"type":"string"},"bucket_size":{"type":"string"},"items":{"type":"array","items":{"$ref":"#/components/schemas/AggregatedBucketItem"}},"total":{"type":"integer","format":"int64"}}},"AggregationLevel":{"type":"string","enum":["events","sessions","visitors"]},"AggregationTemporality":{"type":"string","description":"The aggregation temporality of a Sum/Histogram/ExponentialHistogram metric.\n\nMirrors OTel's `AggregationTemporality` proto enum: whether reported values\nare cumulative since the start of the series (Cumulative) or only the delta\nsince the previous report (Delta).","enum":["unspecified","delta","cumulative"]},"AiAgentBreakdownResponse":{"type":"object","description":"Response wrapping the AI agent breakdown rows.","required":["items","start_time","end_time"],"properties":{"end_time":{"type":"string"},"items":{"type":"array","items":{"$ref":"#/components/schemas/AiAgentBreakdownRow"}},"start_time":{"type":"string"}}},"AiAgentBreakdownRow":{"type":"object","description":"One row in the AI-agent analytics breakdown. `agent` is the canonical\ncrawler name (e.g. `GPTBot`, `Claude-User`), `provider` is the vendor used\nfor grouping + logos. The UI mirrors the browsers card and ranks by\n`request_count`.","required":["provider","agent","purpose","request_count","unique_ips"],"properties":{"agent":{"type":"string"},"last_seen":{"type":["string","null"],"description":"Last-seen timestamp in RFC3339 format, or `None` if no rows matched.","example":"2026-05-29T12:00:00Z"},"provider":{"type":"string"},"purpose":{"type":"string"},"request_count":{"type":"integer","format":"int64"},"unique_ips":{"type":"integer","format":"int64"}}},"AiAgentDescriptor":{"type":"object","description":"Static descriptor for one entry in the known-AI-agents taxonomy.","required":["provider","agent","purpose"],"properties":{"agent":{"type":"string"},"provider":{"type":"string"},"purpose":{"type":"string"}}},"AiAgentPageRow":{"type":"object","description":"One row in the pages-by-agent breakdown. Returned by\n[`ProxyLogService::get_ai_agent_pages`] for a single named agent.\n`unique_ips` counts distinct client IPs that hit this path via that agent\n(same definition as the per-agent unique-IPs in [`AiAgentBreakdownRow`]).","required":["path","request_count","unique_ips"],"properties":{"last_seen":{"type":["string","null"],"description":"Last-seen timestamp in RFC3339 format, or `None` if no rows matched.","example":"2026-05-29T12:00:00Z"},"path":{"type":"string"},"request_count":{"type":"integer","format":"int64"},"unique_ips":{"type":"integer","format":"int64"}}},"AiAgentPagesResponse":{"type":"object","description":"Response wrapping the per-agent pages breakdown rows.","required":["agent","items","start_time","end_time"],"properties":{"agent":{"type":"string","description":"The agent name this breakdown is scoped to."},"end_time":{"type":"string"},"items":{"type":"array","items":{"$ref":"#/components/schemas/AiAgentPageRow"}},"start_time":{"type":"string"}}},"AiAgentTimelineResponse":{"type":"object","description":"Response wrapping the AI agent timeline rows.","required":["items","start_time","end_time","bucket","group_by"],"properties":{"bucket":{"type":"string","description":"Bucket interval used for the buckets (so the UI can label the x-axis).","example":"1 hour"},"end_time":{"type":"string"},"group_by":{"type":"string","description":"Echoes the grouping dimension actually applied.","example":"provider"},"items":{"type":"array","items":{"$ref":"#/components/schemas/AiAgentTimelineRow"}},"start_time":{"type":"string"}}},"AiAgentTimelineRow":{"type":"object","description":"One point in the AI-agent timeline: the request count for a single\n(`bucket`, `key`) pair, where `key` is a provider or agent name depending on\nthe requested grouping. The UI pivots these into one stacked series per\n`key` across the shared bucket x-axis.","required":["bucket","key","request_count"],"properties":{"bucket":{"type":"string","description":"Bucket start in RFC3339 format.","example":"2026-05-29T12:00:00Z"},"key":{"type":"string","description":"Provider or agent name this count belongs to.","example":"OpenAI"},"request_count":{"type":"integer","format":"int64"}}},"AiChatLimitsSettings":{"type":"object","description":"Bounds on one AI chat turn.\n\nA turn is bounded by TIME rather than by a number of steps. A step count\nsays nothing about cost or about how long someone has been watching a\nspinner, and it cuts short exactly the long, productive turns the chat\nexists for. The user can already see each tool call and press Stop; the\ndeadline is what guarantees an *unattended* turn still ends.\n\nThe right value is a property of the model, which is why it is configurable\nrather than compiled in: a full alert-suggestion turn takes ~10 minutes\nagainst a slow local model and seconds against a hosted one.","properties":{"turn_timeout_secs":{"type":"integer","format":"int32","description":"How long one turn may run before it is stopped and the partial answer\nreturned, in seconds. The user is told the turn was cut short.\n\nChecked between steps, not mid-call: a model round already in flight\nfinishes, so a turn can overrun by up to one round. Against a slow\nself-hosted model that is a minute or two. Aborting mid-stream would cut\nthe answer off in the middle of a sentence and throw away work already\npaid for, which is worse than a late stop.","default":900,"example":900,"maximum":3600,"minimum":30}}},"AiConfigSettings":{"type":"object","description":"Global AI configuration settings. Controls the default config repo\ncontaining `.claude/` directory (skills, MCP servers, plugins) that\ngets overlaid into every agent sandbox.","properties":{"config_repo":{"type":"string","description":"Global config repo URL in \"owner/repo\" format (e.g. \"myorg/claude-config\").\nCloned at agent run time and overlaid into the sandbox's `.claude/` directory.","default":"","example":""},"config_repo_branch":{"type":"string","description":"Branch of the config repo to use.","default":"main","example":"main"}}},"AiPageBreakdownResponse":{"type":"object","description":"Response wrapping the AI page breakdown rows.","required":["items","start_time","end_time"],"properties":{"end_time":{"type":"string"},"items":{"type":"array","items":{"$ref":"#/components/schemas/AiPageBreakdownRow"}},"start_time":{"type":"string"}}},"AiPageBreakdownRow":{"type":"object","description":"One row in the AI-crawled-pages breakdown. `agent_count` is the number of\n*distinct* AI agents that hit this path, so the UI can show both how heavily\nand how broadly a page is being crawled.","required":["path","request_count","agent_count"],"properties":{"agent_count":{"type":"integer","format":"int64"},"last_seen":{"type":["string","null"],"description":"Last-seen timestamp in RFC3339 format, or `None` if no rows matched.","example":"2026-05-29T12:00:00Z"},"path":{"type":"string"},"request_count":{"type":"integer","format":"int64"}}},"AiStatusBreakdownResponse":{"type":"object","description":"Response wrapping the AI status breakdown rows.","required":["items","start_time","end_time"],"properties":{"end_time":{"type":"string"},"items":{"type":"array","items":{"$ref":"#/components/schemas/AiStatusBreakdownRow"}},"start_time":{"type":"string"}}},"AiStatusBreakdownRow":{"type":"object","description":"One row in the AI-agent HTTP status breakdown: the request count for a\nstatus class (`2xx`/`3xx`/`4xx`/`5xx`/`other`) across crawler traffic.","required":["status_class","request_count"],"properties":{"request_count":{"type":"integer","format":"int64"},"status_class":{"type":"string","description":"Status class label.","example":"2xx"}}},"AlarmListResponse":{"type":"object","description":"Paginated list of alarms.","required":["items","total","page","page_size"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/AlarmResponse"}},"page":{"type":"integer","format":"int64","minimum":0},"page_size":{"type":"integer","format":"int64","minimum":0},"total":{"type":"integer","format":"int64","minimum":0}}},"AlarmResponse":{"type":"object","description":"Full alarm representation returned by list/summary endpoints.","required":["id","project_id","alarm_type","severity","status","title","fired_at","created_at","updated_at"],"properties":{"acknowledged_at":{"type":["string","null"],"description":"ISO-8601 UTC timestamp when the alarm was acknowledged, if any."},"acknowledged_by":{"type":["integer","null"],"format":"int32","description":"User ID who acknowledged the alarm, if any."},"alarm_type":{"type":"string"},"container_id":{"type":["integer","null"],"format":"int32"},"created_at":{"type":"string","description":"ISO-8601 UTC timestamp when the row was created."},"deployment_id":{"type":["integer","null"],"format":"int32"},"environment_id":{"type":["integer","null"],"format":"int32"},"fired_at":{"type":"string","description":"ISO-8601 UTC timestamp when the alarm fired."},"id":{"type":"integer","format":"int32"},"message":{"type":["string","null"]},"metadata":{"description":"Arbitrary JSON metadata attached by the alarm source."},"project_id":{"type":"integer","format":"int32"},"resolved_at":{"type":["string","null"],"description":"ISO-8601 UTC timestamp when the alarm was resolved, if any."},"service_id":{"type":["integer","null"],"format":"int32"},"severity":{"type":"string"},"status":{"type":"string"},"title":{"type":"string"},"updated_at":{"type":"string","description":"ISO-8601 UTC timestamp when the row was last updated."}}},"AlarmSummaryResponse":{"type":"object","description":"Re-export AlarmSummary for the OpenAPI schema.","required":["total_active","firing","acknowledged","critical","warning","by_type"],"properties":{"acknowledged":{"type":"integer","format":"int32","minimum":0},"by_type":{"type":"object","additionalProperties":{"type":"integer","format":"int32","minimum":0},"propertyNames":{"type":"string"}},"critical":{"type":"integer","format":"int32","minimum":0},"firing":{"type":"integer","format":"int32","minimum":0},"total_active":{"type":"integer","format":"int32","minimum":0},"warning":{"type":"integer","format":"int32","minimum":0}}},"AlertRuleResponse":{"type":"object","required":["id","project_id","name","trigger_type","trigger_config","notification_priority","cooldown_minutes","enabled","created_at","updated_at"],"properties":{"cooldown_minutes":{"type":"integer","format":"int32"},"created_at":{"type":"string"},"enabled":{"type":"boolean"},"environment_filter":{"type":["integer","null"],"format":"int32"},"error_level_filter":{"type":["string","null"]},"id":{"type":"integer","format":"int32"},"name":{"type":"string"},"notification_priority":{"type":"string"},"project_id":{"type":"integer","format":"int32"},"trigger_config":{},"trigger_type":{"type":"string"},"updated_at":{"type":"string"}}},"AllocEntry":{"type":"object","description":"Wire-format allocation. `null` in the JSON when the node hasn't been\nallocated yet — workers should treat that as \"single-host mode, do\nnot bring up the overlay\".","required":["node_id","compute_cidr","bridge_address","underlay_address"],"properties":{"bridge_address":{"type":"string"},"compute_cidr":{"type":"string"},"node_id":{"type":"string","description":"Stable v5 UUID derived from the database node id."},"underlay_address":{"type":"string"}}},"AnalyticsSessionEventsResponse":{"type":"object","required":["session_id","events","total_events"],"properties":{"events":{"type":"array","items":{"$ref":"#/components/schemas/SessionEvent"}},"session_id":{"type":"string"},"total_events":{"type":"integer","minimum":0}}},"AnnotatedSpan":{"type":"object","description":"A single span annotated with the project that originally stored it.\nUsed in `UnifiedTrace` to let the UI colour-code spans by project.","required":["project_id","project_name","span"],"properties":{"project_id":{"type":"integer","format":"int32","description":"The project that stored this span (same as `span.project_id`)."},"project_name":{"type":"string","description":"Human-readable project name for waterfall colour-coding and legend."},"span":{"$ref":"#/components/schemas/SpanRecord","description":"Original span data verbatim from storage."}}},"AnomalyAlgorithm":{"type":"string","description":"Anomaly baseline algorithm. Adding one (e.g. a new robust variant) is a\ncode-only enum addition — no migration, since it lives inside the blob.","enum":["robust","basic","agile","ewma"]},"AnomalyParams":{"type":"object","description":"Seasonal anomaly-band detector parameters (stub — not yet evaluated).","properties":{"algorithm":{"$ref":"#/components/schemas/AnomalyAlgorithm","description":"Baseline model. `robust` is the default (seasonal, stable, flags level\nshifts); `ewma`/`agile` adopt level shifts; `basic` is non-seasonal."},"baseline_lookback_days":{"type":["integer","null"],"format":"int32","description":"How far back to build the baseline. `None` = an evaluator default."},"deviations":{"type":"number","format":"double","description":"Band width in robust standard deviations (Datadog's `bounds`)."},"direction":{"$ref":"#/components/schemas/Direction","description":"Which side(s) of the band a deviation must be on to count."},"pct_anomalous":{"type":"number","format":"double","description":"Fraction (0..=1) of points in the window that must be anomalous to fire."},"seasonality":{"$ref":"#/components/schemas/Seasonality","description":"Seasonality model for the baseline."}}},"AnomalyPreviewPointResponse":{"type":"object","required":["bucket","value","lower","upper","breaching"],"properties":{"breaching":{"type":"boolean"},"bucket":{"type":"string","example":"2025-10-12T12:15:47Z"},"lower":{"type":"number","format":"double","description":"Lower edge of the expected band at this point."},"upper":{"type":"number","format":"double","description":"Upper edge of the expected band at this point."},"value":{"type":"number","format":"double"}}},"AnomalyPreviewRequest":{"type":"object","required":["project_id","metric_name","aggregation","window_secs","detection_config"],"properties":{"aggregation":{"type":"string","description":"One of `avg|sum|min|max|count|rate|p50|p90|p95|p99`."},"detection_config":{"$ref":"#/components/schemas/DetectionConfig","description":"The detector to backtest. `static` and `anomaly` are supported — the\nkinds the evaluator actually runs."},"end_time":{"type":["string","null"],"description":"RFC 3339; defaults to now.","example":"2025-10-12T12:15:47Z"},"metric_name":{"type":"string"},"project_id":{"type":"integer","format":"int32"},"start_time":{"type":["string","null"],"description":"RFC 3339; defaults to 7 days before `end_time`.","example":"2025-10-12T12:15:47Z"},"window_secs":{"type":"integer","format":"int32"}}},"AnomalyPreviewResponse":{"type":"object","required":["points","breach_count","baseline_samples","sufficient"],"properties":{"baseline_samples":{"type":"integer","format":"int64","description":"Baseline sample count (drives the `sufficient` flag)."},"breach_count":{"type":"integer","format":"int64","description":"How many points in the range would have fired."},"points":{"type":"array","items":{"$ref":"#/components/schemas/AnomalyPreviewPointResponse"}},"sufficient":{"type":"boolean","description":"Whether the baseline had enough history for a trustworthy band."}}},"ApiKeyListResponse":{"type":"object","required":["api_keys","total"],"properties":{"api_keys":{"type":"array","items":{"$ref":"#/components/schemas/ApiKeyResponse"}},"total":{"type":"integer","format":"int64","minimum":0}}},"ApiKeyResponse":{"type":"object","required":["id","name","key_prefix","role_type","is_active","created_at"],"properties":{"created_at":{"type":"string","format":"date-time","example":"2024-01-01T00:00:00Z"},"expires_at":{"type":["string","null"],"format":"date-time","example":"2024-12-31T23:59:59Z"},"id":{"type":"integer","format":"int32"},"is_active":{"type":"boolean"},"key_prefix":{"type":"string"},"last_used_at":{"type":["string","null"],"format":"date-time","example":"2024-01-01T00:00:00Z"},"name":{"type":"string"},"permissions":{"type":["array","null"],"items":{"type":"string"}},"role_type":{"type":"string"}}},"AppSettings":{"type":"object","description":"Application settings stored in the database\nAll fields have sensible defaults for easy onboarding","properties":{"agent_sandbox":{"oneOf":[{"$ref":"#/components/schemas/AgentSandboxSettings"}],"default":{"default_provider":"claude_cli","providers":{},"auth_type":"subscription","api_key_encrypted":null,"enabled":true,"runtime":"node","custom_image":"","cpu_limit":4.0,"memory_limit_mb":8192,"network_mode":"full","sandbox_backend":null}},"ai_chat_limits":{"oneOf":[{"$ref":"#/components/schemas/AiChatLimitsSettings","description":"Limits on a single AI chat turn. Operator-tunable because the right\nvalue depends on the model: a turn against a slow self-hosted model can\nlegitimately take ten minutes, while a hosted one finishes in seconds\nand a shorter ceiling keeps costs predictable."}],"default":{"turn_timeout_secs":900}},"ai_config":{"oneOf":[{"$ref":"#/components/schemas/AiConfigSettings"}],"default":{"config_repo":"","config_repo_branch":"main"}},"build_limits":{"oneOf":[{"$ref":"#/components/schemas/BuildLimitsSettings","description":"Build-time resource limits applied on the control plane to prevent\n`docker build` from saturating host CPU/RAM. Worker nodes are\nintentionally NOT subject to these limits (each worker is dedicated\nhardware that already has its own per-host headroom)."}],"default":{"max_concurrent":2,"cpu_limit_cores":0.0,"memory_limit_mb":0}},"cluster_dns":{"oneOf":[{"$ref":"#/components/schemas/ClusterDnsSettings","description":"Cluster-DNS resolver settings (ADR-024, experimental beta). Off by\ndefault — see `ClusterDnsSettings` for the incident background and\ntrade-offs. Must be explicitly enabled by operators who need\n`*.temps.local` service-to-service resolution inside containers."}],"default":{"enabled":false}},"console_version":{"type":["string","null"],"description":"Binary version tag (e.g. \"v0.1.0\") of the *console* process\n(`temps serve`, role=all or role=console) that last started. Written\non console startup; read by the standalone `temps proxy` to detect\nversion skew during a rolling upgrade (ADR-017 Phase 3). `None` on\ninstalls that never ran a console build carrying this field.\n\nThis is informational state written by the binary itself — NOT an\noperator-tunable setting. It is intentionally absent from\n`AppSettingsResponse` and the PATCH path so an operator cannot\naccidentally overwrite the self-recorded value.","default":null},"container_logs":{"oneOf":[{"$ref":"#/components/schemas/ContainerLogSettings"}],"default":{"max_size":"50m","max_file":3,"service_max_size":"20m","service_max_file":3}},"disk_space_alert":{"oneOf":[{"$ref":"#/components/schemas/DiskSpaceAlertSettings"}],"default":{"enabled":true,"threshold_percent":80,"check_interval_seconds":300,"monitor_path":null}},"dns_provider":{"oneOf":[{"$ref":"#/components/schemas/DnsProviderSettings"}],"default":{"provider":"manual","cloudflare_api_key":null}},"docker_registry":{"oneOf":[{"$ref":"#/components/schemas/DockerRegistrySettings"}],"default":{"enabled":false,"registry_url":null,"username":null,"password":null,"tls_verify":true,"ca_certificate":null}},"edge_target":{"type":["string","null"],"description":"Public edge target that generated DNS records point at when a managed\ndomain opts into automatic record sync. An IPv4/IPv6 address produces an\n`A`/`AAAA` record; anything else is treated as a `CNAME` target. `None`\ndisables DNS record sync regardless of per-domain opt-in.","default":null},"external_url":{"type":["string","null"],"default":null},"insecure_tls":{"type":"boolean","description":"Skip TLS certificate verification on outbound HTTP clients built by the\nserver (deployer, agent, remote service client). Strictly opt-in for\noperators running self-signed control plane / worker certs on a trusted\ninternal network. Worker→control-plane traffic that traverses the public\ninternet must keep this `false` — otherwise a MitM steals the join token.","default":false},"internal_url":{"type":["string","null"],"description":"URL that service containers use to reach the Temps API from *inside*\nthe Docker network (OTLP metrics ingest, agent callbacks, etc.). On\nDocker Desktop this defaults to `http://host.docker.internal:`;\non Linux it requires the `host.docker.internal:host-gateway` host\nmapping (which Temps adds to provisioned containers). Distinct from\n`external_url`, which is the public-facing address.","default":null},"letsencrypt":{"oneOf":[{"$ref":"#/components/schemas/LetsEncryptSettings"}],"default":{"email":null,"environment":"production"}},"monitoring":{"oneOf":[{"$ref":"#/components/schemas/MonitoringSettings","description":"Metrics observability settings. Controls the MetricsStore backend,\nscrape interval, and tiered retention windows."}],"default":{"enabled":false,"store":"timescale_db","scrape_interval_secs":30,"retention_raw_days":7,"retention_hourly_days":90,"retention_daily_years":2,"clickhouse_url":null}},"multi_node":{"oneOf":[{"$ref":"#/components/schemas/MultiNodeSettings"}],"default":{"join_token_hash":null,"private_address":null,"legacy_shared_token_enabled":true,"cluster_ca_cert_pem":null,"cluster_ca_key_encrypted":null,"require_mtls":false,"node_cpu_alert_percent":90.0,"node_memory_alert_percent":90.0,"node_disk_alert_percent":90.0}},"observability_compression":{"oneOf":[{"$ref":"#/components/schemas/ObservabilityCompressionSettings","description":"TimescaleDB compression delays for immutable observability data.\nChanges are applied at runtime by the Settings API."}],"default":{"proxy_logs_after_hours":24,"otel_spans_after_hours":24}},"observability_retention":{"oneOf":[{"$ref":"#/components/schemas/ObservabilityRetentionSettings","description":"Retention windows for raw proxy and OpenTelemetry telemetry.\nTimescaleDB policies are updated at runtime by the Settings API."}],"default":{"proxy_logs_days":30,"otel_spans_days":90,"otel_logs_days":90,"otel_metrics_days":90}},"on_demand_tls":{"oneOf":[{"$ref":"#/components/schemas/OnDemandTlsSettings"}],"default":{"enabled":false,"zone":null,"max_concurrent":3,"hourly_cap":10,"deployment_url_mode":"http"}},"preview_domain":{"type":"string","default":"localho.st"},"preview_gateway":{"oneOf":[{"$ref":"#/components/schemas/PreviewGatewaySettings"}],"default":{"image":"ghcr.io/gotempsh/temps-preview-gateway:latest","host_port":8090,"auto_upgrade":true}},"rate_limiting":{"oneOf":[{"$ref":"#/components/schemas/RateLimitSettings"}],"default":{"enabled":false,"max_requests_per_minute":60,"max_requests_per_hour":1000,"whitelist_ips":[],"blacklist_ips":[]}},"require_mfa_for_admins":{"type":"boolean","description":"When `true`, any user holding the `Admin` role must have MFA enrolled\n(`users.mfa_enabled = true`) to complete a **password** login. Users\nwithout MFA enrolled are rejected with a typed error instructing them\nto enroll before retrying. This only gates the password-login path\n(`AuthService::login`) -- SSO/OIDC logins are handled by a separate\ncode path (`OidcService::resolve_user` + `oidc_handler`) and are\nintentionally unaffected, since federating identity to a\nproperly-hardened IdP is itself an acceptable alternative to local\nTOTP MFA. Modeled as a settings row (not an env var) per CLAUDE.md so\nan operator can flip it at runtime via the Settings API without\nrestarting the binary.","default":false},"screenshots":{"oneOf":[{"$ref":"#/components/schemas/ScreenshotSettings"}],"default":{"enabled":false,"provider":"local","url":""}},"security_headers":{"oneOf":[{"$ref":"#/components/schemas/SecurityHeadersSettings"}],"default":{"enabled":false,"preset":"moderate","content_security_policy":"default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' data:; connect-src 'self'; frame-ancestors 'self'","x_frame_options":"SAMEORIGIN","x_content_type_options":"nosniff","x_xss_protection":"1; mode=block","strict_transport_security":"max-age=31536000; includeSubDomains","referrer_policy":"strict-origin-when-cross-origin","permissions_policy":"geolocation=(), microphone=(), camera=()"}},"setup_complete":{"type":"boolean","description":"Set to `true` by `temps setup` (all modes) once initial configuration\nhas been applied. The web onboarding wizard reads this from the server\nand skips itself when true, preventing the \"Configure Base Domain\" wall\nfrom appearing on installs that were already configured via the CLI.","default":false}}},"AppSettingsResponse":{"type":"object","description":"Safe response for application settings that masks sensitive fields","required":["preview_domain","screenshots","letsencrypt","dns_provider","security_headers","rate_limiting","docker_registry","disk_space_alert","container_logs","agent_sandbox","ai_config","preview_gateway","multi_node","monitoring","observability_compression","observability_retention","effective_metrics_store","effective_observability_store","insecure_tls","setup_complete","require_mfa_for_admins","cluster_dns","build_limits","ai_chat_limits"],"properties":{"agent_sandbox":{"$ref":"#/components/schemas/AgentSandboxSettingsMasked"},"ai_chat_limits":{"$ref":"#/components/schemas/AiChatLimitsSettings","description":"Per-turn limits for the AI chat. No sensitive content."},"ai_config":{"$ref":"#/components/schemas/AiConfigSettings"},"build_limits":{"$ref":"#/components/schemas/BuildLimitsSettings","description":"Build-time resource limits (control-plane only). No sensitive content,\npassed through as-is."},"cluster_dns":{"$ref":"#/components/schemas/ClusterDnsSettings","description":"Cluster-DNS resolver settings (ADR-024, experimental beta). No masking\nneeded — `enabled` is a plain bool with no sensitive content. Passed\nthrough as-is so the settings UI can read and toggle the flag."},"container_logs":{"$ref":"#/components/schemas/ContainerLogSettings"},"disk_space_alert":{"$ref":"#/components/schemas/DiskSpaceAlertSettings"},"dns_provider":{"$ref":"#/components/schemas/DnsProviderSettingsMasked"},"docker_registry":{"$ref":"#/components/schemas/DockerRegistrySettingsMasked"},"edge_target":{"type":["string","null"],"description":"Public edge target that synced DNS records point at (IP → A/AAAA, else CNAME)."},"effective_metrics_store":{"$ref":"#/components/schemas/MetricsStoreKind","description":"The storage backend the runtime is **actually** using for metrics,\nafter reconciling the `monitoring.store` toggle with the server's\n`TEMPS_CLICKHOUSE_*` configuration. When `monitoring.store` is\n`click_house` but those env vars are not fully set, the runtime falls\nback to TimescaleDB — in that case this reports `timescale_db` even\nthough `monitoring.store` says `click_house`. The UI shows this as the\neffective backend and warns when it diverges from the configured store."},"effective_observability_store":{"$ref":"#/components/schemas/MetricsStoreKind","description":"Storage backend actually used for proxy logs, OTel spans, and OTel\nmetrics. OTel logs remain TimescaleDB-backed. Unlike resource metrics,\nthese domains switch to ClickHouse whenever the server-level ClickHouse\nconnection is configured; they do not use the monitoring store toggle."},"external_url":{"type":["string","null"]},"insecure_tls":{"type":"boolean"},"internal_url":{"type":["string","null"]},"letsencrypt":{"$ref":"#/components/schemas/LetsEncryptSettings"},"monitored_services_count":{"type":["integer","null"],"format":"int64","description":"Number of enabled, running services the MetricsScraper currently\nincludes. Used for the lightweight storage estimate in the UI.","minimum":0},"monitoring":{"$ref":"#/components/schemas/MonitoringSettingsMasked"},"multi_node":{"$ref":"#/components/schemas/MultiNodeSettingsMasked"},"observability_compression":{"$ref":"#/components/schemas/ObservabilityCompressionSettings","description":"TimescaleDB compression delays for immutable proxy logs and OTel spans."},"observability_retention":{"$ref":"#/components/schemas/ObservabilityRetentionSettings","description":"Retention windows for raw proxy logs and OpenTelemetry data."},"preview_domain":{"type":"string"},"preview_gateway":{"$ref":"#/components/schemas/PreviewGatewaySettingsMasked"},"rate_limiting":{"$ref":"#/components/schemas/RateLimitSettings"},"require_mfa_for_admins":{"type":"boolean","description":"When enabled, Admin-role accounts without MFA enrolled are rejected\nat password login (bherila/temps#32). SSO/OIDC logins are unaffected."},"screenshots":{"$ref":"#/components/schemas/ScreenshotSettings"},"security_headers":{"$ref":"#/components/schemas/SecurityHeadersSettings"},"setup_complete":{"type":"boolean","description":"Whether `temps setup` has been run at least once. The web onboarding\nwizard checks this field on load and skips itself when true."}}},"ApplyHostnameModeRequest":{"type":"object","description":"Request to apply a hostname mode (recompute + optional DNS sync).","required":["mode"],"properties":{"mode":{"type":"string","description":"Target mode to apply: `\"standard\"` or `\"flat\"`."},"sync_dns":{"type":"boolean","description":"Also reconcile the provider's DNS zone for the affected hostnames."}}},"ArchiveFlagResponse":{"type":"object","required":["key"],"properties":{"archived_at":{"type":["string","null"]},"key":{"type":"string"}}},"ArchiveMode":{"type":"string","enum":["off","on","always","unknown"]},"AssignRoleRequest":{"type":"object","required":["user_id","role_type"],"properties":{"role_type":{"type":"string"},"user_id":{"type":"integer","format":"int32"}}},"AttachScheduleServicesRequest":{"type":"object","description":"Body for `POST /api/backups/schedules/{id}/services` — attach external\nservices to a backup schedule. Idempotent.","required":["service_ids"],"properties":{"service_ids":{"type":"array","items":{"type":"integer","format":"int32"},"description":"External service ids to attach. Duplicates are de-duplicated server-side."}}},"AttachScheduleServicesResponse":{"type":"object","description":"Response for `POST /api/backups/schedules/{id}/services`.","required":["inserted","total_attached"],"properties":{"inserted":{"type":"integer","format":"int64","description":"Number of rows actually inserted (excludes rows skipped by\n`ON CONFLICT DO NOTHING`).","minimum":0},"total_attached":{"type":"integer","description":"Total number of services now attached to the schedule.","minimum":0}}},"AuditLogIpInfo":{"type":"object","description":"IP address information in audit log","required":["ip"],"properties":{"city":{"type":["string","null"],"description":"City name","example":"San Francisco"},"country":{"type":["string","null"],"description":"Country code","example":"US"},"ip":{"type":"string","description":"IP address","example":"192.168.1.1"},"latitude":{"type":["number","null"],"format":"double","description":"Latitude","example":37.7749},"longitude":{"type":["number","null"],"format":"double","description":"Longitude","example":122.4194}}},"AuditLogResponse":{"type":"object","description":"Response type for audit log entries","required":["id","operation_type","audit_date"],"properties":{"audit_date":{"type":"integer","format":"int64","description":"When the action occurred","example":11932193},"data":{"description":"Additional context about the action"},"id":{"type":"integer","format":"int32","description":"Unique identifier for the audit log entry"},"ip_address":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/AuditLogIpInfo","description":"IP address details"}]},"operation_type":{"type":"string","description":"The type of action that was performed","example":"USER_LOGIN"},"user":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/AuditLogUserInfo","description":"User details who performed the action"}]},"user_id":{"type":["integer","null"],"format":"int32","description":"The user who performed the action (`null` when that account has\nsince been deleted; `data` retains the original actor context)"}}},"AuditLogUserInfo":{"type":"object","description":"User information in audit log","required":["id","name","email"],"properties":{"email":{"type":"string","description":"User's email","example":"john.doe@example.com"},"id":{"type":"integer","format":"int32","description":"User ID"},"name":{"type":"string","description":"User's name","example":"John Doe"}}},"AuthFlavorDto":{"type":"object","description":"One auth flavor surfaced to the UI. Mirrors `AuthFlavor` in the catalog\nbut without the seed-path / env-var fields the frontend doesn't need\n(those are server-side only — exposing them just bloats the response).","required":["id","label","description","format"],"properties":{"description":{"type":"string"},"env_var":{"type":["string","null"],"description":"For `api_key` format: the env var name that will be set inside the\nsandbox. Useful for showing the user \"we'll set OPENAI_API_KEY\" so\nthey know what their key controls."},"format":{"type":"string","description":"`api_key`, `oauth_token`, or `config_file` — drives which input UI\nthe settings page renders (single-line vs. multi-line textarea)."},"id":{"type":"string"},"label":{"type":"string"}}},"AuthResponse":{"type":"object","required":["success","message","mfa_required"],"properties":{"message":{"type":"string"},"mfa_required":{"type":"boolean"},"success":{"type":"boolean"},"user_id":{"type":["integer","null"],"format":"int32"}}},"AuthStatusResponse":{"type":"object","required":["status"],"properties":{"cli_token":{"type":["string","null"]},"status":{"type":"string"}}},"AuthTokenResponse":{"type":"object","required":["access_token","refresh_token","expires_at"],"properties":{"access_token":{"type":"string"},"expires_at":{"type":"integer","format":"int64"},"refresh_token":{"type":"string"}}},"AutoWatchParams":{"type":"object","description":"Auto-watch (Watchdog-style) detector parameters (stub — not evaluated).","properties":{"direction":{"$ref":"#/components/schemas/Direction","description":"The engine self-tunes the band; the user supplies only the direction."}}},"AutofixRunConfig":{"type":"object","description":"User-chosen per-run options, persisted as JSON in `agent_runs.run_config`.\nEvery field is optional — unset fields fall back to the provider defaults\nin settings, then to built-in defaults.","properties":{"branch":{"type":["string","null"],"description":"Branch to clone instead of the project's main branch.","default":null},"max_turns":{"type":["integer","null"],"format":"int32","description":"Per-run turn cap applied to every phase of this run. Only enforced\nfor CLIs with a turn flag (Claude Code); Codex/OpenCode run to\ncompletion. `None` uses the provider's per-phase defaults.","default":null},"model":{"type":["string","null"],"description":"Model id for the chosen provider. `None` uses the provider's saved\ndefault model, or the CLI's own default.","default":null},"provider":{"type":["string","null"],"description":"AI provider id (\"claude_cli\", \"codex_cli\", \"opencode\"). `None` uses\nthe platform default provider from agent sandbox settings.","default":null}}},"AutofixerRunResponse":{"type":"object","required":["id","project_id","status","tokens_input","tokens_output","files_changed","created_at"],"properties":{"ai_model":{"type":["string","null"]},"ai_output":{"type":["string","null"]},"ai_provider":{"type":["string","null"],"description":"AI provider slug this run executes with (e.g. claude_cli, codex_cli)."},"analysis":{"type":["string","null"]},"branch_name":{"type":["string","null"]},"completed_at":{"type":["string","null"]},"created_at":{"type":"string"},"error_message":{"type":["string","null"]},"files_changed":{"type":"integer","format":"int32"},"id":{"type":"integer","format":"int32"},"phase":{"type":["string","null"]},"pr_number":{"type":["integer","null"],"format":"int32"},"pr_url":{"type":["string","null"]},"project_id":{"type":"integer","format":"int32"},"run_config":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/AutofixRunConfig","description":"Per-run options the run was started with; used to prefill the\nretry / start-over dialog."}]},"started_at":{"type":["string","null"]},"status":{"type":"string"},"tokens_input":{"type":"integer","format":"int32"},"tokens_output":{"type":"integer","format":"int32"},"trigger_source_id":{"type":["integer","null"],"format":"int32"},"user_context":{"type":["string","null"]}}},"AutofixerRunWithLogsResponse":{"type":"object","required":["run","logs"],"properties":{"logs":{"type":"array","items":{"$ref":"#/components/schemas/AgentRunLogResponse"}},"run":{"$ref":"#/components/schemas/AutofixerRunResponse"}}},"AvailableContainerInfo":{"type":"object","description":"Available Docker container that can be imported as a service","required":["container_id","container_name","image","version","service_type","is_running"],"properties":{"container_id":{"type":"string","description":"Container ID or name","example":"abc123def456"},"container_name":{"type":"string","description":"Container display name","example":"my-postgres"},"exposed_ports":{"type":"array","items":{"type":"integer","format":"int32","minimum":0},"description":"Exposed ports (e.g., [5432] for PostgreSQL, [6379] for Redis)"},"image":{"type":"string","description":"Docker image name (e.g., \"gotempsh/postgres-walg:18-bookworm\")","example":"gotempsh/postgres-walg:18-bookworm"},"is_running":{"type":"boolean","description":"Whether the container is currently running","example":true},"service_type":{"$ref":"#/components/schemas/ServiceTypeRoute","description":"Service type this container represents"},"version":{"type":"string","description":"Extracted version from image","example":"18"}}},"AvailablePermissions":{"type":"object","description":"Response containing all available permissions for frontend validation","required":["permissions","roles"],"properties":{"permissions":{"type":"array","items":{"$ref":"#/components/schemas/PermissionInfo"},"description":"All available permissions in the system"},"roles":{"type":"array","items":{"$ref":"#/components/schemas/RoleInfo"},"description":"All available roles"}}},"BackupAlertListResponse":{"type":"object","description":"Response body for the list-backup-alerts endpoint.","required":["alerts"],"properties":{"alerts":{"type":"array","items":{"$ref":"#/components/schemas/BackupAlertResponse"},"description":"All currently open (unresolved) alerts, newest first."}}},"BackupAlertResponse":{"type":"object","description":"A single open backup alert surfaced in the UI banner.\n\nAlerts are auto-opened by the watcher and auto-resolved when the triggering\ncondition clears. No manual dismiss is required or supported.\n\nThe optional `schedule_s3_source_id` field is included so the UI can\ndeep-link an `overdue_schedule` alert to the S3 source detail page that\nhosts the schedule. `stalled_job` alerts no longer carry a deep-link\ntarget — the alert message text contains the backup id for display.","required":["id","kind","severity","message","opened_at"],"properties":{"id":{"type":"integer","format":"int64","description":"Database id of the alert row."},"kind":{"type":"string","description":"`\"overdue_schedule\"` or `\"stalled_job\"`."},"message":{"type":"string","description":"Human-readable description of the alert condition."},"opened_at":{"type":"string","description":"RFC 3339 timestamp when the alert was opened.","example":"2026-05-15T10:00:00Z"},"schedule_id":{"type":["integer","null"],"format":"int32","description":"FK to `backup_schedules.id`. Set for `overdue_schedule` alerts."},"schedule_name":{"type":["string","null"],"description":"Human-readable name of the linked schedule, if applicable."},"schedule_s3_source_id":{"type":["integer","null"],"format":"int32","description":"FK to `backup_schedules.s3_source_id`. The UI uses this to deep-link\nthe alert to the S3 source detail page that hosts the schedule.\nSet for `overdue_schedule` alerts."},"severity":{"type":"string","description":"`\"warning\"` or `\"critical\"`."}}},"BackupResponse":{"type":"object","description":"Response type for backup","required":["id","name","backup_id","backup_type","state","started_at","s3_source_id","s3_location","metadata","compression_type","created_by","tags"],"properties":{"attempts":{"type":["integer","null"],"format":"int32","description":"How many times this job has been claimed and run. `null` for legacy\nbackups with no `backup_jobs` row."},"backup_id":{"type":"string"},"backup_type":{"type":"string"},"checksum":{"type":["string","null"]},"completed_at":{"type":["integer","null"],"format":"int64"},"compression_type":{"type":"string"},"created_by":{"type":"integer","format":"int32"},"current_step":{"type":["string","null"],"description":"Name of the engine step currently executing (e.g., `\"walg_push\"`).\n`null` when no `backup_jobs` row exists for this backup (legacy rows\npre-dating ADR-014), or when the job has not yet completed its first step."},"error_message":{"type":["string","null"]},"expires_at":{"type":["integer","null"],"format":"int64"},"external_service":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/ExternalServiceSummary","description":"External service that owns this backup (Redis, Postgres, etc.).\n`null` for control-plane backups (the Temps server's own database)."}]},"file_count":{"type":["integer","null"],"format":"int32"},"id":{"type":"integer","format":"int32"},"live_size_bytes":{"type":["integer","null"],"format":"int64","description":"Best-effort partial size while a backup is still running, computed\nby listing the S3 prefix. Null when the backup is finished\n(`size_bytes` is authoritative in that case)."},"max_attempts":{"type":["integer","null"],"format":"int32","description":"Maximum attempts before the job is permanently failed. `null` for\nlegacy backups."},"max_runtime_secs":{"type":["integer","null"],"format":"int64","description":"Resolved wall-clock timeout for this backup job (seconds). `null` for\nlegacy backups. Derived from the three-tier resolution order:\ncaller override → schedule override → engine default."},"metadata":{},"name":{"type":"string"},"s3_location":{"type":"string"},"s3_source_id":{"type":"integer","format":"int32"},"schedule_id":{"type":["integer","null"],"format":"int32"},"size_bytes":{"type":["integer","null"],"format":"int64","description":"Final size of the backup once completed. Null while running."},"started_at":{"type":"integer","format":"int64"},"state":{"type":"string"},"tags":{"type":"array","items":{"type":"string"}}}},"BackupScheduleResponse":{"type":"object","description":"Response type for backup schedule","required":["id","name","backup_type","retention_period","s3_source_id","schedule_expression","enabled","created_at","updated_at","tags","target_all_services","include_control_plane"],"properties":{"backup_type":{"type":"string"},"created_at":{"type":"integer","format":"int64"},"description":{"type":["string","null"]},"enabled":{"type":"boolean"},"id":{"type":"integer","format":"int32"},"include_control_plane":{"type":"boolean","description":"When `true`, every run also produces a `control_plane` backup\n(Temps's own Postgres). When `false`, only the external service\nfan-out happens."},"last_run":{"type":["integer","null"],"format":"int64"},"max_runtime_secs":{"type":["integer","null"],"format":"int64","description":"Per-schedule wall-clock timeout override for backup jobs (seconds).\n`null` means the engine-family default is used. See\n`temps_backup_core::timeouts::default_max_runtime_secs`."},"name":{"type":"string"},"next_run":{"type":["integer","null"],"format":"int64"},"retention_period":{"type":"integer","format":"int32"},"s3_source_id":{"type":"integer","format":"int32"},"schedule_expression":{"type":"string","example":"0 0 * * *"},"tags":{"type":"array","items":{"type":"string"}},"target_all_services":{"type":"boolean","description":"When `true`, the schedule auto-includes every external service on\nthe host (and any future ones). When `false`, the schedule only\ntargets services attached via `backup_schedule_services`."},"updated_at":{"type":"integer","format":"int64"}}},"BitbucketAuthInput":{"oneOf":[{"type":"object","description":"Personal / Workspace / Repository Access Token.","required":["token","type"],"properties":{"token":{"type":"string","description":"The Bitbucket access token value."},"type":{"type":"string","enum":["access_token"]}}},{"type":"object","description":"HTTP Basic / App Password authentication.","required":["username","password","type"],"properties":{"password":{"type":"string","description":"App password generated in Bitbucket security settings."},"type":{"type":"string","enum":["app_password"]},"username":{"type":"string","description":"Bitbucket account username."}}}],"description":"Authentication input for a Bitbucket Cloud provider. Use `access_token` for\na Repository or Workspace Access Token (PAT), or `username` + `app_password`\nfor App Password (HTTP Basic) authentication."},"BlobResponse":{"type":"object","description":"Response after uploading a blob","required":["url","pathname","contentType","size","uploadedAt"],"properties":{"contentType":{"type":"string","description":"Content type of the blob","example":"image/png"},"pathname":{"type":"string","description":"Original pathname","example":"images/avatar-abc123.png"},"size":{"type":"integer","format":"int64","description":"Size in bytes","example":12345},"uploadedAt":{"type":"string","format":"date-time","description":"Upload timestamp","example":"2025-01-03T12:00:00Z"},"url":{"type":"string","description":"URL path to access the blob","example":"/api/blob/123/images/avatar-abc123.png"}}},"BlobStatusResponse":{"type":"object","description":"Response for Blob service status","required":["enabled","healthy"],"properties":{"docker_image":{"type":["string","null"],"description":"Docker image being used","example":"ghcr.io/rustfs/rustfs:0.5.0"},"enabled":{"type":"boolean","description":"Whether the Blob service is enabled","example":true},"healthy":{"type":"boolean","description":"Whether the service is healthy","example":true},"version":{"type":["string","null"],"description":"Current version (if running)","example":"0.5.0"}}},"BranchInfo":{"type":"object","required":["name","commit_sha","protected"],"properties":{"commit_sha":{"type":"string"},"name":{"type":"string"},"protected":{"type":"boolean"}}},"BranchListResponse":{"type":"object","required":["branches"],"properties":{"branches":{"type":"array","items":{"$ref":"#/components/schemas/BranchInfo"}}}},"BrowserCount":{"type":"object","required":["browser","count","percentage"],"properties":{"browser":{"type":"string"},"count":{"type":"integer","format":"int64"},"percentage":{"type":"number","format":"double"}}},"BrowsersQuery":{"type":"object","required":["start_date","end_date","project_id"],"properties":{"end_date":{"type":"string","format":"date-time"},"environment_id":{"type":["integer","null"],"format":"int32"},"limit":{"type":["integer","null"],"format":"int32"},"project_id":{"type":"integer","format":"int32"},"start_date":{"type":"string","format":"date-time"}}},"BuildConfiguration":{"type":"object","description":"Build configuration (for building images from source)","required":["context","args"],"properties":{"args":{"type":"object","description":"Build arguments","additionalProperties":{"type":"string"},"propertyNames":{"type":"string"}},"context":{"type":"string","description":"Build context (Dockerfile path or buildpack)"},"dockerfile":{"type":["string","null"],"description":"Dockerfile path (relative to context)"},"target":{"type":["string","null"],"description":"Target stage (for multi-stage builds)"}}},"BuildLimitsSettings":{"type":"object","description":"Control-plane build resource limits.\n\nCaps how many builds run concurrently AND how much CPU/memory each build\nis allowed to consume. A single global semaphore in the deployer crate\ngates every `DockerRuntime::build_image` call to `max_concurrent`. When\nthe semaphore is full, additional builds queue and wait — they do not\nfail. Per-build CPU/memory caps are forwarded to Docker via\n`BuildImageOptions { memory, cpuquota, cpuperiod }`.\n\n`cpu_limit_cores = 0.0` or `memory_limit_mb = 0` means \"no explicit cap\"\n— fall back to the legacy 50%-of-host heuristic for backwards\ncompatibility with operators who never visit the settings page.","properties":{"cpu_limit_cores":{"type":"number","format":"float","description":"CPU cores allowed per build (float, e.g. 2.0 = 2 cores, 0.5 = half\na core). 0 means \"use the legacy 50%-of-host default\".","default":0.0,"example":2.0,"minimum":0},"max_concurrent":{"type":"integer","format":"int32","description":"Maximum number of `docker build` operations allowed to run at the\nsame time on the control plane. Additional builds queue. Min 1.","default":2,"example":2,"minimum":1},"memory_limit_mb":{"type":"integer","format":"int32","description":"Memory allowed per build, in megabytes. 0 means \"use the legacy\n50%-of-host default\". Docker enforces this as a hard cap — builds\nthat exceed it OOM-kill.","default":0,"example":2048,"minimum":0}}},"CancelBackupResponse":{"type":"object","description":"Response body for cancel endpoints.","required":["cancelled"],"properties":{"cancelled":{"type":"integer","format":"int64","description":"Number of rows that were actually flipped to `failed`. `0` is a valid\nsuccess and means the backup was already terminal — the call is\nidempotent.","minimum":0}}},"CertStatusResponse":{"type":"object","description":"Current on-demand cert status for a single hostname (ADR-018 §5). Backs\n`GET /domains/by-host/{hostname}/cert-status`.","required":["hostname"],"properties":{"backoff_until":{"type":["integer","null"],"format":"int64","description":"On-demand negative-cache deadline (epoch millis), when in backoff."},"hostname":{"type":"string","description":"SNI hostname."},"last_attempt":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/OnDemandCertAttemptResponse","description":"The most recent on-demand issuance attempt for this hostname, if any."}]},"status":{"type":["string","null"],"description":"Current cert lifecycle status from the `domains` row, when one exists."}}},"ChallengeConfig":{"type":"object","description":"Challenge configuration (future feature)\nFor CAPTCHA, JS challenges, proof-of-work, etc.","required":["challengeType","difficulty"],"properties":{"challengeType":{"type":"string","description":"Challenge type: \"captcha\", \"js_challenge\", \"proof_of_work\""},"difficulty":{"type":"integer","format":"int32","description":"Challenge difficulty level (1-10)","minimum":0},"protectedPaths":{"type":"array","items":{"type":"string"},"description":"Paths that require challenges"}}},"ChallengeError":{"type":"object","required":["type","detail","status"],"properties":{"detail":{"type":"string","description":"Human-readable error description"},"status":{"type":"integer","format":"int32","description":"HTTP status code"},"type":{"type":"string","description":"Error type (e.g., \"urn:ietf:params:acme:error:unauthorized\")"}}},"ChallengeValidationStatus":{"type":"object","required":["type","url","status","token"],"properties":{"error":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/ChallengeError","description":"Error details if validation failed"}]},"status":{"type":"string","description":"Challenge status (e.g., \"pending\", \"valid\", \"invalid\")"},"token":{"type":"string","description":"Challenge token"},"type":{"type":"string","description":"Challenge type (e.g., \"dns-01\", \"http-01\")"},"url":{"type":"string","description":"Challenge validation URL"},"validated":{"type":["string","null"],"description":"When the challenge was validated (if successful)"}}},"ChangePasswordRequest":{"type":"object","required":["current_password","new_password"],"properties":{"current_password":{"type":"string","example":"current_password_value"},"mfa_code":{"type":["string","null"],"description":"TOTP code (or recovery code). Required iff the user has MFA enabled.","example":"123456"},"new_password":{"type":"string","example":"new_password_value"},"revoke_other_sessions":{"type":"boolean","description":"When true, every session OTHER than the one making this request is\nrevoked. Defaults to false; the UI surfaces this as a checkbox."}}},"ChangeProjectSourceRequest":{"type":"object","description":"Change a project's source type to a Git-less type (docker_image /\nstatic_files / manual). Switching TO `git` is done via the Git settings\nendpoint (which also supplies the repository + provider connection).","required":["source_type"],"properties":{"source_type":{"$ref":"#/components/schemas/SourceType"}}},"ChatCompletionChoice":{"type":"object","required":["index","message"],"properties":{"finish_reason":{"type":["string","null"]},"index":{"type":"integer","format":"int32"},"message":{"$ref":"#/components/schemas/ChatMessage"}}},"ChatCompletionRequest":{"allOf":[{"type":["object","null"],"description":"Tolerates extra SDK fields (stream_options, logprobs, etc.)","additionalProperties":{},"propertyNames":{"type":"string"}},{"type":"object","required":["model","messages"],"properties":{"frequency_penalty":{"type":["number","null"],"format":"double"},"max_tokens":{"type":["integer","null"],"format":"int64"},"messages":{"type":"array","items":{"$ref":"#/components/schemas/ChatMessage"}},"model":{"type":"string"},"n":{"type":["integer","null"],"format":"int32"},"presence_penalty":{"type":["number","null"],"format":"double"},"response_format":{},"seed":{"type":["integer","null"],"format":"int64"},"stop":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/StopSequence"}]},"stream":{"type":"boolean"},"temperature":{"type":["number","null"],"format":"double"},"tool_choice":{},"tools":{"type":["array","null"],"items":{}},"top_p":{"type":["number","null"],"format":"double"},"user":{"type":["string","null"]}}}],"description":"OpenAI-compatible chat completion request.\nUses `deny_unknown_fields = false` (serde default) so that SDK-specific\nfields like `stream_options`, `logprobs`, `top_logprobs`, `logit_bias`,\n`parallel_tool_calls`, etc. are silently accepted without breaking."},"ChatCompletionResponse":{"type":"object","required":["id","object","created","model","choices"],"properties":{"choices":{"type":"array","items":{"$ref":"#/components/schemas/ChatCompletionChoice"}},"created":{"type":"integer","format":"int64"},"id":{"type":"string"},"model":{"type":"string"},"object":{"type":"string"},"usage":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/UsageInfo"}]}}},"ChatMessage":{"type":"object","required":["role"],"properties":{"content":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/MessageContent"}]},"name":{"type":["string","null"]},"role":{"type":"string"},"tool_call_id":{"type":["string","null"]},"tool_calls":{"type":["array","null"],"items":{}}}},"ChatReadinessResponse":{"type":"object","description":"What still has to be true before an AI chat can run a turn in this project.\n\nThe three gates are independent and fail for different reasons with different\nfixes, so they are reported separately rather than collapsed into one boolean:\nan instance admin configures a provider (instance-wide), while the two toggles\nare per-project. Collapsing them would leave the user with \"AI unavailable\"\nand no idea which of three places to go.","required":["ai_configured","chat_enabled","write_actions_enabled"],"properties":{"ai_configured":{"type":"boolean","description":"An AI provider is configured on this instance. Fixed in\nSettings → AI Providers; instance-wide, not per project."},"chat_enabled":{"type":"boolean","description":"The per-project read-only chat toggle is on (the default)."},"write_actions_enabled":{"type":"boolean","description":"The per-project write-actions opt-in is on. Required for any flow where\nthe assistant *proposes* changes; irrelevant for read-only questions."}}},"ChildBackupEntryResponse":{"type":"object","description":"A single child backup entry in the `GET /backups/{id}/children` response.\n\nEach entry corresponds to one `external_service_backups` row joined with\n`external_services`, providing service metadata without a second request.","required":["id","service_id","service_name","service_type","state","backup_type","started_at","s3_location","compression_type"],"properties":{"backup_type":{"type":"string","description":"Backup variant (e.g. \"full\", \"incremental\")."},"compression_type":{"type":"string","description":"Compression algorithm used (e.g. \"gzip\", \"lz4\")."},"error_message":{"type":["string","null"],"description":"Engine-reported error message when `state = \"failed\"`."},"finished_at":{"type":["string","null"],"description":"When the child backup finished, if known.","example":"2025-01-15T14:35:00.456Z"},"id":{"type":"integer","format":"int32","description":"Row ID from `external_service_backups`."},"s3_location":{"type":"string","description":"Object key or `s3://` URL where the backup data lives."},"service_id":{"type":"integer","format":"int32","description":"FK to `external_services.id`."},"service_name":{"type":"string","description":"Human-readable name of the external service (e.g. \"redis-prod\")."},"service_type":{"type":"string","description":"Service type string (e.g. \"postgres\", \"redis\", \"mongodb\", \"s3\").","example":"postgres"},"size_bytes":{"type":["integer","null"],"format":"int64","description":"Size of the child backup in bytes, if available."},"started_at":{"type":"string","description":"When the child backup started (RFC 3339).","example":"2025-01-15T14:30:00.123Z"},"state":{"type":"string","description":"Current state: \"pending\" | \"running\" | \"completed\" | \"failed\"."}}},"ChildBackupListResponse":{"type":"object","description":"Response body for `GET /backups/{id}/children`.\n\nReturns an empty `children` list (not 404) when the parent backup has no\nchild records (e.g. control-plane backups).","required":["children"],"properties":{"children":{"type":"array","items":{"$ref":"#/components/schemas/ChildBackupEntryResponse"},"description":"Zero or more child backup entries ordered by `external_service_backups.id` ASC."}}},"CleanupExpiredBackupsRequest":{"type":"object","properties":{"expected_backup_ids":{"type":["array","null"],"items":{"type":"string"},"description":"Exact candidates returned by the dry run. Execution fails if the\nretention selection has changed since preview."}}},"CliDeviceApproveRequest":{"type":"object","required":["user_code"],"properties":{"user_code":{"type":"string"}}},"CliDeviceApproveResponse":{"type":"object","required":["user_code","status"],"properties":{"status":{"type":"string"},"user_code":{"type":"string"}}},"CliDeviceLookupResponse":{"type":"object","required":["user_code","status","expires_at"],"properties":{"client_name":{"type":["string","null"]},"expires_at":{"type":"string","format":"date-time"},"requested_ip":{"type":["string","null"]},"status":{"type":"string","description":"`pending` | `approved` | `denied` | `expired`."},"user_code":{"type":"string"}}},"CliDevicePollRequest":{"type":"object","required":["device_code"],"properties":{"device_code":{"type":"string"}}},"CliDevicePollResponse":{"oneOf":[{"type":"object","description":"Still waiting on the user to approve in the browser.","required":["status"],"properties":{"status":{"type":"string","enum":["authorization_pending"]}}},{"type":"object","description":"CLI is polling faster than the server-suggested interval.","required":["status"],"properties":{"status":{"type":"string","enum":["slow_down"]}}},{"type":"object","description":"User denied the request in the browser.","required":["status"],"properties":{"status":{"type":"string","enum":["access_denied"]}}},{"type":"object","description":"The session has expired without approval.","required":["status"],"properties":{"status":{"type":"string","enum":["expired_token"]}}},{"type":"object","description":"The session was approved; this is the only response that carries\nthe API key. The key is returned exactly once and then cleared\nfrom the session row.","required":["user_id","email","role","api_key","key_prefix","status"],"properties":{"api_key":{"type":"string"},"email":{"type":"string"},"expires_at":{"type":["string","null"],"format":"date-time"},"key_prefix":{"type":"string"},"role":{"type":"string"},"status":{"type":"string","enum":["approved"]},"user_id":{"type":"integer","format":"int32"}}}]},"CliDeviceStartRequest":{"type":"object","properties":{"client_name":{"type":["string","null"],"description":"Friendly hostname / client identifier shown in the browser approval\nscreen. Sanitized before display.","example":"dviejo-mac.local"}}},"CliDeviceStartResponse":{"type":"object","required":["device_code","user_code","verification_uri","verification_uri_complete","expires_in","interval"],"properties":{"device_code":{"type":"string","description":"Opaque secret the CLI polls with. Never display to a human."},"expires_in":{"type":"integer","format":"int64","description":"Seconds until the device_code expires."},"interval":{"type":"integer","format":"int64","description":"Suggested polling interval, in seconds."},"user_code":{"type":"string","description":"Short human-readable code the user types into the browser.","example":"ABCD-1234"},"verification_uri":{"type":"string","description":"Base verification URL — the CLI may display this when the\npre-filled URL is too long to be useful.","example":"https://temps.example.com/cli-login"},"verification_uri_complete":{"type":"string","description":"`verification_uri` with `user_code` pre-filled. Open this directly.","example":"https://temps.example.com/cli-login/ABCD-1234"}}},"CliLoginRequest":{"type":"object","required":["username","password"],"properties":{"password":{"type":"string"},"username":{"type":"string"}}},"CloudProvider":{"type":"string","description":"Cloud provider detected from node metadata","enum":["aws","gcp","azure","hetzner","digitalocean","other"]},"CloudflareConfig":{"type":"object","description":"Configuration for a Cloudflare Email Sending notification provider.\n\nNotifications are delivered through Cloudflare's transactional Email Sending\nAPI. Only the account, token, sender and recipients are configured here —\nsubject and body are derived from each notification.","required":["account_id","api_token","from_address","to_addresses"],"properties":{"account_id":{"type":"string","description":"Cloudflare account id that owns the Email Sending configuration.","example":"023e105f4ecef8ad9ca31a8372d0c353"},"api_token":{"type":"string","description":"Cloudflare API token with the Email Sending permission. Encrypted at\nrest and masked in normal API responses."},"from_address":{"type":"string","description":"Verified sender address (must belong to a domain enabled for Cloudflare\nEmail Sending).","example":"welcome@infracf.example.com"},"from_name":{"type":["string","null"],"description":"Optional human-friendly sender name shown in the recipient's inbox."},"to_addresses":{"type":"array","items":{"type":"string"},"description":"Recipients that should receive the notification."}}},"ClusterCapacity":{"type":"object","description":"Total cluster capacity (sum of node allocatable resources)","required":["node_count","cpu_millis","memory_mb"],"properties":{"cpu_millis":{"type":"integer","format":"int64","description":"Total allocatable CPU in millicores"},"memory_mb":{"type":"integer","format":"int64","description":"Total allocatable memory in MB"},"node_count":{"type":"integer","description":"Number of nodes","minimum":0}}},"ClusterDnsSettings":{"type":"object","description":"Cluster-DNS resolver settings (ADR-024, experimental beta).\n\nWhen `enabled`, the Temps control plane starts a Hickory DNS resolver and\ninjects it as the first nameserver into every deployed container via\n`HostConfig.Dns` — giving containers the ability to resolve `*.temps.local`\nFQDNs for service-to-service communication. Worker nodes pick this flag up\nfrom the `/api/internal/nodes/{id}/network/peers` wire response and gate\ntheir own per-node resolver the same way.\n\n**Default: `false` (disabled).**\n\nWhy disabled by default: a production incident showed that when the injected\nHickory resolver was slow or transiently unresponsive for a non-`*.temps.local`\n(external) hostname, glibc's resolver cycled through all three nameservers\n(`172.20.0.1`, `1.1.1.1`, `8.8.8.8`) at ~5 s timeout × 2 attempts each,\ncausing 22–27 s delays for outbound TCP connections. Disabling the injection\nrestores Docker's embedded DNS as the sole resolver, eliminating that failure\nmode. Operators running single/multi-node installs that depend on\n`*.temps.local` resolution must explicitly opt in by setting `enabled: true`.\n\n`bool` defaults to `false` in Rust and JSON (`#[serde(default)]`), so the\nsafe-off behaviour is automatic for new installs and legacy settings rows.","properties":{"enabled":{"type":"boolean","description":"Master switch. When `false` (default), no custom DNS is injected into\ncontainers — they use Docker's embedded DNS which forwards to the host's\nown `resolv.conf`. When `true`, the control-plane Hickory resolver is\nstarted and its bridge IP is injected as the first nameserver so\n`*.temps.local` FQDNs resolve inside containers.","default":false,"example":false}}},"ClusterHealthReportResponse":{"type":"object","description":"Response body for `GET /external-services/{id}/cluster-health`.","required":["checked_at","monitor_response_ms","members"],"properties":{"checked_at":{"type":"string","description":"ISO-8601 wall-clock when the report was generated.","example":"2025-10-12T12:15:47.609192Z"},"members":{"type":"array","items":{"$ref":"#/components/schemas/ClusterMemberHealthResponse"}},"monitor_error":{"type":["string","null"],"description":"Set when the monitor itself was unreachable. UI shows a banner."},"monitor_response_ms":{"type":"integer","format":"int64","description":"Round-trip to query the monitor (ms)."}}},"ClusterMemberHealthResponse":{"type":"object","description":"One row in the cluster Members table — see `GET /external-services/{id}/cluster-health`.","required":["nodename","nodehost","nodeport","reported_state","goal_state","health","seconds_since_report","candidate_priority","replication_quorum"],"properties":{"candidate_priority":{"type":"integer","format":"int32"},"goal_state":{"type":"string","description":"What the monitor *wants* the node to be. Differs from\n`reported_state` mid-transition (failover, demotion, etc.)."},"health":{"type":"integer","format":"int32","description":"pg_auto_failover liveness signal: `1` healthy, `0` unknown\n(no recent report), `-1` unhealthy."},"nodehost":{"type":"string"},"nodename":{"type":"string"},"nodeport":{"type":"integer","format":"int32"},"replay_lag_ms":{"type":["integer","null"],"format":"int64","description":"`replay_lag` from `pg_stat_replication`, in milliseconds."},"replication_quorum":{"type":"boolean"},"reported_state":{"type":"string","description":"What the node *last told the monitor* it was. Stale during outages."},"seconds_since_report":{"type":"integer","format":"int64","description":"Wall-clock seconds since the node last reported in."},"sync_state":{"type":["string","null"],"description":"`sync` / `quorum` / `async` for secondaries; `null` for the primary."}}},"ClusterMemberRequest":{"type":"object","description":"Request spec for a single cluster member.","required":["role"],"properties":{"node_id":{"type":["integer","null"],"format":"int32","description":"Target worker node ID. Omit or null to run on the control plane."},"role":{"type":"string","description":"Service-type-specific role (e.g., \"monitor\", \"primary\", \"replica\")","example":"primary"}}},"CmdBody":{"type":"object","required":["command"],"properties":{"args":{"type":"array","items":{"type":"string"},"description":"Arguments to pass to the binary. Defaults to empty."},"command":{"type":"string","description":"Binary name (argv[0]) — e.g. `\"ls\"`, `\"node\"`. The SDK sends this\nseparately from `args`."},"cwd":{"type":["string","null"],"description":"Working directory override."},"env":{"type":"object","description":"Extra env vars.","additionalProperties":{"type":"string"},"propertyNames":{"type":"string"}},"sudo":{"type":"boolean","description":"When true, the SDK runs the command privileged. We ignore it today\n— the underlying provider always runs as the sandbox's own user."},"wait":{"type":"boolean","description":"When true, the response is an `application/x-ndjson` stream where\nthe first line is the running-command envelope and the second line\nis the finished-command envelope with `exitCode`."}}},"CmdInner":{"type":"object","description":"Inner `command` object — matches the SDK's zod validator exactly.\n`exitCode` is `null` until the command terminates; `startedAt` is Unix\nepoch milliseconds.","required":["id","name","args","cwd","sandboxId","startedAt"],"properties":{"args":{"type":"array","items":{"type":"string"}},"cwd":{"type":"string"},"exitCode":{"type":["integer","null"],"format":"int32"},"id":{"type":"string"},"name":{"type":"string"},"sandboxId":{"type":"string"},"startedAt":{"type":"integer","format":"int64"}}},"CmdKillBody":{"type":"object","description":"SDK-shaped kill body. The SDK sends `{signal: AbortSignal}` but only\nuses the signal for HTTP request abortion client-side; there's no\nsignal name on the wire.","properties":{"force":{"type":"boolean","description":"Optional: when true, SIGKILL instead of SIGTERM."}}},"CmdResponse":{"type":"object","description":"`@vercel/sandbox` envelope: `{ command: {...} }`.","required":["command"],"properties":{"command":{"$ref":"#/components/schemas/CmdInner"}}},"CommitExistsResponse":{"type":"object","required":["exists"],"properties":{"commit":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/CommitInfo","description":"Commit metadata when the requested SHA exists."}]},"commit_sha":{"type":["string","null"]},"exists":{"type":"boolean"}}},"CommitInfo":{"type":"object","required":["sha","message","author","author_email","date"],"properties":{"author":{"type":"string","description":"Author name"},"author_email":{"type":"string","description":"Author email"},"date":{"type":"string","format":"date-time","description":"Commit date in ISO 8601 format","example":"2025-10-12T12:15:47.609192Z"},"message":{"type":"string","description":"Commit message"},"sha":{"type":"string","description":"Commit SHA hash"}}},"CommitListResponse":{"type":"object","required":["commits"],"properties":{"commits":{"type":"array","items":{"$ref":"#/components/schemas/CommitInfo"}}}},"Comparator":{"type":"string","description":"Comparator for static/forecast threshold detectors. Serializes to the\nkeyword forms `gt|gte|lt|lte` (NOT the SQL operators used by\n`temps-monitoring::compare`).","enum":["gt","gte","lt","lte"]},"ComposePublicPort":{"type":"object","description":"A port that should be exposed publicly through the proxy for a compose service.","required":["service","port"],"properties":{"port":{"type":"integer","format":"int32","description":"Container port to expose (e.g. 8123)","minimum":0},"service":{"type":"string","description":"Compose service name (e.g. \"web\", \"clickhouse\")"}}},"ConnectionListQuery":{"type":"object","properties":{"direction":{"type":["string","null"]},"page":{"type":["integer","null"],"format":"int64","minimum":0},"per_page":{"type":["integer","null"],"format":"int64","minimum":0},"sort":{"type":["string","null"]}}},"ConnectionListResponse":{"type":"object","required":["connections","total_count","page","per_page"],"properties":{"connections":{"type":"array","items":{"$ref":"#/components/schemas/ConnectionResponse"}},"page":{"type":"integer","format":"int64","minimum":0},"per_page":{"type":"integer","format":"int64","minimum":0},"total_count":{"type":"integer","minimum":0}}},"ConnectionResponse":{"type":"object","required":["id","provider_id","account_name","account_type","is_active","is_expired","syncing","synced_repository_count","health_status","consecutive_health_failures","created_at","updated_at"],"properties":{"account_name":{"type":"string"},"account_type":{"type":"string"},"consecutive_health_failures":{"type":"integer","format":"int32"},"created_at":{"type":"string","format":"date-time"},"health_message":{"type":["string","null"],"description":"Human-readable reason when health_status is \"unhealthy\"; null otherwise."},"health_status":{"type":"string","description":"Current health status: \"healthy\", \"unhealthy\", or \"unknown\"."},"id":{"type":"integer","format":"int32"},"installation_id":{"type":["string","null"]},"is_active":{"type":"boolean"},"is_expired":{"type":"boolean"},"last_health_check_at":{"type":["string","null"],"format":"date-time"},"last_synced_at":{"type":["string","null"],"format":"date-time"},"provider_id":{"type":"integer","format":"int32"},"synced_repository_count":{"type":"integer","format":"int32","description":"Running count of repositories persisted by the current (or most\nrecent) sync. Resets to 0 when a new sync begins; useful for showing\nlive progress on large syncs."},"syncing":{"type":"boolean"},"updated_at":{"type":"string","format":"date-time"},"user_id":{"type":["integer","null"],"format":"int32"}}},"ConnectionTestResult":{"type":"object","description":"Connection test result","required":["success","message"],"properties":{"message":{"type":"string"},"success":{"type":"boolean"}}},"ConsoleEventPayload":{"type":"object","description":"Payload for server-side event ingestion via the console API.\n\nThe app backend reads the encrypted `_temps_visitor_id` and `_temps_sid`\ncookie values from the user's request and forwards them here.\nTemps decrypts them server-side to resolve visitor/session identity.","required":["event_name","environment_id","deployment_id"],"properties":{"deployment_id":{"type":"integer","format":"int32","description":"Deployment ID to attribute the event to"},"environment_id":{"type":"integer","format":"int32","description":"Environment ID to attribute the event to"},"event_data":{"description":"Arbitrary JSON event data"},"event_name":{"type":"string","description":"Event name (e.g. \"purchase\", \"signup\", custom event names)"},"request_path":{"type":"string","description":"Page path context (defaults to \"/\")"},"request_query":{"type":"string","description":"Query string context"},"session_id":{"type":["string","null"],"description":"Encrypted `_temps_sid` cookie value from the user's browser"},"visitor_id":{"type":["string","null"],"description":"Encrypted `_temps_visitor_id` cookie value from the user's browser"}}},"ContainerActionResponse":{"type":"object","description":"Response indicating success of container state change","required":["container_id","container_name","action","status","message"],"properties":{"action":{"type":"string"},"container_id":{"type":"string"},"container_name":{"type":"string"},"message":{"type":"string"},"status":{"type":"string"}}},"ContainerDetailResponse":{"type":"object","description":"Detailed container information with environment variables and metrics","required":["id","container_id","container_name","image_name","status","deployment_id","created_at","deployed_at","container_port","environment_variables"],"properties":{"container_id":{"type":"string"},"container_name":{"type":"string"},"container_port":{"type":"integer","format":"int32","description":"Port inside the container"},"cpu_limit_cores":{"type":["number","null"],"format":"double","description":"CPU limit in whole cores (e.g. 1.0). None when no limit is configured."},"created_at":{"type":"string","example":"2025-10-12T12:15:47.609192Z"},"deployed_at":{"type":"string","example":"2025-10-12T12:15:47.609192Z"},"deployment_id":{"type":"integer","format":"int32"},"environment_variables":{"type":"array","items":{"$ref":"#/components/schemas/EnvVarResponse"},"description":"Environment variables (sensitive values masked)"},"error_message":{"type":["string","null"],"description":"Free-form error string from Docker's container state on exit."},"exit_code":{"type":["integer","null"],"format":"int32","description":"Process exit code reported by Docker. None while still running."},"exit_reason":{"type":["string","null"],"description":"Human-readable reason the container exited."},"finished_at":{"type":["string","null"],"description":"When the container exited (Docker's FinishedAt). None while running.","example":"2025-10-12T12:16:47.609192Z"},"host_port":{"type":["integer","null"],"format":"int32","description":"Port on the host machine"},"id":{"type":"integer","format":"int32"},"image_name":{"type":"string"},"oom_killed":{"type":["boolean","null"],"description":"True when Docker's OOM killer terminated the container."},"ready_at":{"type":["string","null"],"example":"2025-10-12T12:16:47.609192Z"},"resource_limits":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/ResourceLimitsResponse","description":"Resource limits"}]},"restart_count":{"type":["integer","null"],"format":"int64","description":"Container restart count from Docker"},"service_name":{"type":["string","null"],"description":"Compose service name (e.g. \"web\", \"redis\"). None for single-container deployments."},"service_url":{"type":["string","null"],"description":"Per-service URL for compose deployments"},"started_at":{"type":["string","null"],"description":"When the container's main process most recently started.","example":"2025-10-12T12:15:50.000000Z"},"status":{"type":"string"}}},"ContainerEnvironmentVariableValueResponse":{"type":"object","required":["value"],"properties":{"value":{"type":"string"}}},"ContainerInfoResponse":{"type":"object","required":["container_id","container_name","image_name","status","created_at"],"properties":{"container_id":{"type":"string"},"container_name":{"type":"string"},"cpu_limit_cores":{"type":["number","null"],"format":"double","description":"CPU limit in whole cores (e.g. 1.0). None when no limit is configured."},"created_at":{"type":"string","example":"2025-10-12T12:15:47.609192Z"},"error_message":{"type":["string","null"],"description":"Free-form error string from Docker's container state on exit."},"exit_code":{"type":["integer","null"],"format":"int32","description":"Process exit code reported by Docker. None while still running."},"exit_reason":{"type":["string","null"],"description":"Human-readable reason the container exited (e.g. \"OOMKilled\",\n\"Killed by SIGKILL (exit code 137)\", \"Exit code 1\"). None while running."},"finished_at":{"type":["string","null"],"description":"When the container exited (Docker's FinishedAt). None while running.","example":"2025-10-12T12:16:47.609192Z"},"image_name":{"type":"string"},"node_name":{"type":["string","null"],"description":"Node name where this container is running. None for local (single-node) deployments."},"oom_killed":{"type":["boolean","null"],"description":"True when Docker's OOM killer terminated the container."},"restart_count":{"type":["integer","null"],"format":"int64","description":"Container restart count from Docker. The UI shows a chip when this is\n> 0 so a crash loop is visible without opening detail."},"service_name":{"type":["string","null"],"description":"Compose service name (e.g. \"web\", \"redis\"). None for single-container deployments."},"service_url":{"type":["string","null"],"description":"Per-service URL for compose deployments (e.g. \"https://web-myapp.localho.st\")"},"started_at":{"type":["string","null"],"description":"When the container's main process most recently started. The UI uses\nthis for the uptime label so the count resets when a container is\nrestarted in place. None for containers that never started.","example":"2025-10-12T12:15:50.000000Z"},"status":{"type":"string"}}},"ContainerInventoryItem":{"type":"object","description":"A container reported by the agent during heartbeat reconciliation.","required":["container_id","container_name"],"properties":{"container_id":{"type":"string","description":"Docker container ID"},"container_name":{"type":"string","description":"Docker container name"}}},"ContainerListResponse":{"type":"object","required":["containers","total"],"properties":{"containers":{"type":"array","items":{"$ref":"#/components/schemas/ContainerInfoResponse"}},"total":{"type":"integer","minimum":0}}},"ContainerLogSettings":{"type":"object","description":"Docker container log rotation settings\nControls the `--log-opt max-size` and `--log-opt max-file` for containers","properties":{"max_file":{"type":"integer","format":"int32","description":"Maximum number of rotated log files to keep (e.g., 3 means up to 3 x max_size total)","default":3,"example":3,"minimum":0},"max_size":{"type":"string","description":"Maximum size of each log file (e.g., \"50m\", \"100m\", \"1g\")\nDocker default is unlimited; we default to \"50m\" to prevent disk exhaustion","default":"50m","example":"50m"},"service_max_file":{"type":"integer","format":"int32","description":"Maximum rotated log files for external service containers","default":3,"example":3,"minimum":0},"service_max_size":{"type":"string","description":"Maximum size for external service container logs (postgres, redis, etc.)\nDefaults to \"20m\" since services are typically less verbose than app containers","default":"20m","example":"20m"}}},"ContainerLogsQuery":{"type":"object","properties":{"container_name":{"type":["string","null"],"description":"Optional container name to get logs from (if deployment has multiple containers)"},"end_date":{"type":["integer","null"],"format":"int64"},"follow":{"type":"boolean","description":"Follow log output in real-time (default: true for backward compatibility)"},"start_date":{"type":["integer","null"],"format":"int64"},"tail":{"type":["string","null"]},"timestamps":{"type":"boolean","description":"Include timestamps in log output (default: false)"}}},"ContainerMetricHistoryPoint":{"type":"object","description":"One bucketed data point of a container resource metric time series.","required":["time","value"],"properties":{"time":{"type":"string","description":"Bucket timestamp (ISO 8601 with `Z` suffix).","example":"2025-10-12T12:15:00+00:00"},"value":{"type":"number","format":"double","description":"Averaged metric value for the bucket."}}},"ContainerMetricsHistoryQuery":{"type":"object","description":"Query parameters for the container metrics history endpoint.","required":["metric"],"properties":{"metric":{"type":"string","description":"Dotted metric name, e.g. `container.cpu_percent` or\n`container.memory_used_bytes`."},"range":{"type":"string","description":"Time window: `1h`, `6h`, `24h`, or `7d` (defaults to `1h`)."}}},"ContainerMetricsResponse":{"type":"object","description":"Container resource metrics (CPU, memory usage)","required":["container_id","container_name","cpu_percent","memory_bytes","network_rx_bytes","network_tx_bytes","timestamp"],"properties":{"container_id":{"type":"string"},"container_name":{"type":"string"},"cpu_limit_cores":{"type":["number","null"],"format":"double","description":"CPU limit in whole cores (e.g. 1.0). None = no limit."},"cpu_percent":{"type":"number","format":"double","description":"CPU usage as a multi-core percentage (Docker convention: 200 = 2 cores\nfully pinned). Divide by 100 to get cores used."},"memory_bytes":{"type":"integer","format":"int64","description":"Memory usage in bytes","minimum":0},"memory_limit_bytes":{"type":["integer","null"],"format":"int64","description":"Memory limit in bytes (if set)","minimum":0},"memory_percent":{"type":["number","null"],"format":"double","description":"Memory usage percentage (0-100) if limit is set"},"network_rx_bytes":{"type":"integer","format":"int64","description":"Network bytes received","minimum":0},"network_tx_bytes":{"type":"integer","format":"int64","description":"Network bytes transmitted","minimum":0},"timestamp":{"type":"string","description":"Timestamp of metrics collection","example":"2025-10-12T12:15:47.609192Z"}}},"ContainerResponse":{"type":"object","required":["name","container_type","can_contain_containers","can_contain_entities","metadata"],"properties":{"can_contain_containers":{"type":"boolean","description":"Can this container hold other containers?","example":true},"can_contain_entities":{"type":"boolean","description":"Can this container hold entities (tables, collections, etc.)?","example":false},"child_container_type":{"type":["string","null"],"description":"Type of child containers (if can_contain_containers is true)","example":"schema"},"container_type":{"type":"string","description":"Container type (database, schema, keyspace, bucket, etc.)","example":"database"},"entity_count_hint":{"type":["string","null"],"description":"Hint for UI on expected entity count (small = sidebar, large = pagination)","example":"large"},"entity_type_label":{"type":["string","null"],"description":"Label for entity type (if can_contain_entities is true)","example":"table"},"metadata":{"description":"Additional metadata"},"name":{"type":"string","description":"Container name","example":"mydb"}}},"ContainerRuntimeInfo":{"type":"object","description":"Snapshot of a container's lifecycle state from `docker inspect`.\n`restart_count` and `oom_killed` are the load-bearing fields when\ndiagnosing crash loops — the kernel OOM killer never reaches the\napplication's logs, so seeing `oom_killed=true` is the only signal\nthat a memory limit was the cause.","required":["role","container_name","resource_limits"],"properties":{"container_id":{"type":["string","null"],"description":"Container Docker id, when present. None = container does not exist\n(was never created or was removed externally)."},"container_name":{"type":"string","description":"Stable name of the Docker container (e.g. `postgres-mydb`)."},"exit_code":{"type":["integer","null"],"format":"int64","description":"Last container exit code, when known. Non-zero = unclean stop."},"finished_at":{"type":["string","null"],"description":"ISO-8601 timestamp of the most recent termination, when known."},"image":{"type":["string","null"],"description":"Currently-effective Docker image (e.g. `gotempsh/postgres-walg:18-bookworm`)."},"oom_killed":{"type":["boolean","null"],"description":"True when the container's last termination was caused by the\nkernel OOM killer. Set if the user enabled hard memory limits\nand the working set exceeded them."},"resource_limits":{"$ref":"#/components/schemas/ServiceResourceLimits","description":"Currently-applied resource limits read off the container's\n`HostConfig`. Compare this against the user-configured limits to\ndetect drift (an old container that never picked up new caps)."},"restart_count":{"type":["integer","null"],"format":"int64","description":"Total restarts since the container was created. Useful for\ndetecting crash loops — a steady stream means something is killing\nthe container repeatedly (frequently OOM)."},"role":{"type":"string","description":"`service_members.role` for cluster members; \"standalone\" otherwise."},"started_at":{"type":["string","null"],"description":"ISO-8601 timestamp of when the container last started. None when\nit has never started (i.e. created but never run)."},"status":{"type":["string","null"],"description":"Bollard container state (\"running\", \"exited\", \"dead\", etc.). None\nwhen the container does not exist."}}},"ContainerStatsSample":{"type":"object","description":"Live resource usage sample for a single container.\n\n`cpu_percent` is computed by Docker's standard formula:\n ((cpu_delta / system_delta) * online_cpus) * 100\n`memory_percent` is `(memory_usage / memory_limit) * 100` — when no\nmemory limit is set the limit reported by Docker is the host's total\nRAM, so a 5% reading means \"5% of host RAM\", not \"5% of allocated\".","required":["role","container_name"],"properties":{"container_name":{"type":"string"},"cpu_percent":{"type":["number","null"],"format":"double","description":"CPU usage as a percentage. `None` when the container is not running\n(Docker returns no usable counters)."},"memory_limit_bytes":{"type":["integer","null"],"format":"int64","description":"Memory limit in bytes (host RAM if no limit set).","minimum":0},"memory_percent":{"type":["number","null"],"format":"double","description":"Memory usage as a percentage of `memory_limit_bytes`."},"memory_usage_bytes":{"type":["integer","null"],"format":"int64","description":"Resident memory usage in bytes.","minimum":0},"online_cpus":{"type":["integer","null"],"format":"int32","description":"Number of cores Docker observed at sample time. Used by the UI\nto label \"x/y cores\" instead of just a percent.","minimum":0},"role":{"type":"string"}}},"ContentPart":{"type":"object","required":["type"],"properties":{"image_url":{},"text":{"type":["string","null"]},"type":{"type":"string"}}},"ContextLine":{"type":"object","description":"A line in context response","required":["timestamp","level","message","line_offset","is_match"],"properties":{"fields":{},"is_match":{"type":"boolean","description":"Whether this line matched the original search"},"level":{"$ref":"#/components/schemas/LogLevel"},"line_offset":{"type":"integer","format":"int32"},"message":{"type":"string"},"timestamp":{"type":"string"}}},"ContextLogsRequest":{"type":"object","required":["chunk_id","line_offset"],"properties":{"chunk_id":{"type":"string"},"line_offset":{"type":"integer","format":"int32"},"lines":{"type":["integer","null"],"format":"int32","description":"Number of context lines before and after (default: 25)","minimum":0}}},"ContextLogsResponse":{"type":"object","required":["lines","target_index"],"properties":{"lines":{"type":"array","items":{"$ref":"#/components/schemas/ContextLine"}},"target_index":{"type":"integer","minimum":0}}},"ConversationDetailResponse":{"allOf":[{"$ref":"#/components/schemas/ConversationResponse"},{"type":"object","required":["messages"],"properties":{"messages":{"type":"array","items":{"$ref":"#/components/schemas/MessageResponse"},"description":"Turns oldest-first. The `system` seed message is omitted (internal)."}}}]},"ConversationResponse":{"type":"object","required":["public_id","context_type","context_id","status","created_at","last_activity_at"],"properties":{"context_id":{"type":"string"},"context_type":{"type":"string"},"created_at":{"type":"string"},"last_activity_at":{"type":"string"},"public_id":{"type":"string"},"status":{"type":"string"},"title":{"type":["string","null"]}}},"ConversationSummary":{"type":"object","description":"A conversation summary grouping related AI invocations.","required":["conversation_id","message_count","total_input_tokens","total_output_tokens","total_tokens","total_cost_microcents","avg_latency_ms","models_used","first_at","last_at"],"properties":{"avg_latency_ms":{"type":"number","format":"double"},"conversation_id":{"type":"string"},"first_at":{"type":"string"},"last_at":{"type":"string"},"message_count":{"type":"integer","format":"int64"},"models_used":{"type":"array","items":{"type":"string"}},"total_cost_microcents":{"type":"integer","format":"int64"},"total_input_tokens":{"type":"integer","format":"int64"},"total_output_tokens":{"type":"integer","format":"int64"},"total_tokens":{"type":"integer","format":"int64"}}},"ConversationsQueryParams":{"type":"object","properties":{"from":{"type":["string","null"],"description":"ISO 8601 start time (defaults to 24h ago)"},"limit":{"type":["integer","null"],"format":"int64","description":"Max results (defaults to 50, max 100)","minimum":0},"model":{"type":["string","null"],"description":"Filter by model name"},"tags":{"type":["string","null"],"description":"Filter by tags (comma-separated, AND logic)"},"to":{"type":["string","null"],"description":"ISO 8601 end time (defaults to now)"},"user_id":{"type":["integer","null"],"format":"int32","description":"Filter by user ID"}}},"CopyBlobRequest":{"type":"object","description":"Request to copy a blob","required":["fromUrl","toPathname"],"properties":{"fromUrl":{"type":"string","description":"Source blob URL or pathname","example":"/api/blob/10/images/avatar.png"},"projectId":{"type":["integer","null"],"format":"int32","description":"Project ID (required for API key/session auth, optional for deployment tokens)","example":1},"toPathname":{"type":"string","description":"Destination pathname","example":"images/avatar-copy.png"}}},"CostAnalysis":{"type":"object","description":"Full cluster cost + rightsizing analysis attached to an import plan.","required":["nodes","capacity","requested","usage_source","overprovisioning","recommendation","notes"],"properties":{"actual_usage":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/ResourceFootprint","description":"Measured usage from the metrics API (`metrics.k8s.io`).\n`None` when metrics-server is not installed."}]},"capacity":{"$ref":"#/components/schemas/ClusterCapacity","description":"Total cluster capacity (sum of node allocatable resources)"},"control_plane_monthly_usd":{"type":["number","null"],"format":"double","description":"Managed control-plane fee included in `current_monthly_usd` (EKS/GKE\ncharge ~$73/mo per cluster). `None` when not applicable/unknown."},"current_monthly_usd":{"type":["number","null"],"format":"double","description":"Estimated total infrastructure cost per month in USD (compute nodes +\ncontrol-plane fee). `None` when no node could be priced."},"nodes":{"type":"array","items":{"$ref":"#/components/schemas/NodeCostInfo"},"description":"Per-node inventory with price estimates where the instance type is known"},"notes":{"type":"array","items":{"type":"string"},"description":"Honesty notes: what could not be measured, which numbers are\nestimates, and any assumptions made. Always shown to the user."},"overprovisioning":{"$ref":"#/components/schemas/OverprovisioningAssessment","description":"Requests-vs-capacity-vs-usage assessment"},"provider":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/CloudProvider","description":"Detected cloud provider (from node `providerID` prefixes)"}]},"recommendation":{"$ref":"#/components/schemas/TargetRecommendation","description":"The temps/Hetzner target sizing and savings estimate"},"requested":{"$ref":"#/components/schemas/ResourceFootprint","description":"Sum of pod resource *requests* across running pods — what the\nscheduler has reserved, i.e. what the cluster is sized for."},"usage_source":{"$ref":"#/components/schemas/UsageSource","description":"How the usage numbers were obtained (drives UI wording)"}}},"CreateAlertRuleRequest":{"type":"object","required":["name","trigger_type"],"properties":{"cooldown_minutes":{"type":"integer","format":"int32","description":"Minimum minutes between notifications for same rule+group"},"enabled":{"type":"boolean"},"environment_filter":{"type":["integer","null"],"format":"int32","description":"Optional environment ID to filter alerts"},"error_level_filter":{"type":["string","null"],"description":"Optional error type/level filter"},"name":{"type":"string"},"notification_priority":{"type":"string","description":"Notification priority: Low, Normal, High, Critical"},"trigger_config":{"description":"Trigger-specific configuration (e.g., {\"count\": 100, \"window_minutes\": 60} for frequency)"},"trigger_type":{"type":"string","description":"Trigger type: new_issue, regression, frequency, new_user, user_count, status_change"}}},"CreateApiKeyRequest":{"type":"object","required":["name","role_type"],"properties":{"expires_at":{"type":["string","null"],"format":"date-time","example":"2024-12-31T23:59:59Z"},"name":{"type":"string"},"permissions":{"type":["array","null"],"items":{"type":"string"},"example":["projects:read","deployments:read"]},"role_type":{"type":"string","example":"admin"}}},"CreateApiKeyResponse":{"type":"object","required":["id","name","key_prefix","role_type","api_key","created_at"],"properties":{"api_key":{"type":"string"},"created_at":{"type":"string","format":"date-time","example":"2024-01-01T00:00:00Z"},"expires_at":{"type":["string","null"],"format":"date-time","example":"2024-12-31T23:59:59Z"},"id":{"type":"integer","format":"int32"},"key_prefix":{"type":"string"},"name":{"type":"string"},"permissions":{"type":["array","null"],"items":{"type":"string"}},"role_type":{"type":"string"}}},"CreateBackupScheduleRequest":{"type":"object","required":["name","backup_type","retention_period","schedule_expression","enabled","tags"],"properties":{"backup_type":{"type":"string"},"description":{"type":["string","null"]},"enabled":{"type":"boolean"},"include_control_plane":{"type":["boolean","null"],"description":"When `true` (default), every run also produces a `control_plane`\nbackup of Temps's own database. Operators who use Temps purely as\na backup orchestrator for external DBs can set this to `false` to\nkeep the run history focused on those services."},"max_runtime_secs":{"type":["integer","null"],"format":"int64","description":"Optional wall-clock timeout override for jobs created by this schedule\n(seconds). When set, overrides the engine-family default. `null` means\n\"use engine default.\" The per-job `max_runtime_secs` in\n`EnqueueJobParams` can still override this for ad-hoc triggers."},"name":{"type":"string"},"retention_period":{"type":"integer","format":"int32"},"s3_source_id":{"type":["integer","null"],"format":"int32","description":"Optional S3 source. If omitted, the current default S3 source is used."},"schedule_expression":{"type":"string"},"tags":{"type":"array","items":{"type":"string"}},"target_all_services":{"type":["boolean","null"],"description":"When `true` (default), the schedule backs up every external service\non the host — including databases created in the future. When\n`false`, the schedule backs up only the services explicitly attached\nvia `POST /backups/schedules/{id}/services`. Omit to use the default."}}},"CreateBitbucketRequest":{"type":"object","required":["name","auth"],"properties":{"auth":{"$ref":"#/components/schemas/BitbucketAuthInput","description":"Authentication credentials — either an access token or an app password."},"name":{"type":"string","description":"Display name for this provider."}}},"CreateCloudflareProviderRequest":{"type":"object","required":["name","config"],"properties":{"config":{"$ref":"#/components/schemas/CloudflareConfig"},"enabled":{"type":["boolean","null"]},"name":{"type":"string"}}},"CreateConversationRequest":{"type":"object","required":["context_type","context_id"],"properties":{"context_id":{"type":"string","description":"The entity id (ints stringified)."},"context_type":{"type":"string","description":"e.g. `\"deployment\"`."}}},"CreateDSNRequest":{"type":"object","properties":{"base_url":{"type":["string","null"]},"deployment_id":{"type":["integer","null"],"format":"int32"},"environment_id":{"type":["integer","null"],"format":"int32"},"name":{"type":["string","null"]}}},"CreateDashboardRequest":{"type":"object","required":["project_id","name","layout"],"properties":{"layout":{"$ref":"#/components/schemas/DashboardLayout"},"name":{"type":"string"},"project_id":{"type":"integer","format":"int32"}}},"CreateDeploymentTokenRequest":{"type":"object","required":["name"],"properties":{"deployment_id":{"type":["integer","null"],"format":"int32","description":"Optional deployment ID - if set, token is scoped to a specific deployment"},"environment_id":{"type":["integer","null"],"format":"int32","description":"Optional environment ID - if not set, token applies to all environments"},"expires_at":{"type":["string","null"],"format":"date-time","example":"2024-12-31T23:59:59Z"},"name":{"type":"string"},"permissions":{"type":["array","null"],"items":{"type":"string"},"description":"List of permissions (e.g., [\"visitors:enrich\", \"emails:send\"])\nIf not provided, defaults to full access","example":["visitors:enrich","emails:send"]}}},"CreateDeploymentTokenResponse":{"type":"object","required":["id","project_id","name","token_prefix","token","created_at"],"properties":{"created_at":{"type":"string","format":"date-time","example":"2024-01-01T00:00:00Z"},"deployment_id":{"type":["integer","null"],"format":"int32"},"environment_id":{"type":["integer","null"],"format":"int32"},"expires_at":{"type":["string","null"],"format":"date-time","example":"2024-12-31T23:59:59Z"},"id":{"type":"integer","format":"int32"},"name":{"type":"string"},"permissions":{"type":["array","null"],"items":{"type":"string"}},"project_id":{"type":"integer","format":"int32"},"token":{"type":"string","description":"The full token value - only returned on creation"},"token_prefix":{"type":"string"}}},"CreateDnsProviderRequest":{"type":"object","description":"Request to create a new DNS provider","required":["name","provider_type","credentials"],"properties":{"credentials":{"$ref":"#/components/schemas/DnsProviderCredentials","description":"Provider credentials"},"description":{"type":["string","null"],"description":"Optional description"},"name":{"type":"string","description":"User-friendly name","example":"My Cloudflare"},"provider_type":{"$ref":"#/components/schemas/DnsProviderType","description":"Provider type"}}},"CreateDomainRequest":{"type":"object","required":["domain"],"properties":{"challenge_type":{"type":"string","description":"Challenge type for Let's Encrypt validation. Options: \"http-01\" (default) or \"dns-01\""},"domain":{"type":"string"}}},"CreateEmailDomainRequest":{"type":"object","required":["provider_id","domain"],"properties":{"domain":{"type":"string","description":"Domain name (e.g., \"updates.example.com\")","example":"updates.example.com"},"provider_id":{"type":"integer","format":"int32","description":"Provider ID to use for this domain"}}},"CreateEmailProviderRequest":{"type":"object","required":["name","provider_type","region"],"properties":{"name":{"type":"string","description":"User-friendly name for the provider","example":"My AWS SES"},"provider_type":{"$ref":"#/components/schemas/EmailProviderTypeRoute","description":"Provider type"},"region":{"type":"string","description":"Cloud region. For SMTP this is informational only — the host/port carry the real routing.","example":"us-east-1"},"scaleway_credentials":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/ScalewayCredentialsRequest","description":"Scaleway credentials (required if provider_type is scaleway)"}]},"ses_credentials":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/SesCredentialsRequest","description":"AWS SES credentials (required if provider_type is ses)"}]},"smtp_credentials":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/SmtpCredentialsRequest","description":"Generic SMTP credentials (required if provider_type is smtp). Use when\nyou only have SMTP creds and want to import an already-set-up domain."}]},"sns_topic_arn":{"type":["string","null"],"description":"Exact SNS topic allowed to deliver SES events for this provider."}}},"CreateEnvironmentRequest":{"type":"object","required":["name","branch"],"properties":{"branch":{"type":"string"},"name":{"type":"string"},"set_as_preview":{"type":"boolean","description":"If true, set this environment as the preview environment for the project"}}},"CreateEnvironmentVariableRequest":{"type":"object","required":["key","value","environment_ids"],"properties":{"environment_ids":{"type":"array","items":{"type":"integer","format":"int32"}},"include_in_preview":{"type":"boolean","description":"Include this environment variable in preview environments (default: true)"},"is_secret":{"type":"boolean","description":"When true the variable is treated as write-only: never returned in\nplaintext from the API, masked in the UI, and updates that omit the\nvalue preserve the existing ciphertext. The flag is one-way — secret\nvars cannot be demoted back to regular vars."},"key":{"type":"string"},"value":{"type":"string"}}},"CreateExternalServiceRequest":{"type":"object","required":["name","service_type","parameters"],"properties":{"members":{"type":"array","items":{"$ref":"#/components/schemas/ClusterMemberRequest"},"description":"Cluster member specifications. Required when topology is \"cluster\"."},"name":{"type":"string"},"node_id":{"type":["integer","null"],"format":"int32","description":"Target node ID for the service. Omit or null to run on the control plane."},"parameters":{"type":"object","additionalProperties":{},"propertyNames":{"type":"string"}},"service_type":{"$ref":"#/components/schemas/ServiceTypeRoute"},"topology":{"type":"string","description":"Service topology: \"standalone\" (default) or \"cluster\" (HA multi-member).","example":"standalone"},"version":{"type":["string","null"]}}},"CreateFlagRequest":{"type":"object","required":["key","value_type","default_value"],"properties":{"client_visible":{"type":"boolean","description":"Whether the flag may be exposed on the unauthenticated same-origin\nevaluation endpoint. Defaults to `false`: flags are server-only unless\nexplicitly opted in, because targeting rules can encode business logic."},"default_value":{"description":"Served whenever evaluation cannot do better. Must match `value_type`.\n\nLeft unannotated so utoipa emits a free-form schema: a bool flag's\ndefault is `false`, not an object, and `value_type = Object` would tell\nevery generated client otherwise."},"description":{"type":["string","null"]},"key":{"type":"string","description":"Stable key used in application code. Immutable after create.","example":"checkout.v2"},"value_type":{"$ref":"#/components/schemas/FlagValueType","description":"Fixed at create: retyping would invalidate every stored value and every\ncall site."}}},"CreateFunnelRequest":{"type":"object","required":["name","steps"],"properties":{"description":{"type":["string","null"]},"name":{"type":"string"},"steps":{"type":"array","items":{"$ref":"#/components/schemas/CreateFunnelStep"}}}},"CreateFunnelResponse":{"type":"object","required":["funnel_id","message"],"properties":{"funnel_id":{"type":"integer","format":"int32"},"message":{"type":"string"}}},"CreateFunnelStep":{"type":"object","required":["event_name"],"properties":{"event_filter":{"type":"array","items":{"$ref":"#/components/schemas/SmartFilter"}},"event_name":{"type":"string"}}},"CreateGenericRequest":{"type":"object","required":["name","clone_url"],"properties":{"base_url":{"type":["string","null"],"description":"Optional base URL of the git host for display purposes (no API is called)."},"clone_url":{"type":"string","description":"HTTPS clone URL for the repository, e.g. `https://git.example.com/org/repo.git`."},"name":{"type":"string","description":"Display name for this provider."},"token":{"type":["string","null"],"description":"Access token or password. Omit (or set to `null`) for public repositories."},"token_username":{"type":["string","null"],"description":"HTTP Basic username used with the token. Defaults to `x-access-token` when\nabsent or empty. Ignored for public (unauthenticated) repositories."}}},"CreateGitHubPATRequest":{"type":"object","required":["name","token"],"properties":{"name":{"type":"string"},"token":{"type":"string"}}},"CreateGitLabOAuthRequest":{"type":"object","required":["name","client_id","client_secret","redirect_uri"],"properties":{"base_url":{"type":["string","null"]},"client_id":{"type":"string"},"client_secret":{"type":"string"},"name":{"type":"string"},"redirect_uri":{"type":"string"}}},"CreateGitLabPATRequest":{"type":"object","required":["name","token"],"properties":{"base_url":{"type":["string","null"]},"name":{"type":"string"},"token":{"type":"string"}}},"CreateGiteaPATRequest":{"type":"object","required":["name","token","base_url"],"properties":{"base_url":{"type":"string","description":"HTTPS base URL of the Gitea instance, e.g. `https://git.example.com`."},"name":{"type":"string","description":"Display name for this provider."},"token":{"type":"string","description":"Personal access token issued by the Gitea instance."}}},"CreateIncidentRequest":{"type":"object","required":["title","severity"],"properties":{"description":{"type":["string","null"]},"environment_id":{"type":["integer","null"],"format":"int32"},"monitor_id":{"type":["integer","null"],"format":"int32"},"severity":{"type":"string"},"title":{"type":"string"}}},"CreateIntegrationBody":{"type":"object","required":["provider","signing_secret"],"properties":{"provider":{"type":"string","description":"Registered provider name, e.g. \"stripe\"."},"signing_secret":{"type":"string","description":"Signing secret from the provider's dashboard."}}},"CreateIpAccessControlRequest":{"type":"object","description":"Request to create an IP access control rule","required":["ip_address","action"],"properties":{"action":{"type":"string","description":"Action to take: \"block\" or \"allow\"","example":"block"},"ip_address":{"type":"string","description":"IP address in CIDR notation (e.g., \"192.168.1.1\" or \"10.0.0.0/24\")","example":"192.168.1.100"},"reason":{"type":["string","null"],"description":"Optional reason for the action","example":"Malicious activity detected"}}},"CreateMcpRequest":{"type":"object","required":["slug","name","config"],"properties":{"config":{"type":"object"},"description":{"type":["string","null"]},"name":{"type":"string"},"slug":{"type":"string"}}},"CreateMetricAlertRequest":{"type":"object","required":["project_id","name","metric_name","aggregation","detection_config","window_secs","for_duration_secs","severity","enabled"],"properties":{"aggregation":{"type":"string","description":"One of `avg|sum|min|max|count|rate|p50|p90|p95|p99`."},"detection_config":{"$ref":"#/components/schemas/DetectionConfig","description":"The detector: a discriminated union keyed by `kind`. Today only\n`{ \"kind\": \"static\", \"comparator\": \"gt\", \"threshold\": 500 }` is evaluable."},"dynamic_alerts":{"type":"boolean","description":"When true (and `group_by` is set) fire one independent alarm per breaching\nseries. Static detectors only. Default false."},"enabled":{"type":"boolean"},"for_duration_secs":{"type":"integer","format":"int32"},"group_by":{"type":"array","items":{"type":"string"},"description":"Label keys to break the metric down by, e.g. `[\"endpoint\",\"region\"]`. Empty\n(the default) = one aggregate stream. Max 2 keys; keys must match\n`[a-zA-Z0-9_.:-]`."},"grouped_notification_threshold":{"type":"integer","format":"int32","description":"When more than this many series transition to firing in the same tick, only\nthe first gets the expensive chart/AI enrichment. Range 1–1000, default 5."},"label_filters":{"type":"array","items":{"type":"array","items":false,"prefixItems":[{"type":"string"},{"type":"string"}]},"description":"AND-combined label equality filters: `[[\"key\",\"value\"],…]`. Empty = no\nfiltering (the default). Max 10 pairs; keys must match `[a-zA-Z0-9_.:-]`;\nvalues capped at 500 characters."},"max_series":{"type":"integer","format":"int32","description":"Cardinality cap for dynamic alerting: at most this many series (top by\n`|value|`). Range 1–100, default 20."},"metric_name":{"type":"string"},"name":{"type":"string"},"project_id":{"type":"integer","format":"int32"},"severity":{"type":"string","description":"One of `info|warning|critical`."},"window_secs":{"type":"integer","format":"int32"}}},"CreateMonitorRequest":{"type":"object","required":["name","monitor_type","environment_id"],"properties":{"check_interval_seconds":{"type":["integer","null"],"format":"int32"},"check_path":{"type":["string","null"]},"environment_id":{"type":"integer","format":"int32"},"monitor_type":{"type":"string"},"name":{"type":"string"}}},"CreateNotificationEmailProviderRequest":{"type":"object","required":["name","config"],"properties":{"config":{"$ref":"#/components/schemas/EmailConfig"},"enabled":{"type":["boolean","null"]},"name":{"type":"string"}}},"CreateOidcProviderRequest":{"type":"object","required":["name","issuer_url","client_id","client_secret"],"properties":{"client_id":{"type":"string"},"client_secret":{"type":"string"},"default_role":{"type":"string"},"enabled":{"type":"boolean"},"group_claim":{"type":"string"},"issuer_url":{"type":"string"},"jit_provisioning":{"type":"boolean"},"name":{"type":"string"},"role_claim":{"type":"string"},"scopes":{"type":"string"},"template":{"type":"string"},"trust_idp_email":{"type":"boolean","description":"Defaults false. Set to true only for IdPs where an admin\ncontrols user provisioning (corporate Okta, Azure AD) and\nself-signup of arbitrary emails is not possible — see the\n`trust_idp_email` field on `oidc_providers::Model` for the\nsecurity tradeoff this enables."}}},"CreateOidcRoleMappingRequest":{"type":"object","required":["priority","idp_group","role"],"properties":{"idp_group":{"type":"string"},"priority":{"type":"integer","format":"int32"},"role":{"type":"string"}}},"CreatePlanRequest":{"type":"object","description":"Request to create an import plan","required":["source","workload_id"],"properties":{"credentials":{"$ref":"#/components/schemas/ImportCredentials","description":"Platform credentials (required for cloud platforms like Vercel, Railway)"},"repository_id":{"type":["integer","null"],"format":"int32","description":"Optional repository ID to associate with the import\nIf provided, preset will be detected from the repository"},"source":{"$ref":"#/components/schemas/ImportSource","description":"Source to import from"},"workload_id":{"$ref":"#/components/schemas/WorkloadId","description":"Workload ID to import"}}},"CreatePlanResponse":{"type":"object","description":"Response with created plan","required":["session_id","plan","validation","can_execute"],"properties":{"can_execute":{"type":"boolean","description":"Whether the plan can be executed"},"plan":{"$ref":"#/components/schemas/ImportPlan","description":"Generated import plan"},"session_id":{"type":"string","description":"Session ID for tracking"},"validation":{"$ref":"#/components/schemas/ValidationReport","description":"Validation report"}}},"CreatePrResponse":{"type":"object","required":["run","pr_url","pr_number","branch_name"],"properties":{"branch_name":{"type":"string"},"pr_number":{"type":"integer","format":"int32"},"pr_url":{"type":"string"},"run":{"$ref":"#/components/schemas/AutofixerRunResponse"}}},"CreateProjectAccessRequest":{"type":"object","required":["team_id","role"],"properties":{"role":{"$ref":"#/components/schemas/TeamRole"},"team_id":{"type":"integer","format":"int32"}}},"CreateProjectFromTemplateRequest":{"type":"object","description":"Request to create a project from a template\n\nSupports two deploy modes:\n * **Fork mode** — when `git_provider_connection_id` is set, the template\n repo is cloned into a new repository under the user's Git account and the\n project tracks that fork (git-push deploys, automatic deploy on push).\n * **One-click public-repo mode** — when `git_provider_connection_id` is\n omitted, the project deploys directly from the template's public source\n repository (no fork, no Git account required). This is the activation\n path: a brand-new user with no Git provider connected can still deploy a\n demo in one click. `repository_name` / `repository_owner` are ignored in\n this mode, and automatic-deploy-on-push is unavailable (there is no fork\n to receive webhooks).","required":["template_slug","project_name"],"properties":{"automatic_deploy":{"type":"boolean","description":"Enable automatic deployment on push (defaults to true). Only honoured in\nfork mode; public-repo deploys cannot receive push webhooks."},"environment_variables":{"type":"array","items":{"$ref":"#/components/schemas/EnvVarInput"},"description":"Environment variables to set (key-value pairs)"},"git_provider_connection_id":{"type":["integer","null"],"format":"int32","description":"Git provider connection ID. When omitted, the project deploys directly\nfrom the template's public source repository instead of forking it."},"private":{"type":"boolean","description":"Whether to make the repository private (defaults to true)"},"project_name":{"type":"string","description":"Name for the new project"},"repository_name":{"type":["string","null"],"description":"Name for the new repository to create. Required in fork mode; ignored in\none-click public-repo mode."},"repository_owner":{"type":["string","null"],"description":"Owner/organization for the new repository (defaults to authenticated user)"},"storage_service_ids":{"type":"array","items":{"type":"integer","format":"int32"},"description":"External storage service IDs to attach to the project"},"template_slug":{"type":"string","description":"Template slug to use as the base"}}},"CreateProjectFromTemplateResponse":{"type":"object","description":"Response after creating a project from template","required":["project_id","project_slug","project_name","repository_url","template_slug","message"],"properties":{"message":{"type":"string","description":"Message with additional info"},"project_id":{"type":"integer","format":"int32","description":"ID of the created project"},"project_name":{"type":"string","description":"Name of the created project"},"project_slug":{"type":"string","description":"Slug of the created project"},"repository_url":{"type":"string","description":"URL of the created repository"},"template_slug":{"type":"string","description":"Template that was used"}}},"CreateProjectRequest":{"type":"object","required":["name","directory","main_branch","preset","storage_service_ids"],"properties":{"automatic_deploy":{"type":["boolean","null"]},"build_command":{"type":["string","null"]},"custom_domain":{"type":["string","null"]},"directory":{"type":"string"},"environment_variables":{"type":["array","null"],"items":{"type":"array","items":false,"prefixItems":[{"type":"string"},{"type":"string"}]}},"exposed_port":{"type":["integer","null"],"format":"int32","description":"Port exposed by the container (fallback when image has no EXPOSE directive)\n\nPriority order for port resolution:\n1. Image EXPOSE directive (auto-detected from built image)\n2. Environment-level exposed_port (overrides this value per environment)\n3. This project-level exposed_port (fallback)\n4. Default: 3000\n\nOnly set this if your image doesn't use EXPOSE directive.","example":8080},"git_provider_connection_id":{"type":["integer","null"],"format":"int32"},"git_url":{"type":["string","null"]},"install_command":{"type":["string","null"]},"is_on_demand":{"type":["boolean","null"]},"is_public_repo":{"type":["boolean","null"]},"is_web_app":{"type":["boolean","null"]},"main_branch":{"type":"string"},"name":{"type":"string"},"output_dir":{"type":["string","null"]},"performance_metrics_enabled":{"type":"boolean"},"preset":{"type":"string"},"preset_config":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/PresetConfigSchema","description":"Preset-specific configuration\n\nDifferent presets accept different configuration options:\n- **Dockerfile preset**: Accepts `DockerfilePresetConfig` with `dockerfile_path` and `build_context`\n- **Nixpacks preset**: Accepts ordered `providers` (for example `[\"...\", \"python\"]`)\n and optional inline `nixpacksConfig` TOML\n- **Static presets** (Vite, Next.js, etc.): Accept `StaticPresetConfig` with build commands and output dir\n\nExample for Dockerfile preset:\n```json\n{\n \"dockerfilePath\": \"docker/Dockerfile\",\n \"buildContext\": \"./api\"\n}\n```"}]},"project_type":{"type":["string","null"]},"repo_name":{"type":["string","null"]},"repo_owner":{"type":["string","null"]},"source_type":{"$ref":"#/components/schemas/SourceType","description":"Source type for deployments\n\nDetermines how the project is deployed:\n- **git** (default): Traditional Git-based deployments - source code is pulled, built, and deployed\n- **docker_image**: Deploy pre-built Docker images from external registries (DockerHub, GHCR, etc.)\n- **static_files**: Deploy pre-built static files uploaded as tar.gz or zip bundles\n\nFor `docker_image` and `static_files` source types, `repo_name` and `repo_owner` are optional."},"storage_service_ids":{"type":"array","items":{"type":"integer","format":"int32"}},"use_default_wildcard":{"type":["boolean","null"]}}},"CreateProjectSecretRequest":{"type":"object","description":"Request to create a new project secret.\n\nProject secrets are mounted into the container as files under\n`/run/secrets/` (mode 0400, tmpfs) instead of as environment variables.\nValues are always encrypted at rest and never returned in plaintext from\nthe API after create. Distinct from agent secrets (global `/settings/secrets`).","required":["key","value"],"properties":{"environment_ids":{"type":"array","items":{"type":"integer","format":"int32"}},"include_in_preview":{"type":"boolean","description":"Include this secret in preview environments."},"key":{"type":"string","description":"Identifier for the secret. Becomes the filename at `/run/secrets/`.\nMust start with a letter or underscore and contain only A-Z, a-z, 0-9, _."},"value":{"type":"string","description":"Plaintext value, <= 1 MiB."}}},"CreateProviderKeyRequest":{"type":"object","required":["provider","display_name","api_key"],"properties":{"api_key":{"type":"string"},"base_url":{"type":["string","null"]},"default_model":{"type":["string","null"],"description":"Optional model id to pin for this provider (e.g. \"gpt-4o-mini\")."},"display_name":{"type":"string"},"provider":{"type":"string"}}},"CreateProviderRequest":{"type":"object","required":["name","provider_type","config"],"properties":{"config":{},"enabled":{"type":["boolean","null"]},"name":{"type":"string"},"provider_type":{"type":"string"}}},"CreateRouteRequest":{"type":"object","required":["domain","host","port"],"properties":{"domain":{"type":"string"},"host":{"type":"string"},"port":{"type":"integer","format":"int32"},"route_type":{"type":["string","null"],"description":"Route type: \"http\" (default) matches on HTTP Host header,\n\"tls\" matches on TLS SNI hostname for TCP passthrough"}}},"CreateS3SourceRequest":{"type":"object","required":["name","bucket_name","bucket_path","access_key_id","secret_key","region"],"properties":{"access_key_id":{"type":"string"},"bucket_name":{"type":"string"},"bucket_path":{"type":"string"},"endpoint":{"type":["string","null"],"description":"Optional endpoint URL for S3-compatible services like MinIO","example":"http://minio.example.com:9000"},"force_path_style":{"type":["boolean","null"],"description":"Whether to use path-style addressing (default: true)","example":true},"is_default":{"type":["boolean","null"],"description":"When true, make this the default source (will swap out any existing default).\nThe very first S3 source is always created as default regardless of this flag.","example":false},"name":{"type":"string"},"region":{"type":"string"},"secret_key":{"type":"string"}}},"CreateSandboxBody":{"type":"object","properties":{"_runtime":{"type":["string","null"]},"backend":{"type":["string","null"],"description":"Isolation backend: `\"docker\"` (default) or `\"firecracker\"` (ADR-029,\nhardware-virtualized microVM — requires a host provisioned with\n`temps firecracker setup`). Omit for the platform default; existing\nclients are unaffected. Requesting an unavailable backend fails with\n400 rather than silently downgrading isolation."},"cpu_limit":{"type":["number","null"],"format":"double"},"disk_size_mb":{"type":["integer","null"],"format":"int64","description":"Root disk size in MB (Firecracker only; Docker ignores it). Omit for\nthe platform default (1 GiB).","minimum":0},"env":{"type":"object","description":"Extra env vars baked into the container on create.","additionalProperties":{"type":"string"},"propertyNames":{"type":"string"}},"image":{"type":["string","null"],"description":"Docker image override. `null` uses the platform default."},"memory_limit_mb":{"type":["integer","null"],"format":"int64","minimum":0},"name":{"type":["string","null"]},"networkPolicy":{},"pids_limit":{"type":["integer","null"],"format":"int64"},"ports":{"type":"array","items":{"type":"integer","format":"int32","minimum":0},"description":"Ports the sandbox will listen on. Each port becomes a `routes[]`\nentry in the create/get response so `@vercel/sandbox`'s\n`sandbox.domain(port)` can resolve it client-side without an\nextra round-trip."},"preview_password":{"type":["string","null"],"description":"Optional preview-URL password. When set, every preview URL served\nfor this sandbox is gated behind a login form. 8–256 characters.\nOmit to leave preview URLs open (the sandbox ID remains the only\ngate). The plaintext is never returned; only the last-4 hint is\nsurfaced in `SandboxResponse.preview_password_hint`."},"projectId":{"type":["string","null"]},"resources":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/ResourcesBody","description":"`@vercel/sandbox`'s nested resources object. When present, its\n`memory` / `vcpus` populate `memory_limit_mb` / `cpu_limit` if those\nweren't sent directly."}]},"source":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/SourceBody","description":"Optional initial content to seed into the work dir. Clones a\nrepo or extracts a tarball after the sandbox is created."}]},"timeout":{"type":["integer","null"],"format":"int64","description":"Idle timeout as sent by `@vercel/sandbox` (milliseconds). Converted\nto seconds when `timeout_secs` is absent.","minimum":0},"timeout_secs":{"type":["integer","null"],"format":"int64","description":"Idle timeout in seconds (temps-native). Clamped to `[60, 86400]`.","minimum":0}}},"CreateSkillRequest":{"type":"object","required":["slug","name","content"],"properties":{"content":{"type":"string"},"description":{"type":["string","null"]},"name":{"type":"string"},"slug":{"type":"string"}}},"CreateSlackProviderRequest":{"type":"object","required":["name","config"],"properties":{"config":{"$ref":"#/components/schemas/SlackConfig"},"enabled":{"type":["boolean","null"]},"name":{"type":"string"}}},"CreateTeamMemberRequest":{"type":"object","required":["user_id","role"],"properties":{"role":{"$ref":"#/components/schemas/TeamRole"},"user_id":{"type":"integer","format":"int32"}}},"CreateTeamRequest":{"type":"object","required":["name","slug"],"properties":{"description":{"type":["string","null"]},"name":{"type":"string"},"slug":{"type":"string"}}},"CreateUserRequest":{"type":"object","required":["username","roles"],"properties":{"email":{"type":["string","null"]},"password":{"type":["string","null"]},"roles":{"type":"array","items":{"type":"string"}},"username":{"type":"string"}}},"CreateWebhookProviderRequest":{"type":"object","required":["name","config"],"properties":{"config":{"$ref":"#/components/schemas/WebhookConfig"},"enabled":{"type":["boolean","null"]},"name":{"type":"string"}}},"CreateWebhookRequestBody":{"type":"object","required":["url","events"],"properties":{"enabled":{"type":["boolean","null"],"description":"Whether the webhook is enabled","default":true},"events":{"type":"array","items":{"type":"string"},"description":"Event types to subscribe to","example":["deployment.created","deployment.succeeded"]},"secret":{"type":["string","null"],"description":"Secret for HMAC signature verification (optional)"},"url":{"type":"string","description":"Target URL for webhook delivery","example":"https://example.com/webhook"}}},"CreatedResource":{"type":"object","description":"Resource created during import (for rollback / audit)","required":["resource_type","resource_id","resource_name"],"properties":{"resource_id":{"type":"integer","format":"int32","description":"Resource ID"},"resource_name":{"type":"string","description":"Resource name"},"resource_type":{"type":"string","description":"Resource type (project, environment, deployment, service, domain, etc.)"}}},"CronExecutionInfo":{"type":"object","required":["id","cron_id","executed_at","url","status_code","headers","response_time_ms"],"properties":{"cron_id":{"type":"integer","format":"int32"},"error_message":{"type":["string","null"]},"executed_at":{"type":"string"},"headers":{"type":"string"},"id":{"type":"integer","format":"int32"},"response_time_ms":{"type":"integer","format":"int32"},"status_code":{"type":"integer","format":"int32"},"url":{"type":"string"}}},"CronInfo":{"type":"object","required":["id","project_id","environment_id","path","schedule","created_at","updated_at"],"properties":{"created_at":{"type":"string"},"deleted_at":{"type":["string","null"]},"environment_id":{"type":"integer","format":"int32"},"id":{"type":"integer","format":"int32"},"next_run":{"type":["string","null"]},"path":{"type":"string"},"project_id":{"type":"integer","format":"int32"},"schedule":{"type":"string"},"updated_at":{"type":"string"}}},"CrossProjectSiblingRef":{"type":"object","description":"A sibling project that shares the same `trace_id`, returned by the\nPhase 1 cross-project banner endpoint.","required":["project_id","project_name","project_slug","first_seen"],"properties":{"first_seen":{"type":"string","format":"date-time","description":"ISO 8601 timestamp (UTC, `Z` suffix) of first span ingest for this\n`(trace_id, project_id)` pair."},"project_id":{"type":"integer","format":"int32"},"project_name":{"type":"string"},"project_slug":{"type":"string","description":"URL slug used to link into the sibling project's single-project trace view."}}},"CrossProjectTraceResponse":{"type":"object","description":"Response body for `GET /otel/traces/cross-project/{trace_id}`.\n\nAn empty `siblings` vec is the normal single-project case — never 404.","required":["trace_id","siblings"],"properties":{"siblings":{"type":"array","items":{"$ref":"#/components/schemas/CrossProjectSiblingRef"},"description":"Projects other than the caller's that hold spans for this trace,\nordered by `first_seen ASC`."},"trace_id":{"type":"string","description":"The trace_id that was queried (echoed back for client convenience)."}}},"CurrentStatusResponse":{"type":"object","required":["monitor_id","current_status","uptime_percentage"],"properties":{"avg_response_time_ms":{"type":["number","null"],"format":"double"},"current_status":{"type":"string"},"last_check_at":{"type":["string","null"],"format":"date-time"},"monitor_id":{"type":"integer","format":"int32"},"uptime_percentage":{"type":"number","format":"double"}}},"CustomDomainRequest":{"type":"object","required":["domain","environment_id"],"properties":{"branch":{"type":["string","null"]},"domain":{"type":"string"},"environment_id":{"type":"integer","format":"int32"},"redirect_to":{"type":["string","null"]},"service_name":{"type":["string","null"],"description":"Docker Compose service name this domain routes to (only for docker-compose projects)"},"status_code":{"type":["integer","null"],"format":"int32"}}},"CustomDomainResponse":{"type":"object","required":["id","project_id","domain","status","created_at","updated_at"],"properties":{"branch":{"type":["string","null"]},"created_at":{"type":"integer","format":"int64"},"domain":{"type":"string"},"domain_id":{"type":["integer","null"],"format":"int32"},"environment":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/DomainEnvironmentResponse"}]},"expiration_time":{"type":["integer","null"],"format":"int64"},"id":{"type":"integer","format":"int32"},"last_renewed":{"type":["integer","null"],"format":"int64"},"message":{"type":["string","null"]},"project_id":{"type":"integer","format":"int32"},"redirect_to":{"type":["string","null"]},"service_name":{"type":["string","null"],"description":"Docker Compose service name this domain routes to"},"status":{"type":"string"},"status_code":{"type":["integer","null"],"format":"int32"},"updated_at":{"type":"integer","format":"int64"}}},"CustomerMovementResponse":{"type":"object","required":["bucket","new_customers","churned_customers"],"properties":{"bucket":{"type":"string","format":"date-time"},"churned_customers":{"type":"integer","format":"int64"},"new_customers":{"type":"integer","format":"int64"}}},"DashboardLayout":{"type":"object","description":"The typed layout persisted (as JSONB) in `metric_dashboards.layout`.","required":["sections"],"properties":{"sections":{"type":"array","items":{"$ref":"#/components/schemas/DashboardSection"},"description":"Ordered sections that make up the dashboard."}}},"DashboardProjectsAnalyticsQuery":{"type":"object","description":"Query parameters for batch dashboard analytics","required":["project_ids","start_date","end_date"],"properties":{"end_date":{"type":"string","format":"date-time","description":"End date for the query range"},"project_ids":{"type":"string","description":"Comma-separated list of project IDs"},"start_date":{"type":"string","format":"date-time","description":"Start date for the query range"}}},"DashboardProjectsAnalyticsResponse":{"type":"object","description":"Batch response for dashboard project analytics","required":["projects"],"properties":{"projects":{"type":"object","description":"Map of project_id -> analytics data","additionalProperties":{"$ref":"#/components/schemas/ProjectDashboardAnalytics"},"propertyNames":{"type":"string"}}}},"DashboardSection":{"type":"object","description":"A titled group of tiles within a dashboard.","required":["id","title","tiles"],"properties":{"id":{"type":"string","description":"Stable client-generated section id."},"tiles":{"type":"array","items":{"$ref":"#/components/schemas/DashboardTile"},"description":"Tiles rendered within this section."},"title":{"type":"string","description":"Section heading."}}},"DashboardTile":{"type":"object","description":"A single metric tile within a dashboard section.","required":["id","metric_name","aggregation"],"properties":{"aggregation":{"type":"string","description":"Aggregation applied per bucket: one of\n`avg|sum|min|max|count|rate|p50|p90|p95|p99`."},"group_by":{"type":"array","items":{"type":"string"},"description":"Label keys to break the metric down by (group-by / multi-series view).\nEmpty = single aggregated series (current behavior). Max 2 keys — more\ndimensions are unreadable in a chart (ADR-026 Phase 2). Each key must\nmatch `[a-zA-Z0-9_.:-]`. Wired directly to `MetricQuery.group_by` by\nthe tile query path (separate frontend task)."},"id":{"type":"string","description":"Stable client-generated tile id (used as a React key / for reordering)."},"label_filters":{"type":"array","items":{"type":"array","items":false,"prefixItems":[{"type":"string"},{"type":"string"}]},"description":"AND-combined label equality filters: `[[\"key\",\"value\"],…]`. Empty = no\nfiltering. Max 10 pairs; keys must match `[a-zA-Z0-9_.:-]`; values\ncapped at 500 characters. Not yet wired into the tile query path\n(Phase 1 ADR-026 — field round-trips and validates; query wiring is\na separate frontend task)."},"metric_name":{"type":"string","description":"The metric name to chart (e.g. `http.server.duration`)."},"title":{"type":["string","null"],"description":"Optional display title; falls back to the metric name in the UI."}}},"DataImplication":{"type":"object","description":"A specific data implication the user needs to understand","required":["severity","message"],"properties":{"message":{"type":"string","description":"Human-readable description of what could happen"},"recommended_action":{"type":["string","null"],"description":"What the user should do about it (if anything)"},"severity":{"$ref":"#/components/schemas/DataImplicationSeverity","description":"Severity of this implication"}}},"DataImplicationSeverity":{"type":"string","description":"Severity of a data implication","enum":["info","warning","data-not-migrated","potential-data-loss"]},"DatabaseMetricsResponse":{"type":"object","description":"Response for the per-database metrics breakdown.","required":["databases"],"properties":{"databases":{"type":"array","items":{"$ref":"#/components/schemas/DatabaseMetricsRow"},"description":"One entry per database, sorted by the first metric descending\n(largest first) so the biggest database leads the table."}}},"DatabaseMetricsRow":{"type":"object","description":"Per-database metric values for a Postgres service.\n\nA Postgres instance can host many databases (some unrelated to this\nservice). The collector records per-`datname` series; this groups the\nlatest value of each requested metric by database so the UI can render a\n\"Databases\" breakdown table instead of one collapsed number.","required":["database","metrics"],"properties":{"database":{"type":"string","description":"Database name (`datname`)."},"metrics":{"type":"object","description":"Latest value of each requested metric for this database\n(e.g. `{\"pg.database_size_bytes\": 7943871, \"pg.cache_hit_ratio\": 0.99}`).","additionalProperties":{"type":"number","format":"double"},"propertyNames":{"type":"string"}}}},"DelRequest":{"type":"object","description":"Request to delete keys","required":["keys"],"properties":{"keys":{"type":"array","items":{"type":"string"},"description":"The key(s) to delete","example":["user:123","user:456"]},"project_id":{"type":["integer","null"],"format":"int32","description":"Project ID (required for API key/session auth, optional for deployment tokens)","example":1}}},"DelResponse":{"type":"object","description":"Response for delete operation","required":["deleted"],"properties":{"deleted":{"type":"integer","format":"int64","description":"Number of keys deleted","example":2}}},"DeleteBlobRequest":{"type":"object","description":"Request to delete blobs","required":["pathnames"],"properties":{"pathnames":{"type":"array","items":{"type":"string"},"description":"Pathnames to delete (relative to project)","example":["images/avatar.png","documents/file.pdf"]},"projectId":{"type":["integer","null"],"format":"int32","description":"Project ID (required for API key/session auth, optional for deployment tokens)","example":1}}},"DeleteBlobResponse":{"type":"object","description":"Response after deleting blobs","required":["deleted"],"properties":{"deleted":{"type":"integer","format":"int64","description":"Number of blobs deleted","example":2}}},"DeleteResponse":{"type":"object","required":["deleted"],"properties":{"deleted":{"type":"integer","format":"int64","minimum":0}}},"DeployFromImageRequest":{"type":"object","properties":{"external_image_id":{"type":["integer","null"],"format":"int32","description":"External image ID (if already registered). If provided without image_ref,\nthe image reference will be fetched from the registered external image."},"health_check_path":{"type":["string","null"],"description":"Optional HTTP health-check path override (e.g. \"/api/healthz\").\nImage deploys can't read `.temps.yaml`, so this sets the path the deployer\nprobes after the container starts and the path the environment's uptime\nmonitor checks. Must start with '/'. When omitted, defaults to \"/\".","example":"/api/healthz"},"image_ref":{"type":["string","null"],"description":"Docker image reference (e.g., \"ghcr.io/org/app:v1.0\")\nRequired if external_image_id is not provided","example":"ghcr.io/myorg/myapp:v1.0"},"metadata":{"description":"Optional deployment metadata"}}},"DeployFromImageUploadQuery":{"type":"object","description":"Query parameters for deploying from an uploaded image tarball","properties":{"health_check_path":{"type":["string","null"],"description":"Optional HTTP health-check path override (e.g. \"/api/healthz\").\nMust start with '/'. When omitted, defaults to \"/\".","example":"/api/healthz"},"tag":{"type":["string","null"],"description":"Tag to apply to the imported image (e.g., \"myapp:v1.0\")\nIf not provided, a unique tag will be generated","example":"myapp:v1.0"}}},"DeployFromStaticRequest":{"type":"object","required":["static_bundle_id"],"properties":{"health_check_path":{"type":["string","null"],"description":"Optional HTTP health-check path override (e.g. \"/api/healthz\").\nStatic deploys can't read `.temps.yaml`, so this sets the path the deployer\nprobes after the container starts and the path the environment's uptime\nmonitor checks. Must start with '/'. When omitted, defaults to \"/\".","example":"/api/healthz"},"metadata":{"description":"Optional deployment metadata"},"static_bundle_id":{"type":"integer","format":"int32","description":"Static bundle ID (required)"}}},"DeploymentConfig":{"type":"object","description":"Deployment configuration shared between projects and environments\n\nThis configuration can be set at the project level (as defaults) and\noverridden at the environment level for specific deployments.\n\nNote: Environment variables are managed separately and are not part of this config.","properties":{"antiAffinity":{"type":"boolean","description":"Anti-affinity: spread replicas across different nodes.\n\nWhen enabled, the scheduler avoids placing two replicas of the same\nenvironment on the same node. If there are fewer eligible nodes than\nreplicas, remaining replicas wrap around (best-effort spreading).\n\nDefaults to `true` — replicas spread by default."},"automaticDeploy":{"type":["boolean","null"],"description":"Enable automatic deployments on git push.\n`None` = inherit from project config; `Some(true/false)` = explicit override.\nStored as JSONB so absent key → `None` (inherit), never silently defaults to false."},"containerExecEnabled":{"type":"boolean","description":"Enable container exec/shell access (disabled by default for security)"},"cpuLimit":{"type":["integer","null"],"format":"int32","description":"CPU limit in microcores, where 1_000_000 = 1 full CPU core\n(e.g., 2_000_000 = 2 CPUs). NOT millicores. `None` = uncapped."},"cpuRequest":{"type":["integer","null"],"format":"int32","description":"CPU request in microcores, where 1_000_000 = 1 full CPU core\n(e.g., 100_000 = 0.1 CPU, 500_000 = 0.5 CPU, 2_000_000 = 2 CPUs).\nNOT millicores — the deployer formats this as `{n}u` and converts\n`n / 1_000_000` cores into Docker nano_cpus."},"crossArchitectureBuilds":{"type":["boolean","null"],"description":"Build one image per architecture the eligible nodes run.\n\n`None`/`false` (the default) builds exactly once, on the control\nplane's native platform — byte-for-byte the behaviour of a\nsingle-architecture cluster. When enabled and the nodes this\ndeployment could land on span more than one architecture, the build\njob produces one image per architecture; the non-native ones go\nthrough the daemon's `platform` option, which requires QEMU binfmt\nhandlers registered on the control plane.\n\n**Opt-in on purpose.** Cross-architecture builds are emulated and\nsubstantially slower, and deriving them from cluster topology would\nmean a single node joining silently changes build behaviour for every\ndeployment in the cluster. It also keeps the decision on operator\nconfig rather than on a value each node reports about itself.\n\n`Option` so an environment inherits the project's setting\n(`None`) or overrides it, matching `automatic_deploy`."},"exposedPort":{"type":["integer","null"],"format":"int32","description":"Port exposed by the container\nIf not specified, will be auto-detected from Docker image or default to 3000"},"idleTimeoutSeconds":{"type":"integer","format":"int32","description":"Seconds of inactivity before containers are stopped in on-demand mode.\nOnly used when `on_demand` is true. Min: 60, Max: 86400 (24h).\nDefault: 300 (5 minutes)."},"memoryLimit":{"type":["integer","null"],"format":"int32","description":"Memory limit in megabytes. Three-state semantics:\n- `None` → inherit the parent layer (env inherits project, project\n inherits the seeded default); used by the settings UI's \"Use default\".\n- `Some(0)` → explicit **uncapped**: stop inheriting and run with no\n memory limit. This is the deliberate escape hatch for dedicated\n workloads, distinct from `None`.\n- `Some(n)` → hard cap of `n` MB.\n\n`merge`/resolution keep `Some(0)` as a present value (it wins precedence\nover a parent cap), and the deployer collapses it to \"no limit\" before\ntalking to Docker."},"memoryRequest":{"type":["integer","null"],"format":"int32","description":"Memory request in megabytes (e.g., 128 = 128MB)"},"onDemand":{"type":"boolean","description":"Enable on-demand mode (scale-to-zero).\nWhen enabled, containers are stopped after `idle_timeout_seconds` of no traffic\nand automatically started when a new request arrives."},"performanceMetricsEnabled":{"type":"boolean","description":"Enable performance metrics collection (speed insights)"},"replicas":{"type":"integer","format":"int32","description":"Number of replicas/instances to run\nDefaults to 1 replica"},"security":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/SecurityConfig","description":"Security configuration (headers, rate limiting, attack mode, etc.)\nThese settings inherit and override from parent level (Environment > Project > Global)"}]},"sessionRecordingEnabled":{"type":"boolean","description":"Enable session recording for analytics"},"targetLabels":{"description":"Label selector for node-based scheduling. Replicas are only deployed to\nnodes whose labels match the selector.\n\nMatching rules:\n- **Same key, array value** → OR: node must match any value\n- **Different keys** → AND: node must satisfy all keys\n\nExample: `{\"region\": [\"us\", \"asia\"], \"gpu\": \"true\"}`\n→ (region=us OR region=asia) AND gpu=true\n\nApplied after `target_nodes` filtering (they stack)."},"targetNodes":{"type":["array","null"],"items":{"type":"integer","format":"int32"},"description":"Optional list of node IDs to deploy to. When set, replicas are distributed\nonly across these nodes (round-robin). When None, the scheduler distributes\nacross all active nodes (or deploys locally if no nodes exist)."},"wakeTimeoutSeconds":{"type":"integer","format":"int32","description":"Max seconds to wait for containers to start when waking from on-demand sleep.\nRequests return 503 if exceeded. Default: 30."}}},"DeploymentConfigSnapshot":{"type":"object","description":"Deployment configuration snapshot for deployments\n\nThis extends DeploymentConfig with environment variables to capture\nthe complete state of a deployment at the time it was created.","properties":{"automaticDeploy":{"type":"boolean","description":"Enable automatic deployments on git push"},"containerExecEnabled":{"type":"boolean","description":"Enable container exec/shell access"},"cpuLimit":{"type":["integer","null"],"format":"int32","description":"CPU limit in millicores"},"cpuRequest":{"type":["integer","null"],"format":"int32","description":"CPU request in millicores"},"environmentVariables":{"type":"object","description":"Environment variables used for this deployment","additionalProperties":{"type":"string"},"propertyNames":{"type":"string"}},"exposedPort":{"type":["integer","null"],"format":"int32","description":"Port exposed by the container"},"memoryLimit":{"type":["integer","null"],"format":"int32","description":"Memory limit in megabytes"},"memoryRequest":{"type":["integer","null"],"format":"int32","description":"Memory request in megabytes"},"performanceMetricsEnabled":{"type":"boolean","description":"Enable performance metrics collection"},"replicas":{"type":"integer","format":"int32","description":"Number of replicas"},"sessionRecordingEnabled":{"type":"boolean","description":"Enable session recording"}}},"DeploymentConfiguration":{"type":"object","description":"Deployment-level configuration","required":["image","strategy","env_vars","ports","volumes","network","resources"],"properties":{"build":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/BuildConfiguration","description":"Build configuration (if building from source)"}]},"command":{"type":["array","null"],"items":{"type":"string"},"description":"Command override"},"entrypoint":{"type":["array","null"],"items":{"type":"string"},"description":"Entrypoint override"},"env_vars":{"type":"array","items":{"$ref":"#/components/schemas/EnvironmentVariable"},"description":"Environment variables"},"git":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/GitSourcePlan","description":"Where the application's source code lives, when the source platform\nbuilds from a git repository. Execution uses this to link the temps\nproject to the same repository so the real deployment pipeline can\nclone and build it."}]},"health_check":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/HealthCheckConfiguration","description":"Health check configuration"}]},"image":{"type":"string","description":"Image to deploy"},"network":{"$ref":"#/components/schemas/NetworkConfiguration","description":"Network configuration"},"ports":{"type":"array","items":{"$ref":"#/components/schemas/PortMapping"},"description":"Port mappings"},"resources":{"$ref":"#/components/schemas/ResourceLimits","description":"Resource limits"},"strategy":{"$ref":"#/components/schemas/DeploymentStrategy","description":"Deployment strategy"},"volumes":{"type":"array","items":{"$ref":"#/components/schemas/VolumeMount"},"description":"Volume mounts"},"working_dir":{"type":["string","null"],"description":"Working directory"}}},"DeploymentContainerLogContentResponse":{"type":"object","description":"A single captured container-log dump, including its full text content.","required":["id","container_name","size_bytes","truncated","captured_at","content"],"properties":{"captured_at":{"type":"integer","format":"int64"},"container_name":{"type":"string"},"content":{"type":"string","description":"The captured plain-text log content."},"id":{"type":"integer","format":"int32"},"service_name":{"type":["string","null"]},"size_bytes":{"type":"integer","format":"int64"},"truncated":{"type":"boolean"}}},"DeploymentContainerLogResponse":{"type":"object","description":"Metadata for one captured (historical) container-log dump. Listed on the\ndeployment detail page so a user can pick which past container's logs to read.","required":["id","deployment_id","container_id","container_name","size_bytes","truncated","captured_at"],"properties":{"captured_at":{"type":"integer","format":"int64","description":"Unix epoch milliseconds of when the logs were captured (just before\nteardown). Matches the timestamp convention used by `DeploymentResponse`."},"container_id":{"type":"string"},"container_name":{"type":"string"},"deployment_id":{"type":"integer","format":"int32"},"id":{"type":"integer","format":"int32"},"node_id":{"type":["integer","null"],"format":"int32"},"service_name":{"type":["string","null"]},"size_bytes":{"type":"integer","format":"int64"},"truncated":{"type":"boolean"}}},"DeploymentContainerLogsListResponse":{"type":"object","description":"The list of captured container-log dumps for a deployment.","required":["logs"],"properties":{"logs":{"type":"array","items":{"$ref":"#/components/schemas/DeploymentContainerLogResponse"}}}},"DeploymentEnvironmentResponse":{"type":"object","required":["id","name","slug","domains"],"properties":{"domains":{"type":"array","items":{"type":"string"}},"id":{"type":"integer","format":"int32"},"name":{"type":"string"},"slug":{"type":"string"}}},"DeploymentJobResponse":{"type":"object","required":["id","deployment_id","job_id","job_type","name","status","created_at","updated_at","log_id"],"properties":{"created_at":{"type":"integer","format":"int64"},"dependencies":{},"deployment_id":{"type":"integer","format":"int32"},"description":{"type":["string","null"]},"error_message":{"type":["string","null"]},"execution_order":{"type":["integer","null"],"format":"int32"},"finished_at":{"type":["integer","null"],"format":"int64"},"id":{"type":"integer","format":"int32"},"job_config":{"description":"Internal workflow configuration is intentionally redacted. It can\ncontain legacy plaintext secrets or encrypted secret envelopes."},"job_id":{"type":"string"},"job_type":{"type":"string"},"log_id":{"type":"string"},"name":{"type":"string"},"outputs":{},"started_at":{"type":["integer","null"],"format":"int64"},"status":{"type":"string"},"updated_at":{"type":"integer","format":"int64"}}},"DeploymentJobsResponse":{"type":"object","required":["jobs","total"],"properties":{"jobs":{"type":"array","items":{"$ref":"#/components/schemas/DeploymentJobResponse"}},"total":{"type":"integer","minimum":0}}},"DeploymentListResponse":{"type":"object","required":["deployments","total","page","per_page"],"properties":{"deployments":{"type":"array","items":{"$ref":"#/components/schemas/DeploymentResponse"}},"page":{"type":"integer","format":"int64"},"per_page":{"type":"integer","format":"int64"},"total":{"type":"integer","format":"int64"}}},"DeploymentMetadata":{"type":"object","description":"Deployment metadata - typed information about the deployment","properties":{"buildDurationMs":{"type":["integer","null"],"format":"int64","description":"Build duration in milliseconds"},"builder":{"type":["string","null"],"description":"Docker builder used (e.g., \"nixpacks\", \"dockerfile\")"},"deploymentDurationMs":{"type":["integer","null"],"format":"int64","description":"Deployment duration in milliseconds"},"deploymentSourceType":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/SourceType","description":"Source type for THIS specific deployment (for Manual/flexible projects)\nThis allows Manual projects to have deployments via different methods\n(docker_image, static_files, or git) while keeping per-deployment tracking"}]},"dockerfilePath":{"type":["string","null"],"description":"Dockerfile path if using Dockerfile builder"},"externalImageId":{"type":["integer","null"],"format":"int32","description":"External image ID (reference to external_images table)"},"externalImageRef":{"type":["string","null"],"description":"External Docker image reference (for docker_image source type)\ne.g., \"ghcr.io/org/app:v1.0\" or \"docker.io/myapp:sha-abc123\""},"fileCount":{"type":["integer","null"],"format":"int32","description":"Number of files in the build output"},"gitPushEvent":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/GitPushEvent","description":"Git push event that triggered this deployment (if from webhook)"}]},"healthCheckPath":{"type":["string","null"],"description":"Explicit deploy-time HTTP health-check path override.\nImage/static deploys can't read `.temps.yaml`, so this lets the deploy\nrequest set a custom path (e.g. \"/api/healthz\"). When present it takes\npriority over any `.temps.yaml` `health.path` value. Always starts with '/'."},"imageSizeBytes":{"type":["integer","null"],"format":"int64","description":"Total size of the built image in bytes"},"imageUploadedLocally":{"type":"boolean","description":"Whether the image was uploaded directly (via docker save/load) rather than pulled from registry\nWhen true, the PullExternalImageJob is skipped since the image is already loaded locally"},"isRollback":{"type":"boolean","description":"Whether this is a rollback deployment"},"labels":{"type":"array","items":{"type":"string"},"description":"Custom labels/tags for the deployment"},"rolledBackFromId":{"type":["integer","null"],"format":"int32","description":"ID of the deployment this was rolled back from (if applicable)"},"staticBundleContentType":{"type":["string","null"],"description":"Static bundle content type (for proper extraction: application/gzip or application/zip)"},"staticBundleId":{"type":["integer","null"],"format":"int32","description":"Static bundle ID (reference to static_bundles table, for static_files source type)"},"staticBundlePath":{"type":["string","null"],"description":"Static bundle path in blob storage (for static_files source type)"},"uploadedImageId":{"type":["string","null"],"description":"Docker image ID of the locally uploaded image (sha256:...)\nUsed to verify the image exists before deployment"}}},"DeploymentResponse":{"type":"object","required":["id","project_id","environment_id","environment","status","url","created_at","is_current"],"properties":{"branch":{"type":["string","null"]},"cancelled_reason":{"type":["string","null"]},"commit_author":{"type":["string","null"]},"commit_date":{"type":["integer","null"],"format":"int64"},"commit_hash":{"type":["string","null"]},"commit_message":{"type":["string","null"]},"created_at":{"type":"integer","format":"int64"},"deployment_config":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/DeploymentConfigSnapshot","description":"Deployment configuration snapshot (CPU, memory, replicas, environment variables, etc.)"}]},"environment":{"$ref":"#/components/schemas/DeploymentEnvironmentResponse"},"environment_id":{"type":"integer","format":"int32"},"finished_at":{"type":["integer","null"],"format":"int64"},"id":{"type":"integer","format":"int32"},"is_current":{"type":"boolean"},"metadata":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/DeploymentMetadata","description":"Deployment metadata (build info, git event, etc.)"}]},"project_id":{"type":"integer","format":"int32"},"screenshot_location":{"type":["string","null"]},"started_at":{"type":["integer","null"],"format":"int64"},"status":{"type":"string"},"tag":{"type":["string","null"]},"url":{"type":"string"}}},"DeploymentStateResponse":{"type":"object","required":["id","state","message"],"properties":{"id":{"type":"integer","format":"int32"},"message":{"type":"string"},"state":{"type":"string"}}},"DeploymentStrategy":{"type":"string","description":"Deployment strategy","enum":["replace","blue-green","rolling"]},"DeploymentTokenListResponse":{"type":"object","required":["tokens","total"],"properties":{"tokens":{"type":"array","items":{"$ref":"#/components/schemas/DeploymentTokenResponse"}},"total":{"type":"integer","format":"int64","minimum":0}}},"DeploymentTokenResponse":{"type":"object","required":["id","project_id","name","token_prefix","is_active","created_at"],"properties":{"created_at":{"type":"string","format":"date-time","example":"2024-01-01T00:00:00Z"},"created_by":{"type":["integer","null"],"format":"int32"},"deployment_id":{"type":["integer","null"],"format":"int32"},"environment_id":{"type":["integer","null"],"format":"int32"},"expires_at":{"type":["string","null"],"format":"date-time","example":"2024-12-31T23:59:59Z"},"id":{"type":"integer","format":"int32"},"is_active":{"type":"boolean"},"last_used_at":{"type":["string","null"],"format":"date-time","example":"2024-01-01T00:00:00Z"},"name":{"type":"string"},"permissions":{"type":["array","null"],"items":{"type":"string"}},"project_id":{"type":"integer","format":"int32"},"token_prefix":{"type":"string"}}},"DetectionConfig":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/StaticParams","description":"v0 (shipping): static threshold comparison of the aggregated value."},{"type":"object","required":["kind"],"properties":{"kind":{"type":"string","enum":["static"]}}}],"description":"v0 (shipping): static threshold comparison of the aggregated value."},{"allOf":[{"$ref":"#/components/schemas/AnomalyParams","description":"Seasonal anomaly band (basic/agile/robust/ewma share this variant — the\nalgorithm is a field, not a new kind). Creation rejected until evaluated."},{"type":"object","required":["kind"],"properties":{"kind":{"type":"string","enum":["anomaly"]}}}],"description":"Seasonal anomaly band (basic/agile/robust/ewma share this variant — the\nalgorithm is a field, not a new kind). Creation rejected until evaluated."},{"allOf":[{"$ref":"#/components/schemas/ForecastParams","description":"Predict a future threshold breach (capacity planning). Stub."},{"type":"object","required":["kind"],"properties":{"kind":{"type":"string","enum":["forecast"]}}}],"description":"Predict a future threshold breach (capacity planning). Stub."},{"allOf":[{"$ref":"#/components/schemas/OutlierParams","description":"Cross-series population outlier (one host misbehaving vs its peers). Stub."},{"type":"object","required":["kind"],"properties":{"kind":{"type":"string","enum":["outlier"]}}}],"description":"Cross-series population outlier (one host misbehaving vs its peers). Stub."},{"allOf":[{"$ref":"#/components/schemas/AutoWatchParams","description":"Watchdog-style self-tuning auto-watch (engine picks bounds). Stub."},{"type":"object","required":["kind"],"properties":{"kind":{"type":"string","enum":["auto_watch"]}}}],"description":"Watchdog-style self-tuning auto-watch (engine picks bounds). Stub."}],"description":"The typed detector definition stored (as jsonb) in\n`metric_alert_rules.detection_config`.\n\nToday only [`DetectionConfig::Static`] is evaluable; the other variants are\nschema-present (so the SDK/UI and storage are already future-shaped) but\nrejected by [`DetectionConfig::validate`] until their evaluator lands. Each is\nthen enabled code-only, with no schema migration."},"DeviceCount":{"type":"object","required":["device_type","count","percentage"],"properties":{"count":{"type":"integer","format":"int64"},"device_type":{"type":"string"},"percentage":{"type":"number","format":"double"}}},"DigestSections":{"type":"object","description":"Sections that can be included in the weekly digest\nNote: `#[serde(default)]` allows backward compatibility when deserializing\nold data that may have `security` and `resources` fields instead of `projects`","properties":{"deployments":{"type":"boolean","default":true},"errors":{"type":"boolean","default":true},"funnels":{"type":"boolean","default":true},"performance":{"type":"boolean","default":true},"projects":{"type":"boolean","default":true}}},"Direction":{"type":"string","description":"Which side(s) of an anomaly band count as a deviation.","enum":["both","above","below"]},"DisableBlobResponse":{"type":"object","description":"Response after disabling Blob service","required":["success","message"],"properties":{"message":{"type":"string","description":"Human-readable message","example":"Blob service disabled successfully"},"success":{"type":"boolean","description":"Whether the operation succeeded","example":true}}},"DisableKvResponse":{"type":"object","description":"Response after disabling KV service","required":["success","message"],"properties":{"message":{"type":"string","description":"Status message","example":"KV service disabled successfully"},"success":{"type":"boolean","description":"Whether the service was successfully disabled"}}},"DisableMfaRequest":{"type":"object","required":["code"],"properties":{"code":{"type":"string"}}},"DiscoverRequest":{"type":"object","description":"Request to discover workloads","required":["source"],"properties":{"credentials":{"$ref":"#/components/schemas/ImportCredentials","description":"Platform credentials (required for cloud platforms like Vercel, Railway)"},"selector":{"$ref":"#/components/schemas/ImportSelector","description":"Optional selector to filter workloads"},"source":{"$ref":"#/components/schemas/ImportSource","description":"Source to discover from"}}},"DiscoverResponse":{"type":"object","description":"Response with discovered workloads","required":["workloads"],"properties":{"workloads":{"type":"array","items":{"$ref":"#/components/schemas/WorkloadDescriptor"},"description":"Discovered workloads"}}},"DiskInfo":{"type":"object","description":"Disk space information for a single disk/partition","required":["mount_point","total_bytes","used_bytes","available_bytes","usage_percent","file_system"],"properties":{"available_bytes":{"type":"integer","format":"int64","description":"Available space in bytes","minimum":0},"file_system":{"type":"string","description":"File system type (e.g., \"ext4\", \"apfs\")"},"mount_point":{"type":"string","description":"Mount point of the disk"},"total_bytes":{"type":"integer","format":"int64","description":"Total space in bytes","minimum":0},"usage_percent":{"type":"number","format":"double","description":"Usage percentage (0-100)"},"used_bytes":{"type":"integer","format":"int64","description":"Used space in bytes","minimum":0}}},"DiskSpaceAlert":{"type":"object","description":"Alert for a disk that exceeds the threshold","required":["mount_point","usage_percent","threshold_percent","available_bytes","available_human"],"properties":{"available_bytes":{"type":"integer","format":"int64","description":"Available space in bytes","minimum":0},"available_human":{"type":"string","description":"Human-readable available space"},"mount_point":{"type":"string","description":"Mount point of the disk"},"threshold_percent":{"type":"integer","format":"int32","description":"Configured threshold percentage","minimum":0},"usage_percent":{"type":"number","format":"double","description":"Current usage percentage"}}},"DiskSpaceAlertSettings":{"type":"object","description":"Disk space alert settings for monitoring disk usage","properties":{"check_interval_seconds":{"type":"integer","format":"int64","description":"Interval in seconds between disk space checks","default":300,"example":300,"minimum":60},"enabled":{"type":"boolean","description":"Whether disk space alerts are enabled","default":true},"monitor_path":{"type":["string","null"],"description":"Restrict monitoring to the disk backing this path. When unset (the\ndefault), every mounted writable volume is monitored — including\ndedicated volumes such as `/var/lib/docker`.","default":null},"threshold_percent":{"type":"integer","format":"int32","description":"Threshold percentage (0-100) at which to trigger alerts","default":80,"example":80,"maximum":100,"minimum":0}}},"DiskSpaceCheckResult":{"type":"object","description":"Result of a disk space check","required":["checked_at","enabled","threshold_percent","disks","alerts"],"properties":{"alerts":{"type":"array","items":{"$ref":"#/components/schemas/DiskSpaceAlert"},"description":"Disks that meet or exceed the threshold"},"checked_at":{"type":"string","format":"date-time","description":"Timestamp of the check (ISO 8601, UTC)","example":"2026-05-28T12:15:47.609192Z"},"disks":{"type":"array","items":{"$ref":"#/components/schemas/DiskInfo"},"description":"List of all monitored disks"},"enabled":{"type":"boolean","description":"Whether disk space monitoring is enabled in settings"},"threshold_percent":{"type":"integer","format":"int32","description":"Configured alert threshold percentage (0-100)","minimum":0}}},"DnsAckRequest":{"type":"object","required":["applied_generation"],"properties":{"applied_generation":{"type":"integer","format":"int64","description":"Highest generation the agent has actually applied locally."}}},"DnsAckResponse":{"type":"object","required":["node_id","applied_generation","server_generation"],"properties":{"applied_generation":{"type":"integer","format":"int64"},"node_id":{"type":"integer","format":"int32"},"server_generation":{"type":"integer","format":"int64"}}},"DnsChallengeRecordResult":{"type":"object","description":"Result of a single DNS TXT record creation for ACME challenge","required":["name","value","success","message"],"properties":{"message":{"type":"string","description":"Human-readable message about the operation"},"name":{"type":"string","description":"TXT record name (e.g., \"_acme-challenge.example.com\")","example":"_acme-challenge.example.com"},"success":{"type":"boolean","description":"Whether the record was created successfully"},"value":{"type":"string","description":"TXT record value (the ACME challenge token)","example":"abc123..."}}},"DnsChangesResponse":{"type":"object","required":["generation","full_snapshot","records","removed_ids"],"properties":{"full_snapshot":{"type":"boolean","description":"`true` ⇒ replace the local zone with `records`. `false` ⇒ merge\n`records` into the existing zone (and remove `removed_ids`)."},"generation":{"type":"integer","format":"int64","description":"Highest generation included in this response. Agent ACKs this back."},"records":{"type":"array","items":{"$ref":"#/components/schemas/EndpointDto"}},"removed_ids":{"type":"array","items":{"type":"integer","format":"int64"},"description":"IDs the agent should remove from its zone. Always empty in the v1\nprotocol — the resolver reconciles by name on snapshot mode. Kept\nin the wire format so a future tombstone-based protocol doesn't\nrequire a breaking change."}}},"DnsCompletionResponse":{"type":"object","required":["domain","status"],"properties":{"domain":{"type":"string"},"status":{"type":"string"}}},"DnsLookupError":{"type":"object","description":"Error response for DNS lookup failures","required":["error","domain"],"properties":{"domain":{"type":"string","description":"Domain name that failed","example":"nonexistent.com"},"error":{"type":"string","description":"Error message","example":"DNS lookup failed: domain not found"}}},"DnsLookupRequest":{"type":"object","description":"Request to lookup DNS A records for a domain","required":["domain"],"properties":{"domain":{"type":"string","description":"Domain name to lookup","example":"example.com"}}},"DnsLookupResponse":{"type":"object","description":"Response containing DNS A records","required":["domain","records","count","dns_servers"],"properties":{"count":{"type":"integer","description":"Number of records found","example":1,"minimum":0},"dns_servers":{"type":"array","items":{"type":"string"},"description":"DNS servers used for the lookup","example":["8.8.8.8","8.8.4.4"]},"domain":{"type":"string","description":"Domain name that was queried","example":"example.com"},"records":{"type":"array","items":{"type":"string"},"description":"List of A record IP addresses","example":["93.184.216.34"]}}},"DnsProviderCredentials":{"oneOf":[{"type":"object","required":["api_token","type"],"properties":{"account_id":{"type":["string","null"]},"api_token":{"type":"string","example":"your-api-token"},"type":{"type":"string","enum":["cloudflare"]}}},{"type":"object","required":["api_user","api_key","type"],"properties":{"api_key":{"type":"string","example":"your-api-key"},"api_user":{"type":"string","example":"your-username"},"client_ip":{"type":["string","null"]},"sandbox":{"type":"boolean"},"type":{"type":"string","enum":["namecheap"]}}},{"type":"object","required":["access_key_id","secret_access_key","type"],"properties":{"access_key_id":{"type":"string","example":"AKIAIOSFODNN7EXAMPLE"},"region":{"type":["string","null"],"example":"us-east-1"},"secret_access_key":{"type":"string","example":"wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"},"session_token":{"type":["string","null"]},"type":{"type":"string","enum":["route53"]}}},{"type":"object","required":["api_token","type"],"properties":{"api_token":{"type":"string","example":"dop_v1_your-token"},"type":{"type":"string","enum":["digitalocean"]}}},{"type":"object","required":["service_account_email","private_key","project_id","type"],"properties":{"private_key":{"type":"string","example":"-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----"},"project_id":{"type":"string","example":"my-gcp-project"},"service_account_email":{"type":"string","example":"dns-admin@myproject.iam.gserviceaccount.com"},"type":{"type":"string","enum":["gcp"]}}},{"type":"object","required":["tenant_id","client_id","client_secret","subscription_id","resource_group","type"],"properties":{"client_id":{"type":"string","example":"00000000-0000-0000-0000-000000000000"},"client_secret":{"type":"string"},"resource_group":{"type":"string","example":"my-resource-group"},"subscription_id":{"type":"string","example":"00000000-0000-0000-0000-000000000000"},"tenant_id":{"type":"string","example":"00000000-0000-0000-0000-000000000000"},"type":{"type":"string","enum":["azure"]}}},{"type":"object","description":"Pebble challtestsrv mock DNS (LOCAL DEV/TEST ONLY)","required":["management_url","type"],"properties":{"management_url":{"type":"string","example":"http://localhost:8055"},"type":{"type":"string","enum":["pebble"]}}}],"description":"DNS provider credentials (API-facing)"},"DnsProviderResponse":{"type":"object","description":"DNS provider response","required":["id","name","provider_type","credentials","is_active","flat_hostnames_supported","created_at","updated_at"],"properties":{"created_at":{"type":"string"},"credentials":{"description":"Masked credentials for display"},"description":{"type":["string","null"]},"flat_hostnames_supported":{"type":"boolean","description":"Whether this provider benefits from the flat hostname mode (e.g. Cloudflare\nUniversal SSL). The UI surfaces/recommends the Flat toggle when true."},"id":{"type":"integer","format":"int32"},"is_active":{"type":"boolean"},"last_error":{"type":["string","null"]},"last_used_at":{"type":["string","null"]},"name":{"type":"string"},"provider_type":{"type":"string"},"updated_at":{"type":"string"}}},"DnsProviderSettings":{"type":"object","properties":{"cloudflare_api_key":{"type":["string","null"],"default":null},"provider":{"type":"string","default":"manual"}}},"DnsProviderSettingsMasked":{"type":"object","description":"DNS provider settings with masked sensitive fields","required":["provider"],"properties":{"cloudflare_api_key":{"type":["string","null"]},"provider":{"type":"string"}}},"DnsProviderType":{"type":"string","description":"Supported DNS provider types","enum":["cloudflare","namecheap","route53","digitalocean","gcp","azure","manual","pebble"]},"DnsRecord":{"type":"object","description":"A DNS record","required":["zone","name","fqdn","content","ttl"],"properties":{"content":{"$ref":"#/components/schemas/DnsRecordContent","description":"Record content"},"fqdn":{"type":"string","description":"Fully qualified domain name","example":"www.example.com"},"id":{"type":["string","null"],"description":"Provider-specific record ID (if exists)","example":"abc123"},"metadata":{"type":"object","description":"Provider-specific metadata","additionalProperties":{"type":"string"},"propertyNames":{"type":"string"}},"name":{"type":"string","description":"Record name (without zone, e.g., \"www\" or \"@\" for root)","example":"www"},"proxied":{"type":"boolean","description":"Whether this record is proxied (Cloudflare-specific)"},"ttl":{"type":"integer","format":"int32","description":"Time to live in seconds","example":300,"minimum":0},"zone":{"type":"string","description":"Zone/domain this record belongs to","example":"example.com"}}},"DnsRecordChange":{"type":"object","description":"A single DNS record change the Cloudflare sync would make.","required":["action","name","record_type","value"],"properties":{"action":{"type":"string","description":"`\"create\"`, `\"update\"`, or `\"delete\"`."},"name":{"type":"string"},"record_type":{"type":"string","description":"Record type, e.g. `\"A\"` or `\"CNAME\"`."},"value":{"type":"string"}}},"DnsRecordContent":{"oneOf":[{"type":"object","description":"A record - IPv4 address (as string, e.g., \"192.0.2.1\")","required":["value","type"],"properties":{"type":{"type":"string","enum":["A"]},"value":{"type":"object","description":"A record - IPv4 address (as string, e.g., \"192.0.2.1\")","required":["address"],"properties":{"address":{"type":"string","example":"192.0.2.1"}}}}},{"type":"object","description":"AAAA record - IPv6 address (as string, e.g., \"2001:db8::1\")","required":["value","type"],"properties":{"type":{"type":"string","enum":["AAAA"]},"value":{"type":"object","description":"AAAA record - IPv6 address (as string, e.g., \"2001:db8::1\")","required":["address"],"properties":{"address":{"type":"string","example":"2001:db8::1"}}}}},{"type":"object","description":"CNAME record - canonical name","required":["value","type"],"properties":{"type":{"type":"string","enum":["CNAME"]},"value":{"type":"object","description":"CNAME record - canonical name","required":["target"],"properties":{"target":{"type":"string"}}}}},{"type":"object","description":"TXT record - text content","required":["value","type"],"properties":{"type":{"type":"string","enum":["TXT"]},"value":{"type":"object","description":"TXT record - text content","required":["content"],"properties":{"content":{"type":"string"}}}}},{"type":"object","description":"MX record - mail exchange","required":["value","type"],"properties":{"type":{"type":"string","enum":["MX"]},"value":{"type":"object","description":"MX record - mail exchange","required":["priority","target"],"properties":{"priority":{"type":"integer","format":"int32","minimum":0},"target":{"type":"string"}}}}},{"type":"object","description":"NS record - nameserver","required":["value","type"],"properties":{"type":{"type":"string","enum":["NS"]},"value":{"type":"object","description":"NS record - nameserver","required":["nameserver"],"properties":{"nameserver":{"type":"string"}}}}},{"type":"object","description":"SRV record - service","required":["value","type"],"properties":{"type":{"type":"string","enum":["SRV"]},"value":{"type":"object","description":"SRV record - service","required":["priority","weight","port","target"],"properties":{"port":{"type":"integer","format":"int32","minimum":0},"priority":{"type":"integer","format":"int32","minimum":0},"target":{"type":"string"},"weight":{"type":"integer","format":"int32","minimum":0}}}}},{"type":"object","description":"CAA record - certification authority authorization","required":["value","type"],"properties":{"type":{"type":"string","enum":["CAA"]},"value":{"type":"object","description":"CAA record - certification authority authorization","required":["flags","tag","value"],"properties":{"flags":{"type":"integer","format":"int32","minimum":0},"tag":{"type":"string"},"value":{"type":"string"}}}}},{"type":"object","description":"PTR record - pointer","required":["value","type"],"properties":{"type":{"type":"string","enum":["PTR"]},"value":{"type":"object","description":"PTR record - pointer","required":["target"],"properties":{"target":{"type":"string"}}}}}],"description":"DNS record content - varies by record type"},"DnsRecordResponse":{"type":"object","required":["record_type","name","value","status"],"properties":{"name":{"type":"string","description":"DNS record name (host)","example":"temps._domainkey.example.com"},"priority":{"type":["integer","null"],"format":"int32","description":"Priority (for MX records)","example":"10","minimum":0},"record_type":{"type":"string","description":"Record type: TXT, CNAME, MX","example":"TXT"},"status":{"$ref":"#/components/schemas/DnsRecordStatusResponse","description":"Verification status: unknown, verified, pending, failed"},"value":{"type":"string","description":"DNS record value","example":"v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3..."}}},"DnsRecordSetupResult":{"type":"object","description":"Result of a single DNS record creation","required":["record_type","name","success","automatic","message"],"properties":{"automatic":{"type":"boolean","description":"Whether the operation was automatic or manual"},"message":{"type":"string","description":"Human-readable message"},"name":{"type":"string","description":"Record name"},"record_type":{"type":"string","description":"Record type (TXT, CNAME, MX)"},"success":{"type":"boolean","description":"Whether the record was created successfully"}}},"DnsRecordStatusResponse":{"type":"string","description":"DNS record verification status","enum":["unknown","verified","pending","failed"]},"DnsZone":{"type":"object","description":"A DNS zone (domain managed by the provider)","required":["id","name","status","nameservers"],"properties":{"id":{"type":"string","description":"Provider-specific zone ID","example":"zone123"},"metadata":{"type":"object","description":"Provider-specific metadata","additionalProperties":{"type":"string"},"propertyNames":{"type":"string"}},"name":{"type":"string","description":"Zone name (domain)","example":"example.com"},"nameservers":{"type":"array","items":{"type":"string"},"description":"Nameservers for this zone"},"status":{"type":"string","description":"Zone status","example":"active"}}},"DockerComposePresetConfig":{"type":"object","description":"Configuration for Docker Compose deployments.","properties":{"composeOverride":{"type":["string","null"],"description":"User-provided docker-compose.override.yml content."},"composePath":{"type":["string","null"],"description":"Path to the Compose file relative to the project directory."},"publicPorts":{"type":"array","items":{"$ref":"#/components/schemas/ComposePublicPort"},"description":"Compose service ports that should be publicly routed."}}},"DockerRegistrySettings":{"type":"object","properties":{"ca_certificate":{"type":["string","null"],"default":null},"enabled":{"type":"boolean","default":false},"password":{"type":["string","null"],"default":null},"registry_url":{"type":["string","null"],"default":null},"tls_verify":{"type":"boolean","default":true},"username":{"type":["string","null"],"default":null}}},"DockerRegistrySettingsMasked":{"type":"object","description":"Docker registry settings with masked sensitive fields","required":["enabled","tls_verify"],"properties":{"ca_certificate":{"type":["string","null"]},"enabled":{"type":"boolean"},"password":{"type":["string","null"]},"registry_url":{"type":["string","null"]},"tls_verify":{"type":"boolean"},"username":{"type":["string","null"]}}},"DockerfilePresetConfig":{"type":"object","description":"Configuration for Dockerfile preset\nAllows customizing the Dockerfile path and build context for Docker-based deployments","properties":{"buildContext":{"type":["string","null"],"description":"Custom build context path (relative to repository root)\nIf not specified, uses the project's directory setting","example":"./api"},"dockerfilePath":{"type":["string","null"],"description":"Custom Dockerfile path (relative to build context)\nIf not specified, defaults to \"Dockerfile\" in the build context","example":"docker/Dockerfile"},"variant":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/DockerfileVariant","description":"Catalog variant. Normally omitted; `custom` selects the generated\nDockerfile compatibility preset."}]}}},"DockerfileVariant":{"type":"string","description":"Catalog variant persisted under the canonical Dockerfile preset.\n\nExisting rows predate this discriminator and therefore deserialize as\n[`DockerfileVariant::File`].","enum":["file","custom"]},"DomainAction":{"type":"string","description":"What to do with a domain during migration","enum":["import","skip"]},"DomainChallengeResponse":{"type":"object","required":["domain","txt_records","status"],"properties":{"domain":{"type":"string"},"status":{"type":"string"},"txt_records":{"type":"array","items":{"$ref":"#/components/schemas/TxtRecord"},"description":"Array of TXT records to add to DNS. For wildcards, multiple records are required."}}},"DomainEnvironmentResponse":{"type":"object","required":["id","name","slug"],"properties":{"id":{"type":"integer","format":"int32"},"name":{"type":"string"},"slug":{"type":"string"}}},"DomainError":{"type":"object","required":["message","code"],"properties":{"code":{"type":"string"},"details":{"type":["string","null"]},"message":{"type":"string"}}},"DomainPlan":{"type":"object","description":"Plan for migrating a single custom domain","required":["domain","environment","action","action_description"],"properties":{"action":{"$ref":"#/components/schemas/DomainAction","description":"What to do with this domain"},"action_description":{"type":"string","description":"Human-readable explanation"},"domain":{"type":"string","description":"Full domain name"},"environment":{"type":"string","description":"Which environment to associate with (\"production\")"},"redirect_to":{"type":["string","null"],"description":"Redirect target (if this is a redirect domain)"},"replacement":{"type":["string","null"],"description":"The temps-side address that replaces this domain when it is skipped.\n\nSource-generated domains (sslip.io / traefik.me / platform subdomains)\nembed the source server's IP and would keep pointing at the old\nmachine — this tells the user where the app will be reachable on\ntemps instead."},"status_code":{"type":["integer","null"],"format":"int32","description":"Redirect status code"}}},"DomainResponse":{"type":"object","required":["id","domain","status","is_wildcard","verification_method","created_at","updated_at"],"properties":{"certificate":{"type":["string","null"],"description":"The PEM-encoded certificate chain (can be displayed in browser or downloaded)"},"created_at":{"type":"integer","format":"int64"},"dns_challenge_token":{"type":["string","null"]},"dns_challenge_value":{"type":["string","null"]},"domain":{"type":"string"},"expiration_time":{"type":["integer","null"],"format":"int64"},"id":{"type":"integer","format":"int32"},"is_wildcard":{"type":"boolean"},"last_error":{"type":["string","null"]},"last_error_type":{"type":["string","null"]},"last_renewed":{"type":["integer","null"],"format":"int64"},"on_demand_backoff_until":{"type":["integer","null"],"format":"int64","description":"On-demand TLS negative-cache deadline (epoch millis), when this hostname's\non-demand HTTP-01 issuance is in backoff after a failure (ADR-018 §4).\n`None` means no active backoff."},"status":{"type":"string"},"updated_at":{"type":"integer","format":"int64"},"verification_method":{"type":"string"}}},"DrainNodeResponse":{"type":"object","required":["id","name","status","affected_environments","message"],"properties":{"affected_environments":{"type":"integer","minimum":0},"id":{"type":"integer","format":"int32"},"message":{"type":"string"},"name":{"type":"string"},"status":{"type":"string"}}},"DrainStatusResponse":{"type":"object","description":"Progress of a node drain operation.","required":["node_id","node_name","status","remaining_containers","drain_complete","can_remove","message"],"properties":{"can_remove":{"type":"boolean","description":"Can the node be safely removed?"},"drain_complete":{"type":"boolean","description":"Whether the drain is complete (all containers migrated)"},"message":{"type":"string"},"node_id":{"type":"integer","format":"int32"},"node_name":{"type":"string"},"remaining_containers":{"type":"integer","description":"Number of containers still on this node","minimum":0},"status":{"type":"string"}}},"DropArchiveUpload":{"type":"object","required":["file"],"properties":{"file":{"type":"string","format":"binary"}}},"DropInspectionResponse":{"type":"object","required":["suggestedName","candidates"],"properties":{"candidates":{"type":"array","items":{"$ref":"#/components/schemas/DropPresetCandidate"}},"suggestedName":{"type":"string"}}},"DropOffPoint":{"type":"object","description":"Drop-off point: pages where visitors leave the site","required":["page_path","exit_count","total_views","exit_rate"],"properties":{"exit_count":{"type":"integer","format":"int64","description":"Number of exits from this page"},"exit_rate":{"type":"number","format":"double","description":"Exit rate for this page (exit_count / total_views)"},"page_path":{"type":"string","description":"The page path where visitors drop off"},"total_views":{"type":"integer","format":"int64","description":"Total views of this page"}}},"DropPresetCandidate":{"type":"object","required":["directory","preset","label","confidence","reason","isStatic"],"properties":{"confidence":{"type":"string"},"directory":{"type":"string"},"isStatic":{"type":"boolean"},"label":{"type":"string"},"preset":{"type":"string"},"reason":{"type":"string"}}},"EmailConfig":{"type":"object","required":["smtp_host","smtp_port","username","password","from_address","to_addresses"],"properties":{"accept_invalid_certs":{"type":"boolean"},"from_address":{"type":"string"},"from_name":{"type":["string","null"]},"password":{"type":"string"},"smtp_host":{"type":"string"},"smtp_port":{"type":"integer","format":"int32","minimum":0},"starttls_required":{"type":"boolean"},"tls_mode":{"$ref":"#/components/schemas/TlsMode"},"to_addresses":{"type":"array","items":{"type":"string"}},"username":{"type":"string"}}},"EmailDomainResponse":{"type":"object","required":["id","provider_id","domain","status","created_at","updated_at"],"properties":{"created_at":{"type":"string","example":"2025-12-03T10:30:00Z"},"domain":{"type":"string","example":"updates.example.com"},"id":{"type":"integer","format":"int32"},"last_verified_at":{"type":["string","null"]},"provider_id":{"type":"integer","format":"int32"},"status":{"type":"string","example":"verified"},"updated_at":{"type":"string","example":"2025-12-03T10:30:00Z"},"verification_error":{"type":["string","null"]}}},"EmailDomainWithDnsResponse":{"type":"object","required":["domain","dns_records"],"properties":{"dns_records":{"type":"array","items":{"$ref":"#/components/schemas/DnsRecordResponse"}},"domain":{"$ref":"#/components/schemas/EmailDomainResponse"}}},"EmailProviderResponse":{"type":"object","required":["id","name","provider_type","region","is_active","credentials","created_at","updated_at"],"properties":{"created_at":{"type":"string","example":"2025-12-03T10:30:00Z"},"credentials":{"description":"Masked credentials for display"},"id":{"type":"integer","format":"int32"},"is_active":{"type":"boolean"},"name":{"type":"string","example":"My AWS SES"},"provider_type":{"$ref":"#/components/schemas/EmailProviderTypeRoute"},"region":{"type":"string","example":"us-east-1"},"sns_topic_arn":{"type":["string","null"]},"updated_at":{"type":"string","example":"2025-12-03T10:30:00Z"}}},"EmailProviderTypeRoute":{"type":"string","enum":["ses","scaleway","smtp"]},"EmailRequest":{"type":"object","description":"Request body carrying just an email address (password-reset request).","required":["email"],"properties":{"email":{"type":"string"}}},"EmailResponse":{"type":"object","required":["id","from_address","to_addresses","subject","status","created_at","track_opens","track_clicks","open_count","click_count"],"properties":{"bcc_addresses":{"type":["array","null"],"items":{"type":"string"}},"cc_addresses":{"type":["array","null"],"items":{"type":"string"}},"click_count":{"type":"integer","format":"int32","description":"Number of times links in the email were clicked"},"created_at":{"type":"string","example":"2025-12-03T10:30:00Z"},"domain_id":{"type":["integer","null"],"format":"int32"},"error_message":{"type":["string","null"]},"first_clicked_at":{"type":["string","null"],"description":"When a link was first clicked"},"first_opened_at":{"type":["string","null"],"description":"When the email was first opened"},"from_address":{"type":"string","example":"hello@updates.example.com"},"from_name":{"type":["string","null"]},"headers":{"type":["object","null"],"additionalProperties":{"type":"string"},"propertyNames":{"type":"string"}},"html_body":{"type":["string","null"]},"id":{"type":"string","example":"550e8400-e29b-41d4-a716-446655440000"},"open_count":{"type":"integer","format":"int32","description":"Number of times the email was opened"},"project_id":{"type":["integer","null"],"format":"int32"},"provider_message_id":{"type":["string","null"]},"reply_to":{"type":["string","null"]},"sent_at":{"type":["string","null"]},"status":{"type":"string","example":"sent"},"subject":{"type":"string"},"tags":{"type":["array","null"],"items":{"type":"string"}},"text_body":{"type":["string","null"]},"to_addresses":{"type":"array","items":{"type":"string"}},"track_clicks":{"type":"boolean","description":"Whether click tracking is enabled"},"track_opens":{"type":"boolean","description":"Whether open tracking is enabled"},"tracked_html_body":{"type":["string","null"],"description":"The final HTML sent to the provider (with tracking pixel and rewritten links)"}}},"EmailStatsResponse":{"type":"object","required":["total","sent","failed","queued","captured"],"properties":{"captured":{"type":"integer","format":"int64","description":"Emails captured without sending (Mailhog mode - no provider configured)","minimum":0},"failed":{"type":"integer","format":"int64","minimum":0},"queued":{"type":"integer","format":"int64","minimum":0},"sent":{"type":"integer","format":"int64","minimum":0},"total":{"type":"integer","format":"int64","minimum":0}}},"EmailStatusResponse":{"type":"object","required":["email_configured","password_reset_available","oidc_providers"],"properties":{"email_configured":{"type":"boolean"},"oidc_providers":{"type":"array","items":{"$ref":"#/components/schemas/OidcProviderSummary"}},"password_reset_available":{"type":"boolean"}}},"EmailTrackingResponse":{"type":"object","description":"Email tracking summary","required":["email_id","track_opens","track_clicks","open_count","click_count","unique_opens","unique_clicks","links"],"properties":{"click_count":{"type":"integer","format":"int32"},"email_id":{"type":"string"},"first_clicked_at":{"type":["string","null"]},"first_opened_at":{"type":["string","null"]},"links":{"type":"array","items":{"$ref":"#/components/schemas/TrackedLinkResponse"}},"open_count":{"type":"integer","format":"int32"},"track_clicks":{"type":"boolean"},"track_opens":{"type":"boolean"},"unique_clicks":{"type":"integer","format":"int64","minimum":0},"unique_opens":{"type":"integer","format":"int64","minimum":0}}},"EmailTrackingSetupResponse":{"type":"object","description":"Result of the one-click AWS-side event-tracking setup.","required":["topic_arn","webhook_url","subscription_requested","event_destination_attached"],"properties":{"event_destination_attached":{"type":"boolean","description":"The SESv2 event destination (bounce/complaint/delivery) is attached\nto the `temps-tracking` configuration set."},"subscription_requested":{"type":"boolean","description":"The webhook subscription was requested; SNS confirms it\nasynchronously through the webhook itself."},"topic_arn":{"type":"string","example":"arn:aws:sns:us-east-1:123456789012:temps-email-events-1"},"webhook_url":{"type":"string"}}},"EmailTrackingStatusResponse":{"type":"object","description":"Live status of the SES event-tracking pipeline for one provider.","required":["webhook_url","supports_event_tracking"],"properties":{"last_event_at":{"type":["string","null"],"description":"Most recent delivered/bounced/complained event recorded for an email\nsent through this provider. `null` means no provider feedback has\narrived yet.","example":"2026-07-18T10:31:00Z"},"sns_topic_arn":{"type":["string","null"]},"subscription_confirmed_at":{"type":["string","null"],"description":"When the SNS subscription for the current topic was confirmed.\n`null` with a topic set usually means the subscription is still\npending — most often because the endpoint was subscribed before the\ntopic ARN was saved here.","example":"2026-07-18T10:30:00Z"},"supports_event_tracking":{"type":"boolean","description":"Only SES providers support SNS event tracking."},"webhook_url":{"type":"string","description":"Public webhook endpoint SNS must deliver events to.","example":"https://temps.example.com/api/t/webhook/ses"}}},"EmbeddingData":{"type":"object","required":["object","embedding","index"],"properties":{"embedding":{"type":"array","items":{"type":"number","format":"double"}},"index":{"type":"integer","format":"int32"},"object":{"type":"string"}}},"EmbeddingInput":{"oneOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}]},"EmbeddingRequest":{"type":"object","required":["model","input"],"properties":{"dimensions":{"type":["integer","null"],"format":"int32"},"encoding_format":{"type":["string","null"]},"input":{"$ref":"#/components/schemas/EmbeddingInput"},"model":{"type":"string"}}},"EmbeddingResponse":{"type":"object","required":["object","data","model","usage"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/EmbeddingData"}},"model":{"type":"string"},"object":{"type":"string"},"usage":{"$ref":"#/components/schemas/EmbeddingUsage"}}},"EmbeddingUsage":{"type":"object","required":["prompt_tokens","total_tokens"],"properties":{"prompt_tokens":{"type":"integer","format":"int64"},"total_tokens":{"type":"integer","format":"int64"}}},"EnableBlobRequest":{"type":"object","description":"Request to enable Blob service","properties":{"docker_image":{"type":["string","null"],"description":"Docker image to use (optional, defaults to RustFS)","example":"ghcr.io/rustfs/rustfs:0.5.0"},"root_password":{"type":["string","null"],"description":"Root password for S3 access"},"root_user":{"type":["string","null"],"description":"Root user for S3 access"}}},"EnableBlobResponse":{"type":"object","description":"Response after enabling Blob service","required":["success","message","status"],"properties":{"message":{"type":"string","description":"Human-readable message","example":"Blob service enabled successfully"},"status":{"$ref":"#/components/schemas/BlobStatusResponse","description":"Current status"},"success":{"type":"boolean","description":"Whether the operation succeeded","example":true}}},"EnableKvRequest":{"type":"object","description":"Request to enable the KV service","properties":{"docker_image":{"type":["string","null"],"description":"Docker image to use (optional, uses default if not provided)","example":"gotempsh/redis-walg:8-bookworm"},"max_memory":{"type":["string","null"],"description":"Maximum memory allocation (e.g., \"256mb\", \"1gb\")","example":"256mb"},"persistence":{"type":"boolean","description":"Enable data persistence"}}},"EnableKvResponse":{"type":"object","description":"Response after enabling KV service","required":["success","message","status"],"properties":{"message":{"type":"string","description":"Status message","example":"KV service enabled successfully"},"status":{"$ref":"#/components/schemas/KvStatusResponse","description":"Current service status"},"success":{"type":"boolean","description":"Whether the service was successfully enabled"}}},"EnablePgStatStatementsResponse":{"type":"object","description":"Response for the enable pg_stat_statements endpoint.","required":["message"],"properties":{"message":{"type":"string","description":"Human-readable message confirming the action."}}},"EndpointDto":{"type":"object","description":"One DNS record on the wire. Mirrors `service_endpoints::Model` but\nkeeps the API stable across entity evolution. `target_ip` is a string\n(v4 or v6 literal, or CNAME target hostname) parsed by the resolver.","required":["id","fqdn","record_type","ttl","owner_kind","owner_id","generation"],"properties":{"fqdn":{"type":"string"},"generation":{"type":"integer","format":"int64"},"id":{"type":"integer","format":"int64"},"node_id":{"type":["integer","null"],"format":"int32"},"owner_id":{"type":"integer","format":"int64"},"owner_kind":{"type":"string"},"record_type":{"type":"string"},"target_ip":{"type":["string","null"]},"target_port":{"type":["integer","null"],"format":"int32"},"ttl":{"type":"integer","format":"int32"}}},"EnqueuedJob":{"type":"object","description":"A single job that was successfully enqueued during a fan-out run.","required":["backup_id","job_id","engine"],"properties":{"backup_id":{"type":"integer","format":"int32","description":"FK to `backups.id` for this job."},"engine":{"type":"string","description":"Engine key (e.g. `\"control_plane\"`, `\"redis\"`, `\"postgres_pgdump\"`)."},"job_id":{"type":"integer","format":"int64","description":"FK to `backup_jobs.id` for this job."},"target_service_id":{"type":["integer","null"],"format":"int32","description":"FK to `external_services.id` when this is an external-service job.\n`None` for the control-plane job."}}},"EnrichVisitorRequest":{"type":"object","required":["custom_data"],"properties":{"custom_data":{"type":"object"}}},"EnrichVisitorResponse":{"type":"object","required":["success","visitor_id","message"],"properties":{"message":{"type":"string"},"success":{"type":"boolean"},"visitor_id":{"type":"string"}}},"EnrollmentTokenInfo":{"type":"object","required":["id","expires_at","used_count","max_uses","created_at"],"properties":{"bound_node_name":{"type":["string","null"]},"created_at":{"type":"string"},"expires_at":{"type":"string"},"id":{"type":"integer","format":"int32"},"max_uses":{"type":"integer","format":"int32"},"used_count":{"type":"integer","format":"int32"}}},"EnrollmentTokenListResponse":{"type":"object","required":["tokens"],"properties":{"tokens":{"type":"array","items":{"$ref":"#/components/schemas/EnrollmentTokenInfo"}}}},"EntityInfoResponse":{"type":"object","required":["container_path","entity","entity_type","fields"],"properties":{"container_path":{"type":"array","items":{"type":"string"},"description":"Full container path","example":["mydb","public"]},"entity":{"type":"string","description":"Entity name","example":"users"},"entity_type":{"type":"string","description":"Entity type","example":"table"},"fields":{"type":"array","items":{"$ref":"#/components/schemas/FieldResponse"},"description":"Field definitions"},"metadata":{"description":"Additional metadata (content_type, last_modified, etag, etc.)"},"row_count":{"type":["integer","null"],"description":"Approximate row count (for tables/collections)","example":1234,"minimum":0},"size_bytes":{"type":["integer","null"],"format":"int64","description":"Size in bytes (for objects/files)","example":1048576,"minimum":0},"sort_schema":{"description":"JSON Schema for sort options (if supported)"}}},"EntityResponse":{"type":"object","required":["name","entity_type"],"properties":{"entity_type":{"type":"string","description":"Entity type (table, view, collection, etc.)","example":"table"},"name":{"type":"string","description":"Entity name (table/collection)","example":"users"},"row_count":{"type":["integer","null"],"description":"Approximate row count","example":1234,"minimum":0},"size_bytes":{"type":["integer","null"],"format":"int64","description":"Size in bytes (for files/objects)","example":1048576,"minimum":0}}},"EnvVarInput":{"type":"object","description":"Input for environment variable","required":["name","value"],"properties":{"name":{"type":"string","description":"Variable name"},"value":{"type":"string","description":"Variable value"}}},"EnvVarIntegrationInfo":{"type":"object","required":["service_id","service_name","service_type","service_updated_at"],"properties":{"service_id":{"type":"integer","format":"int32"},"service_name":{"type":"string"},"service_slug":{"type":["string","null"]},"service_type":{"type":"string"},"service_updated_at":{"type":"string"}}},"EnvVarResponse":{"type":"object","description":"Environment variable with masked sensitive values","required":["key","value","is_masked"],"properties":{"is_masked":{"type":"boolean","description":"Whether this is a sensitive/masked value"},"key":{"type":"string"},"value":{"type":"string"}}},"EnvVarTemplateResponse":{"type":"object","description":"Environment variable template response","required":["name","required"],"properties":{"default":{"type":["string","null"],"description":"Default value if not provided by user"},"default_generator":{"type":["string","null"],"description":"Frontend-side generator hint for the default value\n(e.g. `app_url`, `random_secret`, `random_hex_32`)"},"description":{"type":["string","null"],"description":"Description of what this variable is used for"},"example":{"type":["string","null"],"description":"Example value for documentation"},"name":{"type":"string","description":"Name of the environment variable"},"required":{"type":"boolean","description":"Whether this variable is required"}}},"EnvironmentConfiguration":{"type":"object","description":"Environment-level configuration","required":["name","subdomain","resources"],"properties":{"name":{"type":"string","description":"Environment name"},"resources":{"$ref":"#/components/schemas/ResourceLimits","description":"Resource limits for environment"},"subdomain":{"type":"string","description":"Proposed subdomain"}}},"EnvironmentDomainResponse":{"type":"object","required":["id","environment_id","domain","created_at","url"],"properties":{"created_at":{"type":"integer","format":"int64"},"domain":{"type":"string"},"environment_id":{"type":"integer","format":"int32"},"id":{"type":"integer","format":"int32"},"url":{"type":"string","description":"Full URL for this domain (e.g., https://buildtolearndev-production.example.com)","example":"https://buildtolearndev-production.example.com"}}},"EnvironmentInfo":{"type":"object","required":["id","name","main_url"],"properties":{"current_deployment_id":{"type":["integer","null"],"format":"int32"},"id":{"type":"integer","format":"int32"},"main_url":{"type":"string"},"name":{"type":"string"}}},"EnvironmentResponse":{"type":"object","required":["id","project_id","name","slug","main_url","subdomain","created_at","updated_at","is_preview","protected","sleeping"],"properties":{"attack_mode":{"type":["boolean","null"],"description":"Per-environment CAPTCHA attack-mode override.\n`null` means inherit the project-level `attack_mode`; `true`/`false`\nexplicitly enable/disable the challenge for this environment. Always\nserialized (NOT skipped) so the UI can distinguish `null` from `false`."},"branch":{"type":["string","null"]},"created_at":{"type":"integer","format":"int64"},"current_deployment_id":{"type":["integer","null"],"format":"int32"},"deployment_config":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/DeploymentConfig","description":"Deployment configuration for this environment (overrides project-level config)"}]},"estimated_sleep_at":{"type":["integer","null"],"format":"int64","description":"Estimated time (epoch millis) when the environment will go to sleep\nbased on last activity + idle timeout. NULL when sleeping or on-demand disabled."},"force_https":{"type":["boolean","null"],"description":"Per-environment HTTP→HTTPS redirect override.\n`null` means inherit the proxy default (redirect only when the host has\nan active TLS certificate); `true` always redirects plain HTTP for this\nenvironment, `false` never does. Always serialized (NOT skipped) so the\nUI can distinguish `null` from `false`."},"id":{"type":"integer","format":"int32"},"is_preview":{"type":"boolean","description":"Indicates if this is a preview environment (auto-created per branch)\nFor preview environments, 'branch' contains the feature branch name"},"last_activity_at":{"type":["integer","null"],"format":"int64","description":"Last proxied request timestamp (epoch millis) for on-demand environments.\nNULL when on-demand is disabled or no traffic has been received yet."},"main_url":{"type":"string"},"name":{"type":"string"},"project_id":{"type":"integer","format":"int32"},"protected":{"type":"boolean","description":"When true, git pushes do NOT auto-deploy to this environment.\nDeployments must be promoted from another environment."},"sleeping":{"type":"boolean","description":"When true, the environment's containers are currently stopped due to\ninactivity (on-demand mode) and will start on the next request."},"slug":{"type":"string"},"subdomain":{"type":"string","description":"The host label stored for this environment (e.g.\n`myproject-production`). This is the prefix that is combined with the\nplatform's preview domain at request time to produce `main_url`. Edit\nthis via the rename-subdomain endpoint, not the full URL."},"updated_at":{"type":"integer","format":"int64"}}},"EnvironmentVariable":{"type":"object","description":"Environment variable","required":["key","value","is_secret"],"properties":{"is_secret":{"type":"boolean","description":"Whether this is a secret (should be encrypted)"},"key":{"type":"string","description":"Variable name"},"source_description":{"type":["string","null"],"description":"Where this env var originates from (for traceability)"},"value":{"type":"string","description":"Variable value (may be redacted for secrets)"}}},"EnvironmentVariableInfo":{"type":"object","required":["name","value","sensitive"],"properties":{"name":{"type":"string"},"sensitive":{"type":"boolean","description":"Whether this variable contains sensitive data (passwords, keys, tokens)","example":false},"value":{"type":"string"}}},"EnvironmentVariableResponse":{"type":"object","required":["id","key","created_at","updated_at","environments","include_in_preview","is_secret"],"properties":{"created_at":{"type":"integer","format":"int64"},"environments":{"type":"array","items":{"$ref":"#/components/schemas/EnvironmentInfo"}},"id":{"type":"integer","format":"int32"},"include_in_preview":{"type":"boolean","description":"Include this environment variable in preview environments"},"is_secret":{"type":"boolean","description":"Whether the variable is a write-only secret. Secrets always have\n`value: None` in responses."},"key":{"type":"string"},"updated_at":{"type":"integer","format":"int64"},"value":{"type":["string","null"],"description":"Plaintext value for non-secret vars (or `\"***\"` mask for list responses).\n`None` for secret vars — secrets are write-only."}}},"EnvironmentVariableValueResponse":{"type":"object","required":["value"],"properties":{"value":{"type":"string"}}},"ErrorDashboardStatsQuery":{"type":"object","required":["start_time","end_time"],"properties":{"compare_to_previous":{"type":["boolean","null"]},"end_time":{"type":"string","format":"date-time"},"environment_id":{"type":["integer","null"],"format":"int32"},"start_time":{"type":"string","format":"date-time"}}},"ErrorDashboardStatsResponse":{"type":"object","required":["total_errors","total_errors_previous_period","total_errors_change_percent","error_groups","error_groups_previous_period","start_time","end_time"],"properties":{"comparison_end_time":{"type":["string","null"],"format":"date-time"},"comparison_start_time":{"type":["string","null"],"format":"date-time"},"end_time":{"type":"string","format":"date-time"},"error_groups":{"type":"integer","format":"int64"},"error_groups_previous_period":{"type":"integer","format":"int64"},"start_time":{"type":"string","format":"date-time"},"total_errors":{"type":"integer","format":"int64"},"total_errors_change_percent":{"type":"number","format":"double"},"total_errors_previous_period":{"type":"integer","format":"int64"}}},"ErrorEventResponse":{"type":"object","required":["id","error_group_id","timestamp","created_at"],"properties":{"created_at":{"type":"string"},"data":{"description":"Full error event data (contains raw Sentry event or custom error data)"},"error_group_id":{"type":"integer","format":"int32"},"id":{"type":"integer","format":"int64"},"source":{"type":["string","null"],"description":"Source of the error event (e.g., \"sentry\", \"custom\", \"bugsnag\")"},"timestamp":{"type":"string"}}},"ErrorGroupResponse":{"type":"object","required":["id","title","error_type","first_seen","last_seen","total_count","status","project_id","created_at","updated_at"],"properties":{"assigned_to":{"type":["string","null"]},"created_at":{"type":"string"},"deployment_id":{"type":["integer","null"],"format":"int32"},"environment_id":{"type":["integer","null"],"format":"int32"},"error_type":{"type":"string"},"first_seen":{"type":"string"},"id":{"type":"integer","format":"int32"},"last_seen":{"type":"string"},"message_template":{"type":["string","null"]},"project_id":{"type":"integer","format":"int32"},"status":{"type":"string"},"title":{"type":"string"},"total_count":{"type":"integer","format":"int32"},"updated_at":{"type":"string"},"visitor_id":{"type":["integer","null"],"format":"int32"}}},"ErrorGroupStatsResponse":{"type":"object","required":["total_groups","unresolved_groups","resolved_groups","ignored_groups"],"properties":{"ignored_groups":{"type":"integer","format":"int64"},"resolved_groups":{"type":"integer","format":"int64"},"total_groups":{"type":"integer","format":"int64"},"unresolved_groups":{"type":"integer","format":"int64"}}},"ErrorResponse":{"type":"object","required":["error"],"properties":{"details":{"type":["string","null"]},"error":{"type":"string"}}},"ErrorRow":{"type":"object","required":["id","ts","error_group_id","fingerprint","error_class","stacktrace_preview","stacktrace_truncated"],"properties":{"deployment_id":{"type":["integer","null"],"format":"int32"},"environment_id":{"type":["integer","null"],"format":"int32"},"error_class":{"type":"string"},"error_group_id":{"type":"integer","format":"int32"},"fingerprint":{"type":"string"},"id":{"type":"integer","format":"int64"},"message":{"type":["string","null"]},"stacktrace_preview":{},"stacktrace_truncated":{"type":"boolean"},"trace_id":{"type":["string","null"]},"ts":{"type":"string","format":"date-time"}}},"ErrorTimeSeriesDataResponse":{"type":"object","required":["timestamp","count"],"properties":{"count":{"type":"integer","format":"int64"},"timestamp":{"type":"string"}}},"ErrorTimeSeriesQuery":{"type":"object","required":["start_time","end_time"],"properties":{"bucket":{"type":"string","description":"Time bucket size (e.g., \"1h\", \"15m\", \"1d\", \"1 hour\", \"30 minutes\")","example":"1h"},"end_time":{"type":"string","format":"date-time"},"start_time":{"type":"string","format":"date-time"}}},"EventActivityBucket":{"type":"object","description":"Time bucket data point for event activity graph","required":["timestamp","count","unique_visitors"],"properties":{"count":{"type":"integer","format":"int64","description":"Number of event occurrences in this bucket"},"timestamp":{"type":"string","description":"Timestamp for this bucket (ISO 8601)"},"unique_visitors":{"type":"integer","format":"int64","description":"Number of unique visitors in this bucket"}}},"EventBreakdown":{"type":"string","enum":["country","region","city"]},"EventBrowserStats":{"type":"object","description":"Browser stats for an event","required":["browser","count","percentage"],"properties":{"browser":{"type":"string","description":"Browser name"},"count":{"type":"integer","format":"int64","description":"Number of event occurrences from this browser"},"percentage":{"type":"number","format":"double","description":"Percentage of total events"}}},"EventCount":{"type":"object","required":["event_name","count","percentage"],"properties":{"count":{"type":"integer","format":"int64"},"event_name":{"type":"string"},"percentage":{"type":"number","format":"double"}}},"EventCountryStats":{"type":"object","description":"Country stats for an event","required":["country","count","percentage"],"properties":{"count":{"type":"integer","format":"int64","description":"Number of event occurrences from this country"},"country":{"type":"string","description":"Country name"},"country_code":{"type":["string","null"],"description":"ISO country code (2-letter)"},"percentage":{"type":"number","format":"double","description":"Percentage of total events"}}},"EventDetailQuery":{"type":"object","description":"Query parameters for event detail analytics","required":["event_name","project_id","start_date","end_date"],"properties":{"bucket_interval":{"type":["string","null"],"description":"Bucket interval for time series: 'hour', 'day', 'week', 'month' (default: auto)"},"end_date":{"type":"string","format":"date-time"},"environment_id":{"type":["integer","null"],"format":"int32"},"event_name":{"type":"string","description":"The specific event name to get details for"},"project_id":{"type":"integer","format":"int32"},"start_date":{"type":"string","format":"date-time"}}},"EventDetailResponse":{"type":"object","description":"Summary response for a specific event's analytics","required":["event_name","total_count","unique_visitors","unique_sessions","activity_over_time","referrers","countries","browsers","bucket_interval"],"properties":{"activity_over_time":{"type":"array","items":{"$ref":"#/components/schemas/EventActivityBucket"},"description":"Time series data for event activity graph"},"browsers":{"type":"array","items":{"$ref":"#/components/schemas/EventBrowserStats"},"description":"Browser distribution of visitors who triggered this event"},"bucket_interval":{"type":"string","description":"Bucket interval used for time series ('hour', 'day', etc.)"},"countries":{"type":"array","items":{"$ref":"#/components/schemas/EventCountryStats"},"description":"Geographic distribution of visitors who triggered this event"},"event_name":{"type":"string","description":"The event name being analyzed"},"referrers":{"type":"array","items":{"$ref":"#/components/schemas/EventReferrerStats"},"description":"Top referrer hostnames for visitors who triggered this event"},"total_count":{"type":"integer","format":"int64","description":"Total number of times this event was triggered in the date range"},"unique_sessions":{"type":"integer","format":"int64","description":"Number of unique sessions where this event occurred"},"unique_visitors":{"type":"integer","format":"int64","description":"Number of unique visitors who triggered this event"}}},"EventEntriesQuery":{"type":"object","description":"Query parameters for the raw event entries list","required":["event_name","project_id","start_date","end_date"],"properties":{"end_date":{"type":"string","format":"date-time"},"environment_id":{"type":["integer","null"],"format":"int32"},"event_name":{"type":"string","description":"The specific event name to list occurrences for"},"page":{"type":["integer","null"],"format":"int64","description":"Page number (1-based, default: 1)","minimum":0},"per_page":{"type":["integer","null"],"format":"int64","description":"Items per page (default: 20, max: 100)","minimum":0},"project_id":{"type":"integer","format":"int32"},"start_date":{"type":"string","format":"date-time"}}},"EventEntriesResponse":{"type":"object","description":"Paginated response for raw event entries","required":["event_name","total_count","page","per_page","entries"],"properties":{"entries":{"type":"array","items":{"$ref":"#/components/schemas/EventEntryInfo"},"description":"Individual event occurrences, most recent first"},"event_name":{"type":"string","description":"The event name"},"page":{"type":"integer","format":"int64","description":"Current page number","minimum":0},"per_page":{"type":"integer","format":"int64","description":"Items per page","minimum":0},"total_count":{"type":"integer","format":"int64","description":"Total number of occurrences of this event in the date range"}}},"EventEntryInfo":{"type":"object","description":"A single raw occurrence of an event, including its custom JSON properties","required":["id","timestamp","page_path","href"],"properties":{"browser":{"type":["string","null"],"description":"Browser name"},"city":{"type":["string","null"],"description":"City of the visitor at the time of the event"},"country":{"type":["string","null"],"description":"Country of the visitor at the time of the event"},"country_code":{"type":["string","null"],"description":"ISO country code (2-letter)"},"device_type":{"type":["string","null"],"description":"Device type (Desktop, Mobile, Tablet)"},"href":{"type":"string","description":"Full URL where the event was triggered"},"id":{"type":"integer","format":"int64","description":"Event row ID"},"page_path":{"type":"string","description":"Page path where the event was triggered"},"props":{"type":["object","null"],"description":"Custom event properties as JSON (null when the event carried no data)"},"session_id":{"type":["string","null"],"description":"Session ID the event belongs to (if any)"},"timestamp":{"type":"string","format":"date-time","description":"When the event occurred"},"visitor_id":{"type":["integer","null"],"format":"int32","description":"Visitor numeric ID (if known)"},"visitor_uuid":{"type":["string","null"],"description":"Visitor UUID (if known)"}}},"EventKind":{"type":"string","description":"Tag enum for filter parameters and routing. Matches the variant\ndiscriminator used by `ObservabilityEvent`.","enum":["request","span","error","revenue"]},"EventMetricsPayload":{"type":"object","required":["event_name","event_data","request_path","request_query"],"properties":{"cls":{"type":["number","null"],"format":"float","description":"Cumulative Layout Shift (score)"},"event_data":{},"event_name":{"type":"string"},"fcp":{"type":["number","null"],"format":"float","description":"First Contentful Paint (milliseconds)"},"fid":{"type":["number","null"],"format":"float","description":"First Input Delay (milliseconds)"},"inp":{"type":["number","null"],"format":"float","description":"Interaction to Next Paint (milliseconds)"},"language":{"type":["string","null"]},"lcp":{"type":["number","null"],"format":"float","description":"Largest Contentful Paint (milliseconds)"},"page_title":{"type":["string","null"]},"referrer":{"type":["string","null"],"description":"Referrer URL (falls back to Referer header if not provided)"},"request_path":{"type":"string"},"request_query":{"type":"string"},"screen_height":{"type":["integer","null"],"format":"int32","minimum":0},"screen_width":{"type":["integer","null"],"format":"int32","minimum":0},"ttfb":{"type":["number","null"],"format":"float","description":"Time to First Byte (milliseconds)"},"viewport_height":{"type":["integer","null"],"format":"int32","minimum":0},"viewport_width":{"type":["integer","null"],"format":"int32","minimum":0}}},"EventReferrerStats":{"type":"object","description":"Referrer stats for an event","required":["referrer","count","percentage"],"properties":{"count":{"type":"integer","format":"int64","description":"Number of event occurrences from this referrer"},"percentage":{"type":"number","format":"double","description":"Percentage of total events"},"referrer":{"type":"string","description":"Referrer hostname or \"Direct\""}}},"EventTimeline":{"type":"object","required":["date","count"],"properties":{"count":{"type":"integer","format":"int64"},"date":{"type":"string","format":"date-time"}}},"EventTimelineQuery":{"type":"object","required":["start_date","end_date"],"properties":{"aggregation_level":{"$ref":"#/components/schemas/AggregationLevel","description":"Aggregation level: events (raw count), sessions (unique sessions), or visitors (unique visitors)"},"bucket_size":{"type":["string","null"],"description":"Bucket size: hour, day, or week (auto-detected if not specified)"},"end_date":{"type":"string","format":"date-time"},"environment_id":{"type":["integer","null"],"format":"int32"},"event_name":{"type":["string","null"]},"start_date":{"type":"string","format":"date-time"}}},"EventType":{"type":"object","required":["name","count"],"properties":{"count":{"type":"integer","format":"int64"},"name":{"type":"string"}}},"EventTypeBreakdown":{"type":"object","required":["event_type","count","percentage"],"properties":{"count":{"type":"integer","format":"int64"},"event_type":{"type":"string"},"percentage":{"type":"number","format":"double"}}},"EventTypeBreakdownQuery":{"type":"object","required":["start_date","end_date"],"properties":{"aggregation_level":{"$ref":"#/components/schemas/AggregationLevel","description":"Aggregation level: events (raw count), sessions (unique sessions), or visitors (unique visitors)"},"end_date":{"type":"string","format":"date-time"},"environment_id":{"type":["integer","null"],"format":"int32"},"start_date":{"type":"string","format":"date-time"}}},"EventTypeResponse":{"type":"object","required":["event_type","description","category"],"properties":{"category":{"type":"string"},"description":{"type":"string"},"event_type":{"type":"string"}}},"EventTypesResponse":{"type":"object","required":["events","total","page","page_size"],"properties":{"events":{"type":"array","items":{"$ref":"#/components/schemas/EventType"}},"page":{"type":"integer","format":"int64","minimum":0},"page_size":{"type":"integer","format":"int64","minimum":0},"total":{"type":"integer","format":"int64","minimum":0}}},"EventVisitorInfo":{"type":"object","description":"A visitor who triggered a specific event","required":["visitor_id","visitor_uuid","event_count","first_triggered","last_triggered"],"properties":{"browser":{"type":["string","null"],"description":"Browser name"},"city":{"type":["string","null"],"description":"Visitor's city"},"country":{"type":["string","null"],"description":"Visitor's country"},"country_code":{"type":["string","null"],"description":"Visitor's country code"},"device_type":{"type":["string","null"],"description":"Device type (Desktop, Mobile, Tablet)"},"event_count":{"type":"integer","format":"int64","description":"Number of times this visitor triggered the event"},"first_triggered":{"type":"string","format":"date-time","description":"When the visitor first triggered the event in the date range"},"last_triggered":{"type":"string","format":"date-time","description":"When the visitor last triggered the event in the date range"},"referrer_hostname":{"type":["string","null"],"description":"Referrer hostname for the event"},"visitor_id":{"type":"integer","format":"int32","description":"Visitor numeric ID"},"visitor_uuid":{"type":"string","description":"Visitor UUID"}}},"EventVisitorsQuery":{"type":"object","description":"Query parameters for event visitors list","required":["event_name","project_id","start_date","end_date"],"properties":{"end_date":{"type":"string","format":"date-time"},"environment_id":{"type":["integer","null"],"format":"int32"},"event_name":{"type":"string","description":"The specific event name to list visitors for"},"page":{"type":["integer","null"],"format":"int64","description":"Page number (1-based, default: 1)","minimum":0},"per_page":{"type":["integer","null"],"format":"int64","description":"Items per page (default: 20, max: 100)","minimum":0},"project_id":{"type":"integer","format":"int32"},"start_date":{"type":"string","format":"date-time"}}},"EventVisitorsResponse":{"type":"object","description":"Paginated response for event visitors","required":["event_name","total_count","page","per_page","visitors"],"properties":{"event_name":{"type":"string","description":"The event name"},"page":{"type":"integer","format":"int64","description":"Current page number","minimum":0},"per_page":{"type":"integer","format":"int64","description":"Items per page","minimum":0},"total_count":{"type":"integer","format":"int64","description":"Total number of unique visitors who triggered this event"},"visitors":{"type":"array","items":{"$ref":"#/components/schemas/EventVisitorInfo"},"description":"Individual visitors who triggered this event"}}},"EventsCountQuery":{"type":"object","required":["start_date","end_date"],"properties":{"aggregation_level":{"$ref":"#/components/schemas/AggregationLevel","description":"Aggregation level: events (raw count), sessions (unique sessions), or visitors (unique visitors)"},"custom_events_only":{"type":["boolean","null"],"description":"Only return custom events, excluding system events like page_view, page_leave, heartbeat (default: true)"},"end_date":{"type":"string","format":"date-time"},"environment_id":{"type":["integer","null"],"format":"int32"},"limit":{"type":["integer","null"],"format":"int32"},"start_date":{"type":"string","format":"date-time"}}},"EventsResponse":{"type":"object","required":["events","applied_kinds"],"properties":{"applied_kinds":{"type":"array","items":{"$ref":"#/components/schemas/EventKind"},"description":"Echo of the kinds filter actually applied (server-resolved). Useful\nfor clients that pass `kinds=` empty and want to know what they got."},"events":{"type":"array","items":{"$ref":"#/components/schemas/ObservabilityEvent"}}}},"ExecBody":{"type":"object","required":["cmd"],"properties":{"cmd":{"type":"array","items":{"type":"string"}},"cwd":{"type":["string","null"]},"env":{"type":"object","additionalProperties":{"type":"string"},"propertyNames":{"type":"string"}}},"additionalProperties":false},"ExecDetachedResponse":{"type":"object","required":["job_id"],"properties":{"job_id":{"type":"string"}}},"ExecResponse":{"type":"object","required":["exit_code","stdout","stderr"],"properties":{"exit_code":{"type":"integer","format":"int32"},"stderr":{"type":"string"},"stdout":{"type":"string"}}},"ExecuteImportRequest":{"type":"object","description":"Request to execute an import","required":["session_id","project_name","preset","directory","main_branch"],"properties":{"directory":{"type":"string","description":"Project directory","example":"."},"dry_run":{"type":["boolean","null"],"description":"Dry run mode (don't create resources)"},"main_branch":{"type":"string","description":"Main branch name","example":"main"},"preset":{"type":"string","description":"Preset to use for the project (e.g., \"nextjs\", \"express\", \"docker\")"},"project_name":{"type":"string","description":"Project name to use (overrides the name from the plan)","example":"my-app"},"session_id":{"type":"string","description":"Session ID from plan creation"}}},"ExecuteImportResponse":{"type":"object","description":"Response from import execution","required":["session_id","status","step_results"],"properties":{"deployment_id":{"type":["integer","null"],"format":"int32","description":"Created deployment ID (if completed)"},"environment_id":{"type":["integer","null"],"format":"int32","description":"Created environment ID (if completed)"},"project_id":{"type":["integer","null"],"format":"int32","description":"Created project ID (if completed)"},"session_id":{"type":"string","description":"Session ID"},"status":{"$ref":"#/components/schemas/ImportExecutionStatus","description":"Execution status"},"step_results":{"type":"array","items":{"$ref":"#/components/schemas/StepResult"},"description":"Per-step results (in execution order)"}}},"ExecuteOperationRequest":{"type":"object","required":["operation"],"properties":{"operation":{"type":"string"}}},"ExpireRequest":{"type":"object","description":"Request to set expiration on a key","required":["key","seconds"],"properties":{"key":{"type":"string","description":"The key to set expiration on","example":"session:abc"},"project_id":{"type":["integer","null"],"format":"int32","description":"Project ID (required for API key/session auth, optional for deployment tokens)","example":1},"seconds":{"type":"integer","format":"int64","description":"Expiration time in seconds","example":3600}}},"ExpireResponse":{"type":"object","description":"Response for expire operation","required":["success"],"properties":{"success":{"type":"boolean","description":"True if expiration was set, false if key doesn't exist"}}},"ExplorerSupportResponse":{"type":"object","required":["supported","service_type","capabilities","hierarchy"],"properties":{"capabilities":{"type":"array","items":{"type":"string"},"description":"Capabilities supported by this service","example":["sql"]},"filter_schema":{"description":"JSON Schema for filter format with embedded UI hints (if supported)"},"hierarchy":{"type":"array","items":{"$ref":"#/components/schemas/HierarchyLevel"},"description":"Hierarchy levels (describes the navigation structure)"},"reason":{"type":["string","null"],"description":"Reason why explorer is not supported (if applicable)"},"service_type":{"type":"string","description":"Service type","example":"postgres"},"supported":{"type":"boolean","description":"Whether the service supports query explorer functionality","example":true}}},"ExtendTimeoutBody":{"type":"object","properties":{"duration":{"type":["integer","null"],"format":"int64","description":"`@vercel/sandbox`-compatible alternative — duration in milliseconds.\nUsed when `extra_secs` is absent.","minimum":0},"extra_secs":{"type":["integer","null"],"format":"int64","description":"Extra seconds to add to the existing `expires_at` (temps-native).","minimum":0}}},"ExternalImageResponse":{"type":"object","required":["id","project_id","image_ref","pushed_at","created_at"],"properties":{"created_at":{"type":"string","format":"date-time","example":"2025-10-12T12:15:47.609192Z"},"digest":{"type":["string","null"]},"id":{"type":"integer","format":"int32"},"image_ref":{"type":"string"},"metadata":{},"project_id":{"type":"integer","format":"int32"},"pushed_at":{"type":"string","format":"date-time","example":"2025-10-12T12:15:47.609192Z"},"size_bytes":{"type":["integer","null"],"format":"int64"},"tag":{"type":["string","null"]}}},"ExternalServiceBackupResponse":{"type":"object","description":"Response type for external service backup","required":["id","service_id","backup_id","backup_type","state","started_at","s3_location","metadata","compression_type","created_by"],"properties":{"backup_id":{"type":"integer","format":"int32"},"backup_type":{"type":"string"},"checksum":{"type":["string","null"]},"compression_type":{"type":"string"},"created_by":{"type":"integer","format":"int32"},"error_message":{"type":["string","null"]},"expires_at":{"type":["string","null"],"example":"2025-02-15T14:30:00.123Z"},"finished_at":{"type":["string","null"],"example":"2025-01-15T14:35:00.456Z"},"id":{"type":"integer","format":"int32"},"metadata":{},"s3_location":{"type":"string"},"service_id":{"type":"integer","format":"int32"},"size_bytes":{"type":["integer","null"],"format":"int64"},"started_at":{"type":"string","example":"2025-01-15T14:30:00.123Z"},"state":{"type":"string"}}},"ExternalServiceDetails":{"type":"object","required":["service","sensitive_parameters"],"properties":{"current_parameters":{"type":["object","null"],"additionalProperties":{"type":"string"},"propertyNames":{"type":"string"}},"parameter_schema":{},"sensitive_parameters":{"type":"array","items":{"type":"string"},"description":"Parameter names whose values are masked in `current_parameters` and\nmay be fetched only through the audited reveal endpoint."},"service":{"$ref":"#/components/schemas/ExternalServiceInfo"}}},"ExternalServiceInfo":{"type":"object","required":["id","name","service_type","status","created_at","updated_at","topology"],"properties":{"connection_info":{"type":["string","null"]},"created_at":{"type":"string"},"error_message":{"type":["string","null"],"description":"Error message from failed initialization."},"id":{"type":"integer","format":"int32"},"members":{"type":"array","items":{"$ref":"#/components/schemas/ServiceMemberInfo"},"description":"Cluster members (empty for standalone services)."},"metrics_enabled":{"type":"boolean","description":"Whether metric collection is enabled for this service. The UI uses this\nto decide whether to poll the monitoring endpoints."},"name":{"type":"string"},"node_id":{"type":["integer","null"],"format":"int32","description":"Node ID where the service runs. Null means control plane (local)."},"service_type":{"$ref":"#/components/schemas/ServiceTypeRoute"},"status":{"type":"string"},"topology":{"type":"string","description":"Service topology: \"standalone\" (single container) or \"cluster\" (HA multi-member).","example":"standalone"},"updated_at":{"type":"string"},"version":{"type":["string","null"]}}},"ExternalServiceSummary":{"type":"object","description":"Summary of the external service that owns a backup. Only populated for\nexternal-service backups (Redis, Postgres, etc.); absent for control-plane\nbackups.","required":["id","name","service_type"],"properties":{"id":{"type":"integer","format":"int32","description":"Database id of the external service."},"name":{"type":"string","description":"Human-readable service name (e.g. \"redis-prod\")."},"service_type":{"type":"string","description":"Service type string (e.g. \"postgres\", \"redis\", \"mongodb\").","example":"postgres"}}},"FieldResponse":{"type":"object","required":["name","field_type","nullable"],"properties":{"field_type":{"type":"string","description":"Field type (Int32, String, Timestamp, etc.)","example":"Int64"},"name":{"type":"string","description":"Field name","example":"id"},"nullable":{"type":"boolean","description":"Whether the field is nullable","example":false}}},"FiringSeriesEntry":{"type":"object","description":"A single currently-firing series for a dynamic alert rule, snapshotted from\nthe evaluator's in-memory per-series firing map at read time (ADR-026 Phase 3).","required":["series_key","series_label"],"properties":{"alarm_id":{"type":["integer","null"],"format":"int32","description":"The open alarm's id, when one was created (absent if suppressed)."},"series_key":{"type":"array","items":{"type":"array","items":false,"prefixItems":[{"type":"string"},{"type":"string"}]},"description":"The series' label pairs, e.g. `[[\"endpoint\",\"/checkout\"],[\"region\",\"eu-west\"]]`."},"series_label":{"type":"string","description":"The human-readable joined label, e.g. `endpoint=/checkout, region=eu-west`."}}},"FlagEnvironmentResponse":{"type":"object","required":["environment_id","enabled"],"properties":{"enabled":{"type":"boolean"},"environment_id":{"type":"integer","format":"int32"},"value":{}}},"FlagListResponse":{"type":"object","description":"Note the absence of `salt`: it is never exposed. Publishing the bucketing\nsalt would let a client predict, and self-select into, a rollout cohort.","required":["flags","total","page","page_size","total_pages"],"properties":{"flags":{"type":"array","items":{"$ref":"#/components/schemas/FlagResponse"}},"page":{"type":"integer","format":"int64","minimum":0},"page_size":{"type":"integer","format":"int64","minimum":0},"total":{"type":"integer","format":"int64","description":"Total flags matching the filter, across all pages.","minimum":0},"total_pages":{"type":"integer","format":"int64","minimum":0}}},"FlagResponse":{"type":"object","required":["id","key","value_type","default_value","client_visible","created_at","updated_at","environments"],"properties":{"archived_at":{"type":["string","null"]},"client_visible":{"type":"boolean"},"created_at":{"type":"string"},"default_value":{},"description":{"type":["string","null"]},"environments":{"type":"array","items":{"$ref":"#/components/schemas/FlagEnvironmentResponse"},"description":"Per-environment overrides. Empty means the flag inherits its default\neverywhere."},"id":{"type":"integer","format":"int32"},"key":{"type":"string"},"last_evaluated_at":{"type":["string","null"],"description":"When an app last actually evaluated this flag. `None` means never seen,\nwhich is a real answer rather than missing data."},"updated_at":{"type":"string"},"value_type":{"type":"string"}}},"FlagSnapshot":{"type":"object","description":"A single flag, already resolved down to one environment. This is what the\nevaluator sees and what the SDK caches in memory.","required":["key","value_type","default_value","enabled"],"properties":{"default_value":{"description":"Served whenever evaluation cannot do better. Genuinely polymorphic by\ndesign — the surrounding struct carries the type."},"enabled":{"type":"boolean","description":"False means the kill switch is engaged for this environment."},"environment_value":{"description":"`None` means \"inherit `default_value`\"."},"key":{"type":"string"},"value_type":{"$ref":"#/components/schemas/FlagValueType"}}},"FlagSnapshotResponse":{"type":"object","required":["environment_id","flags"],"properties":{"environment_id":{"type":"integer","format":"int32"},"flags":{"type":"array","items":{"$ref":"#/components/schemas/FlagSnapshot"},"description":"Flags collapsed to what the evaluator needs, sorted by key so the\nserialized form — and therefore the ETag — is stable."}}},"FlagValueType":{"type":"string","description":"The declared type of a flag's value. Fixed at create time.","enum":["bool","string","number","json"]},"ForecastAlgorithm":{"type":"string","description":"Forecast model family.","enum":["linear","seasonal"]},"ForecastParams":{"type":"object","description":"Forecast detector parameters (stub — not yet evaluated).","required":["forecast_horizon_secs","comparator","threshold"],"properties":{"algorithm":{"$ref":"#/components/schemas/ForecastAlgorithm"},"comparator":{"$ref":"#/components/schemas/Comparator","description":"Comparator + threshold the *forecast* is checked against."},"deviations":{"type":"number","format":"double"},"forecast_horizon_secs":{"type":"integer","format":"int32","description":"How far ahead to project before checking the breach condition."},"threshold":{"type":"number","format":"double"}}},"FullError":{"type":"object","required":["id","ts","error_group_id","fingerprint","error_class"],"properties":{"data":{"description":"Full JSONB blob from `error_events.data` — stack trace, breadcrumbs,\nrequest context, everything. Schema is documented per source SDK."},"deployment_id":{"type":["integer","null"],"format":"int32"},"environment_id":{"type":["integer","null"],"format":"int32"},"error_class":{"type":"string"},"error_group_id":{"type":"integer","format":"int32"},"fingerprint":{"type":"string"},"id":{"type":"integer","format":"int64"},"message":{"type":["string","null"]},"trace_id":{"type":["string","null"]},"ts":{"type":"string","format":"date-time"}}},"FullEvent":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/FullRequest"},{"type":"object","required":["type"],"properties":{"type":{"type":"string","enum":["request"]}}}]},{"allOf":[{"$ref":"#/components/schemas/FullError"},{"type":"object","required":["type"],"properties":{"type":{"type":"string","enum":["error"]}}}]},{"allOf":[{"$ref":"#/components/schemas/RevenueRow"},{"type":"object","required":["type"],"properties":{"type":{"type":"string","enum":["revenue"]}}}]},{"allOf":[{"$ref":"#/components/schemas/SpanRow","description":"`SpanRow.attributes` is the truncated form; re-fetching returns\nthe same shape so the panel has a stable contract."},{"type":"object","required":["type"],"properties":{"type":{"type":"string","enum":["span"]}}}],"description":"`SpanRow.attributes` is the truncated form; re-fetching returns\nthe same shape so the panel has a stable contract."}],"description":"One un-truncated row, returned by the `/full/{type}/{id}` endpoint when\nthe user clicks \"Show full\". Same shape as the list rows, but with the\nraw heavy fields restored (no truncation flags) so the side panel can\nrender the long form."},"FullRequest":{"type":"object","required":["id","ts","method","host","path","status"],"properties":{"client_ip":{"type":["string","null"]},"deployment_id":{"type":["integer","null"],"format":"int32"},"environment_id":{"type":["integer","null"],"format":"int32"},"error_group_id":{"type":["integer","null"],"format":"int32"},"host":{"type":"string"},"id":{"type":"string","description":"The request's unique `request_id` — same identity the list rows carry\n(backend-agnostic; ClickHouse rows have no serial PK)."},"latency_ms":{"type":["integer","null"],"format":"int32"},"method":{"type":"string"},"path":{"type":"string"},"referrer":{"type":["string","null"]},"request_headers":{},"response_headers":{},"status":{"type":"integer","format":"int32"},"trace_id":{"type":["string","null"]},"ts":{"type":"string","format":"date-time"},"user_agent":{"type":["string","null"]}}},"FunnelMetricsResponse":{"type":"object","required":["funnel_id","funnel_name","total_entries","step_conversions","overall_conversion_rate","average_completion_time_seconds"],"properties":{"average_completion_time_seconds":{"type":"number","format":"double"},"funnel_id":{"type":"integer","format":"int32"},"funnel_name":{"type":"string"},"overall_conversion_rate":{"type":"number","format":"double"},"step_conversions":{"type":"array","items":{"$ref":"#/components/schemas/StepConversionResponse"}},"total_entries":{"type":"integer","format":"int64","minimum":0}}},"FunnelResponse":{"type":"object","required":["id","name","is_active","created_at","updated_at"],"properties":{"created_at":{"type":"string"},"description":{"type":["string","null"]},"id":{"type":"integer","format":"int32"},"is_active":{"type":"boolean"},"name":{"type":"string"},"updated_at":{"type":"string"}}},"GatewayStatus":{"type":"object","description":"Detailed gateway container status surfaced to the settings UI.","required":["present","running","health","container_name","expected_image","drift","auto_upgrade"],"properties":{"auto_upgrade":{"type":"boolean","description":"True if `auto_upgrade` is enabled in settings."},"container_name":{"type":"string","description":"Container name."},"drift":{"type":"boolean","description":"True when `image != expected_image` and the container is present."},"expected_image":{"type":"string","description":"The image the supervisor *expects* (from settings/constant). If this\ndiffers from `image`, the UI shows a \"drift\" badge."},"health":{"type":"string","description":"Higher-level health label: \"running\" | \"restarting\" | \"crash_looping\"\n| \"stopped\" | \"missing\". UI should prefer this over `running`."},"host_port":{"type":["integer","null"],"format":"int32","description":"Host port that the container's :8080 is published on.","minimum":0},"image":{"type":["string","null"],"description":"Image reference the container was created with (e.g.\n`ghcr.io/gotempsh/temps-preview-gateway:latest`)."},"image_digest":{"type":["string","null"],"description":"Image digest if available (e.g. `sha256:…`)."},"last_error":{"type":["string","null"],"description":"Error string Docker recorded for the container (e.g. startup failure)."},"last_exit_code":{"type":["integer","null"],"format":"int64","description":"Exit code of the last run, if the container is not currently running."},"network":{"type":["string","null"],"description":"Network the container is attached to (should be `temps-sandbox-net`)."},"present":{"type":"boolean","description":"Whether the container exists at all."},"restart_count":{"type":["integer","null"],"format":"int64","description":"Number of times Docker has restarted the container."},"running":{"type":"boolean","description":"Whether the container is currently running."},"started_at":{"type":["string","null"],"description":"ISO 8601 timestamp the container was started at, if running."}}},"GenAiEvent":{"type":"object","description":"A GenAI-related event extracted from span events.\n\nCovers `gen_ai.client.inference.operation.details` and `gen_ai.evaluation.result`\nevents per the OTel GenAI semantic conventions.","required":["span_id","trace_id","event_name","timestamp","attributes"],"properties":{"attributes":{"type":"object","description":"All event attributes.","additionalProperties":{"type":"string"},"propertyNames":{"type":"string"}},"event_name":{"type":"string"},"span_id":{"type":"string"},"timestamp":{"type":"string","format":"date-time"},"trace_id":{"type":"string"}}},"GenAiSpanDetail":{"type":"object","description":"A single GenAI span with extracted semantic convention fields.\n\nFields are aligned with the OpenTelemetry GenAI Semantic Conventions spec:\n","required":["span_id","name","kind","start_time","duration_ms","status_code","attributes"],"properties":{"agent_description":{"type":["string","null"],"description":"Agent description from `gen_ai.agent.description`."},"agent_id":{"type":["string","null"],"description":"Agent identifier from `gen_ai.agent.id`."},"agent_name":{"type":["string","null"],"description":"Agent name from `gen_ai.agent.name`."},"agent_version":{"type":["string","null"],"description":"Agent version from `gen_ai.agent.version`."},"attributes":{"type":"object","description":"All span attributes for extensibility.","additionalProperties":{"type":"string"},"propertyNames":{"type":"string"}},"aws_bedrock_guardrail_id":{"type":["string","null"],"description":"AWS Bedrock guardrail ID from `aws.bedrock.guardrail.id`."},"aws_bedrock_knowledge_base_id":{"type":["string","null"],"description":"AWS Bedrock knowledge base ID from `aws.bedrock.knowledge_base.id`."},"azure_resource_provider_namespace":{"type":["string","null"],"description":"Azure resource provider namespace from `azure.resource_provider.namespace`."},"cache_creation_input_tokens":{"type":["integer","null"],"format":"int64","description":"Tokens written to provider cache from `gen_ai.usage.cache_creation.input_tokens`."},"cache_read_input_tokens":{"type":["integer","null"],"format":"int64","description":"Tokens served from provider cache from `gen_ai.usage.cache_read.input_tokens`."},"conversation_id":{"type":["string","null"],"description":"Unique conversation/session/thread ID from `gen_ai.conversation.id`."},"data_source_id":{"type":["string","null"],"description":"Data source identifier from `gen_ai.data_source.id`."},"duration_ms":{"type":"number","format":"double"},"embeddings_dimension_count":{"type":["integer","null"],"format":"int64","description":"Output embedding dimensions from `gen_ai.embeddings.dimension.count`."},"error_type":{"type":["string","null"],"description":"Error type from `error.type` when the span status is ERROR."},"gen_ai_model":{"type":["string","null"],"description":"The requested model from `gen_ai.request.model`."},"gen_ai_operation":{"type":["string","null"],"description":"The operation type from `gen_ai.operation.name` (e.g. \"chat\", \"embeddings\", \"execute_tool\")."},"gen_ai_response_model":{"type":["string","null"],"description":"The model that actually generated the response from `gen_ai.response.model`."},"gen_ai_system":{"type":["string","null"],"description":"The GenAI provider from `gen_ai.provider.name` (falls back to deprecated `gen_ai.system`)."},"input_messages":{"type":["string","null"],"description":"Chat history input from `gen_ai.input.messages` (opt-in, JSON string)."},"input_tokens":{"type":["integer","null"],"format":"int64"},"kind":{"$ref":"#/components/schemas/SpanKind"},"name":{"type":"string"},"openai_api_type":{"type":["string","null"],"description":"OpenAI API type from `openai.api.type` (chat_completions, responses)."},"openai_request_service_tier":{"type":["string","null"],"description":"Requested service tier from `openai.request.service_tier`."},"openai_response_service_tier":{"type":["string","null"],"description":"Actual service tier from `openai.response.service_tier`."},"openai_system_fingerprint":{"type":["string","null"],"description":"System fingerprint from `openai.response.system_fingerprint`."},"output_messages":{"type":["string","null"],"description":"Model output from `gen_ai.output.messages` (opt-in, JSON string)."},"output_tokens":{"type":["integer","null"],"format":"int64"},"output_type":{"type":["string","null"],"description":"Output content type from `gen_ai.output.type` (text, json, image, speech)."},"parent_span_id":{"type":["string","null"]},"request_choice_count":{"type":["integer","null"],"format":"int64","description":"Number of choices requested from `gen_ai.request.choice.count`."},"request_encoding_formats":{"type":["array","null"],"items":{"type":"string"},"description":"Requested encoding formats from `gen_ai.request.encoding_formats`."},"request_frequency_penalty":{"type":["number","null"],"format":"double","description":"Frequency penalty from `gen_ai.request.frequency_penalty`."},"request_max_tokens":{"type":["integer","null"],"format":"int64","description":"Max tokens from `gen_ai.request.max_tokens`."},"request_presence_penalty":{"type":["number","null"],"format":"double","description":"Presence penalty from `gen_ai.request.presence_penalty`."},"request_seed":{"type":["integer","null"],"format":"int64","description":"Seed for reproducibility from `gen_ai.request.seed`."},"request_stop_sequences":{"type":["array","null"],"items":{"type":"string"},"description":"Stop sequences from `gen_ai.request.stop_sequences`."},"request_temperature":{"type":["number","null"],"format":"double","description":"Temperature setting from `gen_ai.request.temperature`."},"request_top_k":{"type":["number","null"],"format":"double","description":"Top-k setting from `gen_ai.request.top_k`."},"request_top_p":{"type":["number","null"],"format":"double","description":"Top-p setting from `gen_ai.request.top_p`."},"response_finish_reasons":{"type":["array","null"],"items":{"type":"string"},"description":"Reasons the model stopped from `gen_ai.response.finish_reasons` (e.g. [\"stop\"])."},"response_id":{"type":["string","null"],"description":"Unique completion ID from `gen_ai.response.id` (e.g. \"chatcmpl-123\")."},"retrieval_documents":{"type":["string","null"],"description":"Retrieved documents from `gen_ai.retrieval.documents` (opt-in, JSON string)."},"retrieval_query_text":{"type":["string","null"],"description":"Retrieval query text from `gen_ai.retrieval.query.text` (opt-in)."},"server_address":{"type":["string","null"],"description":"GenAI server address from `server.address`."},"server_port":{"type":["integer","null"],"format":"int64","description":"GenAI server port from `server.port`."},"span_id":{"type":"string"},"start_time":{"type":"string","format":"date-time"},"status_code":{"$ref":"#/components/schemas/SpanStatusCode"},"system_instructions":{"type":["string","null"],"description":"System instructions from `gen_ai.system_instructions` (opt-in, JSON string)."},"tool_call_arguments":{"type":["string","null"],"description":"Tool call arguments from `gen_ai.tool.call.arguments` (opt-in, JSON string)."},"tool_call_id":{"type":["string","null"],"description":"Tool call ID from `gen_ai.tool.call.id`."},"tool_call_result":{"type":["string","null"],"description":"Tool call result from `gen_ai.tool.call.result` (opt-in, JSON string)."},"tool_definitions":{"type":["string","null"],"description":"Tool definitions from `gen_ai.tool.definitions` (opt-in, JSON string)."},"tool_description":{"type":["string","null"],"description":"Tool description from `gen_ai.tool.description`."},"tool_name":{"type":["string","null"],"description":"Tool name from `gen_ai.tool.name`."},"tool_type":{"type":["string","null"],"description":"Tool type from `gen_ai.tool.type` (function, extension, datastore)."}}},"GenAiTraceDetailResponse":{"type":"object","required":["trace_id","spans","span_count","events","event_count"],"properties":{"event_count":{"type":"integer","minimum":0},"events":{"type":"array","items":{"$ref":"#/components/schemas/GenAiEvent"}},"span_count":{"type":"integer","minimum":0},"spans":{"type":"array","items":{"$ref":"#/components/schemas/GenAiSpanDetail"}},"trace_id":{"type":"string"}}},"GenAiTraceSummariesResponse":{"type":"object","required":["data","total"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/GenAiTraceSummary"}},"total":{"type":"integer","format":"int64","minimum":0}}},"GenAiTraceSummary":{"type":"object","description":"Summary of a GenAI conversation — aggregated from OTel spans with `gen_ai.*` attributes.","required":["trace_id","root_span_name","service_name","start_time","duration_ms","span_count","error_count"],"properties":{"duration_ms":{"type":"number","format":"double"},"error_count":{"type":"integer","format":"int64"},"gen_ai_model":{"type":["string","null"],"description":"The requested model from `gen_ai.request.model`."},"gen_ai_operation":{"type":["string","null"],"description":"The operation type from `gen_ai.operation.name` (e.g. \"chat\", \"embeddings\")."},"gen_ai_system":{"type":["string","null"],"description":"The GenAI provider (e.g. \"openai\", \"anthropic\") from `gen_ai.provider.name`."},"root_span_name":{"type":"string"},"service_name":{"type":"string"},"span_count":{"type":"integer","format":"int64"},"start_time":{"type":"string","format":"date-time"},"total_cache_creation_input_tokens":{"type":["integer","null"],"format":"int64","description":"Total cache-creation input tokens across all spans."},"total_cache_read_input_tokens":{"type":["integer","null"],"format":"int64","description":"Total cache-read input tokens across all spans."},"total_input_tokens":{"type":["integer","null"],"format":"int64","description":"Total input tokens across all spans in this trace."},"total_output_tokens":{"type":["integer","null"],"format":"int64","description":"Total output tokens across all spans in this trace."},"trace_id":{"type":"string"}}},"GeneralStatsQuery":{"type":"object","required":["start_date","end_date"],"properties":{"end_date":{"type":"string","format":"date-time"},"start_date":{"type":"string","format":"date-time"}}},"GeneralStatsResponse":{"type":"object","required":["total_unique_visitors","total_visits","total_page_views","total_events","total_projects","avg_bounce_rate","avg_engagement_rate","project_breakdown"],"properties":{"avg_bounce_rate":{"type":"number","format":"double"},"avg_engagement_rate":{"type":"number","format":"double"},"page_views_trend_percentage":{"type":["number","null"],"format":"double","description":"Percentage change in page views vs previous period"},"previous_page_views":{"type":["integer","null"],"format":"int64","description":"Previous period page views"},"previous_unique_visitors":{"type":["integer","null"],"format":"int64","description":"Previous period unique visitors (same duration, shifted back)"},"project_breakdown":{"type":"array","items":{"$ref":"#/components/schemas/ProjectStatsBreakdown"}},"total_events":{"type":"integer","format":"int64"},"total_page_views":{"type":"integer","format":"int64"},"total_projects":{"type":"integer","format":"int64"},"total_unique_visitors":{"type":"integer","format":"int64"},"total_visits":{"type":"integer","format":"int64"},"visitors_trend_percentage":{"type":["number","null"],"format":"double","description":"Percentage change in unique visitors vs previous period"}}},"GenerateDockerfileRequest":{"type":"object","description":"Request body for generating a Dockerfile from a preset","properties":{"build_command":{"type":["string","null"],"description":"Custom build command (overrides preset default)","example":"npm run build"},"install_command":{"type":["string","null"],"description":"Custom install command (overrides preset default)","example":"npm ci"},"output_dir":{"type":["string","null"],"description":"Output directory for static builds","example":"dist"},"package_manager":{"type":["string","null"],"description":"Package manager used by the project (npm, yarn, pnpm, bun)\nIf not provided, defaults to npm","example":"npm"},"project_name":{"type":["string","null"],"description":"Project name/slug used for container naming","example":"my-app"},"use_buildkit":{"type":"boolean","description":"Whether to use BuildKit cache mounts for faster builds"}}},"GenerateDockerfileResponse":{"type":"object","description":"Response containing a generated Dockerfile and build arguments","required":["dockerfile","build_args","preset"],"properties":{"build_args":{"type":"object","description":"Build arguments to pass to `docker build --build-arg KEY=VALUE`","additionalProperties":{"type":"string"},"propertyNames":{"type":"string"}},"dockerfile":{"type":"string","description":"The generated Dockerfile content"},"preset":{"type":"string","description":"The preset slug used for generation"}}},"GenerateJoinTokenResponse":{"type":"object","description":"Response returned when a join token is generated (plaintext shown once)","required":["token","message"],"properties":{"message":{"type":"string"},"token":{"type":"string","description":"The plaintext join token — shown only once, save it now"}}},"GeoLocationResponse":{"type":"object","description":"Response containing geolocation information for an IP address","required":["ip","is_eu"],"properties":{"city":{"type":["string","null"],"description":"City name","example":"Mountain View"},"country":{"type":["string","null"],"description":"Country name","example":"United States"},"country_code":{"type":["string","null"],"description":"ISO country code (2 letters)","example":"US"},"ip":{"type":"string","description":"IP address that was geolocated","example":"8.8.8.8"},"is_eu":{"type":"boolean","description":"Whether the IP is in the European Union","example":false},"latitude":{"type":["number","null"],"format":"double","description":"Latitude coordinate","example":37.386},"longitude":{"type":["number","null"],"format":"double","description":"Longitude coordinate","example":-122.0838},"region":{"type":["string","null"],"description":"Region/state name","example":"California"},"timezone":{"type":["string","null"],"description":"Timezone identifier","example":"America/Los_Angeles"}}},"GeoRestrictionsConfig":{"type":"object","description":"Geographic restrictions configuration (future feature)","properties":{"allowedCountries":{"type":"array","items":{"type":"string"},"description":"Allow traffic only from specific countries"},"blockedCountries":{"type":"array","items":{"type":"string"},"description":"Block traffic from specific countries (ISO 3166-1 alpha-2 codes)"}}},"GetDeploymentsParams":{"type":"object","properties":{"environment_id":{"type":["integer","null"],"format":"int32"},"page":{"type":["integer","null"],"format":"int64"},"per_page":{"type":["integer","null"],"format":"int64"}}},"GetEnvironmentVariablesQuery":{"type":"object","properties":{"environment_id":{"type":["integer","null"],"format":"int32"},"service_id":{"type":["integer","null"],"format":"int32","description":"Required by integration-value reveals to bind the plaintext response to\nthe exact service displayed by the client."},"var_id":{"type":["integer","null"],"format":"int32","description":"Exact manual env-var row to reveal. Required by the dashboard so\nduplicate keys on disjoint environments cannot cross-reveal."}}},"GetFunnelMetricsQuery":{"type":"object","properties":{"country_code":{"type":["string","null"]},"end_date":{"type":["string","null"],"format":"date-time"},"environment_id":{"type":["integer","null"],"format":"int32"},"start_date":{"type":["string","null"],"format":"date-time"}}},"GetOrCreateDSNRequest":{"type":"object","properties":{"base_url":{"type":["string","null"]},"deployment_id":{"type":["integer","null"],"format":"int32"},"environment_id":{"type":["integer","null"],"format":"int32"}}},"GetProjectSecretsQuery":{"type":"object","properties":{"environment_id":{"type":["integer","null"],"format":"int32"}}},"GetProjectSessionReplaysQuery":{"type":"object","required":["project_id"],"properties":{"environment_id":{"type":["integer","null"],"format":"int32"},"page":{"type":["integer","null"],"format":"int64","minimum":0},"per_page":{"type":["integer","null"],"format":"int64","minimum":0},"project_id":{"type":"integer","format":"int32"}}},"GetProjectSessionReplaysResponse":{"type":"object","required":["sessions","page","per_page","total_count"],"properties":{"page":{"type":"integer","format":"int64","minimum":0},"per_page":{"type":"integer","format":"int64","minimum":0},"sessions":{"type":"array","items":{"$ref":"#/components/schemas/SessionReplayWithVisitorDto"}},"total_count":{"type":"integer","format":"int64","minimum":0}}},"GetRequest":{"type":"object","description":"Request to get a value by key","required":["key"],"properties":{"key":{"type":"string","description":"The key to retrieve","example":"user:123"},"project_id":{"type":["integer","null"],"format":"int32","description":"Project ID (required for API key/session auth, optional for deployment tokens)","example":1}}},"GetResponse":{"type":"object","description":"Response for get operation","properties":{"value":{"description":"The value, or null if not found"}}},"GetSessionReplayResponse":{"type":"object","required":["session"],"properties":{"session":{"$ref":"#/components/schemas/SessionReplayWithVisitorDto"}}},"GetUniqueEventsQuery":{"type":"object","properties":{"page":{"type":["integer","null"],"format":"int64","minimum":0},"page_size":{"type":["integer","null"],"format":"int64","minimum":0}}},"GetVisitorSessionsQuery":{"type":"object","properties":{"page":{"type":["integer","null"],"format":"int64","minimum":0},"per_page":{"type":["integer","null"],"format":"int64","minimum":0}}},"GetVisitorSessionsResponse":{"type":"object","required":["sessions","page","per_page","total_count"],"properties":{"page":{"type":"integer","format":"int64","minimum":0},"per_page":{"type":"integer","format":"int64","minimum":0},"sessions":{"type":"array","items":{"$ref":"#/components/schemas/SessionReplayWithVisitorDto"}},"total_count":{"type":"integer","minimum":0}}},"GitPushEvent":{"type":"object","description":"Git push event information that triggered the deployment","required":["repo","owner","branch","commit"],"properties":{"branch":{"type":"string","description":"Branch that was pushed"},"commit":{"type":"string","description":"Commit SHA"},"owner":{"type":"string","description":"Repository owner/organization"},"repo":{"type":"string","description":"Repository name"}}},"GitRefResponse":{"type":"object","description":"Git repository reference response","required":["url","ref"],"properties":{"path":{"type":["string","null"],"description":"Path within the repository (for monorepos)"},"ref":{"type":"string","description":"Git reference (branch, tag, or commit)"},"url":{"type":"string","description":"Git repository URL"}}},"GitSourcePlan":{"type":"object","description":"Git repository the source platform deploys from","required":["owner","repo","branch","is_public"],"properties":{"branch":{"type":"string","description":"Branch the source platform deploys"},"clone_url":{"type":["string","null"],"description":"Full clone URL, e.g. `https://github.com/owner/repo.git`"},"is_public":{"type":"boolean","description":"True when the repository is public (no credentials on the source\nplatform) — the project can then build without a git provider\nconnection."},"owner":{"type":"string","description":"Repository owner (organization or user)"},"repo":{"type":"string","description":"Repository name"}}},"GlobalConversationResponse":{"type":"object","description":"A conversation in the unified cross-project switcher: carries the project it\nbelongs to (name/slug) so the UI can show where the chat was started and\nlink back to the source.","required":["public_id","project_id","context_type","context_id","status","created_at","last_activity_at"],"properties":{"context_id":{"type":"string"},"context_type":{"type":"string"},"created_at":{"type":"string"},"last_activity_at":{"type":"string"},"project_id":{"type":"integer","format":"int32"},"project_name":{"type":["string","null"]},"project_slug":{"type":["string","null"]},"public_id":{"type":"string"},"status":{"type":"string"},"title":{"type":["string","null"]}}},"GlobalEventStatsResponse":{"type":"object","required":["delivered","opened","clicked","bounced","complained"],"properties":{"bounce_rate":{"type":["number","null"],"format":"double"},"bounced":{"type":"integer","format":"int64","minimum":0},"click_rate":{"type":["number","null"],"format":"double"},"clicked":{"type":"integer","format":"int64","minimum":0},"complained":{"type":"integer","format":"int64","minimum":0},"delivered":{"type":"integer","format":"int64","minimum":0},"open_rate":{"type":["number","null"],"format":"double"},"opened":{"type":"integer","format":"int64","minimum":0}}},"GlobalMrrResponse":{"type":"object","required":["currency","current_mrr_minor","previous_mrr_minor"],"properties":{"change_percentage":{"type":["number","null"],"format":"double","description":"Percentage change vs 24h ago. Null when previous MRR is zero\n(no baseline to compare against)."},"currency":{"type":"string"},"current_mrr_minor":{"type":"integer","format":"int64"},"previous_mrr_minor":{"type":"integer","format":"int64","description":"MRR 24h before now, reconstructed from the event log."}}},"GlobalRecentEventResponse":{"type":"object","required":["id","project_id","project_name","occurred_at","event_type"],"properties":{"amount_minor":{"type":["integer","null"],"format":"int64"},"currency":{"type":["string","null"]},"customer_ref":{"type":["string","null"]},"event_type":{"type":"string"},"id":{"type":"integer","format":"int64"},"mrr_minor":{"type":["integer","null"],"format":"int64"},"occurred_at":{"type":"string","format":"date-time"},"project_id":{"type":"integer","format":"int32"},"project_name":{"type":"string"}}},"GlobalRevenueSummaryResponse":{"type":"object","required":["currency","current_mrr_minor","paid_last_30d_minor","refunded_last_30d_minor","paid_all_time_minor","refunded_all_time_minor","active_subscriptions","active_customers","transactions_last_30d"],"properties":{"active_customers":{"type":"integer","format":"int64"},"active_subscriptions":{"type":"integer","format":"int64"},"currency":{"type":"string"},"current_mrr_minor":{"type":"integer","format":"int64"},"paid_all_time_minor":{"type":"integer","format":"int64"},"paid_last_30d_minor":{"type":"integer","format":"int64"},"refunded_all_time_minor":{"type":"integer","format":"int64"},"refunded_last_30d_minor":{"type":"integer","format":"int64"},"transactions_last_30d":{"type":"integer","format":"int64"}}},"GroupedPageMetric":{"type":"object","required":["group_key","events"],"properties":{"cls":{"type":["number","null"],"format":"float"},"country_code":{"type":["string","null"],"description":"ISO 3166-1 alpha-2 code of the group's country. Populated for the\ngeographic dimensions (country/region/city) so clients can match map\ngeometries without name-based lookups; null otherwise."},"events":{"type":"integer","format":"int64"},"fcp":{"type":["number","null"],"format":"float"},"group_key":{"type":"string"},"inp":{"type":["number","null"],"format":"float"},"lcp":{"type":["number","null"],"format":"float"},"ttfb":{"type":["number","null"],"format":"float"}}},"GroupedPageMetricsQuery":{"allOf":[{"$ref":"#/components/schemas/SpeedSegmentFilters","description":"Segment filters — same shape as `PerformanceMetricsQuery`."},{"type":"object","required":["start_date","end_date","project_id","group_by"],"properties":{"deployment_id":{"type":["integer","null"],"format":"int32"},"device_type":{"type":["string","null"],"description":"Device type filter: \"desktop\" or \"mobile\""},"end_date":{"type":"string","format":"date-time"},"environment_id":{"type":["integer","null"],"format":"int32"},"group_by":{"type":"string"},"include_bots":{"type":["boolean","null"],"description":"Include crawler/datacenter (bot) samples. Defaults to false."},"project_id":{"type":"integer","format":"int32"},"start_date":{"type":"string","format":"date-time"}}}]},"GroupedPageMetricsResponse":{"type":"object","required":["groups","total_events","grouped_by"],"properties":{"grouped_by":{"type":"string"},"groups":{"type":"array","items":{"$ref":"#/components/schemas/GroupedPageMetric"}},"total_events":{"type":"integer","format":"int64"}}},"HasAnalyticsEventsResponse":{"type":"object","required":["has_events"],"properties":{"has_events":{"type":"boolean"}}},"HasErrorGroupsResponse":{"type":"object","required":["has_error_groups"],"properties":{"has_error_groups":{"type":"boolean"}}},"HasEventsQuery":{"type":"object","required":["project_id"],"properties":{"environment_id":{"type":["integer","null"],"format":"int32"},"project_id":{"type":"integer","format":"int32"}}},"HasEventsResponse":{"type":"object","required":["has_events"],"properties":{"has_events":{"type":"boolean"}}},"HasMetricsQuery":{"type":"object","required":["project_id"],"properties":{"project_id":{"type":"integer","format":"int32"}}},"HasMetricsResponse":{"type":"object","required":["has_metrics"],"properties":{"has_metrics":{"type":"boolean"}}},"HealthCheckConfiguration":{"type":"object","description":"Health check configuration","required":["port","interval","timeout","retries"],"properties":{"http_path":{"type":["string","null"],"description":"HTTP path to check (if applicable)"},"interval":{"type":"integer","format":"int32","description":"Interval between checks (seconds)","minimum":0},"port":{"type":"integer","format":"int32","description":"Port to check","minimum":0},"retries":{"type":"integer","format":"int32","description":"Number of retries before marking unhealthy","minimum":0},"timeout":{"type":"integer","format":"int32","description":"Timeout for each check (seconds)","minimum":0}}},"HealthCheckEntryResponse":{"type":"object","required":["checked_at","status"],"properties":{"checked_at":{"type":"string","description":"ISO 8601 timestamp of when the probe ran.","example":"2026-04-22T11:30:00Z"},"error_message":{"type":["string","null"],"description":"Present only when the probe failed or was degraded."},"response_time_ms":{"type":["integer","null"],"format":"int32","description":"TCP connect latency in milliseconds."},"status":{"type":"string","description":"\"operational\" | \"degraded\" | \"down\"","example":"operational"}}},"HealthResponse":{"type":"object","required":["summaries"],"properties":{"summaries":{"type":"array","items":{"$ref":"#/components/schemas/HealthSummary"}}}},"HealthStatus":{"type":"string","description":"Overall health status.","enum":["healthy","degraded","down","unknown"]},"HealthSummary":{"type":"object","description":"Pre-computed health summary for a project environment.","required":["project_id","service_name","status","uptime_pct","error_rate","p95_latency_ms","cpu_usage_pct","memory_usage_pct","computed_at"],"properties":{"computed_at":{"type":"string","format":"date-time"},"cpu_usage_pct":{"type":"number","format":"double"},"environment_id":{"type":["integer","null"],"format":"int32"},"error_rate":{"type":"number","format":"double"},"last_deploy_at":{"type":["string","null"],"format":"date-time"},"last_deploy_id":{"type":["integer","null"],"format":"int32"},"memory_usage_pct":{"type":"number","format":"double"},"p95_latency_ms":{"type":"number","format":"double"},"project_id":{"type":"integer","format":"int32"},"service_name":{"type":"string"},"status":{"$ref":"#/components/schemas/HealthStatus"},"uptime_pct":{"type":"number","format":"double"}}},"HeartbeatApiRequest":{"type":"object","properties":{"architecture":{"type":["string","null"],"description":"Container platform of this node's Docker daemon (`linux/amd64`,\n`linux/arm64`), read from `docker info` by the agent. Absent from\npre-multi-arch agents; the stored value is then left untouched."},"capacity":{"description":"Resource capacity/usage info as JSON (cpu_usage, memory_usage, etc.)"},"containers":{"type":["array","null"],"items":{"$ref":"#/components/schemas/ContainerInventoryItem"},"description":"Container inventory for reconciliation (sent on first heartbeat after agent startup).\nEach entry has `container_id` and `container_name` of temps-managed containers."},"labels":{"description":"Updated node labels for scheduling (allows runtime label changes)."}}},"HeartbeatResponse":{"type":"object","required":["status","message"],"properties":{"message":{"type":"string"},"status":{"type":"string"}}},"HierarchyLevel":{"type":"object","description":"Describes a level in the data source hierarchy","required":["level","name","container_type","can_list_containers","can_list_entities"],"properties":{"can_list_containers":{"type":"boolean","description":"Can list containers at this level?","example":true},"can_list_entities":{"type":"boolean","description":"Can list entities at this level?","example":false},"container_type":{"type":"string","description":"Type of container at this level","example":"database"},"level":{"type":"integer","format":"int32","description":"Level number (0 = root)","example":0,"minimum":0},"name":{"type":"string","description":"Human-readable name for this level","example":"root"}}},"HistogramSummary":{"type":"object","description":"An explicit-bucket histogram aggregated over a time bucket.\n\nCarries the reduced scalars (count/sum/min/max) plus the explicit bucket\nlayout — `bounds` (the upper bounds) and `bucket_counts` (observation counts,\nsummed element-wise across the window; length is `bounds.len() + 1`, the last\nentry being the +Inf overflow bucket). With these, a caller can reconstruct\nany quantile (e.g. p95) via cumulative-count interpolation.","required":["count","sum","bounds","bucket_counts"],"properties":{"bounds":{"type":"array","items":{"type":"number","format":"double"},"description":"Explicit bucket upper bounds (OTLP `explicit_bounds`), ascending."},"bucket_counts":{"type":"array","items":{"type":"integer","format":"int64","minimum":0},"description":"Per-bucket observation counts summed element-wise across the window.\nLength is `bounds.len() + 1` (the trailing element is the +Inf bucket)."},"count":{"type":"integer","format":"int64","description":"Total observation count summed across the bucket window.","minimum":0},"max":{"type":["number","null"],"format":"double","description":"Maximum observed value, when reported by the producer."},"min":{"type":["number","null"],"format":"double","description":"Minimum observed value, when reported by the producer."},"sum":{"type":"number","format":"double","description":"Sum of observed values across the bucket window."}}},"HostnameChange":{"type":"object","description":"A single generated-hostname change in a flatten preview/apply.","required":["kind","id","old","new"],"properties":{"id":{"type":"integer","format":"int32","description":"Row id of the affected record."},"kind":{"type":"string","description":"`\"deployment\"` or `\"environment\"`."},"new":{"type":"string"},"old":{"type":"string"}}},"HostnamePreviewResponse":{"type":"object","description":"Combined preview of a hostname-mode change.","required":["hostname_changes","dns_changes","total"],"properties":{"dns_changes":{"type":"array","items":{"$ref":"#/components/schemas/DnsRecordChange"}},"hostname_changes":{"type":"array","items":{"$ref":"#/components/schemas/HostnameChange"}},"total":{"type":"integer","minimum":0},"zone_access_ok":{"type":["boolean","null"],"description":"Whether the provider token can manage this zone (None if not checked)."}}},"HourlyPageSessions":{"type":"object","required":["timestamp","session_count","event_count","avg_duration_seconds"],"properties":{"avg_duration_seconds":{"type":"number","format":"double"},"event_count":{"type":"integer","format":"int64"},"session_count":{"type":"integer","format":"int64"},"timestamp":{"type":"string"}}},"HourlyVisitsQuery":{"type":"object","required":["start_date","end_date"],"properties":{"aggregation_level":{"$ref":"#/components/schemas/AggregationLevel","description":"Aggregation level: events (page views), sessions (unique sessions), or visitors (unique visitors)"},"end_date":{"type":"string","format":"date-time"},"environment_id":{"type":["integer","null"],"format":"int32"},"start_date":{"type":"string","format":"date-time"}}},"HttpChallengeDebugResponse":{"type":"object","required":["domain","challenge_exists","dns_a_records","dns_aaaa_records"],"properties":{"challenge_exists":{"type":"boolean"},"challenge_token":{"type":["string","null"]},"challenge_url":{"type":["string","null"],"description":"The full URL that Let's Encrypt will try to access to validate the challenge"},"dns_a_records":{"type":"array","items":{"type":"string"},"description":"IPv4 addresses the domain points to"},"dns_aaaa_records":{"type":"array","items":{"type":"string"},"description":"IPv6 addresses the domain points to"},"dns_error":{"type":["string","null"],"description":"Any DNS resolution errors"},"domain":{"type":"string"},"validation_url":{"type":["string","null"],"description":"The ACME validation URL (internal to ACME protocol)"}}},"ImportCredentials":{"type":"object","description":"Platform-specific credentials for accessing the source system.\n\nFor platforms like Vercel and Railway, this contains the API token.\nFor self-hosted platforms like Coolify and Dokploy, this also contains\nthe `base_url` of the instance.\n\nLocal importers (Docker) can use `ImportCredentials::none()`.","properties":{"base_url":{"type":["string","null"],"description":"Base URL override (for self-hosted platforms like Coolify, Dokploy)\n\nExample: `https://coolify.example.com`"},"extra":{"type":"object","description":"Additional platform-specific parameters","additionalProperties":{"type":"string"},"propertyNames":{"type":"string"}},"team_id":{"type":["string","null"],"description":"Team or organization ID (for platforms with team scoping like Vercel)"},"token":{"type":["string","null"],"description":"API token / bearer token for the source platform"}}},"ImportExecutionStatus":{"type":"string","description":"Import execution status","enum":["pending","inprogress","completed","failed"]},"ImportExternalServiceRequest":{"type":"object","description":"Request to import a Docker container as a managed service","required":["name","service_type","parameters","container_id"],"properties":{"container_id":{"type":"string","description":"Container ID or name to import","example":"abc123def456"},"name":{"type":"string","description":"Name to register the service as in Temps","example":"production-database"},"parameters":{"type":"object","description":"Service configuration parameters","additionalProperties":{},"propertyNames":{"type":"string"}},"service_type":{"$ref":"#/components/schemas/ServiceTypeRoute","description":"Service type"},"version":{"type":["string","null"],"description":"Optional version override"}}},"ImportOutcomeResponse":{"type":"object","required":["rows_read","inserted","updated","skipped_stale","skipped_invalid","errors"],"properties":{"errors":{"type":"array","items":{"$ref":"#/components/schemas/ImportRowErrorResponse"}},"inserted":{"type":"integer","minimum":0},"rows_read":{"type":"integer","minimum":0},"skipped_invalid":{"type":"integer","minimum":0},"skipped_stale":{"type":"integer","minimum":0},"updated":{"type":"integer","minimum":0}}},"ImportPlan":{"type":"object","description":"Complete import plan describing all operations to onboard a workload.\n\nThe plan is generated from a snapshot and presented to the user for review\nbefore any resources are created. Users can modify individual items\n(skip services, change actions) before approving execution.","required":["version","source","source_id","project","environment","deployment","summary","metadata"],"properties":{"additional_deployments":{"type":"array","items":{"$ref":"#/components/schemas/DeploymentConfiguration"},"description":"Additional deployments (workers, cron jobs, etc.)"},"cost_analysis":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/CostAnalysis","description":"Cost, overprovisioning, and savings analysis. Populated by importers\nthat can observe the whole source cluster (currently Kubernetes);\n`None` for container/platform imports."}]},"deployment":{"$ref":"#/components/schemas/DeploymentConfiguration","description":"Primary deployment configuration"},"domains":{"type":"array","items":{"$ref":"#/components/schemas/DomainPlan"},"description":"Custom domains to migrate"},"environment":{"$ref":"#/components/schemas/EnvironmentConfiguration","description":"Environment configuration"},"metadata":{"$ref":"#/components/schemas/PlanMetadata","description":"Plan metadata"},"project":{"$ref":"#/components/schemas/ProjectConfiguration","description":"Project configuration"},"services":{"type":"array","items":{"$ref":"#/components/schemas/ServicePlan"},"description":"Services to migrate (databases, caches, blob stores)\n\nEach service has an `action` field the user can change before execution."},"source":{"type":"string","description":"Source system this plan was generated from"},"source_id":{"type":"string","description":"Source workload / project ID in the source system"},"steps":{"type":"array","items":{"$ref":"#/components/schemas/MigrationStep"},"description":"Ordered list of migration steps that will be executed.\n\nThis is the human-readable execution plan. Each step describes what\nwill happen, what risks are involved, and what the user should verify.\nSteps are executed in order. If a step fails, execution stops and\nalready-created resources are reported for manual cleanup."},"summary":{"$ref":"#/components/schemas/MigrationSummary","description":"Human-readable summary of the entire migration"},"version":{"type":"string","description":"Plan version for compatibility tracking"}}},"ImportRowErrorResponse":{"type":"object","required":["row","reason"],"properties":{"reason":{"type":"string"},"row":{"type":"integer","minimum":0}}},"ImportSelector":{"type":"object","description":"Selector for discovering workloads","properties":{"label_filter":{"type":["object","null"],"description":"Filter by labels/tags","additionalProperties":{"type":"string"},"propertyNames":{"type":"string"}},"limit":{"type":["integer","null"],"description":"Limit number of results","minimum":0},"name_pattern":{"type":["string","null"],"description":"Filter by name pattern (glob/regex)"},"status_filter":{"type":["array","null"],"items":{"type":"string"},"description":"Filter by status (running, stopped, deployed, etc.)"},"workload_type_filter":{"type":["array","null"],"items":{"type":"string"},"description":"Filter by workload type (container, function, static-site, etc.)"}}},"ImportSource":{"type":"string","description":"Import source identifier","enum":["docker","coolify","dokploy","vercel","netlify","railway","render","fly","kubernetes","caprover","portainer","kamal","custom"]},"ImportSourceCapabilities":{"type":"object","description":"Source capabilities","required":["supports_volumes","supports_networks","supports_health_checks","supports_resource_limits","supports_build","supports_services","supports_domains","supports_project_snapshot","supports_cost_analysis","requires_credentials"],"properties":{"requires_credentials":{"type":"boolean","description":"Whether this source requires API credentials (token, base URL)"},"supports_build":{"type":"boolean"},"supports_cost_analysis":{"type":"boolean","description":"Supports cluster cost + overprovisioning analysis in the plan"},"supports_domains":{"type":"boolean","description":"Supports custom domain migration"},"supports_health_checks":{"type":"boolean"},"supports_networks":{"type":"boolean"},"supports_project_snapshot":{"type":"boolean","description":"Supports full project-level snapshots"},"supports_resource_limits":{"type":"boolean"},"supports_services":{"type":"boolean","description":"Supports service migration (databases, caches, etc.)"},"supports_volumes":{"type":"boolean"}}},"ImportSourceInfo":{"type":"object","description":"Information about an import source","required":["source","name","version","available","capabilities"],"properties":{"available":{"type":"boolean","description":"Whether the source is currently available"},"capabilities":{"$ref":"#/components/schemas/ImportSourceCapabilities","description":"Capabilities"},"name":{"type":"string","description":"Human-readable name"},"source":{"$ref":"#/components/schemas/ImportSource","description":"Source identifier"},"version":{"type":"string","description":"Source version"}}},"ImportStatusResponse":{"type":"object","description":"Response with import status","required":["session_id","status","errors","warnings","created_at","updated_at"],"properties":{"created_at":{"type":"string","format":"date-time","description":"Created at timestamp"},"deployment_id":{"type":["integer","null"],"format":"int32","description":"Created deployment ID"},"environment_id":{"type":["integer","null"],"format":"int32","description":"Created environment ID"},"errors":{"type":"array","items":{"type":"string"},"description":"Errors (if any)"},"plan":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/ImportPlan","description":"Import plan"}]},"project_id":{"type":["integer","null"],"format":"int32","description":"Created project ID"},"session_id":{"type":"string","description":"Session ID"},"status":{"$ref":"#/components/schemas/ImportExecutionStatus","description":"Current status"},"updated_at":{"type":"string","format":"date-time","description":"Updated at timestamp"},"validation":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/ValidationReport","description":"Validation report"}]},"warnings":{"type":"array","items":{"type":"string"},"description":"Warnings (if any)"}}},"IncidentBucket":{"type":"object","required":["bucket_start","total_incidents","minor_incidents","major_incidents","critical_incidents","resolved_incidents","active_incidents"],"properties":{"active_incidents":{"type":"integer","format":"int64"},"avg_resolution_time_minutes":{"type":["number","null"],"format":"double"},"bucket_start":{"type":"string","format":"date-time"},"critical_incidents":{"type":"integer","format":"int64"},"major_incidents":{"type":"integer","format":"int64"},"minor_incidents":{"type":"integer","format":"int64"},"resolved_incidents":{"type":"integer","format":"int64"},"total_incidents":{"type":"integer","format":"int64"}}},"IncidentBucketedResponse":{"type":"object","required":["project_id","interval","buckets"],"properties":{"buckets":{"type":"array","items":{"$ref":"#/components/schemas/IncidentBucket"}},"environment_id":{"type":["integer","null"],"format":"int32"},"interval":{"type":"string"},"project_id":{"type":"integer","format":"int32"}}},"IncidentResponse":{"type":"object","required":["id","project_id","title","severity","status","started_at","created_at","updated_at"],"properties":{"created_at":{"type":"string","format":"date-time"},"description":{"type":["string","null"]},"environment_id":{"type":["integer","null"],"format":"int32"},"id":{"type":"integer","format":"int32"},"monitor_id":{"type":["integer","null"],"format":"int32"},"project_id":{"type":"integer","format":"int32"},"resolved_at":{"type":["string","null"],"format":"date-time"},"severity":{"type":"string"},"started_at":{"type":"string","format":"date-time"},"status":{"type":"string"},"title":{"type":"string"},"updated_at":{"type":"string","format":"date-time"}}},"IncidentUpdateResponse":{"type":"object","required":["id","incident_id","status","message","created_at"],"properties":{"created_at":{"type":"string","format":"date-time"},"id":{"type":"integer","format":"int32"},"incident_id":{"type":"integer","format":"int32"},"message":{"type":"string"},"status":{"type":"string"}}},"IncrRequest":{"type":"object","description":"Request to increment a value","required":["key"],"properties":{"amount":{"type":["integer","null"],"format":"int64","description":"Amount to increment by (default: 1)"},"key":{"type":"string","description":"The key to increment","example":"counter"},"project_id":{"type":["integer","null"],"format":"int32","description":"Project ID (required for API key/session auth, optional for deployment tokens)","example":1}}},"IncrResponse":{"type":"object","description":"Response for increment operation","required":["value"],"properties":{"value":{"type":"integer","format":"int64","description":"New value after increment","example":42}}},"InitAuthResponse":{"type":"object","required":["auth_url","session_token"],"properties":{"auth_url":{"type":"string"},"session_token":{"type":"string"}}},"Insight":{"type":"object","description":"An anomaly insight.","required":["id","project_id","service_name","severity","status","title","description","anomaly_ids","started_at","created_at","updated_at"],"properties":{"anomaly_ids":{"type":"array","items":{"type":"integer","format":"int64"}},"correlated_deploy_id":{"type":["integer","null"],"format":"int32"},"created_at":{"type":"string","format":"date-time"},"description":{"type":"string"},"environment":{"type":["string","null"]},"id":{"type":"integer","format":"int64"},"metric_name":{"type":["string","null"]},"project_id":{"type":"integer","format":"int32"},"resolved_at":{"type":["string","null"],"format":"date-time"},"service_name":{"type":"string"},"severity":{"$ref":"#/components/schemas/InsightSeverity"},"started_at":{"type":"string","format":"date-time"},"status":{"$ref":"#/components/schemas/InsightStatus"},"title":{"type":"string"},"updated_at":{"type":"string","format":"date-time"}}},"InsightSeverity":{"type":"string","description":"Severity of an anomaly insight.","enum":["low","medium","high","critical"]},"InsightStatus":{"type":"string","description":"Status of an insight.","enum":["active","resolved"]},"InsightsResponse":{"type":"object","required":["data","count"],"properties":{"count":{"type":"integer","minimum":0},"data":{"type":"array","items":{"$ref":"#/components/schemas/Insight"}}}},"IntegrationResponse":{"type":"object","required":["id","project_id","provider","webhook_path_token","webhook_path","status","has_secret","created_at"],"properties":{"config":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/ProviderConfig","description":"Typed provider config — allowlist and metered-billing mode. Null\nwhen the operator hasn't configured one yet (accept everything)."}]},"created_at":{"type":"string","format":"date-time"},"has_secret":{"type":"boolean"},"id":{"type":"integer","format":"int32"},"last_event_at":{"type":["string","null"],"format":"date-time"},"project_id":{"type":"integer","format":"int32"},"provider":{"type":"string"},"status":{"type":"string"},"webhook_path":{"type":"string","description":"Relative path the UI can display and copy. The frontend builds\nthe full URL by prefixing its own origin."},"webhook_path_token":{"type":"string","description":"Unguessable token embedded in the public webhook URL. The full\nURL is `{api_origin}/webhooks/revenue/{provider}/{webhook_path_token}`."}}},"IpAccessControlQuery":{"type":"object","description":"Query parameters for listing IP access control rules","properties":{"action":{"type":["string","null"],"description":"Filter by action (\"block\" or \"allow\")"}}},"IpAccessControlResponse":{"type":"object","description":"Response model for IP access control rules","required":["id","ip_address","action","created_at","updated_at"],"properties":{"action":{"type":"string"},"created_at":{"type":"string","example":"2025-10-12T12:15:47.609Z"},"created_by":{"type":["integer","null"],"format":"int32"},"id":{"type":"integer","format":"int32"},"ip_address":{"type":"string"},"reason":{"type":["string","null"]},"updated_at":{"type":"string","example":"2025-10-12T12:15:47.609Z"}}},"JobStatusResponse":{"type":"object","description":"Snapshot of a background job. `status` is one of \"running\" | \"exited\"\n| \"failed\"; `exit_code` is populated only when `status == \"exited\"`.","required":["status","stdout","stderr"],"properties":{"exit_code":{"type":["integer","null"],"format":"int32"},"reason":{"type":["string","null"]},"status":{"type":"string"},"stderr":{"type":"string"},"stdout":{"type":"string"}}},"JobSummaryResponse":{"type":"object","description":"Row in the jobs list. Omits stdout/stderr so a noisy dev server doesn't\nbloat the list payload — callers drill into `GET /jobs/{id}` for the\nfull buffer.","required":["id","status","cmd","started_at"],"properties":{"cmd":{"type":"string"},"exit_code":{"type":["integer","null"],"format":"int32"},"id":{"type":"string"},"reason":{"type":["string","null"]},"started_at":{"type":"string"},"status":{"type":"string"}}},"JoinTokenStatusResponse":{"type":"object","description":"Response for join token status check","required":["has_token"],"properties":{"has_token":{"type":"boolean","description":"Whether a join token has been configured"}}},"JourneyEvent":{"type":"object","description":"A single event in the visitor journey timeline","required":["id","event_type","event_name","occurred_at","is_entry","is_exit","is_bounce"],"properties":{"event_data":{"description":"Custom event properties (for custom events)"},"event_name":{"type":"string","description":"Resolved event name (event_name for custom events, event_type for system events)"},"event_type":{"type":"string","description":"Event type: \"page_view\", \"page_leave\", \"custom\", \"web_vitals\""},"id":{"type":"integer","format":"int64","description":"Event ID"},"is_bounce":{"type":"boolean","description":"Whether this was a bounce"},"is_entry":{"type":"boolean","description":"Whether this is the entry page of the session"},"is_exit":{"type":"boolean","description":"Whether this is the exit page of the session"},"occurred_at":{"type":"string","format":"date-time","description":"When the event occurred"},"page_path":{"type":["string","null"],"description":"Page path where the event happened"},"page_title":{"type":["string","null"],"description":"Page title (if available)"},"referrer":{"type":["string","null"],"description":"Referrer URL for this event"},"scroll_depth":{"type":["integer","null"],"format":"int32","description":"Scroll depth percentage (0-100)"},"session_page_number":{"type":["integer","null"],"format":"int32","description":"Page number within the session (1-indexed)"},"time_on_page":{"type":["integer","null"],"format":"int32","description":"Time spent on page in seconds (computed, not from column)"}}},"JourneySession":{"type":"object","description":"A session within the visitor journey, grouping events","required":["session_id","started_at","duration_seconds","page_views","events_count","is_bounced","is_engaged","events"],"properties":{"channel":{"type":["string","null"],"description":"Traffic source: channel (e.g. \"organic\", \"direct\", \"social\")"},"duration_seconds":{"type":"integer","format":"int64","description":"Session duration in seconds"},"ended_at":{"type":["string","null"],"format":"date-time","description":"When the session ended"},"entry_path":{"type":["string","null"],"description":"Entry page path"},"events":{"type":"array","items":{"$ref":"#/components/schemas/JourneyEvent"},"description":"Events within this session, ordered chronologically"},"events_count":{"type":"integer","format":"int64","description":"Total events in this session"},"exit_path":{"type":["string","null"],"description":"Exit page path"},"is_bounced":{"type":"boolean","description":"Whether the session was a bounce"},"is_engaged":{"type":"boolean","description":"Whether the visitor was engaged (had non-pageview events)"},"page_views":{"type":"integer","format":"int64","description":"Number of page views in this session"},"referrer":{"type":["string","null"],"description":"Traffic source: referrer URL"},"referrer_hostname":{"type":["string","null"],"description":"Traffic source: referrer hostname"},"session_id":{"type":"integer","format":"int32","description":"Session internal ID"},"started_at":{"type":"string","format":"date-time","description":"When the session started"},"utm_campaign":{"type":["string","null"],"description":"UTM campaign parameter"},"utm_medium":{"type":["string","null"],"description":"UTM medium parameter"},"utm_source":{"type":["string","null"],"description":"UTM source parameter"}}},"KeysRequest":{"type":"object","description":"Request to get keys matching a pattern","required":["pattern"],"properties":{"pattern":{"type":"string","description":"Pattern to match (supports * and ? wildcards)","example":"user:*"},"project_id":{"type":["integer","null"],"format":"int32","description":"Project ID (required for API key/session auth, optional for deployment tokens)","example":1}}},"KeysResponse":{"type":"object","description":"Response for keys operation","required":["keys"],"properties":{"keys":{"type":"array","items":{"type":"string"},"description":"List of matching keys","example":["user:1","user:2","user:3"]}}},"KillJobBody":{"type":"object","properties":{"force":{"type":"boolean","description":"When true, sends SIGKILL immediately. Defaults to SIGTERM so the\nprocess gets a chance to flush (mirrors `Command.kill()` in\n`@vercel/sandbox`, which also accepts a signal override)."}},"additionalProperties":false},"KnownAiAgentsResponse":{"type":"object","description":"Response listing every AI agent the detector knows about.","required":["items"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/AiAgentDescriptor"}}}},"KvStatusResponse":{"type":"object","description":"Response for KV service status","required":["enabled","healthy"],"properties":{"docker_image":{"type":["string","null"],"description":"Docker image being used","example":"gotempsh/redis-walg:8-bookworm"},"enabled":{"type":"boolean","description":"Whether the KV service is enabled"},"healthy":{"type":"boolean","description":"Whether the underlying Redis service is healthy"},"version":{"type":["string","null"],"description":"Service version","example":"7.2"}}},"LemonSqueezyConfig":{"type":"object","properties":{"product_allowlist":{"type":"array","items":{"type":"string"}},"variant_allowlist":{"type":"array","items":{"type":"string"}}}},"LetsEncryptSettings":{"type":"object","properties":{"email":{"type":["string","null"],"default":null},"environment":{"type":"string","default":"production"}}},"LineContext":{"type":"object","description":"Raw surrounding lines for a single match (grep -C style).","required":["before","after"],"properties":{"after":{"type":"array","items":{"$ref":"#/components/schemas/ContextLine"},"description":"Lines immediately after the match, oldest-first."},"before":{"type":"array","items":{"$ref":"#/components/schemas/ContextLine"},"description":"Lines immediately before the match, oldest-first."}}},"LinkServiceRequest":{"type":"object","required":["project_id"],"properties":{"project_id":{"type":"integer","format":"int32"}}},"ListAgentsResponse":{"type":"object","required":["items","total"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/AgentConfigResponse"}},"total":{"type":"integer","minimum":0}}},"ListApiKeysQuery":{"type":"object","properties":{"page":{"type":["integer","null"],"format":"int64","minimum":0},"page_size":{"type":["integer","null"],"format":"int64","minimum":0}}},"ListAuditLogsQuery":{"type":"object","description":"Query parameters for listing audit logs.\n\nEvery field is optional — omitting one means \"don't filter on it\". Deriving\n`IntoParams` makes utoipa render them as optional query params with the\ncorrect types; the previous hand-written `params((\"operation_type\", Query,\n…))` tuples defaulted every param to `required: true, type: string`, which\nmisled both API clients and the AI `describe_api`/`call_api` tools into\nthinking all filters were mandatory.","properties":{"from":{"type":["string","null"],"format":"date-time","description":"Start timestamp (milliseconds since epoch)"},"limit":{"type":["integer","null"],"format":"int32","description":"Maximum number of logs to return"},"offset":{"type":["integer","null"],"format":"int32","description":"Number of logs to skip"},"operation_type":{"type":["string","null"],"description":"Filter logs by operation type (omit for all)"},"to":{"type":["string","null"],"format":"date-time","description":"End timestamp (milliseconds since epoch)"},"user_id":{"type":["integer","null"],"format":"int32","description":"Filter logs by user ID (omit for all users)"}}},"ListBlobsQuery":{"type":"object","description":"Query parameters for listing blobs","properties":{"cursor":{"type":["string","null"],"description":"Continuation token for pagination"},"limit":{"type":["integer","null"],"format":"int32","description":"Maximum number of items to return","example":100},"prefix":{"type":["string","null"],"description":"Prefix to filter by","example":"images/"},"project_id":{"type":["integer","null"],"format":"int32","description":"Project ID (required for API key/session auth, optional for deployment tokens)","example":1}}},"ListBlobsResponse":{"type":"object","description":"Response for listing blobs","required":["blobs","hasMore"],"properties":{"blobs":{"type":"array","items":{"$ref":"#/components/schemas/BlobResponse"},"description":"List of blobs"},"cursor":{"type":["string","null"],"description":"Continuation token for next page"},"hasMore":{"type":"boolean","description":"Whether there are more results","example":false}}},"ListCustomDomainsResponse":{"type":"object","required":["domains","total"],"properties":{"domains":{"type":"array","items":{"$ref":"#/components/schemas/CustomDomainResponse"}},"total":{"type":"integer","minimum":0}}},"ListDeploymentTokensQuery":{"type":"object","properties":{"page":{"type":["integer","null"],"format":"int64","example":1,"minimum":0},"page_size":{"type":["integer","null"],"format":"int64","example":20,"minimum":0}}},"ListDomainsResponse":{"type":"object","required":["domains","total","page","page_size"],"properties":{"domains":{"type":"array","items":{"$ref":"#/components/schemas/DomainResponse"}},"page":{"type":"integer","format":"int64","minimum":0},"page_size":{"type":"integer","format":"int64","minimum":0},"total":{"type":"integer","format":"int64","minimum":0}}},"ListEntitiesQuery":{"type":"object","properties":{"limit":{"type":"integer","description":"Maximum number of entities to return","example":100,"minimum":0},"token":{"type":["string","null"],"description":"Continuation token for pagination (backend-specific)"}}},"ListErrorEventsQuery":{"type":"object","properties":{"page":{"type":"integer","format":"int64","minimum":0},"page_size":{"type":"integer","format":"int64","minimum":0}}},"ListErrorGroupsQuery":{"type":"object","properties":{"end_date":{"type":["string","null"],"format":"date-time"},"environment_id":{"type":["integer","null"],"format":"int32"},"page":{"type":"integer","format":"int64","minimum":0},"page_size":{"type":"integer","format":"int64","minimum":0},"sort_by":{"type":["string","null"]},"sort_order":{"type":"string"},"start_date":{"type":["string","null"],"format":"date-time"},"status":{"type":["string","null"]}}},"ListJobsResponse":{"type":"object","required":["items"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/JobSummaryResponse"}}}},"ListMcpsResponse":{"type":"object","description":"Concrete list wrapper for MCP server definitions (utoipa requires non-generic types).","required":["items","total"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/McpDefinitionResponse"}},"total":{"type":"integer","minimum":0}}},"ListOnDemandCertsResponse":{"type":"object","description":"Paginated list of on-demand cert attempts (ADR-018 §5 console \"Certificates\"\nsurface). Joined with current `domains.status`, newest first.","required":["certs","total","page","page_size"],"properties":{"certs":{"type":"array","items":{"$ref":"#/components/schemas/OnDemandCertRow"}},"page":{"type":"integer","format":"int64","minimum":0},"page_size":{"type":"integer","format":"int64","minimum":0},"total":{"type":"integer","format":"int64","minimum":0}}},"ListOrdersResponse":{"type":"object","required":["orders"],"properties":{"orders":{"type":"array","items":{"$ref":"#/components/schemas/AcmeOrderResponse"}}}},"ListPresetsResponse":{"type":"object","required":["presets","total"],"properties":{"presets":{"type":"array","items":{"$ref":"#/components/schemas/PresetResponse"}},"total":{"type":"integer","minimum":0}}},"ListRunsResponse":{"type":"object","required":["items","total","page","page_size"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/AgentRunResponse"}},"page":{"type":"integer","format":"int64","minimum":0},"page_size":{"type":"integer","format":"int64","minimum":0},"total":{"type":"integer","format":"int64","minimum":0}}},"ListSandboxesResponse":{"type":"object","description":"SDK list response: `{ sandboxes: [...], pagination: {...} }`.","required":["sandboxes","pagination"],"properties":{"pagination":{"$ref":"#/components/schemas/Pagination"},"sandboxes":{"type":"array","items":{"$ref":"#/components/schemas/SandboxInner"}}}},"ListScansQuery":{"type":"object","properties":{"page":{"type":["integer","null"],"format":"int64","example":1,"minimum":0},"page_size":{"type":["integer","null"],"format":"int64","example":20,"minimum":0}}},"ListSecretsResponse":{"type":"object","required":["items","total"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/SecretResponse"}},"total":{"type":"integer","minimum":0}}},"ListSkillsResponse":{"type":"object","description":"Concrete list wrapper for skill definitions (utoipa requires non-generic types).","required":["items","total"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/SkillDefinitionResponse"}},"total":{"type":"integer","minimum":0}}},"ListTagsResponse":{"type":"object","description":"Response for listing tags","required":["tags","total"],"properties":{"tags":{"type":"array","items":{"type":"string"},"description":"List of available tags"},"total":{"type":"integer","description":"Total number of tags","minimum":0}}},"ListTemplatesQuery":{"type":"object","description":"Query parameters for listing templates","properties":{"featured":{"type":["boolean","null"],"description":"Only return featured templates"},"tag":{"type":["string","null"],"description":"Filter templates by tag"}}},"ListTemplatesResponse":{"type":"object","description":"Response for listing templates","required":["templates","total"],"properties":{"templates":{"type":"array","items":{"$ref":"#/components/schemas/TemplateResponse"},"description":"List of templates"},"total":{"type":"integer","description":"Total number of templates","minimum":0}}},"ListVulnerabilitiesQuery":{"type":"object","properties":{"page":{"type":["integer","null"],"format":"int64","example":1,"minimum":0},"page_size":{"type":["integer","null"],"format":"int64","example":20,"minimum":0},"severity":{"type":["string","null"],"example":"CRITICAL"}}},"LiveVisitorInfo":{"type":"object","required":["id","visitor_id","project_id","environment_id","first_seen","last_seen","is_crawler"],"properties":{"city":{"type":["string","null"]},"country":{"type":["string","null"]},"country_code":{"type":["string","null"]},"crawler_name":{"type":["string","null"]},"current_page":{"type":["string","null"],"description":"Most recent page path visited by this visitor"},"custom_data":{},"environment_id":{"type":"integer","format":"int32"},"first_channel":{"type":["string","null"],"description":"Marketing channel from the first visit (e.g. \"Organic Search\", \"Direct\")"},"first_referrer":{"type":["string","null"],"description":"Full referrer URL from the visitor's first session"},"first_referrer_hostname":{"type":["string","null"],"description":"Hostname extracted from first_referrer"},"first_seen":{"type":"string","format":"date-time","example":"2024-01-01T00:00:00"},"id":{"type":"integer","format":"int32"},"ip_address":{"type":["string","null"]},"ip_address_id":{"type":["integer","null"],"format":"int32"},"is_crawler":{"type":"boolean"},"is_eu":{"type":["boolean","null"]},"last_seen":{"type":"string","format":"date-time","example":"2024-01-01T00:00:00"},"latitude":{"type":["number","null"],"format":"double"},"longitude":{"type":["number","null"],"format":"double"},"project_id":{"type":"integer","format":"int32"},"region":{"type":["string","null"]},"timezone":{"type":["string","null"]},"user_agent":{"type":["string","null"]},"visitor_id":{"type":"string"}}},"LiveVisitorsListResponse":{"type":"object","required":["total_count","visitors","window_minutes"],"properties":{"total_count":{"type":"integer","format":"int64"},"visitors":{"type":"array","items":{"$ref":"#/components/schemas/LiveVisitorInfo"}},"window_minutes":{"type":"integer","format":"int32"}}},"LocationCount":{"type":"object","required":["location","count","percentage"],"properties":{"count":{"type":"integer","format":"int64"},"location":{"type":"string"},"percentage":{"type":"number","format":"double"}}},"LocationGranularity":{"type":"string","enum":["country","region","city"]},"LocationInfo":{"type":"object","properties":{"city":{"type":["string","null"]},"country":{"type":["string","null"]},"region":{"type":["string","null"]}}},"LogLevel":{"type":"string","description":"Normalized log level","enum":["TRACE","DEBUG","INFO","WARN","ERROR"]},"LogRecord":{"type":"object","description":"A single log record ready for storage.","required":["project_id","resource","timestamp","observed_timestamp","severity","severity_text","body","attributes"],"properties":{"attributes":{"type":"object","additionalProperties":{"type":"string"},"propertyNames":{"type":"string"}},"body":{"type":"string"},"deployment_id":{"type":["integer","null"],"format":"int32"},"observed_timestamp":{"type":"string","format":"date-time"},"project_id":{"type":"integer","format":"int32"},"resource":{"$ref":"#/components/schemas/ResourceInfo"},"severity":{"$ref":"#/components/schemas/LogSeverity"},"severity_text":{"type":"string"},"span_id":{"type":["string","null"]},"timestamp":{"type":"string","format":"date-time"},"trace_id":{"type":["string","null"]}}},"LogSearchLine":{"type":"object","description":"A single line in search results","required":["timestamp","level","service","message","chunk_id","line_offset"],"properties":{"chunk_id":{"type":"string"},"container_id":{"type":"string","description":"Container this line came from — lets the UI tag/group lines by container\nin a combined (\"show all\") multi-container view."},"context":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/LineContext","description":"Raw surrounding lines (grep -C). `None` unless `context_lines > 0` was\nrequested. Overlapping windows between nearby matches are merged: the\nshared neighbors appear on the earlier match only, so the frontend can\nrender one continuous block without duplicated lines."}]},"deploy_id":{"type":["integer","null"],"format":"int32"},"fields":{},"level":{"$ref":"#/components/schemas/LogLevel"},"line_offset":{"type":"integer","format":"int32"},"message":{"type":"string"},"node_id":{"type":["integer","null"],"format":"int32","description":"Worker node the line came from (`None` = control-plane-local)."},"node_name":{"type":["string","null"],"description":"Human-readable node name for display."},"service":{"type":"string"},"timestamp":{"type":"string"}}},"LogSeverity":{"type":"string","description":"Log severity level (simplified from OTel's 24 levels).","enum":["TRACE","DEBUG","INFO","WARN","ERROR","FATAL"]},"LogSource":{"type":"object","description":"A distinct log source (container) seen in the queried scope. Used to populate\nthe history filter dropdowns with the *full* set of containers/nodes for the\nproject + env + deployment + time window — independent of the active\ncontainer/node/service filter, so the user can switch between them.","required":["container_id","service"],"properties":{"container_id":{"type":"string"},"node_id":{"type":["integer","null"],"format":"int32"},"node_name":{"type":["string","null"]},"service":{"type":"string"}}},"LogStream":{"type":"string","description":"Log output stream","enum":["stdout","stderr"]},"LoginRequest":{"type":"object","required":["email","password"],"properties":{"email":{"type":"string"},"password":{"type":"string"}}},"LogsQuery":{"type":"object","properties":{"tail":{"type":["integer","null"],"description":"Number of lines to return from the tail. Defaults to 200, capped at 2000.","minimum":0}}},"LogsResponse":{"type":"object","required":["data","count"],"properties":{"count":{"type":"integer","minimum":0},"data":{"type":"array","items":{"$ref":"#/components/schemas/LogRecord"}}}},"ManagedDomainResponse":{"type":"object","description":"Managed domain response","required":["id","provider_id","domain","auto_manage","verified","generated_hostname_mode","sync_generated_records","created_at","updated_at"],"properties":{"auto_manage":{"type":"boolean"},"created_at":{"type":"string"},"domain":{"type":"string"},"generated_hostname_mode":{"type":"string","description":"Generated hostname layout: `\"standard\"` or `\"flat\"`."},"id":{"type":"integer","format":"int32"},"provider_id":{"type":"integer","format":"int32"},"sync_generated_records":{"type":"boolean","description":"Whether generated hostnames are reconciled into the provider's DNS zone."},"updated_at":{"type":"string"},"verification_error":{"type":["string","null"]},"verified":{"type":"boolean"},"verified_at":{"type":["string","null"]},"zone_access_error":{"type":["string","null"],"description":"Detail for a failed zone-access check."},"zone_access_ok":{"type":["boolean","null"],"description":"Last token zone-access check: `Some(true)`/`Some(false)`/`None` (unchecked)."},"zone_id":{"type":["string","null"]}}},"ManualAction":{"type":"object","description":"A manual action the user must perform outside of the automated migration","required":["timing","description","reason"],"properties":{"description":{"type":"string","description":"Human-readable description"},"reason":{"type":"string","description":"Why this can't be automated"},"timing":{"$ref":"#/components/schemas/ManualActionTiming","description":"When this action needs to happen"}}},"ManualActionTiming":{"type":"string","description":"When a manual action needs to happen relative to migration","enum":["before-migration","after-migration","within-hours"]},"McpDefinitionResponse":{"type":"object","required":["id","slug","name","config","created_at","updated_at"],"properties":{"config":{"type":"object"},"created_at":{"type":"string"},"description":{"type":["string","null"]},"id":{"type":"integer","format":"int32"},"name":{"type":"string"},"project_id":{"type":["integer","null"],"format":"int32"},"slug":{"type":"string"},"updated_at":{"type":"string"}}},"MessageContent":{"oneOf":[{"type":"string"},{"type":"array","items":{"$ref":"#/components/schemas/ContentPart"}}]},"MessagePart":{"oneOf":[{"type":"object","required":["text","type"],"properties":{"text":{"type":"string"},"type":{"type":"string","enum":["text"]}}},{"type":"object","required":["tool","type"],"properties":{"tool":{"$ref":"#/components/schemas/ToolInfo"},"type":{"type":"string","enum":["tool"]}}}],"description":"One ordered segment of an assistant turn: a chunk of prose, or a tool\ninvocation. Mirrors the `metadata.parts` persisted by the chat service."},"MessageResponse":{"type":"object","required":["role","content","created_at"],"properties":{"content":{"type":"string"},"created_at":{"type":"string"},"parts":{"type":["array","null"],"items":{"$ref":"#/components/schemas/MessagePart"},"description":"Ordered render segments (text / tool, in the order they occurred) so a\nreloaded chat shows the same interleaving as the live stream. Absent for\nolder messages persisted before parts were tracked; the client then falls\nback to `tools` (rendered first) + `content`."},"role":{"type":"string"},"tools":{"type":["array","null"],"items":{"$ref":"#/components/schemas/ToolInfo"},"description":"Tools the assistant ran on this turn (persisted in message metadata), so\nthe chat replays its tool work after a reload. Absent for plain turns."}}},"MeteredMode":{"type":"string","description":"How to treat metered-billing subscriptions when computing MRR.\n\n* `DeriveFromInvoices` (default): ignore the subscription row's\n `mrr_minor` for metered items and rely on the per-invoice\n [`NormalizedEventType::MrrRealized`] events instead. Correct for\n pure-metered, hybrid, tiered, and flat — recommended.\n* `UseSubscription`: trust whatever MRR the subscription parser\n returns (0 for metered). Legacy behavior.\n* `Ignore`: drop metered subscriptions from MRR entirely.","enum":["derive_from_invoices","use_subscription","ignore"]},"MetricAggregation":{"oneOf":[{"type":"string","description":"Arithmetic mean of the scalar value in each bucket. The default.","enum":["avg"]},{"type":"string","description":"Sum of the scalar value in each bucket.","enum":["sum"]},{"type":"string","description":"Minimum scalar value in each bucket.","enum":["min"]},{"type":"string","description":"Maximum scalar value in each bucket.","enum":["max"]},{"type":"string","description":"Number of points in each bucket.","enum":["count"]},{"type":"string","description":"Per-second rate of change of a cumulative monotonic counter, computed as\n`(max - min) / window_seconds` within each bucket. Non-monotonic series\nfall back to a simple delta.","enum":["rate_per_sec"]},{"type":"object","description":"A quantile of the scalar value in each bucket. The carried `f64` is the\nrequested quantile in `[0.0, 1.0]`.","required":["quantile"],"properties":{"quantile":{"type":"number","format":"double","description":"A quantile of the scalar value in each bucket. The carried `f64` is the\nrequested quantile in `[0.0, 1.0]`."}}}],"description":"The aggregation applied when reducing raw metric points into a time bucket.\n\nStore-neutral: every storage backend (ClickHouse today, TimescaleDB later)\nmust be able to satisfy this contract. `Quantile(q)` carries the requested\nquantile in `[0.0, 1.0]` (e.g. `0.95` for p95)."},"MetricBucket":{"type":"object","description":"A time-bucketed metric aggregate for chart display.\n\nStore-neutral response contract. The legacy scalar fields\n(`avg_value`/`min_value`/`max_value`/`count`) are always populated for chart\nback-compat. The richer fields describe the explicitly-requested\n[`MetricAggregation`] (`value`), optional `quantiles`, an optional\n`histogram_summary`, and a `series_key` identifying the label-set when the\nquery used `group_by`.","required":["bucket","avg_value","min_value","max_value","count"],"properties":{"avg_value":{"type":"number","format":"double"},"bucket":{"type":"string","format":"date-time"},"count":{"type":"integer","format":"int64"},"histogram_summary":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/HistogramSummary","description":"A reduced histogram summary when the bucketed metric is a histogram."}]},"max_value":{"type":"number","format":"double"},"min_value":{"type":"number","format":"double"},"quantiles":{"type":"array","items":{"type":"array","items":false,"prefixItems":[{"type":"number","format":"double"},{"type":"number","format":"double"}]},"description":"Computed quantile/value pairs `(quantile, value)` when the query asked for\nquantile aggregation; otherwise empty."},"series_key":{"type":["array","null"],"items":{"type":"array","items":false,"prefixItems":[{"type":"string"},{"type":"string"}]},"description":"The label-set this bucket belongs to, as ordered `(key, value)` pairs,\nwhen the query grouped by labels. Empty/`None` = the single ungrouped\naggregate stream."},"value":{"type":"number","format":"double","description":"The value of the requested [`MetricAggregation`] for this bucket. For the\ndefault `Avg` aggregation this equals `avg_value`. `#[serde(default)]` so\npre-existing payloads (which only carried avg/min/max/count) still parse."}}},"MetricDataPoint":{"type":"object","description":"A single `(timestamp, value)` data point in a metric series.","required":["time","value"],"properties":{"time":{"type":"string","description":"ISO 8601 timestamp with `Z` suffix."},"value":{"type":"number","format":"double","description":"Metric value at this bucket."}}},"MetricType":{"type":"string","description":"The type of an OTel metric.","enum":["gauge","sum","histogram","exponential_histogram","summary"]},"MetricsOverTimeResponse":{"type":"object","required":["timestamps","ttfb","lcp","fid","fcp","cls","inp"],"properties":{"cls":{"type":"array","items":{"type":["number","null"],"format":"float"}},"cls_p75":{"type":["number","null"],"format":"float"},"cls_p90":{"type":["number","null"],"format":"float"},"cls_p95":{"type":["number","null"],"format":"float"},"cls_p99":{"type":["number","null"],"format":"float"},"fcp":{"type":"array","items":{"type":["number","null"],"format":"float"}},"fcp_p75":{"type":["number","null"],"format":"float"},"fcp_p90":{"type":["number","null"],"format":"float"},"fcp_p95":{"type":["number","null"],"format":"float"},"fcp_p99":{"type":["number","null"],"format":"float"},"fid":{"type":"array","items":{"type":["number","null"],"format":"float"}},"fid_p75":{"type":["number","null"],"format":"float"},"fid_p90":{"type":["number","null"],"format":"float"},"fid_p95":{"type":["number","null"],"format":"float"},"fid_p99":{"type":["number","null"],"format":"float"},"inp":{"type":"array","items":{"type":["number","null"],"format":"float"}},"inp_p75":{"type":["number","null"],"format":"float"},"inp_p90":{"type":["number","null"],"format":"float"},"inp_p95":{"type":["number","null"],"format":"float"},"inp_p99":{"type":["number","null"],"format":"float"},"lcp":{"type":"array","items":{"type":["number","null"],"format":"float"}},"lcp_p75":{"type":["number","null"],"format":"float"},"lcp_p90":{"type":["number","null"],"format":"float"},"lcp_p95":{"type":["number","null"],"format":"float"},"lcp_p99":{"type":["number","null"],"format":"float"},"timestamps":{"type":"array","items":{"type":"string"}},"ttfb":{"type":"array","items":{"type":["number","null"],"format":"float"}},"ttfb_p75":{"type":["number","null"],"format":"float"},"ttfb_p90":{"type":["number","null"],"format":"float"},"ttfb_p95":{"type":["number","null"],"format":"float"},"ttfb_p99":{"type":["number","null"],"format":"float"}}},"MetricsQuery":{"type":"object","required":["start_date","end_date","project_id"],"properties":{"deployment_id":{"type":["integer","null"],"format":"int32"},"end_date":{"type":"string","format":"date-time"},"environment_id":{"type":["integer","null"],"format":"int32"},"project_id":{"type":"integer","format":"int32"},"start_date":{"type":"string","format":"date-time"}}},"MetricsRangeQuery":{"type":"object","description":"Query params for range metric queries.","required":["metric"],"properties":{"metric":{"type":"string","description":"Metric name, e.g. `\"pg.connections_active\"`."},"percentile":{"type":["number","null"],"format":"double","description":"Optional histogram percentile (0–100). When provided, the endpoint\nfetches histogram buckets and computes the requested quantile."},"range":{"type":"string","description":"Time window: `\"1h\"` | `\"6h\"` | `\"24h\"` | `\"7d\"`."}}},"MetricsStatusResponse":{"type":"object","description":"Freshness status: when metrics were last received for this service.","properties":{"last_received_at":{"type":["string","null"],"description":"ISO 8601 timestamp of the most recent metric row, or null if none yet."}}},"MetricsStoreKind":{"type":"string","description":"Which storage backend to use for the MetricsStore.","enum":["timescale_db","click_house"]},"MetricsSummaryResponse":{"type":"object","required":["currency","current_mrr_minor","current_arr_minor","active_subscriptions","active_customers","churned_last_30d","arpu_minor"],"properties":{"active_customers":{"type":"integer","format":"int64"},"active_subscriptions":{"type":"integer","format":"int64"},"arpu_minor":{"type":"integer","format":"int64"},"churned_last_30d":{"type":"integer","format":"int64"},"currency":{"type":"string"},"current_arr_minor":{"type":"integer","format":"int64"},"current_mrr_minor":{"type":"integer","format":"int64"}}},"MfaRequiredResponse":{"type":"object","required":["requires_mfa","session_token"],"properties":{"requires_mfa":{"type":"boolean"},"session_token":{"type":"string"}}},"MfaSetupResponse":{"type":"object","required":["secret_key","qr_code","recovery_codes"],"properties":{"qr_code":{"type":"string"},"recovery_codes":{"type":"array","items":{"type":"string"}},"secret_key":{"type":"string"}}},"MfaVerificationRequest":{"type":"object","required":["code"],"properties":{"code":{"type":"string"}}},"MigrationStep":{"type":"object","description":"A single step in the migration execution plan.\n\nSteps are presented to the user before execution so they know exactly\nwhat will happen. During execution, each step runs in order and reports\nits outcome before proceeding to the next.","required":["order","id","title","description","resource_type","risk","skippable","reversible"],"properties":{"data_implications":{"type":"array","items":{"$ref":"#/components/schemas/DataImplication"},"description":"Data implications — what could go wrong or what the user needs to know"},"description":{"type":"string","description":"Detailed description of what this step does"},"estimated_duration":{"type":["string","null"],"description":"Estimated duration hint (e.g., \"< 1 second\", \"10-30 seconds\")"},"id":{"type":"string","description":"Machine-readable step identifier (e.g., \"create-project\", \"create-service-postgres\")"},"order":{"type":"integer","description":"Step number (1-based, for display)","minimum":0},"post_conditions":{"type":"array","items":{"type":"string"},"description":"Things the user should verify AFTER this step completes"},"pre_conditions":{"type":"array","items":{"type":"string"},"description":"Things the user should verify BEFORE this step runs"},"resource_type":{"$ref":"#/components/schemas/StepResourceType","description":"What kind of resource this step creates/modifies"},"reversible":{"type":"boolean","description":"Whether this step is reversible (can be cleaned up on failure)"},"risk":{"$ref":"#/components/schemas/RiskLevel","description":"Risk level for this step"},"skippable":{"type":"boolean","description":"Whether this step can be skipped by the user"},"skipped":{"type":"boolean","description":"Whether the user has chosen to skip this step (set during review)"},"title":{"type":"string","description":"Human-readable title (e.g., \"Create project 'my-app'\")"}}},"MigrationSummary":{"type":"object","description":"Human-readable summary of the entire migration plan","required":["headline","overall_risk","resource_counts"],"properties":{"critical_warnings":{"type":"array","items":{"type":"string"},"description":"Critical warnings that must be acknowledged before proceeding.\nThese are the most important things the user needs to know."},"headline":{"type":"string","description":"One-line summary (e.g., \"Migrate 'my-app' from Vercel with 1 database, 2 domains\")"},"manual_actions_required":{"type":"array","items":{"$ref":"#/components/schemas/ManualAction"},"description":"Manual actions the user must perform (before or after migration)"},"overall_risk":{"$ref":"#/components/schemas/RiskLevel","description":"Overall risk assessment for the migration"},"resource_counts":{"$ref":"#/components/schemas/ResourceCounts","description":"Resource counts for quick overview"},"unsupported_features":{"type":"array","items":{"$ref":"#/components/schemas/UnsupportedFeature"},"description":"Features from the source platform that cannot be migrated"}}},"MintEnrollmentTokenRequest":{"type":"object","properties":{"bound_node_name":{"type":["string","null"],"description":"Optional: restrict the token to register one specific node name."},"max_uses":{"type":["integer","null"],"format":"int32","description":"Maximum registrations this token may authorize (default 1)."},"ttl_secs":{"type":["integer","null"],"format":"int64","description":"Time-to-live in seconds (default 3600 = 1h)."}}},"MintEnrollmentTokenResponse":{"type":"object","required":["id","token","expires_at","max_uses","message"],"properties":{"ca_fingerprint":{"type":["string","null"],"description":"SHA-256 fingerprint of the cluster CA (if mTLS is set up). Pass it to the\nworker as `temps join --ca-fingerprint ` to verify the CA on join."},"expires_at":{"type":"string"},"id":{"type":"integer","format":"int32"},"max_uses":{"type":"integer","format":"int32"},"message":{"type":"string"},"token":{"type":"string","description":"The plaintext enrollment token — shown only once, save it now."}}},"MiscResult":{"type":"object","description":"Miscellaneous validation result","required":["is_disposable","is_role_account","is_b2c"],"properties":{"gravatar_url":{"type":["string","null"],"description":"Gravatar URL if available"},"is_b2c":{"type":"boolean","description":"Whether the email provider is a B2C (consumer) email provider"},"is_disposable":{"type":"boolean","description":"Whether the email is from a disposable email provider"},"is_role_account":{"type":"boolean","description":"Whether the email is a role-based account (e.g., admin@, info@)"}}},"MkdirBody":{"type":"object","required":["path"],"properties":{"path":{"type":"string"}},"additionalProperties":false},"ModelInfo":{"type":"object","required":["id","object","owned_by"],"properties":{"id":{"type":"string"},"object":{"type":"string"},"owned_by":{"type":"string"}}},"ModelListResponse":{"type":"object","required":["object","data"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ModelInfo"}},"object":{"type":"string"}}},"ModelPricing":{"type":"object","description":"Pricing for a single model, all values in USD per 1M tokens.\nFields are optional because not every provider supports every pricing tier.","required":["model","display_name","provider","input_per_million","output_per_million"],"properties":{"batch_input_per_million":{"type":["number","null"],"format":"double","description":"Batch API input cost per 1M tokens (if provider offers batch pricing)"},"batch_output_per_million":{"type":["number","null"],"format":"double","description":"Batch API output cost per 1M tokens"},"cache_hit_per_million":{"type":["number","null"],"format":"double","description":"Cache hit / refresh cost per 1M tokens"},"cache_write_1h_per_million":{"type":["number","null"],"format":"double","description":"1-hour cache write cost per 1M tokens"},"cache_write_5m_per_million":{"type":["number","null"],"format":"double","description":"5-minute cache write cost per 1M tokens (Anthropic-style prompt caching)"},"deprecated":{"type":"boolean","description":"Whether the model is deprecated"},"display_name":{"type":"string","description":"Human-readable model name (e.g. \"Claude Sonnet 4.6\")"},"input_per_million":{"type":"number","format":"double","description":"Base input token cost per 1M tokens"},"model":{"type":"string","description":"Model identifier (e.g. \"gpt-5.4\", \"claude-sonnet-4-6\")"},"output_per_million":{"type":"number","format":"double","description":"Output token cost per 1M tokens"},"provider":{"type":"string","description":"Provider ID (e.g. \"openai\", \"anthropic\")"}}},"ModelUsage":{"type":"object","required":["model","provider","request_count","input_tokens","output_tokens","total_tokens","avg_latency_ms"],"properties":{"avg_latency_ms":{"type":"number","format":"double"},"input_tokens":{"type":"integer","format":"int64"},"model":{"type":"string"},"output_tokens":{"type":"integer","format":"int64"},"provider":{"type":"string"},"request_count":{"type":"integer","format":"int64"},"total_tokens":{"type":"integer","format":"int64"}}},"MonitorResponse":{"type":"object","required":["id","project_id","name","monitor_type","monitor_url","check_interval_seconds","is_active","created_at","updated_at"],"properties":{"check_interval_seconds":{"type":"integer","format":"int32"},"check_path":{"type":["string","null"]},"created_at":{"type":"string","format":"date-time"},"environment_id":{"type":["integer","null"],"format":"int32"},"id":{"type":"integer","format":"int32"},"is_active":{"type":"boolean"},"monitor_type":{"type":"string"},"monitor_url":{"type":"string"},"name":{"type":"string"},"project_id":{"type":"integer","format":"int32"},"updated_at":{"type":"string","format":"date-time"}}},"MonitorStatus":{"type":"object","required":["monitor","current_status","uptime_percentage"],"properties":{"avg_response_time_ms":{"type":["integer","null"],"format":"int32"},"current_status":{"type":"string"},"monitor":{"$ref":"#/components/schemas/MonitorResponse"},"uptime_percentage":{"type":"number","format":"double"}}},"MonitoringSettings":{"type":"object","description":"Global metrics observability configuration.\n\nControls whether the MetricsScraper and AlertEvaluator background tasks\nare active, which storage backend they write to, and how long data is kept\nat each retention tier.","properties":{"clickhouse_url":{"type":["string","null"],"description":"ClickHouse DSN (legacy, optional). The runtime metrics store is built\nfrom the `TEMPS_CLICKHOUSE_*` env vars, never from this field; it is\nretained for compatibility and operator reference only.\nExample: `\"http://localhost:8123\"`.","default":null},"enabled":{"type":"boolean","description":"Enable or disable all metrics collection (scraping + alerting).\nDefaults to `false` so new installs don't write to TimescaleDB until\nan operator explicitly enables the feature.","default":false},"retention_daily_years":{"type":"integer","format":"int32","description":"How many years of daily-aggregate data to keep (converted to days internally).","default":2,"example":2,"maximum":10,"minimum":1},"retention_hourly_days":{"type":"integer","format":"int32","description":"How many days of hourly-aggregate data to keep.","default":90,"example":90,"minimum":1},"retention_raw_days":{"type":"integer","format":"int32","description":"How many days of raw (30 s resolution) metric data to keep.","default":7,"example":7,"minimum":1},"scrape_interval_secs":{"type":"integer","format":"int64","description":"How often the MetricsScraper collects data from all sources, in seconds.\nMinimum effective value is 10 s; values below that are clamped at runtime.","default":30,"example":30,"minimum":10},"store":{"oneOf":[{"$ref":"#/components/schemas/MetricsStoreKind","description":"Storage backend for metric data."}],"default":"timescale_db"}}},"MonitoringSettingsMasked":{"type":"object","description":"Monitoring settings with the ClickHouse DSN masked.\n\n`clickhouse_url` can embed credentials (`http://user:pass@host`), so it is\nreported only as a boolean (`clickhouse_url_set`) rather than echoed back —\nconsistent with how the DNS API key and Docker registry password are masked.","required":["enabled","store","scrape_interval_secs","retention_raw_days","retention_hourly_days","retention_daily_years","clickhouse_url_set"],"properties":{"clickhouse_url_set":{"type":"boolean","description":"True when a ClickHouse DSN is configured. The DSN itself is never\nreturned over HTTP because it may contain credentials."},"enabled":{"type":"boolean"},"retention_daily_years":{"type":"integer","format":"int32","minimum":0},"retention_hourly_days":{"type":"integer","format":"int32","minimum":0},"retention_raw_days":{"type":"integer","format":"int32","minimum":0},"scrape_interval_secs":{"type":"integer","format":"int64","minimum":0},"store":{"$ref":"#/components/schemas/MetricsStoreKind"}}},"MrrBucketResponse":{"type":"object","required":["bucket","mrr_minor","charge_total_minor","refund_total_minor","charge_count"],"properties":{"bucket":{"type":"string","format":"date-time"},"charge_count":{"type":"integer","format":"int64"},"charge_total_minor":{"type":"integer","format":"int64"},"mrr_minor":{"type":"integer","format":"int64"},"refund_total_minor":{"type":"integer","format":"int64"}}},"MultiNodeSettings":{"type":"object","description":"Multi-node cluster settings","properties":{"cluster_ca_cert_pem":{"type":["string","null"],"description":"Per-cluster CA certificate (PEM) for multi-node mTLS (ADR-020 WS-2.1).\nPublic — distributed to nodes as the trust root and used by the control\nplane as the root for verifying agent server certs. Minted lazily on the\nfirst CSR-bearing registration.","default":null},"cluster_ca_key_encrypted":{"type":["string","null"],"description":"Per-cluster CA private key, AES-256-GCM ciphertext (EncryptionService).\nSECRET — never returned over HTTP (elided in the masked response).","default":null},"join_token_hash":{"type":["string","null"],"description":"SHA-256 hash of the join token (never store plaintext)","default":null},"legacy_shared_token_enabled":{"type":"boolean","description":"Whether the legacy single shared join token is still accepted for node\nregistration (ADR-020 WS-1.1). Defaults to `true` so existing clusters\nkeep working on upgrade; fresh installs should set it `false` and rely on\nshort-lived, single-use enrollment tokens instead.","default":true},"node_cpu_alert_percent":{"type":["number","null"],"format":"double","description":"CPU-usage percent above which a worker node raises a resource alert\n(ADR-020 / monitoring). `None` disables CPU alerting. Default 90.","default":90.0},"node_disk_alert_percent":{"type":["number","null"],"format":"double","description":"Disk-usage percent above which a worker node raises a resource alert.\n`None` disables disk alerting. Default 90.","default":90.0},"node_memory_alert_percent":{"type":["number","null"],"format":"double","description":"Memory-usage percent above which a worker node raises a resource alert.\n`None` disables memory alerting. Default 90.","default":90.0},"private_address":{"type":["string","null"],"description":"Private/WireGuard IP address of the control plane node.\nUsed by remote worker nodes to reach services (databases, etc.) running on the control plane.\nSet via `--private-address` or `TEMPS_PRIVATE_ADDRESS`.","default":null},"require_mtls":{"type":"boolean","description":"Whether to enforce multi-node mTLS (ADR-020 WS-2.1). When `false`\n(default), the control plane ignores join-time CSRs and nodes keep\nserving plaintext HTTP — zero behavior change. When `true`, the CP signs\nnode CSRs, nodes serve mutual TLS, and every CP→agent call uses the\ncluster client cert. Observe-then-enforce: flip this on only once all\nworkers have re-enrolled with certs.","default":false}}},"MultiNodeSettingsMasked":{"type":"object","description":"Multi-node settings with `join_token_hash` elided.","required":["has_join_token","require_mtls","legacy_shared_token_enabled"],"properties":{"cluster_ca_fingerprint":{"type":["string","null"],"description":"SHA-256 fingerprint of the cluster CA certificate (public — operators can\nverify it out of band; the CA private key is never exposed)."},"has_join_token":{"type":"boolean"},"legacy_shared_token_enabled":{"type":"boolean","description":"Whether the deprecated shared join token is still accepted."},"node_cpu_alert_percent":{"type":["number","null"],"format":"double","description":"Node resource-alert thresholds (percent); `None` = that alert disabled."},"node_disk_alert_percent":{"type":["number","null"],"format":"double"},"node_memory_alert_percent":{"type":["number","null"],"format":"double"},"private_address":{"type":["string","null"]},"require_mtls":{"type":"boolean","description":"Whether control-plane↔agent mutual TLS is enforced."}}},"MxResult":{"type":"object","description":"MX (Mail Exchange) validation result","required":["accepts_mail","records"],"properties":{"accepts_mail":{"type":"boolean","description":"Whether the domain accepts mail"},"error":{"type":["string","null"],"description":"Error message if MX lookup failed"},"records":{"type":"array","items":{"type":"string"},"description":"List of MX records for the domain","example":["alt1.gmail-smtp-in.l.google.com.","gmail-smtp-in.l.google.com."]}}},"NavEntry":{"type":"object","description":"A navigation entry that the plugin contributes to the Temps UI.","required":["label","icon","section","path","order"],"properties":{"icon":{"type":"string","description":"Lucide icon name (e.g., \"puzzle\", \"database\", \"activity\")"},"label":{"type":"string","description":"Display label in the sidebar"},"order":{"type":"integer","format":"int32","description":"Sort order within the section (lower = higher in list)","minimum":0},"path":{"type":"string","description":"Client-side route path (e.g., \"/my-plugin\")"},"section":{"$ref":"#/components/schemas/NavSection","description":"Which sidebar section this entry belongs to"}}},"NavSection":{"type":"string","description":"Where the plugin's nav entry appears in the Temps UI sidebar.","enum":["platform","settings","project"]},"NetworkConfiguration":{"type":"object","description":"Network configuration","required":["mode","dns_servers"],"properties":{"dns_servers":{"type":"array","items":{"type":"string"},"description":"DNS servers"},"hostname":{"type":["string","null"],"description":"Hostname"},"mode":{"$ref":"#/components/schemas/NetworkMode","description":"Network mode"}}},"NetworkMode":{"oneOf":[{"type":"string","enum":["bridge"]},{"type":"string","enum":["host"]},{"type":"string","enum":["none"]},{"type":"object","required":["custom"],"properties":{"custom":{"type":"string"}}}],"description":"Network mode"},"NixpacksPresetConfig":{"type":"object","description":"Configuration for Nixpacks preset\nNixpacks provider and inline build-plan configuration.","properties":{"nixpacksConfig":{"type":["string","null"],"description":"Optional inline nixpacks.toml contents."},"providers":{"type":"array","items":{"$ref":"#/components/schemas/NixpacksProvider"},"description":"Ordered Nixpacks providers. Empty means repository config or auto-detect;\ninclude `...` to combine auto-detection with explicit providers."}}},"NixpacksProvider":{"type":"string","description":"A Nixpacks build provider.\n\n`Auto` serializes as the native Nixpacks `...` marker, which includes the\nprovider detected from the project alongside any explicitly listed\nproviders.","enum":["...","node","python","rust","go","java","php","ruby","deno","elixir","csharp","fsharp","dart","swift","zig","scala","haskell","clojure","crystal","cobol","gleam","lunatic","scheme","static"]},"NodeContainerListResponse":{"type":"object","required":["containers","total"],"properties":{"containers":{"type":"array","items":{"$ref":"#/components/schemas/NodeContainerResponse"}},"total":{"type":"integer","minimum":0}}},"NodeContainerResponse":{"type":"object","description":"A container running on a specific node, enriched with project/environment context.","required":["container_id","container_name","image_name","status","created_at","deployment_id","project_id","project_name","environment_id","environment_name"],"properties":{"container_id":{"type":"string"},"container_name":{"type":"string"},"created_at":{"type":"string"},"deployment_id":{"type":"integer","format":"int32"},"environment_id":{"type":"integer","format":"int32"},"environment_name":{"type":"string"},"image_name":{"type":"string"},"project_id":{"type":"integer","format":"int32"},"project_name":{"type":"string"},"status":{"type":"string"}}},"NodeCostInfo":{"type":"object","description":"One cluster node with capacity and (when priceable) a cost estimate","required":["name","cpu_millis","memory_mb"],"properties":{"cpu_millis":{"type":"integer","format":"int64","description":"CPU capacity in millicores"},"instance_type":{"type":["string","null"],"description":"Instance type from `node.kubernetes.io/instance-type` (e.g. \"m5.xlarge\")"},"memory_mb":{"type":"integer","format":"int64","description":"Memory capacity in MB"},"monthly_usd":{"type":["number","null"],"format":"double","description":"Estimated on-demand monthly price in USD. `None` when the instance\ntype is unknown or not in the price table."},"name":{"type":"string","description":"Node name"},"region":{"type":["string","null"],"description":"Region from `topology.kubernetes.io/region`"}}},"NodeInfoResponse":{"type":"object","required":["id","name","address","private_address","role","status","labels","capacity","created_at"],"properties":{"address":{"type":"string"},"architecture":{"type":["string","null"],"description":"Container platform this node runs (`linux/amd64`, `linux/arm64`).\n`None` until an agent that reports it has heartbeated."},"capacity":{"description":"Resource capacity/usage metrics from the latest heartbeat"},"created_at":{"type":"string"},"id":{"type":"integer","format":"int32"},"labels":{},"last_heartbeat":{"type":["string","null"]},"name":{"type":"string"},"private_address":{"type":"string"},"role":{"type":"string"},"status":{"type":"string"}}},"NodeListResponse":{"type":"object","required":["nodes","total"],"properties":{"nodes":{"type":"array","items":{"$ref":"#/components/schemas/NodeInfoResponse"}},"total":{"type":"integer","minimum":0}}},"NotificationPreferencesResponse":{"type":"object","required":["email_enabled","slack_enabled","batch_similar_notifications","minimum_severity","deployment_failures_enabled","build_errors_enabled","runtime_errors_enabled","error_threshold","error_time_window","ssl_expiration_enabled","ssl_days_before_expiration","domain_expiration_enabled","dns_changes_enabled","backup_failures_enabled","backup_successes_enabled","s3_connection_issues_enabled","retention_policy_violations_enabled","route_downtime_enabled","load_balancer_issues_enabled","weekly_digest_enabled","digest_send_day","digest_send_time","digest_sections"],"properties":{"backup_failures_enabled":{"type":"boolean"},"backup_successes_enabled":{"type":"boolean"},"batch_similar_notifications":{"type":"boolean"},"build_errors_enabled":{"type":"boolean"},"deployment_failures_enabled":{"type":"boolean"},"digest_sections":{"$ref":"#/components/schemas/DigestSections"},"digest_send_day":{"type":"string"},"digest_send_time":{"type":"string"},"dns_changes_enabled":{"type":"boolean"},"domain_expiration_enabled":{"type":"boolean"},"email_enabled":{"type":"boolean"},"error_threshold":{"type":"integer","format":"int32"},"error_time_window":{"type":"integer","format":"int32"},"load_balancer_issues_enabled":{"type":"boolean"},"minimum_severity":{"type":"string"},"retention_policy_violations_enabled":{"type":"boolean"},"route_downtime_enabled":{"type":"boolean"},"runtime_errors_enabled":{"type":"boolean"},"s3_connection_issues_enabled":{"type":"boolean"},"slack_enabled":{"type":"boolean"},"ssl_days_before_expiration":{"type":"integer","format":"int32"},"ssl_expiration_enabled":{"type":"boolean"},"weekly_digest_enabled":{"type":"boolean"}}},"NotificationProviderResponse":{"type":"object","required":["id","name","provider_type","config","enabled","created_at","updated_at"],"properties":{"config":{},"created_at":{"type":"integer","format":"int64"},"enabled":{"type":"boolean"},"id":{"type":"integer","format":"int32"},"name":{"type":"string"},"provider_type":{"type":"string"},"updated_at":{"type":"integer","format":"int64"}}},"ObservabilityCompressionSettings":{"type":"object","description":"TimescaleDB compression policy configuration for append-only observability\ntables. Values are expressed in hours so operators can choose sub-day\nwindows while keeping the API representation unambiguous.","properties":{"otel_spans_after_hours":{"type":"integer","format":"int32","description":"Compress OpenTelemetry span chunks after this many hours. Defaults to\n24 hours.","default":24,"example":24,"maximum":2160,"minimum":1},"proxy_logs_after_hours":{"type":"integer","format":"int32","description":"Compress proxy-log chunks after this many hours. Defaults to 24 hours.","default":24,"example":24,"maximum":720,"minimum":1}}},"ObservabilityEvent":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/RequestRow"},{"type":"object","required":["type"],"properties":{"type":{"type":"string","enum":["request"]}}}]},{"allOf":[{"$ref":"#/components/schemas/SpanRow"},{"type":"object","required":["type"],"properties":{"type":{"type":"string","enum":["span"]}}}]},{"allOf":[{"$ref":"#/components/schemas/ErrorRow"},{"type":"object","required":["type"],"properties":{"type":{"type":"string","enum":["error"]}}}]},{"allOf":[{"$ref":"#/components/schemas/RevenueRow"},{"type":"object","required":["type"],"properties":{"type":{"type":"string","enum":["revenue"]}}}]}],"description":"Discriminated union of every row that can appear in the Observe list.\n\nSerializes to `{ \"type\": \"request\" | \"span\" | ... , ...rest }` so the UI\ncan switch on `event.type` without ambiguity.\n\n**No `Log` variant**: runtime stdout/stderr lines live on a dedicated\nLogs page rather than Observe. Logs are too high-volume to interleave\nwith business signals (requests, errors, revenue) without dominating\nthe timeline, and they have their own retention/storage constraints\n(TimescaleDB hypertable + chunked file/S3 store) that don't compose\nwith the merge service's per-kind LIMIT strategy."},"ObservabilityRetentionSettings":{"type":"object","description":"Retention policy configuration for raw observability tables. Values are in\ndays. The Settings API applies them to TimescaleDB; ClickHouse-backed proxy\nlogs and spans retain their storage-level per-row TTL behavior.","properties":{"otel_logs_days":{"type":"integer","format":"int32","description":"Retain OpenTelemetry log events for this many days.","default":90,"example":90,"maximum":3650,"minimum":1},"otel_metrics_days":{"type":"integer","format":"int32","description":"Retain OpenTelemetry metric points for this many days.","default":90,"example":90,"maximum":3650,"minimum":1},"otel_spans_days":{"type":"integer","format":"int32","description":"Retain OpenTelemetry spans (traces) for this many days.","default":90,"example":90,"maximum":3650,"minimum":1},"proxy_logs_days":{"type":"integer","format":"int32","description":"Retain proxy request logs for this many days.","default":30,"example":30,"maximum":3650,"minimum":1}}},"OidcProviderResponse":{"type":"object","required":["id","name","issuer_url","client_id","client_secret","scopes","jit_provisioning","enabled","template","group_claim","role_claim","default_role","trust_idp_email"],"properties":{"client_id":{"type":"string"},"client_secret":{"type":"string","description":"Always masked — the secret is never returned after creation."},"default_role":{"type":"string"},"enabled":{"type":"boolean"},"group_claim":{"type":"string"},"id":{"type":"integer","format":"int32"},"issuer_url":{"type":"string"},"jit_provisioning":{"type":"boolean"},"name":{"type":"string"},"role_claim":{"type":"string"},"scopes":{"type":"string"},"template":{"type":"string"},"trust_idp_email":{"type":"boolean","description":"When true, the resolver skips the `email_verified` claim gate\nduring SSO login. Only safe for IdPs where an admin controls\nuser provisioning — see `oidc_providers::Model::trust_idp_email`."}}},"OidcProviderSummary":{"type":"object","required":["slug","name","template"],"properties":{"name":{"type":"string"},"slug":{"type":"string","description":"Stable opaque slug — use this as the path parameter when initiating\nOIDC login (`/auth/oidc/login/{slug}`). The integer database ID is\nintentionally omitted from this public endpoint to prevent provider\nenumeration."},"template":{"type":"string","description":"The template the provider was created from — e.g. `keycloak`,\n`okta`, `auth0`, `google`, `azure-ad`, or `generic`. Surfaced on\nthe public login endpoint so the unauthenticated login page can\nrender the right brand logo on the \"Sign in with X\" button.\nNever sensitive — the template name is part of the provider's\npublic identity, not configuration."}}},"OidcProviderUserResponse":{"type":"object","description":"A user that has logged in via a given OIDC provider. Used by the\nadmin \"Users for provider\" panel — the `oidc_subject` is the\nIdP-side identifier we matched on, useful when diagnosing why a\nuser can or can't log in.","required":["id","name","email","email_verified","mfa_enabled","created_at","updated_at"],"properties":{"created_at":{"type":"string","format":"date-time","example":"2024-01-15T14:30:00Z"},"email":{"type":"string"},"email_verified":{"type":"boolean"},"id":{"type":"integer","format":"int32"},"mfa_enabled":{"type":"boolean"},"name":{"type":"string"},"oidc_subject":{"type":["string","null"]},"updated_at":{"type":"string","format":"date-time","example":"2024-01-15T14:30:00Z"}}},"OidcProvidersListResponse":{"type":"object","required":["providers"],"properties":{"providers":{"type":"array","items":{"$ref":"#/components/schemas/OidcProviderSummary"}}}},"OidcRoleMappingResponse":{"type":"object","required":["id","provider_id","priority","idp_group","role"],"properties":{"id":{"type":"integer","format":"int32"},"idp_group":{"type":"string"},"priority":{"type":"integer","format":"int32"},"provider_id":{"type":"integer","format":"int32"},"role":{"type":"string"}}},"OidcTestConnectionResponse":{"type":"object","required":["success","message"],"properties":{"message":{"type":"string"},"success":{"type":"boolean"}}},"OnDemandCertAttemptResponse":{"type":"object","description":"A single on-demand HTTP-01 issuance attempt from the append-only\n`on_demand_cert_attempts` audit log. Carries the full forensic detail for one\nattempt; the current cert state lives on the enclosing row's domain fields.\n\nContains no private-key or certificate material — only audit metadata — so it\nis safe to return without masking.","required":["id","hostname","trigger","outcome","created_at"],"properties":{"acme_request_sent":{"type":["boolean","null"],"description":"Did we reach the Let's Encrypt API?"},"acme_response_status":{"type":["string","null"],"description":"HTTP status or ACME error type returned by Let's Encrypt, when known."},"challenge_served":{"type":["boolean","null"],"description":"Did the proxy serve the `/.well-known/acme-challenge/` request?"},"created_at":{"type":"integer","format":"int64","description":"When the attempt was recorded (epoch millis)."},"duration_ms":{"type":["integer","null"],"format":"int32","description":"End-to-end issuance duration in milliseconds (0/None for skipped)."},"error_category":{"type":["string","null"],"description":"Coarse error category for UI labelling: `\"rate_limited\"`, `\"dns_failure\"`,\n`\"acme_order_expired\"`, `\"challenge_mismatch\"`, `\"timeout\"`, `\"internal\"`."},"error_chain":{"type":["string","null"],"description":"Full `Display` chain of the error (all `source()` levels), when failed."},"hostname":{"type":"string","description":"SNI hostname that triggered the attempt."},"id":{"type":"integer","format":"int32"},"outcome":{"type":"string","description":"Final outcome: `\"issued\"`, `\"failed\"`, `\"skipped_duplicate\"`,\n`\"skipped_gate\"`, `\"skipped_rate_limit\"`, or `\"skipped_no_route\"`."},"trigger":{"type":"string","description":"What triggered the attempt (always `\"tls_callback\"` today)."}}},"OnDemandCertRow":{"type":"object","description":"One row of the on-demand certificates list: the most-recent attempt for a\nhostname plus the current authoritative cert state from its `domains` row.","required":["hostname","attempt"],"properties":{"attempt":{"$ref":"#/components/schemas/OnDemandCertAttemptResponse","description":"The audit record for the attempt this row represents (newest first in\nthe list)."},"backoff_until":{"type":["integer","null"],"format":"int64","description":"On-demand negative-cache deadline (epoch millis), when in backoff."},"expiration_time":{"type":["integer","null"],"format":"int64","description":"Certificate expiration (epoch millis), when an active cert exists."},"hostname":{"type":"string","description":"SNI hostname."},"status":{"type":["string","null"],"description":"Current cert lifecycle status from the `domains` row, when one exists:\n`on_demand_pending`, `on_demand_issuing`, `active`, `on_demand_failed`,\netc. `None` when no `domains` row exists yet for this hostname."}}},"OnDemandTlsSettings":{"type":"object","description":"On-demand (lazy) HTTP-01 TLS issuance settings (ADR-018).\n\nWhen `enabled`, the proxy's `certificate_callback` triggers ACME HTTP-01\nissuance for allowlisted, STABLE hostnames (per-environment aliases and the\nconsole host) that have no active cert, rather than silently failing the\nhandshake. Ephemeral per-deployment hostnames are NEVER certed (ADR §2).\n\nOff by default — operators opt in explicitly, except QuickStart (`sslip.io`)\ninstalls where `temps setup` auto-enables it and derives `zone`.","properties":{"deployment_url_mode":{"type":"string","description":"How ephemeral per-deployment hostnames behave when they have no cert\n(they are NEVER certed — see ADR §2). One of:\n - `\"http\"` (default): serve plain HTTP on :80.\n - `\"redirect_to_env\"`: 308-redirect to the stable per-environment URL,\n which IS certed.","default":"http","example":"http"},"enabled":{"type":"boolean","description":"Master switch. When `false` (default) the proxy's on-demand cert gate\nrejects every SNI and no issuance is ever triggered.","default":false,"example":false},"hourly_cap":{"type":"integer","format":"int32","description":"Global cap on total on-demand issuances per hour across all hostnames\n(ADR §4 Layer 3). The operator's self-imposed safety net, separate from\nthe Let's Encrypt rate limit.","default":10,"example":10,"minimum":1},"max_concurrent":{"type":"integer","format":"int32","description":"Maximum number of ACME issuance flows allowed to run simultaneously\n(the concurrent-issuance semaphore, ADR §4 Layer 1). Min 1.","default":3,"example":3,"minimum":1},"zone":{"type":["string","null"],"description":"Zone suffix for the allowlist gate. A hostname passes the gate only if\nit is a direct subdomain of this zone (e.g. zone `1.2.3.4.sslip.io`\nadmits `myapp.1.2.3.4.sslip.io` but not `deep.sub.1.2.3.4.sslip.io`).\n`None` (default) means \"auto-derive from `external_url`\"; if no zone can\nbe derived the gate rejects all SNI, disabling the feature.","default":null,"example":"1.2.3.4.sslip.io"}}},"OpenAiError":{"type":"object","required":["message","type"],"properties":{"code":{"type":["string","null"]},"message":{"type":"string"},"type":{"type":"string"}}},"OpenAiErrorResponse":{"type":"object","required":["error"],"properties":{"error":{"$ref":"#/components/schemas/OpenAiError"}}},"OperatingSystemCount":{"type":"object","required":["operating_system","count","percentage"],"properties":{"count":{"type":"integer","format":"int64"},"operating_system":{"type":"string"},"percentage":{"type":"number","format":"double"}}},"OperationResultResponse":{"type":"object","required":["operation","success","message","executed_at"],"properties":{"data":{},"executed_at":{"type":"string","format":"date-time","example":"2025-10-12T12:15:47.609192Z"},"message":{"type":"string"},"operation":{"type":"string"},"success":{"type":"boolean"}}},"OperationResultsResponse":{"type":"object","required":["deployment_id","operations"],"properties":{"deployment_id":{"type":"string"},"operations":{"type":"array","items":{"$ref":"#/components/schemas/OperationResultResponse"}}}},"OtelDashboardResponse":{"type":"object","required":["id","project_id","name","layout","created_at","updated_at"],"properties":{"created_at":{"type":"string","example":"2025-10-12T12:15:47.609192Z"},"id":{"type":"integer","format":"int32"},"layout":{"$ref":"#/components/schemas/DashboardLayout"},"name":{"type":"string"},"project_id":{"type":"integer","format":"int32"},"updated_at":{"type":"string","example":"2025-10-12T12:15:47.609192Z"}}},"OtelDashboardsResponse":{"type":"object","required":["data","total"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/OtelDashboardResponse"}},"total":{"type":"integer","format":"int64","minimum":0}}},"OtelMetricAlertRuleResponse":{"type":"object","required":["id","project_id","name","metric_name","aggregation","detection_kind","detection_config","window_secs","for_duration_secs","severity","enabled","last_state","label_filters","group_by","dynamic_alerts","max_series","grouped_notification_threshold","last_dropped_series_count","series_states","created_at","updated_at"],"properties":{"aggregation":{"type":"string"},"created_at":{"type":"string","example":"2025-10-12T12:15:47.609192Z"},"detection_config":{"$ref":"#/components/schemas/DetectionConfig","description":"The typed detector definition (discriminated union keyed by `kind`)."},"detection_kind":{"type":"string","description":"Coarse detector discriminator: `static|anomaly|forecast|outlier|auto_watch`."},"dynamic_alerts":{"type":"boolean","description":"Whether per-series (\"dynamic\") alerting is enabled for this rule."},"enabled":{"type":"boolean"},"firing_series":{"type":"array","items":{"$ref":"#/components/schemas/FiringSeriesEntry"},"description":"Currently-firing series for a dynamic rule, snapshotted from the evaluator's\nin-memory firing map at read time. Empty for static/aggregate rules or when\nnothing is firing."},"for_duration_secs":{"type":"integer","format":"int32"},"group_by":{"type":"array","items":{"type":"string"},"description":"Label keys the rule breaks the metric down by. Empty = one aggregate stream."},"grouped_notification_threshold":{"type":"integer","format":"int32","description":"Notification-grouping threshold: when more than this many series fire in the\nsame tick, only the first gets chart/AI enrichment (1–1000)."},"id":{"type":"integer","format":"int32"},"label_filters":{"type":"array","items":{"type":"array","items":false,"prefixItems":[{"type":"string"},{"type":"string"}]},"description":"AND-combined label equality filters applied when evaluating this rule.\nEmpty = no filtering (matches all series)."},"last_dropped_series_count":{"type":"integer","format":"int32","description":"Number of series dropped by the cardinality cap on the latest dynamic tick\n(0 when nothing was dropped or for static/aggregate rules). Lets a UI warn\n\"N series were dropped this tick\" without reading server logs."},"last_evaluated_at":{"type":["string","null"],"example":"2025-10-12T12:15:47.609192Z"},"last_state":{"type":"string","description":"One of `ok|firing|unknown`."},"last_value":{"type":["number","null"],"format":"double"},"max_series":{"type":"integer","format":"int32","description":"Cardinality cap for dynamic alerting (1–100)."},"metric_name":{"type":"string"},"name":{"type":"string"},"project_id":{"type":"integer","format":"int32"},"series_states":{"type":"object","description":"Full per-series state snapshot persisted after the latest dynamic-rule tick,\nkeyed by the human-readable series label (`endpoint=/checkout`). Empty for\nstatic/aggregate rules. Unlike `firing_series` (a live in-memory snapshot),\nthis is decoded from the persisted `series_states` jsonb column, so an\nexternal consumer that only reads the rule row still sees per-series detail.","additionalProperties":{"$ref":"#/components/schemas/SeriesStateEntry"},"propertyNames":{"type":"string"}},"severity":{"type":"string"},"updated_at":{"type":"string","example":"2025-10-12T12:15:47.609192Z"},"window_secs":{"type":"integer","format":"int32"}}},"OtelMetricAlertsResponse":{"type":"object","required":["data","total"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/OtelMetricAlertRuleResponse"}},"total":{"type":"integer","format":"int64","minimum":0}}},"OtelMetricLabelKeysResponse":{"type":"object","required":["keys"],"properties":{"keys":{"type":"array","items":{"type":"string"}}}},"OtelMetricLabelValuesResponse":{"type":"object","required":["values"],"properties":{"values":{"type":"array","items":{"type":"string"}}}},"OtelMetricNamesResponse":{"type":"object","required":["names"],"properties":{"names":{"type":"array","items":{"type":"string"}}}},"OtelMetricsResponse":{"type":"object","required":["data","count"],"properties":{"count":{"type":"integer","minimum":0},"data":{"type":"array","items":{"$ref":"#/components/schemas/MetricBucket"}}}},"OutlierAlgorithm":{"type":"string","description":"Outlier detection algorithm.","enum":["dbscan","scaled_dbscan","mad","scaled_mad"]},"OutlierParams":{"type":"object","description":"Outlier (cross-series population) detector parameters (stub — not evaluated).","required":["peer_group_key"],"properties":{"algorithm":{"$ref":"#/components/schemas/OutlierAlgorithm"},"peer_group_key":{"type":"string","description":"Label key defining the peer population compared across series (e.g. `host`)."},"tolerance":{"type":"number","format":"double","description":"Sensitivity; higher tolerates larger spread before flagging."}}},"OverprovisioningAssessment":{"type":"object","description":"Requests-vs-capacity-vs-usage assessment","required":["verdict","explanation"],"properties":{"cpu_request_inflation_ratio":{"type":["number","null"],"format":"double","description":"Ratio of requested CPU to measured CPU usage (e.g. 40.0 = requests\nreserve 40× what the workloads actually use). `None` without metrics."},"cpu_requested_pct":{"type":["number","null"],"format":"double","description":"Requested CPU as % of cluster capacity"},"cpu_utilization_pct":{"type":["number","null"],"format":"double","description":"Measured CPU usage as % of cluster capacity (`None` without metrics)"},"explanation":{"type":"string","description":"Human-readable explanation of the verdict, e.g. \"Cluster capacity is\n8 vCPU but measured usage is 0.3 vCPU (3.7%) — severely overprovisioned\""},"memory_request_inflation_ratio":{"type":["number","null"],"format":"double","description":"Ratio of requested memory to measured memory usage"},"memory_requested_pct":{"type":["number","null"],"format":"double","description":"Requested memory as % of cluster capacity"},"memory_utilization_pct":{"type":["number","null"],"format":"double","description":"Measured memory usage as % of cluster capacity (`None` without metrics)"},"verdict":{"$ref":"#/components/schemas/OverprovisioningVerdict","description":"Overall verdict"}}},"OverprovisioningVerdict":{"type":"string","description":"Overall overprovisioning verdict","enum":["severe","moderate","reasonable","unknown"]},"PageActivityBucket":{"type":"object","description":"Time bucket data point for page activity graph","required":["timestamp","visitors","page_views","avg_time_seconds"],"properties":{"avg_time_seconds":{"type":"number","format":"double","description":"Average time on page in seconds"},"page_views":{"type":"integer","format":"int64","description":"Number of page views in this bucket"},"timestamp":{"type":"string","description":"Timestamp for this bucket (ISO 8601)"},"visitors":{"type":"integer","format":"int64","description":"Number of unique visitors in this bucket"}}},"PageCountryStats":{"type":"object","description":"Geographic distribution of visitors for a page","required":["country","visitors","page_views","percentage"],"properties":{"country":{"type":"string","description":"Country name"},"country_code":{"type":["string","null"],"description":"ISO country code (2-letter)"},"page_views":{"type":"integer","format":"int64","description":"Number of page views from this country"},"percentage":{"type":"number","format":"double","description":"Percentage of total visitors"},"visitors":{"type":"integer","format":"int64","description":"Number of unique visitors from this country"}}},"PageFlowEntry":{"type":"object","description":"A single page with its entry/exit/bounce statistics","required":["page_path","entry_count","exit_count","bounce_count","total_views","entry_rate","exit_rate","bounce_rate"],"properties":{"avg_time_on_page":{"type":["number","null"],"format":"double","description":"Average time spent on this page in seconds"},"bounce_count":{"type":"integer","format":"int64","description":"Number of times visitors bounced on this page"},"bounce_rate":{"type":"number","format":"double","description":"Bounce rate: bounce_count / entry_count (only meaningful for entry pages)"},"entry_count":{"type":"integer","format":"int64","description":"Number of times this page was the entry page of a session"},"entry_rate":{"type":"number","format":"double","description":"Entry rate: entry_count / total_views"},"exit_count":{"type":"integer","format":"int64","description":"Number of times this page was the exit page of a session"},"exit_rate":{"type":"number","format":"double","description":"Exit rate: exit_count / total_views"},"page_path":{"type":"string","description":"The page path (e.g. \"/pricing\", \"/docs/getting-started\")"},"total_views":{"type":"integer","format":"int64","description":"Total page views for this page"}}},"PageFlowQuery":{"type":"object","description":"Query parameters for page flow analytics","required":["project_id","start_date","end_date"],"properties":{"end_date":{"type":"string","format":"date-time"},"environment_id":{"type":["integer","null"],"format":"int32"},"limit":{"type":["integer","null"],"format":"int32","description":"Maximum number of entry/exit pages to return (default: 20)"},"min_views_for_dropoff":{"type":["integer","null"],"format":"int32","description":"Minimum views for drop-off analysis (default: 5)"},"project_id":{"type":"integer","format":"int32"},"start_date":{"type":"string","format":"date-time"},"transitions_limit":{"type":["integer","null"],"format":"int32","description":"Maximum number of transitions to return (default: 50)"}}},"PageFlowResponse":{"type":"object","description":"Complete page flow analytics response","required":["top_entry_pages","top_exit_pages","drop_off_points","transitions","total_pages","total_sessions"],"properties":{"drop_off_points":{"type":"array","items":{"$ref":"#/components/schemas/DropOffPoint"},"description":"Top drop-off points (highest exit rates with meaningful traffic)"},"top_entry_pages":{"type":"array","items":{"$ref":"#/components/schemas/PageFlowEntry"},"description":"Top entry pages (where visitors land), sorted by entry_count DESC"},"top_exit_pages":{"type":"array","items":{"$ref":"#/components/schemas/PageFlowEntry"},"description":"Top exit pages (where visitors leave), sorted by exit_count DESC"},"total_pages":{"type":"integer","format":"int64","description":"Total unique pages seen in the period"},"total_sessions":{"type":"integer","format":"int64","description":"Total sessions in the period"},"transitions":{"type":"array","items":{"$ref":"#/components/schemas/PageTransition"},"description":"Page-to-page transitions (most common navigation paths)"}}},"PageHourlySessionsQuery":{"type":"object","description":"Query parameters for page hourly sessions endpoint","required":["page_path","project_id","start_time","end_time"],"properties":{"bucket_interval":{"type":["string","null"]},"end_time":{"type":"string","format":"date-time"},"environment_id":{"type":["integer","null"],"format":"int32"},"page_path":{"type":"string"},"project_id":{"type":"integer","format":"int32"},"start_time":{"type":"string","format":"date-time"}}},"PageHourlySessionsResponse":{"type":"object","required":["page_path","hourly_data","total_sessions","hours"],"properties":{"hourly_data":{"type":"array","items":{"$ref":"#/components/schemas/HourlyPageSessions"}},"hours":{"type":"integer","format":"int32"},"page_path":{"type":"string"},"total_sessions":{"type":"integer","format":"int64"}}},"PagePathDetailQuery":{"type":"object","description":"Query parameters for page path detail analytics","required":["page_path","project_id","start_date","end_date"],"properties":{"bucket_interval":{"type":["string","null"],"description":"Bucket interval for time series: 'hour', 'day', 'week', 'month' (default: auto)"},"end_date":{"type":"string","format":"date-time"},"environment_id":{"type":["integer","null"],"format":"int32"},"page_path":{"type":"string","description":"The specific page path to get details for (URL-encoded)"},"project_id":{"type":"integer","format":"int32"},"start_date":{"type":"string","format":"date-time"}}},"PagePathDetailResponse":{"type":"object","description":"Detailed analytics response for a specific page path","required":["page_path","unique_visitors","total_page_views","avg_time_on_page","bounce_rate","entry_rate","exit_rate","activity_over_time","countries","referrers","bucket_interval"],"properties":{"activity_over_time":{"type":"array","items":{"$ref":"#/components/schemas/PageActivityBucket"},"description":"Time series data for activity graph"},"avg_time_on_page":{"type":"number","format":"double","description":"Average time on page in seconds"},"bounce_rate":{"type":"number","format":"double","description":"Bounce rate percentage (0-100)"},"bucket_interval":{"type":"string","description":"Bucket interval used for time series ('hour', 'day', etc.)"},"countries":{"type":"array","items":{"$ref":"#/components/schemas/PageCountryStats"},"description":"Geographic distribution of visitors"},"entry_rate":{"type":"number","format":"double","description":"Entry rate - percentage of sessions that started on this page"},"exit_rate":{"type":"number","format":"double","description":"Exit rate - percentage of sessions that ended on this page"},"page_path":{"type":"string","description":"The page path being analyzed"},"referrers":{"type":"array","items":{"$ref":"#/components/schemas/PageReferrerStats"},"description":"Top referrers to this page"},"total_page_views":{"type":"integer","format":"int64","description":"Total page views in the date range"},"unique_visitors":{"type":"integer","format":"int64","description":"Total unique visitors to this page in the date range"}}},"PagePathInfo":{"type":"object","required":["page_path","session_count","page_view_count","first_seen","last_seen"],"properties":{"avg_time_seconds":{"type":["number","null"],"format":"double"},"first_seen":{"type":"string"},"last_seen":{"type":"string"},"page_path":{"type":"string"},"page_view_count":{"type":"integer","format":"int64"},"session_count":{"type":"integer","format":"int64"}}},"PagePathSparkline":{"type":"object","required":["page_path","points"],"properties":{"page_path":{"type":"string"},"points":{"type":"array","items":{"$ref":"#/components/schemas/PagePathSparklinePoint"}}}},"PagePathSparklinePoint":{"type":"object","required":["timestamp","session_count"],"properties":{"session_count":{"type":"integer","format":"int64"},"timestamp":{"type":"string"}}},"PagePathVisitorsQuery":{"type":"object","description":"Query parameters for page path visitors","required":["page_path","project_id","start_date","end_date"],"properties":{"end_date":{"type":"string","format":"date-time"},"environment_id":{"type":["integer","null"],"format":"int32"},"page":{"type":["integer","null"],"format":"int64","description":"Page number (1-based, default: 1)","minimum":0},"page_path":{"type":"string","description":"The specific page path to get visitors for"},"per_page":{"type":["integer","null"],"format":"int64","description":"Items per page (default: 50, max: 100)","minimum":0},"project_id":{"type":"integer","format":"int32"},"start_date":{"type":"string","format":"date-time"}}},"PagePathVisitorsResponse":{"type":"object","description":"Response for page path visitors endpoint","required":["page_path","total_count","page","per_page","sessions"],"properties":{"page":{"type":"integer","format":"int64","description":"Current page number","minimum":0},"page_path":{"type":"string","description":"The page path"},"per_page":{"type":"integer","format":"int64","description":"Items per page","minimum":0},"sessions":{"type":"array","items":{"$ref":"#/components/schemas/PageVisitorSession"},"description":"Individual visitor sessions"},"total_count":{"type":"integer","format":"int64","description":"Total number of visitor sessions matching the query"}}},"PagePathsQuery":{"type":"object","required":["project_id"],"properties":{"end_date":{"type":["string","null"],"format":"date-time"},"environment_id":{"type":["integer","null"],"format":"int32"},"limit":{"type":["integer","null"],"format":"int32"},"project_id":{"type":"integer","format":"int32"},"start_date":{"type":["string","null"],"format":"date-time"}}},"PagePathsResponse":{"type":"object","required":["page_paths","total_count"],"properties":{"page_paths":{"type":"array","items":{"$ref":"#/components/schemas/PagePathInfo"}},"total_count":{"type":"integer","minimum":0}}},"PagePathsSparklineQuery":{"type":"object","description":"Query parameters for batch page paths sparkline endpoint","required":["project_id","start_time","end_time","page_paths"],"properties":{"end_time":{"type":"string","format":"date-time"},"environment_id":{"type":["integer","null"],"format":"int32"},"page_paths":{"type":"string","description":"Comma-separated list of page paths"},"project_id":{"type":"integer","format":"int32"},"start_time":{"type":"string","format":"date-time"}}},"PagePathsSparklineResponse":{"type":"object","required":["sparklines"],"properties":{"sparklines":{"type":"array","items":{"$ref":"#/components/schemas/PagePathSparkline"}}}},"PageReferrerStats":{"type":"object","description":"Referrer source for the page","required":["referrer","visits","percentage"],"properties":{"percentage":{"type":"number","format":"double","description":"Percentage of total visits"},"referrer":{"type":"string","description":"Referrer URL or domain"},"visits":{"type":"integer","format":"int64","description":"Number of visits from this referrer"}}},"PageSessionComparison":{"type":"object","required":["page_path","date","session_count","event_count","avg_duration_seconds"],"properties":{"avg_duration_seconds":{"type":"number","format":"double"},"date":{"type":"string"},"event_count":{"type":"integer","format":"int64"},"page_path":{"type":"string"},"session_count":{"type":"integer","format":"int64"}}},"PageSessionStats":{"type":"object","required":["page_path","total_sessions","avg_time_seconds","min_time_seconds","max_time_seconds","total_page_views","avg_page_views_per_session"],"properties":{"avg_page_views_per_session":{"type":"number","format":"double"},"avg_time_seconds":{"type":"number","format":"double"},"max_time_seconds":{"type":"number","format":"double"},"min_time_seconds":{"type":"number","format":"double"},"page_path":{"type":"string"},"total_page_views":{"type":"integer","format":"int64"},"total_sessions":{"type":"integer","format":"int64"}}},"PageSessionStatsQuery":{"type":"object","required":["page_path","project_id","start_date","end_date"],"properties":{"end_date":{"type":"string","format":"date-time"},"environment_id":{"type":["integer","null"],"format":"int32"},"page_path":{"type":"string"},"project_id":{"type":"integer","format":"int32"},"start_date":{"type":"string","format":"date-time"}}},"PageTransition":{"type":"object","description":"A page-to-page transition with count","required":["from_page","to_page","transition_count","percentage"],"properties":{"from_page":{"type":"string","description":"The source page path"},"percentage":{"type":"number","format":"double","description":"Percentage of transitions from the source page that go to this destination"},"to_page":{"type":"string","description":"The destination page path"},"transition_count":{"type":"integer","format":"int64","description":"Number of times this transition occurred"}}},"PageVisit":{"type":"object","required":["path","visits"],"properties":{"path":{"type":"string"},"visits":{"type":"integer","format":"int64"}}},"PageVisitorSession":{"type":"object","description":"Individual visitor session that viewed a specific page","required":["visitor_id","visitor_uuid","viewed_at","is_entry","is_exit","is_bounce"],"properties":{"browser":{"type":["string","null"],"description":"Browser name"},"city":{"type":["string","null"],"description":"Visitor's city"},"country":{"type":["string","null"],"description":"Visitor's country"},"country_code":{"type":["string","null"],"description":"Visitor's country code"},"device_type":{"type":["string","null"],"description":"Device type (Desktop, Mobile, Tablet)"},"is_bounce":{"type":"boolean","description":"Whether this was a bounce"},"is_entry":{"type":"boolean","description":"Whether this was the entry page for the session"},"is_exit":{"type":"boolean","description":"Whether this was the exit page for the session"},"operating_system":{"type":["string","null"],"description":"Operating system"},"referrer":{"type":["string","null"],"description":"Referrer URL"},"session_id":{"type":["string","null"],"description":"Session ID"},"session_page_number":{"type":["integer","null"],"format":"int32","description":"Page number in session flow"},"time_on_page":{"type":["integer","null"],"format":"int32","description":"Time spent on this page in seconds"},"viewed_at":{"type":"string","format":"date-time","description":"When the page was viewed"},"visitor_id":{"type":"integer","format":"int32","description":"Visitor numeric ID"},"visitor_uuid":{"type":"string","description":"Visitor UUID"}}},"PagesComparisonResponse":{"type":"object","required":["comparisons","page_paths"],"properties":{"comparisons":{"type":"array","items":{"$ref":"#/components/schemas/PageSessionComparison"}},"page_paths":{"type":"array","items":{"type":"string"}}}},"PaginatedEmailsResponse":{"type":"object","required":["data","total","page","page_size"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/EmailResponse"}},"page":{"type":"integer","format":"int64","minimum":0},"page_size":{"type":"integer","format":"int64","minimum":0},"total":{"type":"integer","format":"int64","minimum":0}}},"PaginatedEntitiesResponse":{"type":"object","required":["entities","count","limit","has_more"],"properties":{"count":{"type":"integer","description":"Number of entities returned","minimum":0},"entities":{"type":"array","items":{"$ref":"#/components/schemas/EntityResponse"},"description":"List of entities"},"has_more":{"type":"boolean","description":"Whether there are more entities available"},"limit":{"type":"integer","description":"Limit used for this request","minimum":0},"next_token":{"type":["string","null"],"description":"Continuation token for next page (S3, etc.)"},"total":{"type":["integer","null"],"description":"Total number of entities (if available)","minimum":0}}},"PaginatedErrorEventsResponse":{"type":"object","required":["data","pagination"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ErrorEventResponse"}},"pagination":{"$ref":"#/components/schemas/PaginationMeta"}}},"PaginatedErrorGroupsResponse":{"type":"object","required":["data","pagination"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ErrorGroupResponse"}},"pagination":{"$ref":"#/components/schemas/PaginationMeta"}}},"PaginatedEventsResponse":{"type":"object","required":["events","total","page","page_size"],"properties":{"events":{"type":"array","items":{"$ref":"#/components/schemas/TrackingEventResponse"}},"page":{"type":"integer","format":"int64","minimum":0},"page_size":{"type":"integer","format":"int64","minimum":0},"total":{"type":"integer","format":"int64","minimum":0}}},"PaginatedExternalImagesResponse":{"type":"object","required":["data","total","page","page_size"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ExternalImageResponse"}},"page":{"type":"integer","format":"int64","minimum":0},"page_size":{"type":"integer","format":"int64","minimum":0},"total":{"type":"integer","format":"int64","minimum":0}}},"PaginatedProjectList":{"type":"object","required":["projects","total","page","per_page"],"properties":{"page":{"type":"integer","format":"int64"},"per_page":{"type":"integer","format":"int64"},"projects":{"type":"array","items":{"$ref":"#/components/schemas/ProjectResponse"}},"total":{"type":"integer","format":"int64"}}},"PaginatedStaticBundlesResponse":{"type":"object","required":["data","total","page","page_size"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/StaticBundleResponse"}},"page":{"type":"integer","format":"int64","minimum":0},"page_size":{"type":"integer","format":"int64","minimum":0},"total":{"type":"integer","format":"int64","minimum":0}}},"Pagination":{"type":"object","description":"SDK pagination cursor. We use opaque page numbers internally but\nexpose `count`/`next`/`prev` the way `@vercel/sandbox` expects.","required":["count"],"properties":{"count":{"type":"integer","format":"int64","minimum":0},"next":{"type":["integer","null"],"format":"int64","minimum":0},"prev":{"type":["integer","null"],"format":"int64","minimum":0}}},"PaginationMeta":{"type":"object","required":["page","page_size","total_count","total_pages"],"properties":{"page":{"type":"integer","format":"int64","minimum":0},"page_size":{"type":"integer","format":"int64","minimum":0},"total_count":{"type":"integer","format":"int64","minimum":0},"total_pages":{"type":"integer","format":"int64","minimum":0}}},"PaginationParams":{"type":"object","properties":{"page":{"type":"integer","format":"int64"},"per_page":{"type":"integer","format":"int64"}}},"PasswordProtectionConfig":{"type":"object","description":"Password protection configuration\n\nWhen enabled, the proxy shows an HTML password form before allowing access.\nAfter the user enters the correct password, an HMAC-signed cookie is set\nso subsequent requests pass through without re-entering the password.","required":["enabled","passwordHash"],"properties":{"enabled":{"type":"boolean","description":"Whether password protection is enabled"},"passwordHash":{"type":"string","description":"The bcrypt-hashed password (never stored or returned in plaintext)"}}},"PatchSettingsRequest":{"type":"object","properties":{"auto_upgrade":{"type":["boolean","null"]},"host_port":{"type":["integer","null"],"format":"int32","minimum":0},"image":{"type":["string","null"]}}},"PathVisitors":{"type":"object","required":["name","visitors","percentage"],"properties":{"name":{"type":"string"},"percentage":{"type":"number","format":"double"},"visitors":{"type":"integer","format":"int64"}}},"PathVisitorsAnalyticsQuery":{"type":"object","required":["start_date","end_date","project_id"],"properties":{"deployment_id":{"type":["integer","null"],"format":"int32"},"end_date":{"type":"string","format":"date-time"},"environment_id":{"type":["integer","null"],"format":"int32"},"limit":{"type":["integer","null"],"format":"int32"},"project_id":{"type":"integer","format":"int32"},"start_date":{"type":"string","format":"date-time"}}},"PathVisitorsResponse":{"type":"object","required":["results"],"properties":{"results":{"type":"array","items":{"$ref":"#/components/schemas/PathVisitors"}}}},"PeerEntry":{"type":"object","description":"Wire-format peer entry. Matches `temps_network::config::Peer` but\nuses strings on the wire to keep the API stable across underlying\ntype evolution.","required":["node_id","compute_cidr","underlay_address"],"properties":{"compute_cidr":{"type":"string","description":"Per-node CIDR (e.g. `\"172.20.5.0/24\"`)."},"node_id":{"type":"string","description":"Stable v5 UUID derived from the database node id. Workers use\nthis as the kernel-layer identifier when calling\n`NetworkManager::reconcile_peers`."},"underlay_address":{"type":"string","description":"Address the local node should use to reach this peer over the\nunderlay (private VPC IP for same-DC, public IP for cross-DC)."}}},"PeerListResponse":{"type":"object","description":"Response body for `GET /internal/nodes/{node_id}/network/peers`.","required":["peers","cluster_dns_enabled"],"properties":{"alloc":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/AllocEntry","description":"Caller's own allocation, or `null` if multi-host networking has\nnot been enabled for this node yet."}]},"cluster_dns_enabled":{"type":"boolean","description":"Whether the cluster-DNS resolver is enabled on this control plane\n(`AppSettings.cluster_dns.enabled`). Workers should start their\nper-node resolver and write `overlay_bridge_address` only when this\nis `true`. Always serialized (never `skip_serializing_if`) so older\nand newer version skew degrades to the safe default of `false`."},"peers":{"type":"array","items":{"$ref":"#/components/schemas/PeerEntry"},"description":"All other nodes with a `compute_cidr` set, excluding the caller."}}},"PendingActionResponse":{"type":"object","description":"A proposed AI write action awaiting human confirmation.","required":["public_id","operation_id","method","summary","status","step_index","params","created_at"],"properties":{"confirmed_at":{"type":["string","null"]},"created_at":{"type":"string"},"error":{"type":["string","null"]},"executed_at":{"type":["string","null"]},"method":{"type":"string"},"operation_id":{"type":"string"},"params":{"description":"The flat params to be replayed at execute time (shown pre-execution for review)."},"plan_public_id":{"type":["string","null"],"description":"Set when this action is one step of a multi-step plan (chained actions);\nall steps of the plan share this id. Absent for standalone single actions."},"public_id":{"type":"string"},"required_permission":{"type":["string","null"]},"result":{},"status":{"type":"string"},"step_index":{"type":"integer","format":"int32","description":"0-based order of this step within its plan (0 for standalone actions)."},"summary":{"type":"string"}}},"PerformanceMetricsQuery":{"allOf":[{"$ref":"#/components/schemas/SpeedSegmentFilters","description":"Segment filters (filter_path, filter_country, filter_region,\nfilter_city, filter_browser, filter_operating_system) — flattened so\neach remains a top-level query string param."},{"type":"object","required":["start_date","end_date","project_id"],"properties":{"deployment_id":{"type":["integer","null"],"format":"int32"},"device_type":{"type":["string","null"],"description":"Device type filter: \"desktop\" or \"mobile\""},"end_date":{"type":"string","format":"date-time"},"environment_id":{"type":["integer","null"],"format":"int32"},"include_bots":{"type":["boolean","null"],"description":"Include crawler/datacenter (bot) samples. Defaults to false — bots\nare excluded from the read view but always stored at ingest."},"project_id":{"type":"integer","format":"int32"},"start_date":{"type":"string","format":"date-time"}}}]},"PerformanceMetricsResponse":{"type":"object","properties":{"cls":{"type":["number","null"],"format":"float"},"cls_p75":{"type":["number","null"],"format":"float"},"cls_p90":{"type":["number","null"],"format":"float"},"cls_p95":{"type":["number","null"],"format":"float"},"cls_p99":{"type":["number","null"],"format":"float"},"fcp":{"type":["number","null"],"format":"float"},"fcp_p75":{"type":["number","null"],"format":"float"},"fcp_p90":{"type":["number","null"],"format":"float"},"fcp_p95":{"type":["number","null"],"format":"float"},"fcp_p99":{"type":["number","null"],"format":"float"},"fid":{"type":["number","null"],"format":"float"},"fid_p75":{"type":["number","null"],"format":"float"},"fid_p90":{"type":["number","null"],"format":"float"},"fid_p95":{"type":["number","null"],"format":"float"},"fid_p99":{"type":["number","null"],"format":"float"},"inp":{"type":["number","null"],"format":"float"},"inp_p75":{"type":["number","null"],"format":"float"},"inp_p90":{"type":["number","null"],"format":"float"},"inp_p95":{"type":["number","null"],"format":"float"},"inp_p99":{"type":["number","null"],"format":"float"},"lcp":{"type":["number","null"],"format":"float"},"lcp_p75":{"type":["number","null"],"format":"float"},"lcp_p90":{"type":["number","null"],"format":"float"},"lcp_p95":{"type":["number","null"],"format":"float"},"lcp_p99":{"type":["number","null"],"format":"float"},"ttfb":{"type":["number","null"],"format":"float"},"ttfb_p75":{"type":["number","null"],"format":"float"},"ttfb_p90":{"type":["number","null"],"format":"float"},"ttfb_p95":{"type":["number","null"],"format":"float"},"ttfb_p99":{"type":["number","null"],"format":"float"}}},"PermissionInfo":{"type":"object","description":"Information about a single permission","required":["name","description","category"],"properties":{"category":{"type":"string","description":"Category of the permission (e.g., \"Projects\", \"Deployments\")"},"description":{"type":"string","description":"Human-readable description of the permission"},"name":{"type":"string","description":"The permission identifier (e.g., \"projects:read\")"}}},"PgUpgradeLogResponse":{"type":"object","required":["log_id","content"],"properties":{"content":{"type":"string"},"log_id":{"type":"string"}}},"PgUpgradeResponse":{"type":"object","required":["id","service_id","from_version","to_version","from_image","to_image","status","phase","log_id","attempt","created_at"],"properties":{"attempt":{"type":"integer","format":"int32"},"created_at":{"type":"string"},"error_message":{"type":["string","null"]},"finished_at":{"type":["string","null"]},"from_image":{"type":"string"},"from_version":{"type":"string"},"id":{"type":"integer","format":"int32"},"log_id":{"type":"string"},"phase":{"type":"string"},"pre_upgrade_backup_id":{"type":["integer","null"],"format":"int32"},"rollback_volume_name":{"type":["string","null"]},"service_id":{"type":"integer","format":"int32"},"started_at":{"type":["string","null"]},"status":{"type":"string"},"to_image":{"type":"string"},"to_version":{"type":"string"}}},"PipelineStats":{"type":"object","description":"Internal pipeline statistics for self-observability.","required":["metrics_received","metrics_stored","metrics_dropped","spans_received","spans_stored","spans_dropped","logs_received","logs_stored_db","logs_stored_s3","logs_dropped","ingest_errors"],"properties":{"ingest_errors":{"type":"integer","format":"int64","minimum":0},"logs_dropped":{"type":"integer","format":"int64","minimum":0},"logs_received":{"type":"integer","format":"int64","minimum":0},"logs_stored_db":{"type":"integer","format":"int64","minimum":0},"logs_stored_s3":{"type":"integer","format":"int64","minimum":0},"metrics_dropped":{"type":"integer","format":"int64","minimum":0},"metrics_received":{"type":"integer","format":"int64","minimum":0},"metrics_stored":{"type":"integer","format":"int64","minimum":0},"spans_dropped":{"type":"integer","format":"int64","minimum":0},"spans_received":{"type":"integer","format":"int64","minimum":0},"spans_stored":{"type":"integer","format":"int64","minimum":0}}},"PipelineStatsResponse":{"type":"object","required":["stats"],"properties":{"stats":{"$ref":"#/components/schemas/PipelineStats"}}},"PlanComplexity":{"type":"string","description":"Plan complexity indicator","enum":["low","medium","high"]},"PlanMetadata":{"type":"object","description":"Plan metadata","required":["generated_at","generator_version","complexity","warnings"],"properties":{"complexity":{"$ref":"#/components/schemas/PlanComplexity","description":"Estimated complexity (low, medium, high)"},"generated_at":{"type":"string","format":"date-time","description":"When the plan was generated"},"generator_version":{"type":"string","description":"Generator (importer) version"},"warnings":{"type":"array","items":{"type":"string"},"description":"Warnings detected during planning"}}},"PlanSourceBackup":{"type":"object","required":["location","location_was_resolved","format"],"properties":{"created_at":{"type":["string","null"]},"format":{"type":"string","description":"\"walg\", \"pg_dump\", \"unknown\"."},"id":{"type":["integer","null"],"format":"int32","description":"DB id, absent for orphan (S3-scan) backups."},"location":{"type":"string","description":"Resolved S3 location the orchestrator will actually use."},"location_was_resolved":{"type":"boolean","description":"True when the original row's `s3_location` was empty and we resolved\na location by probing S3. The UI shows this as a warning."},"origin_service_name":{"type":["string","null"],"description":"Service that originally produced the backup, if known."},"size_bytes":{"type":["integer","null"],"format":"int64"}}},"PlanTarget":{"type":"object","required":["id","name","container"],"properties":{"container":{"type":"string","description":"Expected Docker container name."},"id":{"type":"integer","format":"int32"},"name":{"type":"string"}}},"PlatformInfo":{"type":"object","description":"Platform compatibility information","required":["os_type","architecture","platforms"],"properties":{"architecture":{"type":"string","description":"System architecture (e.g., \"x86_64\", \"aarch64\")"},"os_type":{"type":"string","description":"Operating system type (e.g., \"linux\", \"windows\", \"darwin\")"},"platforms":{"type":"array","items":{"type":"string"},"description":"List of supported platforms in \"os/arch\" format (e.g., [\"linux/amd64\"])"}}},"PluginManifest":{"type":"object","description":"The complete plugin manifest — the handshake contract.","required":["name","version"],"properties":{"description":{"type":["string","null"],"description":"Short description of what the plugin does"},"display_name":{"type":["string","null"],"description":"Human-readable display name"},"events":{"type":"array","items":{"type":"string"},"description":"Platform event types the plugin subscribes to.\n\nWhen specified, Temps will POST matching events to the plugin's\n`/_events` endpoint. Uses dot-notation event names matching the\nwebhook event types (e.g., \"deployment.succeeded\", \"project.created\").\n\nAvailable events:\n- `deployment.created`, `deployment.succeeded`, `deployment.failed`,\n `deployment.cancelled`, `deployment.ready`\n- `project.created`, `project.deleted`\n- `domain.created`, `domain.provisioned`"},"health_path":{"type":"string","description":"Health check endpoint path (relative to plugin root)"},"name":{"type":"string","description":"Unique plugin identifier (kebab-case, e.g., \"backup-manager\")"},"nav":{"type":"array","items":{"$ref":"#/components/schemas/NavEntry"},"description":"Navigation entries for the UI sidebar"},"requires_db":{"type":"boolean","description":"Whether the plugin needs database access"},"ui":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/UiManifest","description":"UI bundle manifest (if the plugin has a UI)"}]},"version":{"type":"string","description":"SemVer version string"}}},"PortMapping":{"type":"object","description":"Port mapping","required":["container_port","protocol","is_primary"],"properties":{"container_port":{"type":"integer","format":"int32","description":"Container port","minimum":0},"host_port":{"type":["integer","null"],"format":"int32","description":"Host port (optional - can be assigned dynamically)","minimum":0},"is_primary":{"type":"boolean","description":"Whether this is the primary HTTP port"},"protocol":{"$ref":"#/components/schemas/Protocol","description":"Protocol (tcp, udp)"}}},"PostgresWalHealth":{"type":"object","required":["probed_at","pg_wal_bytes","max_wal_size_bytes","archive_mode","archive_backlog","stale_slots","oldest_wal_age_secs","warnings"],"properties":{"archive_backlog":{"type":"integer","format":"int64","description":"Number of `archive_status/*.ready` files — un-shipped WAL segments."},"archive_command":{"type":["string","null"],"description":"The literal `archive_command` setting. May be empty or `/bin/true`\nwhen archiving is effectively disabled despite `archive_mode = on`."},"archive_mode":{"$ref":"#/components/schemas/ArchiveMode"},"archiver_failed_count":{"type":["integer","null"],"format":"int64"},"archiver_last_failed_at":{"type":["string","null"],"format":"date-time"},"max_wal_size_bytes":{"type":"integer","format":"int64","description":"`max_wal_size` setting in bytes (parsed from `pg_settings`)."},"oldest_wal_age_secs":{"type":"integer","format":"int64","description":"Age of the oldest WAL file in `pg_wal/` (seconds)."},"pg_wal_bytes":{"type":"integer","format":"int64","description":"Total size of files under `pg_wal/`, from `pg_ls_waldir()`."},"probed_at":{"type":"string","format":"date-time","description":"When the snapshot was taken."},"stale_slots":{"type":"array","items":{"$ref":"#/components/schemas/StaleSlot"}},"warnings":{"type":"array","items":{"$ref":"#/components/schemas/WalWarning"},"description":"Computed warnings, ordered by severity (critical first)."}}},"PresetConfigSchema":{"oneOf":[{"$ref":"#/components/schemas/DockerfilePresetConfig","description":"Configuration for Dockerfile preset"},{"$ref":"#/components/schemas/DockerComposePresetConfig","description":"Configuration for Docker Compose"},{"$ref":"#/components/schemas/NixpacksPresetConfig","description":"Configuration for Nixpacks provider selection and inline build plan"},{"$ref":"#/components/schemas/StaticPresetConfig","description":"Configuration for static site presets (Vite, Next.js, etc.)"}],"description":"Union type for preset configurations\nUse the appropriate configuration type based on your preset"},"PresetInfo":{"type":"object","description":"Detected preset information","required":["path","preset","preset_label","project_type"],"properties":{"compose_files":{"type":["array","null"],"items":{"type":"string"},"description":"Compose file paths found in the repository (only for docker-compose preset)"},"exposed_port":{"type":["integer","null"],"format":"int32","description":"Default exposed port for this preset"},"icon_url":{"type":["string","null"],"description":"Icon URL for this preset"},"path":{"type":"string","description":"Path where preset was detected (empty for root)"},"preset":{"type":"string","description":"Preset slug (e.g., \"nextjs\", \"fastapi\")"},"preset_label":{"type":"string","description":"Human-readable preset label"},"project_type":{"type":"string","description":"Project type (e.g., \"frontend\", \"backend\", \"fullstack\")"}}},"PresetResponse":{"type":"object","required":["slug","label","icon_url","project_type","description"],"properties":{"default_port":{"type":["integer","null"],"format":"int32","description":"Default port the application listens on (None for static sites)","example":3000,"minimum":0},"description":{"type":"string","description":"Description of what this preset does"},"icon_url":{"type":"string","description":"Icon URL for the preset"},"label":{"type":"string","description":"Display name/label for the preset"},"project_type":{"type":"string","description":"Project type (server or static)"},"slug":{"type":"string","description":"Unique identifier slug for the preset"}}},"PreviewGatewaySettings":{"type":"object","description":"Workspace preview gateway settings.\n\nThe preview gateway is a single shared Docker container that lives on the\n`temps-sandbox-net` network and routes requests to workspace sandbox dev\nservers based on the `Host` header (`ws--.`).\n`temps serve` reconciles this container on startup; these settings let an\noperator override the image, host port, and auto-upgrade behavior.","properties":{"auto_upgrade":{"type":"boolean","description":"When true (default), the supervisor will pull and apply the image\npinned in the Temps binary on every startup. When false, the\ncurrently-running image is left alone — operators upgrade manually\nfrom the settings UI.","default":true,"example":true},"host_port":{"type":"integer","format":"int32","description":"Host port to publish the gateway on (always bound to 127.0.0.1).\nPingora forwards `ws-*` traffic to this port after authenticating.","default":8090,"example":8090,"minimum":0},"image":{"type":"string","description":"Docker image reference for the gateway. Pinned per Temps release.\nOperators can override this to test a custom build.","default":"ghcr.io/gotempsh/temps-preview-gateway:latest","example":"ghcr.io/gotempsh/temps-preview-gateway:latest"},"shared_secret":{"type":"string","description":"Shared secret the host-side Pingora sends on every forwarded preview\nrequest via `X-Temps-Preview-Token`; the gateway rejects requests\nwithout it. Auto-generated on first boot, persisted in DB so the\nsecret is stable across `temps serve` restarts regardless of cwd,\n`TEMPS_DATA_DIR`, or data-dir changes. MUST be masked (`***`) in any\nAPI response — never expose it over HTTP.","default":"","example":""}}},"PreviewGatewaySettingsMasked":{"type":"object","description":"Preview gateway settings with `shared_secret` elided.","required":["image","host_port","auto_upgrade","shared_secret_set"],"properties":{"auto_upgrade":{"type":"boolean"},"host_port":{"type":"integer","format":"int32","minimum":0},"image":{"type":"string"},"shared_secret_set":{"type":"boolean"}}},"PreviewGatewaySettingsResponse":{"type":"object","required":["image","host_port","auto_upgrade","default_image","default_host_port"],"properties":{"auto_upgrade":{"type":"boolean"},"default_host_port":{"type":"integer","format":"int32","description":"The compile-time default host port.","minimum":0},"default_image":{"type":"string","description":"The compile-time default image — exposed so the UI can offer a\n\"Reset to default\" link without round-tripping."},"host_port":{"type":"integer","format":"int32","minimum":0},"image":{"type":"string"}}},"PreviewShareLinkBody":{"type":"object","description":"Request body for minting a preview share link.","required":["port"],"properties":{"path":{"type":["string","null"],"description":"Path the recipient lands on. Must be same-origin (start with a single\n`/`); anything else is replaced with `/` so a share link can never be\nturned into an open redirect."},"port":{"type":"integer","format":"int32","description":"Port inside the sandbox the preview serves on.","minimum":0},"ttl_seconds":{"type":["integer","null"],"format":"int64","description":"How long the link stays usable, in seconds. Clamped to 24 hours.\nDefaults to one hour — long enough to send to a reviewer, short enough\nthat a link pasted in a ticket does not stay live indefinitely.","minimum":0}}},"PreviewShareLinkResponse":{"type":"object","required":["url","expires_at"],"properties":{"expires_at":{"type":"integer","format":"int64","description":"Unix seconds after which the link stops working.","minimum":0},"url":{"type":"string","description":"The full link. Its fragment contains the grant and must be treated as a\ncredential; URL fragments are not sent to servers or in Referer headers."}}},"PricingResponse":{"type":"object","required":["models"],"properties":{"models":{"type":"array","items":{"$ref":"#/components/schemas/ModelPricing"}}}},"ProblemDetails":{"type":"object","description":"Representation of a Problem error to return to the client.\nFollows RFC 7807 - Problem Details for HTTP APIs","required":["title","extensions"],"properties":{"detail":{"type":["string","null"],"description":"A human-readable explanation specific to this occurrence of the problem","example":"The server encountered an unexpected condition"},"extensions":{"type":"object","description":"Additional properties of the problem","additionalProperties":true},"instance":{"type":["string","null"],"description":"A URI reference that identifies the specific occurrence of the problem","example":"/account/12345/msgs/abc"},"title":{"type":"string","description":"A short, human-readable summary of the problem type","example":"Internal Server Error"},"type":{"type":["string","null"],"description":"A URI reference that identifies the problem type","example":"https://example.com/probs/out-of-memory"}},"example":{"type":"https://example.com/probs/out-of-memory","title":"Internal Server Error","detail":"The server encountered an unexpected condition","instance":"/account/12345/msgs/abc","additional_info":"Custom field with additional details"}},"ProjectAccessResponse":{"type":"object","required":["id","project_id","team_id","role","granted_by","created_at","updated_at"],"properties":{"created_at":{"type":"string","format":"date-time","example":"2026-07-30T12:15:47.609192Z"},"granted_by":{"type":"integer","format":"int32"},"id":{"type":"integer","format":"int32"},"project_id":{"type":"integer","format":"int32"},"role":{"$ref":"#/components/schemas/TeamRole"},"team_id":{"type":"integer","format":"int32"},"updated_at":{"type":"string","format":"date-time","example":"2026-07-30T12:15:47.609192Z"}}},"ProjectConfiguration":{"type":"object","description":"Project-level configuration","required":["name","slug","project_type","is_web_app"],"properties":{"is_web_app":{"type":"boolean","description":"Whether this is a web application"},"name":{"type":"string","description":"Proposed project name"},"project_type":{"$ref":"#/components/schemas/ProjectType","description":"Project type"},"slug":{"type":"string","description":"Proposed slug (URL-safe identifier)"}}},"ProjectDSNResponse":{"type":"object","required":["id","project_id","name","public_key","dsn","created_at","is_active","event_count"],"properties":{"created_at":{"type":"string"},"deployment_id":{"type":["integer","null"],"format":"int32"},"dsn":{"type":"string"},"environment_id":{"type":["integer","null"],"format":"int32"},"event_count":{"type":"integer","format":"int64"},"id":{"type":"integer","format":"int32"},"is_active":{"type":"boolean"},"name":{"type":"string"},"project_id":{"type":"integer","format":"int32"},"public_key":{"type":"string"}}},"ProjectDashboardAnalytics":{"type":"object","description":"Analytics data for a single project in the dashboard batch response","required":["project_id","unique_visitors","previous_unique_visitors","hourly_visits"],"properties":{"hourly_visits":{"type":"array","items":{"$ref":"#/components/schemas/EventTimeline"},"description":"Hourly sparkline data points"},"previous_unique_visitors":{"type":"integer","format":"int64","description":"Unique visitor count in the previous period (same duration, shifted back)"},"project_id":{"type":"integer","format":"int32"},"trend_percentage":{"type":["number","null"],"format":"double","description":"Percentage change from previous period (positive = growth, negative = decline)\nNull when previous period had zero visitors (no baseline to compare)"},"unique_visitors":{"type":"integer","format":"int64","description":"Unique visitor count in the current time range"}}},"ProjectHealthSummary":{"type":"object","description":"Health summary for a single project (last 1 hour)","required":["project_id","total_requests","total_errors","avg_response_time_ms","error_rate","status"],"properties":{"avg_response_time_ms":{"type":"number","format":"double","description":"Average response time in ms"},"error_rate":{"type":"number","format":"double","description":"Error rate as a percentage (0-100)"},"project_id":{"type":"integer","format":"int32"},"status":{"type":"string","description":"Health status: \"healthy\", \"degraded\", \"down\", \"unknown\""},"total_errors":{"type":"integer","format":"int64","description":"Total server errors (status >= 500) in the period"},"total_requests":{"type":"integer","format":"int64","description":"Total requests in the period"}}},"ProjectInfo":{"type":"object","required":["id","slug","created_at"],"properties":{"created_at":{"type":"string","example":"2025-10-12T12:15:47.609192Z"},"id":{"type":"integer","format":"int32"},"slug":{"type":"string"}}},"ProjectMonitorHealth":{"type":"object","description":"Health summary for a single project based on its production monitors","required":["project_id","status"],"properties":{"project_id":{"type":"integer","format":"int32"},"status":{"type":"string","description":"Overall status: \"operational\", \"degraded\", \"down\", or \"no_monitors\""}}},"ProjectPresetResponse":{"type":"object","required":["path","preset","presetLabel","projectType"],"properties":{"composeFiles":{"type":["array","null"],"items":{"type":"string"},"description":"Compose file paths found in the repository (only for docker-compose preset)"},"exposedPort":{"type":["integer","null"],"format":"int32","description":"Default exposed port for this preset (e.g., 3000 for Next.js, 8000 for FastAPI)"},"iconUrl":{"type":["string","null"],"description":"Icon URL for the preset"},"path":{"type":"string"},"preset":{"type":"string"},"presetLabel":{"type":"string"},"projectType":{"type":"string","description":"Project type category (e.g., \"frontend\", \"backend\", \"fullstack\")"}}},"ProjectQuery":{"type":"object","required":["project_id"],"properties":{"environment_id":{"type":["integer","null"],"format":"int32"},"project_id":{"type":"integer","format":"int32"}}},"ProjectRef":{"type":"object","description":"A lightweight project descriptor included in `UnifiedTrace`.","required":["project_id","project_name","project_slug"],"properties":{"project_id":{"type":"integer","format":"int32"},"project_name":{"type":"string"},"project_slug":{"type":"string","description":"URL slug used to link a span back into its owning project's trace view."}}},"ProjectResponse":{"type":"object","required":["id","slug","name","directory","main_branch","created_at","updated_at","deployment_config","attack_mode","ai_write_actions_enabled","error_source_context_enabled","enable_preview_environments","preview_envs_on_demand","preview_envs_idle_timeout_seconds","preview_envs_wake_timeout_seconds","source_type","cross_project_trace_sharing"],"properties":{"ai_alert_summaries_enabled":{"type":["boolean","null"],"description":"Opt-in to AI summarization of metric alert notifications (NULL/false = off)."},"ai_debug_chat_enabled":{"type":["boolean","null"],"description":"Opt-in to AI debugging chat, e.g. on deployment failures (NULL/false = off)."},"ai_write_actions_enabled":{"type":"boolean","description":"Opt-in to AI propose-then-confirm write capability (false = off)."},"attack_mode":{"type":"boolean","description":"Attack mode - when enabled, requires CAPTCHA verification for all project environments"},"created_at":{"type":"integer","format":"int64"},"cross_project_trace_sharing":{"type":"boolean","description":"ADR-027 Phase 3 opt-out: when false, this project's traces are suppressed\nfrom cross-project discovery results. Default true (consistent with the\nOSS global-observability model where any OtelRead holder can query any\nproject's telemetry)."},"deployment_config":{"$ref":"#/components/schemas/DeploymentConfig","description":"Deployment configuration (resources, autoscaling, features)"},"directory":{"type":"string"},"enable_preview_environments":{"type":"boolean","description":"Enable automatic preview environment creation for each branch"},"error_source_context_enabled":{"type":"boolean","description":"Opt-in to native error-tracking source context (false = off). When on,\nTemps stores uploaded source files and shows source code in stack traces."},"error_source_root":{"type":["string","null"],"description":"Where auto-capture reads source from (relative to the checkout). Null =\nthe deployment's Docker build context."},"git_provider_connection_id":{"type":["integer","null"],"format":"int32"},"git_url":{"type":["string","null"],"description":"Git clone URL for the repository (used for public repos without a provider connection)"},"gitlab_webhook_id":{"type":["integer","null"],"format":"int32","description":"GitLab webhook ID installed on the connected repository.\n`null` when no GitLab webhook is installed (not connected to GitLab,\nor webhook was removed / never created).","example":42},"id":{"type":"integer","format":"int32"},"last_deployment":{"type":["integer","null"],"format":"int64"},"main_branch":{"type":"string"},"name":{"type":"string"},"preset":{"type":["string","null"]},"preset_config":{"description":"Preset-specific configuration (Dockerfile path, build context, etc.)"},"preview_envs_idle_timeout_seconds":{"type":"integer","format":"int32","description":"Idle timeout (seconds) for on-demand preview environments."},"preview_envs_on_demand":{"type":"boolean","description":"When true, newly-created preview environments default to on-demand mode\n(containers stop after the configured idle timeout to save resources)."},"preview_envs_wake_timeout_seconds":{"type":"integer","format":"int32","description":"Wake timeout (seconds) for on-demand preview environments."},"repo_name":{"type":["string","null"]},"repo_owner":{"type":["string","null"]},"slug":{"type":"string"},"source_type":{"$ref":"#/components/schemas/SourceType","description":"Source type for deployments (git, docker_image, or static_files)"},"updated_at":{"type":"integer","format":"int64"}}},"ProjectSecretEnvironmentInfo":{"type":"object","required":["id","name","main_url"],"properties":{"id":{"type":"integer","format":"int32"},"main_url":{"type":"string"},"name":{"type":"string"}}},"ProjectSecretResponse":{"type":"object","description":"Project secret metadata. There is deliberately no `value` field — secret\nplaintext is never returned after creation. Callers that need the value\nmust read it from the mounted file inside the container.","required":["id","project_id","key","include_in_preview","created_at","updated_at","environments"],"properties":{"created_at":{"type":"integer","format":"int64"},"environments":{"type":"array","items":{"$ref":"#/components/schemas/ProjectSecretEnvironmentInfo"}},"id":{"type":"integer","format":"int32"},"include_in_preview":{"type":"boolean"},"key":{"type":"string"},"project_id":{"type":"integer","format":"int32"},"updated_at":{"type":"integer","format":"int64"}}},"ProjectServiceInfo":{"type":"object","required":["id","project","service"],"properties":{"id":{"type":"integer","format":"int32"},"project":{"$ref":"#/components/schemas/ProjectInfo"},"service":{"$ref":"#/components/schemas/ExternalServiceInfo"}}},"ProjectStatisticsResponse":{"type":"object","required":["total_count"],"properties":{"total_count":{"type":"integer","format":"int64"}}},"ProjectStatsBreakdown":{"type":"object","required":["project_id","unique_visitors","total_visits","total_page_views","bounce_rate","engagement_rate"],"properties":{"bounce_rate":{"type":"number","format":"double"},"engagement_rate":{"type":"number","format":"double"},"project_id":{"type":"integer","format":"int32"},"project_name":{"type":["string","null"]},"total_page_views":{"type":"integer","format":"int64"},"total_visits":{"type":"integer","format":"int64"},"unique_visitors":{"type":"integer","format":"int64"}}},"ProjectType":{"type":"string","description":"Project type enumeration","enum":["static","docker","buildpack","git"]},"ProjectUsageInfoResponse":{"type":"object","required":["id","name","slug","connection_id","connection_name"],"properties":{"connection_id":{"type":"integer","format":"int32"},"connection_name":{"type":"string"},"id":{"type":"integer","format":"int32"},"name":{"type":"string"},"slug":{"type":"string"}}},"ProjectsHealthResponse":{"type":"object","description":"Batch health summary response","required":["projects"],"properties":{"projects":{"type":"object","description":"Health summaries keyed by project ID","additionalProperties":{"$ref":"#/components/schemas/ProjectHealthSummary"},"propertyNames":{"type":"string"}}}},"ProjectsMonitorHealthResponse":{"type":"object","description":"Batch response for projects health","required":["projects"],"properties":{"projects":{"type":"object","additionalProperties":{"$ref":"#/components/schemas/ProjectMonitorHealth"},"propertyNames":{"type":"string"}}}},"PromoteDeploymentRequest":{"type":"object","required":["target_environment_id"],"properties":{"target_environment_id":{"type":"integer","format":"int32","description":"Target environment ID to promote the deployment to"}}},"PropertyBreakdownItem":{"type":"object","required":["value","count","percentage"],"properties":{"count":{"type":"integer","format":"int64"},"percentage":{"type":"number","format":"double"},"value":{"type":"string"}}},"PropertyBreakdownQuery":{"type":"object","description":"Query parameters for property breakdown (group by column)","required":["start_date","end_date","group_by"],"properties":{"aggregation_level":{"$ref":"#/components/schemas/AggregationLevel","description":"Aggregation level"},"deployment_id":{"type":["integer","null"],"format":"int32","description":"Optional deployment filter"},"end_date":{"type":"string","format":"date-time","description":"End date for the query range"},"environment_id":{"type":["integer","null"],"format":"int32","description":"Optional environment filter"},"event_name":{"type":["string","null"],"description":"Optional event name filter (e.g., \"page_view\", \"click\")"},"filter_browser":{"type":["string","null"],"description":"Filter by browser name (for browser version drill-downs)"},"filter_channel":{"type":["string","null"],"description":"Filter by channel name (for channel -> referrer drill-downs)"},"filter_country":{"type":["string","null"],"description":"Filter by country (for region/city drill-downs). Requires geolocation join."},"filter_os":{"type":["string","null"],"description":"Filter by operating system name (for OS version drill-downs)"},"filter_referrer":{"type":["string","null"],"description":"Filter by referrer hostname (for referrer -> pages drill-downs)"},"filter_region":{"type":["string","null"],"description":"Filter by region (for city drill-downs). Requires geolocation join."},"group_by":{"$ref":"#/components/schemas/PropertyColumn","description":"Property column to group by"},"limit":{"type":["integer","null"],"format":"int32","description":"Maximum number of results to return (default: 20, max: 100)"},"start_date":{"type":"string","format":"date-time","description":"Start date for the query range"}}},"PropertyBreakdownResponse":{"type":"object","required":["property","items","total"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/PropertyBreakdownItem"}},"property":{"type":"string"},"total":{"type":"integer","format":"int64"}}},"PropertyColumn":{"type":"string","enum":["channel","device_type","browser","browser_version","operating_system","operating_system_version","utm_source","utm_medium","utm_campaign","utm_term","utm_content","referrer_hostname","language","event_type","event_name","page_path","pathname","country","region","city"]},"PropertyTimelineItem":{"type":"object","required":["timestamp","value","count"],"properties":{"count":{"type":"integer","format":"int64"},"timestamp":{"type":"string"},"value":{"type":"string"}}},"PropertyTimelineQuery":{"type":"object","description":"Query parameters for property timeline (group by column over time)","required":["start_date","end_date","group_by"],"properties":{"aggregation_level":{"$ref":"#/components/schemas/AggregationLevel","description":"Aggregation level"},"bucket_size":{"type":["string","null"],"description":"Time bucket size: \"hour\", \"day\", \"week\", \"month\" (default: auto-detect)"},"deployment_id":{"type":["integer","null"],"format":"int32","description":"Optional deployment filter"},"end_date":{"type":"string","format":"date-time","description":"End date for the query range"},"environment_id":{"type":["integer","null"],"format":"int32","description":"Optional environment filter"},"event_name":{"type":["string","null"],"description":"Optional event name filter"},"group_by":{"$ref":"#/components/schemas/PropertyColumn","description":"Property column to group by"},"start_date":{"type":"string","format":"date-time","description":"Start date for the query range"}}},"PropertyTimelineResponse":{"type":"object","required":["property","bucket_size","items"],"properties":{"bucket_size":{"type":"string"},"items":{"type":"array","items":{"$ref":"#/components/schemas/PropertyTimelineItem"}},"property":{"type":"string"}}},"Protocol":{"type":"string","description":"Network protocol","enum":["tcp","udp"]},"ProviderCatalogDto":{"type":"object","description":"One catalog entry rendered for the settings UI.","required":["id","name","install_command","auth_command","auth_flavors","models","credential_saved","supports_max_turns"],"properties":{"auth_command":{"type":"string"},"auth_flavors":{"type":"array","items":{"$ref":"#/components/schemas/AuthFlavorDto"}},"credential_saved":{"type":"boolean","description":"True when a credential is currently saved for this provider in the\nsettings JSON. Lets the UI render \"Configured\" badges without the\nfrontend having to inspect the encrypted blob."},"current_auth_type":{"type":["string","null"],"description":"Currently saved auth flavor id (when `credential_saved` is true).\n`None` when no credential is saved yet."},"default_model":{"type":["string","null"],"description":"Currently saved default model id for this provider, if one was\npicked. `None` means \"use the CLI's own default\" — the UI renders\nthat as \"Use provider default\"."},"id":{"type":"string"},"install_command":{"type":"string"},"max_turns_analysis":{"type":["integer","null"],"format":"int32","description":"Default max turns for the autofixer analysis phase. `None` = built-in\ndefault (10). Only enforced for CLIs with a turn flag (Claude Code)."},"max_turns_feedback":{"type":["integer","null"],"format":"int32","description":"Default max turns for autofixer feedback rounds. `None` = built-in\ndefault (10)."},"max_turns_fix":{"type":["integer","null"],"format":"int32","description":"Default max turns for the autofixer fix phase. `None` = built-in\ndefault (20)."},"models":{"type":"array","items":{"type":"string"},"description":"Model ids this provider accepts, in display order. The first entry is\nthe recommended default. Empty when the provider doesn't expose model\nselection (e.g. OpenCode), which the UI uses to hide the dropdown."},"name":{"type":"string"},"supports_max_turns":{"type":"boolean","description":"True when this provider's CLI supports enforcing a turn cap. False\nfor Codex/OpenCode, which run to completion — the UI labels their\nmax-turns inputs accordingly."}}},"ProviderCatalogResponse":{"type":"object","required":["default_provider","providers"],"properties":{"default_provider":{"type":"string","description":"Active provider id from `agent_sandbox.default_provider`. The settings\nUI uses this to highlight which card is the active one."},"providers":{"type":"array","items":{"$ref":"#/components/schemas/ProviderCatalogDto"}}}},"ProviderConfig":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/StripeConfig"},{"type":"object","required":["provider"],"properties":{"provider":{"type":"string","enum":["stripe"]}}}]},{"allOf":[{"$ref":"#/components/schemas/LemonSqueezyConfig"},{"type":"object","required":["provider"],"properties":{"provider":{"type":"string","enum":["lemon_squeezy"]}}}]}],"description":"Provider-specific integration settings persisted in\n`revenue_integrations.config`.\n\nThe tag is the lowercase provider name, so adding a new provider\nmeans adding a new variant and the existing rows are untouched.\nOld rows (pre-config) and rows with `NULL` config are treated as\n\"accept all events, no filtering\" via [`ProviderConfig::default_for`]."},"ProviderConfigMasked":{"type":"object","required":["auth_type","credential_saved","extra"],"properties":{"auth_type":{"type":"string"},"credential_saved":{"type":"boolean","description":"True if a credential is stored for this provider. The encrypted blob\nis never returned over HTTP."},"default_model":{"type":["string","null"]},"extra":{}}},"ProviderDeletionCheckResponse":{"type":"object","required":["can_delete","projects_in_use","message"],"properties":{"can_delete":{"type":"boolean"},"message":{"type":"string"},"projects_in_use":{"type":"array","items":{"$ref":"#/components/schemas/ProjectUsageInfoResponse"}}}},"ProviderDescriptor":{"type":"object","required":["name","display_name","recommended_events"],"properties":{"display_name":{"type":"string"},"name":{"type":"string"},"recommended_events":{"type":"array","items":{"type":"string"}}}},"ProviderKeyResponse":{"type":"object","required":["id","provider","display_name","api_key_masked","is_active","created_at","updated_at"],"properties":{"api_key_masked":{"type":"string","description":"Masked API key (only last 4 chars visible)"},"base_url":{"type":["string","null"]},"created_at":{"type":"string"},"default_model":{"type":["string","null"],"description":"Model id this provider serves (NULL → per-provider default)."},"display_name":{"type":"string"},"id":{"type":"integer","format":"int32"},"is_active":{"type":"boolean"},"provider":{"type":"string"},"updated_at":{"type":"string"}}},"ProviderMetadata":{"type":"object","required":["service_type","display_name","description","icon_url","color"],"properties":{"color":{"type":"string","example":"#336791"},"description":{"type":"string","example":"Relational database management system"},"display_name":{"type":"string","example":"PostgreSQL"},"icon_url":{"type":"string","example":"https://cdn.simpleicons.org/postgresql"},"service_type":{"$ref":"#/components/schemas/ServiceTypeRoute"}}},"ProviderResponse":{"type":"object","required":["id","name","provider_type","auth_method","is_active","is_default","created_at","updated_at"],"properties":{"auth_method":{"type":"string"},"base_url":{"type":["string","null"]},"created_at":{"type":"string","format":"date-time"},"id":{"type":"integer","format":"int32"},"is_active":{"type":"boolean"},"is_default":{"type":"boolean"},"name":{"type":"string"},"provider_type":{"type":"string"},"updated_at":{"type":"string","format":"date-time"}}},"ProviderUsage":{"type":"object","required":["provider","request_count","input_tokens","output_tokens","avg_latency_ms","error_count"],"properties":{"avg_latency_ms":{"type":"number","format":"double"},"error_count":{"type":"integer","format":"int64"},"input_tokens":{"type":"integer","format":"int64"},"output_tokens":{"type":"integer","format":"int64"},"provider":{"type":"string"},"request_count":{"type":"integer","format":"int64"}}},"ProvisionResponse":{"oneOf":[{"allOf":[{"$ref":"#/components/schemas/DomainError"},{"type":"object","required":["type"],"properties":{"type":{"type":"string","enum":["error"]}}}]},{"allOf":[{"$ref":"#/components/schemas/DomainResponse"},{"type":"object","required":["type"],"properties":{"type":{"type":"string","enum":["complete"]}}}]},{"allOf":[{"$ref":"#/components/schemas/DomainChallengeResponse"},{"type":"object","required":["type"],"properties":{"type":{"type":"string","enum":["pending"]}}}]}]},"ProxyLogResponse":{"type":"object","description":"Response model for proxy logs","required":["id","timestamp","method","path","host","status_code","request_source","is_system_request","routing_status","request_id"],"properties":{"bot_name":{"type":["string","null"]},"browser":{"type":["string","null"]},"browser_version":{"type":["string","null"]},"cache_status":{"type":["string","null"]},"client_ip":{"type":["string","null"]},"container_id":{"type":["string","null"]},"deployment_id":{"type":["integer","null"],"format":"int32"},"device_type":{"type":["string","null"]},"environment_id":{"type":["integer","null"],"format":"int32"},"error_message":{"type":["string","null"]},"host":{"type":"string"},"id":{"type":"integer","format":"int32"},"ip_geolocation_id":{"type":["integer","null"],"format":"int32"},"is_bot":{"type":["boolean","null"]},"is_system_request":{"type":"boolean"},"method":{"type":"string"},"operating_system":{"type":["string","null"]},"path":{"type":"string"},"project_id":{"type":["integer","null"],"format":"int32"},"query_string":{"type":["string","null"]},"referrer":{"type":["string","null"]},"request_id":{"type":"string"},"request_size_bytes":{"type":["integer","null"],"format":"int64"},"request_source":{"type":"string"},"response_size_bytes":{"type":["integer","null"],"format":"int64"},"response_time_ms":{"type":["integer","null"],"format":"int32"},"routing_status":{"type":"string"},"session_id":{"type":["integer","null"],"format":"int32"},"status_code":{"type":"integer","format":"int32"},"timestamp":{"type":"string"},"upstream_host":{"type":["string","null"]},"user_agent":{"type":["string","null"]},"visitor_id":{"type":["integer","null"],"format":"int32"}}},"ProxyLogsPaginatedResponse":{"type":"object","description":"Paginated response for proxy logs","required":["logs","total","page","page_size","total_pages"],"properties":{"logs":{"type":"array","items":{"$ref":"#/components/schemas/ProxyLogResponse"}},"page":{"type":"integer","format":"int64","minimum":0},"page_size":{"type":"integer","format":"int64","minimum":0},"total":{"type":"integer","format":"int64","minimum":0},"total_pages":{"type":"integer","format":"int64","minimum":0}}},"PublicHostnameStrategy":{"type":"string","description":"Public hostname generation mode for Temps-managed preview routes.\n\nThe mode is stored per managed domain (`dns_managed_domains.generated_hostname_mode`)\nrather than globally, so a provider such as Cloudflare can offer the flat layout\nrequired by its Universal SSL wildcard cert without changing every domain's behaviour.","enum":["standard","flat"]},"PublicPresetResponse":{"type":"object","description":"Response for preset detection","required":["branch","presets"],"properties":{"branch":{"type":"string","description":"Branch name where presets were detected"},"presets":{"type":"array","items":{"$ref":"#/components/schemas/PresetInfo"},"description":"List of detected presets"}}},"PublicRepositoryInfo":{"type":"object","description":"Public repository information","required":["owner","name","full_name","default_branch","stars","forks"],"properties":{"default_branch":{"type":"string","description":"Default branch name"},"description":{"type":["string","null"],"description":"Repository description"},"forks":{"type":"integer","format":"int32","description":"Fork count"},"full_name":{"type":"string","description":"Full repository name (owner/repo)"},"language":{"type":["string","null"],"description":"Primary programming language"},"name":{"type":"string","description":"Repository name"},"owner":{"type":"string","description":"Repository owner"},"stars":{"type":"integer","format":"int32","description":"Star count"}}},"PurgeLogsRequest":{"type":"object","required":["before"],"properties":{"before":{"type":"string","description":"Delete all logs before this timestamp (ISO 8601)"}}},"PushImageRequest":{"type":"object","description":"Request to push an external image","required":["image_ref"],"properties":{"image_ref":{"type":"string"},"metadata":{}}},"PushedExternalImageResponse":{"type":"object","description":"Response for in-memory external image operations (legacy push flow).\n\nRenamed to avoid shadowing the richer database-backed `ExternalImageResponse`\nin `handlers/remote_deployments.rs`. The two types serve different routes\n(`/images` ephemeral push vs `/external-images` registered images).","required":["id","image_ref","pushed_at"],"properties":{"digest":{"type":["string","null"]},"id":{"type":"string"},"image_ref":{"type":"string"},"pushed_at":{"type":"string","format":"date-time","example":"2025-10-12T12:15:47.609192Z"},"size":{"type":["integer","null"],"format":"int64","minimum":0}}},"QueryDataRequest":{"type":"object","properties":{"filters":{"description":"JSON filters (backend-specific format)"},"limit":{"type":"integer","description":"Maximum number of rows to return","example":100,"minimum":0},"offset":{"type":"integer","description":"Number of rows to skip","example":0,"minimum":0},"sort_by":{"type":["string","null"],"description":"Sort by field name"},"sort_order":{"type":["string","null"],"description":"Sort order (asc/desc)"}}},"QueryDataResponse":{"type":"object","required":["fields","rows","total_count","returned_count","execution_time_ms"],"properties":{"execution_time_ms":{"type":"integer","format":"int64","description":"Query execution time in milliseconds","example":45,"minimum":0},"fields":{"type":"array","items":{"$ref":"#/components/schemas/FieldResponse"},"description":"Field definitions"},"returned_count":{"type":"integer","description":"Number of rows returned in this response","example":100,"minimum":0},"rows":{"type":"array","items":{},"description":"Data rows (array of JSON objects)"},"total_count":{"type":"integer","format":"int64","description":"Total number of rows matching the query (before limit/offset)","example":1234,"minimum":0}}},"QuotaResponse":{"type":"object","required":["quota"],"properties":{"quota":{"$ref":"#/components/schemas/StorageQuota"}}},"RateLimitConfig":{"type":"object","description":"Rate limiting configuration (subset of global RateLimitSettings)","properties":{"blacklistIps":{"type":"array","items":{"type":"string"},"description":"Blacklist specific IPs for this project/environment"},"maxRequestsPerHour":{"type":["integer","null"],"format":"int32","description":"Override rate limit per hour","minimum":0},"maxRequestsPerMinute":{"type":["integer","null"],"format":"int32","description":"Override rate limit per minute","minimum":0},"whitelistIps":{"type":"array","items":{"type":"string"},"description":"Whitelist specific IPs for this project/environment"}}},"RateLimitSettings":{"type":"object","properties":{"blacklist_ips":{"type":"array","items":{"type":"string"},"default":[]},"enabled":{"type":"boolean","default":false},"max_requests_per_hour":{"type":"integer","format":"int32","default":1000,"minimum":0},"max_requests_per_minute":{"type":"integer","format":"int32","default":60,"minimum":0},"whitelist_ips":{"type":"array","items":{"type":"string"},"default":[]}}},"ReachabilityStatus":{"type":"string","description":"Email reachability status","enum":["safe","risky","invalid","unknown"]},"ReadFileResponse":{"type":"object","required":["path","contents_b64","size"],"properties":{"contents_b64":{"type":"string","description":"File contents, base64-encoded. Symmetric with `WriteFileBody`."},"path":{"type":"string"},"size":{"type":"integer","format":"int64","minimum":0}}},"RecentActivityQuery":{"type":"object","description":"Query parameters for recent activity endpoint","required":["project_id"],"properties":{"environment_id":{"type":["integer","null"],"format":"int32","description":"Environment ID (optional)"},"limit":{"type":["integer","null"],"format":"int32","description":"Max number of events to return (default: 50, max: 100)"},"project_id":{"type":"integer","format":"int32","description":"Project ID"},"since_id":{"type":["integer","null"],"format":"int64","description":"Return events with ID greater than this (for cursor-based polling)"}}},"RecentActivityResponse":{"type":"object","description":"Response for recent activity events endpoint","required":["events","count"],"properties":{"count":{"type":"integer","description":"Total events returned","minimum":0},"events":{"type":"array","items":{"$ref":"#/components/schemas/ActivityEvent"},"description":"Recent events, newest first"}}},"RecentEventResponse":{"type":"object","required":["occurred_at","event_type"],"properties":{"amount_minor":{"type":["integer","null"],"format":"int64"},"currency":{"type":["string","null"]},"customer_ref":{"type":["string","null"]},"event_type":{"type":"string"},"mrr_minor":{"type":["integer","null"],"format":"int64"},"occurred_at":{"type":"string","format":"date-time"}}},"RecentQueryParams":{"type":"object","properties":{"conversation_id":{"type":["string","null"],"description":"Filter by conversation ID"},"cost_gt":{"type":["integer","null"],"format":"int64","description":"Cost strictly greater-than, in microcents"},"cost_gte":{"type":["integer","null"],"format":"int64","description":"Cost greater-than-or-equal, in microcents"},"cost_lt":{"type":["integer","null"],"format":"int64","description":"Cost strictly less-than, in microcents"},"cost_lte":{"type":["integer","null"],"format":"int64","description":"Cost less-than-or-equal, in microcents"},"limit":{"type":["integer","null"],"format":"int64","description":"Page size (defaults to 20, max 50)","minimum":0},"model":{"type":["string","null"],"description":"Filter by model name"},"offset":{"type":["integer","null"],"format":"int64","description":"Number of results to skip for pagination (defaults to 0)","minimum":0},"provider":{"type":["string","null"],"description":"Filter by provider name"},"status":{"type":["integer","null"],"format":"int32","description":"Filter by HTTP status code (exact match)"},"tags":{"type":["string","null"],"description":"Filter by tags (comma-separated, AND logic)"},"tokens_gt":{"type":["integer","null"],"format":"int64","description":"Total tokens (input + output) strictly greater-than"},"tokens_gte":{"type":["integer","null"],"format":"int64","description":"Total tokens (input + output) greater-than-or-equal"},"tokens_lt":{"type":["integer","null"],"format":"int64","description":"Total tokens (input + output) strictly less-than"},"tokens_lte":{"type":["integer","null"],"format":"int64","description":"Total tokens (input + output) less-than-or-equal"},"user_id":{"type":["integer","null"],"format":"int32","description":"Filter by user ID"}}},"RecordExposureRequest":{"type":"object","description":"Keys a running app actually evaluated since its last report.","required":["keys"],"properties":{"keys":{"type":"array","items":{"type":"string"},"description":"Flag keys evaluated since the last report. Unknown keys are ignored.","example":["checkout.v2","api.rate_limit"]}}},"RecordExposureResponse":{"type":"object","required":["recorded"],"properties":{"recorded":{"type":"integer","format":"int64","description":"How many keys were accepted for processing.\n\nDeliberately not the number of rows updated: echoing that back would\nlet a caller post a single candidate key and read the result as \"this\nflag exists\", turning the endpoint into an existence oracle.","minimum":0}}},"RecordListResponse":{"type":"object","description":"Record list response","required":["records"],"properties":{"records":{"type":"array","items":{"$ref":"#/components/schemas/DnsRecord"}}}},"RecoveryTarget":{"oneOf":[{"type":"object","description":"Recover to a specific timestamp.","required":["time","kind"],"properties":{"kind":{"type":"string","enum":["time"]},"time":{"type":"string","format":"date-time"}}},{"type":"object","description":"Recover to a specific transaction id (Postgres).","required":["xid","kind"],"properties":{"kind":{"type":"string","enum":["xid"]},"xid":{"type":"string"}}},{"type":"object","description":"Recover to a specific log sequence number (Postgres).","required":["lsn","kind"],"properties":{"kind":{"type":"string","enum":["lsn"]},"lsn":{"type":"string"}}},{"type":"object","description":"Recover to a named restore point created via `pg_create_restore_point` (Postgres).","required":["name","kind"],"properties":{"kind":{"type":"string","enum":["name"]},"name":{"type":"string"}}}],"description":"Engine-specific recovery target for PITR.\n\nPostgres honors all variants; Redis/Mongo/S3 will likely reject non-Time\nvariants or define their own semantics when they grow PITR support."},"ReferrerCount":{"type":"object","required":["referrer","count","percentage"],"properties":{"count":{"type":"integer","format":"int64"},"percentage":{"type":"number","format":"double"},"referrer":{"type":"string"}}},"ReferrersAnalyticsQuery":{"type":"object","required":["start_date","end_date","project_id"],"properties":{"end_date":{"type":"string","format":"date-time"},"environment_id":{"type":["integer","null"],"format":"int32"},"project_id":{"type":"integer","format":"int32"},"start_date":{"type":"string","format":"date-time"}}},"RegenerateDSNRequest":{"type":"object","properties":{"base_url":{"type":["string","null"]}}},"RegisterImageRequest":{"type":"object","required":["image_ref"],"properties":{"digest":{"type":["string","null"],"description":"Image digest (sha256:...)","example":"sha256:abc123def456"},"image_ref":{"type":"string","description":"Docker image reference (e.g., \"ghcr.io/org/app:v1.0\")","example":"ghcr.io/myorg/myapp:v1.0"},"metadata":{"description":"Additional metadata"},"tag":{"type":["string","null"],"description":"Image tag","example":"v1.0"}}},"RegisterNodeApiRequest":{"type":"object","required":["name","token","address","private_address"],"properties":{"address":{"type":"string","description":"Node's reachable address (e.g., \"10.100.0.2\" or \"192.168.1.50\")"},"architecture":{"type":["string","null"],"description":"Container platform of this node's Docker daemon (`linux/amd64`,\n`linux/arm64`). Optional: agents older than multi-arch support omit it\nand the value is learned from the first heartbeat instead."},"csr_pem":{"type":["string","null"],"description":"Node-generated certificate signing request (PEM) for multi-node mTLS\n(ADR-020 WS-2.1). When present, the control plane signs it with the\ncluster CA and returns the leaf + CA cert. Optional — token-only nodes\n(legacy / edge) still register without one."},"edge_public_key":{"type":["string","null"],"description":"X25519 public key for ECIES certificate encryption (base64-encoded, edge nodes only)"},"join_token":{"type":["string","null"],"description":"Join token to authorize this registration (must match the token generated in Settings)"},"labels":{"description":"Labels for scheduling (e.g., {\"region\": \"us-east\", \"gpu\": \"true\"})"},"name":{"type":"string","description":"Unique name for this node"},"prior_token":{"type":["string","null"],"description":"The node's *current* token, supplied to prove possession when\nre-registering (changing the identity of) a node that already exists.\nOptional; only needed to rebind a still-live node. (ADR-020 WS-1.2.)"},"private_address":{"type":"string","description":"Private/WireGuard address for inter-node communication"},"public_endpoint":{"type":["string","null"],"description":"Public endpoint for WireGuard (e.g., \"203.0.113.1:51820\")"},"role":{"type":["string","null"],"description":"Node role (default: \"worker\")"},"token":{"type":"string","description":"Registration token (plaintext, will be hashed before storage)"},"wg_public_key":{"type":["string","null"],"description":"WireGuard public key"}}},"RegisterNodeResponse":{"type":"object","required":["id","name","status","message"],"properties":{"ca_cert_pem":{"type":["string","null"],"description":"The cluster CA certificate (PEM) the node pins as its trust root.\nPresent only when a `csr_pem` was supplied. (ADR-020 WS-2.1.)"},"cert_pem":{"type":["string","null"],"description":"The signed per-node leaf certificate (PEM) the agent serves as its TLS\nserver cert. Present only when a `csr_pem` was supplied. (ADR-020 WS-2.1.)"},"id":{"type":"integer","format":"int32"},"message":{"type":"string"},"name":{"type":"string"},"status":{"type":"string"}}},"RegisterRequest":{"type":"object","required":["email","password","name"],"properties":{"email":{"type":"string"},"name":{"type":"string"},"password":{"type":"string"}}},"ReinstallWebhookResponse":{"type":"object","description":"Response for `POST /projects/{project_id}/gitlab/reinstall-webhook`","required":["hook_id","message"],"properties":{"hook_id":{"type":"integer","format":"int32","description":"The new GitLab hook ID that was installed."},"message":{"type":"string","description":"Human-readable status message."}}},"ReleaseListResponse":{"type":"object","required":["releases"],"properties":{"releases":{"type":"array","items":{"type":"string"}}}},"ReloadResponse":{"type":"object","description":"Response from the reload endpoint.","required":["loaded","plugins","message"],"properties":{"loaded":{"type":"integer","description":"Number of plugins successfully loaded after reload","minimum":0},"message":{"type":"string","description":"Human-readable status message"},"plugins":{"type":"array","items":{"type":"string"},"description":"Names of loaded plugins"}}},"RemoteDeploymentResponse":{"type":"object","required":["id","project_id","environment_id","slug","state","source_type","created_at"],"properties":{"created_at":{"type":"string","format":"date-time","example":"2025-10-12T12:15:47.609192Z"},"environment_id":{"type":"integer","format":"int32"},"id":{"type":"integer","format":"int32"},"project_id":{"type":"integer","format":"int32"},"slug":{"type":"string"},"source_type":{"type":"string"},"state":{"type":"string"}}},"RemoveNodeResponse":{"type":"object","required":["id","message"],"properties":{"id":{"type":"integer","format":"int32"},"message":{"type":"string"}}},"RenameConversationRequest":{"type":"object","required":["title"],"properties":{"title":{"type":"string","description":"New human-facing title. Trimmed; must be non-empty after trimming."}}},"RepositoryListQuery":{"type":"object","properties":{"direction":{"type":["string","null"]},"language":{"type":["string","null"]},"owner":{"type":["string","null"]},"page":{"type":["integer","null"],"format":"int64","minimum":0},"per_page":{"type":["integer","null"],"format":"int64","minimum":0},"private":{"type":["boolean","null"]},"search":{"type":["string","null"]},"sort":{"type":["string","null"]}}},"RepositoryListResponse":{"type":"object","required":["repositories","total_count"],"properties":{"repositories":{"type":"array","items":{"$ref":"#/components/schemas/RepositoryResponse"}},"total_count":{"type":"integer","minimum":0}}},"RepositoryPresetResponse":{"type":"object","required":["repository_id","owner","name","presets","calculated_at"],"properties":{"calculated_at":{"type":"string","format":"date-time"},"name":{"type":"string"},"owner":{"type":"string"},"presets":{"type":"array","items":{"$ref":"#/components/schemas/ProjectPresetResponse"}},"repository_id":{"type":"integer","format":"int32"}}},"RepositoryResponse":{"type":"object","required":["id","owner","name","full_name","private","default_branch","created_at","updated_at","pushed_at","git_provider_connection_id"],"properties":{"clone_url":{"type":["string","null"],"description":"HTTPS clone URL (e.g., https://github.com/owner/repo.git)"},"created_at":{"type":"string","format":"date-time"},"default_branch":{"type":"string"},"description":{"type":["string","null"]},"full_name":{"type":"string"},"git_provider_connection_id":{"type":"integer","format":"int32","description":"ID of the git provider connection this repository was synced from."},"id":{"type":"integer","format":"int32"},"language":{"type":["string","null"]},"name":{"type":"string"},"owner":{"type":"string"},"preset":{"type":["array","null"],"items":{"$ref":"#/components/schemas/ProjectPresetResponse"}},"private":{"type":"boolean"},"pushed_at":{"type":"string","format":"date-time"},"ssh_url":{"type":["string","null"],"description":"SSH clone URL (e.g., git@github.com:owner/repo.git)"},"updated_at":{"type":"string","format":"date-time"}}},"RepositorySyncStartedResponse":{"type":"object","description":"Returned by `POST /git-connections/{id}/sync` to acknowledge that a\nsync has been kicked off in the background. Clients should poll the\nconnection's `syncing` and `synced_repository_count` fields to track\nprogress rather than waiting on this response.","required":["connection_id","syncing","started_at"],"properties":{"connection_id":{"type":"integer","format":"int32"},"started_at":{"type":"string","format":"date-time"},"syncing":{"type":"boolean"}}},"RequestRow":{"type":"object","required":["id","ts","method","host","path","status","request_headers","response_headers","headers_truncated"],"properties":{"client_ip":{"type":["string","null"]},"country":{"type":["string","null"]},"deployment_id":{"type":["integer","null"],"format":"int32"},"environment_id":{"type":["integer","null"],"format":"int32"},"error_group_id":{"type":["integer","null"],"format":"int32"},"headers_truncated":{"type":"boolean"},"host":{"type":"string"},"id":{"type":"string","description":"The request's unique `request_id` (assigned by the proxy). Used as the\nrow identity instead of the storage PK because the ClickHouse backend\nhas no serial id (rows come back with `id = 0`) while `request_id` is\nunique and present on both backends."},"latency_ms":{"type":["integer","null"],"format":"int32"},"method":{"type":"string"},"path":{"type":"string"},"query_string":{"type":["string","null"]},"referrer":{"type":["string","null"]},"request_headers":{},"response_headers":{},"status":{"type":"integer","format":"int32"},"trace_id":{"type":["string","null"]},"ts":{"type":"string","format":"date-time"},"user_agent":{"type":["string","null"]}}},"ResetPasswordRequest":{"type":"object","required":["token","new_password"],"properties":{"new_password":{"type":"string"},"token":{"type":"string"}}},"ResetPgStatStatementsRequest":{"type":"object","description":"Explicit confirmation required for the destructive statistics reset.\n\nRequiring JSON makes the endpoint non-simple for browsers, preventing a\ndeployed same-site application from triggering it with a plain HTML form.","required":["confirm"],"properties":{"confirm":{"type":"boolean","description":"Must be `true` to acknowledge the global, irreversible reset."}}},"ResetPgStatStatementsResponse":{"type":"object","description":"Response for the pg_stat_statements reset endpoint.","required":["message"],"properties":{"message":{"type":"string","description":"Human-readable message confirming the destructive action."}}},"ResizeSandboxBody":{"type":"object","required":["disk_size_mb"],"properties":{"disk_size_mb":{"type":"integer","format":"int64","description":"New root disk size in MB. Grow-only; must exceed the current size.","minimum":0}},"additionalProperties":false},"ResolvedEnvVarResponse":{"type":"object","description":"One entry in the computed env-var view that merges manual and integration\nsources and tags each result with its origin. `value_preview` is always\nmasked — plaintext must be fetched per-key via the existing reveal endpoint,\nwhich is audit-logged.","required":["key","value_preview","source","environments","include_in_preview"],"properties":{"environments":{"type":"array","items":{"$ref":"#/components/schemas/EnvironmentInfo"},"description":"Environments this var applies to. For integration-sourced vars this\nreflects every environment of the project (integrations are global)."},"include_in_preview":{"type":"boolean","description":"Whether the var would be auto-applied to preview environments.\nIntegration vars always surface in preview; manual vars follow the flag."},"key":{"type":"string"},"source":{"$ref":"#/components/schemas/ResolvedEnvVarSource"},"value_preview":{"type":"string","description":"Masked or truncated preview. Never the raw value."}}},"ResolvedEnvVarSource":{"oneOf":[{"type":"object","description":"Manually-defined env var. If `overrides_service` is set, this key would\notherwise have been supplied by an integration — the UI should show the\nintegration icon plus an \"overridden\" indicator.","required":["var_id","type"],"properties":{"overrides_service":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/EnvVarIntegrationInfo"}]},"type":{"type":"string","enum":["manual"]},"var_id":{"type":"integer","format":"int32"}}},{"type":"object","description":"Supplied by a linked external service (Postgres, Redis, S3, etc.).","required":["service","type"],"properties":{"service":{"$ref":"#/components/schemas/EnvVarIntegrationInfo"},"type":{"type":"string","enum":["integration"]}}}],"description":"Where a resolved env var comes from. Integration-sourced vars may be\n\"shadowed\" by a manual entry with the same key, in which case the response\ncarries `Manual` with `overrides_service` populated so the UI can still show\nthe integration icon."},"ResourceCounts":{"type":"object","description":"Quick count of resources involved in the migration","required":["projects","environments","deployments","environment_variables","services","domains"],"properties":{"deployments":{"type":"integer","minimum":0},"domains":{"type":"integer","minimum":0},"environment_variables":{"type":"integer","minimum":0},"environments":{"type":"integer","minimum":0},"projects":{"type":"integer","minimum":0},"services":{"type":"integer","minimum":0}}},"ResourceFootprint":{"type":"object","description":"A CPU + memory footprint (requests or measured usage)","required":["cpu_millis","memory_mb"],"properties":{"cpu_millis":{"type":"integer","format":"int64","description":"CPU in millicores"},"memory_mb":{"type":"integer","format":"int64","description":"Memory in MB"}}},"ResourceInfo":{"type":"object","description":"Resource attributes extracted from OTel resource descriptors.","required":["service_name","attributes"],"properties":{"attributes":{"type":"object"},"deployment_environment":{"type":["string","null"]},"service_name":{"type":"string"},"service_version":{"type":["string","null"]}}},"ResourceLimitApplyResult":{"type":"object","description":"Per-container outcome of a live `docker update` call. Surfaced from the\nPATCH /resources endpoint so the UI can tell the operator whether the\nnew caps are already in effect or whether they only apply on next\nrecreate (e.g., container was missing).","required":["role","container_name","outcome"],"properties":{"container_name":{"type":"string"},"error":{"type":["string","null"],"description":"Populated only when `outcome == \"failed\"`."},"outcome":{"type":"string","description":"One of:\n- \"applied\" — Docker accepted the update; caps are live now.\n- \"missing\" — container does not exist; caps stored, will apply on next start.\n- \"stopped\" — container exists but isn't running; Docker still\n accepts the update (the new caps apply on next start).\n- \"failed\" — `docker update` returned an error (see `error`)."},"role":{"type":"string","description":"`service_members.role` for cluster members; \"standalone\" otherwise."}}},"ResourceLimits":{"type":"object","description":"Resource limits and requests","properties":{"cpu_limit":{"type":["integer","null"],"format":"int32","description":"CPU limit (millicores)"},"cpu_request":{"type":["integer","null"],"format":"int32","description":"CPU request (millicores)"},"memory_limit":{"type":["integer","null"],"format":"int32","description":"Memory limit (MB)"},"memory_request":{"type":["integer","null"],"format":"int32","description":"Memory request (MB)"}}},"ResourceLimitsResponse":{"type":"object","description":"Container resource limits","properties":{"cpu_limit":{"type":["integer","null"],"format":"int32"},"cpu_request":{"type":["integer","null"],"format":"int32"},"memory_limit":{"type":["integer","null"],"format":"int32"},"memory_request":{"type":["integer","null"],"format":"int32"}}},"ResourceLimitsUpdateResponse":{"type":"object","description":"Response from PATCH /external-services/{id}/resources.","required":["limits","applied"],"properties":{"applied":{"type":"array","items":{"$ref":"#/components/schemas/ResourceLimitApplyResult"},"description":"Per-container result of trying to apply the limits live."},"limits":{"$ref":"#/components/schemas/ServiceResourceLimits","description":"The limits that were persisted to the encrypted config."}}},"ResourcesBody":{"type":"object","description":"Nested `resources: { memory, vcpus }` as sent by `@vercel/sandbox`.\n`memory` is in MB, `vcpus` is fractional CPU count.","properties":{"memory":{"type":["integer","null"],"format":"int64","minimum":0},"vcpus":{"type":["number","null"],"format":"double"}}},"RestoreCapabilities":{"type":"object","description":"Capabilities a service exposes for the generic restore framework.\n\nEach engine overrides `ExternalService::restore_capabilities` to declare\nwhat it supports. The handler layer uses this to validate requests and\nthe UI uses it to conditionally show options (e.g., PITR picker).","required":["restore_in_place","restore_to_new_service","pitr"],"properties":{"earliest_pitr_time":{"type":["string","null"],"format":"date-time","description":"Earliest recoverable timestamp, if `pitr` is true. Derived from\nengine-specific archive metadata (e.g., `pg_stat_archiver`)."},"latest_pitr_time":{"type":["string","null"],"format":"date-time","description":"Latest recoverable timestamp, if `pitr` is true."},"pitr":{"type":"boolean","description":"Point-in-time recovery using engine-specific continuous archives\n(WAL for Postgres, AOF for Redis, oplog for MongoDB, object versions for S3)."},"restore_in_place":{"type":"boolean","description":"Restore a backup onto the same running service (destructive)."},"restore_to_new_service":{"type":"boolean","description":"Restore a backup into a freshly provisioned service."}}},"RestoreCapabilitiesResponse":{"allOf":[{"$ref":"#/components/schemas/RestoreCapabilities","description":"Trait-declared capabilities."},{"type":"object","required":["suggested_new_service_name"],"properties":{"suggested_new_service_name":{"type":"string","description":"Suggested name for the new service when creating a clone. Safe to\npre-fill into the UI dialog; the user can edit before submitting."}}}]},"RestorePlan":{"type":"object","description":"Preview of a restore operation. Answers \"what will happen if I click\nstart?\" with engine-level specificity so the user can confirm before\ncommitting to a destructive action.","required":["engine","target_service","source_backup","strategy","steps","warnings","errors","destructive","mode"],"properties":{"destructive":{"type":"boolean","description":"Whether any step overwrites existing data on the target service."},"engine":{"type":"string","description":"Target engine (\"postgres\", etc.)."},"errors":{"type":"array","items":{"type":"string"},"description":"Blocking problems. The UI disables the Start button when non-empty."},"mode":{"type":"string","description":"Echo of the requested mode for the UI."},"source_backup":{"$ref":"#/components/schemas/PlanSourceBackup","description":"Backup we'll read from."},"steps":{"type":"array","items":{"type":"string"},"description":"Ordered list of human-readable actions the orchestrator will take."},"strategy":{"type":"string","description":"How the restore will be performed: \"walg_restore\", \"pg_dump_restore\",\nor \"unsupported\"."},"target_service":{"$ref":"#/components/schemas/PlanTarget","description":"Service we'll operate on (or provision a sibling of)."},"warnings":{"type":"array","items":{"type":"string"},"description":"Non-blocking caveats the user should see (cross-service, empty\nlocation that will be auto-resolved, missing engine metadata, ...)."}}},"RestoreRequestMode":{"oneOf":[{"type":"object","description":"Restore the backup onto the existing service (destructive).","required":["mode"],"properties":{"mode":{"type":"string","enum":["in_place"]}}},{"type":"object","description":"Provision a new service and restore into it.","required":["name","mode"],"properties":{"mode":{"type":"string","enum":["new_service"]},"name":{"type":"string","description":"Name for the new service. Orchestrator auto-suggests\n`{source}-restore-{yyyymmdd-hhmm}` if caller omits, but we require\nan explicit value at the API boundary."},"parameter_overrides":{"description":"Optional parameter overrides (port, docker_image, database)."}}},{"type":"object","description":"Point-in-time recovery. Only valid on WAL-G backups (Postgres).","required":["to_new_service","target","mode"],"properties":{"mode":{"type":"string","enum":["pitr"]},"new_service_name":{"type":["string","null"],"description":"Required when `to_new_service` is true."},"target":{"$ref":"#/components/schemas/RecoveryTarget","description":"Recovery target kind + value."},"to_new_service":{"type":"boolean","description":"Whether PITR restores in place or creates a new service."}}}],"description":"What the caller wants to do. Mirrors `externalsvc::RestoreMode` but\nflattened for JSON over the wire."},"RestoreRunView":{"type":"object","required":["id","source_backup_id","source_service_id","mode","status","phase","created_at"],"properties":{"created_at":{"type":"string"},"error_message":{"type":["string","null"]},"finished_at":{"type":["string","null"]},"id":{"type":"integer","format":"int32"},"mode":{"type":"string"},"phase":{"type":"string"},"recovery_target":{},"source_backup_id":{"type":"integer","format":"int32"},"source_service_id":{"type":"integer","format":"int32"},"started_at":{"type":["string","null"]},"status":{"type":"string"},"target_service_id":{"type":["integer","null"],"format":"int32"},"target_service_name":{"type":["string","null"]}}},"RetentionCleanupFailure":{"type":"object","required":["backup_id","reason","partial","deleted_objects"],"properties":{"backup_id":{"type":"string"},"deleted_objects":{"type":"integer","format":"int64","minimum":0},"partial":{"type":"boolean"},"reason":{"type":"string"}}},"RetentionCleanupReport":{"type":"object","required":["dry_run","expired","deleted","failed","failures","deleted_backup_ids","deleted_backup_ids_truncated","partially_deleted_backup_ids","partially_deleted_backup_ids_truncated","candidate_backup_ids","candidate_backup_ids_truncated"],"properties":{"candidate_backup_ids":{"type":"array","items":{"type":"string"},"description":"Capped sample of backups selected by the retention policy."},"candidate_backup_ids_truncated":{"type":"boolean"},"deleted":{"type":"integer","format":"int64","minimum":0},"deleted_backup_ids":{"type":"array","items":{"type":"string"},"description":"Capped sample of deleted backup UUIDs for audit attribution."},"deleted_backup_ids_truncated":{"type":"boolean"},"dry_run":{"type":"boolean","description":"True when this report is a non-destructive preview."},"expired":{"type":"integer","format":"int64","minimum":0},"failed":{"type":"integer","format":"int64","minimum":0},"failures":{"type":"array","items":{"$ref":"#/components/schemas/RetentionCleanupFailure"},"description":"Capped diagnostic sample; `failed` remains the authoritative total."},"partially_deleted_backup_ids":{"type":"array","items":{"type":"string"}},"partially_deleted_backup_ids_truncated":{"type":"boolean"},"schedule_id":{"type":["integer","null"],"format":"int32","description":"Schedule scope, or `None` when every schedule was considered."}}},"RetryClusterRequest":{"type":"object","description":"Request body for retrying a failed cluster initialization.","properties":{"members":{"type":"array","items":{"$ref":"#/components/schemas/ClusterMemberRequest"},"description":"Cluster member specifications (same format as create).\nIf omitted, the original member configuration is reconstructed from\nthe preserved service_members records."}}},"RevenueRow":{"type":"object","required":["id","ts","provider","event_type"],"properties":{"amount_minor":{"type":["integer","null"],"format":"int64"},"currency":{"type":["string","null"]},"customer_ref":{"type":["string","null"]},"deployment_id":{"type":["integer","null"],"format":"int32"},"environment_id":{"type":["integer","null"],"format":"int32"},"event_type":{"type":"string"},"id":{"type":"integer","format":"int64"},"provider":{"type":"string"},"trace_id":{"type":["string","null"]},"ts":{"type":"string","format":"date-time"}}},"RiskLevel":{"type":"string","description":"Risk level for a migration step","enum":["none","low","medium","high","critical"]},"RoleInfo":{"type":"object","description":"Information about a role","required":["name","description","permissions"],"properties":{"description":{"type":"string","description":"Human-readable description of the role"},"name":{"type":"string","description":"The role identifier (e.g., \"admin\")"},"permissions":{"type":"array","items":{"type":"string"},"description":"Permissions included in this role"}}},"RootfsCacheEntry":{"type":"object","description":"A cached rootfs image (Firecracker backend). Digest-keyed build artifact\nshared by all VMs created from the same image.","required":["digest","bytes","referenced_by"],"properties":{"bytes":{"type":"integer","format":"int64","description":"Actual on-disk size in bytes (sparse-aware).","minimum":0},"digest":{"type":"string","description":"Image digest this rootfs was built from (the cache key)."},"referenced_by":{"type":"array","items":{"type":"string"},"description":"IDs of live sandboxes whose per-VM disk was cloned from this entry.\nEmpty means the entry is reclaimable — no sandbox needs it."}}},"RootfsGcReport":{"type":"object","description":"Outcome of a rootfs garbage-collection pass.","required":["removed_digests","freed_bytes"],"properties":{"freed_bytes":{"type":"integer","format":"int64","minimum":0},"removed_digests":{"type":"array","items":{"type":"string"},"description":"Digests of cache entries removed because no sandbox referenced them."}}},"RootfsReport":{"type":"object","description":"Snapshot of a backend's rootfs storage for the management API. Backends\nwithout a rootfs concept (Docker, local) return an empty report.","required":["cache_bytes","cache","vm_bytes","vms"],"properties":{"cache":{"type":"array","items":{"$ref":"#/components/schemas/RootfsCacheEntry"}},"cache_bytes":{"type":"integer","format":"int64","minimum":0},"vm_bytes":{"type":"integer","format":"int64","minimum":0},"vms":{"type":"array","items":{"$ref":"#/components/schemas/RootfsVmEntry"}}}},"RootfsVmEntry":{"type":"object","description":"A per-sandbox rootfs disk (Firecracker backend). One per non-destroyed\nsandbox — the authoritative storage, independent of the cache.","required":["sandbox_name","bytes","running"],"properties":{"bytes":{"type":"integer","format":"int64","minimum":0},"running":{"type":"boolean"},"sandbox_name":{"type":"string"}}},"RouteRefreshResponse":{"type":"object","required":["route_count","message"],"properties":{"message":{"type":"string","description":"Human-readable message"},"route_count":{"type":"integer","description":"Number of routes loaded","minimum":0}}},"RouteResponse":{"type":"object","required":["id","domain","host","port","enabled","route_type","created_at","updated_at"],"properties":{"created_at":{"type":"integer","format":"int64"},"domain":{"type":"string"},"enabled":{"type":"boolean"},"host":{"type":"string"},"id":{"type":"integer","format":"int32"},"port":{"type":"integer","format":"int32"},"route_type":{"type":"string","description":"Route type: \"http\" or \"tls\""},"updated_at":{"type":"integer","format":"int64"}}},"RouteRole":{"type":"object","required":["id","name","created_at","updated_at"],"properties":{"created_at":{"type":"integer","format":"int64","example":"1683900000000"},"id":{"type":"integer","format":"int32"},"name":{"type":"string"},"updated_at":{"type":"integer","format":"int64","example":"1683900000000"}}},"RouteUser":{"type":"object","required":["id","name","username","email","image","mfa_enabled","email_verified","created_at","updated_at"],"properties":{"created_at":{"type":"integer","format":"int64","example":"1683900000000"},"deleted_at":{"type":["integer","null"],"format":"int64"},"email":{"type":"string"},"email_verified":{"type":"boolean"},"id":{"type":"integer","format":"int32"},"image":{"type":"string"},"mfa_enabled":{"type":"boolean"},"name":{"type":"string"},"updated_at":{"type":"integer","format":"int64","example":"1683900000000"},"username":{"type":"string"}}},"RouteUserWithRoles":{"type":"object","required":["user","roles"],"properties":{"roles":{"type":"array","items":{"$ref":"#/components/schemas/RouteRole"}},"user":{"$ref":"#/components/schemas/RouteUser"}}},"RunBackupRequest":{"type":"object","required":["backup_type"],"properties":{"backup_type":{"type":"string","description":"Type of backup to perform","example":"full"}}},"RunExternalServiceBackupRequest":{"type":"object","properties":{"backup_type":{"type":["string","null"],"description":"Type of backup to perform (e.g., \"full\", \"incremental\")","example":"full"},"s3_source_id":{"type":["integer","null"],"format":"int32","description":"ID of the S3 source to store the backup. If omitted, the current default S3 source is used.","example":1}}},"S3ConnectionTestResponse":{"type":"object","description":"Response body for an S3 connection test.","required":["ok","message"],"properties":{"message":{"type":"string","description":"Human-readable message (success confirmation or error detail)."},"ok":{"type":"boolean","description":"Whether the connection and credentials worked."}}},"S3CredentialsResponse":{"type":"object","description":"S3 credentials distributed to agents for backup/restore operations.","required":["access_key_id","secret_key","region","bucket_name","force_path_style"],"properties":{"access_key_id":{"type":"string"},"bucket_name":{"type":"string"},"endpoint":{"type":["string","null"]},"force_path_style":{"type":"boolean"},"region":{"type":"string"},"secret_key":{"type":"string"}}},"S3SourceResponse":{"type":"object","description":"Response type for S3 source","required":["id","name","bucket_name","bucket_path","access_key_id","secret_key","region","is_default","created_at","updated_at"],"properties":{"access_key_id":{"type":"string","example":"AKIAXXXXXXXXXXXXXXXX"},"bucket_name":{"type":"string"},"bucket_path":{"type":"string"},"created_at":{"type":"integer","format":"int64"},"endpoint":{"type":["string","null"],"example":"http://minio.example.com:9000"},"force_path_style":{"type":["boolean","null"]},"id":{"type":"integer","format":"int32"},"is_default":{"type":"boolean"},"name":{"type":"string"},"region":{"type":"string"},"secret_key":{"type":"string","writeOnly":true},"updated_at":{"type":"integer","format":"int64"}}},"SandboxDomainResponse":{"type":"object","required":["url"],"properties":{"url":{"type":"string"}}},"SandboxEvent":{"type":"object","description":"One entry in a sandbox's operations timeline.","required":["event_type","at"],"properties":{"at":{"type":"integer","format":"int64","description":"Unix epoch milliseconds."},"detail":{"description":"Optional structured context (shape depends on `event_type`)."},"event_type":{"type":"string","description":"Machine-readable operation (`created`, `stopped`, `resumed`,\n`restarted`, `timeout_extended`, `resized`, `preview_password_set`,\n`preview_password_cleared`, `preview_share_link_created`, `source_seeded`,\n`destroyed`)."}}},"SandboxEventsResponse":{"type":"object","required":["events"],"properties":{"events":{"type":"array","items":{"$ref":"#/components/schemas/SandboxEvent"}}}},"SandboxInner":{"type":"object","description":"Inner `sandbox` object in `@vercel/sandbox` responses. Strict shape —\nthe SDK's zod validator rejects missing required fields.","required":["id","memory","vcpus","region","runtime","timeout","status","requestedAt","createdAt","updatedAt","cwd","name","preview_url_template"],"properties":{"agent_run_id":{"type":["integer","null"],"format":"int32","description":"Agent run this sandbox executes (autofixer / workflow agent).\n`None` for sandboxes created via this API."},"backend":{"type":["string","null"],"description":"Isolation backend: \"docker\" | \"firecracker\". `None` on legacy rows\ncreated before the backend was recorded."},"createdAt":{"type":"integer","format":"int64"},"cwd":{"type":"string"},"disk_size_mb":{"type":["integer","null"],"format":"int64","description":"Configured root disk size in MB (Firecracker). `None` when unknown or\nthe default.","minimum":0},"id":{"type":"string"},"image":{"type":["string","null"]},"memory":{"type":"integer","format":"int64","minimum":0},"name":{"type":"string"},"preview_password_hint":{"type":["string","null"]},"preview_url_template":{"type":"string"},"region":{"type":"string"},"requestedAt":{"type":"integer","format":"int64","description":"Creation time as Unix epoch milliseconds."},"runtime":{"type":"string"},"status":{"type":"string"},"timeout":{"type":"integer","format":"int64","description":"Idle timeout in milliseconds (SDK convention).","minimum":0},"updatedAt":{"type":"integer","format":"int64"},"vcpus":{"type":"number","format":"double"}}},"SandboxResponse":{"type":"object","description":"`@vercel/sandbox` wraps every single-sandbox response as\n`{ sandbox: {...}, routes: [...] }`. The SDK reads both.","required":["sandbox","routes"],"properties":{"routes":{"type":"array","items":{"$ref":"#/components/schemas/SandboxRoute"}},"sandbox":{"$ref":"#/components/schemas/SandboxInner"}}},"SandboxRoute":{"type":"object","description":"A single preview route, one per declared port. We don't know ports\nupfront, so we surface an empty array by default — SDK clients use\ntheir own port when calling `sandbox.domain(port)`.","required":["url","subdomain","port"],"properties":{"port":{"type":"integer","format":"int32","minimum":0},"subdomain":{"type":"string"},"url":{"type":"string"}}},"SandboxStatusResponse":{"type":"object","required":["docker_available","image_ready","image_name","firecracker_available"],"properties":{"docker_available":{"type":"boolean"},"error":{"type":["string","null"]},"firecracker_available":{"type":"boolean"},"image_name":{"type":"string"},"image_ready":{"type":"boolean"}}},"SaveAgentTokenRequest":{"type":"object","required":["token"],"properties":{"token":{"type":"string","description":"The OAuth token from `claude setup-token` or an API key.\nWill be encrypted before storage."}}},"SaveAgentTokenResponse":{"type":"object","required":["saved"],"properties":{"saved":{"type":"boolean"}}},"SaveCredentialRequest":{"type":"object","required":["auth_type","credential"],"properties":{"auth_type":{"type":"string","description":"Auth flavor id (must match one of the provider's catalog entries)."},"credential":{"type":"string","description":"Plaintext credential body (API key, OAuth token, or full config file\ncontents). Encrypted with `EncryptionService` before being persisted\ninside the `agent_sandbox.providers` JSON map."}}},"SaveCredentialResponse":{"type":"object","required":["saved","provider_id","auth_type"],"properties":{"auth_type":{"type":"string"},"provider_id":{"type":"string"},"saved":{"type":"boolean"}}},"ScalewayCredentialsRequest":{"type":"object","required":["api_key","project_id"],"properties":{"api_key":{"type":"string","example":"scw-secret-key-12345"},"project_id":{"type":"string","example":"12345678-1234-1234-1234-123456789012"}}},"ScanResponse":{"type":"object","required":["id","project_id","scanner_type","status","total_count","critical_count","high_count","medium_count","low_count","unknown_count","started_at","created_at","updated_at"],"properties":{"branch":{"type":["string","null"]},"commit_hash":{"type":["string","null"]},"completed_at":{"type":["string","null"],"example":"2025-12-08T12:15:47.609192Z"},"created_at":{"type":"string","example":"2025-12-08T12:15:47.609192Z"},"critical_count":{"type":"integer","format":"int32"},"deployment_id":{"type":["integer","null"],"format":"int32"},"environment_id":{"type":["integer","null"],"format":"int32"},"error_message":{"type":["string","null"]},"high_count":{"type":"integer","format":"int32"},"id":{"type":"integer","format":"int32"},"low_count":{"type":"integer","format":"int32"},"medium_count":{"type":"integer","format":"int32"},"project_id":{"type":"integer","format":"int32"},"scanner_type":{"type":"string"},"scanner_version":{"type":["string","null"]},"started_at":{"type":"string","example":"2025-12-08T12:15:47.609192Z"},"status":{"type":"string"},"total_count":{"type":"integer","format":"int32"},"unknown_count":{"type":"integer","format":"int32"},"updated_at":{"type":"string","example":"2025-12-08T12:15:47.609192Z"}}},"ScheduleRunEntry":{"type":"object","description":"A single run-history entry for the schedule detail page (deliverable 1).\n\nCombines one `backups` row with the most-recent `backup_jobs` row for that\nbackup via a lateral JOIN. Fields from `backup_jobs` are `None` for legacy\nbackup rows that pre-date ADR-014.","required":["backup_id","backup_uuid","state","started_at","s3_location"],"properties":{"attempts":{"type":["integer","null"],"format":"int32","description":"Number of claim-and-run attempts so far. `None` for legacy rows."},"backup_id":{"type":"integer","format":"int32","description":"DB id of the `backups` row."},"backup_uuid":{"type":"string","description":"UUID string (`backups.backup_id`)."},"current_step":{"type":["string","null"],"description":"Last completed step reported by the engine (e.g. `\"upload\"`).\n`None` when no step has been persisted yet."},"error_message":{"type":["string","null"],"description":"Engine-reported error message when `state = \"failed\"`."},"finished_at":{"type":["string","null"],"description":"When the backup finished, if known."},"job_id":{"type":["integer","null"],"format":"int64","description":"Most recent `backup_jobs.id` for this backup. `None` for legacy rows."},"s3_location":{"type":"string","description":"S3 object key or URL where the backup data lives."},"size_bytes":{"type":["integer","null"],"format":"int64","description":"Final size in bytes once completed. `None` while running."},"started_at":{"type":"string","description":"When the backup was started (ISO 8601 / RFC 3339)."},"state":{"type":"string","description":"Current state: `\"pending\"`, `\"running\"`, `\"completed\"`, `\"failed\"`."}}},"ScheduleRunJobEntry":{"type":"object","description":"A single job entry inside an expanded schedule run, returned by\n[`BackupService::list_schedule_run_jobs`].","required":["backup_id","backup_uuid","engine","service_name","state","started_at","s3_source_id"],"properties":{"backup_id":{"type":"integer","format":"int32","description":"`backups.id` for this job."},"backup_uuid":{"type":"string","description":"`backups.backup_id` UUID string."},"engine":{"type":"string","description":"Engine key (e.g. `\"control_plane\"`, `\"redis\"`)."},"error_message":{"type":["string","null"],"description":"Engine-reported error message when `state = \"failed\"`."},"finished_at":{"type":["string","null"],"description":"When this child backup finished, if known."},"s3_source_id":{"type":"integer","format":"int32","description":"FK to `s3_sources.id` — needed for the backup detail link."},"service_id":{"type":["integer","null"],"format":"int32","description":"`external_services.id` — `NULL` for the control-plane job."},"service_name":{"type":"string","description":"Name of the external service, or `\"control plane\"` for the\ncontrol-plane job."},"size_bytes":{"type":["integer","null"],"format":"int64","description":"Size in bytes once completed; `None` while running."},"started_at":{"type":"string","description":"When this child backup started (ISO 8601 / RFC 3339)."},"state":{"type":"string","description":"Current state of this child backup."}}},"ScheduleRunListResponse":{"type":"object","description":"Paginated run-history response for a backup schedule (deliverable 1).","required":["runs","total","page","page_size"],"properties":{"page":{"type":"integer","format":"int64","description":"Current page (1-based)."},"page_size":{"type":"integer","format":"int64","description":"Number of items per page (clamped to 1–100)."},"runs":{"type":"array","items":{"$ref":"#/components/schemas/ScheduleRunEntry"},"description":"Run entries, newest first."},"total":{"type":"integer","format":"int64","description":"Total number of runs across all pages."}}},"ScheduleRunResponse":{"type":"object","description":"HTTP response body for `POST /api/backups/schedules/{id}/run` (fan-out).","required":["schedule_run_id","jobs"],"properties":{"jobs":{"type":"array","items":{"$ref":"#/components/schemas/EnqueuedJob"},"description":"All jobs that were enqueued in this fan-out."},"schedule_run_id":{"type":"integer","format":"int64","description":"The `schedule_runs.id` of the newly created run."}}},"ScheduleRunSummary":{"type":"object","description":"Summary of one scheduler tick (or one \"Run now\" click), returned by\n[`BackupService::list_schedule_runs`].\n\nThe `aggregate_state` is computed at read time from child backup counts:\n- `\"running\"` — at least one child is `\"pending\"` or `\"running\"`.\n- `\"failed\"` — at least one child is `\"failed\"` and none are running.\n- `\"completed\"` — all children are `\"completed\"`.","required":["run_id","schedule_id","triggered_by","started_at","aggregate_state","total_jobs","completed_jobs","failed_jobs","running_jobs","pending_jobs"],"properties":{"aggregate_state":{"type":"string","description":"Aggregate state computed from child counts (see struct docs)."},"completed_jobs":{"type":"integer","format":"int64","description":"Number of children in `state = \"completed\"`."},"failed_jobs":{"type":"integer","format":"int64","description":"Number of children in `state = \"failed\"`."},"finished_at":{"type":["string","null"],"description":"When all children reached a terminal state. `None` while any child is\nstill `\"pending\"` or `\"running\"`."},"pending_jobs":{"type":"integer","format":"int64","description":"Number of children in `state = \"pending\"`."},"run_id":{"type":"integer","format":"int64","description":"`schedule_runs.id` for this tick."},"running_jobs":{"type":"integer","format":"int64","description":"Number of children in `state = \"running\"`."},"schedule_id":{"type":"integer","format":"int32","description":"FK to `backup_schedules.id`."},"started_at":{"type":"string","description":"When the fan-out started (ISO 8601 / RFC 3339)."},"total_jobs":{"type":"integer","format":"int64","description":"Total number of child backup jobs in this run."},"triggered_by":{"type":"string","description":"How the run was triggered: `\"cron\"` or `\"manual\"`."}}},"ScheduleRunSummaryList":{"type":"object","description":"Paginated list of schedule run summaries returned by the new\n[`BackupService::list_schedule_runs`].","required":["runs","total","page","page_size"],"properties":{"page":{"type":"integer","format":"int64","description":"Current page (1-based)."},"page_size":{"type":"integer","format":"int64","description":"Number of items per page."},"runs":{"type":"array","items":{"$ref":"#/components/schemas/ScheduleRunSummary"},"description":"Run summaries, newest first. Includes synthetic single-job rows for\nlegacy `backups` rows that have `schedule_id` set but no\n`schedule_run_id` (pre-fan-out history)."},"total":{"type":"integer","format":"int64","description":"Total number of run entries across all pages."}}},"ScreenshotSettings":{"type":"object","properties":{"enabled":{"type":"boolean","default":false},"provider":{"type":"string","default":"local"},"url":{"type":"string","default":""}}},"SearchLogsRequest":{"type":"object","required":["project_id"],"properties":{"container_ids":{"type":"array","items":{"type":"string"},"description":"Filter to specific containers (Docker container IDs). Empty = all\ncontainers. Drives \"filter by container / show all\" in a project's\nhistory, which spans multiple deployments and containers."},"context_lines":{"type":["integer","null"],"format":"int32","description":"grep -C: number of raw context lines to include before and after each\nmatch (0 = none, default). Clamped to 50 server-side. The surrounding\nlines ignore the level/text filters — they are the actual adjacent log\nlines, merged across overlapping matches.","minimum":0},"cursor":{"type":["string","null"],"description":"Pagination cursor"},"deploy_id":{"type":["integer","null"],"format":"int32","description":"Filter by deployment ID (deployments.id)"},"end_time":{"type":["string","null"],"description":"End of time range (ISO 8601). Defaults to now."},"envs":{"type":"array","items":{"type":"string"},"description":"Filter by environments"},"external_service_id":{"type":["integer","null"],"format":"int32","description":"When set, search an imported/managed external service's logs instead\nof a project's. `project_id` is ignored in this mode."},"levels":{"type":"array","items":{"type":"string"},"description":"Filter by log levels"},"node_ids":{"type":"array","items":{"type":"integer","format":"int32"},"description":"Filter to specific worker nodes (node_id). Empty = all nodes, including\ncontrol-plane-local logs."},"page_size":{"type":["integer","null"],"format":"int32","description":"Page size (default: 100, max: 500)","minimum":0},"project_id":{"type":"integer","format":"int32","description":"Project ID (integer, as used by the rest of the platform)"},"services":{"type":"array","items":{"type":"string"},"description":"Filter by services"},"start_time":{"type":["string","null"],"description":"Start of time range (ISO 8601). Defaults to 1 hour ago."},"text":{"type":["string","null"],"description":"Full text search query"}}},"SearchLogsResponse":{"type":"object","required":["lines","search_mode","total_scanned"],"properties":{"available_sources":{"type":"array","items":{"$ref":"#/components/schemas/LogSource"},"description":"Distinct containers/nodes/services available in the queried scope, for\nthe filter dropdowns. Populated on the first page (no cursor)."},"lines":{"type":"array","items":{"$ref":"#/components/schemas/LogSearchLine"}},"next_cursor":{"type":["string","null"]},"search_mode":{"$ref":"#/components/schemas/SearchMode"},"total_scanned":{"type":"integer","format":"int64","minimum":0}}},"SearchMode":{"type":"string","description":"Search execution mode","enum":["index","archive"]},"Seasonality":{"type":"string","description":"Seasonality model for an anomaly baseline.","enum":["none","hourly","daily","weekly"]},"SecretResponse":{"type":"object","required":["id","name","secret_type","value","created_at","updated_at"],"properties":{"created_at":{"type":"string"},"description":{"type":["string","null"]},"id":{"type":"integer","format":"int32"},"mount_path":{"type":["string","null"]},"name":{"type":"string"},"secret_type":{"type":"string"},"updated_at":{"type":"string"},"value":{"type":"string","description":"Always masked in responses"}}},"SecurityConfig":{"type":"object","description":"Security configuration for projects and environments\n\nThis configuration can be set at three levels:\n1. Global (in settings table) - applies to all projects\n2. Project level - overrides global settings for specific project\n3. Environment level - overrides project settings for specific environment\n\nThe inheritance chain: Environment > Project > Global","properties":{"attackMode":{"type":["string","null"],"description":"Attack mode configuration (future: \"off\", \"challenge\", \"block\")\nPlaceholder for DDoS protection, bot detection, etc."},"challengeConfig":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/ChallengeConfig","description":"Challenge configuration (future: CAPTCHA, JS challenge, etc.)"}]},"enabled":{"type":["boolean","null"],"description":"Enable/disable security features at this level\nIf None, inherits from parent level"},"geoRestrictions":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/GeoRestrictionsConfig","description":"Geographic restrictions (future: country blocking, etc.)"}]},"headers":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/SecurityHeadersConfig","description":"Security headers configuration"}]},"passwordProtection":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/PasswordProtectionConfig","description":"Password protection: shows an HTML password form before allowing access"}]},"rateLimiting":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/RateLimitConfig","description":"Rate limiting configuration"}]}}},"SecurityHeadersConfig":{"type":"object","description":"Security headers configuration (subset of global SecurityHeadersSettings)","properties":{"contentSecurityPolicy":{"type":["string","null"],"description":"Custom CSP (only used if preset is \"custom\")"},"preset":{"type":["string","null"],"description":"Use a preset: \"strict\", \"moderate\", \"permissive\", \"disabled\", \"custom\""},"referrerPolicy":{"type":["string","null"],"description":"Referrer-Policy override"},"strictTransportSecurity":{"type":["string","null"],"description":"HSTS override"},"xFrameOptions":{"type":["string","null"],"description":"X-Frame-Options override"}}},"SecurityHeadersSettings":{"type":"object","properties":{"content_security_policy":{"type":["string","null"],"default":"default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' data:; connect-src 'self'; frame-ancestors 'self'"},"enabled":{"type":"boolean","default":false},"permissions_policy":{"type":["string","null"],"default":"geolocation=(), microphone=(), camera=()"},"preset":{"type":"string","default":"moderate"},"referrer_policy":{"type":"string","default":"strict-origin-when-cross-origin"},"strict_transport_security":{"type":"string","default":"max-age=31536000; includeSubDomains"},"x_content_type_options":{"type":"string","default":"nosniff"},"x_frame_options":{"type":"string","default":"SAMEORIGIN"},"x_xss_protection":{"type":"string","default":"1; mode=block"}}},"SendEmailRequestBody":{"type":"object","required":["from","to","subject"],"properties":{"bcc":{"type":["array","null"],"items":{"type":"string"},"description":"BCC recipients"},"cc":{"type":["array","null"],"items":{"type":"string"},"description":"CC recipients"},"from":{"type":"string","description":"Sender email address (domain will be auto-extracted for lookup)","example":"hello@updates.example.com"},"from_name":{"type":["string","null"],"description":"Sender display name","example":"My App"},"headers":{"type":["object","null"],"description":"Custom headers","additionalProperties":{"type":"string"},"propertyNames":{"type":"string"}},"html":{"type":["string","null"],"description":"HTML body content","example":"

Hello World

"},"reply_to":{"type":["string","null"],"description":"Reply-to address"},"subject":{"type":"string","description":"Email subject","example":"Welcome to our platform!"},"tags":{"type":["array","null"],"items":{"type":"string"},"description":"Tags for categorization","example":["welcome","onboarding"]},"text":{"type":["string","null"],"description":"Plain text body content","example":"Hello World"},"to":{"type":"array","items":{"type":"string"},"description":"Recipient email addresses","example":["user@example.com"]},"track_clicks":{"type":["boolean","null"],"description":"Enable click tracking (link rewriting). Defaults to false."},"track_opens":{"type":["boolean","null"],"description":"Enable open tracking (tracking pixel injection). Defaults to false."}}},"SendEmailResponseBody":{"type":"object","required":["id","status"],"properties":{"id":{"type":"string","description":"Email ID","example":"550e8400-e29b-41d4-a716-446655440000"},"provider_message_id":{"type":["string","null"],"description":"Provider message ID"},"status":{"type":"string","description":"Email status","example":"sent"}}},"SendMessageRequest":{"type":"object","required":["content"],"properties":{"content":{"type":"string"},"page_context":{"type":["string","null"],"description":"Optional, client-supplied description of the page/entity the user is\ncurrently viewing (e.g. a trace in a project). Injected into the model's\nview of this turn only — never stored or shown in history. Capped server\nside; oversized values are ignored rather than rejected."}}},"SensitiveConfigValueResponse":{"type":"object","required":["value"],"properties":{"value":{"type":"string"}}},"SensitiveMcpConfigValueResponse":{"type":"object","required":["value"],"properties":{"value":{"type":"string"}}},"SensitiveValueResponse":{"type":"object","required":["value"],"properties":{"value":{"type":"string"}}},"SentryChunkUploadResponse":{"type":"object","required":["url","chunkSize","chunksPerRequest","maxFileSize","maxRequestSize","concurrency","hashAlgorithm","compression","accept"],"properties":{"accept":{"type":"array","items":{"type":"string"}},"chunkSize":{"type":"integer","format":"int64","minimum":0},"chunksPerRequest":{"type":"integer","format":"int32","minimum":0},"compression":{"type":"array","items":{"type":"string"}},"concurrency":{"type":"integer","format":"int32","minimum":0},"hashAlgorithm":{"type":"string"},"maxFileSize":{"type":"integer","format":"int64","minimum":0},"maxRequestSize":{"type":"integer","format":"int64","minimum":0},"url":{"type":"string"}}},"SentryCreateReleaseRequest":{"type":"object","required":["version"],"properties":{"projects":{"type":"array","items":{"type":"string"},"description":"Project slugs this release belongs to"},"version":{"type":"string","description":"Release version identifier"}}},"SentryEventRequest":{"type":"object","properties":{"event_id":{"type":["string","null"]},"message":{"type":["string","null"]},"platform":{"type":["string","null"]},"timestamp":{"type":["string","null"]}}},"SentryEventResponse":{"type":"object","required":["id"],"properties":{"id":{"type":"string"}}},"SentryReleaseFileResponse":{"type":"object","required":["id","name","headers","size","sha1","dateCreated"],"properties":{"dateCreated":{"type":"string"},"dist":{"type":["string","null"]},"headers":{},"id":{"type":"string"},"name":{"type":"string"},"sha1":{"type":"string"},"size":{"type":"integer","format":"int64"}}},"SentryReleaseProjectRef":{"type":"object","required":["name","slug"],"properties":{"name":{"type":"string"},"slug":{"type":"string"}}},"SentryReleaseResponse":{"type":"object","required":["version","dateCreated","shortVersion","projects"],"properties":{"dateCreated":{"type":"string"},"dateReleased":{"type":["string","null"]},"projects":{"type":"array","items":{"$ref":"#/components/schemas/SentryReleaseProjectRef"}},"shortVersion":{"type":"string"},"version":{"type":"string"}}},"SeriesStateEntry":{"type":"object","description":"One series' persisted state snapshot for a dynamic rule (ADR-026 follow-up):\nthe state after the latest tick, the value evaluated this tick, and the open\nalarm id (when firing). Serialized into the `series_states` jsonb column keyed\nby the human-readable [`series_label`]; the alert response decodes it back.","required":["state","value"],"properties":{"alarm_id":{"type":["integer","null"],"format":"int32","description":"The open alarm's id when the series is firing; `null` when ok."},"state":{"type":"string","description":"`firing` or `ok` for this series after the latest tick."},"value":{"type":"number","format":"double","description":"The value the rule evaluated for this series this tick."}}},"ServiceAccessInfo":{"type":"object","description":"Response containing information about how the service is being accessed","required":["access_mode","can_create_domains"],"properties":{"access_mode":{"type":"string","description":"Mode of access: \"local\", \"direct\", \"nat\", or \"cloudflare_tunnel\""},"can_create_domains":{"type":"boolean","description":"Whether domain creation is allowed in this mode"},"domain_creation_error":{"type":["string","null"],"description":"Error message if domain creation is not allowed"},"private_ip":{"type":["string","null"],"description":"Server's private/local IP address (always returned if available)"},"public_ip":{"type":["string","null"],"description":"Server's public IP address (always returned if available)"}}},"ServiceAction":{"type":"string","description":"What to do with a service during migration","enum":["create","link-external","skip"]},"ServiceAlertRuleResponse":{"type":"object","description":"Wire representation of a monitoring alert rule.\n\nRegistered under a domain-prefixed OpenAPI schema name to avoid colliding\nwith `temps-error-tracking`'s unrelated `AlertRuleResponse` (utoipa keys\nschemas by their bare struct name, so without `as = ...` the last crate to\nregister would silently shadow this one in the merged spec / generated SDK).","required":["id","name","metric_name","threshold","comparator","severity","for_duration_secs","enabled"],"properties":{"comparator":{"type":"string"},"deployment_id":{"type":["integer","null"],"format":"int32"},"enabled":{"type":"boolean"},"for_duration_secs":{"type":"integer","format":"int32"},"id":{"type":"integer","format":"int32"},"metric_name":{"type":"string"},"name":{"type":"string"},"service_id":{"type":["integer","null"],"format":"int32"},"severity":{"type":"string"},"silenced_until":{"type":["string","null"]},"threshold":{"type":"number","format":"double"}}},"ServiceBackupEntryResponse":{"type":"object","description":"A single backup entry in the per-service backup list.","required":["id","backup_id","name","state","backup_type","started_at","s3_location","compression_type","s3_source_id","s3_source_name","external_service_backup_id"],"properties":{"backup_id":{"type":"string","description":"UUID string assigned at backup creation time."},"backup_type":{"type":"string","description":"Backup variant (e.g. \"full\", \"incremental\")."},"compression_type":{"type":"string","description":"Compression algorithm used (e.g. \"gzip\")."},"error_message":{"type":["string","null"],"description":"Engine-reported error message, populated when `state = \"failed\"`."},"external_service_backup_id":{"type":"integer","format":"int32","description":"Row ID from `external_service_backups`."},"finished_at":{"type":["string","null"],"description":"ISO 8601 timestamp when the backup finished, if known.","example":"2025-01-15T14:35:00Z"},"id":{"type":"integer","format":"int32","description":"Row ID from the `backups` table."},"name":{"type":"string","description":"Human-friendly display name."},"s3_location":{"type":"string","description":"Object key or `s3://` URL for the backup data."},"s3_source_id":{"type":"integer","format":"int32","description":"FK to `s3_sources.id`."},"s3_source_name":{"type":"string","description":"Human-readable name of the S3 source."},"size_bytes":{"type":["integer","null"],"format":"int64","description":"Size of the backup in bytes, if available."},"started_at":{"type":"string","description":"ISO 8601 timestamp when the backup started.","example":"2025-01-15T14:30:00Z"},"state":{"type":"string","description":"Current state: \"completed\", \"running\", \"failed\"."}}},"ServiceBackupListResponse":{"type":"object","description":"Paginated list of backups for a specific external service.\n\nReturned by `GET /backups/external-services/{service_id}/backups`.","required":["backups","total","page","page_size"],"properties":{"backups":{"type":"array","items":{"$ref":"#/components/schemas/ServiceBackupEntryResponse"},"description":"Backups belonging to this service, newest first."},"page":{"type":"integer","format":"int64","description":"Current page (1-based)."},"page_size":{"type":"integer","format":"int64","description":"Number of items per page."},"total":{"type":"integer","format":"int64","description":"Total number of backups for this service across all pages."}}},"ServiceCreateAlertRuleRequest":{"type":"object","description":"Request body for creating an alert rule on an external service.\n\nDomain-prefixed schema name — see [`AlertRuleResponse`] for why.","required":["name","metric_name","threshold","comparator","severity"],"properties":{"comparator":{"type":"string","description":"One of `>`, `<`, `>=`, `<=`."},"enabled":{"type":"boolean"},"for_duration_secs":{"type":"integer","format":"int32","description":"Seconds the breach must persist before the alarm fires (0 = immediate)."},"metric_name":{"type":"string"},"name":{"type":"string"},"severity":{"type":"string","description":"`\"warning\"` or `\"critical\"`."},"threshold":{"type":"number","format":"double"}}},"ServiceHealthResponse":{"type":"object","required":["service_id","consecutive_failures","recent_checks"],"properties":{"consecutive_failures":{"type":"integer","format":"int32","description":"Consecutive failed probes. Alert fires at 3."},"last_checked_at":{"type":["string","null"]},"last_error":{"type":["string","null"]},"recent_checks":{"type":"array","items":{"$ref":"#/components/schemas/HealthCheckEntryResponse"},"description":"Most recent checks, newest-first (capped at `limit`)."},"response_time_ms":{"type":["integer","null"],"format":"int32"},"service_id":{"type":"integer","format":"int32"},"status":{"type":["string","null"],"description":"Current health. `null` if the service has not been probed yet.","example":"operational"},"uptime_24h_percent":{"type":["number","null"],"format":"double","description":"Uptime percentage over the last 24 hours (0.0 — 100.0).\n`null` when there is not enough history."}}},"ServiceHealthStatusBatchResponse":{"type":"object","required":["statuses"],"properties":{"statuses":{"type":"array","items":{"$ref":"#/components/schemas/ServiceHealthStatusEntryResponse"}}}},"ServiceHealthStatusEntryResponse":{"type":"object","required":["service_id","consecutive_failures"],"properties":{"consecutive_failures":{"type":"integer","format":"int32"},"last_checked_at":{"type":["string","null"]},"service_id":{"type":"integer","format":"int32"},"status":{"type":["string","null"],"description":"\"operational\" | \"degraded\" | \"down\". `null` when the service has not\nbeen probed yet.","example":"operational"}}},"ServiceMemberInfo":{"type":"object","description":"Public info about a cluster member.","required":["id","role","container_name","status","ordinal"],"properties":{"compute_ip":{"type":["string","null"],"description":"Container's IP on the `temps-overlay` multi-host network. Populated\nby the lifecycle hook (ADR-011 Phase 3); `None` on single-host\nclusters where the overlay isn't attached."},"container_name":{"type":"string"},"hostname":{"type":["string","null"]},"id":{"type":"integer","format":"int32"},"live_state":{"type":["string","null"],"description":"Live FSM state from the pg_auto_failover monitor (`primary`,\n`secondary`, `catchingup`, `report_lsn`, …). `None` when the\nmonitor is unreachable, the service is not a cluster, or the row\nis the monitor itself.\n\n**The UI must render the role badge from this field**, falling\nback to `role` only when `live_state` is null. `role` is now\nconfig-only (`monitor` or `replica`); flipping the badge to\n\"primary\" when the monitor elects a new one used to require a\nreconciler that lagged ~5s behind real failovers — and during\nthat window the UI showed two primaries. `live_state` is read\ndirectly from the monitor on every list, so it can never lag."},"node_id":{"type":["integer","null"],"format":"int32"},"ordinal":{"type":"integer","format":"int32"},"port":{"type":["integer","null"],"format":"int32"},"provisioning_error":{"type":["string","null"],"description":"Most recent provisioning failure message, when `status='failed'`.\nSet by the background task so the UI can show *why* the new\nreplica didn't come up."},"provisioning_step":{"type":["string","null"],"description":"Last-attempted phase of the async `add_cluster_member` background\ntask (e.g. `validating`, `provisioning_container`, `done`,\n`failed`). `None` for members not created through that flow —\nthe UI falls back to the `status` column for those."},"role":{"type":"string"},"status":{"type":"string"}}},"ServiceParameter":{"type":"object","required":["name","required","encrypted","description"],"properties":{"choices":{"type":["array","null"],"items":{"type":"string"}},"default_value":{"type":["string","null"]},"description":{"type":"string"},"encrypted":{"type":"boolean"},"name":{"type":"string"},"required":{"type":"boolean"},"validation_pattern":{"type":["string","null"]}}},"ServicePlan":{"type":"object","description":"Plan for migrating a single service (database, cache, etc.)","required":["name","service_type","action","action_description"],"properties":{"action":{"$ref":"#/components/schemas/ServiceAction","description":"What to do with this service"},"action_description":{"type":"string","description":"Human-readable explanation of what this action means"},"data_implications":{"type":"array","items":{"$ref":"#/components/schemas/DataImplication"},"description":"Data implications specific to this service"},"env_var_mappings":{"type":"object","description":"Environment variable key mappings: source_key -> temps_key\n\nFor example, Vercel's `POSTGRES_URL` might map to Temps' `DATABASE_URL`.\nBoth keys will be set during migration so the app works with either.","additionalProperties":{"type":"string"},"propertyNames":{"type":"string"}},"name":{"type":"string","description":"Human-readable service name"},"parameters":{"type":"object","description":"Parameters for creating the service in Temps","additionalProperties":{},"propertyNames":{"type":"string"}},"service_type":{"type":"string","description":"Service type (maps to temps-providers ServiceType)"},"version":{"type":["string","null"],"description":"Service version to create (e.g., \"16\" for Postgres 16)"}}},"ServiceResourceLimits":{"type":"object","description":"Optional cgroup resource limits applied to a service container.\n\nAll fields are `Option`: `None` means \"no limit\" (the kernel default),\nmatching Docker's behavior when the corresponding `HostConfig` field is\nleft at zero. Operators opt in to limits explicitly through the\n`PATCH /external-services/{id}/resources` endpoint or by writing the\n`resources` block into `ServiceConfig::parameters` at create time.\n\nThese map directly onto bollard fields:\n- `memory_mb` → `HostConfig.memory` (bytes)\n- `memory_swap_mb`→ `HostConfig.memory_swap` (bytes; ≥ memory)\n- `nano_cpus` → `HostConfig.nano_cpus` (1e9 = 1 full CPU)\n- `cpu_shares` → `HostConfig.cpu_shares` (relative weight, default 1024)\n- `shm_size_mb` → `HostConfig.shm_size` (bytes; default 64 MiB)\n\nIMPORTANT: enabling hard memory limits causes the kernel OOM killer to\nterminate the container when the working set exceeds the limit. The\ncontainer will restart (RestartPolicy::ALWAYS) but in-flight queries\nfail. Surface this clearly in any UI that lets users set limits.","properties":{"cpu_shares":{"type":["integer","null"],"format":"int64","description":"Relative CPU weight (default 1024). Only used when `nano_cpus` is None."},"memory_mb":{"type":["integer","null"],"format":"int64","description":"Hard memory limit in MiB. None = unlimited."},"memory_swap_mb":{"type":["integer","null"],"format":"int64","description":"Memory + swap limit in MiB. None = unlimited.\nMUST be >= memory_mb when both are set; Docker rejects the request otherwise.\nSet equal to `memory_mb` to disable swap entirely."},"nano_cpus":{"type":["integer","null"],"format":"int64","description":"CPU quota in nano-cpus. 1_000_000_000 = 1 full CPU core. None = unlimited."},"shm_size_mb":{"type":["integer","null"],"format":"int64","description":"Shared memory (/dev/shm) size in MiB. None = Docker default (64 MiB).\nMaps to HostConfig.shm_size (bytes). PostgreSQL uses /dev/shm for parallel\nquery workers and large work_mem; the 64 MiB default causes \"could not\nresize shared memory segment ... No space left on device\" under load.\nNOTE: shm_size is fixed at container-create time — Docker's live update\nAPI cannot change it, so changing this value recreates the container."}}},"ServiceRuntimeReport":{"type":"object","description":"Aggregate runtime info for an external service. For standalone services,\n`members` has exactly one entry. For clusters, one entry per member.","required":["service_id","topology","members"],"properties":{"members":{"type":"array","items":{"$ref":"#/components/schemas/ContainerRuntimeInfo"}},"service_id":{"type":"integer","format":"int32"},"topology":{"type":"string"}}},"ServiceStatsReport":{"type":"object","required":["service_id","topology","members"],"properties":{"members":{"type":"array","items":{"$ref":"#/components/schemas/ContainerStatsSample"}},"service_id":{"type":"integer","format":"int32"},"topology":{"type":"string"}}},"ServiceTypeInfo":{"type":"object","required":["service_type","parameters"],"properties":{"parameters":{"type":"array","items":{"$ref":"#/components/schemas/ServiceParameter"},"example":"[{\"name\": \"host\", \"required\": true, \"encrypted\": false, \"description\": \"Database host\"}]"},"service_type":{"$ref":"#/components/schemas/ServiceTypeRoute"}}},"ServiceTypeRoute":{"type":"string","enum":["mariadb","mongodb","postgres","redis","s3","kv","blob","rustfs","minio"]},"ServiceUpdateAlertRuleRequest":{"type":"object","description":"Request body for updating an existing alert rule.\n\nDomain-prefixed schema name — see [`AlertRuleResponse`] for why.","properties":{"comparator":{"type":["string","null"]},"enabled":{"type":["boolean","null"]},"for_duration_secs":{"type":["integer","null"],"format":"int32"},"metric_name":{"type":["string","null"]},"name":{"type":["string","null"]},"severity":{"type":["string","null"]},"threshold":{"type":["number","null"],"format":"double"}}},"SesCredentialsRequest":{"type":"object","required":["access_key_id","secret_access_key"],"properties":{"access_key_id":{"type":"string","example":"AKIAIOSFODNN7EXAMPLE"},"secret_access_key":{"type":"string","example":"wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"}}},"SessionDetails":{"type":"object","required":["session_id","visitor_id","started_at","duration_seconds","is_bounced","is_engaged","page_views"],"properties":{"duration_seconds":{"type":"integer","format":"int64"},"ended_at":{"type":["string","null"],"format":"date-time","example":"2024-01-01T00:00:00"},"entry_path":{"type":["string","null"]},"exit_path":{"type":["string","null"]},"is_bounced":{"type":"boolean"},"is_engaged":{"type":"boolean"},"page_views":{"type":"integer","format":"int64"},"referrer":{"type":["string","null"]},"session_id":{"type":"integer","format":"int32"},"started_at":{"type":"string","format":"date-time","example":"2024-01-01T00:00:00"},"visitor_id":{"type":"string"}}},"SessionDetailsQuery":{"type":"object","required":["project_id"],"properties":{"environment_id":{"type":["integer","null"],"format":"int32"},"project_id":{"type":"integer","format":"int32"}}},"SessionEvent":{"type":"object","required":["id","timestamp"],"properties":{"event_data":{},"event_name":{"type":["string","null"]},"event_type":{"type":["string","null"]},"id":{"type":"integer","format":"int32"},"page_title":{"type":["string","null"]},"page_url":{"type":["string","null"]},"timestamp":{"type":"string"}}},"SessionEventDto":{"type":"object","required":["id","session_id","data","timestamp"],"properties":{"data":{},"event_type":{"type":["integer","null"],"format":"int32"},"id":{"type":"integer","format":"int32"},"session_id":{"type":"integer","format":"int32"},"timestamp":{"type":"integer","format":"int64"}}},"SessionEventsQuery":{"type":"object","required":["project_id"],"properties":{"environment_id":{"type":["integer","null"],"format":"int32"},"project_id":{"type":"integer","format":"int32"}}},"SessionEventsResponse":{"type":"object","required":["session_id","events","total_count","offset","limit"],"properties":{"events":{"type":"array","items":{"$ref":"#/components/schemas/SessionEvent"}},"limit":{"type":"integer","format":"int32"},"offset":{"type":"integer","format":"int32"},"session_id":{"type":"integer","format":"int32"},"total_count":{"type":"integer","format":"int64"}}},"SessionLogsQuery":{"type":"object","required":["project_id"],"properties":{"end_date":{"type":["string","null"],"format":"date-time"},"environment_id":{"type":["integer","null"],"format":"int32"},"limit":{"type":["integer","null"],"format":"int32"},"offset":{"type":["integer","null"],"format":"int32"},"project_id":{"type":"integer","format":"int32"},"sort_order":{"type":["string","null"]},"start_date":{"type":["string","null"],"format":"date-time"},"visitor_id":{"type":["integer","null"],"format":"int32"}}},"SessionLogsResponse":{"type":"object","required":["session_id","logs","total_count","offset","limit"],"properties":{"limit":{"type":"integer","format":"int32"},"logs":{"type":"array","items":{"$ref":"#/components/schemas/SessionRequestLog"}},"offset":{"type":"integer","format":"int32"},"session_id":{"type":"integer","format":"int32"},"total_count":{"type":"integer","format":"int64"}}},"SessionReplayEventsRequest":{"type":"object","required":["sessionId","events"],"properties":{"events":{"type":"string"},"sessionId":{"type":"string"}}},"SessionReplayInfoDto":{"type":"object","required":["id","visitor_id"],"properties":{"created_at":{"type":["string","null"]},"duration":{"type":["integer","null"],"format":"int32"},"id":{"type":"string"},"language":{"type":["string","null"]},"screen_height":{"type":["integer","null"],"format":"int32"},"screen_width":{"type":["integer","null"],"format":"int32"},"timezone":{"type":["string","null"]},"url":{"type":["string","null"]},"user_agent":{"type":["string","null"]},"viewport_height":{"type":["integer","null"],"format":"int32"},"viewport_width":{"type":["integer","null"],"format":"int32"},"visitor_id":{"type":"integer","format":"int32"}}},"SessionReplayInitRequest":{"type":"object","required":["sessionId"],"properties":{"colorDepth":{"type":["integer","null"],"format":"int32","minimum":0},"language":{"type":["string","null"]},"screenHeight":{"type":["integer","null"],"format":"int32","minimum":0},"screenWidth":{"type":["integer","null"],"format":"int32","minimum":0},"sessionId":{"type":"string"},"timestamp":{"type":["string","null"]},"timezone":{"type":["string","null"]},"url":{"type":["string","null"]},"userAgent":{"type":["string","null"]},"viewportHeight":{"type":["integer","null"],"format":"int32","minimum":0},"viewportWidth":{"type":["integer","null"],"format":"int32","minimum":0}}},"SessionReplayInitResponse":{"type":"object","required":["session_id","message"],"properties":{"message":{"type":"string"},"session_id":{"type":"string"}}},"SessionReplayWithEventsDto":{"type":"object","required":["session","events"],"properties":{"events":{"type":"array","items":{"$ref":"#/components/schemas/SessionEventDto"}},"session":{"$ref":"#/components/schemas/SessionReplayWithVisitorDto"}}},"SessionReplayWithVisitorDto":{"type":"object","required":["id","session_replay_id","visitor_id","visitor_uuid","visitor_project_id","visitor_environment_id","visitor_first_seen","visitor_last_seen","visitor_is_crawler"],"properties":{"browser":{"type":["string","null"]},"browser_version":{"type":["string","null"]},"created_at":{"type":["string","null"]},"device_type":{"type":["string","null"]},"duration":{"type":["integer","null"],"format":"int32"},"id":{"type":"integer","format":"int32"},"language":{"type":["string","null"]},"operating_system":{"type":["string","null"]},"operating_system_version":{"type":["string","null"]},"screen_height":{"type":["integer","null"],"format":"int32"},"screen_width":{"type":["integer","null"],"format":"int32"},"session_replay_id":{"type":"string"},"timezone":{"type":["string","null"]},"url":{"type":["string","null"]},"user_agent":{"type":["string","null"]},"viewport_height":{"type":["integer","null"],"format":"int32"},"viewport_width":{"type":["integer","null"],"format":"int32"},"visitor_city":{"type":["string","null"]},"visitor_country":{"type":["string","null"]},"visitor_country_code":{"type":["string","null"]},"visitor_crawler_name":{"type":["string","null"]},"visitor_custom_data":{},"visitor_environment_id":{"type":"integer","format":"int32"},"visitor_first_seen":{"type":"string"},"visitor_id":{"type":"integer","format":"int32"},"visitor_is_crawler":{"type":"boolean"},"visitor_last_seen":{"type":"string"},"visitor_project_id":{"type":"integer","format":"int32"},"visitor_region":{"type":["string","null"]},"visitor_uuid":{"type":"string"}}},"SessionRequestLog":{"type":"object","required":["id","method","path","status_code","created_at"],"properties":{"created_at":{"type":"string","format":"date-time","example":"2024-01-01T00:00:00"},"id":{"type":"integer","format":"int32"},"method":{"type":"string"},"path":{"type":"string"},"referrer":{"type":["string","null"]},"request_headers":{"type":["string","null"]},"response_headers":{"type":["string","null"]},"response_time_ms":{"type":["integer","null"],"format":"int32"},"status_code":{"type":"integer","format":"int32"},"user_agent":{"type":["string","null"]}}},"SessionSummary":{"type":"object","required":["session_id","started_at","duration_seconds","page_views","events_count","requests_count","is_bounced","is_engaged"],"properties":{"duration_seconds":{"type":"integer","format":"int64"},"ended_at":{"type":["string","null"],"format":"date-time","example":"2024-01-01T00:00:00"},"entry_path":{"type":["string","null"]},"events_count":{"type":"integer","format":"int64"},"exit_path":{"type":["string","null"]},"is_bounced":{"type":"boolean"},"is_engaged":{"type":"boolean"},"page_views":{"type":"integer","format":"int64"},"referrer":{"type":["string","null"]},"requests_count":{"type":"integer","format":"int64"},"session_id":{"type":"integer","format":"int32"},"started_at":{"type":"string","format":"date-time","example":"2024-01-01T00:00:00"}}},"SetFlagEnvironmentRequest":{"type":"object","properties":{"enabled":{"type":["boolean","null"],"description":"The kill switch. `false` makes the flag serve its default regardless of\nany override — and, once targeting exists, regardless of any rule."},"value":{"description":"Tri-state: absent leaves the override, `null` clears it (inherit the\nflag default), anything else sets it. Must match `value_type`."}}},"SetPreviewPasswordBody":{"type":"object","required":["password"],"properties":{"password":{"type":"string","description":"Plaintext password to protect the sandbox's preview URLs. Hashed\nserver-side with argon2id — we never persist or echo this back.\nMust be between 8 and 256 characters."}}},"SetPreviewPasswordResponse":{"type":"object","required":["preview_password_hint"],"properties":{"preview_password_hint":{"type":"string","description":"Last 4 chars of the password we just stored. Surface in the UI so\nusers can confirm which password is live without re-entering it."}}},"SetRequest":{"type":"object","description":"Request to set a value","required":["key","value"],"properties":{"ex":{"type":["integer","null"],"format":"int64","description":"Expire in seconds","example":3600},"key":{"type":"string","description":"The key to set","example":"user:123"},"nx":{"type":"boolean","description":"Only set if key does not exist"},"project_id":{"type":["integer","null"],"format":"int32","description":"Project ID (required for API key/session auth, optional for deployment tokens)","example":1},"px":{"type":["integer","null"],"format":"int64","description":"Expire in milliseconds"},"value":{"description":"The value to store (can be any JSON value)"},"xx":{"type":"boolean","description":"Only set if key exists"}}},"SetResponse":{"type":"object","description":"Response for set operation","required":["result"],"properties":{"result":{"type":"string","description":"Always \"OK\" on success","example":"OK"}}},"SettingsUpdateResponse":{"type":"object","description":"Response for successful settings update","required":["message"],"properties":{"message":{"type":"string"}}},"SetupDnsChallengeRequest":{"type":"object","description":"Request to setup DNS challenge records using a configured DNS provider","required":["dns_provider_id"],"properties":{"dns_provider_id":{"type":"integer","format":"int32","description":"The ID of the DNS provider to use for creating the TXT records"}}},"SetupDnsChallengeResponse":{"type":"object","description":"Response from DNS challenge setup operation","required":["success","records_created","total_records","results","message"],"properties":{"message":{"type":"string","description":"Human-readable summary message"},"records_created":{"type":"integer","format":"int32","description":"Number of TXT records that were successfully created","minimum":0},"results":{"type":"array","items":{"$ref":"#/components/schemas/DnsChallengeRecordResult"},"description":"Results for each individual TXT record"},"success":{"type":"boolean","description":"Overall success status (true if all records were created)"},"total_records":{"type":"integer","format":"int32","description":"Total number of TXT records required for the challenge","minimum":0}}},"SetupDnsRequest":{"type":"object","description":"Request to setup DNS records using a configured DNS provider","required":["dns_provider_id"],"properties":{"dns_provider_id":{"type":"integer","format":"int32","description":"The ID of the DNS provider to use for creating records"}}},"SetupDnsResponse":{"type":"object","description":"Response from DNS setup operation","required":["success","records_created","total_records","results","message"],"properties":{"message":{"type":"string","description":"Human-readable summary message"},"records_created":{"type":"integer","format":"int32","description":"Number of records that were successfully created","minimum":0},"results":{"type":"array","items":{"$ref":"#/components/schemas/DnsRecordSetupResult"},"description":"Results for each individual record"},"success":{"type":"boolean","description":"Overall success status"},"total_records":{"type":"integer","format":"int32","description":"Total number of records attempted","minimum":0}}},"SiblingRef":{"type":"object","description":"A sibling project that shares the same `trace_id` and has opted in to\ncross-project trace sharing (`cross_project_trace_sharing = TRUE`).\n\nReturned by `CrossProjectTraceService::find_sibling_projects` and exposed\nby the Phase 1 `GET /otel/traces/cross-project/{trace_id}` endpoint.","required":["project_id","project_name","project_slug","first_seen"],"properties":{"first_seen":{"type":"string","format":"date-time"},"project_id":{"type":"integer","format":"int32"},"project_name":{"type":"string"},"project_slug":{"type":"string","description":"URL slug used to link into the sibling project's single-project trace view."}}},"SkillDefinitionResponse":{"type":"object","required":["id","slug","name","content","has_archive","created_at","updated_at"],"properties":{"content":{"type":"string"},"created_at":{"type":"string"},"description":{"type":["string","null"]},"has_archive":{"type":"boolean"},"id":{"type":"integer","format":"int32"},"name":{"type":"string"},"project_id":{"type":["integer","null"],"format":"int32"},"slug":{"type":"string"},"updated_at":{"type":"string"}}},"SlackConfig":{"type":"object","required":["webhook_url"],"properties":{"channel":{"type":["string","null"]},"webhook_url":{"type":"string"}}},"SlowQueriesResponse":{"type":"object","description":"Response envelope for the slow-queries list endpoint.","required":["queries","page","page_size","total_count"],"properties":{"page":{"type":"integer","format":"int32","description":"Current page number (1-based).","minimum":0},"page_size":{"type":"integer","format":"int32","description":"Number of rows per page used for this request.","minimum":0},"queries":{"type":"array","items":{"$ref":"#/components/schemas/SlowQueryRow"},"description":"Ordered list of query stats, slowest first by mean_exec_time_ms."},"total_count":{"type":"integer","format":"int64","description":"Total number of qualifying rows across all pages.","minimum":0}}},"SlowQueryRow":{"type":"object","description":"A single entry from `pg_stat_statements`, representing one normalized\nquery fingerprint and its aggregate execution stats.","required":["query","database","calls","total_exec_time_ms","mean_exec_time_ms","rows"],"properties":{"cache_hit_ratio":{"type":["number","null"],"format":"double","description":"Shared block cache hit ratio (0.0–1.0).\n`None` when total block accesses are zero (e.g. function-only queries)."},"calls":{"type":"integer","format":"int64","description":"Number of times this query was executed."},"database":{"type":"string","description":"Name of the database this query ran against. `(dropped database)`\nwhen the originating database no longer exists but\n`pg_stat_statements` still holds stats for it."},"mean_exec_time_ms":{"type":"number","format":"double","description":"Average wall-clock time per execution, in milliseconds."},"query":{"type":"string","description":"Normalized query text (parameter literals replaced with `$N`)."},"rows":{"type":"integer","format":"int64","description":"Total number of rows returned or affected."},"total_exec_time_ms":{"type":"number","format":"double","description":"Total wall-clock time spent executing this query, in milliseconds."}}},"SmartFilter":{"oneOf":[{"type":"object","description":"Match specific page path","required":["value","type"],"properties":{"type":{"type":"string","enum":["page_path"]},"value":{"type":"string","description":"Match specific page path"}}},{"type":"object","description":"Match specific hostname","required":["value","type"],"properties":{"type":{"type":"string","enum":["hostname"]},"value":{"type":"string","description":"Match specific hostname"}}},{"type":"object","description":"Match UTM source","required":["value","type"],"properties":{"type":{"type":"string","enum":["utm_source"]},"value":{"type":"string","description":"Match UTM source"}}},{"type":"object","description":"Match UTM campaign","required":["value","type"],"properties":{"type":{"type":"string","enum":["utm_campaign"]},"value":{"type":"string","description":"Match UTM campaign"}}},{"type":"object","description":"Match UTM medium","required":["value","type"],"properties":{"type":{"type":"string","enum":["utm_medium"]},"value":{"type":"string","description":"Match UTM medium"}}},{"type":"object","description":"Match referrer hostname","required":["value","type"],"properties":{"type":{"type":"string","enum":["referrer_hostname"]},"value":{"type":"string","description":"Match referrer hostname"}}},{"type":"object","description":"Match specific channel (organic, paid, direct, referral, etc.)","required":["value","type"],"properties":{"type":{"type":"string","enum":["channel"]},"value":{"type":"string","description":"Match specific channel (organic, paid, direct, referral, etc.)"}}},{"type":"object","description":"Match device type (mobile, desktop, tablet)","required":["value","type"],"properties":{"type":{"type":"string","enum":["device_type"]},"value":{"type":"string","description":"Match device type (mobile, desktop, tablet)"}}},{"type":"object","description":"Match browser","required":["value","type"],"properties":{"type":{"type":"string","enum":["browser"]},"value":{"type":"string","description":"Match browser"}}},{"type":"object","description":"Match operating system","required":["value","type"],"properties":{"type":{"type":"string","enum":["operating_system"]},"value":{"type":"string","description":"Match operating system"}}},{"type":"object","description":"Match language","required":["value","type"],"properties":{"type":{"type":"string","enum":["language"]},"value":{"type":"string","description":"Match language"}}},{"type":"object","description":"Match custom event_data by JSON path\nFormat: {\"path\": \"user.plan\", \"value\": \"premium\"}\nThis will match events where event_data->'user'->>'plan' = 'premium'","required":["value","type"],"properties":{"type":{"type":"string","enum":["custom_data"]},"value":{"type":"object","description":"Match custom event_data by JSON path\nFormat: {\"path\": \"user.plan\", \"value\": \"premium\"}\nThis will match events where event_data->'user'->>'plan' = 'premium'","required":["path","value"],"properties":{"path":{"type":"string"},"value":{"type":"string"}}}}}],"description":"Smart filter presets for common funnel patterns"},"SmokeTestResponse":{"type":"object","required":["passed","environment","cli_installed","cli_authenticated"],"properties":{"auth_info":{"type":["string","null"],"description":"Auth email / method"},"cli_authenticated":{"type":"boolean","description":"Claude CLI authenticated?"},"cli_installed":{"type":"boolean","description":"Claude CLI installed?"},"cli_version":{"type":["string","null"],"description":"Claude CLI version"},"detail":{"type":["string","null"],"description":"Full output for debugging"},"environment":{"type":"string","description":"Where the test ran: \"host\" or \"sandbox\""},"passed":{"type":"boolean","description":"Whether the smoke test passed"},"setup_hint":{"type":["string","null"],"description":"What the user needs to do if the test failed"}}},"SmtpCredentialsRequest":{"type":"object","description":"Generic SMTP credentials request body.\n\nWorks with any SMTP relay — AWS SES SMTP endpoints, Sendgrid, Mailgun,\nPostmark, or a self-hosted Postfix. Use this when you only have SMTP\ncredentials (i.e. you cannot create identities via the upstream API).","required":["host","port"],"properties":{"accept_invalid_certs":{"type":"boolean","description":"Accept self-signed certificates. Only safe for local testing."},"encryption":{"$ref":"#/components/schemas/SmtpEncryptionRoute","description":"TLS mode. Defaults to STARTTLS."},"host":{"type":"string","description":"SMTP host, e.g. `email-smtp.eu-west-1.amazonaws.com`.","example":"email-smtp.eu-west-1.amazonaws.com"},"password":{"type":["string","null"],"description":"SMTP password / API token. Required when `username` is set."},"port":{"type":"integer","format":"int32","description":"SMTP port (587 for STARTTLS, 465 for implicit TLS, 25/1025 for plain).","example":587,"minimum":0},"username":{"type":["string","null"],"description":"SMTP username. Leave empty for unauthenticated relays.","example":"AKIAIOSFODNN7EXAMPLE"}}},"SmtpEncryptionRoute":{"type":"string","description":"TLS mode for the SMTP relay.","enum":["starttls","tls","none"]},"SmtpResult":{"type":"object","description":"SMTP validation result","required":["can_connect_smtp","has_full_inbox","is_catch_all","is_deliverable","is_disabled"],"properties":{"can_connect_smtp":{"type":"boolean","description":"Whether we could connect to the SMTP server"},"error":{"type":["string","null"],"description":"Error message if SMTP check failed"},"has_full_inbox":{"type":"boolean","description":"Whether the mailbox appears to have a full inbox"},"is_catch_all":{"type":"boolean","description":"Whether this is a catch-all domain"},"is_deliverable":{"type":"boolean","description":"Whether the email is deliverable"},"is_disabled":{"type":"boolean","description":"Whether the mailbox is disabled"}}},"SourceArchiveUpload":{"type":"object","required":["file"],"properties":{"file":{"type":"string","format":"binary"}}},"SourceBackupEntry":{"type":"object","description":"Entry in the source backup index. Covers both DB-tracked backups\n(have a row in `backups`) and S3-scan discoveries (raw S3 objects with\nno DB row — used for disaster-recovery from another Temps instance).","required":["id","backup_id","name","backup_type","created_at","location","metadata_location","source","state"],"properties":{"backup_id":{"type":"string","description":"UUID identifier from the DB row. Empty for S3-scan entries.","example":"550e8400-e29b-41d4-a716-446655440000"},"backup_type":{"type":"string","description":"Backup variant as recorded by the backup pipeline (e.g. \"full\").","example":"full"},"created_at":{"type":"string","description":"When the backup was created. For S3-scan entries this is the\nobject's LastModified time.","example":"2024-01-15T14:30:00.123Z"},"engine":{"type":["string","null"],"description":"Engine that produced the backup (\"postgres\", \"redis\", \"mongodb\",\n\"s3\", \"rustfs\"). Used by the UI to mark engine-compat with the\ntarget service.","example":"postgres"},"format":{"type":["string","null"],"description":"Storage format: \"walg\" for continuous-archive (PITR-capable),\n\"pg_dump\" for point-in-time dumps, \"\" for non-postgres.","example":"walg"},"id":{"type":"integer","format":"int32","description":"DB row id. Zero for S3-scan entries that have no DB row.","example":1},"location":{"type":"string","description":"Raw S3 URL / key where the backup sits. For Postgres WAL-G backups\nthis starts with `s3://`; for pg_dump-style backups it's the\nrelative object key.","example":"s3://bucket/external_services/postgres/svc-name/walg"},"metadata_location":{"type":"string","description":"Sidecar metadata.json location, if any. Empty when none.","example":""},"name":{"type":"string","description":"Human-friendly display name (\"postgres backup (svc-name)\" for DB\nrows, or a synthesized label derived from the S3 path for scans).","example":"postgres backup (postgres-n4ea)"},"origin_service_name":{"type":["string","null"],"description":"Name of the service that produced the backup. For S3-scan entries\nthis is parsed from the S3 path.","example":"postgres-n4ea"},"size_bytes":{"type":["integer","null"],"format":"int64","description":"Size of the backup in bytes, if known.","example":1024000},"source":{"type":"string","description":"Provenance: \"db\" for rows in this Temps, \"s3_scan\" for objects\ndiscovered by the S3 bucket walk (e.g., backups made by another\nTemps instance).","example":"db"},"state":{"type":"string","description":"Observed state (\"completed\", \"running\", \"failed\") — DB only.\nEmpty string for S3-scan entries.","example":"completed"}}},"SourceBackupIndexResponse":{"type":"object","description":"Response type for source backup index","required":["backups","last_updated"],"properties":{"backups":{"type":"array","items":{"$ref":"#/components/schemas/SourceBackupEntry"},"description":"List of backups in the source"},"last_updated":{"type":"string","description":"When the index was last updated","example":"2024-01-15T14:30:00.123Z"}}},"SourceBody":{"oneOf":[{"type":"object","required":["url","type"],"properties":{"depth":{"type":["integer","null"],"format":"int32","minimum":0},"git_connection_id":{"type":["integer","null"],"format":"int32"},"password":{"type":["string","null"]},"revision":{"type":["string","null"]},"type":{"type":"string","enum":["git"]},"url":{"type":"string"},"username":{"type":["string","null"]}}},{"type":"object","required":["url","type"],"properties":{"type":{"type":"string","enum":["tarball"]},"url":{"type":"string"}}}],"description":"Initial content to seed into the sandbox work dir. Mirrors the\n`@vercel/sandbox` `source` option. `type` is one of:\n- `git` — clone `url`; optionally check out `revision`\n- `tarball` — download `url` (must be tar or tar.gz) and extract\n\nFor private git repos, pass credentials one of two ways:\n1. **Inline (SDK-compatible):** `username` + `password`. GitHub\n tokens use `username: \"x-access-token\"`.\n2. **Stored connection (temps-native):** `git_connection_id`\n references a row in the caller's git provider connections. Temps\n resolves the token server-side and injects it safely.\n\n`git_connection_id` is mutually exclusive with `username`/`password`."},"SourceFileListResponse":{"type":"object","required":["source_files","total"],"properties":{"source_files":{"type":"array","items":{"$ref":"#/components/schemas/SourceFileResponse"}},"total":{"type":"integer","minimum":0}}},"SourceFileResponse":{"type":"object","required":["id","project_id","release","file_path","size_bytes","created_at"],"properties":{"checksum":{"type":["string","null"]},"created_at":{"type":"string","example":"2025-10-12T12:15:47.609192Z"},"file_path":{"type":"string"},"id":{"type":"integer","format":"int32"},"project_id":{"type":"integer","format":"int32"},"release":{"type":"string"},"size_bytes":{"type":"integer","format":"int64"}}},"SourceMapListResponse":{"type":"object","required":["source_maps","total"],"properties":{"source_maps":{"type":"array","items":{"$ref":"#/components/schemas/SourceMapResponse"}},"total":{"type":"integer","minimum":0}}},"SourceMapResponse":{"type":"object","required":["id","project_id","release","file_path","size_bytes","created_at"],"properties":{"checksum":{"type":["string","null"]},"created_at":{"type":"string","example":"2025-10-12T12:15:47.609192Z"},"dist":{"type":["string","null"]},"file_path":{"type":"string"},"id":{"type":"integer","format":"int32"},"project_id":{"type":"integer","format":"int32"},"release":{"type":"string"},"size_bytes":{"type":"integer","format":"int64"}}},"SourceType":{"type":"string","description":"Source type for project deployments\n\nDetermines where the deployment artifacts come from:\n- `Git`: Source code from a Git repository (traditional flow)\n- `DockerImage`: Pre-built Docker image from external registry\n- `StaticFiles`: Pre-built static files uploaded as a bundle\n- `UploadedSource`: Source archive uploaded without a Git repository\n- `Manual`: Flexible type that accepts any deployment method","enum":["git","docker_image","static_files","uploaded_source","manual"]},"SpanEvent":{"type":"object","description":"A span event (log-like annotation on a span).","required":["timestamp","name","attributes"],"properties":{"attributes":{"type":"object","additionalProperties":{"type":"string"},"propertyNames":{"type":"string"}},"name":{"type":"string"},"timestamp":{"type":"string","format":"date-time"}}},"SpanKind":{"type":"string","description":"Span kind.","enum":["UNSPECIFIED","INTERNAL","SERVER","CLIENT","PRODUCER","CONSUMER"]},"SpanRecord":{"type":"object","description":"A single trace span ready for storage.","required":["project_id","resource","trace_id","span_id","name","kind","start_time","end_time","duration_ms","status_code","status_message","attributes","events"],"properties":{"attributes":{"type":"object","description":"Raw key/value pairs exactly as reported by the instrumenting library.\nNumeric values are NOT guaranteed to share `duration_ms`'s unit — they\nmay be seconds, milliseconds, microseconds, or nanoseconds depending on\nthe exporter's own convention, and the unit is not labeled here.","additionalProperties":{"type":"string"},"propertyNames":{"type":"string"}},"deployment_id":{"type":["integer","null"],"format":"int32"},"duration_ms":{"type":"number","format":"double","description":"Span duration in milliseconds. The only field on this struct guaranteed\nto be in milliseconds."},"end_time":{"type":"string","format":"date-time"},"events":{"type":"array","items":{"$ref":"#/components/schemas/SpanEvent"}},"kind":{"$ref":"#/components/schemas/SpanKind"},"name":{"type":"string"},"parent_span_id":{"type":["string","null"]},"project_id":{"type":"integer","format":"int32"},"resource":{"$ref":"#/components/schemas/ResourceInfo"},"span_id":{"type":"string"},"start_time":{"type":"string","format":"date-time"},"status_code":{"$ref":"#/components/schemas/SpanStatusCode"},"status_message":{"type":"string"},"trace_id":{"type":"string"}}},"SpanRow":{"type":"object","required":["id","ts","trace_id","span_id","service","operation","attributes","attributes_truncated"],"properties":{"attributes":{},"attributes_truncated":{"type":"boolean"},"deployment_id":{"type":["integer","null"],"format":"int32"},"duration_ms":{"type":["number","null"],"format":"double"},"environment_id":{"type":["integer","null"],"format":"int32"},"id":{"type":"string"},"operation":{"type":"string"},"parent_span_id":{"type":["string","null"]},"service":{"type":"string"},"span_id":{"type":"string"},"status":{"type":["string","null"]},"trace_id":{"type":"string"},"ts":{"type":"string","format":"date-time"}}},"SpanStatusCode":{"type":"string","description":"Span status code.","enum":["UNSET","OK","ERROR"]},"SpeedMetricsPayload":{"type":"object","description":"Speed metrics payload for recording web vitals","properties":{"cls":{"type":["number","null"],"format":"float","description":"Cumulative Layout Shift (score)"},"fcp":{"type":["number","null"],"format":"float","description":"First Contentful Paint (milliseconds)"},"fid":{"type":["number","null"],"format":"float","description":"First Input Delay (milliseconds)"},"inp":{"type":["number","null"],"format":"float","description":"Interaction to Next Paint (milliseconds)"},"language":{"type":["string","null"],"description":"Browser language"},"lcp":{"type":["number","null"],"format":"float","description":"Largest Contentful Paint (milliseconds)"},"pathname":{"type":["string","null"],"description":"Page pathname"},"query":{"type":["string","null"],"description":"Query string"},"screenHeight":{"type":["integer","null"],"format":"int32","description":"Screen height in pixels"},"screenWidth":{"type":["integer","null"],"format":"int32","description":"Screen width in pixels"},"ttfb":{"type":["number","null"],"format":"float","description":"Time to First Byte (milliseconds)"},"viewportHeight":{"type":["integer","null"],"format":"int32","description":"Viewport height in pixels"},"viewportWidth":{"type":["integer","null"],"format":"int32","description":"Viewport width in pixels"}}},"SpeedSegmentFilters":{"type":"object","description":"Optional segment filters for the performance read endpoints, mirroring\nanalytics' `VisitorSegmentFilters`. Each filter narrows results to samples\nmatching the dimension value, so metrics can be scoped to e.g. one page,\none browser, or one country. Geographic filters resolve via\n`ip_geolocations`; the rest live directly on `performance_metrics`.","properties":{"filter_browser":{"type":["string","null"],"description":"Browser name (matches `performance_metrics.browser`)"},"filter_city":{"type":["string","null"],"description":"Geolocation city (matches `ip_geolocations.city`)"},"filter_country":{"type":["string","null"],"description":"Geolocation country (matches `ip_geolocations.country`)"},"filter_operating_system":{"type":["string","null"],"description":"Operating system (matches `performance_metrics.operating_system`)"},"filter_path":{"type":["string","null"],"description":"Page pathname (matches `performance_metrics.pathname`)"},"filter_region":{"type":["string","null"],"description":"Geolocation region (matches `ip_geolocations.region`)"}}},"StaleSlot":{"type":"object","required":["slot_name","active","retained_bytes"],"properties":{"active":{"type":"boolean"},"retained_bytes":{"type":"integer","format":"int64"},"slot_name":{"type":"string"}}},"StartAnalysisRequest":{"type":"object","required":["error_group_id"],"properties":{"branch":{"type":["string","null"],"description":"Branch to clone instead of the project's main branch."},"error_group_id":{"type":"integer","format":"int32"},"max_turns":{"type":["integer","null"],"format":"int32","description":"Per-run turn cap applied to every phase (1–200). Only enforced for\nCLIs with a turn flag (Claude Code). `None` uses the provider's\nconfigured defaults."},"model":{"type":["string","null"],"description":"Model id for the chosen provider. `None` uses the provider's saved\ndefault model."},"provider":{"type":["string","null"],"description":"AI provider id (\"claude_cli\", \"codex_cli\", \"opencode\"). `None` uses\nthe platform default provider."},"user_context":{"type":["string","null"],"description":"Free-text notes for the model (extra context about the error, retry\nguidance, constraints). Included verbatim in the analysis prompt."}}},"StartPgUpgradeRequest":{"type":"object","required":["from_version","to_version","from_image","to_image"],"properties":{"from_image":{"type":"string","example":"postgres:16-bookworm"},"from_version":{"type":"string","example":"16"},"to_image":{"type":"string","example":"postgres:17-bookworm"},"to_version":{"type":"string","example":"17"}}},"StartRestoreRequest":{"allOf":[{"$ref":"#/components/schemas/RestoreRequestMode","description":"Requested restore mode. See `RestoreRequestMode`."},{"type":"object","properties":{"backup_engine":{"type":["string","null"],"description":"Engine of the backup when specified by `backup_location`\n(\"postgres\", \"redis\", \"mongodb\", \"s3\"). Ignored when `backup_id`\nis used — we infer from the DB row."},"backup_id":{"type":["integer","null"],"format":"int32","description":"DB id of the backup to restore from. Either `backup_id` or\n`backup_location` MUST be provided. Use `backup_id` when restoring\na backup this Temps instance recorded."},"backup_location":{"type":["string","null"],"description":"Raw S3 URL / key of the backup — used when restoring a backup\ndiscovered by S3 scan (i.e., produced by another Temps instance).\nRequires `backup_engine` and `s3_source_id` to also be set."},"s3_source_id":{"type":["integer","null"],"format":"int32","description":"S3 source the `backup_location` lives in. Ignored when `backup_id`\nis used."}}}]},"StatResponse":{"type":"object","required":["path","exists","is_dir","is_file","size"],"properties":{"exists":{"type":"boolean"},"is_dir":{"type":"boolean"},"is_file":{"type":"boolean"},"path":{"type":"string"},"size":{"type":"integer","format":"int64","minimum":0}}},"StaticBundleResponse":{"type":"object","required":["id","project_id","blob_path","content_type","size_bytes","uploaded_at","created_at"],"properties":{"blob_path":{"type":"string"},"checksum":{"type":["string","null"]},"content_type":{"type":"string"},"created_at":{"type":"string","format":"date-time","example":"2025-10-12T12:15:47.609192Z"},"format":{"type":["string","null"]},"id":{"type":"integer","format":"int32"},"metadata":{},"original_filename":{"type":["string","null"]},"project_id":{"type":"integer","format":"int32"},"size_bytes":{"type":"integer","format":"int64"},"uploaded_at":{"type":"string","format":"date-time","example":"2025-10-12T12:15:47.609192Z"}}},"StaticParams":{"type":"object","description":"Static threshold detector: compare the aggregated `value` against `threshold`.","required":["comparator","threshold"],"properties":{"comparator":{"$ref":"#/components/schemas/Comparator","description":"How `value` is compared against `threshold`."},"threshold":{"type":"number","format":"double","description":"The threshold the aggregated value is compared against."}}},"StaticPresetConfig":{"type":"object","description":"Configuration for static site presets (Vite, Next.js, Docusaurus, etc.)\nThese presets build static sites that are served via a web server","properties":{"buildCommand":{"type":["string","null"],"description":"Custom build command (overrides preset default)","example":"npm run build:production"},"buildContext":{"type":["string","null"],"description":"Custom build context path (relative to repository root)\nUseful for monorepo setups where the app is in a subdirectory","example":"./apps/frontend"},"installCommand":{"type":["string","null"],"description":"Custom install command (overrides auto-detected package manager)","example":"npm ci"},"outputDir":{"type":["string","null"],"description":"Custom output directory (overrides preset default)\nCommon values: \"dist\", \"build\", \".next\", \"out\"","example":"dist"}}},"StatsFilters":{"type":"object","description":"Filters for statistics queries","properties":{"client_ip":{"type":["string","null"]},"deployment_id":{"type":["integer","null"],"format":"int32"},"device_type":{"type":["string","null"]},"environment_id":{"type":["integer","null"],"format":"int32"},"has_project":{"type":["boolean","null"],"description":"When true, only count requests that matched a project (project_id IS NOT NULL).\nUsed by the health dashboard so totals match the per-project cards."},"host":{"type":["string","null"]},"is_bot":{"type":["boolean","null"]},"method":{"type":["string","null"]},"project_id":{"type":["integer","null"],"format":"int32"},"request_source":{"type":["string","null"]},"routing_status":{"type":["string","null"]},"status_code":{"type":["integer","null"],"format":"int32"},"status_code_class":{"type":["string","null"],"description":"Filter by status code class (e.g. \"2xx\", \"3xx\", \"4xx\", \"5xx\")"}}},"StatusBucket":{"type":"object","required":["bucket_start","status","total_checks","operational_count","degraded_count","down_count","uptime_percentage"],"properties":{"avg_response_time_ms":{"type":["number","null"],"format":"double"},"bucket_start":{"type":"string","format":"date-time"},"degraded_count":{"type":"integer","format":"int64"},"down_count":{"type":"integer","format":"int64"},"max_response_time_ms":{"type":["number","null"],"format":"double"},"min_response_time_ms":{"type":["number","null"],"format":"double"},"operational_count":{"type":"integer","format":"int64"},"p50_response_time_ms":{"type":["number","null"],"format":"double"},"p95_response_time_ms":{"type":["number","null"],"format":"double"},"p99_response_time_ms":{"type":["number","null"],"format":"double"},"status":{"type":"string"},"total_checks":{"type":"integer","format":"int64"},"uptime_percentage":{"type":"number","format":"double"}}},"StatusBucketedResponse":{"type":"object","required":["monitor_id","interval","buckets"],"properties":{"buckets":{"type":"array","items":{"$ref":"#/components/schemas/StatusBucket"}},"interval":{"type":"string"},"monitor_id":{"type":"integer","format":"int32"}}},"StatusCodeCount":{"type":"object","required":["status_code","count","percentage"],"properties":{"count":{"type":"integer","format":"int64"},"percentage":{"type":"number","format":"double"},"status_code":{"type":"integer","format":"int32"}}},"StatusCodesQuery":{"type":"object","required":["start_date","end_date","project_id"],"properties":{"deployment_id":{"type":["integer","null"],"format":"int32"},"end_date":{"type":"string","format":"date-time"},"environment_id":{"type":["integer","null"],"format":"int32"},"limit":{"type":["integer","null"],"format":"int32"},"project_id":{"type":"integer","format":"int32"},"start_date":{"type":"string","format":"date-time"}}},"StatusPageOverview":{"type":"object","required":["status","monitors","recent_incidents"],"properties":{"monitors":{"type":"array","items":{"$ref":"#/components/schemas/MonitorStatus"}},"recent_incidents":{"type":"array","items":{"$ref":"#/components/schemas/IncidentResponse"}},"status":{"type":"string"}}},"StepConversionResponse":{"type":"object","required":["step_id","step_name","step_order","completions","conversion_rate","drop_off_rate","average_time_to_complete_seconds"],"properties":{"average_time_to_complete_seconds":{"type":"number","format":"double"},"completions":{"type":"integer","format":"int64","minimum":0},"conversion_rate":{"type":"number","format":"double"},"drop_off_rate":{"type":"number","format":"double"},"step_id":{"type":"integer","format":"int32"},"step_name":{"type":"string"},"step_order":{"type":"integer","format":"int32"}}},"StepResourceType":{"type":"string","description":"What kind of resource a migration step operates on","enum":["project","environment","deployment","environment-variable","service","domain","git-link","other"]},"StepResult":{"type":"object","description":"Result of executing a single migration step","required":["step_id","step_title","success","skipped","message","created_resources","duration_seconds"],"properties":{"created_resources":{"type":"array","items":{"$ref":"#/components/schemas/CreatedResource"},"description":"Resources created by this step"},"duration_seconds":{"type":"number","format":"double","description":"Duration of this step"},"message":{"type":"string","description":"Human-readable message about what happened"},"skipped":{"type":"boolean","description":"Whether this step was skipped"},"step_id":{"type":"string","description":"Step ID (matches `MigrationStep.id`)"},"step_title":{"type":"string","description":"Step title (for display)"},"success":{"type":"boolean","description":"Whether this step succeeded"}}},"StepUpResponse":{"type":"object","required":["expires_at"],"properties":{"expires_at":{"type":"string","format":"date-time","description":"ISO 8601 timestamp after which sensitive actions require verification\nagain."}}},"StopSequence":{"oneOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}]},"StorageQuota":{"type":"object","description":"Quota usage information for a project.","required":["project_id","metrics_bytes","traces_bytes","logs_bytes","total_bytes","limit_bytes","usage_pct"],"properties":{"limit_bytes":{"type":"integer","format":"int64","minimum":0},"logs_bytes":{"type":"integer","format":"int64","minimum":0},"metrics_bytes":{"type":"integer","format":"int64","minimum":0},"project_id":{"type":"integer","format":"int32"},"total_bytes":{"type":"integer","format":"int64","minimum":0},"traces_bytes":{"type":"integer","format":"int64","minimum":0},"usage_pct":{"type":"number","format":"double"}}},"StripeConfig":{"type":"object","properties":{"include_unpriced_charges":{"type":"boolean","description":"When an allowlist is set, should we still ingest charges that\nlack a price reference (e.g. standalone `charge.succeeded` without\na subscription)? Default true — charges don't belong to a SKU."},"metered_mode":{"$ref":"#/components/schemas/MeteredMode","description":"How to compute MRR for metered / tiered / hybrid subscriptions."},"price_allowlist":{"type":"array","items":{"type":"string"},"description":"Only events tagged with one of these Stripe price IDs are ingested.\nEmpty = accept all prices."},"product_allowlist":{"type":"array","items":{"type":"string"},"description":"Only events tagged with one of these Stripe product IDs are\ningested. Empty = accept all products. Combined with\n`price_allowlist` via OR — if either list has a match, accept."}}},"SyncedRepositoryListQuery":{"type":"object","properties":{"direction":{"type":["string","null"]},"git_provider_connection_id":{"type":["integer","null"],"format":"int32"},"language":{"type":["string","null"]},"owner":{"type":["string","null"]},"page":{"type":["integer","null"],"format":"int64","minimum":0},"per_page":{"type":["integer","null"],"format":"int64","minimum":0},"private":{"type":["boolean","null"]},"search":{"type":["string","null"]},"sort":{"type":["string","null"]}}},"SyntaxResult":{"type":"object","description":"Syntax validation result","required":["is_valid_syntax"],"properties":{"domain":{"type":["string","null"],"description":"The domain part of the email","example":"gmail.com"},"is_valid_syntax":{"type":"boolean","description":"Whether the email syntax is valid"},"suggestion":{"type":["string","null"],"description":"Suggested email correction if available"},"username":{"type":["string","null"],"description":"The username part of the email","example":"someone"}}},"TagInfo":{"type":"object","required":["name","commit_sha"],"properties":{"commit_sha":{"type":"string"},"name":{"type":"string"}}},"TagListResponse":{"type":"object","required":["tags"],"properties":{"tags":{"type":"array","items":{"$ref":"#/components/schemas/TagInfo"}}}},"TailLogsRequest":{"type":"object","required":["project_id","service","env"],"properties":{"env":{"type":"string"},"external_service_id":{"type":["integer","null"],"format":"int32","description":"When set, tail an imported/managed external service's logs instead of\na project's (`project_id` is ignored in this mode)."},"levels":{"type":"array","items":{"type":"string"}},"project_id":{"type":"integer","format":"int32","description":"Project ID (integer, as used by the rest of the platform)"},"service":{"type":"string"},"text":{"type":["string","null"]}}},"TargetRecommendation":{"type":"object","description":"The temps/Hetzner target sizing and savings estimate","required":["server_type","vcpus","memory_gb","monthly_eur","fits_single_node","sizing_basis","rationale"],"properties":{"fits_single_node":{"type":"boolean","description":"Whether the workloads fit a single recommended server. When `false`,\nthe rationale explains the multi-node option (temps worker nodes)."},"memory_gb":{"type":"integer","format":"int32","description":"Memory (GB) of the recommended server"},"monthly_eur":{"type":"number","format":"double","description":"Estimated monthly price of the recommended server in EUR"},"monthly_savings_usd":{"type":["number","null"],"format":"double","description":"Estimated monthly savings in USD (current cost minus target cost,\ntreating EUR≈USD for the rough comparison — disclaimed in `notes`).\n`None` when the current cost is unknown."},"rationale":{"type":"string","description":"Human-readable recommendation summary"},"server_type":{"type":"string","description":"Recommended Hetzner server type (e.g. \"cpx32\")"},"sizing_basis":{"type":"string","description":"What the sizing was based on, e.g. \"2× measured usage + temps\nplatform overhead\" or \"resource requests (no metrics available)\""},"vcpus":{"type":"integer","format":"int32","description":"vCPUs of the recommended server"},"yearly_savings_usd":{"type":["number","null"],"format":"double","description":"`monthly_savings_usd × 12`"}}},"TeamListResponse":{"type":"object","required":["teams","total","page","page_size"],"properties":{"page":{"type":"integer","format":"int64","minimum":0},"page_size":{"type":"integer","format":"int64","minimum":0},"teams":{"type":"array","items":{"$ref":"#/components/schemas/TeamResponse"}},"total":{"type":"integer","format":"int64","minimum":0}}},"TeamMemberResponse":{"type":"object","required":["id","team_id","user_id","role","added_by","created_at","updated_at"],"properties":{"added_by":{"type":"integer","format":"int32"},"created_at":{"type":"string","format":"date-time","example":"2026-07-30T12:15:47.609192Z"},"id":{"type":"integer","format":"int32"},"role":{"$ref":"#/components/schemas/TeamRole","description":"The source of this member's project-scoped permissions, intersected\nwith `project_team_access.role`."},"team_id":{"type":"integer","format":"int32"},"updated_at":{"type":"string","format":"date-time","example":"2026-07-30T12:15:47.609192Z"},"user_email":{"type":["string","null"],"description":"The member's email, joined from `users`."},"user_id":{"type":"integer","format":"int32"},"user_name":{"type":["string","null"],"description":"The member's display name, joined from `users`. `None` if the\nreferenced user no longer exists."}}},"TeamResponse":{"type":"object","required":["id","name","slug","created_by","created_at","updated_at"],"properties":{"created_at":{"type":"string","format":"date-time","example":"2026-07-30T12:15:47.609192Z"},"created_by":{"type":"integer","format":"int32"},"description":{"type":["string","null"]},"id":{"type":"integer","format":"int32"},"name":{"type":"string"},"slug":{"type":"string"},"updated_at":{"type":"string","format":"date-time","example":"2026-07-30T12:15:47.609192Z"}}},"TeamRole":{"type":"string","description":"Role a user holds within a team, or that a team holds on a project.\n\nNamed `TeamRole` rather than `Role` to keep it distinct from\n`temps_auth::permissions::Role`, which is the instance-wide role\n(Admin/User/…) attached to a session. The two are orthogonal: the\ninstance-wide role decides whether you may touch a resource *kind* at\nall, `TeamRole` decides what you may do *within a project* you have\nteam access to. See `temps_teams::fixed_role_permissions` for the\nproject-scoped permission set each variant maps to.\n\nStored as a `varchar(32)` rather than a Postgres enum so the role set\ncan evolve in pure migration code without a schema-level enum\nalteration blocking a downgrade.","enum":["owner","admin","deployer","viewer"]},"TemplateResponse":{"type":"object","description":"Response type for a single template","required":["slug","name","git","preset","tags","features","services","env_vars","is_featured"],"properties":{"description":{"type":["string","null"],"description":"Short description"},"env_vars":{"type":"array","items":{"$ref":"#/components/schemas/EnvVarTemplateResponse"},"description":"Environment variables template"},"exposed_port":{"type":["integer","null"],"format":"int32","description":"Container port the prebuilt image listens on (image deploys only)."},"features":{"type":"array","items":{"type":"string"},"description":"Feature highlights"},"git":{"$ref":"#/components/schemas/GitRefResponse","description":"Git repository reference"},"health_check_path":{"type":["string","null"],"description":"HTTP health-check path probed after the container starts (image deploys)."},"image":{"type":["string","null"],"description":"Prebuilt Docker image reference. When set, the one-click deploy pulls and\nruns this image directly (no build); when absent it builds from `git`."},"image_url":{"type":["string","null"],"description":"URL to template image/icon"},"is_featured":{"type":"boolean","description":"Whether the template is featured/promoted"},"name":{"type":"string","description":"Display name"},"preset":{"type":"string","description":"Framework/preset to use"},"screenshot_url":{"type":["string","null"],"description":"URL to a wide screenshot/banner preview of the deployed template.\nAbsent for templates that don't have one captured yet."},"services":{"type":"array","items":{"type":"string"},"description":"Required external services"},"slug":{"type":"string","description":"Unique identifier for the template (used in URLs)"},"tags":{"type":"array","items":{"type":"string"},"description":"Tags/categories for filtering"}}},"TestEmailRequest":{"type":"object","description":"Request body for testing an email provider","required":["from"],"properties":{"from":{"type":"string","description":"Sender email address (must be verified with the provider)","example":"test@example.com"},"from_name":{"type":["string","null"],"description":"Sender display name","example":"My App"}}},"TestEmailResponse":{"type":"object","description":"Response for test email endpoint","required":["success","sent_to"],"properties":{"error":{"type":["string","null"],"description":"Error message if the test failed"},"provider_message_id":{"type":["string","null"],"description":"Provider message ID if successful"},"sent_to":{"type":"string","description":"The email address the test was sent to","example":"user@example.com"},"success":{"type":"boolean","description":"Whether the test email was sent successfully"}}},"TestProviderKeyRequest":{"type":"object","required":["provider","api_key"],"properties":{"api_key":{"type":"string","description":"The raw API key to test"},"base_url":{"type":["string","null"],"description":"Optional custom base URL"},"provider":{"type":"string","description":"Provider ID: \"openai\", \"anthropic\", \"xai\", \"gemini\""}}},"TestProviderKeyResponse":{"type":"object","required":["success","provider","latency_ms"],"properties":{"error":{"type":["string","null"],"description":"Error message if the test failed"},"latency_ms":{"type":"integer","format":"int64","description":"Response time in milliseconds","minimum":0},"provider":{"type":"string"},"success":{"type":"boolean"}}},"TestProviderResponse":{"type":"object","required":["success"],"properties":{"message":{"type":["string","null"]},"success":{"type":"boolean"}}},"TimeBucketStats":{"type":"object","description":"Time bucket statistics response","required":["bucket","request_count","avg_response_time_ms","error_count","total_request_bytes","total_response_bytes"],"properties":{"avg_response_time_ms":{"type":"number","format":"double","description":"Average response time in milliseconds"},"bucket":{"type":"string","description":"Bucket timestamp in RFC3339 format","example":"2025-10-23T12:00:00Z"},"error_count":{"type":"integer","format":"int64","description":"Number of errors (status >= 400)"},"request_count":{"type":"integer","format":"int64","description":"Total number of requests in this bucket"},"total_request_bytes":{"type":"integer","format":"int64","description":"Total request bytes"},"total_response_bytes":{"type":"integer","format":"int64","description":"Total response bytes"}}},"TimeBucketStatsResponse":{"type":"object","description":"Response for time bucket stats","required":["stats","start_time","end_time","bucket_interval"],"properties":{"bucket_interval":{"type":"string"},"end_time":{"type":"string"},"start_time":{"type":"string"},"stats":{"type":"array","items":{"$ref":"#/components/schemas/TimeBucketStats"}}}},"TimeseriesBucket":{"type":"object","required":["bucket","request_count","input_tokens","output_tokens","avg_latency_ms"],"properties":{"avg_latency_ms":{"type":"number","format":"double"},"bucket":{"type":"string","description":"ISO 8601 timestamp"},"input_tokens":{"type":"integer","format":"int64"},"output_tokens":{"type":"integer","format":"int64"},"request_count":{"type":"integer","format":"int64"}}},"TimeseriesQueryParams":{"type":"object","properties":{"bucket":{"type":["string","null"],"description":"Bucket size: \"hour\", \"day\", \"week\" (defaults to \"day\")"},"conversation_id":{"type":["string","null"],"description":"Filter by conversation ID"},"from":{"type":["string","null"],"description":"ISO 8601 start time (defaults to 24h ago)"},"model":{"type":["string","null"],"description":"Filter by model name"},"provider":{"type":["string","null"],"description":"Filter by provider name"},"tags":{"type":["string","null"],"description":"Filter by tags (comma-separated, AND logic)"},"to":{"type":["string","null"],"description":"ISO 8601 end time (defaults to now)"},"user_id":{"type":["integer","null"],"format":"int32","description":"Filter by user ID"}}},"TlsMode":{"type":"string","enum":["None","Starttls","Tls"]},"TodayStatsResponse":{"type":"object","description":"Today's stats response","required":["total_requests","date"],"properties":{"date":{"type":"string","description":"Date for which stats are returned","example":"2025-10-23"},"total_requests":{"type":"integer","format":"int64","description":"Total requests today"}}},"ToggleDeploymentMetricsRequest":{"type":"object","description":"Request body to toggle OTLP metric ingestion for a deployment.","required":["enabled"],"properties":{"enabled":{"type":"boolean","description":"Whether to enable (`true`) or disable (`false`) metric ingestion."},"path":{"type":["string","null"],"description":"Prometheus scrape path (optional, defaults to `/metrics`)."},"port":{"type":["integer","null"],"format":"int32","description":"Prometheus scrape port (optional).","minimum":0}}},"ToggleServiceMetricsRequest":{"type":"object","description":"Request body to toggle metric collection for an external service.","required":["enabled"],"properties":{"enabled":{"type":"boolean","description":"Whether to enable (`true`) or disable (`false`) metric collection."}}},"TokenRenewalRequest":{"type":"object","required":["refresh_token"],"properties":{"refresh_token":{"type":"string"}}},"ToolCallEvent":{"type":"object","description":"Payload for the `tool_call` SSE event: the model is about to run a tool.\nSerialized as compact single-line JSON onto one `data:` line.","required":["id","name","arguments"],"properties":{"arguments":{"type":"string","description":"The raw JSON-args string the model emitted."},"id":{"type":"string"},"name":{"type":"string"}}},"ToolInfo":{"type":"object","description":"One persisted tool invocation + its result, attached to an assistant message.","required":["id","name","arguments"],"properties":{"arguments":{"type":"string"},"id":{"type":"string"},"name":{"type":"string"},"result":{"type":["string","null"]}}},"ToolResultEvent":{"type":"object","description":"Payload for the `tool_result` SSE event: a tool finished running. Serialized\nas compact single-line JSON; `content` is JSON-string-escaped so it stays on\none `data:` line even when long.","required":["id","name","content"],"properties":{"content":{"type":"string"},"id":{"type":"string"},"name":{"type":"string"}}},"TopModelsQueryParams":{"type":"object","properties":{"from":{"type":["string","null"],"description":"ISO 8601 start time (defaults to 24h ago)"},"limit":{"type":["integer","null"],"format":"int64","description":"Max results (defaults to 10)","minimum":0},"tags":{"type":["string","null"],"description":"Filter by tags (comma-separated, AND logic)"},"to":{"type":["string","null"],"description":"ISO 8601 end time (defaults to now)"},"user_id":{"type":["integer","null"],"format":"int32","description":"Filter by user ID"}}},"TraceProjectRef":{"type":"object","description":"All projects that contributed spans to a trace, including their sharing flag.\n\nReturned by `CrossProjectTraceService::find_trace_projects`.","required":["project_id","project_name","project_slug","first_seen","sharing"],"properties":{"first_seen":{"type":"string","format":"date-time"},"project_id":{"type":"integer","format":"int32"},"project_name":{"type":"string"},"project_slug":{"type":"string","description":"URL slug used to link into the project's single-project trace view."},"sharing":{"type":"boolean","description":"Whether this project has `cross_project_trace_sharing = true`."}}},"TraceSummariesResponse":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/TraceSummary"}},"total":{"type":["integer","null"],"format":"int64","description":"Total traces matching the filters, ignoring pagination. Omitted when\nthe request passed `include_total=false`, in which case the caller\nasked not to pay for the count — treat its absence as \"unknown\", not\nas zero.","minimum":0}}},"TraceSummary":{"type":"object","description":"A trace summary for the list view — one row per trace, aggregated from spans.","required":["trace_id","root_span_name","service_name","kind","status_code","start_time","duration_ms","span_count","error_count"],"properties":{"deployment_environment":{"type":["string","null"],"description":"The deployment environment from the root span's resource attributes (e.g. \"production\")."},"duration_ms":{"type":"number","format":"double"},"error_count":{"type":"integer","format":"int64"},"kind":{"$ref":"#/components/schemas/SpanKind"},"root_span_name":{"type":"string"},"service_name":{"type":"string"},"span_count":{"type":"integer","format":"int64"},"start_time":{"type":"string","format":"date-time"},"status_code":{"$ref":"#/components/schemas/SpanStatusCode"},"trace_id":{"type":"string"}}},"TracesResponse":{"type":"object","required":["data","count"],"properties":{"count":{"type":"integer","minimum":0},"data":{"type":"array","items":{"$ref":"#/components/schemas/SpanRecord"}}}},"TrackedLinkResponse":{"type":"object","description":"Tracked link with click count","required":["link_index","original_url","click_count"],"properties":{"click_count":{"type":"integer","format":"int32"},"link_index":{"type":"integer","format":"int32"},"original_url":{"type":"string"}}},"TrackingEventResponse":{"type":"object","description":"Email tracking event","required":["id","email_id","event_type","created_at"],"properties":{"created_at":{"type":"string"},"email_id":{"type":"string"},"event_type":{"type":"string"},"id":{"type":"integer","format":"int64"},"ip_address":{"type":["string","null"]},"link_index":{"type":["integer","null"],"format":"int32"},"link_url":{"type":["string","null"]},"user_agent":{"type":["string","null"]}}},"TriggerAgentRequest":{"type":"object","properties":{"trigger_source_id":{"type":["integer","null"],"format":"int32"},"trigger_source_type":{"type":["string","null"]},"user_context":{"type":["string","null"],"description":"Optional context from the user (e.g. a research topic, bug description, or instructions)."}}},"TriggerDigestResponse":{"type":"object","required":["success","message"],"properties":{"message":{"type":"string"},"success":{"type":"boolean"}}},"TriggerPipelinePayload":{"type":"object","properties":{"branch":{"type":["string","null"]},"commit":{"type":["string","null"]},"environment_id":{"type":["integer","null"],"format":"int32","description":"Optional environment ID - if not provided, will use the project's preview environment"},"tag":{"type":["string","null"]}}},"TriggerPipelineResponse":{"type":"object","required":["message","project_id","environment_id"],"properties":{"branch":{"type":["string","null"]},"commit":{"type":["string","null"]},"environment_id":{"type":"integer","format":"int32"},"message":{"type":"string"},"project_id":{"type":"integer","format":"int32"},"tag":{"type":["string","null"]}}},"TriggerScanRequest":{"type":"object","required":["environment_id"],"properties":{"environment_id":{"type":"integer","format":"int32","description":"Environment ID to scan (uses the current deployment for this environment)","example":1}}},"TriggerScanResponse":{"type":"object","required":["scan_id","status","message"],"properties":{"message":{"type":"string"},"scan_id":{"type":"integer","format":"int32"},"status":{"type":"string"}}},"TtlRequest":{"type":"object","description":"Request to get TTL for a key","required":["key"],"properties":{"key":{"type":"string","description":"The key to check TTL for","example":"session:abc"},"project_id":{"type":["integer","null"],"format":"int32","description":"Project ID (required for API key/session auth, optional for deployment tokens)","example":1}}},"TtlResponse":{"type":"object","description":"Response for TTL operation","required":["ttl"],"properties":{"ttl":{"type":"integer","format":"int64","description":"TTL in seconds, -1 if no expiration, -2 if key doesn't exist","example":3600}}},"TxtRecord":{"type":"object","required":["name","value"],"properties":{"name":{"type":"string"},"value":{"type":"string"}}},"UiManifest":{"type":"object","description":"Describes the plugin's embedded UI bundle.","required":["entry_js"],"properties":{"css":{"type":"array","items":{"type":"string"},"description":"CSS files to load"},"entry_js":{"type":"string","description":"JavaScript entry point filename relative to the bundle root"},"routes":{"type":"array","items":{"$ref":"#/components/schemas/UiRoute"},"description":"Client-side routes the plugin handles"}}},"UiRoute":{"type":"object","description":"A client-side route provided by the plugin UI.","required":["path","title"],"properties":{"path":{"type":"string","description":"Route path pattern (e.g., \"/my-plugin\", \"/my-plugin/:id\")"},"title":{"type":"string","description":"Page title for breadcrumbs"}}},"UndrainNodeResponse":{"type":"object","description":"Response after undraining (reactivating) a node.","required":["id","name","status","message"],"properties":{"id":{"type":"integer","format":"int32"},"message":{"type":"string"},"name":{"type":"string"},"status":{"type":"string"}}},"UnifiedTrace":{"type":"object","description":"Merged cross-project trace result (Phase 2 unified waterfall).\n\nSpans are sorted by `start_time ASC`. At most 20 projects and 10,000\nspans total are included; `truncated` / `truncated_projects` signal when\nthe caps were hit.","required":["trace_id","projects","spans","start_time","end_time","total_duration_ms","span_count","error_count","has_redacted_spans","truncated","truncated_projects"],"properties":{"end_time":{"type":"string","format":"date-time"},"error_count":{"type":"integer","minimum":0},"has_redacted_spans":{"type":"boolean","description":"`true` when at least one project has `cross_project_trace_sharing = false`\nand its spans were therefore excluded from the result set."},"projects":{"type":"array","items":{"$ref":"#/components/schemas/ProjectRef"},"description":"Projects that contributed spans to this result set."},"span_count":{"type":"integer","minimum":0},"spans":{"type":"array","items":{"$ref":"#/components/schemas/AnnotatedSpan"},"description":"Annotated, merged span list sorted by `start_time ASC`."},"start_time":{"type":"string","format":"date-time"},"total_duration_ms":{"type":"number","format":"double","description":"Trace wall-clock duration in milliseconds (`end_time – start_time`)."},"trace_id":{"type":"string"},"truncated":{"type":"boolean","description":"`true` when the 20-project or 10,000-span cap was hit."},"truncated_projects":{"type":"array","items":{"type":"integer","format":"int32"},"description":"project_ids excluded due to truncation (most-recent first_seen dropped first)."}}},"UniqueCountsQuery":{"type":"object","description":"Query parameters for unique counts over time frame","required":["start_date","end_date"],"properties":{"deployment_id":{"type":["integer","null"],"format":"int32","description":"Optional deployment filter"},"end_date":{"type":"string","format":"date-time","description":"End date for the query range"},"environment_id":{"type":["integer","null"],"format":"int32","description":"Optional environment filter"},"metric":{"type":"string","description":"Metric to count: \"sessions\" (unique sessions), \"visitors\" (unique visitors),\n\"returning_visitors\" (visitors seen before the range), or \"page_views\"\n(total page views) (default: \"sessions\")"},"start_date":{"type":"string","format":"date-time","description":"Start date for the query range"}}},"UniqueCountsResponse":{"type":"object","required":["count"],"properties":{"count":{"type":"integer","format":"int64"}}},"UnsupportedFeature":{"type":"object","description":"A feature from the source platform that cannot be migrated","required":["feature","reason"],"properties":{"alternative":{"type":["string","null"],"description":"Suggested alternative in Temps (if any)"},"feature":{"type":"string","description":"Feature name (e.g., \"Edge Middleware\", \"Serverless Functions\", \"Cron Jobs\")"},"reason":{"type":"string","description":"Why it can't be migrated"}}},"UpdateAdminGateRequest":{"type":"object","required":["allowed_ips","allowed_hosts","trust_forwarded_for"],"properties":{"allowed_hosts":{"type":"array","items":{"type":"string"}},"allowed_ips":{"type":"array","items":{"type":"string"}},"trust_forwarded_for":{"type":"boolean"}}},"UpdateAiProviderRequest":{"type":"object","description":"Body for `PATCH /settings/ai-providers/{provider_id}` — updates\nprovider-scoped settings (just the default model for now) without\ntouching the credential. Keeping credentials out of this shape means\nthe UI can auto-save model changes on select, without forcing the user\nto re-paste their token or config file.\nName-spaced schema name avoids an OpenAPI collision with\n`temps-notifications::UpdateProviderRequest`, which has different fields.\nBoth are exposed as `utoipa::ToSchema`; without the override the merged\nOpenAPI doc would silently shadow one struct with the other and break\ngenerated CLI/web clients.","properties":{"default_model":{"type":["string","null"],"description":"New default model id. `None` or an empty string clears the stored\nvalue so the CLI falls back to its own default."},"max_turns_analysis":{"type":["integer","null"],"format":"int32","description":"Default max turns for the autofixer analysis phase (1–200). `0`\nclears the stored value (built-in default applies); omitted/`None`\nleaves the current value unchanged — so a PATCH that only updates\n`default_model` doesn't wipe the turn settings."},"max_turns_feedback":{"type":["integer","null"],"format":"int32","description":"Default max turns for autofixer feedback rounds (1–200). `0` clears;\nomitted leaves unchanged."},"max_turns_fix":{"type":["integer","null"],"format":"int32","description":"Default max turns for the autofixer fix phase (1–200). `0` clears;\nomitted leaves unchanged."}}},"UpdateAiProviderResponse":{"type":"object","required":["provider_id"],"properties":{"default_model":{"type":["string","null"]},"max_turns_analysis":{"type":["integer","null"],"format":"int32"},"max_turns_feedback":{"type":["integer","null"],"format":"int32"},"max_turns_fix":{"type":["integer","null"],"format":"int32"},"provider_id":{"type":"string"}}},"UpdateAlertRuleRequest":{"type":"object","properties":{"cooldown_minutes":{"type":["integer","null"],"format":"int32"},"enabled":{"type":["boolean","null"]},"environment_filter":{"type":["integer","null"],"format":"int32"},"error_level_filter":{"type":["string","null"]},"name":{"type":["string","null"]},"notification_priority":{"type":["string","null"]},"trigger_config":{},"trigger_type":{"type":["string","null"]}}},"UpdateApiKeyRequest":{"type":"object","properties":{"expires_at":{"type":["string","null"],"format":"date-time","example":"2024-12-31T23:59:59Z"},"is_active":{"type":["boolean","null"]},"name":{"type":["string","null"]},"permissions":{"type":["array","null"],"items":{"type":"string"},"example":["projects:read","deployments:read"]}}},"UpdateAutomaticDeployRequest":{"type":"object","required":["automatic_deploy"],"properties":{"automatic_deploy":{"type":"boolean"}}},"UpdateBackupScheduleRequest":{"type":"object","description":"Request body for updating an existing backup schedule via `PATCH /api/backups/schedules/{id}`.\n\nAll fields are optional; only present fields are updated. Absent fields\nleave the corresponding column unchanged.","properties":{"description":{"type":["string","null"],"description":"New human-readable description. Pass an empty string `\"\"` to clear."},"enabled":{"type":["boolean","null"],"description":"Enable or disable the schedule. Skipped when `None`."},"include_control_plane":{"type":["boolean","null"],"description":"Toggle whether the control-plane backup is produced on every run."},"max_runtime_secs":{"type":["integer","null"],"format":"int64","description":"Per-schedule wall-clock timeout override (seconds).\n\n- `None` (field absent) — leave current value unchanged\n- `Some(None)` (field present, JSON `null`) — clear override; fall back to engine default\n- `Some(Some(n))` — set to `n` seconds (must be >= 60)"},"name":{"type":["string","null"],"description":"New schedule name. Skipped when `None`. Must not be empty if provided."},"retention_period":{"type":["integer","null"],"format":"int32","description":"Days to retain backups produced by this schedule. Must be >= 1."},"schedule_expression":{"type":["string","null"],"description":"New cron expression. When changed, `next_run` is recomputed."},"tags":{"type":["array","null"],"items":{"type":"string"},"description":"Replace the full tag list. Skipped when `None`."},"target_all_services":{"type":["boolean","null"],"description":"Toggle between \"back up every database\" (`true`) and \"back up only\nthe explicit list\" (`false`). When set to `true`, the server clears\nthe explicit membership rows for this schedule."}}},"UpdateBlobRequest":{"type":"object","description":"Request to update Blob service configuration","properties":{"docker_image":{"type":["string","null"],"description":"Docker image to use (e.g., \"rustfs/rustfs:1.0.0-alpha.98\")","example":"rustfs/rustfs:1.0.0-alpha.98"}}},"UpdateBlobResponse":{"type":"object","description":"Response after updating Blob service","required":["success","message","status"],"properties":{"message":{"type":"string","description":"Human-readable message","example":"Blob service updated successfully"},"status":{"$ref":"#/components/schemas/BlobStatusResponse","description":"Current status"},"success":{"type":"boolean","description":"Whether the operation succeeded","example":true}}},"UpdateCloudflareProviderRequest":{"type":"object","required":["config"],"properties":{"config":{"$ref":"#/components/schemas/CloudflareConfig"},"enabled":{"type":["boolean","null"]},"name":{"type":["string","null"]}}},"UpdateConfigBody":{"type":"object","properties":{"config":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/ProviderConfig","description":"Typed provider configuration. Setting `config` to `null` clears\nthe stored config back to the accept-everything default. The\nconfig's `provider` tag must match the integration's provider."}]}}},"UpdateCustomDomainRequest":{"type":"object","properties":{"branch":{"type":["string","null"]},"domain":{"type":["string","null"]},"environment_id":{"type":["integer","null"],"format":"int32"},"redirect_to":{"type":["string","null"]},"service_name":{"type":["string","null"],"description":"Docker Compose service name this domain routes to (empty string clears it)"},"status_code":{"type":["integer","null"],"format":"int32"}}},"UpdateDashboardRequest":{"type":"object","properties":{"layout":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/DashboardLayout"}]},"name":{"type":["string","null"]}}},"UpdateDeploymentConfigRequest":{"type":"object","properties":{"automaticDeploy":{"type":["boolean","null"]},"cpuLimit":{"type":["integer","null"],"format":"int32"},"cpuRequest":{"type":["integer","null"],"format":"int32"},"crossArchitectureBuilds":{"type":["boolean","null"],"description":"Build one image per architecture the eligible nodes run. Off by\ndefault; environments inherit this and may override it. Cross-builds\nare emulated on the control plane and substantially slower, so they are\nopted into rather than triggered by cluster topology."},"exposedPort":{"type":["integer","null"],"format":"int32"},"memoryLimit":{"type":["integer","null"],"format":"int32"},"memoryRequest":{"type":["integer","null"],"format":"int32"},"performanceMetricsEnabled":{"type":["boolean","null"]},"replicas":{"type":["integer","null"],"format":"int32"},"security":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/SecurityConfig"}]},"sessionRecordingEnabled":{"type":["boolean","null"]}}},"UpdateDeploymentTokenRequest":{"type":"object","properties":{"expires_at":{"type":["string","null"],"format":"date-time","example":"2024-12-31T23:59:59Z"},"is_active":{"type":["boolean","null"]},"name":{"type":["string","null"]},"permissions":{"type":["array","null"],"items":{"type":"string"},"example":["visitors:enrich","emails:send"]}}},"UpdateDnsProviderRequest":{"type":"object","description":"Request to update a DNS provider","properties":{"credentials":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/DnsProviderCredentials","description":"New credentials"}]},"description":{"type":["string","null"],"description":"New description"},"is_active":{"type":["boolean","null"],"description":"Active status"},"name":{"type":["string","null"],"description":"New name"}}},"UpdateEmailProviderRequest":{"type":"object","description":"Request body for `PATCH /email-providers/{id}`.\n\nAll fields are optional. Omit any field to leave it unchanged. The\n`provider_type` is immutable — to switch providers, delete the row and\ncreate a new one. For credentials, supplying any credential variant\nre-encrypts the stored blob; omitting them preserves the existing secret\n(so operators can rename without re-typing passwords).","properties":{"is_active":{"type":["boolean","null"]},"name":{"type":["string","null"],"example":"My AWS SES"},"region":{"type":["string","null"],"example":"us-east-1"},"scaleway_credentials":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/ScalewayCredentialsRequest"}]},"ses_credentials":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/SesCredentialsRequest"}]},"smtp_credentials":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/SmtpCredentialsRequest"}]},"sns_topic_arn":{"type":["string","null"],"description":"Rotate or clear the exact SNS topic allowed for this SES provider.\nOmit to preserve it, send `null` to clear it, or send a string to set it."}}},"UpdateEnvironmentSettingsRequest":{"type":"object","properties":{"anti_affinity":{"type":["boolean","null"],"description":"Anti-affinity: spread replicas across different nodes.\nWhen enabled, the scheduler avoids placing two replicas of the same\nenvironment on the same node. Defaults to `true`."},"attack_mode":{"type":["boolean","null"],"description":"Per-environment CAPTCHA attack-mode override (tri-state):\n- absent → leave the current override unchanged\n- JSON `null` → clear the override (inherit the project-level setting)\n- `true`/`false` → override the project setting for this environment"},"automatic_deploy":{"type":["boolean","null"],"description":"Enable/disable automatic deployments for this environment"},"branch":{"type":["string","null"]},"cpu_limit":{"type":["integer","null"],"format":"int32","description":"Maximum (limit) CPU in microcores. Send JSON `null` to clear → \"no limit\".\nAbsent leaves the current value unchanged."},"cpu_request":{"type":["integer","null"],"format":"int32","description":"Minimum (request) CPU in microcores. Send JSON `null` to clear (no request).\nAbsent leaves the current value unchanged."},"cross_architecture_builds":{"type":["boolean","null"],"description":"Build one image per architecture the eligible nodes run (overrides the\nproject-level setting). Off by default: cross-architecture builds are\nemulated on the control plane and substantially slower, so they are\nopted into per environment rather than triggered by cluster topology."},"exposed_port":{"type":["integer","null"],"format":"int32","description":"Port exposed by the container (overrides project-level port for this environment)\n\nPriority order for port resolution:\n1. Image EXPOSE directive (auto-detected from built image)\n2. This environment-level exposed_port (overrides project setting)\n3. Project-level exposed_port (fallback)\n4. Default: 3000","example":8080},"force_https":{"type":["boolean","null"],"description":"Per-environment HTTP→HTTPS redirect override (tri-state):\n- absent → leave the current override unchanged\n- JSON `null` → clear the override (inherit the proxy default, which\n redirects only when the host has an active TLS certificate)\n- `true` → always redirect plain HTTP to HTTPS for this environment,\n even when no local certificate exists (TLS terminated upstream)\n- `false` → never redirect this environment, even when a certificate does\n exist\n\nRequests under `/.well-known/acme-challenge/` are never redirected\nregardless of this setting, so ACME HTTP-01 validation always completes."},"idle_timeout_seconds":{"type":["integer","null"],"format":"int32","description":"Seconds of inactivity before stopping containers (60-86400). Default: 300."},"memory_limit":{"type":["integer","null"],"format":"int32","description":"Maximum (limit) memory in MB. Send JSON `null` to clear → \"no limit\".\nAbsent leaves the current value unchanged."},"memory_request":{"type":["integer","null"],"format":"int32","description":"Minimum (request) memory in MB. Send JSON `null` to clear (no request).\nAbsent leaves the current value unchanged."},"on_demand":{"type":["boolean","null"],"description":"Enable on-demand mode (scale-to-zero). Containers are stopped after\nidle_timeout_seconds of no traffic and started on the next request."},"password":{"type":["string","null"],"description":"Set a password to protect this environment. The proxy will show an HTML\npassword form before allowing access. The password is bcrypt-hashed\nserver-side and never stored in plaintext.\nSend an empty string to remove password protection."},"performance_metrics_enabled":{"type":["boolean","null"],"description":"Enable/disable performance metrics collection"},"protected":{"type":["boolean","null"],"description":"When true, git pushes do NOT auto-deploy to this environment.\nDeployments must be promoted from another environment."},"replicas":{"type":["integer","null"],"format":"int32"},"security":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/SecurityConfig","description":"Security configuration for this environment (overrides project-level settings)"}]},"session_recording_enabled":{"type":["boolean","null"],"description":"Enable/disable session recording"},"target_labels":{"description":"Label selector for node-based scheduling (overrides project-level setting).\nSame key with array value -> OR, different keys -> AND.\nExample: `{\"region\": [\"us\", \"asia\"], \"gpu\": \"true\"}`"},"target_nodes":{"type":["array","null"],"items":{"type":"integer","format":"int32"},"description":"Optional list of node IDs to deploy to (overrides project-level setting)"},"wake_timeout_seconds":{"type":["integer","null"],"format":"int32","description":"Max seconds to wait for containers to start on wake (5-120). Default: 30."}}},"UpdateEnvironmentSubdomainRequest":{"type":"object","description":"Request to rename an environment's auto-managed subdomain.\n\nThe subdomain is the host label inserted in front of the platform's\npreview domain (e.g. `myapp` in `myapp.preview.temps.sh`). Renaming\nreplaces the previous subdomain entirely — the old hostname stops\nresolving immediately after this request succeeds.","required":["subdomain"],"properties":{"subdomain":{"type":"string","description":"New subdomain label. Must be a DNS-safe slug (lowercase letters,\ndigits, and hyphens, 1-63 characters). The value is slugified\nserver-side, so casing and disallowed characters are normalized.","example":"myapp"}}},"UpdateEnvironmentVariableRequest":{"type":"object","required":["key","environment_ids"],"properties":{"environment_ids":{"type":"array","items":{"type":"integer","format":"int32"}},"include_in_preview":{"type":"boolean"},"is_secret":{"type":["boolean","null"],"description":"Optional secret-flag transition.\n- `Some(true)` promotes a regular var to a secret.\n- `Some(false)` is rejected if the row is already secret (one-way flag).\n- `None` (omitted) leaves the flag unchanged."},"key":{"type":"string"},"value":{"type":["string","null"],"description":"New plaintext value. `None` (omitted) keeps the existing ciphertext,\nwhich is the only way to edit a secret env var without re-typing its\nvalue (e.g. changing which environments it applies to)."}}},"UpdateErrorGroupRequest":{"type":"object","required":["status"],"properties":{"assigned_to":{"type":["string","null"]},"status":{"type":"string"}}},"UpdateExternalServiceRequest":{"type":"object","required":["parameters"],"properties":{"docker_image":{"type":["string","null"],"description":"Docker image to use for the service (e.g., \"gotempsh/postgres-walg:18-bookworm\", \"timescale/timescaledb-ha:pg18\")\nWhen provided, the service will be recreated with the new image while preserving data"},"parameters":{"type":"object","additionalProperties":{},"propertyNames":{"type":"string"}}}},"UpdateFlagRequest":{"type":"object","properties":{"client_visible":{"type":["boolean","null"]},"default_value":{"description":"Must match the flag's existing `value_type`."},"description":{"type":["string","null"],"description":"Tri-state: absent leaves it, `null` clears it, a string sets it."}}},"UpdateGitSettingsRequest":{"type":"object","required":["main_branch","repo_owner","repo_name","directory"],"properties":{"directory":{"type":"string"},"git_provider_connection_id":{"type":["integer","null"],"format":"int32"},"git_url":{"type":["string","null"],"description":"Git clone URL for public repositories"},"is_public_repo":{"type":["boolean","null"],"description":"Whether this is a public repository (no git provider connection needed)"},"main_branch":{"type":"string"},"preset":{"type":["string","null"]},"preset_config":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/PresetConfigSchema","description":"Preset-specific configuration (e.g., Dockerfile path for Docker preset)\n\nExample for Dockerfile preset:\n```json\n{\n \"dockerfilePath\": \"docker/Dockerfile\",\n \"buildContext\": \"./api\"\n}\n```"}]},"repo_name":{"type":"string"},"repo_owner":{"type":"string"}}},"UpdateIncidentStatusRequest":{"type":"object","required":["status","message"],"properties":{"message":{"type":"string"},"status":{"type":"string"}}},"UpdateIpAccessControlRequest":{"type":"object","description":"Request to update an IP access control rule","properties":{"action":{"type":["string","null"],"description":"Optional new action"},"ip_address":{"type":["string","null"],"description":"Optional new IP address"},"reason":{"type":["string","null"],"description":"Optional new reason"}}},"UpdateKvRequest":{"type":"object","description":"Request to update KV service configuration","properties":{"docker_image":{"type":["string","null"],"description":"Docker image to use (e.g., \"gotempsh/redis-walg:8-bookworm\")","example":"gotempsh/redis-walg:8-bookworm"}}},"UpdateKvResponse":{"type":"object","description":"Response after updating KV service","required":["success","message","status"],"properties":{"message":{"type":"string","description":"Status message","example":"KV service updated successfully"},"status":{"$ref":"#/components/schemas/KvStatusResponse","description":"Current service status"},"success":{"type":"boolean","description":"Whether the operation succeeded"}}},"UpdateManagedDomainApiRequest":{"type":"object","description":"Request to update a managed domain's settings.","properties":{"auto_manage":{"type":["boolean","null"],"description":"Toggle automatic DNS management for this domain."},"generated_hostname_mode":{"type":["string","null"],"description":"`\"standard\"` or `\"flat\"`. Persisted as-is; switching to `\"flat\"` does not\nrecompute existing hostnames — use the apply endpoint for that."},"sync_generated_records":{"type":["boolean","null"],"description":"Toggle DNS record sync for this domain."}}},"UpdateMcpRequest":{"type":"object","required":["config"],"properties":{"config":{"type":"object"},"description":{"type":["string","null"]},"name":{"type":["string","null"]}}},"UpdateMemberRoleRequest":{"type":"object","description":"The new fixed role for an existing membership.","required":["role"],"properties":{"role":{"$ref":"#/components/schemas/TeamRole"}}},"UpdateMetricAlertRequest":{"type":"object","properties":{"aggregation":{"type":["string","null"]},"detection_config":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/DetectionConfig","description":"Replaces the detector wholesale when present (absent = leave unchanged)."}]},"dynamic_alerts":{"type":["boolean","null"],"description":"Toggles per-series (\"dynamic\") alerting (absent = leave unchanged)."},"enabled":{"type":["boolean","null"]},"for_duration_secs":{"type":["integer","null"],"format":"int32"},"group_by":{"type":["array","null"],"items":{"type":"string"},"description":"Replaces the group_by keys wholesale when present (absent = leave unchanged)."},"grouped_notification_threshold":{"type":["integer","null"],"format":"int32","description":"Updates the notification-grouping threshold (absent = leave unchanged)."},"label_filters":{"type":["array","null"],"items":{"type":"array","items":false,"prefixItems":[{"type":"string"},{"type":"string"}]},"description":"Replaces the label filters wholesale when present (absent = leave unchanged)."},"max_series":{"type":["integer","null"],"format":"int32","description":"Updates the dynamic-alerting cardinality cap (absent = leave unchanged)."},"metric_name":{"type":["string","null"]},"name":{"type":["string","null"]},"severity":{"type":["string","null"]},"window_secs":{"type":["integer","null"],"format":"int32"}}},"UpdateNotificationEmailProviderRequest":{"type":"object","required":["config"],"properties":{"config":{"$ref":"#/components/schemas/EmailConfig"},"enabled":{"type":["boolean","null"]},"name":{"type":["string","null"]}}},"UpdateOidcProviderRequest":{"type":"object","properties":{"client_id":{"type":["string","null"]},"client_secret":{"type":["string","null"]},"default_role":{"type":["string","null"]},"enabled":{"type":["boolean","null"]},"group_claim":{"type":["string","null"]},"issuer_url":{"type":["string","null"]},"jit_provisioning":{"type":["boolean","null"]},"name":{"type":["string","null"]},"role_claim":{"type":["string","null"]},"scopes":{"type":["string","null"]},"template":{"type":["string","null"]},"trust_idp_email":{"type":["boolean","null"]}}},"UpdatePreferencesRequest":{"type":"object","required":["preferences"],"properties":{"preferences":{"$ref":"#/components/schemas/NotificationPreferencesResponse"}}},"UpdateProjectSecretRequest":{"type":"object","description":"Request to update a project secret. The `value` field is optional — omit it\nto rotate only the environment scoping / preview flag without touching the\nciphertext.","properties":{"environment_ids":{"type":"array","items":{"type":"integer","format":"int32"}},"include_in_preview":{"type":"boolean"},"value":{"type":["string","null"],"description":"New plaintext value, <= 1 MiB. Omit to keep the existing value."}}},"UpdateProjectSettingsRequest":{"type":"object","properties":{"ai_alert_summaries_enabled":{"type":["boolean","null"],"description":"Opt in to AI summarization of metric alert notifications (ADR-021)."},"ai_debug_chat_enabled":{"type":["boolean","null"],"description":"Opt in to AI debugging chat, e.g. on deployment failures (ADR-023)."},"ai_write_actions_enabled":{"type":["boolean","null"],"description":"Opt in to AI propose-then-confirm write capability."},"attack_mode":{"type":["boolean","null"],"description":"Enable/disable attack mode (CAPTCHA protection) for all project environments"},"cross_project_trace_sharing":{"type":["boolean","null"],"description":"ADR-027 Phase 3 opt-out: set to false to suppress this project's traces\nfrom appearing in cross-project discovery results. Default true (consistent\nwith the OSS global-observability model). Omit to leave unchanged."},"directory":{"type":["string","null"]},"enable_preview_environments":{"type":["boolean","null"],"description":"Enable automatic preview environment creation for each branch"},"error_source_context_enabled":{"type":["boolean","null"],"description":"Opt in to native error-tracking source context (source-file upload +\nsource code shown in stack traces)."},"error_source_root":{"type":["string","null"],"description":"Set the auto-capture source root (relative to the checkout). Send an\nempty string to clear it back to the build-context default. Omit to\nleave unchanged."},"git_provider_connection_id":{"type":["integer","null"],"format":"int32"},"main_branch":{"type":["string","null"]},"preset":{"type":["string","null"]},"preset_config":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/PresetConfigSchema","description":"Preset-specific configuration (e.g., Dockerfile path for Docker preset)\n\nExample for Dockerfile preset:\n```json\n{\n \"dockerfilePath\": \"docker/Dockerfile\",\n \"buildContext\": \"./api\"\n}\n```"}]},"preview_envs_idle_timeout_seconds":{"type":["integer","null"],"format":"int32","description":"Idle timeout (seconds, 60..=86400) for on-demand preview environments."},"preview_envs_on_demand":{"type":["boolean","null"],"description":"When true, newly-created preview environments default to on-demand mode."},"preview_envs_wake_timeout_seconds":{"type":["integer","null"],"format":"int32","description":"Wake timeout (seconds, 5..=120) for on-demand preview environments."},"repo_name":{"type":["string","null"]},"repo_owner":{"type":["string","null"]},"slug":{"type":["string","null"]}}},"UpdateProviderCredentialsRequest":{"type":"object","description":"Partial-update payload for provider credentials. Every field is optional;\nonly the fields the user re-enters are applied. The server validates that\nthe fields supplied make sense for the provider's current auth_method\n(e.g. `app_id` + `private_key` only apply to GitHub Apps).","properties":{"app_id":{"type":["string","null"],"description":"Application ID (GitHub App integer as string; GitLab App string)."},"app_secret":{"type":["string","null"],"description":"GitLab App secret (not used by GitHub App — use `client_secret`)."},"client_id":{"type":["string","null"],"description":"OAuth client ID (GitLab OAuth, GitHub App)."},"client_secret":{"type":["string","null"],"description":"OAuth client secret (GitLab OAuth, GitHub App)."},"private_key":{"type":["string","null"],"description":"GitHub App private key (PEM)."},"redirect_uri":{"type":["string","null"],"description":"OAuth redirect URI (GitLab OAuth / GitLab App)."},"token":{"type":["string","null"],"description":"PAT for PAT-type providers."},"webhook_secret":{"type":["string","null"],"description":"GitHub App webhook secret."}}},"UpdateProviderKeyRequest":{"type":"object","properties":{"api_key":{"type":["string","null"]},"base_url":{"type":["string","null"],"description":"Double-Option: absent = leave unchanged, present-null = clear (revert to\nthe provider's default endpoint), present-value = set."},"default_model":{"type":["string","null"],"description":"Double-Option: absent = leave unchanged, present-null = clear the pinned\nmodel (revert to the per-provider default), present-value = set."},"display_name":{"type":["string","null"]},"is_active":{"type":["boolean","null"]}}},"UpdateProviderRequest":{"type":"object","properties":{"config":{},"enabled":{"type":["boolean","null"]},"name":{"type":["string","null"]}}},"UpdateRouteRequest":{"type":"object","required":["host","port","enabled"],"properties":{"enabled":{"type":"boolean"},"host":{"type":"string"},"port":{"type":"integer","format":"int32"},"route_type":{"type":["string","null"],"description":"Route type: \"http\" (default) matches on HTTP Host header,\n\"tls\" matches on TLS SNI hostname for TCP passthrough"}}},"UpdateS3SourceRequest":{"type":"object","properties":{"access_key_id":{"type":["string","null"],"description":"Optional new access key ID","example":"AKIAXXXXXXXXXXXXXXXX"},"bucket_name":{"type":["string","null"],"description":"Optional new bucket name"},"bucket_path":{"type":["string","null"],"description":"Optional new bucket path"},"endpoint":{"type":["string","null"],"description":"Optional new endpoint URL for S3-compatible services","example":"http://minio.example.com:9000"},"force_path_style":{"type":["boolean","null"],"description":"Optional new path-style addressing setting","example":true},"name":{"type":["string","null"],"description":"Optional new name for the source"},"region":{"type":["string","null"],"description":"Optional new region"},"secret_key":{"type":["string","null"],"description":"Optional new secret key"}}},"UpdateSecretBody":{"type":"object","required":["signing_secret"],"properties":{"signing_secret":{"type":"string","description":"New signing secret from the provider's dashboard. Encrypted at\nrest; never returned in any API response."}}},"UpdateSelfRequest":{"type":"object","properties":{"email":{"type":["string","null"],"example":"john.doe@example.com"},"name":{"type":["string","null"],"example":"John Doe"}}},"UpdateSessionDurationRequest":{"type":"object","required":["duration"],"properties":{"duration":{"type":"integer","format":"int32"}}},"UpdateSessionDurationResponse":{"type":"object","required":["message"],"properties":{"message":{"type":"string"}}},"UpdateSkillRequest":{"type":"object","properties":{"content":{"type":["string","null"]},"description":{"type":["string","null"]},"name":{"type":["string","null"]}}},"UpdateSlackProviderRequest":{"type":"object","required":["config"],"properties":{"config":{"$ref":"#/components/schemas/SlackConfig"},"enabled":{"type":["boolean","null"]},"name":{"type":["string","null"]}}},"UpdateSpeedMetricsPayload":{"type":"object","description":"Update speed metrics payload for late-loading metrics","properties":{"cls":{"type":["number","null"],"format":"float","description":"Cumulative Layout Shift (score)"},"inp":{"type":["number","null"],"format":"float","description":"Interaction to Next Paint (milliseconds)"}}},"UpdateStatusResponse":{"type":"object","description":"Result of the background release-update check, driving the web console's\nupgrade banner. All optional fields are set together iff\n`update_available` is true.","required":["update_available","docs_url"],"properties":{"channel":{"type":["string","null"],"description":"Channel the install tracks: `stable` or `beta`."},"checked_at":{"type":["string","null"],"description":"When the check that found the update ran (ISO 8601, UTC)."},"current_version":{"type":["string","null"],"description":"Version tag of the running binary, e.g. `v0.1.0-beta.45`."},"docs_url":{"type":"string","description":"Docs page with upgrade instructions. Always present so the UI links\nthe same page regardless of update state."},"latest_version":{"type":["string","null"],"description":"Newest published tag on this install's channel."},"release_url":{"type":["string","null"],"description":"Release-notes page (GitHub release) for the newer version."},"update_available":{"type":"boolean","description":"True when a newer release than the running binary has been published\non this install's channel."}}},"UpdateTeamRequest":{"type":"object","properties":{"description":{"type":["string","null"]},"name":{"type":["string","null"]}}},"UpdateTokenRequest":{"type":"object","required":["access_token"],"properties":{"access_token":{"type":"string"},"refresh_token":{"type":["string","null"]}}},"UpdateTokenResponse":{"type":"object","required":["connection_id","message","is_active"],"properties":{"connection_id":{"type":"integer","format":"int32"},"is_active":{"type":"boolean"},"message":{"type":"string"}}},"UpdateUserRequest":{"type":"object","properties":{"email":{"type":["string","null"],"example":"john.doe@example.com"},"name":{"type":["string","null"],"example":"John Doe"}}},"UpdateWebhookProviderRequest":{"type":"object","required":["config"],"properties":{"config":{"$ref":"#/components/schemas/WebhookConfig"},"enabled":{"type":["boolean","null"]},"name":{"type":["string","null"]}}},"UpdateWebhookRequestBody":{"type":"object","properties":{"enabled":{"type":["boolean","null"],"description":"Whether the webhook is enabled"},"events":{"type":["array","null"],"items":{"type":"string"},"description":"Event types to subscribe to"},"secret":{"type":["string","null"],"description":"Secret for HMAC signature verification"},"url":{"type":["string","null"],"description":"Target URL for webhook delivery"}}},"UpgradeExternalServiceRequest":{"type":"object","required":["docker_image"],"properties":{"docker_image":{"type":"string","description":"Docker image to upgrade to (e.g., \"gotempsh/postgres-walg:18-bookworm\")\nThis will trigger pg_upgrade for PostgreSQL or equivalent upgrade procedures for other services","example":"gotempsh/postgres-walg:18-bookworm"}}},"UpgradeRequest":{"type":"object","required":["image"],"properties":{"image":{"type":"string","description":"Image reference to pull and run (e.g.\n`ghcr.io/gotempsh/temps-preview-gateway:latest`). Empty resets to default."}}},"UpsertAgentRequest":{"type":"object","properties":{"ai_model":{"type":["string","null"],"description":"Preferred model identifier for the CLI. `Some(\"\")` clears the stored value."},"ai_provider":{"type":["string","null"]},"ai_provider_key_id":{"type":["integer","null"],"format":"int32"},"api_key":{"type":["string","null"],"description":"Plain-text API key — will be encrypted before storage"},"branch_prefix":{"type":["string","null"]},"config_repo_branch":{"type":["string","null"],"description":"Branch of the config repo to use (default: \"main\")."},"config_repo_url":{"type":["string","null"],"description":"Private config repo containing .claude/ directory (skills, MCP, plugins)."},"cooldown_minutes":{"type":["integer","null"],"format":"int32"},"daily_budget_cents":{"type":["integer","null"],"format":"int32"},"deliverable":{"type":["string","null"]},"description":{"type":["string","null"]},"enabled":{"type":["boolean","null"]},"max_turns":{"type":["integer","null"],"format":"int32"},"mcp_servers_config":{"description":"MCP servers config (Claude Code settings.json mcpServers format).\nCredential-bearing legacy inline objects are write-only: normal reads\nmask them, and updates must omit this field to preserve existing values."},"name":{"type":["string","null"]},"prompt":{"type":["string","null"]},"sandbox_enabled":{"type":["boolean","null"]},"skills_config":{"description":"Skills config as JSON array."},"slug":{"type":["string","null"]},"timeout_seconds":{"type":["integer","null"],"format":"int32"},"tools_config":{"description":"Tools config as JSON array. Custom-tool webhook URLs and headers are\nwrite-only; omit this field on update to preserve them."},"trigger_config":{"description":"Trigger configuration JSON: { \"error\": { \"new_issue\": true, \"regression\": true }, \"manual\": true }"}}},"UpsertSecretRequest":{"type":"object","required":["name","value"],"properties":{"description":{"type":["string","null"]},"mount_path":{"type":["string","null"],"description":"Required for \"file\" type secrets — absolute path inside the sandbox"},"name":{"type":"string"},"secret_type":{"type":"string","description":"\"env\" (environment variable) or \"file\" (written to mount_path)"},"value":{"type":"string"}}},"UptimeDataPoint":{"type":"object","required":["timestamp","status"],"properties":{"error_message":{"type":["string","null"]},"response_time_ms":{"type":["integer","null"],"format":"int32"},"status":{"type":"string"},"timestamp":{"type":"string","format":"date-time"}}},"UptimeHistoryResponse":{"type":"object","required":["monitor_id","uptime_data"],"properties":{"monitor_id":{"type":"integer","format":"int32"},"uptime_data":{"type":"array","items":{"$ref":"#/components/schemas/UptimeDataPoint"}}}},"UsageFilter":{"type":"object","description":"Filters for querying AI usage data.\n\nCost bounds are expressed in microcents (the unit stored in\n`estimated_cost_microcents`). At most one of `gte`/`gt` and one of\n`lte`/`lt` is meaningful per query; if both are set the stricter wins\nnaturally because they are ANDead together.","properties":{"conversation_id":{"type":["string","null"]},"cost_gt":{"type":["integer","null"],"format":"int64","description":"Cost strictly greater-than, in microcents."},"cost_gte":{"type":["integer","null"],"format":"int64","description":"Cost greater-than-or-equal, in microcents."},"cost_lt":{"type":["integer","null"],"format":"int64","description":"Cost strictly less-than, in microcents."},"cost_lte":{"type":["integer","null"],"format":"int64","description":"Cost less-than-or-equal, in microcents."},"model":{"type":["string","null"]},"provider":{"type":["string","null"]},"status":{"type":["integer","null"],"format":"int32","description":"Filter by HTTP status code (exact match)."},"tags":{"type":["string","null"],"description":"Comma-separated tags to filter by (AND logic)."},"tokens_gt":{"type":["integer","null"],"format":"int64","description":"Total tokens (input + output) strictly greater-than."},"tokens_gte":{"type":["integer","null"],"format":"int64","description":"Total tokens (input + output) greater-than-or-equal."},"tokens_lt":{"type":["integer","null"],"format":"int64","description":"Total tokens (input + output) strictly less-than."},"tokens_lte":{"type":["integer","null"],"format":"int64","description":"Total tokens (input + output) less-than-or-equal."},"user_id":{"type":["integer","null"],"format":"int32"}}},"UsageInfo":{"type":"object","required":["prompt_tokens","completion_tokens","total_tokens"],"properties":{"completion_tokens":{"type":"integer","format":"int64"},"prompt_tokens":{"type":"integer","format":"int64"},"total_tokens":{"type":"integer","format":"int64"}}},"UsageLogEntry":{"type":"object","required":["id","timestamp","provider","model","input_tokens","output_tokens","latency_ms","estimated_cost_microcents","status","is_streaming","is_byok","tags"],"properties":{"conversation_id":{"type":["string","null"]},"estimated_cost_microcents":{"type":"integer","format":"int64"},"id":{"type":"integer","format":"int64"},"input_tokens":{"type":"integer","format":"int64"},"is_byok":{"type":"boolean"},"is_streaming":{"type":"boolean"},"latency_ms":{"type":"integer","format":"int32"},"model":{"type":"string"},"output_tokens":{"type":"integer","format":"int64"},"provider":{"type":"string"},"request_id":{"type":["string","null"]},"status":{"type":"integer","format":"int32"},"tags":{"type":"array","items":{"type":"string"}},"timestamp":{"type":"string"},"trace_id":{"type":["string","null"]}}},"UsageLogPage":{"type":"object","description":"A page of recent usage log entries plus the total count for pagination.","required":["entries","total"],"properties":{"entries":{"type":"array","items":{"$ref":"#/components/schemas/UsageLogEntry"},"description":"The usage log entries for the requested page."},"total":{"type":"integer","format":"int64","description":"Total number of entries matching the filter (across all pages)."}}},"UsageQueryParams":{"type":"object","properties":{"conversation_id":{"type":["string","null"],"description":"Filter by conversation ID"},"from":{"type":["string","null"],"description":"ISO 8601 start time (defaults to 24h ago)"},"model":{"type":["string","null"],"description":"Filter by model name"},"provider":{"type":["string","null"],"description":"Filter by provider name"},"tags":{"type":["string","null"],"description":"Filter by tags (comma-separated, AND logic)"},"to":{"type":["string","null"],"description":"ISO 8601 end time (defaults to now)"},"user_id":{"type":["integer","null"],"format":"int32","description":"Filter by user ID"}}},"UsageSource":{"type":"string","description":"How the \"actual usage\" numbers were obtained","enum":["metrics-api","requests-only","unavailable"]},"UsageSummary":{"type":"object","required":["total_requests","total_input_tokens","total_output_tokens","total_tokens","avg_latency_ms","total_cost_microcents","error_count","streaming_count","byok_count"],"properties":{"avg_latency_ms":{"type":"number","format":"double"},"byok_count":{"type":"integer","format":"int64"},"error_count":{"type":"integer","format":"int64"},"streaming_count":{"type":"integer","format":"int64"},"total_cost_microcents":{"type":"integer","format":"int64"},"total_input_tokens":{"type":"integer","format":"int64"},"total_output_tokens":{"type":"integer","format":"int64"},"total_requests":{"type":"integer","format":"int64"},"total_tokens":{"type":"integer","format":"int64"}}},"UserResponse":{"type":"object","required":["id","username","name","avatar_url","mfa_enabled","role"],"properties":{"avatar_url":{"type":"string"},"email":{"type":["string","null"]},"id":{"type":"integer","format":"int32"},"mfa_enabled":{"type":"boolean"},"name":{"type":"string"},"role":{"type":"string","description":"User's role (e.g., \"admin\", \"user\", \"demo\")"},"username":{"type":"string"}}},"ValidateEmailRequest":{"type":"object","description":"Request body for validating an email address","required":["email"],"properties":{"email":{"type":"string","description":"Email address to validate","example":"someone@gmail.com"}},"additionalProperties":false},"ValidateEmailResponse":{"type":"object","description":"Complete email validation response","required":["email","is_reachable","syntax","mx","misc","smtp"],"properties":{"email":{"type":"string","description":"The email address that was validated","example":"someone@gmail.com"},"is_reachable":{"$ref":"#/components/schemas/ReachabilityStatus","description":"Overall reachability status: safe, risky, invalid, or unknown"},"misc":{"$ref":"#/components/schemas/MiscResult","description":"Miscellaneous validation result"},"mx":{"$ref":"#/components/schemas/MxResult","description":"MX record validation result"},"smtp":{"$ref":"#/components/schemas/SmtpResult","description":"SMTP validation result"},"syntax":{"$ref":"#/components/schemas/SyntaxResult","description":"Syntax validation result"}}},"ValidationLevel":{"type":"string","description":"Validation severity level","enum":["info","warning","error","critical"]},"ValidationReport":{"type":"object","description":"Complete validation report","required":["results","overall_status","summary"],"properties":{"overall_status":{"$ref":"#/components/schemas/ValidationStatus","description":"Overall status"},"results":{"type":"array","items":{"$ref":"#/components/schemas/ValidationResult"},"description":"All validation results"},"summary":{"$ref":"#/components/schemas/ValidationSummary","description":"Summary statistics"}}},"ValidationResponse":{"type":"object","required":["connection_id","is_valid","message"],"properties":{"connection_id":{"type":"integer","format":"int32"},"is_valid":{"type":"boolean"},"message":{"type":"string"}}},"ValidationResult":{"type":"object","description":"Result of a validation check","required":["rule_id","rule_name","level","passed","message","affected_resources"],"properties":{"affected_resources":{"type":"array","items":{"type":"string"},"description":"Affected resources/fields"},"level":{"$ref":"#/components/schemas/ValidationLevel","description":"Validation level"},"message":{"type":"string","description":"Message describing the result"},"passed":{"type":"boolean","description":"Whether the validation passed"},"remediation":{"type":["string","null"],"description":"Suggested remediation (if failed)"},"rule_id":{"type":"string","description":"Rule that was checked"},"rule_name":{"type":"string","description":"Human-readable rule name"}}},"ValidationStatus":{"type":"string","description":"Overall validation status","enum":["passed","passed-with-warnings","failed-with-warnings","failed"]},"ValidationSummary":{"type":"object","description":"Validation summary statistics","required":["total_count","passed_count","failed_count","info_count","warning_count","error_count","critical_count"],"properties":{"critical_count":{"type":"integer","description":"Critical-level results","minimum":0},"error_count":{"type":"integer","description":"Error-level results","minimum":0},"failed_count":{"type":"integer","description":"Validations that failed","minimum":0},"info_count":{"type":"integer","description":"Info-level results","minimum":0},"passed_count":{"type":"integer","description":"Validations that passed","minimum":0},"total_count":{"type":"integer","description":"Total validations run","minimum":0},"warning_count":{"type":"integer","description":"Warning-level results","minimum":0}}},"VerifyMfaRequest":{"type":"object","required":["code"],"properties":{"code":{"type":"string"}}},"VerifyStepUpRequest":{"type":"object","required":["code"],"properties":{"code":{"type":"string","description":"Current TOTP value or an unused recovery code."}}},"ViewItem":{"type":"object","required":["label","value"],"properties":{"label":{"type":"string","format":"date-time"},"value":{"type":"integer","format":"int64"}}},"ViewsOverTime":{"type":"object","required":["items","metric","present_index"],"properties":{"comparison_labels":{"type":["array","null"],"items":{"type":"string"}},"comparison_plot":{"type":["array","null"],"items":{"type":"integer","format":"int64"}},"full_intervals":{"type":["array","null"],"items":{"type":"string"}},"items":{"type":"array","items":{"$ref":"#/components/schemas/ViewItem"}},"metric":{"type":"string"},"present_index":{"type":"integer","minimum":0}}},"ViewsOverTimeQuery":{"type":"object","required":["start_date","end_date","project_id"],"properties":{"deployment_id":{"type":["integer","null"],"format":"int32"},"end_date":{"type":"string","format":"date-time"},"environment_id":{"type":["integer","null"],"format":"int32"},"project_id":{"type":"integer","format":"int32"},"start_date":{"type":"string","format":"date-time"}}},"VisitorDetails":{"type":"object","required":["id","visitor_id","project_id","environment_id","first_seen","last_seen","is_crawler"],"properties":{"city":{"type":["string","null"]},"country":{"type":["string","null"]},"country_code":{"type":["string","null"]},"crawler_name":{"type":["string","null"]},"custom_data":{},"environment_id":{"type":"integer","format":"int32"},"first_channel":{"type":["string","null"],"description":"Marketing channel from the first visit (e.g. \"Organic Search\", \"Direct\")"},"first_referrer":{"type":["string","null"],"description":"Full referrer URL from the visitor's first session"},"first_referrer_hostname":{"type":["string","null"],"description":"Hostname extracted from first_referrer"},"first_seen":{"type":"string","format":"date-time","example":"2024-01-01T00:00:00"},"id":{"type":"integer","format":"int32"},"ip_address":{"type":["string","null"]},"ip_address_id":{"type":["integer","null"],"format":"int32"},"is_crawler":{"type":"boolean"},"is_eu":{"type":["boolean","null"]},"last_seen":{"type":"string","format":"date-time","example":"2024-01-01T00:00:00"},"latitude":{"type":["number","null"],"format":"double"},"longitude":{"type":["number","null"],"format":"double"},"project_id":{"type":"integer","format":"int32"},"region":{"type":["string","null"]},"timezone":{"type":["string","null"]},"user_agent":{"type":["string","null"]},"visitor_id":{"type":"string"}}},"VisitorFacetValue":{"type":"object","description":"A single facet value with its visitor count. Used to populate filter\ndropdowns on the visitors page (e.g. \"Germany — 1,234 visitors\").","required":["value","count"],"properties":{"code":{"type":["string","null"],"description":"Optional secondary code for the value. Currently only populated for\nthe `country` facet, where it carries the 2-letter ISO country code\nso the UI can render a flag without re-mapping."},"count":{"type":"integer","format":"int64","description":"Distinct visitor count matching this value in the current segment."},"value":{"type":"string","description":"The dimension value (e.g. \"United States\", \"Chrome\", \"google.com\").\n`None` is encoded as the literal string \"Direct\" for referrer and as\nthe empty string for the rest."}}},"VisitorFacets":{"type":"object","description":"All filter dropdown contents in one response. Each list is the top N\nvalues for that dimension within the current date range and segment\n(excluding the dimension being queried so the dropdown still shows\nalternatives when a value is already selected).","required":["country","region","city","channel","referrer"],"properties":{"channel":{"type":"array","items":{"$ref":"#/components/schemas/VisitorFacetValue"}},"city":{"type":"array","items":{"$ref":"#/components/schemas/VisitorFacetValue"}},"country":{"type":"array","items":{"$ref":"#/components/schemas/VisitorFacetValue"}},"referrer":{"type":"array","items":{"$ref":"#/components/schemas/VisitorFacetValue"}},"region":{"type":"array","items":{"$ref":"#/components/schemas/VisitorFacetValue"}}}},"VisitorFacetsQuery":{"allOf":[{"$ref":"#/components/schemas/VisitorSegmentFilters"},{"type":"object","required":["start_date","end_date","project_id"],"properties":{"end_date":{"type":"string","format":"date-time"},"environment_id":{"type":["integer","null"],"format":"int32"},"has_activity_only":{"type":["boolean","null"]},"include_crawlers":{"type":["boolean","null"]},"per_facet_limit":{"type":["integer","null"],"format":"int32","description":"Maximum number of values returned per dimension (default: 50, max: 200)."},"project_id":{"type":"integer","format":"int32"},"start_date":{"type":"string","format":"date-time"}}}],"description":"Query parameters for the visitor-facets endpoint. Mirrors the shape of\n`VisitorsListQuery` so the same segment filters apply — facet counts are\nalways computed against the *currently filtered* visitor pool, minus the\ndimension being aggregated."},"VisitorInfo":{"type":"object","required":["id","visitor_id","project_id","environment_id","first_seen","last_seen","is_crawler"],"properties":{"city":{"type":["string","null"]},"country":{"type":["string","null"]},"country_code":{"type":["string","null"]},"crawler_name":{"type":["string","null"]},"current_page":{"type":["string","null"],"description":"Most recent page path visited by this visitor"},"custom_data":{},"environment_id":{"type":"integer","format":"int32"},"first_channel":{"type":["string","null"],"description":"Marketing channel from the first visit (e.g. \"Organic Search\", \"Direct\")"},"first_referrer":{"type":["string","null"],"description":"Full referrer URL from the visitor's first session"},"first_referrer_hostname":{"type":["string","null"],"description":"Hostname extracted from first_referrer"},"first_seen":{"type":"string","format":"date-time","example":"2024-01-01T00:00:00"},"id":{"type":"integer","format":"int32"},"ip_address":{"type":["string","null"]},"ip_address_id":{"type":["integer","null"],"format":"int32"},"is_crawler":{"type":"boolean"},"is_eu":{"type":["boolean","null"]},"last_seen":{"type":"string","format":"date-time","example":"2024-01-01T00:00:00"},"latitude":{"type":["number","null"],"format":"double"},"longitude":{"type":["number","null"],"format":"double"},"project_id":{"type":"integer","format":"int32"},"region":{"type":["string","null"]},"timezone":{"type":["string","null"]},"user_agent":{"type":["string","null"]},"visitor_id":{"type":"string"}}},"VisitorJourneyQuery":{"type":"object","required":["project_id"],"properties":{"limit_sessions":{"type":["integer","null"],"format":"int32"},"project_id":{"type":"integer","format":"int32"}}},"VisitorJourneyResponse":{"type":"object","description":"Complete visitor journey response","required":["visitor_id","total_sessions","total_events","sessions"],"properties":{"sessions":{"type":"array","items":{"$ref":"#/components/schemas/JourneySession"},"description":"Sessions with their events, ordered newest first"},"total_events":{"type":"integer","format":"int64","description":"Total number of events across all sessions"},"total_sessions":{"type":"integer","format":"int64","description":"Total number of sessions"},"visitor_id":{"type":"integer","format":"int32","description":"Visitor internal ID"}}},"VisitorLocationsQuery":{"type":"object","required":["start_date","end_date","project_id"],"properties":{"end_date":{"type":"string","format":"date-time"},"environment_id":{"type":["integer","null"],"format":"int32"},"granularity":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/LocationGranularity"}]},"limit":{"type":["integer","null"],"format":"int32"},"project_id":{"type":"integer","format":"int32"},"start_date":{"type":"string","format":"date-time"}}},"VisitorRecord":{"type":"object","required":["id","visitor_id","project_id","created_at"],"properties":{"created_at":{"type":"string","format":"date-time","example":"2024-01-01T00:00:00"},"custom_data":{},"id":{"type":"integer","format":"int32"},"project_id":{"type":"integer","format":"int32"},"visitor_id":{"type":"string"}}},"VisitorSegmentFilters":{"type":"object","description":"Optional segment filters for [`VisitorsListQuery`]. Each filter narrows the\nresult set to visitors who match the given dimension value within the date\nrange. All filters resolve against `visitor` / `ip_geolocations` — by\ndesign we never touch the events hypertable here so filtering stays fast\nregardless of event volume.","properties":{"filter_channel":{"type":["string","null"],"description":"First-touch marketing channel (matches `visitor.first_channel`)"},"filter_city":{"type":["string","null"],"description":"Geolocation city (matches `ip_geolocations.city`)"},"filter_country":{"type":["string","null"],"description":"Geolocation country (matches `ip_geolocations.country`)"},"filter_referrer":{"type":["string","null"],"description":"First-touch referrer hostname (matches `visitor.first_referrer_hostname`)"},"filter_region":{"type":["string","null"],"description":"Geolocation region (matches `ip_geolocations.region`)"}}},"VisitorSessionsQuery":{"type":"object","required":["project_id"],"properties":{"environment_id":{"type":["integer","null"],"format":"int32"},"limit":{"type":["integer","null"],"format":"int32"},"project_id":{"type":"integer","format":"int32"}}},"VisitorSessionsResponse":{"type":"object","required":["visitor_id","sessions","total_sessions"],"properties":{"sessions":{"type":"array","items":{"$ref":"#/components/schemas/SessionSummary"}},"total_sessions":{"type":"integer","format":"int64"},"visitor_id":{"type":"string"}}},"VisitorStats":{"type":"object","required":["visitor_id","first_seen","last_seen","total_sessions","total_page_views","total_events","average_session_duration","bounce_rate","engagement_rate","top_pages","top_referrers","devices_used","locations"],"properties":{"average_session_duration":{"type":"number","format":"double"},"bounce_rate":{"type":"number","format":"double"},"devices_used":{"type":"array","items":{"type":"string"}},"engagement_rate":{"type":"number","format":"double"},"first_seen":{"type":"string","format":"date-time","example":"2024-01-01T00:00:00"},"last_seen":{"type":"string","format":"date-time","example":"2024-01-01T00:00:00"},"locations":{"type":"array","items":{"$ref":"#/components/schemas/LocationInfo"}},"top_pages":{"type":"array","items":{"$ref":"#/components/schemas/PageVisit"}},"top_referrers":{"type":"array","items":{"type":"string"}},"total_events":{"type":"integer","format":"int64"},"total_page_views":{"type":"integer","format":"int64"},"total_sessions":{"type":"integer","format":"int64"},"visitor_id":{"type":"integer","format":"int32"}}},"VisitorWithGeolocation":{"type":"object","required":["id","visitor_id","project_id","environment_id","first_seen","last_seen","is_crawler"],"properties":{"city":{"type":["string","null"]},"country":{"type":["string","null"]},"country_code":{"type":["string","null"]},"crawler_name":{"type":["string","null"]},"custom_data":{},"environment_id":{"type":"integer","format":"int32"},"first_channel":{"type":["string","null"],"description":"Marketing channel from the first visit (e.g. \"Organic Search\", \"Direct\")"},"first_referrer":{"type":["string","null"],"description":"Full referrer URL from the visitor's first session"},"first_referrer_hostname":{"type":["string","null"],"description":"Hostname extracted from first_referrer"},"first_seen":{"type":"string","format":"date-time","example":"2024-01-01T00:00:00"},"id":{"type":"integer","format":"int32"},"ip_address":{"type":["string","null"]},"is_crawler":{"type":"boolean"},"is_eu":{"type":["boolean","null"]},"last_seen":{"type":"string","format":"date-time","example":"2024-01-01T00:00:00"},"latitude":{"type":["number","null"],"format":"double"},"longitude":{"type":["number","null"],"format":"double"},"project_id":{"type":"integer","format":"int32"},"region":{"type":["string","null"]},"timezone":{"type":["string","null"]},"user_agent":{"type":["string","null"]},"visitor_id":{"type":"string"}}},"VisitorsListQuery":{"allOf":[{"$ref":"#/components/schemas/VisitorSegmentFilters"},{"type":"object","required":["start_date","end_date","project_id"],"properties":{"end_date":{"type":"string","format":"date-time"},"environment_id":{"type":["integer","null"],"format":"int32"},"has_activity_only":{"type":["boolean","null"],"description":"Filter to only include visitors with recorded activity (events/sessions).\nWhen true, excludes \"ghost\" visitors that have no events."},"include_crawlers":{"type":["boolean","null"]},"limit":{"type":["integer","null"],"format":"int32"},"offset":{"type":["integer","null"],"format":"int32"},"project_id":{"type":"integer","format":"int32"},"start_date":{"type":"string","format":"date-time"}}}]},"VisitorsResponse":{"type":"object","required":["visitors","total_count","filtered_count"],"properties":{"filtered_count":{"type":"integer","format":"int64"},"total_count":{"type":"integer","format":"int64"},"visitors":{"type":"array","items":{"$ref":"#/components/schemas/VisitorInfo"}}}},"VolumeMount":{"type":"object","description":"Volume mount in deployment","required":["source","destination","read_only","type"],"properties":{"destination":{"type":"string","description":"Destination path in container"},"read_only":{"type":"boolean","description":"Read-only flag"},"source":{"type":"string","description":"Source (volume name or path)"},"type":{"$ref":"#/components/schemas/VolumeType","description":"Volume type"}}},"VolumeType":{"type":"string","description":"Volume type","enum":["bind","volume","tmpfs"]},"VulnerabilityResponse":{"type":"object","required":["id","scan_id","vulnerability_id","package_name","installed_version","severity","title","created_at"],"properties":{"class":{"type":["string","null"],"example":"os-pkgs"},"created_at":{"type":"string","example":"2025-12-08T12:15:47.609192Z"},"cvss_score":{"type":["number","null"],"format":"float"},"description":{"type":["string","null"]},"fixed_version":{"type":["string","null"]},"id":{"type":"integer","format":"int32"},"installed_version":{"type":"string"},"last_modified_date":{"type":["string","null"],"example":"2025-12-08T12:15:47.609192Z"},"package_name":{"type":"string"},"primary_url":{"type":["string","null"]},"published_date":{"type":["string","null"],"example":"2025-12-08T12:15:47.609192Z"},"references":{},"scan_id":{"type":"integer","format":"int32"},"severity":{"type":"string"},"target":{"type":["string","null"],"example":"alpine:3.18 (alpine 3.18.0)"},"title":{"type":"string"},"type":{"type":["string","null"],"example":"alpine"},"vulnerability_id":{"type":"string"}}},"WalWarning":{"oneOf":[{"type":"object","description":"`pg_wal` is significantly larger than `max_wal_size`.","required":["pg_wal_bytes","max_wal_size_bytes","ratio","kind"],"properties":{"kind":{"type":"string","enum":["wal_bloat"]},"max_wal_size_bytes":{"type":"integer","format":"int64"},"pg_wal_bytes":{"type":"integer","format":"int64"},"ratio":{"type":"number","format":"double"}}},{"type":"object","description":"A replication slot is holding WAL it's not consuming.","required":["slot_name","retained_bytes","active","kind"],"properties":{"active":{"type":"boolean"},"kind":{"type":"string","enum":["stale_slot"]},"retained_bytes":{"type":"integer","format":"int64"},"slot_name":{"type":"string"}}},{"type":"object","description":"`archive_status/*.ready` count exceeds threshold — `archive_command`\nis either failing or running slower than WAL generation.","required":["ready_count","kind"],"properties":{"kind":{"type":"string","enum":["archive_backlog"]},"ready_count":{"type":"integer","format":"int64"}}},{"type":"object","description":"`archive_mode = on` but `archive_command` is empty / `/bin/true`.\nWAL accumulates forever waiting for a destination that never accepts.","required":["kind"],"properties":{"kind":{"type":"string","enum":["archive_mode_without_command"]}}},{"type":"object","description":"Oldest WAL segment is older than `WAL_NOT_RECYCLED_AGE_SECS`.\nIndependent signal: something is blocking recycling even if total\nsize hasn't exploded yet.","required":["oldest_age_secs","kind"],"properties":{"kind":{"type":"string","enum":["wal_not_recycled"]},"oldest_age_secs":{"type":"integer","format":"int64"}}}],"description":"One actionable warning surfaced to the UI.\n\nEach variant carries the data needed to render a remediation hint without\nthe frontend re-querying anything."},"WalWarningSeverity":{"type":"string","enum":["warning","critical"]},"WebhookConfig":{"type":"object","description":"Configuration for a generic webhook notification provider","required":["url"],"properties":{"headers":{"type":"object","description":"Custom headers to include in the request (e.g., for authentication tokens)","additionalProperties":{"type":"string"},"propertyNames":{"type":"string"},"example":{"Authorization":"Bearer your-token","X-Custom-Header":"custom-value"}},"method":{"type":"string","description":"HTTP method to use (POST, PUT, PATCH). Defaults to POST.","example":"POST"},"timeout_secs":{"type":"integer","format":"int64","description":"Request timeout in seconds. Defaults to 30.","example":30,"minimum":0},"url":{"type":"string","description":"The URL to send webhook requests to","example":"https://api.example.com/notifications"}}},"WebhookDeliveryResponse":{"type":"object","required":["id","webhook_id","event_type","event_id","payload","success","attempt_number","created_at"],"properties":{"attempt_number":{"type":"integer","format":"int32"},"created_at":{"type":"string","format":"date-time","example":"2025-10-12T12:15:47.609192Z"},"delivered_at":{"type":["string","null"],"format":"date-time"},"error_message":{"type":["string","null"]},"event_id":{"type":"string"},"event_type":{"type":"string"},"id":{"type":"integer","format":"int32"},"payload":{"type":"string","description":"JSON payload that was sent to the webhook endpoint","example":{"event_type":"deployment.succeeded","data":{"deployment_id":123}}},"status_code":{"type":["integer","null"],"format":"int32"},"success":{"type":"boolean"},"webhook_id":{"type":"integer","format":"int32"}}},"WebhookResponse":{"type":"object","required":["id","project_id","url","events","enabled","has_secret","created_at","updated_at"],"properties":{"created_at":{"type":"string","format":"date-time","example":"2025-10-12T12:15:47.609192Z"},"enabled":{"type":"boolean"},"events":{"type":"array","items":{"type":"string"}},"has_secret":{"type":"boolean"},"id":{"type":"integer","format":"int32"},"project_id":{"type":"integer","format":"int32"},"updated_at":{"type":"string","format":"date-time","example":"2025-10-12T12:15:47.609192Z"},"url":{"type":"string"}}},"WebhookTriggerRequest":{"allOf":[{"description":"Arbitrary JSON payload from the caller. Passed to the agent as user_context."}]},"WebhookTriggerResponse":{"type":"object","required":["run_id","status"],"properties":{"run_id":{"type":"integer","format":"int32"},"status":{"type":"string"}}},"WorkflowDryRunRequest":{"type":"object","required":["yaml"],"properties":{"cpu_limit":{"type":["number","null"],"format":"double","description":"Optional CPU override applied after parsing YAML (clamped server-side).\nWhen `Some`, this takes precedence over `cpu_limit` inside the YAML —\nlets the CLI pass `--cpu` without rewriting the YAML text."},"error_group_id":{"type":["integer","null"],"format":"int32","description":"Optional error group to link this dry-run to. When set, the executor's\n`load_error_context` path injects `{{error_type}}` / `{{error_message}}`\n/ `{{stack_trace}}` into the prompt — same behaviour as a committed\nworkflow triggered with `trigger_source_type = \"error_group\"`. Must\nbelong to `project_id` (handler enforces)."},"memory_limit_mb":{"type":["integer","null"],"format":"int64","description":"Optional memory override in MB (clamped server-side). Same precedence\nrule as `cpu_limit`.","minimum":0},"user_context":{"type":["string","null"],"description":"Optional context appended to the prompt (e.g. \"test against staging\nonly\"). Mirrors `TriggerAgentRequest.user_context`."},"yaml":{"type":"string","description":"Full WorkflowYamlConfig as YAML text. Server validates and re-serializes\nbefore storing on the run row."}}},"WorkloadDescriptor":{"type":"object","description":"Brief descriptor for discovered workloads (used in listing)","required":["id","workload_type","status","labels"],"properties":{"created_at":{"type":["string","null"],"format":"date-time","description":"Creation timestamp"},"id":{"$ref":"#/components/schemas/WorkloadId","description":"Unique ID in source system"},"image":{"type":["string","null"],"description":"Image/build reference (for containers)"},"labels":{"type":"object","description":"Labels/tags from source system","additionalProperties":{"type":"string"},"propertyNames":{"type":"string"}},"name":{"type":["string","null"],"description":"Workload name (if any)"},"status":{"$ref":"#/components/schemas/WorkloadStatus","description":"Current status"},"workload_type":{"$ref":"#/components/schemas/WorkloadType","description":"Workload type (container, function, static-site, etc.)"}}},"WorkloadId":{"type":"string","description":"Unique identifier for a workload in the source system"},"WorkloadStatus":{"type":"string","description":"Workload status in source system","enum":["running","paused","stopped","exited","failed","deployed","building","unknown"]},"WorkloadType":{"type":"string","description":"Workload type","enum":["container","function","static-site","server-side-app","worker","database","message-queue","cache","cron-job","other"]},"WriteFileBody":{"type":"object","required":["path","contents_b64"],"properties":{"contents_b64":{"type":"string","description":"File contents, base64-encoded. Required — lets callers ship binary\ndata over JSON without charset games."},"mode":{"type":["integer","null"],"format":"int32","description":"Unix permission mask (e.g. 0o644). Defaults to 0o644 when absent.","minimum":0},"path":{"type":"string","description":"Absolute path inside the sandbox. Must start with `/`."}},"additionalProperties":false},"WriteFilesBody":{"type":"object","required":["files"],"properties":{"files":{"type":"array","items":{"$ref":"#/components/schemas/WriteFileBody"},"description":"List of files to write. Each entry must include an absolute\n`path` and base64-encoded `contents_b64`. Empty list is a no-op."}},"additionalProperties":false},"WriteFilesResponse":{"type":"object","required":["written"],"properties":{"written":{"type":"integer","description":"Number of files successfully written before the first failure\n(if any). On full success this equals `files.len()`.","minimum":0}}},"ZoneListResponse":{"type":"object","description":"Zone list response","required":["zones"],"properties":{"zones":{"type":"array","items":{"$ref":"#/components/schemas/DnsZone"}}}}},"securitySchemes":{"bearer_auth":{"type":"http","scheme":"bearer","description":"Bearer token authentication. Use format: `Bearer `. Supports API keys (starting with `tk_`), CLI tokens, and session tokens."}}},"tags":[{"name":"Events","description":"Analytics events tracking endpoints"},{"name":"Metrics","description":"Analytics metrics collection endpoints including performance web vitals"},{"name":"Funnels","description":"Funnel management endpoints"},{"name":"Analytics","description":"Analytics and session replay management"},{"name":"Performance","description":"Performance metrics management"},{"name":"geo","description":"Geolocation API endpoints"},{"name":"Platform","description":"Platform information and compatibility"},{"name":"Teams","description":"Teams and project-scoped access"},{"name":"Git Providers","description":"Git provider management endpoints"},{"name":"Repositories","description":"Repository management endpoints"},{"name":"Public Repositories","description":"Endpoints for accessing public repositories without authentication. Supports GitHub and GitLab."},{"name":"Notification Providers","description":"Notification provider management endpoints"},{"name":"Notification Preferences","description":"User notification preferences and settings"},{"name":"DNS Providers","description":"DNS provider management endpoints"},{"name":"Internal DNS","description":"Per-node DNS resolver sync (ADR-011)"},{"name":"Domains","description":"Domain management endpoints"},{"name":"Email Providers","description":"Email provider management endpoints"},{"name":"Email Domains","description":"Email domain management and verification"},{"name":"Emails","description":"Email sending and retrieval"},{"name":"Email Tracking","description":"Email open and click tracking"},{"name":"Email Validation","description":"Email address validation and verification"},{"name":"Webhooks","description":"Webhook management endpoints"},{"name":"Webhook Deliveries","description":"Webhook delivery history and retry endpoints"},{"name":"External Services","description":"External service integration endpoints"},{"name":"External Services - Query","description":"Data querying and exploration endpoints"},{"name":"Metrics","description":"Time-series metrics and alert rule endpoints"},{"name":"KV Store","description":"Key-Value storage operations"},{"name":"KV Management","description":"KV service management operations"},{"name":"Blob","description":"Blob storage operations"},{"name":"Blob Management","description":"Blob service management operations"},{"name":"Feature Flags","description":"Runtime configuration that changes without a redeploy"},{"name":"Environments","description":"Environment management operations"},{"name":"Secrets","description":"File-mounted secrets (/run/secrets/)"},{"name":"Projects","description":"Project management endpoints"},{"name":"Presets","description":"Available deployment presets"},{"name":"Templates","description":"Project template endpoints"},{"name":"Custom Domains","description":"Custom domain management for projects"},{"name":"error-tracking","description":"Error tracking data fetching endpoints"},{"name":"Vulnerability Scans","description":"Vulnerability scan management endpoints"},{"name":"Agents","description":"Autonomous AI agents, autofixer (interactive AI debugging), skills/MCP definitions, and preview gateway management."},{"name":"Crons","description":"Cron jobs management API"},{"name":"Sandboxes","description":"Standalone sandbox API (`/v1/sandboxes/*`) for running isolated containers."},{"name":"Logs","description":"Log search, context, live tail, and retention management"},{"name":"Imports","description":"Import workloads from external sources"},{"name":"Status Page","description":"Status page and monitoring endpoints"},{"name":"OTel Ingest","description":"OTLP/HTTP ingest endpoints (protobuf)"},{"name":"OTel","description":"Query endpoints for the monitoring UI"},{"name":"GenAI","description":"GenAI agent activity tracing endpoints"},{"name":"Alarms","description":"Unified alarm history — list, summarise, acknowledge, resolve"},{"name":"Authentication","description":"Authentication and authorization endpoints"},{"name":"Users","description":"User management endpoints"},{"name":"Backups","description":"Backup management endpoints"},{"name":"Restore","description":"External service restore operations"},{"name":"Revenue","description":"Per-project revenue tracking integrations and analytics"},{"name":"Observability","description":"Unified observability event stream — runtime logs, requests, spans, errors, revenue"},{"name":"AI Gateway","description":"OpenAI-compatible chat, embeddings, and model endpoints"},{"name":"AI Gateway Admin","description":"Provider key management endpoints"},{"name":"AI Gateway Usage","description":"Usage analytics and reporting endpoints"},{"name":"AI Gateway Pricing","description":"Model pricing endpoints"},{"name":"API Keys","description":"API key management endpoints"},{"name":"Load Balancer","description":"Load balancer management endpoints"},{"name":"IP Access Control","description":"IP access control management endpoints"},{"name":"Files","description":"Static file serving endpoints"},{"name":"External Plugins","description":"External plugin management and discovery"}]} diff --git a/apps/temps-cli/src/api/index.ts b/apps/temps-cli/src/api/index.ts index a93449459..f4db984ac 100644 --- a/apps/temps-cli/src/api/index.ts +++ b/apps/temps-cli/src/api/index.ts @@ -1,4 +1,4 @@ // This file is auto-generated by @hey-api/openapi-ts -export { acknowledgeAlarm, activateAiProvider, activateApiKey, activateConnection, activateProvider, addClusterMember, addContext, addEnvironmentDomain, addEvents, addManagedDomain, addSessionReplayEvents, addTeamMember, adminDrainNode, adminDrainStatus, adminGetNode, adminListNodeContainers, adminListNodes, adminRemoveNode, adminUndrainNode, applyHostnameMode, archiveConversation, archiveFlag, assignRole, attachScheduleServices, blobCopy, blobDelete, blobDisable, blobDownload, blobEnable, blobHead, blobList, blobPut, blobStatus, blobUpdate, cancel, cancelBackup, cancelDeployment, cancelDomainOrder, cancelPgUpgrade, cancelRun, cancelScheduleRun, changePasswordSelf, changeProjectSource, chatCompletions, checkAnalyticsHasEvents, checkCommitExists, checkDomainStatus, checkExplorerSupport, checkIpBlocked, checkProviderDeletionSafety, chunkUploadOptions, cleanupExpiredBackups, clearPreviewPassword, cliDeviceApprove, cliDeviceDeny, cliDeviceLookup, cliDevicePoll, cliDeviceStart, cliLogout, cmd, cmdKill, cmdLogs, confirmPendingAction, containerMetricsGetHistory, createAgent, createAlert, createAlertRule, createApiKey, createBackupSchedule, createBitbucketProvider, createCloudflareProvider, createConversation, createCustomDomain, createDashboard, createDeploymentToken, createDnsProvider, createDomain, createDsn, createEmailDomain, createEmailProvider, createEnvironment, createEnvironmentVariable, createFlag, createFunnel, createGenericProvider, createGiteaPatProvider, createGithubPatProvider, createGitlabOauthProvider, createGitlabPatProvider, createGitProvider, createGlobalMcp, createGlobalSkill, createIncident, createIpAccessControl, createMcp, createMonitor, createNotificationEmailProvider, createNotificationProvider, createOidcProvider, createOidcRoleMapping, createOrRecreateOrder, createPlan, createPr, createProject, createProjectFromTemplate, createProjectRelease, createProjectSecret, createProviderKey, createRelease, createRoute, createS3Source, createSandbox, createService, createSkill, createSlackProvider, createTeam, createUser, createWebhook, createWebhookProvider, deactivateApiKey, deactivateConnection, deactivateProvider, deleteAgent, deleteAlert, deleteAlertRule, deleteApiKey, deleteBackup, deleteBackupSchedule, deleteConnection, deleteCustomDomain, deleteDashboard, deleteDeploymentToken, deleteDnsProvider, deleteDomain, deleteEmailDomain, deleteEmailProvider, deleteEnvironment, deleteEnvironmentDomain, deleteEnvironmentVariable, deleteExternalImage, deleteFunnel, deleteGitProvider, deleteGlobalMcp, deleteGlobalSkill, deleteIpAccessControl, deleteMcp, deleteMonitor, deleteNotificationProvider, deleteOidcProvider, deleteOidcRoleMapping, deletePreferences, deleteProject, deleteProjectSecret, deleteProviderKey, deleteProviderSafely, deleteReleaseSourceFiles, deleteReleaseSourceMaps, deleteRoute, deleteS3Source, deleteScan, deleteSecret, deleteService, deleteSessionReplay, deleteSkill, deleteSourceMap, deleteStaticBundle, deleteTeam, deleteUser, deleteWebhook, deployFromImage, deployFromImageUpload, deployFromStatic, deploymentMetricsGetLatest, deploymentMetricsGetRange, deploymentMetricsToggle, destroySandbox, detachScheduleService, detectPublicPresets, disableBackupSchedule, disableMfa, discoverWorkloads, domain, downloadGlobalSkillArchive, downloadObject, downloadSkillArchive, emailStatus, embeddings, enableBackupSchedule, enrichVisitor, exec, execDetached, executeDeploymentOperation, executeImport, extendTimeout, externalServiceEnablePgStatStatements, externalServiceMetricsByDatabase, externalServiceMetricsCreateAlertRule, externalServiceMetricsDeleteAlertRule, externalServiceMetricsGetAlertRules, externalServiceMetricsGetLatest, externalServiceMetricsGetRange, externalServiceMetricsStatus, externalServiceMetricsToggle, externalServiceMetricsUpdateAlertRule, externalServiceResetPgStatStatements, finalizeOrder, finalizeProjectRelease, findConversation, generateJoinToken, generatePresetDockerfile, getAccessInfo, getActiveVisitors, getActivityGraph, getAdminGate, getAgent, getAggregatedBuckets, getAiAgentBreakdown, getAiAgentPages, getAiAgentTimeline, getAiPageBreakdown, getAiStatusBreakdown, getAlert, getAlertRule, getAllRepositoriesByName, getAnalyticsActiveVisitors, getAnalyticsEventsCount, getAnalyticsSessionEvents, getAnalyticsVisitorSessions, getApiKey, getApiKeyPermissions, getAuditLog, getBackup, getBackupSchedule, getBranchesByRepositoryId, getBucketedIncidents, getBucketedStatus, getChallengeToken, getChatReadiness, getCliStatus, getClusterHealth, getClusterMember, getCmd, getContainerDetail, getContainerEnvironmentVariable, getContainerInfo, getContainerLogs, getContainerLogsById, getContainerMetrics, getConversation, getConversationDetail, getConversations, getCronById, getCronExecutions, getCrossProjectTraceSiblings, getCurrentMonitorStatus, getCurrentUser, getCustomDomain, getDashboard, getDashboardProjectsAnalytics, getDelivery, getDeployment, getDeploymentContainerLogContent, getDeploymentJobLogs, getDeploymentJobs, getDeploymentOperations, getDeploymentOperationStatus, getDeploymentToken, getDiskStatus, getDnsChanges, getDnsProvider, getDomain, getDomainByHost, getDomainById, getDomainByName, getDomainDnsRecords, getDomainOrder, getEmail, getEmailEvents, getEmailLinks, getEmailProvider, getEmailStats, getEmailTracking, getEmailTrackingStatus, getEntityInfo, getEnvironment, getEnvironmentCrons, getEnvironmentDomains, getEnvironments, getEnvironmentVariables, getEnvironmentVariableValue, getErrorDashboardStats, getErrorEvent, getErrorGroup, getErrorStats, getErrorTimeSeries, getEventDetail, getEventEntries, getEventsCount, getEventsTimeline, getEventTypeBreakdown, getEventVisitors, getExternalImage, getFile, getFlag, getFlagSnapshot, getFunnelMetrics, getGenaiTrace, getGeneralStats, getGitProvider, getGlobalEvents, getGlobalEventStats, getGlobalMcp, getGlobalSandboxStatus, getGlobalSkill, getGroupedPageMetrics, getHealth, getHourlyVisits, getHttpChallengeDebug, getImportStatus, getIncident, getIncidentUpdates, getIpAccessControl, getIpGeolocation, getJoinTokenStatus, getLastDeployment, getLatestScan, getLatestScansPerEnvironment, getLiveVisitorsList, getLogContext, getMcp, getMetricsOverTime, getMonitor, getNotificationProvider, getOnDemandCertStatus, getOrCreateDsn, getPageFlow, getPageHourlySessions, getPagePathDetail, getPagePaths, getPagePathsSparklines, getPagePathVisitors, getPendingAction, getPerformanceMetrics, getPgUpgrade, getPgUpgradeLogs, getPipelineStats, getPlatformInfo, getPostgresWalHealth, getPreferences, getPreviewGatewayLogs, getPreviewGatewaySettings, getPreviewGatewayStatus, getPricing, getPrivateIp, getProject, getProjectAlarmsSummary, getProjectBySlug, getProjectDeployments, getProjects, getProjectServiceEnvironmentVariables, getProjectSessionReplays, getProjectsHealth, getProjectsMonitorHealth, getProjectStatistics, getProjectTemplate, getPropertyBreakdown, getPropertyTimeline, getProviderConnections, getProviderMetadata, getProvidersMetadata, getProxyLogById, getProxyLogByRequestId, getProxyLogs, getPublicBranches, getPublicIp, getPublicRepository, getQuota, getRecentActivity, getRemoteExternalImage, getRepositoryBranches, getRepositoryById, getRepositoryByName, getRepositoryPresetByName, getRepositoryPresetLive, getRepositoryTags, getResolvedEnvironmentVariables, getResolvedEnvironmentVariableValue, getRestoreCapabilities, getRestoreRun, getRoute, getRun, getRunWithLogs, getS3Credentials, getS3Source, getSandbox, getSandboxStatus, getScan, getScanByDeployment, getScanVulnerabilities, getService, getServiceBySlug, getServiceEnvironmentVariable, getServiceEnvironmentVariables, getServiceHealthStatus, getServicePreviewEnvironmentVariableNames, getServicePreviewEnvironmentVariablesMasked, getServiceRuntime, getServiceStats, getServiceTypeParameters, getServiceTypes, getSessionDetails, getSessionEvents, getSessionLogs, getSessionReplay, getSessionReplayEvents, getSettings, getSkill, getSlowQueries, getStaticBundle, getStatusOverview, getTagsByRepositoryId, getTeam, getTimeBucketStats, getTodayStats, getTrace, getUnifiedTrace, getUniqueCounts, getUniqueEvents, getUpdateStatus, getUptimeHistory, getUsageByProvider, getUsageRecent, getUsageSummary, getUsageTimeseries, getUsageTopModels, getVisitorByGuid, getVisitorById, getVisitorDetails, getVisitorFacets, getVisitorInfo, getVisitorJourney, getVisitors, getVisitorSessions, getVisitorStats, getWebhook, grantProjectAccess, handleGitProviderOauthCallback, hasAnalyticsEvents, hasErrorGroups, hasPerformanceMetrics, importExternalService, ingestLogs, ingestLogsByPath, ingestMetrics, ingestMetricsByPath, ingestSentryEnvelope, ingestSentryEvent, ingestTraces, ingestTracesByPath, initSessionReplay, jobLogs, jobStatus, killJob, kvDel, kvDisable, kvEnable, kvExpire, kvGet, kvIncr, kvKeys, kvSet, kvStatus, kvTtl, kvUpdate, latestRunForSource, linkCustomDomainToCertificate, linkServiceToProject, listAgentRuns, listAgents, listAiProviders, listAlertRules, listAlerts, listAllConversations, listAllRuns, listApiKeys, listAuditLogs, listAvailableContainers, listBackupAlerts, listBackupChildren, listBackupSchedules, listBackupsForSchedule, listCommitsByRepositoryId, listConnections, listContainers, listContainersAtPath, listConversations, listCustomDomainsForProject, listDashboards, listDeliveries, listDeploymentContainerLogs, listDeploymentTokens, listDnsProviders, listDomains, listDsns, listEmailDomains, listEmailProviders, listEmails, listEnrollmentTokens, listEntities, listErrorEvents, listErrorGroups, listEvents, listEventTypes, listExternalImages, listExternalPlugins, listExternalServiceBackups, listFlags, listFunnels, listGitProviders, listGlobalMcps, listGlobalSkills, listIncidents, listInsights, listIpAccessControl, listJobs, listKnownAiAgents, listManagedDomains, listMcps, listMetricLabelKeys, listMetricLabelValues, listMetricNames, listModels, listMonitors, listNotificationProviders, listOidcProviders, listOidcProviderUsers, listOidcRoleMappings, listOnDemandCerts, listOrders, listPeers, listPendingActions, listPgUpgrades, listPresets, listProjectAccess, listProjectAlarms, listProjectScans, listProjectSecrets, listProjectServices, listProjectTemplates, listProjectTemplateTags, listProviderKeys, listProviderZones, listPublicProviders, listReleaseFiles, listReleases, listRemoteExternalImages, listRepositoriesByConnection, listRepositoriesByProvider, listRestoreRunsForService, listRootContainers, listRoutes, listS3Sources, listSandboxes, listScheduleRunJobs, listScheduleRuns, listScheduleServices, listSecrets, listServiceHealthStatuses, listServiceProjects, listServices, listServiceSchedules, listSkills, listSourceBackups, listSourceFiles, listSourceMaps, listSources, listStaticBundles, listSyncedRepositories, listTeamMembers, listTeamProjects, listTeams, listUsers, listWebhooks, login, logout, lookupDnsARecords, mintEnrollmentToken, mkdir, nodeHeartbeat, nodeMetricsGetRange, observabilityFullEvent, observabilityListEvents, oidcCallback, type Options, patchAdminGate, patchPreviewGatewaySettings, pauseDeployment, pauseSandbox, planRestore, postDnsAck, previewAlert, previewFunnelMetrics, previewHostnameMode, promoteClusterMember, promoteDeployment, provisionDomain, purgeProjectLogs, pushExternalImage, queryData, queryGenaiTraces, queryLogs, queryMetrics, queryTraces, queryTraceSummaries, readFile, reAnalyze, rebuildSandboxImage, recordConsoleEvent, recordEventMetrics, recordFlagExposure, recordSpeedMetrics, refreshRouteTable, regenerateDsn, registerExternalImage, registerNode, reinstallGitlabWebhook, rejectPendingAction, reloadPlugins, removeClusterMember, removeManagedDomain, removeRole, removeTeamMember, renameConversation, renewDomain, requestPasswordReset, resetPassword, resizeSandbox, resolveAlarm, restartContainer, restartPreviewGateway, restartSandbox, restoreFlag, restoreUser, resumeDeployment, resumeSandbox, retryCluster, retryDelivery, retryPgUpgrade, retryRun, revealGlobalMcpConfig, revealMcpConfig, revealNotificationProviderConfig, revealServiceParameter, revenueCreateIntegration, revenueDeleteIntegration, revenueGlobalEvents, revenueImportInvoicesCsv, revenueImportSubscriptionsCsv, revenueListIntegrations, revenueListProviders, revenueMetricsCustomers, revenueMetricsGlobalMrr, revenueMetricsGlobalSummary, revenueMetricsMrr, revenueMetricsSummary, revenueRecentEvents, revenueRotateToken, revenueUpdateConfig, revenueUpdateSecret, revokeDsn, revokeEnrollmentToken, revokeJoinToken, revokeProjectAccess, rollbackPgUpgrade, rollbackToDeployment, rootfsGc, rootfsReport, rotateApiKey, rotateDeploymentToken, runBackupForSource, runConnectionHealthCheck, runExternalServiceBackup, runScheduleNow, sandboxCreatePreviewLink, saveAgentToken, saveAiProviderCredential, searchLogs, sendEmail, sendMessage, setDefaultS3Source, setFlagEnvironment, setPreviewPassword, setupDns, setupDnsChallenge, setupEmailTracking, setupMfa, sleepEnvironment, smokeTestAgent, sourceSandbox, startAnalysis, startContainer, startFix, startGitProviderOauth, startOidcLoginBySlug, startPgUpgrade, startRestore, startService, statPath, stopContainer, stopSandbox, stopService, streamContainerMetrics, streamEvents, streamRunEvents, syncRepositories, tailDeploymentJobLogs, tailLogs, teardownDeployment, teardownEnvironment, testNotificationProvider, testOidcProvider, testProvider, testProviderConnection, testProviderKeyById, testProviderKeyInline, testS3ConnectionPreview, testS3SourceConnection, trackClick, trackOpen, triggerAgent, triggerProjectPipeline, triggerScan, triggerServiceHealthCheck, triggerWeeklyDigest, unlinkServiceFromProject, updateAgent, updateAiProvider, updateAlert, updateAlertRule, updateApiKey, updateAutomaticDeploy, updateBackupSchedule, updateCloudflareProvider, updateConnectionToken, updateCustomDomain, updateDashboard, updateDeploymentToken, updateEmailProvider, updateEnvironmentSettings, updateEnvironmentSubdomain, updateEnvironmentVariable, updateErrorGroup, updateFlag, updateFunnel, updateGitProviderCredentials, updateGitSettings, updateGlobalMcp, updateGlobalSkill, updateIncidentStatus, updateIpAccessControl, updateManagedDomain, updateMcp, updateNotificationEmailProvider, updateNotificationProvider, updateOidcProvider, updatePreferences, updateProject, updateProjectDeploymentConfig, updateProjectSecret, updateProjectSettings, updateProvider, updateProviderKey, updateRoute, updateS3Source, updateSelf, updateService, updateServiceResources, updateSessionDuration, updateSettings, updateSkill, updateSlackProvider, updateSpeedMetrics, updateTeam, updateTeamMemberRole, updateUser, updateWebhook, updateWebhookProvider, upgradePreviewGateway, upgradeService, uploadGlobalSkill, uploadReleaseFile, uploadSkill, uploadSourceFile, uploadSourceMap, uploadStaticBundle, upsertSecret, validateConnection, validateEmail, verifyAndEnableMfa, verifyDomain, verifyEmail, verifyManagedDomain, verifyMfaChallenge, verifyStepUp, wakeEnvironment, webhookTrigger, workflowDryRun, writeFile, writeFiles } from './sdk.gen'; -export type { AcknowledgeAlarmData, AcknowledgeAlarmErrors, AcknowledgeAlarmResponses, AcmeOrderResponse, ActivateAiProviderData, ActivateAiProviderErrors, ActivateAiProviderResponse, ActivateAiProviderResponses, ActivateApiKeyData, ActivateApiKeyErrors, ActivateApiKeyResponse, ActivateApiKeyResponses, ActivateConnectionData, ActivateConnectionErrors, ActivateConnectionResponses, ActivateProviderData, ActivateProviderErrors, ActivateProviderResponse, ActivateProviderResponses, ActiveVisitor, ActiveVisitorsQuery, ActiveVisitorsResponse, ActivityDay, ActivityEvent, ActivityGraphQuery, ActivityGraphResponse, AddClusterMemberData, AddClusterMemberErrors, AddClusterMemberRequest, AddClusterMemberResponse, AddClusterMemberResponses, AddContextData, AddContextErrors, AddContextRequest, AddContextResponses, AddEnvironmentDomainData, AddEnvironmentDomainErrors, AddEnvironmentDomainRequest, AddEnvironmentDomainResponse, AddEnvironmentDomainResponses, AddEventsData, AddEventsError, AddEventsErrors, AddEventsRequest, AddEventsResponse, AddEventsResponse2, AddEventsResponses, AddManagedDomainApiRequest, AddManagedDomainData, AddManagedDomainErrors, AddManagedDomainResponse, AddManagedDomainResponses, AddSessionReplayEventsData, AddSessionReplayEventsError, AddSessionReplayEventsErrors, AddSessionReplayEventsResponse, AddSessionReplayEventsResponses, AddTeamMemberData, AddTeamMemberErrors, AddTeamMemberResponse, AddTeamMemberResponses, AdminDrainNodeData, AdminDrainNodeErrors, AdminDrainNodeResponse, AdminDrainNodeResponses, AdminDrainStatusData, AdminDrainStatusErrors, AdminDrainStatusResponse, AdminDrainStatusResponses, AdminGateResponse, AdminGateSource, AdminGetNodeData, AdminGetNodeErrors, AdminGetNodeResponse, AdminGetNodeResponses, AdminListNodeContainersData, AdminListNodeContainersErrors, AdminListNodeContainersResponse, AdminListNodeContainersResponses, AdminListNodesData, AdminListNodesErrors, AdminListNodesResponse, AdminListNodesResponses, AdminRemoveNodeData, AdminRemoveNodeErrors, AdminRemoveNodeResponse, AdminRemoveNodeResponses, AdminUndrainNodeData, AdminUndrainNodeErrors, AdminUndrainNodeResponse, AdminUndrainNodeResponses, AgentConfigResponse, AgentRunLogResponse, AgentRunResponse, AgentRunWithLogsResponse, AgentSandboxSettings, AgentSandboxSettingsMasked, AggregatedBucketItem, AggregatedBucketsQuery, AggregatedBucketsResponse, AggregationLevel, AggregationTemporality, AiAgentBreakdownResponse, AiAgentBreakdownRow, AiAgentDescriptor, AiAgentPageRow, AiAgentPagesResponse, AiAgentTimelineResponse, AiAgentTimelineRow, AiChatLimitsSettings, AiConfigSettings, AiPageBreakdownResponse, AiPageBreakdownRow, AiStatusBreakdownResponse, AiStatusBreakdownRow, AlarmListResponse, AlarmResponse, AlarmSummaryResponse, AlertRuleResponse, AllocEntry, AnalyticsSessionEventsResponse, AnnotatedSpan, AnomalyAlgorithm, AnomalyParams, AnomalyPreviewPointResponse, AnomalyPreviewRequest, AnomalyPreviewResponse, ApiKeyListResponse, ApiKeyResponse, ApplyHostnameModeData, ApplyHostnameModeErrors, ApplyHostnameModeRequest, ApplyHostnameModeResponse, ApplyHostnameModeResponses, AppSettings, AppSettingsResponse, ArchiveConversationData, ArchiveConversationErrors, ArchiveConversationResponse, ArchiveConversationResponses, ArchiveFlagData, ArchiveFlagErrors, ArchiveFlagResponse, ArchiveFlagResponse2, ArchiveFlagResponses, ArchiveMode, AssignRoleData, AssignRoleErrors, AssignRoleRequest, AssignRoleResponses, AttachScheduleServicesData, AttachScheduleServicesError, AttachScheduleServicesErrors, AttachScheduleServicesRequest, AttachScheduleServicesResponse, AttachScheduleServicesResponse2, AttachScheduleServicesResponses, AuditLogIpInfo, AuditLogResponse, AuditLogUserInfo, AuthFlavorDto, AuthResponse, AuthStatusResponse, AuthTokenResponse, AutofixerRunResponse, AutofixerRunWithLogsResponse, AutofixRunConfig, AutoWatchParams, AvailableContainerInfo, AvailablePermissions, BackupAlertListResponse, BackupAlertResponse, BackupResponse, BackupScheduleResponse, BitbucketAuthInput, BlobCopyData, BlobCopyError, BlobCopyErrors, BlobCopyResponse, BlobCopyResponses, BlobDeleteData, BlobDeleteError, BlobDeleteErrors, BlobDeleteResponse, BlobDeleteResponses, BlobDisableData, BlobDisableErrors, BlobDisableResponse, BlobDisableResponses, BlobDownloadData, BlobDownloadError, BlobDownloadErrors, BlobDownloadResponses, BlobEnableData, BlobEnableErrors, BlobEnableResponse, BlobEnableResponses, BlobHeadData, BlobHeadError, BlobHeadErrors, BlobHeadResponses, BlobListData, BlobListError, BlobListErrors, BlobListResponse, BlobListResponses, BlobPutData, BlobPutError, BlobPutErrors, BlobPutResponse, BlobPutResponses, BlobResponse, BlobStatusData, BlobStatusErrors, BlobStatusResponse, BlobStatusResponse2, BlobStatusResponses, BlobUpdateData, BlobUpdateErrors, BlobUpdateResponse, BlobUpdateResponses, BranchInfo, BranchListResponse, BrowserCount, BrowsersQuery, BuildConfiguration, BuildLimitsSettings, CancelBackupData, CancelBackupError, CancelBackupErrors, CancelBackupResponse, CancelBackupResponse2, CancelBackupResponses, CancelData, CancelDeploymentData, CancelDeploymentErrors, CancelDeploymentResponse, CancelDeploymentResponses, CancelDomainOrderData, CancelDomainOrderErrors, CancelDomainOrderResponse, CancelDomainOrderResponses, CancelErrors, CancelPgUpgradeData, CancelPgUpgradeErrors, CancelPgUpgradeResponse, CancelPgUpgradeResponses, CancelResponses, CancelRunData, CancelRunErrors, CancelRunResponse, CancelRunResponses, CancelScheduleRunData, CancelScheduleRunError, CancelScheduleRunErrors, CancelScheduleRunResponse, CancelScheduleRunResponses, CertStatusResponse, ChallengeConfig, ChallengeError, ChallengeValidationStatus, ChangePasswordRequest, ChangePasswordSelfData, ChangePasswordSelfErrors, ChangePasswordSelfResponse, ChangePasswordSelfResponses, ChangeProjectSourceData, ChangeProjectSourceErrors, ChangeProjectSourceRequest, ChangeProjectSourceResponse, ChangeProjectSourceResponses, ChatCompletionChoice, ChatCompletionRequest, ChatCompletionResponse, ChatCompletionsData, ChatCompletionsError, ChatCompletionsErrors, ChatCompletionsResponse, ChatCompletionsResponses, ChatMessage, ChatReadinessResponse, CheckAnalyticsHasEventsData, CheckAnalyticsHasEventsErrors, CheckAnalyticsHasEventsResponse, CheckAnalyticsHasEventsResponses, CheckCommitExistsData, CheckCommitExistsErrors, CheckCommitExistsResponse, CheckCommitExistsResponses, CheckDomainStatusData, CheckDomainStatusErrors, CheckDomainStatusResponse, CheckDomainStatusResponses, CheckExplorerSupportData, CheckExplorerSupportErrors, CheckExplorerSupportResponse, CheckExplorerSupportResponses, CheckIpBlockedData, CheckIpBlockedError, CheckIpBlockedErrors, CheckIpBlockedResponses, CheckProviderDeletionSafetyData, CheckProviderDeletionSafetyErrors, CheckProviderDeletionSafetyResponse, CheckProviderDeletionSafetyResponses, ChildBackupEntryResponse, ChildBackupListResponse, ChunkUploadOptionsData, ChunkUploadOptionsResponse, ChunkUploadOptionsResponses, CleanupExpiredBackupsData, CleanupExpiredBackupsError, CleanupExpiredBackupsErrors, CleanupExpiredBackupsRequest, CleanupExpiredBackupsResponse, CleanupExpiredBackupsResponses, ClearPreviewPasswordData, ClearPreviewPasswordErrors, ClearPreviewPasswordResponse, ClearPreviewPasswordResponses, CliDeviceApproveData, CliDeviceApproveErrors, CliDeviceApproveRequest, CliDeviceApproveResponse, CliDeviceApproveResponse2, CliDeviceApproveResponses, CliDeviceDenyData, CliDeviceDenyErrors, CliDeviceDenyResponse, CliDeviceDenyResponses, CliDeviceLookupData, CliDeviceLookupErrors, CliDeviceLookupResponse, CliDeviceLookupResponse2, CliDeviceLookupResponses, CliDevicePollData, CliDevicePollErrors, CliDevicePollRequest, CliDevicePollResponse, CliDevicePollResponse2, CliDevicePollResponses, CliDeviceStartData, CliDeviceStartErrors, CliDeviceStartRequest, CliDeviceStartResponse, CliDeviceStartResponse2, CliDeviceStartResponses, ClientOptions, CliLoginRequest, CliLogoutData, CliLogoutErrors, CliLogoutResponse, CliLogoutResponses, CloudflareConfig, CloudProvider, ClusterCapacity, ClusterDnsSettings, ClusterHealthReportResponse, ClusterMemberHealthResponse, ClusterMemberRequest, CmdBody, CmdData, CmdErrors, CmdInner, CmdKillBody, CmdKillData, CmdKillErrors, CmdKillResponse, CmdKillResponses, CmdLogsData, CmdLogsErrors, CmdLogsResponses, CmdResponse, CmdResponse2, CmdResponses, CommitExistsResponse, CommitInfo, CommitListResponse, Comparator, ComposePublicPort, ConfirmPendingActionData, ConfirmPendingActionErrors, ConfirmPendingActionResponse, ConfirmPendingActionResponses, ConnectionListQuery, ConnectionListResponse, ConnectionResponse, ConnectionTestResult, ConsoleEventPayload, ContainerActionResponse, ContainerDetailResponse, ContainerEnvironmentVariableValueResponse, ContainerInfoResponse, ContainerInventoryItem, ContainerListResponse, ContainerLogSettings, ContainerLogsQuery, ContainerMetricHistoryPoint, ContainerMetricsGetHistoryData, ContainerMetricsGetHistoryErrors, ContainerMetricsGetHistoryResponse, ContainerMetricsGetHistoryResponses, ContainerMetricsHistoryQuery, ContainerMetricsResponse, ContainerResponse, ContainerRuntimeInfo, ContainerStatsSample, ContentPart, ContextLine, ContextLogsRequest, ContextLogsResponse, ConversationDetailResponse, ConversationResponse, ConversationsQueryParams, ConversationSummary, CopyBlobRequest, CostAnalysis, CreateAgentData, CreateAgentErrors, CreateAgentResponse, CreateAgentResponses, CreateAlertData, CreateAlertError, CreateAlertErrors, CreateAlertResponse, CreateAlertResponses, CreateAlertRuleData, CreateAlertRuleErrors, CreateAlertRuleRequest, CreateAlertRuleResponse, CreateAlertRuleResponses, CreateApiKeyData, CreateApiKeyErrors, CreateApiKeyRequest, CreateApiKeyResponse, CreateApiKeyResponse2, CreateApiKeyResponses, CreateBackupScheduleData, CreateBackupScheduleError, CreateBackupScheduleErrors, CreateBackupScheduleRequest, CreateBackupScheduleResponse, CreateBackupScheduleResponses, CreateBitbucketProviderData, CreateBitbucketProviderErrors, CreateBitbucketProviderResponse, CreateBitbucketProviderResponses, CreateBitbucketRequest, CreateCloudflareProviderData, CreateCloudflareProviderErrors, CreateCloudflareProviderRequest, CreateCloudflareProviderResponse, CreateCloudflareProviderResponses, CreateConversationData, CreateConversationErrors, CreateConversationRequest, CreateConversationResponse, CreateConversationResponses, CreateCustomDomainData, CreateCustomDomainErrors, CreateCustomDomainResponse, CreateCustomDomainResponses, CreateDashboardData, CreateDashboardError, CreateDashboardErrors, CreateDashboardRequest, CreateDashboardResponse, CreateDashboardResponses, CreateDeploymentTokenData, CreateDeploymentTokenErrors, CreateDeploymentTokenRequest, CreateDeploymentTokenResponse, CreateDeploymentTokenResponse2, CreateDeploymentTokenResponses, CreateDnsProviderData, CreateDnsProviderErrors, CreateDnsProviderRequest, CreateDnsProviderResponse, CreateDnsProviderResponses, CreateDomainData, CreateDomainErrors, CreateDomainRequest, CreateDomainResponse, CreateDomainResponses, CreatedResource, CreateDsnData, CreateDsnErrors, CreateDsnRequest, CreateDsnResponse, CreateDsnResponses, CreateEmailDomainData, CreateEmailDomainErrors, CreateEmailDomainRequest, CreateEmailDomainResponse, CreateEmailDomainResponses, CreateEmailProviderData, CreateEmailProviderErrors, CreateEmailProviderRequest, CreateEmailProviderResponse, CreateEmailProviderResponses, CreateEnvironmentData, CreateEnvironmentErrors, CreateEnvironmentRequest, CreateEnvironmentResponse, CreateEnvironmentResponses, CreateEnvironmentVariableData, CreateEnvironmentVariableErrors, CreateEnvironmentVariableRequest, CreateEnvironmentVariableResponse, CreateEnvironmentVariableResponses, CreateExternalServiceRequest, CreateFlagData, CreateFlagErrors, CreateFlagRequest, CreateFlagResponse, CreateFlagResponses, CreateFunnelData, CreateFunnelErrors, CreateFunnelRequest, CreateFunnelResponse, CreateFunnelResponse2, CreateFunnelResponses, CreateFunnelStep, CreateGenericProviderData, CreateGenericProviderErrors, CreateGenericProviderResponse, CreateGenericProviderResponses, CreateGenericRequest, CreateGiteaPatProviderData, CreateGiteaPatProviderErrors, CreateGiteaPatProviderResponse, CreateGiteaPatProviderResponses, CreateGiteaPatRequest, CreateGithubPatProviderData, CreateGithubPatProviderErrors, CreateGithubPatProviderResponse, CreateGithubPatProviderResponses, CreateGitHubPatRequest, CreateGitlabOauthProviderData, CreateGitlabOauthProviderErrors, CreateGitlabOauthProviderResponse, CreateGitlabOauthProviderResponses, CreateGitLabOAuthRequest, CreateGitlabPatProviderData, CreateGitlabPatProviderErrors, CreateGitlabPatProviderResponse, CreateGitlabPatProviderResponses, CreateGitLabPatRequest, CreateGitProviderData, CreateGitProviderErrors, CreateGitProviderResponse, CreateGitProviderResponses, CreateGlobalMcpData, CreateGlobalMcpErrors, CreateGlobalMcpResponse, CreateGlobalMcpResponses, CreateGlobalSkillData, CreateGlobalSkillErrors, CreateGlobalSkillResponse, CreateGlobalSkillResponses, CreateIncidentData, CreateIncidentErrors, CreateIncidentRequest, CreateIncidentResponse, CreateIncidentResponses, CreateIntegrationBody, CreateIpAccessControlData, CreateIpAccessControlError, CreateIpAccessControlErrors, CreateIpAccessControlRequest, CreateIpAccessControlResponse, CreateIpAccessControlResponses, CreateMcpData, CreateMcpErrors, CreateMcpRequest, CreateMcpResponse, CreateMcpResponses, CreateMetricAlertRequest, CreateMonitorData, CreateMonitorErrors, CreateMonitorRequest, CreateMonitorResponse, CreateMonitorResponses, CreateNotificationEmailProviderData, CreateNotificationEmailProviderErrors, CreateNotificationEmailProviderRequest, CreateNotificationEmailProviderResponse, CreateNotificationEmailProviderResponses, CreateNotificationProviderData, CreateNotificationProviderErrors, CreateNotificationProviderResponse, CreateNotificationProviderResponses, CreateOidcProviderData, CreateOidcProviderErrors, CreateOidcProviderRequest, CreateOidcProviderResponse, CreateOidcProviderResponses, CreateOidcRoleMappingData, CreateOidcRoleMappingRequest, CreateOidcRoleMappingResponse, CreateOidcRoleMappingResponses, CreateOrRecreateOrderData, CreateOrRecreateOrderErrors, CreateOrRecreateOrderResponse, CreateOrRecreateOrderResponses, CreatePlanData, CreatePlanErrors, CreatePlanRequest, CreatePlanResponse, CreatePlanResponse2, CreatePlanResponses, CreatePrData, CreatePrErrors, CreateProjectAccessRequest, CreateProjectData, CreateProjectErrors, CreateProjectFromTemplateData, CreateProjectFromTemplateErrors, CreateProjectFromTemplateRequest, CreateProjectFromTemplateResponse, CreateProjectFromTemplateResponse2, CreateProjectFromTemplateResponses, CreateProjectReleaseData, CreateProjectReleaseErrors, CreateProjectReleaseResponse, CreateProjectReleaseResponses, CreateProjectRequest, CreateProjectResponse, CreateProjectResponses, CreateProjectSecretData, CreateProjectSecretErrors, CreateProjectSecretRequest, CreateProjectSecretResponse, CreateProjectSecretResponses, CreateProviderKeyData, CreateProviderKeyError, CreateProviderKeyErrors, CreateProviderKeyRequest, CreateProviderKeyResponse, CreateProviderKeyResponses, CreateProviderRequest, CreatePrResponse, CreatePrResponse2, CreatePrResponses, CreateReleaseData, CreateReleaseErrors, CreateReleaseResponse, CreateReleaseResponses, CreateRouteData, CreateRouteErrors, CreateRouteRequest, CreateRouteResponse, CreateRouteResponses, CreateS3SourceData, CreateS3SourceError, CreateS3SourceErrors, CreateS3SourceRequest, CreateS3SourceResponse, CreateS3SourceResponses, CreateSandboxBody, CreateSandboxData, CreateSandboxErrors, CreateSandboxResponse, CreateSandboxResponses, CreateServiceData, CreateServiceErrors, CreateServiceResponse, CreateServiceResponses, CreateSkillData, CreateSkillErrors, CreateSkillRequest, CreateSkillResponse, CreateSkillResponses, CreateSlackProviderData, CreateSlackProviderErrors, CreateSlackProviderRequest, CreateSlackProviderResponse, CreateSlackProviderResponses, CreateTeamData, CreateTeamErrors, CreateTeamMemberRequest, CreateTeamRequest, CreateTeamResponse, CreateTeamResponses, CreateUserData, CreateUserErrors, CreateUserRequest, CreateUserResponse, CreateUserResponses, CreateWebhookData, CreateWebhookErrors, CreateWebhookProviderData, CreateWebhookProviderErrors, CreateWebhookProviderRequest, CreateWebhookProviderResponse, CreateWebhookProviderResponses, CreateWebhookRequestBody, CreateWebhookResponse, CreateWebhookResponses, CronExecutionInfo, CronInfo, CrossProjectSiblingRef, CrossProjectTraceResponse, CurrentStatusResponse, CustomDomainRequest, CustomDomainResponse, CustomerMovementResponse, DashboardLayout, DashboardProjectsAnalyticsQuery, DashboardProjectsAnalyticsResponse, DashboardSection, DashboardTile, DatabaseMetricsResponse, DatabaseMetricsRow, DataImplication, DataImplicationSeverity, DeactivateApiKeyData, DeactivateApiKeyErrors, DeactivateApiKeyResponse, DeactivateApiKeyResponses, DeactivateConnectionData, DeactivateConnectionErrors, DeactivateConnectionResponses, DeactivateProviderData, DeactivateProviderErrors, DeactivateProviderResponses, DeleteAgentData, DeleteAgentErrors, DeleteAgentResponse, DeleteAgentResponses, DeleteAlertData, DeleteAlertError, DeleteAlertErrors, DeleteAlertResponse, DeleteAlertResponses, DeleteAlertRuleData, DeleteAlertRuleErrors, DeleteAlertRuleResponse, DeleteAlertRuleResponses, DeleteApiKeyData, DeleteApiKeyErrors, DeleteApiKeyResponse, DeleteApiKeyResponses, DeleteBackupData, DeleteBackupError, DeleteBackupErrors, DeleteBackupResponse, DeleteBackupResponses, DeleteBackupScheduleData, DeleteBackupScheduleError, DeleteBackupScheduleErrors, DeleteBackupScheduleResponse, DeleteBackupScheduleResponses, DeleteBlobRequest, DeleteBlobResponse, DeleteConnectionData, DeleteConnectionErrors, DeleteConnectionResponse, DeleteConnectionResponses, DeleteCustomDomainData, DeleteCustomDomainErrors, DeleteCustomDomainResponse, DeleteCustomDomainResponses, DeleteDashboardData, DeleteDashboardError, DeleteDashboardErrors, DeleteDashboardResponse, DeleteDashboardResponses, DeleteDeploymentTokenData, DeleteDeploymentTokenErrors, DeleteDeploymentTokenResponse, DeleteDeploymentTokenResponses, DeleteDnsProviderData, DeleteDnsProviderErrors, DeleteDnsProviderResponse, DeleteDnsProviderResponses, DeleteDomainData, DeleteDomainErrors, DeleteDomainResponse, DeleteDomainResponses, DeleteEmailDomainData, DeleteEmailDomainErrors, DeleteEmailDomainResponse, DeleteEmailDomainResponses, DeleteEmailProviderData, DeleteEmailProviderErrors, DeleteEmailProviderResponse, DeleteEmailProviderResponses, DeleteEnvironmentData, DeleteEnvironmentDomainData, DeleteEnvironmentDomainErrors, DeleteEnvironmentDomainResponse, DeleteEnvironmentDomainResponses, DeleteEnvironmentErrors, DeleteEnvironmentResponse, DeleteEnvironmentResponses, DeleteEnvironmentVariableData, DeleteEnvironmentVariableErrors, DeleteEnvironmentVariableResponse, DeleteEnvironmentVariableResponses, DeleteExternalImageData, DeleteExternalImageErrors, DeleteExternalImageResponse, DeleteExternalImageResponses, DeleteFunnelData, DeleteFunnelErrors, DeleteFunnelResponses, DeleteGitProviderData, DeleteGitProviderErrors, DeleteGitProviderResponse, DeleteGitProviderResponses, DeleteGlobalMcpData, DeleteGlobalMcpErrors, DeleteGlobalMcpResponse, DeleteGlobalMcpResponses, DeleteGlobalSkillData, DeleteGlobalSkillErrors, DeleteGlobalSkillResponse, DeleteGlobalSkillResponses, DeleteIpAccessControlData, DeleteIpAccessControlError, DeleteIpAccessControlErrors, DeleteIpAccessControlResponse, DeleteIpAccessControlResponses, DeleteMcpData, DeleteMcpErrors, DeleteMcpResponse, DeleteMcpResponses, DeleteMonitorData, DeleteMonitorErrors, DeleteMonitorResponse, DeleteMonitorResponses, DeleteNotificationProviderData, DeleteNotificationProviderErrors, DeleteNotificationProviderResponse, DeleteNotificationProviderResponses, DeleteOidcProviderData, DeleteOidcProviderResponse, DeleteOidcProviderResponses, DeleteOidcRoleMappingData, DeleteOidcRoleMappingResponse, DeleteOidcRoleMappingResponses, DeletePreferencesData, DeletePreferencesErrors, DeletePreferencesResponse, DeletePreferencesResponses, DeleteProjectData, DeleteProjectErrors, DeleteProjectResponse, DeleteProjectResponses, DeleteProjectSecretData, DeleteProjectSecretErrors, DeleteProjectSecretResponse, DeleteProjectSecretResponses, DeleteProviderKeyData, DeleteProviderKeyError, DeleteProviderKeyErrors, DeleteProviderKeyResponse, DeleteProviderKeyResponses, DeleteProviderSafelyData, DeleteProviderSafelyErrors, DeleteProviderSafelyResponse, DeleteProviderSafelyResponses, DeleteReleaseSourceFilesData, DeleteReleaseSourceFilesErrors, DeleteReleaseSourceFilesResponse, DeleteReleaseSourceFilesResponses, DeleteReleaseSourceMapsData, DeleteReleaseSourceMapsErrors, DeleteReleaseSourceMapsResponse, DeleteReleaseSourceMapsResponses, DeleteResponse, DeleteRouteData, DeleteRouteErrors, DeleteRouteResponse, DeleteRouteResponses, DeleteS3SourceData, DeleteS3SourceError, DeleteS3SourceErrors, DeleteS3SourceResponse, DeleteS3SourceResponses, DeleteScanData, DeleteScanError, DeleteScanErrors, DeleteScanResponse, DeleteScanResponses, DeleteSecretData, DeleteSecretErrors, DeleteSecretResponse, DeleteSecretResponses, DeleteServiceData, DeleteServiceErrors, DeleteServiceResponse, DeleteServiceResponses, DeleteSessionReplayData, DeleteSessionReplayError, DeleteSessionReplayErrors, DeleteSessionReplayResponses, DeleteSkillData, DeleteSkillErrors, DeleteSkillResponse, DeleteSkillResponses, DeleteSourceMapData, DeleteSourceMapErrors, DeleteSourceMapResponse, DeleteSourceMapResponses, DeleteStaticBundleData, DeleteStaticBundleErrors, DeleteStaticBundleResponse, DeleteStaticBundleResponses, DeleteTeamData, DeleteTeamErrors, DeleteTeamResponse, DeleteTeamResponses, DeleteUserData, DeleteUserErrors, DeleteUserResponse, DeleteUserResponses, DeleteWebhookData, DeleteWebhookErrors, DeleteWebhookResponse, DeleteWebhookResponses, DelRequest, DelResponse, DeployFromImageData, DeployFromImageErrors, DeployFromImageRequest, DeployFromImageResponse, DeployFromImageResponses, DeployFromImageUploadData, DeployFromImageUploadErrors, DeployFromImageUploadQuery, DeployFromImageUploadResponse, DeployFromImageUploadResponses, DeployFromStaticData, DeployFromStaticErrors, DeployFromStaticRequest, DeployFromStaticResponse, DeployFromStaticResponses, DeploymentConfig, DeploymentConfigSnapshot, DeploymentConfiguration, DeploymentContainerLogContentResponse, DeploymentContainerLogResponse, DeploymentContainerLogsListResponse, DeploymentEnvironmentResponse, DeploymentJobResponse, DeploymentJobsResponse, DeploymentListResponse, DeploymentMetadata, DeploymentMetricsGetLatestData, DeploymentMetricsGetLatestErrors, DeploymentMetricsGetLatestResponse, DeploymentMetricsGetLatestResponses, DeploymentMetricsGetRangeData, DeploymentMetricsGetRangeErrors, DeploymentMetricsGetRangeResponse, DeploymentMetricsGetRangeResponses, DeploymentMetricsToggleData, DeploymentMetricsToggleErrors, DeploymentMetricsToggleResponses, DeploymentResponse, DeploymentStateResponse, DeploymentStrategy, DeploymentTokenListResponse, DeploymentTokenResponse, DestroySandboxData, DestroySandboxErrors, DestroySandboxResponse, DestroySandboxResponses, DetachScheduleServiceData, DetachScheduleServiceError, DetachScheduleServiceErrors, DetachScheduleServiceResponse, DetachScheduleServiceResponses, DetectionConfig, DetectPublicPresetsData, DetectPublicPresetsErrors, DetectPublicPresetsResponse, DetectPublicPresetsResponses, DeviceCount, DigestSections, Direction, DisableBackupScheduleData, DisableBackupScheduleErrors, DisableBackupScheduleResponse, DisableBackupScheduleResponses, DisableBlobResponse, DisableKvResponse, DisableMfaData, DisableMfaErrors, DisableMfaRequest, DisableMfaResponse, DisableMfaResponses, DiscoverRequest, DiscoverResponse, DiscoverWorkloadsData, DiscoverWorkloadsErrors, DiscoverWorkloadsResponse, DiscoverWorkloadsResponses, DiskInfo, DiskSpaceAlert, DiskSpaceAlertSettings, DiskSpaceCheckResult, DnsAckRequest, DnsAckResponse, DnsChallengeRecordResult, DnsChangesResponse, DnsCompletionResponse, DnsLookupError, DnsLookupRequest, DnsLookupResponse, DnsProviderCredentials, DnsProviderResponse, DnsProviderSettings, DnsProviderSettingsMasked, DnsProviderType, DnsRecord, DnsRecordChange, DnsRecordContent, DnsRecordResponse, DnsRecordSetupResult, DnsRecordStatusResponse, DnsZone, DockerComposePresetConfig, DockerfilePresetConfig, DockerfileVariant, DockerRegistrySettings, DockerRegistrySettingsMasked, DomainAction, DomainChallengeResponse, DomainData, DomainEnvironmentResponse, DomainError, DomainErrors, DomainPlan, DomainResponse, DomainResponse2, DomainResponses, DownloadGlobalSkillArchiveData, DownloadGlobalSkillArchiveErrors, DownloadGlobalSkillArchiveResponse, DownloadGlobalSkillArchiveResponses, DownloadObjectData, DownloadObjectErrors, DownloadObjectResponse, DownloadObjectResponses, DownloadSkillArchiveData, DownloadSkillArchiveErrors, DownloadSkillArchiveResponse, DownloadSkillArchiveResponses, DrainNodeResponse, DrainStatusResponse, DropOffPoint, EmailConfig, EmailDomainResponse, EmailDomainWithDnsResponse, EmailProviderResponse, EmailProviderTypeRoute, EmailRequest, EmailResponse, EmailStatsResponse, EmailStatusData, EmailStatusErrors, EmailStatusResponse, EmailStatusResponse2, EmailStatusResponses, EmailTrackingResponse, EmailTrackingSetupResponse, EmailTrackingStatusResponse, EmbeddingData, EmbeddingInput, EmbeddingRequest, EmbeddingResponse, EmbeddingsData, EmbeddingsError, EmbeddingsErrors, EmbeddingsResponse, EmbeddingsResponses, EmbeddingUsage, EnableBackupScheduleData, EnableBackupScheduleErrors, EnableBackupScheduleResponse, EnableBackupScheduleResponses, EnableBlobRequest, EnableBlobResponse, EnableKvRequest, EnableKvResponse, EnablePgStatStatementsResponse, EndpointDto, EnqueuedJob, EnrichVisitorData, EnrichVisitorErrors, EnrichVisitorRequest, EnrichVisitorResponse, EnrichVisitorResponse2, EnrichVisitorResponses, EnrollmentTokenInfo, EnrollmentTokenListResponse, EntityInfoResponse, EntityResponse, EnvironmentConfiguration, EnvironmentDomainResponse, EnvironmentInfo, EnvironmentResponse, EnvironmentVariable, EnvironmentVariableInfo, EnvironmentVariableResponse, EnvironmentVariableValueResponse, EnvVarInput, EnvVarIntegrationInfo, EnvVarResponse, EnvVarTemplateResponse, ErrorDashboardStatsQuery, ErrorDashboardStatsResponse, ErrorEventResponse, ErrorGroupResponse, ErrorGroupStatsResponse, ErrorResponse, ErrorRow, ErrorTimeSeriesDataResponse, ErrorTimeSeriesQuery, EventActivityBucket, EventBreakdown, EventBrowserStats, EventCount, EventCountryStats, EventDetailQuery, EventDetailResponse, EventEntriesQuery, EventEntriesResponse, EventEntryInfo, EventKind, EventMetricsPayload, EventReferrerStats, EventsCountQuery, EventsResponse, EventTimeline, EventTimelineQuery, EventType, EventTypeBreakdown, EventTypeBreakdownQuery, EventTypeResponse, EventTypesResponse, EventVisitorInfo, EventVisitorsQuery, EventVisitorsResponse, ExecBody, ExecData, ExecDetachedData, ExecDetachedErrors, ExecDetachedResponse, ExecDetachedResponse2, ExecDetachedResponses, ExecErrors, ExecResponse, ExecResponse2, ExecResponses, ExecuteDeploymentOperationData, ExecuteDeploymentOperationErrors, ExecuteDeploymentOperationResponse, ExecuteDeploymentOperationResponses, ExecuteImportData, ExecuteImportErrors, ExecuteImportRequest, ExecuteImportResponse, ExecuteImportResponse2, ExecuteImportResponses, ExecuteOperationRequest, ExpireRequest, ExpireResponse, ExplorerSupportResponse, ExtendTimeoutBody, ExtendTimeoutData, ExtendTimeoutErrors, ExtendTimeoutResponse, ExtendTimeoutResponses, ExternalImageResponse, ExternalServiceBackupResponse, ExternalServiceDetails, ExternalServiceEnablePgStatStatementsData, ExternalServiceEnablePgStatStatementsErrors, ExternalServiceEnablePgStatStatementsResponse, ExternalServiceEnablePgStatStatementsResponses, ExternalServiceInfo, ExternalServiceMetricsByDatabaseData, ExternalServiceMetricsByDatabaseErrors, ExternalServiceMetricsByDatabaseResponse, ExternalServiceMetricsByDatabaseResponses, ExternalServiceMetricsCreateAlertRuleData, ExternalServiceMetricsCreateAlertRuleErrors, ExternalServiceMetricsCreateAlertRuleResponse, ExternalServiceMetricsCreateAlertRuleResponses, ExternalServiceMetricsDeleteAlertRuleData, ExternalServiceMetricsDeleteAlertRuleErrors, ExternalServiceMetricsDeleteAlertRuleResponse, ExternalServiceMetricsDeleteAlertRuleResponses, ExternalServiceMetricsGetAlertRulesData, ExternalServiceMetricsGetAlertRulesErrors, ExternalServiceMetricsGetAlertRulesResponse, ExternalServiceMetricsGetAlertRulesResponses, ExternalServiceMetricsGetLatestData, ExternalServiceMetricsGetLatestErrors, ExternalServiceMetricsGetLatestResponse, ExternalServiceMetricsGetLatestResponses, ExternalServiceMetricsGetRangeData, ExternalServiceMetricsGetRangeErrors, ExternalServiceMetricsGetRangeResponse, ExternalServiceMetricsGetRangeResponses, ExternalServiceMetricsStatusData, ExternalServiceMetricsStatusErrors, ExternalServiceMetricsStatusResponse, ExternalServiceMetricsStatusResponses, ExternalServiceMetricsToggleData, ExternalServiceMetricsToggleErrors, ExternalServiceMetricsToggleResponses, ExternalServiceMetricsUpdateAlertRuleData, ExternalServiceMetricsUpdateAlertRuleErrors, ExternalServiceMetricsUpdateAlertRuleResponse, ExternalServiceMetricsUpdateAlertRuleResponses, ExternalServiceResetPgStatStatementsData, ExternalServiceResetPgStatStatementsErrors, ExternalServiceResetPgStatStatementsResponse, ExternalServiceResetPgStatStatementsResponses, ExternalServiceSummary, FieldResponse, FinalizeOrderData, FinalizeOrderErrors, FinalizeOrderResponse, FinalizeOrderResponses, FinalizeProjectReleaseData, FinalizeProjectReleaseErrors, FinalizeProjectReleaseResponse, FinalizeProjectReleaseResponses, FindConversationData, FindConversationErrors, FindConversationResponse, FindConversationResponses, FiringSeriesEntry, FlagEnvironmentResponse, FlagListResponse, FlagResponse, FlagSnapshot, FlagSnapshotResponse, FlagValueType, ForecastAlgorithm, ForecastParams, FullError, FullEvent, FullRequest, FunnelMetricsResponse, FunnelResponse, GatewayStatus, GenAiEvent, GenAiSpanDetail, GenAiTraceDetailResponse, GenAiTraceSummariesResponse, GenAiTraceSummary, GeneralStatsQuery, GeneralStatsResponse, GenerateDockerfileRequest, GenerateDockerfileResponse, GenerateJoinTokenData, GenerateJoinTokenErrors, GenerateJoinTokenResponse, GenerateJoinTokenResponse2, GenerateJoinTokenResponses, GeneratePresetDockerfileData, GeneratePresetDockerfileErrors, GeneratePresetDockerfileResponse, GeneratePresetDockerfileResponses, GeoLocationResponse, GeoRestrictionsConfig, GetAccessInfoData, GetAccessInfoErrors, GetAccessInfoResponse, GetAccessInfoResponses, GetActiveVisitorsData, GetActiveVisitorsErrors, GetActiveVisitorsResponse, GetActiveVisitorsResponses, GetActivityGraphData, GetActivityGraphErrors, GetActivityGraphResponse, GetActivityGraphResponses, GetAdminGateData, GetAdminGateErrors, GetAdminGateResponse, GetAdminGateResponses, GetAgentData, GetAgentErrors, GetAgentResponse, GetAgentResponses, GetAggregatedBucketsData, GetAggregatedBucketsErrors, GetAggregatedBucketsResponse, GetAggregatedBucketsResponses, GetAiAgentBreakdownData, GetAiAgentBreakdownError, GetAiAgentBreakdownErrors, GetAiAgentBreakdownResponse, GetAiAgentBreakdownResponses, GetAiAgentPagesData, GetAiAgentPagesError, GetAiAgentPagesErrors, GetAiAgentPagesResponse, GetAiAgentPagesResponses, GetAiAgentTimelineData, GetAiAgentTimelineError, GetAiAgentTimelineErrors, GetAiAgentTimelineResponse, GetAiAgentTimelineResponses, GetAiPageBreakdownData, GetAiPageBreakdownError, GetAiPageBreakdownErrors, GetAiPageBreakdownResponse, GetAiPageBreakdownResponses, GetAiStatusBreakdownData, GetAiStatusBreakdownError, GetAiStatusBreakdownErrors, GetAiStatusBreakdownResponse, GetAiStatusBreakdownResponses, GetAlertData, GetAlertError, GetAlertErrors, GetAlertResponse, GetAlertResponses, GetAlertRuleData, GetAlertRuleErrors, GetAlertRuleResponse, GetAlertRuleResponses, GetAllRepositoriesByNameData, GetAllRepositoriesByNameErrors, GetAllRepositoriesByNameResponse, GetAllRepositoriesByNameResponses, GetAnalyticsActiveVisitorsData, GetAnalyticsActiveVisitorsErrors, GetAnalyticsActiveVisitorsResponse, GetAnalyticsActiveVisitorsResponses, GetAnalyticsEventsCountData, GetAnalyticsEventsCountErrors, GetAnalyticsEventsCountResponse, GetAnalyticsEventsCountResponses, GetAnalyticsSessionEventsData, GetAnalyticsSessionEventsErrors, GetAnalyticsSessionEventsResponse, GetAnalyticsSessionEventsResponses, GetAnalyticsVisitorSessionsData, GetAnalyticsVisitorSessionsErrors, GetAnalyticsVisitorSessionsResponse, GetAnalyticsVisitorSessionsResponses, GetApiKeyData, GetApiKeyErrors, GetApiKeyPermissionsData, GetApiKeyPermissionsErrors, GetApiKeyPermissionsResponse, GetApiKeyPermissionsResponses, GetApiKeyResponse, GetApiKeyResponses, GetAuditLogData, GetAuditLogErrors, GetAuditLogResponse, GetAuditLogResponses, GetBackupData, GetBackupError, GetBackupErrors, GetBackupResponse, GetBackupResponses, GetBackupScheduleData, GetBackupScheduleErrors, GetBackupScheduleResponse, GetBackupScheduleResponses, GetBranchesByRepositoryIdData, GetBranchesByRepositoryIdErrors, GetBranchesByRepositoryIdResponse, GetBranchesByRepositoryIdResponses, GetBucketedIncidentsData, GetBucketedIncidentsErrors, GetBucketedIncidentsResponse, GetBucketedIncidentsResponses, GetBucketedStatusData, GetBucketedStatusErrors, GetBucketedStatusResponse, GetBucketedStatusResponses, GetChallengeTokenData, GetChallengeTokenErrors, GetChallengeTokenResponse, GetChallengeTokenResponses, GetChatReadinessData, GetChatReadinessErrors, GetChatReadinessResponse, GetChatReadinessResponses, GetCliStatusData, GetCliStatusErrors, GetCliStatusResponses, GetClusterHealthData, GetClusterHealthErrors, GetClusterHealthResponse, GetClusterHealthResponses, GetClusterMemberData, GetClusterMemberErrors, GetClusterMemberResponse, GetClusterMemberResponses, GetCmdData, GetCmdErrors, GetCmdResponse, GetCmdResponses, GetContainerDetailData, GetContainerDetailErrors, GetContainerDetailResponse, GetContainerDetailResponses, GetContainerEnvironmentVariableData, GetContainerEnvironmentVariableErrors, GetContainerEnvironmentVariableResponse, GetContainerEnvironmentVariableResponses, GetContainerInfoData, GetContainerInfoErrors, GetContainerInfoResponse, GetContainerInfoResponses, GetContainerLogsByIdData, GetContainerLogsByIdErrors, GetContainerLogsData, GetContainerLogsErrors, GetContainerMetricsData, GetContainerMetricsErrors, GetContainerMetricsResponse, GetContainerMetricsResponses, GetConversationData, GetConversationDetailData, GetConversationDetailError, GetConversationDetailErrors, GetConversationDetailResponse, GetConversationDetailResponses, GetConversationErrors, GetConversationResponse, GetConversationResponses, GetConversationsData, GetConversationsError, GetConversationsErrors, GetConversationsResponse, GetConversationsResponses, GetCronByIdData, GetCronByIdErrors, GetCronByIdResponse, GetCronByIdResponses, GetCronExecutionsData, GetCronExecutionsErrors, GetCronExecutionsResponse, GetCronExecutionsResponses, GetCrossProjectTraceSiblingsData, GetCrossProjectTraceSiblingsError, GetCrossProjectTraceSiblingsErrors, GetCrossProjectTraceSiblingsResponse, GetCrossProjectTraceSiblingsResponses, GetCurrentMonitorStatusData, GetCurrentMonitorStatusErrors, GetCurrentMonitorStatusResponse, GetCurrentMonitorStatusResponses, GetCurrentUserData, GetCurrentUserErrors, GetCurrentUserResponse, GetCurrentUserResponses, GetCustomDomainData, GetCustomDomainErrors, GetCustomDomainResponse, GetCustomDomainResponses, GetDashboardData, GetDashboardError, GetDashboardErrors, GetDashboardProjectsAnalyticsData, GetDashboardProjectsAnalyticsErrors, GetDashboardProjectsAnalyticsResponse, GetDashboardProjectsAnalyticsResponses, GetDashboardResponse, GetDashboardResponses, GetDeliveryData, GetDeliveryErrors, GetDeliveryResponse, GetDeliveryResponses, GetDeploymentContainerLogContentData, GetDeploymentContainerLogContentErrors, GetDeploymentContainerLogContentResponse, GetDeploymentContainerLogContentResponses, GetDeploymentData, GetDeploymentErrors, GetDeploymentJobLogsData, GetDeploymentJobLogsErrors, GetDeploymentJobLogsResponse, GetDeploymentJobLogsResponses, GetDeploymentJobsData, GetDeploymentJobsErrors, GetDeploymentJobsResponse, GetDeploymentJobsResponses, GetDeploymentOperationsData, GetDeploymentOperationsErrors, GetDeploymentOperationsResponse, GetDeploymentOperationsResponses, GetDeploymentOperationStatusData, GetDeploymentOperationStatusErrors, GetDeploymentOperationStatusResponse, GetDeploymentOperationStatusResponses, GetDeploymentResponse, GetDeploymentResponses, GetDeploymentsParams, GetDeploymentTokenData, GetDeploymentTokenErrors, GetDeploymentTokenResponse, GetDeploymentTokenResponses, GetDiskStatusData, GetDiskStatusErrors, GetDiskStatusResponse, GetDiskStatusResponses, GetDnsChangesData, GetDnsChangesErrors, GetDnsChangesResponse, GetDnsChangesResponses, GetDnsProviderData, GetDnsProviderErrors, GetDnsProviderResponse, GetDnsProviderResponses, GetDomainByHostData, GetDomainByHostErrors, GetDomainByHostResponse, GetDomainByHostResponses, GetDomainByIdData, GetDomainByIdErrors, GetDomainByIdResponse, GetDomainByIdResponses, GetDomainByNameData, GetDomainByNameErrors, GetDomainByNameResponse, GetDomainByNameResponses, GetDomainData, GetDomainDnsRecordsData, GetDomainDnsRecordsErrors, GetDomainDnsRecordsResponse, GetDomainDnsRecordsResponses, GetDomainErrors, GetDomainOrderData, GetDomainOrderErrors, GetDomainOrderResponse, GetDomainOrderResponses, GetDomainResponse, GetDomainResponses, GetEmailData, GetEmailErrors, GetEmailEventsData, GetEmailEventsErrors, GetEmailEventsResponse, GetEmailEventsResponses, GetEmailLinksData, GetEmailLinksErrors, GetEmailLinksResponse, GetEmailLinksResponses, GetEmailProviderData, GetEmailProviderErrors, GetEmailProviderResponse, GetEmailProviderResponses, GetEmailResponse, GetEmailResponses, GetEmailStatsData, GetEmailStatsErrors, GetEmailStatsResponse, GetEmailStatsResponses, GetEmailTrackingData, GetEmailTrackingErrors, GetEmailTrackingResponse, GetEmailTrackingResponses, GetEmailTrackingStatusData, GetEmailTrackingStatusErrors, GetEmailTrackingStatusResponse, GetEmailTrackingStatusResponses, GetEntityInfoData, GetEntityInfoErrors, GetEntityInfoResponse, GetEntityInfoResponses, GetEnvironmentCronsData, GetEnvironmentCronsErrors, GetEnvironmentCronsResponse, GetEnvironmentCronsResponses, GetEnvironmentData, GetEnvironmentDomainsData, GetEnvironmentDomainsErrors, GetEnvironmentDomainsResponse, GetEnvironmentDomainsResponses, GetEnvironmentErrors, GetEnvironmentResponse, GetEnvironmentResponses, GetEnvironmentsData, GetEnvironmentsErrors, GetEnvironmentsResponse, GetEnvironmentsResponses, GetEnvironmentVariablesData, GetEnvironmentVariablesErrors, GetEnvironmentVariablesQuery, GetEnvironmentVariablesResponse, GetEnvironmentVariablesResponses, GetEnvironmentVariableValueData, GetEnvironmentVariableValueErrors, GetEnvironmentVariableValueResponse, GetEnvironmentVariableValueResponses, GetErrorDashboardStatsData, GetErrorDashboardStatsErrors, GetErrorDashboardStatsResponse, GetErrorDashboardStatsResponses, GetErrorEventData, GetErrorEventErrors, GetErrorEventResponse, GetErrorEventResponses, GetErrorGroupData, GetErrorGroupErrors, GetErrorGroupResponse, GetErrorGroupResponses, GetErrorStatsData, GetErrorStatsErrors, GetErrorStatsResponse, GetErrorStatsResponses, GetErrorTimeSeriesData, GetErrorTimeSeriesErrors, GetErrorTimeSeriesResponse, GetErrorTimeSeriesResponses, GetEventDetailData, GetEventDetailErrors, GetEventDetailResponse, GetEventDetailResponses, GetEventEntriesData, GetEventEntriesErrors, GetEventEntriesResponse, GetEventEntriesResponses, GetEventsCountData, GetEventsCountErrors, GetEventsCountResponse, GetEventsCountResponses, GetEventsTimelineData, GetEventsTimelineErrors, GetEventsTimelineResponse, GetEventsTimelineResponses, GetEventTypeBreakdownData, GetEventTypeBreakdownErrors, GetEventTypeBreakdownResponse, GetEventTypeBreakdownResponses, GetEventVisitorsData, GetEventVisitorsErrors, GetEventVisitorsResponse, GetEventVisitorsResponses, GetExternalImageData, GetExternalImageErrors, GetExternalImageResponse, GetExternalImageResponses, GetFileData, GetFileErrors, GetFileResponse, GetFileResponses, GetFlagData, GetFlagErrors, GetFlagResponse, GetFlagResponses, GetFlagSnapshotData, GetFlagSnapshotErrors, GetFlagSnapshotResponse, GetFlagSnapshotResponses, GetFunnelMetricsData, GetFunnelMetricsErrors, GetFunnelMetricsQuery, GetFunnelMetricsResponse, GetFunnelMetricsResponses, GetGenaiTraceData, GetGenaiTraceError, GetGenaiTraceErrors, GetGenaiTraceResponse, GetGenaiTraceResponses, GetGeneralStatsData, GetGeneralStatsErrors, GetGeneralStatsResponse, GetGeneralStatsResponses, GetGitProviderData, GetGitProviderErrors, GetGitProviderResponse, GetGitProviderResponses, GetGlobalEventsData, GetGlobalEventsErrors, GetGlobalEventsResponse, GetGlobalEventsResponses, GetGlobalEventStatsData, GetGlobalEventStatsErrors, GetGlobalEventStatsResponse, GetGlobalEventStatsResponses, GetGlobalMcpData, GetGlobalMcpErrors, GetGlobalMcpResponse, GetGlobalMcpResponses, GetGlobalSandboxStatusData, GetGlobalSandboxStatusErrors, GetGlobalSandboxStatusResponse, GetGlobalSandboxStatusResponses, GetGlobalSkillData, GetGlobalSkillErrors, GetGlobalSkillResponse, GetGlobalSkillResponses, GetGroupedPageMetricsData, GetGroupedPageMetricsError, GetGroupedPageMetricsErrors, GetGroupedPageMetricsResponse, GetGroupedPageMetricsResponses, GetHealthData, GetHealthError, GetHealthErrors, GetHealthResponse, GetHealthResponses, GetHourlyVisitsData, GetHourlyVisitsErrors, GetHourlyVisitsResponse, GetHourlyVisitsResponses, GetHttpChallengeDebugData, GetHttpChallengeDebugErrors, GetHttpChallengeDebugResponse, GetHttpChallengeDebugResponses, GetImportStatusData, GetImportStatusErrors, GetImportStatusResponse, GetImportStatusResponses, GetIncidentData, GetIncidentErrors, GetIncidentResponse, GetIncidentResponses, GetIncidentUpdatesData, GetIncidentUpdatesErrors, GetIncidentUpdatesResponse, GetIncidentUpdatesResponses, GetIpAccessControlData, GetIpAccessControlError, GetIpAccessControlErrors, GetIpAccessControlResponse, GetIpAccessControlResponses, GetIpGeolocationData, GetIpGeolocationError, GetIpGeolocationErrors, GetIpGeolocationResponse, GetIpGeolocationResponses, GetJoinTokenStatusData, GetJoinTokenStatusErrors, GetJoinTokenStatusResponse, GetJoinTokenStatusResponses, GetLastDeploymentData, GetLastDeploymentErrors, GetLastDeploymentResponse, GetLastDeploymentResponses, GetLatestScanData, GetLatestScanError, GetLatestScanErrors, GetLatestScanResponse, GetLatestScanResponses, GetLatestScansPerEnvironmentData, GetLatestScansPerEnvironmentError, GetLatestScansPerEnvironmentErrors, GetLatestScansPerEnvironmentResponse, GetLatestScansPerEnvironmentResponses, GetLiveVisitorsListData, GetLiveVisitorsListErrors, GetLiveVisitorsListResponse, GetLiveVisitorsListResponses, GetLogContextData, GetLogContextError, GetLogContextErrors, GetLogContextResponse, GetLogContextResponses, GetMcpData, GetMcpErrors, GetMcpResponse, GetMcpResponses, GetMetricsOverTimeData, GetMetricsOverTimeError, GetMetricsOverTimeErrors, GetMetricsOverTimeResponse, GetMetricsOverTimeResponses, GetMonitorData, GetMonitorErrors, GetMonitorResponse, GetMonitorResponses, GetNotificationProviderData, GetNotificationProviderErrors, GetNotificationProviderResponse, GetNotificationProviderResponses, GetOnDemandCertStatusData, GetOnDemandCertStatusErrors, GetOnDemandCertStatusResponse, GetOnDemandCertStatusResponses, GetOrCreateDsnData, GetOrCreateDsnErrors, GetOrCreateDsnRequest, GetOrCreateDsnResponse, GetOrCreateDsnResponses, GetPageFlowData, GetPageFlowErrors, GetPageFlowResponse, GetPageFlowResponses, GetPageHourlySessionsData, GetPageHourlySessionsErrors, GetPageHourlySessionsResponse, GetPageHourlySessionsResponses, GetPagePathDetailData, GetPagePathDetailErrors, GetPagePathDetailResponse, GetPagePathDetailResponses, GetPagePathsData, GetPagePathsErrors, GetPagePathsResponse, GetPagePathsResponses, GetPagePathsSparklinesData, GetPagePathsSparklinesErrors, GetPagePathsSparklinesResponse, GetPagePathsSparklinesResponses, GetPagePathVisitorsData, GetPagePathVisitorsErrors, GetPagePathVisitorsResponse, GetPagePathVisitorsResponses, GetPendingActionData, GetPendingActionErrors, GetPendingActionResponse, GetPendingActionResponses, GetPerformanceMetricsData, GetPerformanceMetricsError, GetPerformanceMetricsErrors, GetPerformanceMetricsResponse, GetPerformanceMetricsResponses, GetPgUpgradeData, GetPgUpgradeErrors, GetPgUpgradeLogsData, GetPgUpgradeLogsErrors, GetPgUpgradeLogsResponse, GetPgUpgradeLogsResponses, GetPgUpgradeResponse, GetPgUpgradeResponses, GetPipelineStatsData, GetPipelineStatsError, GetPipelineStatsErrors, GetPipelineStatsResponse, GetPipelineStatsResponses, GetPlatformInfoData, GetPlatformInfoErrors, GetPlatformInfoResponse, GetPlatformInfoResponses, GetPostgresWalHealthData, GetPostgresWalHealthErrors, GetPostgresWalHealthResponse, GetPostgresWalHealthResponses, GetPreferencesData, GetPreferencesErrors, GetPreferencesResponse, GetPreferencesResponses, GetPreviewGatewayLogsData, GetPreviewGatewayLogsResponse, GetPreviewGatewayLogsResponses, GetPreviewGatewaySettingsData, GetPreviewGatewaySettingsResponse, GetPreviewGatewaySettingsResponses, GetPreviewGatewayStatusData, GetPreviewGatewayStatusResponse, GetPreviewGatewayStatusResponses, GetPricingData, GetPricingError, GetPricingErrors, GetPricingResponse, GetPricingResponses, GetPrivateIpData, GetPrivateIpErrors, GetPrivateIpResponses, GetProjectAlarmsSummaryData, GetProjectAlarmsSummaryErrors, GetProjectAlarmsSummaryResponse, GetProjectAlarmsSummaryResponses, GetProjectBySlugData, GetProjectBySlugErrors, GetProjectBySlugResponse, GetProjectBySlugResponses, GetProjectData, GetProjectDeploymentsData, GetProjectDeploymentsErrors, GetProjectDeploymentsResponse, GetProjectDeploymentsResponses, GetProjectErrors, GetProjectResponse, GetProjectResponses, GetProjectsData, GetProjectSecretsQuery, GetProjectsErrors, GetProjectServiceEnvironmentVariablesData, GetProjectServiceEnvironmentVariablesErrors, GetProjectServiceEnvironmentVariablesResponse, GetProjectServiceEnvironmentVariablesResponses, GetProjectSessionReplaysData, GetProjectSessionReplaysError, GetProjectSessionReplaysErrors, GetProjectSessionReplaysQuery, GetProjectSessionReplaysResponse, GetProjectSessionReplaysResponse2, GetProjectSessionReplaysResponses, GetProjectsHealthData, GetProjectsHealthError, GetProjectsHealthErrors, GetProjectsHealthResponse, GetProjectsHealthResponses, GetProjectsMonitorHealthData, GetProjectsMonitorHealthErrors, GetProjectsMonitorHealthResponse, GetProjectsMonitorHealthResponses, GetProjectsResponse, GetProjectsResponses, GetProjectStatisticsData, GetProjectStatisticsErrors, GetProjectStatisticsResponse, GetProjectStatisticsResponses, GetProjectTemplateData, GetProjectTemplateErrors, GetProjectTemplateResponse, GetProjectTemplateResponses, GetPropertyBreakdownData, GetPropertyBreakdownErrors, GetPropertyBreakdownResponse, GetPropertyBreakdownResponses, GetPropertyTimelineData, GetPropertyTimelineErrors, GetPropertyTimelineResponse, GetPropertyTimelineResponses, GetProviderConnectionsData, GetProviderConnectionsErrors, GetProviderConnectionsResponse, GetProviderConnectionsResponses, GetProviderMetadataData, GetProviderMetadataErrors, GetProviderMetadataResponse, GetProviderMetadataResponses, GetProvidersMetadataData, GetProvidersMetadataErrors, GetProvidersMetadataResponse, GetProvidersMetadataResponses, GetProxyLogByIdData, GetProxyLogByIdError, GetProxyLogByIdErrors, GetProxyLogByIdResponse, GetProxyLogByIdResponses, GetProxyLogByRequestIdData, GetProxyLogByRequestIdError, GetProxyLogByRequestIdErrors, GetProxyLogByRequestIdResponse, GetProxyLogByRequestIdResponses, GetProxyLogsData, GetProxyLogsError, GetProxyLogsErrors, GetProxyLogsResponse, GetProxyLogsResponses, GetPublicBranchesData, GetPublicBranchesErrors, GetPublicBranchesResponse, GetPublicBranchesResponses, GetPublicIpData, GetPublicIpErrors, GetPublicIpResponses, GetPublicRepositoryData, GetPublicRepositoryErrors, GetPublicRepositoryResponse, GetPublicRepositoryResponses, GetQuotaData, GetQuotaError, GetQuotaErrors, GetQuotaResponse, GetQuotaResponses, GetRecentActivityData, GetRecentActivityErrors, GetRecentActivityResponse, GetRecentActivityResponses, GetRemoteExternalImageData, GetRemoteExternalImageErrors, GetRemoteExternalImageResponse, GetRemoteExternalImageResponses, GetRepositoryBranchesData, GetRepositoryBranchesErrors, GetRepositoryBranchesResponse, GetRepositoryBranchesResponses, GetRepositoryByIdData, GetRepositoryByIdErrors, GetRepositoryByIdResponse, GetRepositoryByIdResponses, GetRepositoryByNameData, GetRepositoryByNameErrors, GetRepositoryByNameResponse, GetRepositoryByNameResponses, GetRepositoryPresetByNameData, GetRepositoryPresetByNameErrors, GetRepositoryPresetByNameResponse, GetRepositoryPresetByNameResponses, GetRepositoryPresetLiveData, GetRepositoryPresetLiveErrors, GetRepositoryPresetLiveResponse, GetRepositoryPresetLiveResponses, GetRepositoryTagsData, GetRepositoryTagsErrors, GetRepositoryTagsResponse, GetRepositoryTagsResponses, GetRequest, GetResolvedEnvironmentVariablesData, GetResolvedEnvironmentVariablesErrors, GetResolvedEnvironmentVariablesResponse, GetResolvedEnvironmentVariablesResponses, GetResolvedEnvironmentVariableValueData, GetResolvedEnvironmentVariableValueErrors, GetResolvedEnvironmentVariableValueResponse, GetResolvedEnvironmentVariableValueResponses, GetResponse, GetRestoreCapabilitiesData, GetRestoreCapabilitiesError, GetRestoreCapabilitiesErrors, GetRestoreCapabilitiesResponse, GetRestoreCapabilitiesResponses, GetRestoreRunData, GetRestoreRunError, GetRestoreRunErrors, GetRestoreRunResponse, GetRestoreRunResponses, GetRouteData, GetRouteErrors, GetRouteResponse, GetRouteResponses, GetRunData, GetRunErrors, GetRunResponse, GetRunResponses, GetRunWithLogsData, GetRunWithLogsErrors, GetRunWithLogsResponse, GetRunWithLogsResponses, GetS3CredentialsData, GetS3CredentialsErrors, GetS3CredentialsResponse, GetS3CredentialsResponses, GetS3SourceData, GetS3SourceError, GetS3SourceErrors, GetS3SourceResponse, GetS3SourceResponses, GetSandboxData, GetSandboxErrors, GetSandboxResponse, GetSandboxResponses, GetSandboxStatusData, GetSandboxStatusErrors, GetSandboxStatusResponse, GetSandboxStatusResponses, GetScanByDeploymentData, GetScanByDeploymentError, GetScanByDeploymentErrors, GetScanByDeploymentResponse, GetScanByDeploymentResponses, GetScanData, GetScanError, GetScanErrors, GetScanResponse, GetScanResponses, GetScanVulnerabilitiesData, GetScanVulnerabilitiesError, GetScanVulnerabilitiesErrors, GetScanVulnerabilitiesResponse, GetScanVulnerabilitiesResponses, GetServiceBySlugData, GetServiceBySlugErrors, GetServiceBySlugResponse, GetServiceBySlugResponses, GetServiceData, GetServiceEnvironmentVariableData, GetServiceEnvironmentVariableErrors, GetServiceEnvironmentVariableResponse, GetServiceEnvironmentVariableResponses, GetServiceEnvironmentVariablesData, GetServiceEnvironmentVariablesErrors, GetServiceEnvironmentVariablesResponse, GetServiceEnvironmentVariablesResponses, GetServiceErrors, GetServiceHealthStatusData, GetServiceHealthStatusErrors, GetServiceHealthStatusResponse, GetServiceHealthStatusResponses, GetServicePreviewEnvironmentVariableNamesData, GetServicePreviewEnvironmentVariableNamesErrors, GetServicePreviewEnvironmentVariableNamesResponse, GetServicePreviewEnvironmentVariableNamesResponses, GetServicePreviewEnvironmentVariablesMaskedData, GetServicePreviewEnvironmentVariablesMaskedErrors, GetServicePreviewEnvironmentVariablesMaskedResponse, GetServicePreviewEnvironmentVariablesMaskedResponses, GetServiceResponse, GetServiceResponses, GetServiceRuntimeData, GetServiceRuntimeErrors, GetServiceRuntimeResponse, GetServiceRuntimeResponses, GetServiceStatsData, GetServiceStatsErrors, GetServiceStatsResponse, GetServiceStatsResponses, GetServiceTypeParametersData, GetServiceTypeParametersErrors, GetServiceTypeParametersResponses, GetServiceTypesData, GetServiceTypesErrors, GetServiceTypesResponse, GetServiceTypesResponses, GetSessionDetailsData, GetSessionDetailsErrors, GetSessionDetailsResponse, GetSessionDetailsResponses, GetSessionEventsData, GetSessionEventsErrors, GetSessionEventsResponse, GetSessionEventsResponses, GetSessionLogsData, GetSessionLogsErrors, GetSessionLogsResponse, GetSessionLogsResponses, GetSessionReplayData, GetSessionReplayError, GetSessionReplayErrors, GetSessionReplayEventsData, GetSessionReplayEventsError, GetSessionReplayEventsErrors, GetSessionReplayEventsResponse, GetSessionReplayEventsResponses, GetSessionReplayResponse, GetSessionReplayResponse2, GetSessionReplayResponses, GetSettingsData, GetSettingsErrors, GetSettingsResponse, GetSettingsResponses, GetSkillData, GetSkillErrors, GetSkillResponse, GetSkillResponses, GetSlowQueriesData, GetSlowQueriesErrors, GetSlowQueriesResponse, GetSlowQueriesResponses, GetStaticBundleData, GetStaticBundleErrors, GetStaticBundleResponse, GetStaticBundleResponses, GetStatusOverviewData, GetStatusOverviewErrors, GetStatusOverviewResponse, GetStatusOverviewResponses, GetTagsByRepositoryIdData, GetTagsByRepositoryIdErrors, GetTagsByRepositoryIdResponse, GetTagsByRepositoryIdResponses, GetTeamData, GetTeamErrors, GetTeamResponse, GetTeamResponses, GetTimeBucketStatsData, GetTimeBucketStatsError, GetTimeBucketStatsErrors, GetTimeBucketStatsResponse, GetTimeBucketStatsResponses, GetTodayStatsData, GetTodayStatsError, GetTodayStatsErrors, GetTodayStatsResponse, GetTodayStatsResponses, GetTraceData, GetTraceError, GetTraceErrors, GetTraceResponse, GetTraceResponses, GetUnifiedTraceData, GetUnifiedTraceError, GetUnifiedTraceErrors, GetUnifiedTraceResponse, GetUnifiedTraceResponses, GetUniqueCountsData, GetUniqueCountsErrors, GetUniqueCountsResponse, GetUniqueCountsResponses, GetUniqueEventsData, GetUniqueEventsErrors, GetUniqueEventsQuery, GetUniqueEventsResponse, GetUniqueEventsResponses, GetUpdateStatusData, GetUpdateStatusErrors, GetUpdateStatusResponse, GetUpdateStatusResponses, GetUptimeHistoryData, GetUptimeHistoryErrors, GetUptimeHistoryResponse, GetUptimeHistoryResponses, GetUsageByProviderData, GetUsageByProviderError, GetUsageByProviderErrors, GetUsageByProviderResponse, GetUsageByProviderResponses, GetUsageRecentData, GetUsageRecentError, GetUsageRecentErrors, GetUsageRecentResponse, GetUsageRecentResponses, GetUsageSummaryData, GetUsageSummaryError, GetUsageSummaryErrors, GetUsageSummaryResponse, GetUsageSummaryResponses, GetUsageTimeseriesData, GetUsageTimeseriesError, GetUsageTimeseriesErrors, GetUsageTimeseriesResponse, GetUsageTimeseriesResponses, GetUsageTopModelsData, GetUsageTopModelsError, GetUsageTopModelsErrors, GetUsageTopModelsResponse, GetUsageTopModelsResponses, GetVisitorByGuidData, GetVisitorByGuidErrors, GetVisitorByGuidResponse, GetVisitorByGuidResponses, GetVisitorByIdData, GetVisitorByIdErrors, GetVisitorByIdResponse, GetVisitorByIdResponses, GetVisitorDetailsData, GetVisitorDetailsErrors, GetVisitorDetailsResponse, GetVisitorDetailsResponses, GetVisitorFacetsData, GetVisitorFacetsErrors, GetVisitorFacetsResponse, GetVisitorFacetsResponses, GetVisitorInfoData, GetVisitorInfoErrors, GetVisitorInfoResponse, GetVisitorInfoResponses, GetVisitorJourneyData, GetVisitorJourneyErrors, GetVisitorJourneyResponse, GetVisitorJourneyResponses, GetVisitorsData, GetVisitorsErrors, GetVisitorSessionsData, GetVisitorSessionsError, GetVisitorSessionsErrors, GetVisitorSessionsQuery, GetVisitorSessionsResponse, GetVisitorSessionsResponse2, GetVisitorSessionsResponses, GetVisitorsResponse, GetVisitorsResponses, GetVisitorStatsData, GetVisitorStatsErrors, GetVisitorStatsResponse, GetVisitorStatsResponses, GetWebhookData, GetWebhookErrors, GetWebhookResponse, GetWebhookResponses, GitPushEvent, GitRefResponse, GitSourcePlan, GlobalConversationResponse, GlobalEventStatsResponse, GlobalMrrResponse, GlobalRecentEventResponse, GlobalRevenueSummaryResponse, GrantProjectAccessData, GrantProjectAccessErrors, GrantProjectAccessResponse, GrantProjectAccessResponses, GroupedPageMetric, GroupedPageMetricsQuery, GroupedPageMetricsResponse, HandleGitProviderOauthCallbackData, HandleGitProviderOauthCallbackErrors, HasAnalyticsEventsData, HasAnalyticsEventsErrors, HasAnalyticsEventsResponse, HasAnalyticsEventsResponse2, HasAnalyticsEventsResponses, HasErrorGroupsData, HasErrorGroupsErrors, HasErrorGroupsResponse, HasErrorGroupsResponse2, HasErrorGroupsResponses, HasEventsQuery, HasEventsResponse, HasMetricsQuery, HasMetricsResponse, HasPerformanceMetricsData, HasPerformanceMetricsError, HasPerformanceMetricsErrors, HasPerformanceMetricsResponse, HasPerformanceMetricsResponses, HealthCheckConfiguration, HealthCheckEntryResponse, HealthResponse, HealthStatus, HealthSummary, HeartbeatApiRequest, HeartbeatResponse, HierarchyLevel, HistogramSummary, HostnameChange, HostnamePreviewResponse, HourlyPageSessions, HourlyVisitsQuery, HttpChallengeDebugResponse, ImportCredentials, ImportExecutionStatus, ImportExternalServiceData, ImportExternalServiceErrors, ImportExternalServiceRequest, ImportExternalServiceResponse, ImportExternalServiceResponses, ImportOutcomeResponse, ImportPlan, ImportRowErrorResponse, ImportSelector, ImportSource, ImportSourceCapabilities, ImportSourceInfo, ImportStatusResponse, IncidentBucket, IncidentBucketedResponse, IncidentResponse, IncidentUpdateResponse, IncrRequest, IncrResponse, IngestLogsByPathData, IngestLogsByPathError, IngestLogsByPathErrors, IngestLogsByPathResponses, IngestLogsData, IngestLogsError, IngestLogsErrors, IngestLogsResponses, IngestMetricsByPathData, IngestMetricsByPathError, IngestMetricsByPathErrors, IngestMetricsByPathResponses, IngestMetricsData, IngestMetricsError, IngestMetricsErrors, IngestMetricsResponses, IngestSentryEnvelopeData, IngestSentryEnvelopeErrors, IngestSentryEnvelopeResponses, IngestSentryEventData, IngestSentryEventErrors, IngestSentryEventResponse, IngestSentryEventResponses, IngestTracesByPathData, IngestTracesByPathError, IngestTracesByPathErrors, IngestTracesByPathResponses, IngestTracesData, IngestTracesError, IngestTracesErrors, IngestTracesResponses, InitAuthResponse, InitSessionReplayData, InitSessionReplayError, InitSessionReplayErrors, InitSessionReplayResponse, InitSessionReplayResponses, Insight, InsightSeverity, InsightsResponse, InsightStatus, IntegrationResponse, IpAccessControlQuery, IpAccessControlResponse, JobLogsData, JobLogsErrors, JobLogsResponses, JobStatusData, JobStatusErrors, JobStatusResponse, JobStatusResponse2, JobStatusResponses, JobSummaryResponse, JoinTokenStatusResponse, JourneyEvent, JourneySession, KeysRequest, KeysResponse, KillJobBody, KillJobData, KillJobErrors, KillJobResponse, KillJobResponses, KnownAiAgentsResponse, KvDelData, KvDelErrors, KvDelResponse, KvDelResponses, KvDisableData, KvDisableErrors, KvDisableResponse, KvDisableResponses, KvEnableData, KvEnableErrors, KvEnableResponse, KvEnableResponses, KvExpireData, KvExpireErrors, KvExpireResponse, KvExpireResponses, KvGetData, KvGetErrors, KvGetResponse, KvGetResponses, KvIncrData, KvIncrErrors, KvIncrResponse, KvIncrResponses, KvKeysData, KvKeysErrors, KvKeysResponse, KvKeysResponses, KvSetData, KvSetErrors, KvSetResponse, KvSetResponses, KvStatusData, KvStatusErrors, KvStatusResponse, KvStatusResponse2, KvStatusResponses, KvTtlData, KvTtlErrors, KvTtlResponse, KvTtlResponses, KvUpdateData, KvUpdateErrors, KvUpdateResponse, KvUpdateResponses, LatestRunForSourceData, LatestRunForSourceErrors, LatestRunForSourceResponse, LatestRunForSourceResponses, LemonSqueezyConfig, LetsEncryptSettings, LineContext, LinkCustomDomainToCertificateData, LinkCustomDomainToCertificateErrors, LinkCustomDomainToCertificateResponse, LinkCustomDomainToCertificateResponses, LinkServiceRequest, LinkServiceToProjectData, LinkServiceToProjectErrors, LinkServiceToProjectResponse, LinkServiceToProjectResponses, ListAgentRunsData, ListAgentRunsErrors, ListAgentRunsResponse, ListAgentRunsResponses, ListAgentsData, ListAgentsErrors, ListAgentsResponse, ListAgentsResponse2, ListAgentsResponses, ListAiProvidersData, ListAiProvidersErrors, ListAiProvidersResponse, ListAiProvidersResponses, ListAlertRulesData, ListAlertRulesErrors, ListAlertRulesResponse, ListAlertRulesResponses, ListAlertsData, ListAlertsError, ListAlertsErrors, ListAlertsResponse, ListAlertsResponses, ListAllConversationsData, ListAllConversationsErrors, ListAllConversationsResponse, ListAllConversationsResponses, ListAllRunsData, ListAllRunsErrors, ListAllRunsResponse, ListAllRunsResponses, ListApiKeysData, ListApiKeysErrors, ListApiKeysQuery, ListApiKeysResponse, ListApiKeysResponses, ListAuditLogsData, ListAuditLogsErrors, ListAuditLogsQuery, ListAuditLogsResponse, ListAuditLogsResponses, ListAvailableContainersData, ListAvailableContainersErrors, ListAvailableContainersResponse, ListAvailableContainersResponses, ListBackupAlertsData, ListBackupAlertsError, ListBackupAlertsErrors, ListBackupAlertsResponse, ListBackupAlertsResponses, ListBackupChildrenData, ListBackupChildrenError, ListBackupChildrenErrors, ListBackupChildrenResponse, ListBackupChildrenResponses, ListBackupSchedulesData, ListBackupSchedulesError, ListBackupSchedulesErrors, ListBackupSchedulesResponse, ListBackupSchedulesResponses, ListBackupsForScheduleData, ListBackupsForScheduleErrors, ListBackupsForScheduleResponse, ListBackupsForScheduleResponses, ListBlobsQuery, ListBlobsResponse, ListCommitsByRepositoryIdData, ListCommitsByRepositoryIdErrors, ListCommitsByRepositoryIdResponse, ListCommitsByRepositoryIdResponses, ListConnectionsData, ListConnectionsErrors, ListConnectionsResponse, ListConnectionsResponses, ListContainersAtPathData, ListContainersAtPathErrors, ListContainersAtPathResponse, ListContainersAtPathResponses, ListContainersData, ListContainersErrors, ListContainersResponse, ListContainersResponses, ListConversationsData, ListConversationsErrors, ListConversationsResponse, ListConversationsResponses, ListCustomDomainsForProjectData, ListCustomDomainsForProjectErrors, ListCustomDomainsForProjectResponse, ListCustomDomainsForProjectResponses, ListCustomDomainsResponse, ListDashboardsData, ListDashboardsError, ListDashboardsErrors, ListDashboardsResponse, ListDashboardsResponses, ListDeliveriesData, ListDeliveriesErrors, ListDeliveriesResponse, ListDeliveriesResponses, ListDeploymentContainerLogsData, ListDeploymentContainerLogsErrors, ListDeploymentContainerLogsResponse, ListDeploymentContainerLogsResponses, ListDeploymentTokensData, ListDeploymentTokensErrors, ListDeploymentTokensQuery, ListDeploymentTokensResponse, ListDeploymentTokensResponses, ListDnsProvidersData, ListDnsProvidersErrors, ListDnsProvidersResponse, ListDnsProvidersResponses, ListDomainsData, ListDomainsErrors, ListDomainsResponse, ListDomainsResponse2, ListDomainsResponses, ListDsnsData, ListDsnsErrors, ListDsnsResponse, ListDsnsResponses, ListEmailDomainsData, ListEmailDomainsErrors, ListEmailDomainsResponse, ListEmailDomainsResponses, ListEmailProvidersData, ListEmailProvidersErrors, ListEmailProvidersResponse, ListEmailProvidersResponses, ListEmailsData, ListEmailsErrors, ListEmailsResponse, ListEmailsResponses, ListEnrollmentTokensData, ListEnrollmentTokensErrors, ListEnrollmentTokensResponse, ListEnrollmentTokensResponses, ListEntitiesData, ListEntitiesErrors, ListEntitiesQuery, ListEntitiesResponse, ListEntitiesResponses, ListErrorEventsData, ListErrorEventsErrors, ListErrorEventsQuery, ListErrorEventsResponse, ListErrorEventsResponses, ListErrorGroupsData, ListErrorGroupsErrors, ListErrorGroupsQuery, ListErrorGroupsResponse, ListErrorGroupsResponses, ListEventsData, ListEventsResponse, ListEventsResponses, ListEventTypesData, ListEventTypesResponse, ListEventTypesResponses, ListExternalImagesData, ListExternalImagesErrors, ListExternalImagesResponse, ListExternalImagesResponses, ListExternalPluginsData, ListExternalPluginsErrors, ListExternalPluginsResponse, ListExternalPluginsResponses, ListExternalServiceBackupsData, ListExternalServiceBackupsError, ListExternalServiceBackupsErrors, ListExternalServiceBackupsResponse, ListExternalServiceBackupsResponses, ListFlagsData, ListFlagsErrors, ListFlagsResponse, ListFlagsResponses, ListFunnelsData, ListFunnelsErrors, ListFunnelsResponse, ListFunnelsResponses, ListGitProvidersData, ListGitProvidersErrors, ListGitProvidersResponse, ListGitProvidersResponses, ListGlobalMcpsData, ListGlobalMcpsErrors, ListGlobalMcpsResponse, ListGlobalMcpsResponses, ListGlobalSkillsData, ListGlobalSkillsErrors, ListGlobalSkillsResponse, ListGlobalSkillsResponses, ListIncidentsData, ListIncidentsErrors, ListIncidentsResponses, ListInsightsData, ListInsightsError, ListInsightsErrors, ListInsightsResponse, ListInsightsResponses, ListIpAccessControlData, ListIpAccessControlError, ListIpAccessControlErrors, ListIpAccessControlResponse, ListIpAccessControlResponses, ListJobsData, ListJobsErrors, ListJobsResponse, ListJobsResponse2, ListJobsResponses, ListKnownAiAgentsData, ListKnownAiAgentsError, ListKnownAiAgentsErrors, ListKnownAiAgentsResponse, ListKnownAiAgentsResponses, ListManagedDomainsData, ListManagedDomainsErrors, ListManagedDomainsResponse, ListManagedDomainsResponses, ListMcpsData, ListMcpsErrors, ListMcpsResponse, ListMcpsResponse2, ListMcpsResponses, ListMetricLabelKeysData, ListMetricLabelKeysError, ListMetricLabelKeysErrors, ListMetricLabelKeysResponse, ListMetricLabelKeysResponses, ListMetricLabelValuesData, ListMetricLabelValuesError, ListMetricLabelValuesErrors, ListMetricLabelValuesResponse, ListMetricLabelValuesResponses, ListMetricNamesData, ListMetricNamesError, ListMetricNamesErrors, ListMetricNamesResponse, ListMetricNamesResponses, ListModelsData, ListModelsError, ListModelsErrors, ListModelsResponse, ListModelsResponses, ListMonitorsData, ListMonitorsErrors, ListMonitorsResponse, ListMonitorsResponses, ListNotificationProvidersData, ListNotificationProvidersErrors, ListNotificationProvidersResponse, ListNotificationProvidersResponses, ListOidcProvidersData, ListOidcProvidersResponse, ListOidcProvidersResponses, ListOidcProviderUsersData, ListOidcProviderUsersErrors, ListOidcProviderUsersResponse, ListOidcProviderUsersResponses, ListOidcRoleMappingsData, ListOidcRoleMappingsResponse, ListOidcRoleMappingsResponses, ListOnDemandCertsData, ListOnDemandCertsErrors, ListOnDemandCertsResponse, ListOnDemandCertsResponse2, ListOnDemandCertsResponses, ListOrdersData, ListOrdersErrors, ListOrdersResponse, ListOrdersResponse2, ListOrdersResponses, ListPeersData, ListPeersErrors, ListPeersResponse, ListPeersResponses, ListPendingActionsData, ListPendingActionsErrors, ListPendingActionsResponse, ListPendingActionsResponses, ListPgUpgradesData, ListPgUpgradesErrors, ListPgUpgradesResponse, ListPgUpgradesResponses, ListPresetsData, ListPresetsErrors, ListPresetsResponse, ListPresetsResponse2, ListPresetsResponses, ListProjectAccessData, ListProjectAccessErrors, ListProjectAccessResponse, ListProjectAccessResponses, ListProjectAlarmsData, ListProjectAlarmsErrors, ListProjectAlarmsResponse, ListProjectAlarmsResponses, ListProjectScansData, ListProjectScansError, ListProjectScansErrors, ListProjectScansResponse, ListProjectScansResponses, ListProjectSecretsData, ListProjectSecretsErrors, ListProjectSecretsResponse, ListProjectSecretsResponses, ListProjectServicesData, ListProjectServicesErrors, ListProjectServicesResponse, ListProjectServicesResponses, ListProjectTemplatesData, ListProjectTemplatesErrors, ListProjectTemplatesResponse, ListProjectTemplatesResponses, ListProjectTemplateTagsData, ListProjectTemplateTagsErrors, ListProjectTemplateTagsResponse, ListProjectTemplateTagsResponses, ListProviderKeysData, ListProviderKeysError, ListProviderKeysErrors, ListProviderKeysResponse, ListProviderKeysResponses, ListProviderZonesData, ListProviderZonesErrors, ListProviderZonesResponse, ListProviderZonesResponses, ListPublicProvidersData, ListPublicProvidersResponse, ListPublicProvidersResponses, ListReleaseFilesData, ListReleaseFilesErrors, ListReleaseFilesResponse, ListReleaseFilesResponses, ListReleasesData, ListReleasesErrors, ListReleasesResponse, ListReleasesResponses, ListRemoteExternalImagesData, ListRemoteExternalImagesErrors, ListRemoteExternalImagesResponse, ListRemoteExternalImagesResponses, ListRepositoriesByConnectionData, ListRepositoriesByConnectionErrors, ListRepositoriesByConnectionResponse, ListRepositoriesByConnectionResponses, ListRepositoriesByProviderData, ListRepositoriesByProviderErrors, ListRepositoriesByProviderResponse, ListRepositoriesByProviderResponses, ListRestoreRunsForServiceData, ListRestoreRunsForServiceResponse, ListRestoreRunsForServiceResponses, ListRootContainersData, ListRootContainersErrors, ListRootContainersResponse, ListRootContainersResponses, ListRoutesData, ListRoutesErrors, ListRoutesResponse, ListRoutesResponses, ListRunsResponse, ListS3SourcesData, ListS3SourcesError, ListS3SourcesErrors, ListS3SourcesResponse, ListS3SourcesResponses, ListSandboxesData, ListSandboxesResponse, ListSandboxesResponse2, ListSandboxesResponses, ListScansQuery, ListScheduleRunJobsData, ListScheduleRunJobsError, ListScheduleRunJobsErrors, ListScheduleRunJobsResponse, ListScheduleRunJobsResponses, ListScheduleRunsData, ListScheduleRunsError, ListScheduleRunsErrors, ListScheduleRunsResponse, ListScheduleRunsResponses, ListScheduleServicesData, ListScheduleServicesError, ListScheduleServicesErrors, ListScheduleServicesResponse, ListScheduleServicesResponses, ListSecretsData, ListSecretsErrors, ListSecretsResponse, ListSecretsResponse2, ListSecretsResponses, ListServiceHealthStatusesData, ListServiceHealthStatusesErrors, ListServiceHealthStatusesResponse, ListServiceHealthStatusesResponses, ListServiceProjectsData, ListServiceProjectsErrors, ListServiceProjectsResponse, ListServiceProjectsResponses, ListServiceSchedulesData, ListServiceSchedulesError, ListServiceSchedulesErrors, ListServiceSchedulesResponse, ListServiceSchedulesResponses, ListServicesData, ListServicesErrors, ListServicesResponse, ListServicesResponses, ListSkillsData, ListSkillsErrors, ListSkillsResponse, ListSkillsResponse2, ListSkillsResponses, ListSourceBackupsData, ListSourceBackupsError, ListSourceBackupsErrors, ListSourceBackupsResponse, ListSourceBackupsResponses, ListSourceFilesData, ListSourceFilesErrors, ListSourceFilesResponse, ListSourceFilesResponses, ListSourceMapsData, ListSourceMapsErrors, ListSourceMapsResponse, ListSourceMapsResponses, ListSourcesData, ListSourcesErrors, ListSourcesResponse, ListSourcesResponses, ListStaticBundlesData, ListStaticBundlesErrors, ListStaticBundlesResponse, ListStaticBundlesResponses, ListSyncedRepositoriesData, ListSyncedRepositoriesErrors, ListSyncedRepositoriesResponse, ListSyncedRepositoriesResponses, ListTagsResponse, ListTeamMembersData, ListTeamMembersErrors, ListTeamMembersResponse, ListTeamMembersResponses, ListTeamProjectsData, ListTeamProjectsErrors, ListTeamProjectsResponse, ListTeamProjectsResponses, ListTeamsData, ListTeamsErrors, ListTeamsResponse, ListTeamsResponses, ListTemplatesQuery, ListTemplatesResponse, ListUsersData, ListUsersErrors, ListUsersResponse, ListUsersResponses, ListVulnerabilitiesQuery, ListWebhooksData, ListWebhooksErrors, ListWebhooksResponse, ListWebhooksResponses, LiveVisitorInfo, LiveVisitorsListResponse, LocationCount, LocationGranularity, LocationInfo, LoginData, LoginErrors, LoginRequest, LoginResponse, LoginResponses, LogLevel, LogoutData, LogoutErrors, LogoutResponses, LogRecord, LogSearchLine, LogSeverity, LogSource, LogsQuery, LogsResponse, LogStream, LookupDnsARecordsData, LookupDnsARecordsError, LookupDnsARecordsErrors, LookupDnsARecordsResponse, LookupDnsARecordsResponses, ManagedDomainResponse, ManualAction, ManualActionTiming, McpDefinitionResponse, MessageContent, MessagePart, MessageResponse, MeteredMode, MetricAggregation, MetricBucket, MetricDataPoint, MetricsOverTimeResponse, MetricsQuery, MetricsRangeQuery, MetricsStatusResponse, MetricsStoreKind, MetricsSummaryResponse, MetricType, MfaRequiredResponse, MfaSetupResponse, MfaVerificationRequest, MigrationStep, MigrationSummary, MintEnrollmentTokenData, MintEnrollmentTokenErrors, MintEnrollmentTokenRequest, MintEnrollmentTokenResponse, MintEnrollmentTokenResponse2, MintEnrollmentTokenResponses, MiscResult, MkdirBody, MkdirData, MkdirErrors, MkdirResponse, MkdirResponses, ModelInfo, ModelListResponse, ModelPricing, ModelUsage, MonitoringSettings, MonitoringSettingsMasked, MonitorResponse, MonitorStatus, MrrBucketResponse, MultiNodeSettings, MultiNodeSettingsMasked, MxResult, NavEntry, NavSection, NetworkConfiguration, NetworkMode, NixpacksPresetConfig, NixpacksProvider, NodeContainerListResponse, NodeContainerResponse, NodeCostInfo, NodeHeartbeatData, NodeHeartbeatErrors, NodeHeartbeatResponse, NodeHeartbeatResponses, NodeInfoResponse, NodeListResponse, NodeMetricsGetRangeData, NodeMetricsGetRangeErrors, NodeMetricsGetRangeResponse, NodeMetricsGetRangeResponses, NotificationPreferencesResponse, NotificationProviderResponse, ObservabilityCompressionSettings, ObservabilityEvent, ObservabilityFullEventData, ObservabilityFullEventError, ObservabilityFullEventErrors, ObservabilityFullEventResponse, ObservabilityFullEventResponses, ObservabilityListEventsData, ObservabilityListEventsError, ObservabilityListEventsErrors, ObservabilityListEventsResponse, ObservabilityListEventsResponses, ObservabilityRetentionSettings, OidcCallbackData, OidcProviderResponse, OidcProvidersListResponse, OidcProviderSummary, OidcProviderUserResponse, OidcRoleMappingResponse, OidcTestConnectionResponse, OnDemandCertAttemptResponse, OnDemandCertRow, OnDemandTlsSettings, OpenAiError, OpenAiErrorResponse, OperatingSystemCount, OperationResultResponse, OperationResultsResponse, OtelDashboardResponse, OtelDashboardsResponse, OtelMetricAlertRuleResponse, OtelMetricAlertsResponse, OtelMetricLabelKeysResponse, OtelMetricLabelValuesResponse, OtelMetricNamesResponse, OtelMetricsResponse, OutlierAlgorithm, OutlierParams, OverprovisioningAssessment, OverprovisioningVerdict, PageActivityBucket, PageCountryStats, PageFlowEntry, PageFlowQuery, PageFlowResponse, PageHourlySessionsQuery, PageHourlySessionsResponse, PagePathDetailQuery, PagePathDetailResponse, PagePathInfo, PagePathSparkline, PagePathSparklinePoint, PagePathsQuery, PagePathsResponse, PagePathsSparklineQuery, PagePathsSparklineResponse, PagePathVisitorsQuery, PagePathVisitorsResponse, PageReferrerStats, PagesComparisonResponse, PageSessionComparison, PageSessionStats, PageSessionStatsQuery, PageTransition, PageVisit, PageVisitorSession, PaginatedEmailsResponse, PaginatedEntitiesResponse, PaginatedErrorEventsResponse, PaginatedErrorGroupsResponse, PaginatedEventsResponse, PaginatedExternalImagesResponse, PaginatedProjectList, PaginatedStaticBundlesResponse, Pagination, PaginationMeta, PaginationParams, PasswordProtectionConfig, PatchAdminGateData, PatchAdminGateErrors, PatchAdminGateResponse, PatchAdminGateResponses, PatchPreviewGatewaySettingsData, PatchPreviewGatewaySettingsResponse, PatchPreviewGatewaySettingsResponses, PatchSettingsRequest, PathVisitors, PathVisitorsAnalyticsQuery, PathVisitorsResponse, PauseDeploymentData, PauseDeploymentErrors, PauseDeploymentResponse, PauseDeploymentResponses, PauseSandboxData, PauseSandboxErrors, PauseSandboxResponse, PauseSandboxResponses, PeerEntry, PeerListResponse, PendingActionResponse, PerformanceMetricsQuery, PerformanceMetricsResponse, PermissionInfo, PgUpgradeLogResponse, PgUpgradeResponse, PipelineStats, PipelineStatsResponse, PlanComplexity, PlanMetadata, PlanRestoreData, PlanRestoreError, PlanRestoreErrors, PlanRestoreResponse, PlanRestoreResponses, PlanSourceBackup, PlanTarget, PlatformInfo, PluginManifest, PortMapping, PostDnsAckData, PostDnsAckErrors, PostDnsAckResponse, PostDnsAckResponses, PostgresWalHealth, PresetConfigSchema, PresetInfo, PresetResponse, PreviewAlertData, PreviewAlertError, PreviewAlertErrors, PreviewAlertResponse, PreviewAlertResponses, PreviewFunnelMetricsData, PreviewFunnelMetricsErrors, PreviewFunnelMetricsResponse, PreviewFunnelMetricsResponses, PreviewGatewaySettings, PreviewGatewaySettingsMasked, PreviewGatewaySettingsResponse, PreviewHostnameModeData, PreviewHostnameModeErrors, PreviewHostnameModeResponse, PreviewHostnameModeResponses, PreviewShareLinkBody, PreviewShareLinkResponse, PricingResponse, ProblemDetails, ProjectAccessResponse, ProjectConfiguration, ProjectDashboardAnalytics, ProjectDsnResponse, ProjectHealthSummary, ProjectInfo, ProjectMonitorHealth, ProjectPresetResponse, ProjectQuery, ProjectRef, ProjectResponse, ProjectSecretEnvironmentInfo, ProjectSecretResponse, ProjectServiceInfo, ProjectsHealthResponse, ProjectsMonitorHealthResponse, ProjectStatisticsResponse, ProjectStatsBreakdown, ProjectType, ProjectUsageInfoResponse, PromoteClusterMemberData, PromoteClusterMemberErrors, PromoteClusterMemberResponses, PromoteDeploymentData, PromoteDeploymentErrors, PromoteDeploymentRequest, PromoteDeploymentResponse, PromoteDeploymentResponses, PropertyBreakdownItem, PropertyBreakdownQuery, PropertyBreakdownResponse, PropertyColumn, PropertyTimelineItem, PropertyTimelineQuery, PropertyTimelineResponse, Protocol, ProviderCatalogDto, ProviderCatalogResponse, ProviderConfig, ProviderConfigMasked, ProviderDeletionCheckResponse, ProviderDescriptor, ProviderKeyResponse, ProviderMetadata, ProviderResponse, ProviderUsage, ProvisionDomainData, ProvisionDomainErrors, ProvisionDomainResponse, ProvisionDomainResponses, ProvisionResponse, ProxyLogResponse, ProxyLogsPaginatedResponse, PublicHostnameStrategy, PublicPresetResponse, PublicRepositoryInfo, PurgeLogsRequest, PurgeProjectLogsData, PurgeProjectLogsError, PurgeProjectLogsErrors, PurgeProjectLogsResponses, PushedExternalImageResponse, PushExternalImageData, PushExternalImageErrors, PushExternalImageResponse, PushExternalImageResponses, PushImageRequest, QueryDataData, QueryDataErrors, QueryDataRequest, QueryDataResponse, QueryDataResponse2, QueryDataResponses, QueryGenaiTracesData, QueryGenaiTracesError, QueryGenaiTracesErrors, QueryGenaiTracesResponse, QueryGenaiTracesResponses, QueryLogsData, QueryLogsError, QueryLogsErrors, QueryLogsResponse, QueryLogsResponses, QueryMetricsData, QueryMetricsError, QueryMetricsErrors, QueryMetricsResponse, QueryMetricsResponses, QueryTracesData, QueryTracesError, QueryTracesErrors, QueryTracesResponse, QueryTracesResponses, QueryTraceSummariesData, QueryTraceSummariesError, QueryTraceSummariesErrors, QueryTraceSummariesResponse, QueryTraceSummariesResponses, QuotaResponse, RateLimitConfig, RateLimitSettings, ReachabilityStatus, ReadFileData, ReadFileErrors, ReadFileResponse, ReadFileResponse2, ReadFileResponses, ReAnalyzeData, ReAnalyzeErrors, ReAnalyzeResponses, RebuildSandboxImageData, RebuildSandboxImageErrors, RebuildSandboxImageResponses, RecentActivityQuery, RecentActivityResponse, RecentEventResponse, RecentQueryParams, RecordConsoleEventData, RecordConsoleEventErrors, RecordConsoleEventResponses, RecordEventMetricsData, RecordEventMetricsErrors, RecordEventMetricsResponse, RecordEventMetricsResponses, RecordExposureRequest, RecordExposureResponse, RecordFlagExposureData, RecordFlagExposureErrors, RecordFlagExposureResponse, RecordFlagExposureResponses, RecordListResponse, RecordSpeedMetricsData, RecordSpeedMetricsError, RecordSpeedMetricsErrors, RecordSpeedMetricsResponse, RecordSpeedMetricsResponses, RecoveryTarget, ReferrerCount, ReferrersAnalyticsQuery, RefreshRouteTableData, RefreshRouteTableErrors, RefreshRouteTableResponse, RefreshRouteTableResponses, RegenerateDsnData, RegenerateDsnErrors, RegenerateDsnRequest, RegenerateDsnResponse, RegenerateDsnResponses, RegisterExternalImageData, RegisterExternalImageErrors, RegisterExternalImageResponse, RegisterExternalImageResponses, RegisterImageRequest, RegisterNodeApiRequest, RegisterNodeData, RegisterNodeErrors, RegisterNodeResponse, RegisterNodeResponse2, RegisterNodeResponses, RegisterRequest, ReinstallGitlabWebhookData, ReinstallGitlabWebhookErrors, ReinstallGitlabWebhookResponse, ReinstallGitlabWebhookResponses, ReinstallWebhookResponse, RejectPendingActionData, RejectPendingActionErrors, RejectPendingActionResponse, RejectPendingActionResponses, ReleaseListResponse, ReloadPluginsData, ReloadPluginsErrors, ReloadPluginsResponse, ReloadPluginsResponses, ReloadResponse, RemoteDeploymentResponse, RemoveClusterMemberData, RemoveClusterMemberErrors, RemoveClusterMemberResponse, RemoveClusterMemberResponses, RemoveManagedDomainData, RemoveManagedDomainErrors, RemoveManagedDomainResponse, RemoveManagedDomainResponses, RemoveNodeResponse, RemoveRoleData, RemoveRoleErrors, RemoveRoleResponse, RemoveRoleResponses, RemoveTeamMemberData, RemoveTeamMemberErrors, RemoveTeamMemberResponse, RemoveTeamMemberResponses, RenameConversationData, RenameConversationErrors, RenameConversationRequest, RenameConversationResponse, RenameConversationResponses, RenewDomainData, RenewDomainErrors, RenewDomainResponse, RenewDomainResponses, RepositoryListQuery, RepositoryListResponse, RepositoryPresetResponse, RepositoryResponse, RepositorySyncStartedResponse, RequestPasswordResetData, RequestPasswordResetErrors, RequestPasswordResetResponse, RequestPasswordResetResponses, RequestRow, ResetPasswordData, ResetPasswordErrors, ResetPasswordRequest, ResetPasswordResponse, ResetPasswordResponses, ResetPgStatStatementsRequest, ResetPgStatStatementsResponse, ResizeSandboxBody, ResizeSandboxData, ResizeSandboxErrors, ResizeSandboxResponse, ResizeSandboxResponses, ResolveAlarmData, ResolveAlarmErrors, ResolveAlarmResponses, ResolvedEnvVarResponse, ResolvedEnvVarSource, ResourceCounts, ResourceFootprint, ResourceInfo, ResourceLimitApplyResult, ResourceLimits, ResourceLimitsResponse, ResourceLimitsUpdateResponse, ResourcesBody, RestartContainerData, RestartContainerErrors, RestartContainerResponse, RestartContainerResponses, RestartPreviewGatewayData, RestartPreviewGatewayResponse, RestartPreviewGatewayResponses, RestartSandboxData, RestartSandboxErrors, RestartSandboxResponse, RestartSandboxResponses, RestoreCapabilities, RestoreCapabilitiesResponse, RestoreFlagData, RestoreFlagErrors, RestoreFlagResponse, RestoreFlagResponses, RestorePlan, RestoreRequestMode, RestoreRunView, RestoreUserData, RestoreUserErrors, RestoreUserResponse, RestoreUserResponses, ResumeDeploymentData, ResumeDeploymentErrors, ResumeDeploymentResponse, ResumeDeploymentResponses, ResumeSandboxData, ResumeSandboxErrors, ResumeSandboxResponse, ResumeSandboxResponses, RetentionCleanupFailure, RetentionCleanupReport, RetryClusterData, RetryClusterErrors, RetryClusterRequest, RetryClusterResponse, RetryClusterResponses, RetryDeliveryData, RetryDeliveryErrors, RetryDeliveryResponse, RetryDeliveryResponses, RetryPgUpgradeData, RetryPgUpgradeErrors, RetryPgUpgradeResponse, RetryPgUpgradeResponses, RetryRunData, RetryRunErrors, RetryRunResponse, RetryRunResponses, RevealGlobalMcpConfigData, RevealGlobalMcpConfigErrors, RevealGlobalMcpConfigResponse, RevealGlobalMcpConfigResponses, RevealMcpConfigData, RevealMcpConfigErrors, RevealMcpConfigResponse, RevealMcpConfigResponses, RevealNotificationProviderConfigData, RevealNotificationProviderConfigErrors, RevealNotificationProviderConfigResponse, RevealNotificationProviderConfigResponses, RevealServiceParameterData, RevealServiceParameterErrors, RevealServiceParameterResponse, RevealServiceParameterResponses, RevenueCreateIntegrationData, RevenueCreateIntegrationErrors, RevenueCreateIntegrationResponse, RevenueCreateIntegrationResponses, RevenueDeleteIntegrationData, RevenueDeleteIntegrationResponse, RevenueDeleteIntegrationResponses, RevenueGlobalEventsData, RevenueGlobalEventsResponse, RevenueGlobalEventsResponses, RevenueImportInvoicesCsvData, RevenueImportInvoicesCsvErrors, RevenueImportInvoicesCsvResponse, RevenueImportInvoicesCsvResponses, RevenueImportSubscriptionsCsvData, RevenueImportSubscriptionsCsvErrors, RevenueImportSubscriptionsCsvResponse, RevenueImportSubscriptionsCsvResponses, RevenueListIntegrationsData, RevenueListIntegrationsResponse, RevenueListIntegrationsResponses, RevenueListProvidersData, RevenueListProvidersResponse, RevenueListProvidersResponses, RevenueMetricsCustomersData, RevenueMetricsCustomersResponse, RevenueMetricsCustomersResponses, RevenueMetricsGlobalMrrData, RevenueMetricsGlobalMrrResponse, RevenueMetricsGlobalMrrResponses, RevenueMetricsGlobalSummaryData, RevenueMetricsGlobalSummaryResponse, RevenueMetricsGlobalSummaryResponses, RevenueMetricsMrrData, RevenueMetricsMrrResponse, RevenueMetricsMrrResponses, RevenueMetricsSummaryData, RevenueMetricsSummaryResponse, RevenueMetricsSummaryResponses, RevenueRecentEventsData, RevenueRecentEventsResponse, RevenueRecentEventsResponses, RevenueRotateTokenData, RevenueRotateTokenResponse, RevenueRotateTokenResponses, RevenueRow, RevenueUpdateConfigData, RevenueUpdateConfigErrors, RevenueUpdateConfigResponse, RevenueUpdateConfigResponses, RevenueUpdateSecretData, RevenueUpdateSecretErrors, RevenueUpdateSecretResponse, RevenueUpdateSecretResponses, RevokeDsnData, RevokeDsnErrors, RevokeDsnResponse, RevokeDsnResponses, RevokeEnrollmentTokenData, RevokeEnrollmentTokenErrors, RevokeEnrollmentTokenResponse, RevokeEnrollmentTokenResponses, RevokeJoinTokenData, RevokeJoinTokenErrors, RevokeJoinTokenResponse, RevokeJoinTokenResponses, RevokeProjectAccessData, RevokeProjectAccessErrors, RevokeProjectAccessResponse, RevokeProjectAccessResponses, RiskLevel, RoleInfo, RollbackPgUpgradeData, RollbackPgUpgradeErrors, RollbackPgUpgradeResponse, RollbackPgUpgradeResponses, RollbackToDeploymentData, RollbackToDeploymentErrors, RollbackToDeploymentResponse, RollbackToDeploymentResponses, RootfsCacheEntry, RootfsGcData, RootfsGcReport, RootfsGcResponses, RootfsReport, RootfsReportData, RootfsReportResponses, RootfsVmEntry, RotateApiKeyData, RotateApiKeyErrors, RotateApiKeyResponse, RotateApiKeyResponses, RotateDeploymentTokenData, RotateDeploymentTokenErrors, RotateDeploymentTokenResponse, RotateDeploymentTokenResponses, RouteRefreshResponse, RouteResponse, RouteRole, RouteUser, RouteUserWithRoles, RunBackupForSourceData, RunBackupForSourceError, RunBackupForSourceErrors, RunBackupForSourceResponse, RunBackupForSourceResponses, RunBackupRequest, RunConnectionHealthCheckData, RunConnectionHealthCheckErrors, RunConnectionHealthCheckResponse, RunConnectionHealthCheckResponses, RunExternalServiceBackupData, RunExternalServiceBackupError, RunExternalServiceBackupErrors, RunExternalServiceBackupRequest, RunExternalServiceBackupResponse, RunExternalServiceBackupResponses, RunScheduleNowData, RunScheduleNowError, RunScheduleNowErrors, RunScheduleNowResponse, RunScheduleNowResponses, S3ConnectionTestResponse, S3CredentialsResponse, S3SourceResponse, S3SourceResponseWritable, SandboxCreatePreviewLinkData, SandboxCreatePreviewLinkErrors, SandboxCreatePreviewLinkResponse, SandboxCreatePreviewLinkResponses, SandboxDomainResponse, SandboxEvent, SandboxEventsResponse, SandboxInner, SandboxResponse, SandboxRoute, SandboxStatusResponse, SaveAgentTokenData, SaveAgentTokenErrors, SaveAgentTokenRequest, SaveAgentTokenResponse, SaveAgentTokenResponse2, SaveAgentTokenResponses, SaveAiProviderCredentialData, SaveAiProviderCredentialErrors, SaveAiProviderCredentialResponse, SaveAiProviderCredentialResponses, SaveCredentialRequest, SaveCredentialResponse, ScalewayCredentialsRequest, ScanResponse, ScheduleRunEntry, ScheduleRunJobEntry, ScheduleRunListResponse, ScheduleRunResponse, ScheduleRunSummary, ScheduleRunSummaryList, ScreenshotSettings, SearchLogsData, SearchLogsError, SearchLogsErrors, SearchLogsRequest, SearchLogsResponse, SearchLogsResponse2, SearchLogsResponses, SearchMode, Seasonality, SecretResponse, SecurityConfig, SecurityHeadersConfig, SecurityHeadersSettings, SendEmailData, SendEmailErrors, SendEmailRequestBody, SendEmailResponse, SendEmailResponseBody, SendEmailResponses, SendMessageData, SendMessageErrors, SendMessageRequest, SendMessageResponses, SensitiveConfigValueResponse, SensitiveMcpConfigValueResponse, SensitiveValueResponse, SentryChunkUploadResponse, SentryCreateReleaseRequest, SentryEventRequest, SentryEventResponse, SentryReleaseFileResponse, SentryReleaseProjectRef, SentryReleaseResponse, SeriesStateEntry, ServiceAccessInfo, ServiceAction, ServiceAlertRuleResponse, ServiceBackupEntryResponse, ServiceBackupListResponse, ServiceCreateAlertRuleRequest, ServiceHealthResponse, ServiceHealthStatusBatchResponse, ServiceHealthStatusEntryResponse, ServiceMemberInfo, ServiceParameter, ServicePlan, ServiceResourceLimits, ServiceRuntimeReport, ServiceStatsReport, ServiceTypeInfo, ServiceTypeRoute, ServiceUpdateAlertRuleRequest, SesCredentialsRequest, SessionDetails, SessionDetailsQuery, SessionEvent, SessionEventDto, SessionEventsQuery, SessionEventsResponse, SessionLogsQuery, SessionLogsResponse, SessionReplayEventsRequest, SessionReplayInfoDto, SessionReplayInitRequest, SessionReplayInitResponse, SessionReplayWithEventsDto, SessionReplayWithVisitorDto, SessionRequestLog, SessionSummary, SetDefaultS3SourceData, SetDefaultS3SourceError, SetDefaultS3SourceErrors, SetDefaultS3SourceResponse, SetDefaultS3SourceResponses, SetFlagEnvironmentData, SetFlagEnvironmentErrors, SetFlagEnvironmentRequest, SetFlagEnvironmentResponse, SetFlagEnvironmentResponses, SetPreviewPasswordBody, SetPreviewPasswordData, SetPreviewPasswordErrors, SetPreviewPasswordResponse, SetPreviewPasswordResponse2, SetPreviewPasswordResponses, SetRequest, SetResponse, SettingsUpdateResponse, SetupDnsChallengeData, SetupDnsChallengeErrors, SetupDnsChallengeRequest, SetupDnsChallengeResponse, SetupDnsChallengeResponse2, SetupDnsChallengeResponses, SetupDnsData, SetupDnsErrors, SetupDnsRequest, SetupDnsResponse, SetupDnsResponse2, SetupDnsResponses, SetupEmailTrackingData, SetupEmailTrackingErrors, SetupEmailTrackingResponse, SetupEmailTrackingResponses, SetupMfaData, SetupMfaErrors, SetupMfaResponse, SetupMfaResponses, SiblingRef, SkillDefinitionResponse, SlackConfig, SleepEnvironmentData, SleepEnvironmentErrors, SleepEnvironmentResponse, SleepEnvironmentResponses, SlowQueriesResponse, SlowQueryRow, SmartFilter, SmokeTestAgentData, SmokeTestAgentErrors, SmokeTestAgentResponse, SmokeTestAgentResponses, SmokeTestResponse, SmtpCredentialsRequest, SmtpEncryptionRoute, SmtpResult, SourceBackupEntry, SourceBackupIndexResponse, SourceBody, SourceFileListResponse, SourceFileResponse, SourceMapListResponse, SourceMapResponse, SourceSandboxData, SourceSandboxErrors, SourceSandboxResponse, SourceSandboxResponses, SourceType, SpanEvent, SpanKind, SpanRecord, SpanRow, SpanStatusCode, SpeedMetricsPayload, SpeedSegmentFilters, StaleSlot, StartAnalysisData, StartAnalysisErrors, StartAnalysisRequest, StartAnalysisResponse, StartAnalysisResponses, StartContainerData, StartContainerErrors, StartContainerResponse, StartContainerResponses, StartFixData, StartFixErrors, StartFixResponses, StartGitProviderOauthData, StartGitProviderOauthErrors, StartOidcLoginBySlugData, StartOidcLoginBySlugErrors, StartPgUpgradeData, StartPgUpgradeErrors, StartPgUpgradeRequest, StartPgUpgradeResponse, StartPgUpgradeResponses, StartRestoreData, StartRestoreError, StartRestoreErrors, StartRestoreRequest, StartRestoreResponse, StartRestoreResponses, StartServiceData, StartServiceErrors, StartServiceResponse, StartServiceResponses, StaticBundleResponse, StaticParams, StaticPresetConfig, StatPathData, StatPathErrors, StatPathResponse, StatPathResponses, StatResponse, StatsFilters, StatusBucket, StatusBucketedResponse, StatusCodeCount, StatusCodesQuery, StatusPageOverview, StepConversionResponse, StepResourceType, StepResult, StepUpResponse, StopContainerData, StopContainerErrors, StopContainerResponse, StopContainerResponses, StopSandboxData, StopSandboxErrors, StopSandboxResponse, StopSandboxResponses, StopSequence, StopServiceData, StopServiceErrors, StopServiceResponse, StopServiceResponses, StorageQuota, StreamContainerMetricsData, StreamContainerMetricsErrors, StreamContainerMetricsResponses, StreamEventsData, StreamEventsErrors, StreamEventsResponses, StreamRunEventsData, StreamRunEventsErrors, StreamRunEventsResponses, StripeConfig, SyncedRepositoryListQuery, SyncRepositoriesData, SyncRepositoriesErrors, SyncRepositoriesResponse, SyncRepositoriesResponses, SyntaxResult, TagInfo, TagListResponse, TailDeploymentJobLogsData, TailDeploymentJobLogsErrors, TailLogsData, TailLogsError, TailLogsErrors, TailLogsRequest, TailLogsResponses, TargetRecommendation, TeamListResponse, TeamMemberResponse, TeamResponse, TeamRole, TeardownDeploymentData, TeardownDeploymentErrors, TeardownDeploymentResponse, TeardownDeploymentResponses, TeardownEnvironmentData, TeardownEnvironmentErrors, TeardownEnvironmentResponse, TeardownEnvironmentResponses, TemplateResponse, TestEmailRequest, TestEmailResponse, TestNotificationProviderData, TestNotificationProviderErrors, TestNotificationProviderResponse, TestNotificationProviderResponses, TestOidcProviderData, TestOidcProviderResponse, TestOidcProviderResponses, TestProviderConnectionData, TestProviderConnectionErrors, TestProviderConnectionResponse, TestProviderConnectionResponses, TestProviderData, TestProviderErrors, TestProviderKeyByIdData, TestProviderKeyByIdError, TestProviderKeyByIdErrors, TestProviderKeyByIdResponse, TestProviderKeyByIdResponses, TestProviderKeyInlineData, TestProviderKeyInlineError, TestProviderKeyInlineErrors, TestProviderKeyInlineResponse, TestProviderKeyInlineResponses, TestProviderKeyRequest, TestProviderKeyResponse, TestProviderResponse, TestProviderResponse2, TestProviderResponses, TestS3ConnectionPreviewData, TestS3ConnectionPreviewError, TestS3ConnectionPreviewErrors, TestS3ConnectionPreviewResponse, TestS3ConnectionPreviewResponses, TestS3SourceConnectionData, TestS3SourceConnectionError, TestS3SourceConnectionErrors, TestS3SourceConnectionResponse, TestS3SourceConnectionResponses, TimeBucketStats, TimeBucketStatsResponse, TimeseriesBucket, TimeseriesQueryParams, TlsMode, TodayStatsResponse, ToggleDeploymentMetricsRequest, ToggleServiceMetricsRequest, TokenRenewalRequest, ToolCallEvent, ToolInfo, ToolResultEvent, TopModelsQueryParams, TraceProjectRef, TracesResponse, TraceSummariesResponse, TraceSummary, TrackClickData, TrackClickErrors, TrackedLinkResponse, TrackingEventResponse, TrackOpenData, TrackOpenErrors, TrackOpenResponses, TriggerAgentData, TriggerAgentErrors, TriggerAgentRequest, TriggerAgentResponse, TriggerAgentResponses, TriggerDigestResponse, TriggerPipelinePayload, TriggerPipelineResponse, TriggerProjectPipelineData, TriggerProjectPipelineErrors, TriggerProjectPipelineResponse, TriggerProjectPipelineResponses, TriggerScanData, TriggerScanError, TriggerScanErrors, TriggerScanRequest, TriggerScanResponse, TriggerScanResponse2, TriggerScanResponses, TriggerServiceHealthCheckData, TriggerServiceHealthCheckErrors, TriggerServiceHealthCheckResponse, TriggerServiceHealthCheckResponses, TriggerWeeklyDigestData, TriggerWeeklyDigestErrors, TriggerWeeklyDigestResponse, TriggerWeeklyDigestResponses, TtlRequest, TtlResponse, TxtRecord, UiManifest, UiRoute, UndrainNodeResponse, UnifiedTrace, UniqueCountsQuery, UniqueCountsResponse, UnlinkServiceFromProjectData, UnlinkServiceFromProjectErrors, UnlinkServiceFromProjectResponse, UnlinkServiceFromProjectResponses, UnsupportedFeature, UpdateAdminGateRequest, UpdateAgentData, UpdateAgentErrors, UpdateAgentResponse, UpdateAgentResponses, UpdateAiProviderData, UpdateAiProviderErrors, UpdateAiProviderRequest, UpdateAiProviderResponse, UpdateAiProviderResponse2, UpdateAiProviderResponses, UpdateAlertData, UpdateAlertError, UpdateAlertErrors, UpdateAlertResponse, UpdateAlertResponses, UpdateAlertRuleData, UpdateAlertRuleErrors, UpdateAlertRuleRequest, UpdateAlertRuleResponse, UpdateAlertRuleResponses, UpdateApiKeyData, UpdateApiKeyErrors, UpdateApiKeyRequest, UpdateApiKeyResponse, UpdateApiKeyResponses, UpdateAutomaticDeployData, UpdateAutomaticDeployErrors, UpdateAutomaticDeployRequest, UpdateAutomaticDeployResponse, UpdateAutomaticDeployResponses, UpdateBackupScheduleData, UpdateBackupScheduleError, UpdateBackupScheduleErrors, UpdateBackupScheduleRequest, UpdateBackupScheduleResponse, UpdateBackupScheduleResponses, UpdateBlobRequest, UpdateBlobResponse, UpdateCloudflareProviderData, UpdateCloudflareProviderErrors, UpdateCloudflareProviderRequest, UpdateCloudflareProviderResponse, UpdateCloudflareProviderResponses, UpdateConfigBody, UpdateConnectionTokenData, UpdateConnectionTokenErrors, UpdateConnectionTokenResponse, UpdateConnectionTokenResponses, UpdateCustomDomainData, UpdateCustomDomainErrors, UpdateCustomDomainRequest, UpdateCustomDomainResponse, UpdateCustomDomainResponses, UpdateDashboardData, UpdateDashboardError, UpdateDashboardErrors, UpdateDashboardRequest, UpdateDashboardResponse, UpdateDashboardResponses, UpdateDeploymentConfigRequest, UpdateDeploymentTokenData, UpdateDeploymentTokenErrors, UpdateDeploymentTokenRequest, UpdateDeploymentTokenResponse, UpdateDeploymentTokenResponses, UpdateDnsProviderRequest, UpdateEmailProviderData, UpdateEmailProviderErrors, UpdateEmailProviderRequest, UpdateEmailProviderResponse, UpdateEmailProviderResponses, UpdateEnvironmentSettingsData, UpdateEnvironmentSettingsErrors, UpdateEnvironmentSettingsRequest, UpdateEnvironmentSettingsResponse, UpdateEnvironmentSettingsResponses, UpdateEnvironmentSubdomainData, UpdateEnvironmentSubdomainErrors, UpdateEnvironmentSubdomainRequest, UpdateEnvironmentSubdomainResponse, UpdateEnvironmentSubdomainResponses, UpdateEnvironmentVariableData, UpdateEnvironmentVariableErrors, UpdateEnvironmentVariableRequest, UpdateEnvironmentVariableResponse, UpdateEnvironmentVariableResponses, UpdateErrorGroupData, UpdateErrorGroupErrors, UpdateErrorGroupRequest, UpdateErrorGroupResponses, UpdateExternalServiceRequest, UpdateFlagData, UpdateFlagErrors, UpdateFlagRequest, UpdateFlagResponse, UpdateFlagResponses, UpdateFunnelData, UpdateFunnelErrors, UpdateFunnelResponses, UpdateGitProviderCredentialsData, UpdateGitProviderCredentialsErrors, UpdateGitProviderCredentialsResponse, UpdateGitProviderCredentialsResponses, UpdateGitSettingsData, UpdateGitSettingsErrors, UpdateGitSettingsRequest, UpdateGitSettingsResponse, UpdateGitSettingsResponses, UpdateGlobalMcpData, UpdateGlobalMcpErrors, UpdateGlobalMcpResponse, UpdateGlobalMcpResponses, UpdateGlobalSkillData, UpdateGlobalSkillErrors, UpdateGlobalSkillResponse, UpdateGlobalSkillResponses, UpdateIncidentStatusData, UpdateIncidentStatusErrors, UpdateIncidentStatusRequest, UpdateIncidentStatusResponse, UpdateIncidentStatusResponses, UpdateIpAccessControlData, UpdateIpAccessControlError, UpdateIpAccessControlErrors, UpdateIpAccessControlRequest, UpdateIpAccessControlResponse, UpdateIpAccessControlResponses, UpdateKvRequest, UpdateKvResponse, UpdateManagedDomainApiRequest, UpdateManagedDomainData, UpdateManagedDomainErrors, UpdateManagedDomainResponse, UpdateManagedDomainResponses, UpdateMcpData, UpdateMcpErrors, UpdateMcpRequest, UpdateMcpResponse, UpdateMcpResponses, UpdateMemberRoleRequest, UpdateMetricAlertRequest, UpdateNotificationEmailProviderData, UpdateNotificationEmailProviderErrors, UpdateNotificationEmailProviderRequest, UpdateNotificationEmailProviderResponse, UpdateNotificationEmailProviderResponses, UpdateNotificationProviderData, UpdateNotificationProviderErrors, UpdateNotificationProviderResponse, UpdateNotificationProviderResponses, UpdateOidcProviderData, UpdateOidcProviderRequest, UpdateOidcProviderResponse, UpdateOidcProviderResponses, UpdatePreferencesData, UpdatePreferencesErrors, UpdatePreferencesRequest, UpdatePreferencesResponse, UpdatePreferencesResponses, UpdateProjectData, UpdateProjectDeploymentConfigData, UpdateProjectDeploymentConfigErrors, UpdateProjectDeploymentConfigResponse, UpdateProjectDeploymentConfigResponses, UpdateProjectErrors, UpdateProjectResponse, UpdateProjectResponses, UpdateProjectSecretData, UpdateProjectSecretErrors, UpdateProjectSecretRequest, UpdateProjectSecretResponse, UpdateProjectSecretResponses, UpdateProjectSettingsData, UpdateProjectSettingsErrors, UpdateProjectSettingsRequest, UpdateProjectSettingsResponse, UpdateProjectSettingsResponses, UpdateProviderCredentialsRequest, UpdateProviderData, UpdateProviderErrors, UpdateProviderKeyData, UpdateProviderKeyError, UpdateProviderKeyErrors, UpdateProviderKeyRequest, UpdateProviderKeyResponse, UpdateProviderKeyResponses, UpdateProviderRequest, UpdateProviderResponse, UpdateProviderResponses, UpdateRouteData, UpdateRouteErrors, UpdateRouteRequest, UpdateRouteResponse, UpdateRouteResponses, UpdateS3SourceData, UpdateS3SourceError, UpdateS3SourceErrors, UpdateS3SourceRequest, UpdateS3SourceResponse, UpdateS3SourceResponses, UpdateSecretBody, UpdateSelfData, UpdateSelfErrors, UpdateSelfRequest, UpdateSelfResponse, UpdateSelfResponses, UpdateServiceData, UpdateServiceErrors, UpdateServiceResourcesData, UpdateServiceResourcesErrors, UpdateServiceResourcesResponse, UpdateServiceResourcesResponses, UpdateServiceResponse, UpdateServiceResponses, UpdateSessionDurationData, UpdateSessionDurationError, UpdateSessionDurationErrors, UpdateSessionDurationRequest, UpdateSessionDurationResponse, UpdateSessionDurationResponse2, UpdateSessionDurationResponses, UpdateSettingsData, UpdateSettingsErrors, UpdateSettingsResponse, UpdateSettingsResponses, UpdateSkillData, UpdateSkillErrors, UpdateSkillRequest, UpdateSkillResponse, UpdateSkillResponses, UpdateSlackProviderData, UpdateSlackProviderErrors, UpdateSlackProviderRequest, UpdateSlackProviderResponse, UpdateSlackProviderResponses, UpdateSpeedMetricsData, UpdateSpeedMetricsError, UpdateSpeedMetricsErrors, UpdateSpeedMetricsPayload, UpdateSpeedMetricsResponse, UpdateSpeedMetricsResponses, UpdateStatusResponse, UpdateTeamData, UpdateTeamErrors, UpdateTeamMemberRoleData, UpdateTeamMemberRoleErrors, UpdateTeamMemberRoleResponse, UpdateTeamMemberRoleResponses, UpdateTeamRequest, UpdateTeamResponse, UpdateTeamResponses, UpdateTokenRequest, UpdateTokenResponse, UpdateUserData, UpdateUserErrors, UpdateUserRequest, UpdateUserResponse, UpdateUserResponses, UpdateWebhookData, UpdateWebhookErrors, UpdateWebhookProviderData, UpdateWebhookProviderErrors, UpdateWebhookProviderRequest, UpdateWebhookProviderResponse, UpdateWebhookProviderResponses, UpdateWebhookRequestBody, UpdateWebhookResponse, UpdateWebhookResponses, UpgradeExternalServiceRequest, UpgradePreviewGatewayData, UpgradePreviewGatewayResponse, UpgradePreviewGatewayResponses, UpgradeRequest, UpgradeServiceData, UpgradeServiceErrors, UpgradeServiceResponse, UpgradeServiceResponses, UploadGlobalSkillData, UploadGlobalSkillErrors, UploadGlobalSkillResponse, UploadGlobalSkillResponses, UploadReleaseFileData, UploadReleaseFileErrors, UploadReleaseFileResponse, UploadReleaseFileResponses, UploadSkillData, UploadSkillErrors, UploadSkillResponse, UploadSkillResponses, UploadSourceFileData, UploadSourceFileErrors, UploadSourceFileResponse, UploadSourceFileResponses, UploadSourceMapData, UploadSourceMapErrors, UploadSourceMapResponse, UploadSourceMapResponses, UploadStaticBundleData, UploadStaticBundleErrors, UploadStaticBundleResponse, UploadStaticBundleResponses, UpsertAgentRequest, UpsertSecretData, UpsertSecretErrors, UpsertSecretRequest, UpsertSecretResponse, UpsertSecretResponses, UptimeDataPoint, UptimeHistoryResponse, UsageFilter, UsageInfo, UsageLogEntry, UsageLogPage, UsageQueryParams, UsageSource, UsageSummary, UserResponse, ValidateConnectionData, ValidateConnectionErrors, ValidateConnectionResponse, ValidateConnectionResponses, ValidateEmailData, ValidateEmailErrors, ValidateEmailRequest, ValidateEmailResponse, ValidateEmailResponse2, ValidateEmailResponses, ValidationLevel, ValidationReport, ValidationResponse, ValidationResult, ValidationStatus, ValidationSummary, VerifyAndEnableMfaData, VerifyAndEnableMfaErrors, VerifyAndEnableMfaResponse, VerifyAndEnableMfaResponses, VerifyDomainData, VerifyDomainErrors, VerifyDomainResponse, VerifyDomainResponses, VerifyEmailData, VerifyEmailErrors, VerifyEmailResponse, VerifyEmailResponses, VerifyManagedDomainData, VerifyManagedDomainErrors, VerifyManagedDomainResponse, VerifyManagedDomainResponses, VerifyMfaChallengeData, VerifyMfaChallengeErrors, VerifyMfaChallengeResponse, VerifyMfaChallengeResponses, VerifyMfaRequest, VerifyStepUpData, VerifyStepUpErrors, VerifyStepUpRequest, VerifyStepUpResponse, VerifyStepUpResponses, ViewItem, ViewsOverTime, ViewsOverTimeQuery, VisitorDetails, VisitorFacets, VisitorFacetsQuery, VisitorFacetValue, VisitorInfo, VisitorJourneyQuery, VisitorJourneyResponse, VisitorLocationsQuery, VisitorRecord, VisitorSegmentFilters, VisitorSessionsQuery, VisitorSessionsResponse, VisitorsListQuery, VisitorsResponse, VisitorStats, VisitorWithGeolocation, VolumeMount, VolumeType, VulnerabilityResponse, WakeEnvironmentData, WakeEnvironmentErrors, WakeEnvironmentResponse, WakeEnvironmentResponses, WalWarning, WalWarningSeverity, WebhookConfig, WebhookDeliveryResponse, WebhookResponse, WebhookTriggerData, WebhookTriggerErrors, WebhookTriggerRequest, WebhookTriggerResponse, WebhookTriggerResponse2, WebhookTriggerResponses, WorkflowDryRunData, WorkflowDryRunErrors, WorkflowDryRunRequest, WorkflowDryRunResponse, WorkflowDryRunResponses, WorkloadDescriptor, WorkloadId, WorkloadStatus, WorkloadType, WriteFileBody, WriteFileData, WriteFileErrors, WriteFileResponse, WriteFileResponses, WriteFilesBody, WriteFilesData, WriteFilesErrors, WriteFilesResponse, WriteFilesResponse2, WriteFilesResponses, ZoneListResponse } from './types.gen'; +export { acknowledgeAlarm, activateAiProvider, activateApiKey, activateConnection, activateProvider, addClusterMember, addContext, addEnvironmentDomain, addEvents, addManagedDomain, addSessionReplayEvents, addTeamMember, adminDrainNode, adminDrainStatus, adminGetNode, adminListNodeContainers, adminListNodes, adminRemoveNode, adminUndrainNode, applyHostnameMode, archiveConversation, archiveFlag, assignRole, attachScheduleServices, blobCopy, blobDelete, blobDisable, blobDownload, blobEnable, blobHead, blobList, blobPut, blobStatus, blobUpdate, cancel, cancelBackup, cancelDeployment, cancelDomainOrder, cancelPgUpgrade, cancelRun, cancelScheduleRun, changePasswordSelf, changeProjectSource, chatCompletions, checkAnalyticsHasEvents, checkCommitExists, checkDomainStatus, checkExplorerSupport, checkIpBlocked, checkProviderDeletionSafety, chunkUploadOptions, cleanupExpiredBackups, clearPreviewPassword, cliDeviceApprove, cliDeviceDeny, cliDeviceLookup, cliDevicePoll, cliDeviceStart, cliLogout, cmd, cmdKill, cmdLogs, confirmPendingAction, containerMetricsGetHistory, createAgent, createAlert, createAlertRule, createApiKey, createBackupSchedule, createBitbucketProvider, createCloudflareProvider, createConversation, createCustomDomain, createDashboard, createDeploymentToken, createDnsProvider, createDomain, createDsn, createEmailDomain, createEmailProvider, createEnvironment, createEnvironmentVariable, createFlag, createFunnel, createGenericProvider, createGiteaPatProvider, createGithubPatProvider, createGitlabOauthProvider, createGitlabPatProvider, createGitProvider, createGlobalMcp, createGlobalSkill, createIncident, createIpAccessControl, createMcp, createMonitor, createNotificationEmailProvider, createNotificationProvider, createOidcProvider, createOidcRoleMapping, createOrRecreateOrder, createPlan, createPr, createProject, createProjectFromTemplate, createProjectRelease, createProjectSecret, createProviderKey, createRelease, createRoute, createS3Source, createSandbox, createService, createSkill, createSlackProvider, createTeam, createUser, createWebhook, createWebhookProvider, deactivateApiKey, deactivateConnection, deactivateProvider, deleteAgent, deleteAlert, deleteAlertRule, deleteApiKey, deleteBackup, deleteBackupSchedule, deleteConnection, deleteCustomDomain, deleteDashboard, deleteDeploymentToken, deleteDnsProvider, deleteDomain, deleteEmailDomain, deleteEmailProvider, deleteEnvironment, deleteEnvironmentDomain, deleteEnvironmentVariable, deleteExternalImage, deleteFunnel, deleteGitProvider, deleteGlobalMcp, deleteGlobalSkill, deleteIpAccessControl, deleteMcp, deleteMonitor, deleteNotificationProvider, deleteOidcProvider, deleteOidcRoleMapping, deletePreferences, deleteProject, deleteProjectSecret, deleteProviderKey, deleteProviderSafely, deleteReleaseSourceFiles, deleteReleaseSourceMaps, deleteRoute, deleteS3Source, deleteScan, deleteSecret, deleteService, deleteSessionReplay, deleteSkill, deleteSourceMap, deleteStaticBundle, deleteTeam, deleteUser, deleteWebhook, deployFromImage, deployFromImageUpload, deployFromStatic, deployFromUploadedSource, deploymentMetricsGetLatest, deploymentMetricsGetRange, deploymentMetricsToggle, destroySandbox, detachScheduleService, detectPublicPresets, disableBackupSchedule, disableMfa, discoverWorkloads, domain, downloadGlobalSkillArchive, downloadObject, downloadSkillArchive, emailStatus, embeddings, enableBackupSchedule, enrichVisitor, exec, execDetached, executeDeploymentOperation, executeImport, extendTimeout, externalServiceEnablePgStatStatements, externalServiceMetricsByDatabase, externalServiceMetricsCreateAlertRule, externalServiceMetricsDeleteAlertRule, externalServiceMetricsGetAlertRules, externalServiceMetricsGetLatest, externalServiceMetricsGetRange, externalServiceMetricsStatus, externalServiceMetricsToggle, externalServiceMetricsUpdateAlertRule, externalServiceResetPgStatStatements, finalizeOrder, finalizeProjectRelease, findConversation, generateJoinToken, generatePresetDockerfile, getAccessInfo, getActiveVisitors, getActivityGraph, getAdminGate, getAgent, getAggregatedBuckets, getAiAgentBreakdown, getAiAgentPages, getAiAgentTimeline, getAiPageBreakdown, getAiStatusBreakdown, getAlert, getAlertRule, getAllRepositoriesByName, getAnalyticsActiveVisitors, getAnalyticsEventsCount, getAnalyticsSessionEvents, getAnalyticsVisitorSessions, getApiKey, getApiKeyPermissions, getAuditLog, getBackup, getBackupSchedule, getBranchesByRepositoryId, getBucketedIncidents, getBucketedStatus, getChallengeToken, getChatReadiness, getCliStatus, getClusterHealth, getClusterMember, getCmd, getContainerDetail, getContainerEnvironmentVariable, getContainerInfo, getContainerLogs, getContainerLogsById, getContainerMetrics, getConversation, getConversationDetail, getConversations, getCronById, getCronExecutions, getCrossProjectTraceSiblings, getCurrentMonitorStatus, getCurrentUser, getCustomDomain, getDashboard, getDashboardProjectsAnalytics, getDelivery, getDeployment, getDeploymentContainerLogContent, getDeploymentJobLogs, getDeploymentJobs, getDeploymentOperations, getDeploymentOperationStatus, getDeploymentToken, getDiskStatus, getDnsChanges, getDnsProvider, getDomain, getDomainByHost, getDomainById, getDomainByName, getDomainDnsRecords, getDomainOrder, getEmail, getEmailEvents, getEmailLinks, getEmailProvider, getEmailStats, getEmailTracking, getEmailTrackingStatus, getEntityInfo, getEnvironment, getEnvironmentCrons, getEnvironmentDomains, getEnvironments, getEnvironmentVariables, getEnvironmentVariableValue, getErrorDashboardStats, getErrorEvent, getErrorGroup, getErrorStats, getErrorTimeSeries, getEventDetail, getEventEntries, getEventsCount, getEventsTimeline, getEventTypeBreakdown, getEventVisitors, getExternalImage, getFile, getFlag, getFlagSnapshot, getFunnelMetrics, getGenaiTrace, getGeneralStats, getGitProvider, getGlobalEvents, getGlobalEventStats, getGlobalMcp, getGlobalSandboxStatus, getGlobalSkill, getGroupedPageMetrics, getHealth, getHourlyVisits, getHttpChallengeDebug, getImportStatus, getIncident, getIncidentUpdates, getIpAccessControl, getIpGeolocation, getJoinTokenStatus, getLastDeployment, getLatestScan, getLatestScansPerEnvironment, getLiveVisitorsList, getLogContext, getMcp, getMetricsOverTime, getMonitor, getNotificationProvider, getOnDemandCertStatus, getOrCreateDsn, getPageFlow, getPageHourlySessions, getPagePathDetail, getPagePaths, getPagePathsSparklines, getPagePathVisitors, getPendingAction, getPerformanceMetrics, getPgUpgrade, getPgUpgradeLogs, getPipelineStats, getPlatformInfo, getPostgresWalHealth, getPreferences, getPreviewGatewayLogs, getPreviewGatewaySettings, getPreviewGatewayStatus, getPricing, getPrivateIp, getProject, getProjectAlarmsSummary, getProjectBySlug, getProjectDeployments, getProjects, getProjectServiceEnvironmentVariables, getProjectSessionReplays, getProjectsHealth, getProjectsMonitorHealth, getProjectStatistics, getProjectTemplate, getPropertyBreakdown, getPropertyTimeline, getProviderConnections, getProviderMetadata, getProvidersMetadata, getProxyLogById, getProxyLogByRequestId, getProxyLogs, getPublicBranches, getPublicIp, getPublicRepository, getQuota, getRecentActivity, getRemoteExternalImage, getRepositoryBranches, getRepositoryById, getRepositoryByName, getRepositoryPresetByName, getRepositoryPresetLive, getRepositoryTags, getResolvedEnvironmentVariables, getResolvedEnvironmentVariableValue, getRestoreCapabilities, getRestoreRun, getRoute, getRun, getRunWithLogs, getS3Credentials, getS3Source, getSandbox, getSandboxStatus, getScan, getScanByDeployment, getScanVulnerabilities, getService, getServiceBySlug, getServiceEnvironmentVariable, getServiceEnvironmentVariables, getServiceHealthStatus, getServicePreviewEnvironmentVariableNames, getServicePreviewEnvironmentVariablesMasked, getServiceRuntime, getServiceStats, getServiceTypeParameters, getServiceTypes, getSessionDetails, getSessionEvents, getSessionLogs, getSessionReplay, getSessionReplayEvents, getSettings, getSkill, getSlowQueries, getStaticBundle, getStatusOverview, getTagsByRepositoryId, getTeam, getTimeBucketStats, getTodayStats, getTrace, getUnifiedTrace, getUniqueCounts, getUniqueEvents, getUpdateStatus, getUptimeHistory, getUsageByProvider, getUsageRecent, getUsageSummary, getUsageTimeseries, getUsageTopModels, getVisitorByGuid, getVisitorById, getVisitorDetails, getVisitorFacets, getVisitorInfo, getVisitorJourney, getVisitors, getVisitorSessions, getVisitorStats, getWebhook, grantProjectAccess, handleGitProviderOauthCallback, hasAnalyticsEvents, hasErrorGroups, hasPerformanceMetrics, importExternalService, ingestLogs, ingestLogsByPath, ingestMetrics, ingestMetricsByPath, ingestSentryEnvelope, ingestSentryEvent, ingestTraces, ingestTracesByPath, initSessionReplay, inspectDropArchive, jobLogs, jobStatus, killJob, kvDel, kvDisable, kvEnable, kvExpire, kvGet, kvIncr, kvKeys, kvSet, kvStatus, kvTtl, kvUpdate, latestRunForSource, linkCustomDomainToCertificate, linkServiceToProject, listAgentRuns, listAgents, listAiProviders, listAlertRules, listAlerts, listAllConversations, listAllRuns, listApiKeys, listAuditLogs, listAvailableContainers, listBackupAlerts, listBackupChildren, listBackupSchedules, listBackupsForSchedule, listCommitsByRepositoryId, listConnections, listContainers, listContainersAtPath, listConversations, listCustomDomainsForProject, listDashboards, listDeliveries, listDeploymentContainerLogs, listDeploymentTokens, listDnsProviders, listDomains, listDsns, listEmailDomains, listEmailProviders, listEmails, listEnrollmentTokens, listEntities, listErrorEvents, listErrorGroups, listEvents, listEventTypes, listExternalImages, listExternalPlugins, listExternalServiceBackups, listFlags, listFunnels, listGitProviders, listGlobalMcps, listGlobalSkills, listIncidents, listInsights, listIpAccessControl, listJobs, listKnownAiAgents, listManagedDomains, listMcps, listMetricLabelKeys, listMetricLabelValues, listMetricNames, listModels, listMonitors, listNotificationProviders, listOidcProviders, listOidcProviderUsers, listOidcRoleMappings, listOnDemandCerts, listOrders, listPeers, listPendingActions, listPgUpgrades, listPresets, listProjectAccess, listProjectAlarms, listProjectScans, listProjectSecrets, listProjectServices, listProjectTemplates, listProjectTemplateTags, listProviderKeys, listProviderZones, listPublicProviders, listReleaseFiles, listReleases, listRemoteExternalImages, listRepositoriesByConnection, listRepositoriesByProvider, listRestoreRunsForService, listRootContainers, listRoutes, listS3Sources, listSandboxes, listScheduleRunJobs, listScheduleRuns, listScheduleServices, listSecrets, listServiceHealthStatuses, listServiceProjects, listServices, listServiceSchedules, listSkills, listSourceBackups, listSourceFiles, listSourceMaps, listSources, listStaticBundles, listSyncedRepositories, listTeamMembers, listTeamProjects, listTeams, listUsers, listWebhooks, login, logout, lookupDnsARecords, mintEnrollmentToken, mkdir, nodeHeartbeat, nodeMetricsGetRange, observabilityFullEvent, observabilityListEvents, oidcCallback, type Options, patchAdminGate, patchPreviewGatewaySettings, pauseDeployment, pauseSandbox, planRestore, postDnsAck, previewAlert, previewFunnelMetrics, previewHostnameMode, promoteClusterMember, promoteDeployment, provisionDomain, purgeProjectLogs, pushExternalImage, queryData, queryGenaiTraces, queryLogs, queryMetrics, queryTraces, queryTraceSummaries, readFile, reAnalyze, rebuildSandboxImage, recordConsoleEvent, recordEventMetrics, recordFlagExposure, recordSpeedMetrics, refreshRouteTable, regenerateDsn, registerExternalImage, registerNode, reinstallGitlabWebhook, rejectPendingAction, reloadPlugins, removeClusterMember, removeManagedDomain, removeRole, removeTeamMember, renameConversation, renewDomain, requestPasswordReset, resetPassword, resizeSandbox, resolveAlarm, restartContainer, restartPreviewGateway, restartSandbox, restoreFlag, restoreUser, resumeDeployment, resumeSandbox, retryCluster, retryDelivery, retryPgUpgrade, retryRun, revealGlobalMcpConfig, revealMcpConfig, revealNotificationProviderConfig, revealServiceParameter, revenueCreateIntegration, revenueDeleteIntegration, revenueGlobalEvents, revenueImportInvoicesCsv, revenueImportSubscriptionsCsv, revenueListIntegrations, revenueListProviders, revenueMetricsCustomers, revenueMetricsGlobalMrr, revenueMetricsGlobalSummary, revenueMetricsMrr, revenueMetricsSummary, revenueRecentEvents, revenueRotateToken, revenueUpdateConfig, revenueUpdateSecret, revokeDsn, revokeEnrollmentToken, revokeJoinToken, revokeProjectAccess, rollbackPgUpgrade, rollbackToDeployment, rootfsGc, rootfsReport, rotateApiKey, rotateDeploymentToken, runBackupForSource, runConnectionHealthCheck, runExternalServiceBackup, runScheduleNow, sandboxCreatePreviewLink, saveAgentToken, saveAiProviderCredential, searchLogs, sendEmail, sendMessage, setDefaultS3Source, setFlagEnvironment, setPreviewPassword, setupDns, setupDnsChallenge, setupEmailTracking, setupMfa, sleepEnvironment, smokeTestAgent, sourceSandbox, startAnalysis, startContainer, startFix, startGitProviderOauth, startOidcLoginBySlug, startPgUpgrade, startRestore, startService, statPath, stopContainer, stopSandbox, stopService, streamContainerMetrics, streamEvents, streamRunEvents, syncRepositories, tailDeploymentJobLogs, tailLogs, teardownDeployment, teardownEnvironment, testNotificationProvider, testOidcProvider, testProvider, testProviderConnection, testProviderKeyById, testProviderKeyInline, testS3ConnectionPreview, testS3SourceConnection, trackClick, trackOpen, triggerAgent, triggerProjectPipeline, triggerScan, triggerServiceHealthCheck, triggerWeeklyDigest, unlinkServiceFromProject, updateAgent, updateAiProvider, updateAlert, updateAlertRule, updateApiKey, updateAutomaticDeploy, updateBackupSchedule, updateCloudflareProvider, updateConnectionToken, updateCustomDomain, updateDashboard, updateDeploymentToken, updateEmailProvider, updateEnvironmentSettings, updateEnvironmentSubdomain, updateEnvironmentVariable, updateErrorGroup, updateFlag, updateFunnel, updateGitProviderCredentials, updateGitSettings, updateGlobalMcp, updateGlobalSkill, updateIncidentStatus, updateIpAccessControl, updateManagedDomain, updateMcp, updateNotificationEmailProvider, updateNotificationProvider, updateOidcProvider, updatePreferences, updateProject, updateProjectDeploymentConfig, updateProjectSecret, updateProjectSettings, updateProvider, updateProviderKey, updateRoute, updateS3Source, updateSelf, updateService, updateServiceResources, updateSessionDuration, updateSettings, updateSkill, updateSlackProvider, updateSpeedMetrics, updateTeam, updateTeamMemberRole, updateUser, updateWebhook, updateWebhookProvider, upgradePreviewGateway, upgradeService, uploadGlobalSkill, uploadReleaseFile, uploadSkill, uploadSourceFile, uploadSourceMap, uploadStaticBundle, upsertSecret, validateConnection, validateEmail, verifyAndEnableMfa, verifyDomain, verifyEmail, verifyManagedDomain, verifyMfaChallenge, verifyStepUp, wakeEnvironment, webhookTrigger, workflowDryRun, writeFile, writeFiles } from './sdk.gen'; +export type { AcknowledgeAlarmData, AcknowledgeAlarmErrors, AcknowledgeAlarmResponses, AcmeOrderResponse, ActivateAiProviderData, ActivateAiProviderErrors, ActivateAiProviderResponse, ActivateAiProviderResponses, ActivateApiKeyData, ActivateApiKeyErrors, ActivateApiKeyResponse, ActivateApiKeyResponses, ActivateConnectionData, ActivateConnectionErrors, ActivateConnectionResponses, ActivateProviderData, ActivateProviderErrors, ActivateProviderResponse, ActivateProviderResponses, ActiveVisitor, ActiveVisitorsQuery, ActiveVisitorsResponse, ActivityDay, ActivityEvent, ActivityGraphQuery, ActivityGraphResponse, AddClusterMemberData, AddClusterMemberErrors, AddClusterMemberRequest, AddClusterMemberResponse, AddClusterMemberResponses, AddContextData, AddContextErrors, AddContextRequest, AddContextResponses, AddEnvironmentDomainData, AddEnvironmentDomainErrors, AddEnvironmentDomainRequest, AddEnvironmentDomainResponse, AddEnvironmentDomainResponses, AddEventsData, AddEventsError, AddEventsErrors, AddEventsRequest, AddEventsResponse, AddEventsResponse2, AddEventsResponses, AddManagedDomainApiRequest, AddManagedDomainData, AddManagedDomainErrors, AddManagedDomainResponse, AddManagedDomainResponses, AddSessionReplayEventsData, AddSessionReplayEventsError, AddSessionReplayEventsErrors, AddSessionReplayEventsResponse, AddSessionReplayEventsResponses, AddTeamMemberData, AddTeamMemberErrors, AddTeamMemberResponse, AddTeamMemberResponses, AdminDrainNodeData, AdminDrainNodeErrors, AdminDrainNodeResponse, AdminDrainNodeResponses, AdminDrainStatusData, AdminDrainStatusErrors, AdminDrainStatusResponse, AdminDrainStatusResponses, AdminGateResponse, AdminGateSource, AdminGetNodeData, AdminGetNodeErrors, AdminGetNodeResponse, AdminGetNodeResponses, AdminListNodeContainersData, AdminListNodeContainersErrors, AdminListNodeContainersResponse, AdminListNodeContainersResponses, AdminListNodesData, AdminListNodesErrors, AdminListNodesResponse, AdminListNodesResponses, AdminRemoveNodeData, AdminRemoveNodeErrors, AdminRemoveNodeResponse, AdminRemoveNodeResponses, AdminUndrainNodeData, AdminUndrainNodeErrors, AdminUndrainNodeResponse, AdminUndrainNodeResponses, AgentConfigResponse, AgentRunLogResponse, AgentRunResponse, AgentRunWithLogsResponse, AgentSandboxSettings, AgentSandboxSettingsMasked, AggregatedBucketItem, AggregatedBucketsQuery, AggregatedBucketsResponse, AggregationLevel, AggregationTemporality, AiAgentBreakdownResponse, AiAgentBreakdownRow, AiAgentDescriptor, AiAgentPageRow, AiAgentPagesResponse, AiAgentTimelineResponse, AiAgentTimelineRow, AiChatLimitsSettings, AiConfigSettings, AiPageBreakdownResponse, AiPageBreakdownRow, AiStatusBreakdownResponse, AiStatusBreakdownRow, AlarmListResponse, AlarmResponse, AlarmSummaryResponse, AlertRuleResponse, AllocEntry, AnalyticsSessionEventsResponse, AnnotatedSpan, AnomalyAlgorithm, AnomalyParams, AnomalyPreviewPointResponse, AnomalyPreviewRequest, AnomalyPreviewResponse, ApiKeyListResponse, ApiKeyResponse, ApplyHostnameModeData, ApplyHostnameModeErrors, ApplyHostnameModeRequest, ApplyHostnameModeResponse, ApplyHostnameModeResponses, AppSettings, AppSettingsResponse, ArchiveConversationData, ArchiveConversationErrors, ArchiveConversationResponse, ArchiveConversationResponses, ArchiveFlagData, ArchiveFlagErrors, ArchiveFlagResponse, ArchiveFlagResponse2, ArchiveFlagResponses, ArchiveMode, AssignRoleData, AssignRoleErrors, AssignRoleRequest, AssignRoleResponses, AttachScheduleServicesData, AttachScheduleServicesError, AttachScheduleServicesErrors, AttachScheduleServicesRequest, AttachScheduleServicesResponse, AttachScheduleServicesResponse2, AttachScheduleServicesResponses, AuditLogIpInfo, AuditLogResponse, AuditLogUserInfo, AuthFlavorDto, AuthResponse, AuthStatusResponse, AuthTokenResponse, AutofixerRunResponse, AutofixerRunWithLogsResponse, AutofixRunConfig, AutoWatchParams, AvailableContainerInfo, AvailablePermissions, BackupAlertListResponse, BackupAlertResponse, BackupResponse, BackupScheduleResponse, BitbucketAuthInput, BlobCopyData, BlobCopyError, BlobCopyErrors, BlobCopyResponse, BlobCopyResponses, BlobDeleteData, BlobDeleteError, BlobDeleteErrors, BlobDeleteResponse, BlobDeleteResponses, BlobDisableData, BlobDisableErrors, BlobDisableResponse, BlobDisableResponses, BlobDownloadData, BlobDownloadError, BlobDownloadErrors, BlobDownloadResponses, BlobEnableData, BlobEnableErrors, BlobEnableResponse, BlobEnableResponses, BlobHeadData, BlobHeadError, BlobHeadErrors, BlobHeadResponses, BlobListData, BlobListError, BlobListErrors, BlobListResponse, BlobListResponses, BlobPutData, BlobPutError, BlobPutErrors, BlobPutResponse, BlobPutResponses, BlobResponse, BlobStatusData, BlobStatusErrors, BlobStatusResponse, BlobStatusResponse2, BlobStatusResponses, BlobUpdateData, BlobUpdateErrors, BlobUpdateResponse, BlobUpdateResponses, BranchInfo, BranchListResponse, BrowserCount, BrowsersQuery, BuildConfiguration, BuildLimitsSettings, CancelBackupData, CancelBackupError, CancelBackupErrors, CancelBackupResponse, CancelBackupResponse2, CancelBackupResponses, CancelData, CancelDeploymentData, CancelDeploymentErrors, CancelDeploymentResponse, CancelDeploymentResponses, CancelDomainOrderData, CancelDomainOrderErrors, CancelDomainOrderResponse, CancelDomainOrderResponses, CancelErrors, CancelPgUpgradeData, CancelPgUpgradeErrors, CancelPgUpgradeResponse, CancelPgUpgradeResponses, CancelResponses, CancelRunData, CancelRunErrors, CancelRunResponse, CancelRunResponses, CancelScheduleRunData, CancelScheduleRunError, CancelScheduleRunErrors, CancelScheduleRunResponse, CancelScheduleRunResponses, CertStatusResponse, ChallengeConfig, ChallengeError, ChallengeValidationStatus, ChangePasswordRequest, ChangePasswordSelfData, ChangePasswordSelfErrors, ChangePasswordSelfResponse, ChangePasswordSelfResponses, ChangeProjectSourceData, ChangeProjectSourceErrors, ChangeProjectSourceRequest, ChangeProjectSourceResponse, ChangeProjectSourceResponses, ChatCompletionChoice, ChatCompletionRequest, ChatCompletionResponse, ChatCompletionsData, ChatCompletionsError, ChatCompletionsErrors, ChatCompletionsResponse, ChatCompletionsResponses, ChatMessage, ChatReadinessResponse, CheckAnalyticsHasEventsData, CheckAnalyticsHasEventsErrors, CheckAnalyticsHasEventsResponse, CheckAnalyticsHasEventsResponses, CheckCommitExistsData, CheckCommitExistsErrors, CheckCommitExistsResponse, CheckCommitExistsResponses, CheckDomainStatusData, CheckDomainStatusErrors, CheckDomainStatusResponse, CheckDomainStatusResponses, CheckExplorerSupportData, CheckExplorerSupportErrors, CheckExplorerSupportResponse, CheckExplorerSupportResponses, CheckIpBlockedData, CheckIpBlockedError, CheckIpBlockedErrors, CheckIpBlockedResponses, CheckProviderDeletionSafetyData, CheckProviderDeletionSafetyErrors, CheckProviderDeletionSafetyResponse, CheckProviderDeletionSafetyResponses, ChildBackupEntryResponse, ChildBackupListResponse, ChunkUploadOptionsData, ChunkUploadOptionsResponse, ChunkUploadOptionsResponses, CleanupExpiredBackupsData, CleanupExpiredBackupsError, CleanupExpiredBackupsErrors, CleanupExpiredBackupsRequest, CleanupExpiredBackupsResponse, CleanupExpiredBackupsResponses, ClearPreviewPasswordData, ClearPreviewPasswordErrors, ClearPreviewPasswordResponse, ClearPreviewPasswordResponses, CliDeviceApproveData, CliDeviceApproveErrors, CliDeviceApproveRequest, CliDeviceApproveResponse, CliDeviceApproveResponse2, CliDeviceApproveResponses, CliDeviceDenyData, CliDeviceDenyErrors, CliDeviceDenyResponse, CliDeviceDenyResponses, CliDeviceLookupData, CliDeviceLookupErrors, CliDeviceLookupResponse, CliDeviceLookupResponse2, CliDeviceLookupResponses, CliDevicePollData, CliDevicePollErrors, CliDevicePollRequest, CliDevicePollResponse, CliDevicePollResponse2, CliDevicePollResponses, CliDeviceStartData, CliDeviceStartErrors, CliDeviceStartRequest, CliDeviceStartResponse, CliDeviceStartResponse2, CliDeviceStartResponses, ClientOptions, CliLoginRequest, CliLogoutData, CliLogoutErrors, CliLogoutResponse, CliLogoutResponses, CloudflareConfig, CloudProvider, ClusterCapacity, ClusterDnsSettings, ClusterHealthReportResponse, ClusterMemberHealthResponse, ClusterMemberRequest, CmdBody, CmdData, CmdErrors, CmdInner, CmdKillBody, CmdKillData, CmdKillErrors, CmdKillResponse, CmdKillResponses, CmdLogsData, CmdLogsErrors, CmdLogsResponses, CmdResponse, CmdResponse2, CmdResponses, CommitExistsResponse, CommitInfo, CommitListResponse, Comparator, ComposePublicPort, ConfirmPendingActionData, ConfirmPendingActionErrors, ConfirmPendingActionResponse, ConfirmPendingActionResponses, ConnectionListQuery, ConnectionListResponse, ConnectionResponse, ConnectionTestResult, ConsoleEventPayload, ContainerActionResponse, ContainerDetailResponse, ContainerEnvironmentVariableValueResponse, ContainerInfoResponse, ContainerInventoryItem, ContainerListResponse, ContainerLogSettings, ContainerLogsQuery, ContainerMetricHistoryPoint, ContainerMetricsGetHistoryData, ContainerMetricsGetHistoryErrors, ContainerMetricsGetHistoryResponse, ContainerMetricsGetHistoryResponses, ContainerMetricsHistoryQuery, ContainerMetricsResponse, ContainerResponse, ContainerRuntimeInfo, ContainerStatsSample, ContentPart, ContextLine, ContextLogsRequest, ContextLogsResponse, ConversationDetailResponse, ConversationResponse, ConversationsQueryParams, ConversationSummary, CopyBlobRequest, CostAnalysis, CreateAgentData, CreateAgentErrors, CreateAgentResponse, CreateAgentResponses, CreateAlertData, CreateAlertError, CreateAlertErrors, CreateAlertResponse, CreateAlertResponses, CreateAlertRuleData, CreateAlertRuleErrors, CreateAlertRuleRequest, CreateAlertRuleResponse, CreateAlertRuleResponses, CreateApiKeyData, CreateApiKeyErrors, CreateApiKeyRequest, CreateApiKeyResponse, CreateApiKeyResponse2, CreateApiKeyResponses, CreateBackupScheduleData, CreateBackupScheduleError, CreateBackupScheduleErrors, CreateBackupScheduleRequest, CreateBackupScheduleResponse, CreateBackupScheduleResponses, CreateBitbucketProviderData, CreateBitbucketProviderErrors, CreateBitbucketProviderResponse, CreateBitbucketProviderResponses, CreateBitbucketRequest, CreateCloudflareProviderData, CreateCloudflareProviderErrors, CreateCloudflareProviderRequest, CreateCloudflareProviderResponse, CreateCloudflareProviderResponses, CreateConversationData, CreateConversationErrors, CreateConversationRequest, CreateConversationResponse, CreateConversationResponses, CreateCustomDomainData, CreateCustomDomainErrors, CreateCustomDomainResponse, CreateCustomDomainResponses, CreateDashboardData, CreateDashboardError, CreateDashboardErrors, CreateDashboardRequest, CreateDashboardResponse, CreateDashboardResponses, CreateDeploymentTokenData, CreateDeploymentTokenErrors, CreateDeploymentTokenRequest, CreateDeploymentTokenResponse, CreateDeploymentTokenResponse2, CreateDeploymentTokenResponses, CreateDnsProviderData, CreateDnsProviderErrors, CreateDnsProviderRequest, CreateDnsProviderResponse, CreateDnsProviderResponses, CreateDomainData, CreateDomainErrors, CreateDomainRequest, CreateDomainResponse, CreateDomainResponses, CreatedResource, CreateDsnData, CreateDsnErrors, CreateDsnRequest, CreateDsnResponse, CreateDsnResponses, CreateEmailDomainData, CreateEmailDomainErrors, CreateEmailDomainRequest, CreateEmailDomainResponse, CreateEmailDomainResponses, CreateEmailProviderData, CreateEmailProviderErrors, CreateEmailProviderRequest, CreateEmailProviderResponse, CreateEmailProviderResponses, CreateEnvironmentData, CreateEnvironmentErrors, CreateEnvironmentRequest, CreateEnvironmentResponse, CreateEnvironmentResponses, CreateEnvironmentVariableData, CreateEnvironmentVariableErrors, CreateEnvironmentVariableRequest, CreateEnvironmentVariableResponse, CreateEnvironmentVariableResponses, CreateExternalServiceRequest, CreateFlagData, CreateFlagErrors, CreateFlagRequest, CreateFlagResponse, CreateFlagResponses, CreateFunnelData, CreateFunnelErrors, CreateFunnelRequest, CreateFunnelResponse, CreateFunnelResponse2, CreateFunnelResponses, CreateFunnelStep, CreateGenericProviderData, CreateGenericProviderErrors, CreateGenericProviderResponse, CreateGenericProviderResponses, CreateGenericRequest, CreateGiteaPatProviderData, CreateGiteaPatProviderErrors, CreateGiteaPatProviderResponse, CreateGiteaPatProviderResponses, CreateGiteaPatRequest, CreateGithubPatProviderData, CreateGithubPatProviderErrors, CreateGithubPatProviderResponse, CreateGithubPatProviderResponses, CreateGitHubPatRequest, CreateGitlabOauthProviderData, CreateGitlabOauthProviderErrors, CreateGitlabOauthProviderResponse, CreateGitlabOauthProviderResponses, CreateGitLabOAuthRequest, CreateGitlabPatProviderData, CreateGitlabPatProviderErrors, CreateGitlabPatProviderResponse, CreateGitlabPatProviderResponses, CreateGitLabPatRequest, CreateGitProviderData, CreateGitProviderErrors, CreateGitProviderResponse, CreateGitProviderResponses, CreateGlobalMcpData, CreateGlobalMcpErrors, CreateGlobalMcpResponse, CreateGlobalMcpResponses, CreateGlobalSkillData, CreateGlobalSkillErrors, CreateGlobalSkillResponse, CreateGlobalSkillResponses, CreateIncidentData, CreateIncidentErrors, CreateIncidentRequest, CreateIncidentResponse, CreateIncidentResponses, CreateIntegrationBody, CreateIpAccessControlData, CreateIpAccessControlError, CreateIpAccessControlErrors, CreateIpAccessControlRequest, CreateIpAccessControlResponse, CreateIpAccessControlResponses, CreateMcpData, CreateMcpErrors, CreateMcpRequest, CreateMcpResponse, CreateMcpResponses, CreateMetricAlertRequest, CreateMonitorData, CreateMonitorErrors, CreateMonitorRequest, CreateMonitorResponse, CreateMonitorResponses, CreateNotificationEmailProviderData, CreateNotificationEmailProviderErrors, CreateNotificationEmailProviderRequest, CreateNotificationEmailProviderResponse, CreateNotificationEmailProviderResponses, CreateNotificationProviderData, CreateNotificationProviderErrors, CreateNotificationProviderResponse, CreateNotificationProviderResponses, CreateOidcProviderData, CreateOidcProviderErrors, CreateOidcProviderRequest, CreateOidcProviderResponse, CreateOidcProviderResponses, CreateOidcRoleMappingData, CreateOidcRoleMappingRequest, CreateOidcRoleMappingResponse, CreateOidcRoleMappingResponses, CreateOrRecreateOrderData, CreateOrRecreateOrderErrors, CreateOrRecreateOrderResponse, CreateOrRecreateOrderResponses, CreatePlanData, CreatePlanErrors, CreatePlanRequest, CreatePlanResponse, CreatePlanResponse2, CreatePlanResponses, CreatePrData, CreatePrErrors, CreateProjectAccessRequest, CreateProjectData, CreateProjectErrors, CreateProjectFromTemplateData, CreateProjectFromTemplateErrors, CreateProjectFromTemplateRequest, CreateProjectFromTemplateResponse, CreateProjectFromTemplateResponse2, CreateProjectFromTemplateResponses, CreateProjectReleaseData, CreateProjectReleaseErrors, CreateProjectReleaseResponse, CreateProjectReleaseResponses, CreateProjectRequest, CreateProjectResponse, CreateProjectResponses, CreateProjectSecretData, CreateProjectSecretErrors, CreateProjectSecretRequest, CreateProjectSecretResponse, CreateProjectSecretResponses, CreateProviderKeyData, CreateProviderKeyError, CreateProviderKeyErrors, CreateProviderKeyRequest, CreateProviderKeyResponse, CreateProviderKeyResponses, CreateProviderRequest, CreatePrResponse, CreatePrResponse2, CreatePrResponses, CreateReleaseData, CreateReleaseErrors, CreateReleaseResponse, CreateReleaseResponses, CreateRouteData, CreateRouteErrors, CreateRouteRequest, CreateRouteResponse, CreateRouteResponses, CreateS3SourceData, CreateS3SourceError, CreateS3SourceErrors, CreateS3SourceRequest, CreateS3SourceResponse, CreateS3SourceResponses, CreateSandboxBody, CreateSandboxData, CreateSandboxErrors, CreateSandboxResponse, CreateSandboxResponses, CreateServiceData, CreateServiceErrors, CreateServiceResponse, CreateServiceResponses, CreateSkillData, CreateSkillErrors, CreateSkillRequest, CreateSkillResponse, CreateSkillResponses, CreateSlackProviderData, CreateSlackProviderErrors, CreateSlackProviderRequest, CreateSlackProviderResponse, CreateSlackProviderResponses, CreateTeamData, CreateTeamErrors, CreateTeamMemberRequest, CreateTeamRequest, CreateTeamResponse, CreateTeamResponses, CreateUserData, CreateUserErrors, CreateUserRequest, CreateUserResponse, CreateUserResponses, CreateWebhookData, CreateWebhookErrors, CreateWebhookProviderData, CreateWebhookProviderErrors, CreateWebhookProviderRequest, CreateWebhookProviderResponse, CreateWebhookProviderResponses, CreateWebhookRequestBody, CreateWebhookResponse, CreateWebhookResponses, CronExecutionInfo, CronInfo, CrossProjectSiblingRef, CrossProjectTraceResponse, CurrentStatusResponse, CustomDomainRequest, CustomDomainResponse, CustomerMovementResponse, DashboardLayout, DashboardProjectsAnalyticsQuery, DashboardProjectsAnalyticsResponse, DashboardSection, DashboardTile, DatabaseMetricsResponse, DatabaseMetricsRow, DataImplication, DataImplicationSeverity, DeactivateApiKeyData, DeactivateApiKeyErrors, DeactivateApiKeyResponse, DeactivateApiKeyResponses, DeactivateConnectionData, DeactivateConnectionErrors, DeactivateConnectionResponses, DeactivateProviderData, DeactivateProviderErrors, DeactivateProviderResponses, DeleteAgentData, DeleteAgentErrors, DeleteAgentResponse, DeleteAgentResponses, DeleteAlertData, DeleteAlertError, DeleteAlertErrors, DeleteAlertResponse, DeleteAlertResponses, DeleteAlertRuleData, DeleteAlertRuleErrors, DeleteAlertRuleResponse, DeleteAlertRuleResponses, DeleteApiKeyData, DeleteApiKeyErrors, DeleteApiKeyResponse, DeleteApiKeyResponses, DeleteBackupData, DeleteBackupError, DeleteBackupErrors, DeleteBackupResponse, DeleteBackupResponses, DeleteBackupScheduleData, DeleteBackupScheduleError, DeleteBackupScheduleErrors, DeleteBackupScheduleResponse, DeleteBackupScheduleResponses, DeleteBlobRequest, DeleteBlobResponse, DeleteConnectionData, DeleteConnectionErrors, DeleteConnectionResponse, DeleteConnectionResponses, DeleteCustomDomainData, DeleteCustomDomainErrors, DeleteCustomDomainResponse, DeleteCustomDomainResponses, DeleteDashboardData, DeleteDashboardError, DeleteDashboardErrors, DeleteDashboardResponse, DeleteDashboardResponses, DeleteDeploymentTokenData, DeleteDeploymentTokenErrors, DeleteDeploymentTokenResponse, DeleteDeploymentTokenResponses, DeleteDnsProviderData, DeleteDnsProviderErrors, DeleteDnsProviderResponse, DeleteDnsProviderResponses, DeleteDomainData, DeleteDomainErrors, DeleteDomainResponse, DeleteDomainResponses, DeleteEmailDomainData, DeleteEmailDomainErrors, DeleteEmailDomainResponse, DeleteEmailDomainResponses, DeleteEmailProviderData, DeleteEmailProviderErrors, DeleteEmailProviderResponse, DeleteEmailProviderResponses, DeleteEnvironmentData, DeleteEnvironmentDomainData, DeleteEnvironmentDomainErrors, DeleteEnvironmentDomainResponse, DeleteEnvironmentDomainResponses, DeleteEnvironmentErrors, DeleteEnvironmentResponse, DeleteEnvironmentResponses, DeleteEnvironmentVariableData, DeleteEnvironmentVariableErrors, DeleteEnvironmentVariableResponse, DeleteEnvironmentVariableResponses, DeleteExternalImageData, DeleteExternalImageErrors, DeleteExternalImageResponse, DeleteExternalImageResponses, DeleteFunnelData, DeleteFunnelErrors, DeleteFunnelResponses, DeleteGitProviderData, DeleteGitProviderErrors, DeleteGitProviderResponse, DeleteGitProviderResponses, DeleteGlobalMcpData, DeleteGlobalMcpErrors, DeleteGlobalMcpResponse, DeleteGlobalMcpResponses, DeleteGlobalSkillData, DeleteGlobalSkillErrors, DeleteGlobalSkillResponse, DeleteGlobalSkillResponses, DeleteIpAccessControlData, DeleteIpAccessControlError, DeleteIpAccessControlErrors, DeleteIpAccessControlResponse, DeleteIpAccessControlResponses, DeleteMcpData, DeleteMcpErrors, DeleteMcpResponse, DeleteMcpResponses, DeleteMonitorData, DeleteMonitorErrors, DeleteMonitorResponse, DeleteMonitorResponses, DeleteNotificationProviderData, DeleteNotificationProviderErrors, DeleteNotificationProviderResponse, DeleteNotificationProviderResponses, DeleteOidcProviderData, DeleteOidcProviderResponse, DeleteOidcProviderResponses, DeleteOidcRoleMappingData, DeleteOidcRoleMappingResponse, DeleteOidcRoleMappingResponses, DeletePreferencesData, DeletePreferencesErrors, DeletePreferencesResponse, DeletePreferencesResponses, DeleteProjectData, DeleteProjectErrors, DeleteProjectResponse, DeleteProjectResponses, DeleteProjectSecretData, DeleteProjectSecretErrors, DeleteProjectSecretResponse, DeleteProjectSecretResponses, DeleteProviderKeyData, DeleteProviderKeyError, DeleteProviderKeyErrors, DeleteProviderKeyResponse, DeleteProviderKeyResponses, DeleteProviderSafelyData, DeleteProviderSafelyErrors, DeleteProviderSafelyResponse, DeleteProviderSafelyResponses, DeleteReleaseSourceFilesData, DeleteReleaseSourceFilesErrors, DeleteReleaseSourceFilesResponse, DeleteReleaseSourceFilesResponses, DeleteReleaseSourceMapsData, DeleteReleaseSourceMapsErrors, DeleteReleaseSourceMapsResponse, DeleteReleaseSourceMapsResponses, DeleteResponse, DeleteRouteData, DeleteRouteErrors, DeleteRouteResponse, DeleteRouteResponses, DeleteS3SourceData, DeleteS3SourceError, DeleteS3SourceErrors, DeleteS3SourceResponse, DeleteS3SourceResponses, DeleteScanData, DeleteScanError, DeleteScanErrors, DeleteScanResponse, DeleteScanResponses, DeleteSecretData, DeleteSecretErrors, DeleteSecretResponse, DeleteSecretResponses, DeleteServiceData, DeleteServiceErrors, DeleteServiceResponse, DeleteServiceResponses, DeleteSessionReplayData, DeleteSessionReplayError, DeleteSessionReplayErrors, DeleteSessionReplayResponses, DeleteSkillData, DeleteSkillErrors, DeleteSkillResponse, DeleteSkillResponses, DeleteSourceMapData, DeleteSourceMapErrors, DeleteSourceMapResponse, DeleteSourceMapResponses, DeleteStaticBundleData, DeleteStaticBundleErrors, DeleteStaticBundleResponse, DeleteStaticBundleResponses, DeleteTeamData, DeleteTeamErrors, DeleteTeamResponse, DeleteTeamResponses, DeleteUserData, DeleteUserErrors, DeleteUserResponse, DeleteUserResponses, DeleteWebhookData, DeleteWebhookErrors, DeleteWebhookResponse, DeleteWebhookResponses, DelRequest, DelResponse, DeployFromImageData, DeployFromImageErrors, DeployFromImageRequest, DeployFromImageResponse, DeployFromImageResponses, DeployFromImageUploadData, DeployFromImageUploadErrors, DeployFromImageUploadQuery, DeployFromImageUploadResponse, DeployFromImageUploadResponses, DeployFromStaticData, DeployFromStaticErrors, DeployFromStaticRequest, DeployFromStaticResponse, DeployFromStaticResponses, DeployFromUploadedSourceData, DeployFromUploadedSourceErrors, DeployFromUploadedSourceResponse, DeployFromUploadedSourceResponses, DeploymentConfig, DeploymentConfigSnapshot, DeploymentConfiguration, DeploymentContainerLogContentResponse, DeploymentContainerLogResponse, DeploymentContainerLogsListResponse, DeploymentEnvironmentResponse, DeploymentJobResponse, DeploymentJobsResponse, DeploymentListResponse, DeploymentMetadata, DeploymentMetricsGetLatestData, DeploymentMetricsGetLatestErrors, DeploymentMetricsGetLatestResponse, DeploymentMetricsGetLatestResponses, DeploymentMetricsGetRangeData, DeploymentMetricsGetRangeErrors, DeploymentMetricsGetRangeResponse, DeploymentMetricsGetRangeResponses, DeploymentMetricsToggleData, DeploymentMetricsToggleErrors, DeploymentMetricsToggleResponses, DeploymentResponse, DeploymentStateResponse, DeploymentStrategy, DeploymentTokenListResponse, DeploymentTokenResponse, DestroySandboxData, DestroySandboxErrors, DestroySandboxResponse, DestroySandboxResponses, DetachScheduleServiceData, DetachScheduleServiceError, DetachScheduleServiceErrors, DetachScheduleServiceResponse, DetachScheduleServiceResponses, DetectionConfig, DetectPublicPresetsData, DetectPublicPresetsErrors, DetectPublicPresetsResponse, DetectPublicPresetsResponses, DeviceCount, DigestSections, Direction, DisableBackupScheduleData, DisableBackupScheduleErrors, DisableBackupScheduleResponse, DisableBackupScheduleResponses, DisableBlobResponse, DisableKvResponse, DisableMfaData, DisableMfaErrors, DisableMfaRequest, DisableMfaResponse, DisableMfaResponses, DiscoverRequest, DiscoverResponse, DiscoverWorkloadsData, DiscoverWorkloadsErrors, DiscoverWorkloadsResponse, DiscoverWorkloadsResponses, DiskInfo, DiskSpaceAlert, DiskSpaceAlertSettings, DiskSpaceCheckResult, DnsAckRequest, DnsAckResponse, DnsChallengeRecordResult, DnsChangesResponse, DnsCompletionResponse, DnsLookupError, DnsLookupRequest, DnsLookupResponse, DnsProviderCredentials, DnsProviderResponse, DnsProviderSettings, DnsProviderSettingsMasked, DnsProviderType, DnsRecord, DnsRecordChange, DnsRecordContent, DnsRecordResponse, DnsRecordSetupResult, DnsRecordStatusResponse, DnsZone, DockerComposePresetConfig, DockerfilePresetConfig, DockerfileVariant, DockerRegistrySettings, DockerRegistrySettingsMasked, DomainAction, DomainChallengeResponse, DomainData, DomainEnvironmentResponse, DomainError, DomainErrors, DomainPlan, DomainResponse, DomainResponse2, DomainResponses, DownloadGlobalSkillArchiveData, DownloadGlobalSkillArchiveErrors, DownloadGlobalSkillArchiveResponse, DownloadGlobalSkillArchiveResponses, DownloadObjectData, DownloadObjectErrors, DownloadObjectResponse, DownloadObjectResponses, DownloadSkillArchiveData, DownloadSkillArchiveErrors, DownloadSkillArchiveResponse, DownloadSkillArchiveResponses, DrainNodeResponse, DrainStatusResponse, DropArchiveUpload, DropInspectionResponse, DropOffPoint, DropPresetCandidate, EmailConfig, EmailDomainResponse, EmailDomainWithDnsResponse, EmailProviderResponse, EmailProviderTypeRoute, EmailRequest, EmailResponse, EmailStatsResponse, EmailStatusData, EmailStatusErrors, EmailStatusResponse, EmailStatusResponse2, EmailStatusResponses, EmailTrackingResponse, EmailTrackingSetupResponse, EmailTrackingStatusResponse, EmbeddingData, EmbeddingInput, EmbeddingRequest, EmbeddingResponse, EmbeddingsData, EmbeddingsError, EmbeddingsErrors, EmbeddingsResponse, EmbeddingsResponses, EmbeddingUsage, EnableBackupScheduleData, EnableBackupScheduleErrors, EnableBackupScheduleResponse, EnableBackupScheduleResponses, EnableBlobRequest, EnableBlobResponse, EnableKvRequest, EnableKvResponse, EnablePgStatStatementsResponse, EndpointDto, EnqueuedJob, EnrichVisitorData, EnrichVisitorErrors, EnrichVisitorRequest, EnrichVisitorResponse, EnrichVisitorResponse2, EnrichVisitorResponses, EnrollmentTokenInfo, EnrollmentTokenListResponse, EntityInfoResponse, EntityResponse, EnvironmentConfiguration, EnvironmentDomainResponse, EnvironmentInfo, EnvironmentResponse, EnvironmentVariable, EnvironmentVariableInfo, EnvironmentVariableResponse, EnvironmentVariableValueResponse, EnvVarInput, EnvVarIntegrationInfo, EnvVarResponse, EnvVarTemplateResponse, ErrorDashboardStatsQuery, ErrorDashboardStatsResponse, ErrorEventResponse, ErrorGroupResponse, ErrorGroupStatsResponse, ErrorResponse, ErrorRow, ErrorTimeSeriesDataResponse, ErrorTimeSeriesQuery, EventActivityBucket, EventBreakdown, EventBrowserStats, EventCount, EventCountryStats, EventDetailQuery, EventDetailResponse, EventEntriesQuery, EventEntriesResponse, EventEntryInfo, EventKind, EventMetricsPayload, EventReferrerStats, EventsCountQuery, EventsResponse, EventTimeline, EventTimelineQuery, EventType, EventTypeBreakdown, EventTypeBreakdownQuery, EventTypeResponse, EventTypesResponse, EventVisitorInfo, EventVisitorsQuery, EventVisitorsResponse, ExecBody, ExecData, ExecDetachedData, ExecDetachedErrors, ExecDetachedResponse, ExecDetachedResponse2, ExecDetachedResponses, ExecErrors, ExecResponse, ExecResponse2, ExecResponses, ExecuteDeploymentOperationData, ExecuteDeploymentOperationErrors, ExecuteDeploymentOperationResponse, ExecuteDeploymentOperationResponses, ExecuteImportData, ExecuteImportErrors, ExecuteImportRequest, ExecuteImportResponse, ExecuteImportResponse2, ExecuteImportResponses, ExecuteOperationRequest, ExpireRequest, ExpireResponse, ExplorerSupportResponse, ExtendTimeoutBody, ExtendTimeoutData, ExtendTimeoutErrors, ExtendTimeoutResponse, ExtendTimeoutResponses, ExternalImageResponse, ExternalServiceBackupResponse, ExternalServiceDetails, ExternalServiceEnablePgStatStatementsData, ExternalServiceEnablePgStatStatementsErrors, ExternalServiceEnablePgStatStatementsResponse, ExternalServiceEnablePgStatStatementsResponses, ExternalServiceInfo, ExternalServiceMetricsByDatabaseData, ExternalServiceMetricsByDatabaseErrors, ExternalServiceMetricsByDatabaseResponse, ExternalServiceMetricsByDatabaseResponses, ExternalServiceMetricsCreateAlertRuleData, ExternalServiceMetricsCreateAlertRuleErrors, ExternalServiceMetricsCreateAlertRuleResponse, ExternalServiceMetricsCreateAlertRuleResponses, ExternalServiceMetricsDeleteAlertRuleData, ExternalServiceMetricsDeleteAlertRuleErrors, ExternalServiceMetricsDeleteAlertRuleResponse, ExternalServiceMetricsDeleteAlertRuleResponses, ExternalServiceMetricsGetAlertRulesData, ExternalServiceMetricsGetAlertRulesErrors, ExternalServiceMetricsGetAlertRulesResponse, ExternalServiceMetricsGetAlertRulesResponses, ExternalServiceMetricsGetLatestData, ExternalServiceMetricsGetLatestErrors, ExternalServiceMetricsGetLatestResponse, ExternalServiceMetricsGetLatestResponses, ExternalServiceMetricsGetRangeData, ExternalServiceMetricsGetRangeErrors, ExternalServiceMetricsGetRangeResponse, ExternalServiceMetricsGetRangeResponses, ExternalServiceMetricsStatusData, ExternalServiceMetricsStatusErrors, ExternalServiceMetricsStatusResponse, ExternalServiceMetricsStatusResponses, ExternalServiceMetricsToggleData, ExternalServiceMetricsToggleErrors, ExternalServiceMetricsToggleResponses, ExternalServiceMetricsUpdateAlertRuleData, ExternalServiceMetricsUpdateAlertRuleErrors, ExternalServiceMetricsUpdateAlertRuleResponse, ExternalServiceMetricsUpdateAlertRuleResponses, ExternalServiceResetPgStatStatementsData, ExternalServiceResetPgStatStatementsErrors, ExternalServiceResetPgStatStatementsResponse, ExternalServiceResetPgStatStatementsResponses, ExternalServiceSummary, FieldResponse, FinalizeOrderData, FinalizeOrderErrors, FinalizeOrderResponse, FinalizeOrderResponses, FinalizeProjectReleaseData, FinalizeProjectReleaseErrors, FinalizeProjectReleaseResponse, FinalizeProjectReleaseResponses, FindConversationData, FindConversationErrors, FindConversationResponse, FindConversationResponses, FiringSeriesEntry, FlagEnvironmentResponse, FlagListResponse, FlagResponse, FlagSnapshot, FlagSnapshotResponse, FlagValueType, ForecastAlgorithm, ForecastParams, FullError, FullEvent, FullRequest, FunnelMetricsResponse, FunnelResponse, GatewayStatus, GenAiEvent, GenAiSpanDetail, GenAiTraceDetailResponse, GenAiTraceSummariesResponse, GenAiTraceSummary, GeneralStatsQuery, GeneralStatsResponse, GenerateDockerfileRequest, GenerateDockerfileResponse, GenerateJoinTokenData, GenerateJoinTokenErrors, GenerateJoinTokenResponse, GenerateJoinTokenResponse2, GenerateJoinTokenResponses, GeneratePresetDockerfileData, GeneratePresetDockerfileErrors, GeneratePresetDockerfileResponse, GeneratePresetDockerfileResponses, GeoLocationResponse, GeoRestrictionsConfig, GetAccessInfoData, GetAccessInfoErrors, GetAccessInfoResponse, GetAccessInfoResponses, GetActiveVisitorsData, GetActiveVisitorsErrors, GetActiveVisitorsResponse, GetActiveVisitorsResponses, GetActivityGraphData, GetActivityGraphErrors, GetActivityGraphResponse, GetActivityGraphResponses, GetAdminGateData, GetAdminGateErrors, GetAdminGateResponse, GetAdminGateResponses, GetAgentData, GetAgentErrors, GetAgentResponse, GetAgentResponses, GetAggregatedBucketsData, GetAggregatedBucketsErrors, GetAggregatedBucketsResponse, GetAggregatedBucketsResponses, GetAiAgentBreakdownData, GetAiAgentBreakdownError, GetAiAgentBreakdownErrors, GetAiAgentBreakdownResponse, GetAiAgentBreakdownResponses, GetAiAgentPagesData, GetAiAgentPagesError, GetAiAgentPagesErrors, GetAiAgentPagesResponse, GetAiAgentPagesResponses, GetAiAgentTimelineData, GetAiAgentTimelineError, GetAiAgentTimelineErrors, GetAiAgentTimelineResponse, GetAiAgentTimelineResponses, GetAiPageBreakdownData, GetAiPageBreakdownError, GetAiPageBreakdownErrors, GetAiPageBreakdownResponse, GetAiPageBreakdownResponses, GetAiStatusBreakdownData, GetAiStatusBreakdownError, GetAiStatusBreakdownErrors, GetAiStatusBreakdownResponse, GetAiStatusBreakdownResponses, GetAlertData, GetAlertError, GetAlertErrors, GetAlertResponse, GetAlertResponses, GetAlertRuleData, GetAlertRuleErrors, GetAlertRuleResponse, GetAlertRuleResponses, GetAllRepositoriesByNameData, GetAllRepositoriesByNameErrors, GetAllRepositoriesByNameResponse, GetAllRepositoriesByNameResponses, GetAnalyticsActiveVisitorsData, GetAnalyticsActiveVisitorsErrors, GetAnalyticsActiveVisitorsResponse, GetAnalyticsActiveVisitorsResponses, GetAnalyticsEventsCountData, GetAnalyticsEventsCountErrors, GetAnalyticsEventsCountResponse, GetAnalyticsEventsCountResponses, GetAnalyticsSessionEventsData, GetAnalyticsSessionEventsErrors, GetAnalyticsSessionEventsResponse, GetAnalyticsSessionEventsResponses, GetAnalyticsVisitorSessionsData, GetAnalyticsVisitorSessionsErrors, GetAnalyticsVisitorSessionsResponse, GetAnalyticsVisitorSessionsResponses, GetApiKeyData, GetApiKeyErrors, GetApiKeyPermissionsData, GetApiKeyPermissionsErrors, GetApiKeyPermissionsResponse, GetApiKeyPermissionsResponses, GetApiKeyResponse, GetApiKeyResponses, GetAuditLogData, GetAuditLogErrors, GetAuditLogResponse, GetAuditLogResponses, GetBackupData, GetBackupError, GetBackupErrors, GetBackupResponse, GetBackupResponses, GetBackupScheduleData, GetBackupScheduleErrors, GetBackupScheduleResponse, GetBackupScheduleResponses, GetBranchesByRepositoryIdData, GetBranchesByRepositoryIdErrors, GetBranchesByRepositoryIdResponse, GetBranchesByRepositoryIdResponses, GetBucketedIncidentsData, GetBucketedIncidentsErrors, GetBucketedIncidentsResponse, GetBucketedIncidentsResponses, GetBucketedStatusData, GetBucketedStatusErrors, GetBucketedStatusResponse, GetBucketedStatusResponses, GetChallengeTokenData, GetChallengeTokenErrors, GetChallengeTokenResponse, GetChallengeTokenResponses, GetChatReadinessData, GetChatReadinessErrors, GetChatReadinessResponse, GetChatReadinessResponses, GetCliStatusData, GetCliStatusErrors, GetCliStatusResponses, GetClusterHealthData, GetClusterHealthErrors, GetClusterHealthResponse, GetClusterHealthResponses, GetClusterMemberData, GetClusterMemberErrors, GetClusterMemberResponse, GetClusterMemberResponses, GetCmdData, GetCmdErrors, GetCmdResponse, GetCmdResponses, GetContainerDetailData, GetContainerDetailErrors, GetContainerDetailResponse, GetContainerDetailResponses, GetContainerEnvironmentVariableData, GetContainerEnvironmentVariableErrors, GetContainerEnvironmentVariableResponse, GetContainerEnvironmentVariableResponses, GetContainerInfoData, GetContainerInfoErrors, GetContainerInfoResponse, GetContainerInfoResponses, GetContainerLogsByIdData, GetContainerLogsByIdErrors, GetContainerLogsData, GetContainerLogsErrors, GetContainerMetricsData, GetContainerMetricsErrors, GetContainerMetricsResponse, GetContainerMetricsResponses, GetConversationData, GetConversationDetailData, GetConversationDetailError, GetConversationDetailErrors, GetConversationDetailResponse, GetConversationDetailResponses, GetConversationErrors, GetConversationResponse, GetConversationResponses, GetConversationsData, GetConversationsError, GetConversationsErrors, GetConversationsResponse, GetConversationsResponses, GetCronByIdData, GetCronByIdErrors, GetCronByIdResponse, GetCronByIdResponses, GetCronExecutionsData, GetCronExecutionsErrors, GetCronExecutionsResponse, GetCronExecutionsResponses, GetCrossProjectTraceSiblingsData, GetCrossProjectTraceSiblingsError, GetCrossProjectTraceSiblingsErrors, GetCrossProjectTraceSiblingsResponse, GetCrossProjectTraceSiblingsResponses, GetCurrentMonitorStatusData, GetCurrentMonitorStatusErrors, GetCurrentMonitorStatusResponse, GetCurrentMonitorStatusResponses, GetCurrentUserData, GetCurrentUserErrors, GetCurrentUserResponse, GetCurrentUserResponses, GetCustomDomainData, GetCustomDomainErrors, GetCustomDomainResponse, GetCustomDomainResponses, GetDashboardData, GetDashboardError, GetDashboardErrors, GetDashboardProjectsAnalyticsData, GetDashboardProjectsAnalyticsErrors, GetDashboardProjectsAnalyticsResponse, GetDashboardProjectsAnalyticsResponses, GetDashboardResponse, GetDashboardResponses, GetDeliveryData, GetDeliveryErrors, GetDeliveryResponse, GetDeliveryResponses, GetDeploymentContainerLogContentData, GetDeploymentContainerLogContentErrors, GetDeploymentContainerLogContentResponse, GetDeploymentContainerLogContentResponses, GetDeploymentData, GetDeploymentErrors, GetDeploymentJobLogsData, GetDeploymentJobLogsErrors, GetDeploymentJobLogsResponse, GetDeploymentJobLogsResponses, GetDeploymentJobsData, GetDeploymentJobsErrors, GetDeploymentJobsResponse, GetDeploymentJobsResponses, GetDeploymentOperationsData, GetDeploymentOperationsErrors, GetDeploymentOperationsResponse, GetDeploymentOperationsResponses, GetDeploymentOperationStatusData, GetDeploymentOperationStatusErrors, GetDeploymentOperationStatusResponse, GetDeploymentOperationStatusResponses, GetDeploymentResponse, GetDeploymentResponses, GetDeploymentsParams, GetDeploymentTokenData, GetDeploymentTokenErrors, GetDeploymentTokenResponse, GetDeploymentTokenResponses, GetDiskStatusData, GetDiskStatusErrors, GetDiskStatusResponse, GetDiskStatusResponses, GetDnsChangesData, GetDnsChangesErrors, GetDnsChangesResponse, GetDnsChangesResponses, GetDnsProviderData, GetDnsProviderErrors, GetDnsProviderResponse, GetDnsProviderResponses, GetDomainByHostData, GetDomainByHostErrors, GetDomainByHostResponse, GetDomainByHostResponses, GetDomainByIdData, GetDomainByIdErrors, GetDomainByIdResponse, GetDomainByIdResponses, GetDomainByNameData, GetDomainByNameErrors, GetDomainByNameResponse, GetDomainByNameResponses, GetDomainData, GetDomainDnsRecordsData, GetDomainDnsRecordsErrors, GetDomainDnsRecordsResponse, GetDomainDnsRecordsResponses, GetDomainErrors, GetDomainOrderData, GetDomainOrderErrors, GetDomainOrderResponse, GetDomainOrderResponses, GetDomainResponse, GetDomainResponses, GetEmailData, GetEmailErrors, GetEmailEventsData, GetEmailEventsErrors, GetEmailEventsResponse, GetEmailEventsResponses, GetEmailLinksData, GetEmailLinksErrors, GetEmailLinksResponse, GetEmailLinksResponses, GetEmailProviderData, GetEmailProviderErrors, GetEmailProviderResponse, GetEmailProviderResponses, GetEmailResponse, GetEmailResponses, GetEmailStatsData, GetEmailStatsErrors, GetEmailStatsResponse, GetEmailStatsResponses, GetEmailTrackingData, GetEmailTrackingErrors, GetEmailTrackingResponse, GetEmailTrackingResponses, GetEmailTrackingStatusData, GetEmailTrackingStatusErrors, GetEmailTrackingStatusResponse, GetEmailTrackingStatusResponses, GetEntityInfoData, GetEntityInfoErrors, GetEntityInfoResponse, GetEntityInfoResponses, GetEnvironmentCronsData, GetEnvironmentCronsErrors, GetEnvironmentCronsResponse, GetEnvironmentCronsResponses, GetEnvironmentData, GetEnvironmentDomainsData, GetEnvironmentDomainsErrors, GetEnvironmentDomainsResponse, GetEnvironmentDomainsResponses, GetEnvironmentErrors, GetEnvironmentResponse, GetEnvironmentResponses, GetEnvironmentsData, GetEnvironmentsErrors, GetEnvironmentsResponse, GetEnvironmentsResponses, GetEnvironmentVariablesData, GetEnvironmentVariablesErrors, GetEnvironmentVariablesQuery, GetEnvironmentVariablesResponse, GetEnvironmentVariablesResponses, GetEnvironmentVariableValueData, GetEnvironmentVariableValueErrors, GetEnvironmentVariableValueResponse, GetEnvironmentVariableValueResponses, GetErrorDashboardStatsData, GetErrorDashboardStatsErrors, GetErrorDashboardStatsResponse, GetErrorDashboardStatsResponses, GetErrorEventData, GetErrorEventErrors, GetErrorEventResponse, GetErrorEventResponses, GetErrorGroupData, GetErrorGroupErrors, GetErrorGroupResponse, GetErrorGroupResponses, GetErrorStatsData, GetErrorStatsErrors, GetErrorStatsResponse, GetErrorStatsResponses, GetErrorTimeSeriesData, GetErrorTimeSeriesErrors, GetErrorTimeSeriesResponse, GetErrorTimeSeriesResponses, GetEventDetailData, GetEventDetailErrors, GetEventDetailResponse, GetEventDetailResponses, GetEventEntriesData, GetEventEntriesErrors, GetEventEntriesResponse, GetEventEntriesResponses, GetEventsCountData, GetEventsCountErrors, GetEventsCountResponse, GetEventsCountResponses, GetEventsTimelineData, GetEventsTimelineErrors, GetEventsTimelineResponse, GetEventsTimelineResponses, GetEventTypeBreakdownData, GetEventTypeBreakdownErrors, GetEventTypeBreakdownResponse, GetEventTypeBreakdownResponses, GetEventVisitorsData, GetEventVisitorsErrors, GetEventVisitorsResponse, GetEventVisitorsResponses, GetExternalImageData, GetExternalImageErrors, GetExternalImageResponse, GetExternalImageResponses, GetFileData, GetFileErrors, GetFileResponse, GetFileResponses, GetFlagData, GetFlagErrors, GetFlagResponse, GetFlagResponses, GetFlagSnapshotData, GetFlagSnapshotErrors, GetFlagSnapshotResponse, GetFlagSnapshotResponses, GetFunnelMetricsData, GetFunnelMetricsErrors, GetFunnelMetricsQuery, GetFunnelMetricsResponse, GetFunnelMetricsResponses, GetGenaiTraceData, GetGenaiTraceError, GetGenaiTraceErrors, GetGenaiTraceResponse, GetGenaiTraceResponses, GetGeneralStatsData, GetGeneralStatsErrors, GetGeneralStatsResponse, GetGeneralStatsResponses, GetGitProviderData, GetGitProviderErrors, GetGitProviderResponse, GetGitProviderResponses, GetGlobalEventsData, GetGlobalEventsErrors, GetGlobalEventsResponse, GetGlobalEventsResponses, GetGlobalEventStatsData, GetGlobalEventStatsErrors, GetGlobalEventStatsResponse, GetGlobalEventStatsResponses, GetGlobalMcpData, GetGlobalMcpErrors, GetGlobalMcpResponse, GetGlobalMcpResponses, GetGlobalSandboxStatusData, GetGlobalSandboxStatusErrors, GetGlobalSandboxStatusResponse, GetGlobalSandboxStatusResponses, GetGlobalSkillData, GetGlobalSkillErrors, GetGlobalSkillResponse, GetGlobalSkillResponses, GetGroupedPageMetricsData, GetGroupedPageMetricsError, GetGroupedPageMetricsErrors, GetGroupedPageMetricsResponse, GetGroupedPageMetricsResponses, GetHealthData, GetHealthError, GetHealthErrors, GetHealthResponse, GetHealthResponses, GetHourlyVisitsData, GetHourlyVisitsErrors, GetHourlyVisitsResponse, GetHourlyVisitsResponses, GetHttpChallengeDebugData, GetHttpChallengeDebugErrors, GetHttpChallengeDebugResponse, GetHttpChallengeDebugResponses, GetImportStatusData, GetImportStatusErrors, GetImportStatusResponse, GetImportStatusResponses, GetIncidentData, GetIncidentErrors, GetIncidentResponse, GetIncidentResponses, GetIncidentUpdatesData, GetIncidentUpdatesErrors, GetIncidentUpdatesResponse, GetIncidentUpdatesResponses, GetIpAccessControlData, GetIpAccessControlError, GetIpAccessControlErrors, GetIpAccessControlResponse, GetIpAccessControlResponses, GetIpGeolocationData, GetIpGeolocationError, GetIpGeolocationErrors, GetIpGeolocationResponse, GetIpGeolocationResponses, GetJoinTokenStatusData, GetJoinTokenStatusErrors, GetJoinTokenStatusResponse, GetJoinTokenStatusResponses, GetLastDeploymentData, GetLastDeploymentErrors, GetLastDeploymentResponse, GetLastDeploymentResponses, GetLatestScanData, GetLatestScanError, GetLatestScanErrors, GetLatestScanResponse, GetLatestScanResponses, GetLatestScansPerEnvironmentData, GetLatestScansPerEnvironmentError, GetLatestScansPerEnvironmentErrors, GetLatestScansPerEnvironmentResponse, GetLatestScansPerEnvironmentResponses, GetLiveVisitorsListData, GetLiveVisitorsListErrors, GetLiveVisitorsListResponse, GetLiveVisitorsListResponses, GetLogContextData, GetLogContextError, GetLogContextErrors, GetLogContextResponse, GetLogContextResponses, GetMcpData, GetMcpErrors, GetMcpResponse, GetMcpResponses, GetMetricsOverTimeData, GetMetricsOverTimeError, GetMetricsOverTimeErrors, GetMetricsOverTimeResponse, GetMetricsOverTimeResponses, GetMonitorData, GetMonitorErrors, GetMonitorResponse, GetMonitorResponses, GetNotificationProviderData, GetNotificationProviderErrors, GetNotificationProviderResponse, GetNotificationProviderResponses, GetOnDemandCertStatusData, GetOnDemandCertStatusErrors, GetOnDemandCertStatusResponse, GetOnDemandCertStatusResponses, GetOrCreateDsnData, GetOrCreateDsnErrors, GetOrCreateDsnRequest, GetOrCreateDsnResponse, GetOrCreateDsnResponses, GetPageFlowData, GetPageFlowErrors, GetPageFlowResponse, GetPageFlowResponses, GetPageHourlySessionsData, GetPageHourlySessionsErrors, GetPageHourlySessionsResponse, GetPageHourlySessionsResponses, GetPagePathDetailData, GetPagePathDetailErrors, GetPagePathDetailResponse, GetPagePathDetailResponses, GetPagePathsData, GetPagePathsErrors, GetPagePathsResponse, GetPagePathsResponses, GetPagePathsSparklinesData, GetPagePathsSparklinesErrors, GetPagePathsSparklinesResponse, GetPagePathsSparklinesResponses, GetPagePathVisitorsData, GetPagePathVisitorsErrors, GetPagePathVisitorsResponse, GetPagePathVisitorsResponses, GetPendingActionData, GetPendingActionErrors, GetPendingActionResponse, GetPendingActionResponses, GetPerformanceMetricsData, GetPerformanceMetricsError, GetPerformanceMetricsErrors, GetPerformanceMetricsResponse, GetPerformanceMetricsResponses, GetPgUpgradeData, GetPgUpgradeErrors, GetPgUpgradeLogsData, GetPgUpgradeLogsErrors, GetPgUpgradeLogsResponse, GetPgUpgradeLogsResponses, GetPgUpgradeResponse, GetPgUpgradeResponses, GetPipelineStatsData, GetPipelineStatsError, GetPipelineStatsErrors, GetPipelineStatsResponse, GetPipelineStatsResponses, GetPlatformInfoData, GetPlatformInfoErrors, GetPlatformInfoResponse, GetPlatformInfoResponses, GetPostgresWalHealthData, GetPostgresWalHealthErrors, GetPostgresWalHealthResponse, GetPostgresWalHealthResponses, GetPreferencesData, GetPreferencesErrors, GetPreferencesResponse, GetPreferencesResponses, GetPreviewGatewayLogsData, GetPreviewGatewayLogsResponse, GetPreviewGatewayLogsResponses, GetPreviewGatewaySettingsData, GetPreviewGatewaySettingsResponse, GetPreviewGatewaySettingsResponses, GetPreviewGatewayStatusData, GetPreviewGatewayStatusResponse, GetPreviewGatewayStatusResponses, GetPricingData, GetPricingError, GetPricingErrors, GetPricingResponse, GetPricingResponses, GetPrivateIpData, GetPrivateIpErrors, GetPrivateIpResponses, GetProjectAlarmsSummaryData, GetProjectAlarmsSummaryErrors, GetProjectAlarmsSummaryResponse, GetProjectAlarmsSummaryResponses, GetProjectBySlugData, GetProjectBySlugErrors, GetProjectBySlugResponse, GetProjectBySlugResponses, GetProjectData, GetProjectDeploymentsData, GetProjectDeploymentsErrors, GetProjectDeploymentsResponse, GetProjectDeploymentsResponses, GetProjectErrors, GetProjectResponse, GetProjectResponses, GetProjectsData, GetProjectSecretsQuery, GetProjectsErrors, GetProjectServiceEnvironmentVariablesData, GetProjectServiceEnvironmentVariablesErrors, GetProjectServiceEnvironmentVariablesResponse, GetProjectServiceEnvironmentVariablesResponses, GetProjectSessionReplaysData, GetProjectSessionReplaysError, GetProjectSessionReplaysErrors, GetProjectSessionReplaysQuery, GetProjectSessionReplaysResponse, GetProjectSessionReplaysResponse2, GetProjectSessionReplaysResponses, GetProjectsHealthData, GetProjectsHealthError, GetProjectsHealthErrors, GetProjectsHealthResponse, GetProjectsHealthResponses, GetProjectsMonitorHealthData, GetProjectsMonitorHealthErrors, GetProjectsMonitorHealthResponse, GetProjectsMonitorHealthResponses, GetProjectsResponse, GetProjectsResponses, GetProjectStatisticsData, GetProjectStatisticsErrors, GetProjectStatisticsResponse, GetProjectStatisticsResponses, GetProjectTemplateData, GetProjectTemplateErrors, GetProjectTemplateResponse, GetProjectTemplateResponses, GetPropertyBreakdownData, GetPropertyBreakdownErrors, GetPropertyBreakdownResponse, GetPropertyBreakdownResponses, GetPropertyTimelineData, GetPropertyTimelineErrors, GetPropertyTimelineResponse, GetPropertyTimelineResponses, GetProviderConnectionsData, GetProviderConnectionsErrors, GetProviderConnectionsResponse, GetProviderConnectionsResponses, GetProviderMetadataData, GetProviderMetadataErrors, GetProviderMetadataResponse, GetProviderMetadataResponses, GetProvidersMetadataData, GetProvidersMetadataErrors, GetProvidersMetadataResponse, GetProvidersMetadataResponses, GetProxyLogByIdData, GetProxyLogByIdError, GetProxyLogByIdErrors, GetProxyLogByIdResponse, GetProxyLogByIdResponses, GetProxyLogByRequestIdData, GetProxyLogByRequestIdError, GetProxyLogByRequestIdErrors, GetProxyLogByRequestIdResponse, GetProxyLogByRequestIdResponses, GetProxyLogsData, GetProxyLogsError, GetProxyLogsErrors, GetProxyLogsResponse, GetProxyLogsResponses, GetPublicBranchesData, GetPublicBranchesErrors, GetPublicBranchesResponse, GetPublicBranchesResponses, GetPublicIpData, GetPublicIpErrors, GetPublicIpResponses, GetPublicRepositoryData, GetPublicRepositoryErrors, GetPublicRepositoryResponse, GetPublicRepositoryResponses, GetQuotaData, GetQuotaError, GetQuotaErrors, GetQuotaResponse, GetQuotaResponses, GetRecentActivityData, GetRecentActivityErrors, GetRecentActivityResponse, GetRecentActivityResponses, GetRemoteExternalImageData, GetRemoteExternalImageErrors, GetRemoteExternalImageResponse, GetRemoteExternalImageResponses, GetRepositoryBranchesData, GetRepositoryBranchesErrors, GetRepositoryBranchesResponse, GetRepositoryBranchesResponses, GetRepositoryByIdData, GetRepositoryByIdErrors, GetRepositoryByIdResponse, GetRepositoryByIdResponses, GetRepositoryByNameData, GetRepositoryByNameErrors, GetRepositoryByNameResponse, GetRepositoryByNameResponses, GetRepositoryPresetByNameData, GetRepositoryPresetByNameErrors, GetRepositoryPresetByNameResponse, GetRepositoryPresetByNameResponses, GetRepositoryPresetLiveData, GetRepositoryPresetLiveErrors, GetRepositoryPresetLiveResponse, GetRepositoryPresetLiveResponses, GetRepositoryTagsData, GetRepositoryTagsErrors, GetRepositoryTagsResponse, GetRepositoryTagsResponses, GetRequest, GetResolvedEnvironmentVariablesData, GetResolvedEnvironmentVariablesErrors, GetResolvedEnvironmentVariablesResponse, GetResolvedEnvironmentVariablesResponses, GetResolvedEnvironmentVariableValueData, GetResolvedEnvironmentVariableValueErrors, GetResolvedEnvironmentVariableValueResponse, GetResolvedEnvironmentVariableValueResponses, GetResponse, GetRestoreCapabilitiesData, GetRestoreCapabilitiesError, GetRestoreCapabilitiesErrors, GetRestoreCapabilitiesResponse, GetRestoreCapabilitiesResponses, GetRestoreRunData, GetRestoreRunError, GetRestoreRunErrors, GetRestoreRunResponse, GetRestoreRunResponses, GetRouteData, GetRouteErrors, GetRouteResponse, GetRouteResponses, GetRunData, GetRunErrors, GetRunResponse, GetRunResponses, GetRunWithLogsData, GetRunWithLogsErrors, GetRunWithLogsResponse, GetRunWithLogsResponses, GetS3CredentialsData, GetS3CredentialsErrors, GetS3CredentialsResponse, GetS3CredentialsResponses, GetS3SourceData, GetS3SourceError, GetS3SourceErrors, GetS3SourceResponse, GetS3SourceResponses, GetSandboxData, GetSandboxErrors, GetSandboxResponse, GetSandboxResponses, GetSandboxStatusData, GetSandboxStatusErrors, GetSandboxStatusResponse, GetSandboxStatusResponses, GetScanByDeploymentData, GetScanByDeploymentError, GetScanByDeploymentErrors, GetScanByDeploymentResponse, GetScanByDeploymentResponses, GetScanData, GetScanError, GetScanErrors, GetScanResponse, GetScanResponses, GetScanVulnerabilitiesData, GetScanVulnerabilitiesError, GetScanVulnerabilitiesErrors, GetScanVulnerabilitiesResponse, GetScanVulnerabilitiesResponses, GetServiceBySlugData, GetServiceBySlugErrors, GetServiceBySlugResponse, GetServiceBySlugResponses, GetServiceData, GetServiceEnvironmentVariableData, GetServiceEnvironmentVariableErrors, GetServiceEnvironmentVariableResponse, GetServiceEnvironmentVariableResponses, GetServiceEnvironmentVariablesData, GetServiceEnvironmentVariablesErrors, GetServiceEnvironmentVariablesResponse, GetServiceEnvironmentVariablesResponses, GetServiceErrors, GetServiceHealthStatusData, GetServiceHealthStatusErrors, GetServiceHealthStatusResponse, GetServiceHealthStatusResponses, GetServicePreviewEnvironmentVariableNamesData, GetServicePreviewEnvironmentVariableNamesErrors, GetServicePreviewEnvironmentVariableNamesResponse, GetServicePreviewEnvironmentVariableNamesResponses, GetServicePreviewEnvironmentVariablesMaskedData, GetServicePreviewEnvironmentVariablesMaskedErrors, GetServicePreviewEnvironmentVariablesMaskedResponse, GetServicePreviewEnvironmentVariablesMaskedResponses, GetServiceResponse, GetServiceResponses, GetServiceRuntimeData, GetServiceRuntimeErrors, GetServiceRuntimeResponse, GetServiceRuntimeResponses, GetServiceStatsData, GetServiceStatsErrors, GetServiceStatsResponse, GetServiceStatsResponses, GetServiceTypeParametersData, GetServiceTypeParametersErrors, GetServiceTypeParametersResponses, GetServiceTypesData, GetServiceTypesErrors, GetServiceTypesResponse, GetServiceTypesResponses, GetSessionDetailsData, GetSessionDetailsErrors, GetSessionDetailsResponse, GetSessionDetailsResponses, GetSessionEventsData, GetSessionEventsErrors, GetSessionEventsResponse, GetSessionEventsResponses, GetSessionLogsData, GetSessionLogsErrors, GetSessionLogsResponse, GetSessionLogsResponses, GetSessionReplayData, GetSessionReplayError, GetSessionReplayErrors, GetSessionReplayEventsData, GetSessionReplayEventsError, GetSessionReplayEventsErrors, GetSessionReplayEventsResponse, GetSessionReplayEventsResponses, GetSessionReplayResponse, GetSessionReplayResponse2, GetSessionReplayResponses, GetSettingsData, GetSettingsErrors, GetSettingsResponse, GetSettingsResponses, GetSkillData, GetSkillErrors, GetSkillResponse, GetSkillResponses, GetSlowQueriesData, GetSlowQueriesErrors, GetSlowQueriesResponse, GetSlowQueriesResponses, GetStaticBundleData, GetStaticBundleErrors, GetStaticBundleResponse, GetStaticBundleResponses, GetStatusOverviewData, GetStatusOverviewErrors, GetStatusOverviewResponse, GetStatusOverviewResponses, GetTagsByRepositoryIdData, GetTagsByRepositoryIdErrors, GetTagsByRepositoryIdResponse, GetTagsByRepositoryIdResponses, GetTeamData, GetTeamErrors, GetTeamResponse, GetTeamResponses, GetTimeBucketStatsData, GetTimeBucketStatsError, GetTimeBucketStatsErrors, GetTimeBucketStatsResponse, GetTimeBucketStatsResponses, GetTodayStatsData, GetTodayStatsError, GetTodayStatsErrors, GetTodayStatsResponse, GetTodayStatsResponses, GetTraceData, GetTraceError, GetTraceErrors, GetTraceResponse, GetTraceResponses, GetUnifiedTraceData, GetUnifiedTraceError, GetUnifiedTraceErrors, GetUnifiedTraceResponse, GetUnifiedTraceResponses, GetUniqueCountsData, GetUniqueCountsErrors, GetUniqueCountsResponse, GetUniqueCountsResponses, GetUniqueEventsData, GetUniqueEventsErrors, GetUniqueEventsQuery, GetUniqueEventsResponse, GetUniqueEventsResponses, GetUpdateStatusData, GetUpdateStatusErrors, GetUpdateStatusResponse, GetUpdateStatusResponses, GetUptimeHistoryData, GetUptimeHistoryErrors, GetUptimeHistoryResponse, GetUptimeHistoryResponses, GetUsageByProviderData, GetUsageByProviderError, GetUsageByProviderErrors, GetUsageByProviderResponse, GetUsageByProviderResponses, GetUsageRecentData, GetUsageRecentError, GetUsageRecentErrors, GetUsageRecentResponse, GetUsageRecentResponses, GetUsageSummaryData, GetUsageSummaryError, GetUsageSummaryErrors, GetUsageSummaryResponse, GetUsageSummaryResponses, GetUsageTimeseriesData, GetUsageTimeseriesError, GetUsageTimeseriesErrors, GetUsageTimeseriesResponse, GetUsageTimeseriesResponses, GetUsageTopModelsData, GetUsageTopModelsError, GetUsageTopModelsErrors, GetUsageTopModelsResponse, GetUsageTopModelsResponses, GetVisitorByGuidData, GetVisitorByGuidErrors, GetVisitorByGuidResponse, GetVisitorByGuidResponses, GetVisitorByIdData, GetVisitorByIdErrors, GetVisitorByIdResponse, GetVisitorByIdResponses, GetVisitorDetailsData, GetVisitorDetailsErrors, GetVisitorDetailsResponse, GetVisitorDetailsResponses, GetVisitorFacetsData, GetVisitorFacetsErrors, GetVisitorFacetsResponse, GetVisitorFacetsResponses, GetVisitorInfoData, GetVisitorInfoErrors, GetVisitorInfoResponse, GetVisitorInfoResponses, GetVisitorJourneyData, GetVisitorJourneyErrors, GetVisitorJourneyResponse, GetVisitorJourneyResponses, GetVisitorsData, GetVisitorsErrors, GetVisitorSessionsData, GetVisitorSessionsError, GetVisitorSessionsErrors, GetVisitorSessionsQuery, GetVisitorSessionsResponse, GetVisitorSessionsResponse2, GetVisitorSessionsResponses, GetVisitorsResponse, GetVisitorsResponses, GetVisitorStatsData, GetVisitorStatsErrors, GetVisitorStatsResponse, GetVisitorStatsResponses, GetWebhookData, GetWebhookErrors, GetWebhookResponse, GetWebhookResponses, GitPushEvent, GitRefResponse, GitSourcePlan, GlobalConversationResponse, GlobalEventStatsResponse, GlobalMrrResponse, GlobalRecentEventResponse, GlobalRevenueSummaryResponse, GrantProjectAccessData, GrantProjectAccessErrors, GrantProjectAccessResponse, GrantProjectAccessResponses, GroupedPageMetric, GroupedPageMetricsQuery, GroupedPageMetricsResponse, HandleGitProviderOauthCallbackData, HandleGitProviderOauthCallbackErrors, HasAnalyticsEventsData, HasAnalyticsEventsErrors, HasAnalyticsEventsResponse, HasAnalyticsEventsResponse2, HasAnalyticsEventsResponses, HasErrorGroupsData, HasErrorGroupsErrors, HasErrorGroupsResponse, HasErrorGroupsResponse2, HasErrorGroupsResponses, HasEventsQuery, HasEventsResponse, HasMetricsQuery, HasMetricsResponse, HasPerformanceMetricsData, HasPerformanceMetricsError, HasPerformanceMetricsErrors, HasPerformanceMetricsResponse, HasPerformanceMetricsResponses, HealthCheckConfiguration, HealthCheckEntryResponse, HealthResponse, HealthStatus, HealthSummary, HeartbeatApiRequest, HeartbeatResponse, HierarchyLevel, HistogramSummary, HostnameChange, HostnamePreviewResponse, HourlyPageSessions, HourlyVisitsQuery, HttpChallengeDebugResponse, ImportCredentials, ImportExecutionStatus, ImportExternalServiceData, ImportExternalServiceErrors, ImportExternalServiceRequest, ImportExternalServiceResponse, ImportExternalServiceResponses, ImportOutcomeResponse, ImportPlan, ImportRowErrorResponse, ImportSelector, ImportSource, ImportSourceCapabilities, ImportSourceInfo, ImportStatusResponse, IncidentBucket, IncidentBucketedResponse, IncidentResponse, IncidentUpdateResponse, IncrRequest, IncrResponse, IngestLogsByPathData, IngestLogsByPathError, IngestLogsByPathErrors, IngestLogsByPathResponses, IngestLogsData, IngestLogsError, IngestLogsErrors, IngestLogsResponses, IngestMetricsByPathData, IngestMetricsByPathError, IngestMetricsByPathErrors, IngestMetricsByPathResponses, IngestMetricsData, IngestMetricsError, IngestMetricsErrors, IngestMetricsResponses, IngestSentryEnvelopeData, IngestSentryEnvelopeErrors, IngestSentryEnvelopeResponses, IngestSentryEventData, IngestSentryEventErrors, IngestSentryEventResponse, IngestSentryEventResponses, IngestTracesByPathData, IngestTracesByPathError, IngestTracesByPathErrors, IngestTracesByPathResponses, IngestTracesData, IngestTracesError, IngestTracesErrors, IngestTracesResponses, InitAuthResponse, InitSessionReplayData, InitSessionReplayError, InitSessionReplayErrors, InitSessionReplayResponse, InitSessionReplayResponses, Insight, InsightSeverity, InsightsResponse, InsightStatus, InspectDropArchiveData, InspectDropArchiveErrors, InspectDropArchiveResponse, InspectDropArchiveResponses, IntegrationResponse, IpAccessControlQuery, IpAccessControlResponse, JobLogsData, JobLogsErrors, JobLogsResponses, JobStatusData, JobStatusErrors, JobStatusResponse, JobStatusResponse2, JobStatusResponses, JobSummaryResponse, JoinTokenStatusResponse, JourneyEvent, JourneySession, KeysRequest, KeysResponse, KillJobBody, KillJobData, KillJobErrors, KillJobResponse, KillJobResponses, KnownAiAgentsResponse, KvDelData, KvDelErrors, KvDelResponse, KvDelResponses, KvDisableData, KvDisableErrors, KvDisableResponse, KvDisableResponses, KvEnableData, KvEnableErrors, KvEnableResponse, KvEnableResponses, KvExpireData, KvExpireErrors, KvExpireResponse, KvExpireResponses, KvGetData, KvGetErrors, KvGetResponse, KvGetResponses, KvIncrData, KvIncrErrors, KvIncrResponse, KvIncrResponses, KvKeysData, KvKeysErrors, KvKeysResponse, KvKeysResponses, KvSetData, KvSetErrors, KvSetResponse, KvSetResponses, KvStatusData, KvStatusErrors, KvStatusResponse, KvStatusResponse2, KvStatusResponses, KvTtlData, KvTtlErrors, KvTtlResponse, KvTtlResponses, KvUpdateData, KvUpdateErrors, KvUpdateResponse, KvUpdateResponses, LatestRunForSourceData, LatestRunForSourceErrors, LatestRunForSourceResponse, LatestRunForSourceResponses, LemonSqueezyConfig, LetsEncryptSettings, LineContext, LinkCustomDomainToCertificateData, LinkCustomDomainToCertificateErrors, LinkCustomDomainToCertificateResponse, LinkCustomDomainToCertificateResponses, LinkServiceRequest, LinkServiceToProjectData, LinkServiceToProjectErrors, LinkServiceToProjectResponse, LinkServiceToProjectResponses, ListAgentRunsData, ListAgentRunsErrors, ListAgentRunsResponse, ListAgentRunsResponses, ListAgentsData, ListAgentsErrors, ListAgentsResponse, ListAgentsResponse2, ListAgentsResponses, ListAiProvidersData, ListAiProvidersErrors, ListAiProvidersResponse, ListAiProvidersResponses, ListAlertRulesData, ListAlertRulesErrors, ListAlertRulesResponse, ListAlertRulesResponses, ListAlertsData, ListAlertsError, ListAlertsErrors, ListAlertsResponse, ListAlertsResponses, ListAllConversationsData, ListAllConversationsErrors, ListAllConversationsResponse, ListAllConversationsResponses, ListAllRunsData, ListAllRunsErrors, ListAllRunsResponse, ListAllRunsResponses, ListApiKeysData, ListApiKeysErrors, ListApiKeysQuery, ListApiKeysResponse, ListApiKeysResponses, ListAuditLogsData, ListAuditLogsErrors, ListAuditLogsQuery, ListAuditLogsResponse, ListAuditLogsResponses, ListAvailableContainersData, ListAvailableContainersErrors, ListAvailableContainersResponse, ListAvailableContainersResponses, ListBackupAlertsData, ListBackupAlertsError, ListBackupAlertsErrors, ListBackupAlertsResponse, ListBackupAlertsResponses, ListBackupChildrenData, ListBackupChildrenError, ListBackupChildrenErrors, ListBackupChildrenResponse, ListBackupChildrenResponses, ListBackupSchedulesData, ListBackupSchedulesError, ListBackupSchedulesErrors, ListBackupSchedulesResponse, ListBackupSchedulesResponses, ListBackupsForScheduleData, ListBackupsForScheduleErrors, ListBackupsForScheduleResponse, ListBackupsForScheduleResponses, ListBlobsQuery, ListBlobsResponse, ListCommitsByRepositoryIdData, ListCommitsByRepositoryIdErrors, ListCommitsByRepositoryIdResponse, ListCommitsByRepositoryIdResponses, ListConnectionsData, ListConnectionsErrors, ListConnectionsResponse, ListConnectionsResponses, ListContainersAtPathData, ListContainersAtPathErrors, ListContainersAtPathResponse, ListContainersAtPathResponses, ListContainersData, ListContainersErrors, ListContainersResponse, ListContainersResponses, ListConversationsData, ListConversationsErrors, ListConversationsResponse, ListConversationsResponses, ListCustomDomainsForProjectData, ListCustomDomainsForProjectErrors, ListCustomDomainsForProjectResponse, ListCustomDomainsForProjectResponses, ListCustomDomainsResponse, ListDashboardsData, ListDashboardsError, ListDashboardsErrors, ListDashboardsResponse, ListDashboardsResponses, ListDeliveriesData, ListDeliveriesErrors, ListDeliveriesResponse, ListDeliveriesResponses, ListDeploymentContainerLogsData, ListDeploymentContainerLogsErrors, ListDeploymentContainerLogsResponse, ListDeploymentContainerLogsResponses, ListDeploymentTokensData, ListDeploymentTokensErrors, ListDeploymentTokensQuery, ListDeploymentTokensResponse, ListDeploymentTokensResponses, ListDnsProvidersData, ListDnsProvidersErrors, ListDnsProvidersResponse, ListDnsProvidersResponses, ListDomainsData, ListDomainsErrors, ListDomainsResponse, ListDomainsResponse2, ListDomainsResponses, ListDsnsData, ListDsnsErrors, ListDsnsResponse, ListDsnsResponses, ListEmailDomainsData, ListEmailDomainsErrors, ListEmailDomainsResponse, ListEmailDomainsResponses, ListEmailProvidersData, ListEmailProvidersErrors, ListEmailProvidersResponse, ListEmailProvidersResponses, ListEmailsData, ListEmailsErrors, ListEmailsResponse, ListEmailsResponses, ListEnrollmentTokensData, ListEnrollmentTokensErrors, ListEnrollmentTokensResponse, ListEnrollmentTokensResponses, ListEntitiesData, ListEntitiesErrors, ListEntitiesQuery, ListEntitiesResponse, ListEntitiesResponses, ListErrorEventsData, ListErrorEventsErrors, ListErrorEventsQuery, ListErrorEventsResponse, ListErrorEventsResponses, ListErrorGroupsData, ListErrorGroupsErrors, ListErrorGroupsQuery, ListErrorGroupsResponse, ListErrorGroupsResponses, ListEventsData, ListEventsResponse, ListEventsResponses, ListEventTypesData, ListEventTypesResponse, ListEventTypesResponses, ListExternalImagesData, ListExternalImagesErrors, ListExternalImagesResponse, ListExternalImagesResponses, ListExternalPluginsData, ListExternalPluginsErrors, ListExternalPluginsResponse, ListExternalPluginsResponses, ListExternalServiceBackupsData, ListExternalServiceBackupsError, ListExternalServiceBackupsErrors, ListExternalServiceBackupsResponse, ListExternalServiceBackupsResponses, ListFlagsData, ListFlagsErrors, ListFlagsResponse, ListFlagsResponses, ListFunnelsData, ListFunnelsErrors, ListFunnelsResponse, ListFunnelsResponses, ListGitProvidersData, ListGitProvidersErrors, ListGitProvidersResponse, ListGitProvidersResponses, ListGlobalMcpsData, ListGlobalMcpsErrors, ListGlobalMcpsResponse, ListGlobalMcpsResponses, ListGlobalSkillsData, ListGlobalSkillsErrors, ListGlobalSkillsResponse, ListGlobalSkillsResponses, ListIncidentsData, ListIncidentsErrors, ListIncidentsResponses, ListInsightsData, ListInsightsError, ListInsightsErrors, ListInsightsResponse, ListInsightsResponses, ListIpAccessControlData, ListIpAccessControlError, ListIpAccessControlErrors, ListIpAccessControlResponse, ListIpAccessControlResponses, ListJobsData, ListJobsErrors, ListJobsResponse, ListJobsResponse2, ListJobsResponses, ListKnownAiAgentsData, ListKnownAiAgentsError, ListKnownAiAgentsErrors, ListKnownAiAgentsResponse, ListKnownAiAgentsResponses, ListManagedDomainsData, ListManagedDomainsErrors, ListManagedDomainsResponse, ListManagedDomainsResponses, ListMcpsData, ListMcpsErrors, ListMcpsResponse, ListMcpsResponse2, ListMcpsResponses, ListMetricLabelKeysData, ListMetricLabelKeysError, ListMetricLabelKeysErrors, ListMetricLabelKeysResponse, ListMetricLabelKeysResponses, ListMetricLabelValuesData, ListMetricLabelValuesError, ListMetricLabelValuesErrors, ListMetricLabelValuesResponse, ListMetricLabelValuesResponses, ListMetricNamesData, ListMetricNamesError, ListMetricNamesErrors, ListMetricNamesResponse, ListMetricNamesResponses, ListModelsData, ListModelsError, ListModelsErrors, ListModelsResponse, ListModelsResponses, ListMonitorsData, ListMonitorsErrors, ListMonitorsResponse, ListMonitorsResponses, ListNotificationProvidersData, ListNotificationProvidersErrors, ListNotificationProvidersResponse, ListNotificationProvidersResponses, ListOidcProvidersData, ListOidcProvidersResponse, ListOidcProvidersResponses, ListOidcProviderUsersData, ListOidcProviderUsersErrors, ListOidcProviderUsersResponse, ListOidcProviderUsersResponses, ListOidcRoleMappingsData, ListOidcRoleMappingsResponse, ListOidcRoleMappingsResponses, ListOnDemandCertsData, ListOnDemandCertsErrors, ListOnDemandCertsResponse, ListOnDemandCertsResponse2, ListOnDemandCertsResponses, ListOrdersData, ListOrdersErrors, ListOrdersResponse, ListOrdersResponse2, ListOrdersResponses, ListPeersData, ListPeersErrors, ListPeersResponse, ListPeersResponses, ListPendingActionsData, ListPendingActionsErrors, ListPendingActionsResponse, ListPendingActionsResponses, ListPgUpgradesData, ListPgUpgradesErrors, ListPgUpgradesResponse, ListPgUpgradesResponses, ListPresetsData, ListPresetsErrors, ListPresetsResponse, ListPresetsResponse2, ListPresetsResponses, ListProjectAccessData, ListProjectAccessErrors, ListProjectAccessResponse, ListProjectAccessResponses, ListProjectAlarmsData, ListProjectAlarmsErrors, ListProjectAlarmsResponse, ListProjectAlarmsResponses, ListProjectScansData, ListProjectScansError, ListProjectScansErrors, ListProjectScansResponse, ListProjectScansResponses, ListProjectSecretsData, ListProjectSecretsErrors, ListProjectSecretsResponse, ListProjectSecretsResponses, ListProjectServicesData, ListProjectServicesErrors, ListProjectServicesResponse, ListProjectServicesResponses, ListProjectTemplatesData, ListProjectTemplatesErrors, ListProjectTemplatesResponse, ListProjectTemplatesResponses, ListProjectTemplateTagsData, ListProjectTemplateTagsErrors, ListProjectTemplateTagsResponse, ListProjectTemplateTagsResponses, ListProviderKeysData, ListProviderKeysError, ListProviderKeysErrors, ListProviderKeysResponse, ListProviderKeysResponses, ListProviderZonesData, ListProviderZonesErrors, ListProviderZonesResponse, ListProviderZonesResponses, ListPublicProvidersData, ListPublicProvidersResponse, ListPublicProvidersResponses, ListReleaseFilesData, ListReleaseFilesErrors, ListReleaseFilesResponse, ListReleaseFilesResponses, ListReleasesData, ListReleasesErrors, ListReleasesResponse, ListReleasesResponses, ListRemoteExternalImagesData, ListRemoteExternalImagesErrors, ListRemoteExternalImagesResponse, ListRemoteExternalImagesResponses, ListRepositoriesByConnectionData, ListRepositoriesByConnectionErrors, ListRepositoriesByConnectionResponse, ListRepositoriesByConnectionResponses, ListRepositoriesByProviderData, ListRepositoriesByProviderErrors, ListRepositoriesByProviderResponse, ListRepositoriesByProviderResponses, ListRestoreRunsForServiceData, ListRestoreRunsForServiceResponse, ListRestoreRunsForServiceResponses, ListRootContainersData, ListRootContainersErrors, ListRootContainersResponse, ListRootContainersResponses, ListRoutesData, ListRoutesErrors, ListRoutesResponse, ListRoutesResponses, ListRunsResponse, ListS3SourcesData, ListS3SourcesError, ListS3SourcesErrors, ListS3SourcesResponse, ListS3SourcesResponses, ListSandboxesData, ListSandboxesResponse, ListSandboxesResponse2, ListSandboxesResponses, ListScansQuery, ListScheduleRunJobsData, ListScheduleRunJobsError, ListScheduleRunJobsErrors, ListScheduleRunJobsResponse, ListScheduleRunJobsResponses, ListScheduleRunsData, ListScheduleRunsError, ListScheduleRunsErrors, ListScheduleRunsResponse, ListScheduleRunsResponses, ListScheduleServicesData, ListScheduleServicesError, ListScheduleServicesErrors, ListScheduleServicesResponse, ListScheduleServicesResponses, ListSecretsData, ListSecretsErrors, ListSecretsResponse, ListSecretsResponse2, ListSecretsResponses, ListServiceHealthStatusesData, ListServiceHealthStatusesErrors, ListServiceHealthStatusesResponse, ListServiceHealthStatusesResponses, ListServiceProjectsData, ListServiceProjectsErrors, ListServiceProjectsResponse, ListServiceProjectsResponses, ListServiceSchedulesData, ListServiceSchedulesError, ListServiceSchedulesErrors, ListServiceSchedulesResponse, ListServiceSchedulesResponses, ListServicesData, ListServicesErrors, ListServicesResponse, ListServicesResponses, ListSkillsData, ListSkillsErrors, ListSkillsResponse, ListSkillsResponse2, ListSkillsResponses, ListSourceBackupsData, ListSourceBackupsError, ListSourceBackupsErrors, ListSourceBackupsResponse, ListSourceBackupsResponses, ListSourceFilesData, ListSourceFilesErrors, ListSourceFilesResponse, ListSourceFilesResponses, ListSourceMapsData, ListSourceMapsErrors, ListSourceMapsResponse, ListSourceMapsResponses, ListSourcesData, ListSourcesErrors, ListSourcesResponse, ListSourcesResponses, ListStaticBundlesData, ListStaticBundlesErrors, ListStaticBundlesResponse, ListStaticBundlesResponses, ListSyncedRepositoriesData, ListSyncedRepositoriesErrors, ListSyncedRepositoriesResponse, ListSyncedRepositoriesResponses, ListTagsResponse, ListTeamMembersData, ListTeamMembersErrors, ListTeamMembersResponse, ListTeamMembersResponses, ListTeamProjectsData, ListTeamProjectsErrors, ListTeamProjectsResponse, ListTeamProjectsResponses, ListTeamsData, ListTeamsErrors, ListTeamsResponse, ListTeamsResponses, ListTemplatesQuery, ListTemplatesResponse, ListUsersData, ListUsersErrors, ListUsersResponse, ListUsersResponses, ListVulnerabilitiesQuery, ListWebhooksData, ListWebhooksErrors, ListWebhooksResponse, ListWebhooksResponses, LiveVisitorInfo, LiveVisitorsListResponse, LocationCount, LocationGranularity, LocationInfo, LoginData, LoginErrors, LoginRequest, LoginResponse, LoginResponses, LogLevel, LogoutData, LogoutErrors, LogoutResponses, LogRecord, LogSearchLine, LogSeverity, LogSource, LogsQuery, LogsResponse, LogStream, LookupDnsARecordsData, LookupDnsARecordsError, LookupDnsARecordsErrors, LookupDnsARecordsResponse, LookupDnsARecordsResponses, ManagedDomainResponse, ManualAction, ManualActionTiming, McpDefinitionResponse, MessageContent, MessagePart, MessageResponse, MeteredMode, MetricAggregation, MetricBucket, MetricDataPoint, MetricsOverTimeResponse, MetricsQuery, MetricsRangeQuery, MetricsStatusResponse, MetricsStoreKind, MetricsSummaryResponse, MetricType, MfaRequiredResponse, MfaSetupResponse, MfaVerificationRequest, MigrationStep, MigrationSummary, MintEnrollmentTokenData, MintEnrollmentTokenErrors, MintEnrollmentTokenRequest, MintEnrollmentTokenResponse, MintEnrollmentTokenResponse2, MintEnrollmentTokenResponses, MiscResult, MkdirBody, MkdirData, MkdirErrors, MkdirResponse, MkdirResponses, ModelInfo, ModelListResponse, ModelPricing, ModelUsage, MonitoringSettings, MonitoringSettingsMasked, MonitorResponse, MonitorStatus, MrrBucketResponse, MultiNodeSettings, MultiNodeSettingsMasked, MxResult, NavEntry, NavSection, NetworkConfiguration, NetworkMode, NixpacksPresetConfig, NixpacksProvider, NodeContainerListResponse, NodeContainerResponse, NodeCostInfo, NodeHeartbeatData, NodeHeartbeatErrors, NodeHeartbeatResponse, NodeHeartbeatResponses, NodeInfoResponse, NodeListResponse, NodeMetricsGetRangeData, NodeMetricsGetRangeErrors, NodeMetricsGetRangeResponse, NodeMetricsGetRangeResponses, NotificationPreferencesResponse, NotificationProviderResponse, ObservabilityCompressionSettings, ObservabilityEvent, ObservabilityFullEventData, ObservabilityFullEventError, ObservabilityFullEventErrors, ObservabilityFullEventResponse, ObservabilityFullEventResponses, ObservabilityListEventsData, ObservabilityListEventsError, ObservabilityListEventsErrors, ObservabilityListEventsResponse, ObservabilityListEventsResponses, ObservabilityRetentionSettings, OidcCallbackData, OidcProviderResponse, OidcProvidersListResponse, OidcProviderSummary, OidcProviderUserResponse, OidcRoleMappingResponse, OidcTestConnectionResponse, OnDemandCertAttemptResponse, OnDemandCertRow, OnDemandTlsSettings, OpenAiError, OpenAiErrorResponse, OperatingSystemCount, OperationResultResponse, OperationResultsResponse, OtelDashboardResponse, OtelDashboardsResponse, OtelMetricAlertRuleResponse, OtelMetricAlertsResponse, OtelMetricLabelKeysResponse, OtelMetricLabelValuesResponse, OtelMetricNamesResponse, OtelMetricsResponse, OutlierAlgorithm, OutlierParams, OverprovisioningAssessment, OverprovisioningVerdict, PageActivityBucket, PageCountryStats, PageFlowEntry, PageFlowQuery, PageFlowResponse, PageHourlySessionsQuery, PageHourlySessionsResponse, PagePathDetailQuery, PagePathDetailResponse, PagePathInfo, PagePathSparkline, PagePathSparklinePoint, PagePathsQuery, PagePathsResponse, PagePathsSparklineQuery, PagePathsSparklineResponse, PagePathVisitorsQuery, PagePathVisitorsResponse, PageReferrerStats, PagesComparisonResponse, PageSessionComparison, PageSessionStats, PageSessionStatsQuery, PageTransition, PageVisit, PageVisitorSession, PaginatedEmailsResponse, PaginatedEntitiesResponse, PaginatedErrorEventsResponse, PaginatedErrorGroupsResponse, PaginatedEventsResponse, PaginatedExternalImagesResponse, PaginatedProjectList, PaginatedStaticBundlesResponse, Pagination, PaginationMeta, PaginationParams, PasswordProtectionConfig, PatchAdminGateData, PatchAdminGateErrors, PatchAdminGateResponse, PatchAdminGateResponses, PatchPreviewGatewaySettingsData, PatchPreviewGatewaySettingsResponse, PatchPreviewGatewaySettingsResponses, PatchSettingsRequest, PathVisitors, PathVisitorsAnalyticsQuery, PathVisitorsResponse, PauseDeploymentData, PauseDeploymentErrors, PauseDeploymentResponse, PauseDeploymentResponses, PauseSandboxData, PauseSandboxErrors, PauseSandboxResponse, PauseSandboxResponses, PeerEntry, PeerListResponse, PendingActionResponse, PerformanceMetricsQuery, PerformanceMetricsResponse, PermissionInfo, PgUpgradeLogResponse, PgUpgradeResponse, PipelineStats, PipelineStatsResponse, PlanComplexity, PlanMetadata, PlanRestoreData, PlanRestoreError, PlanRestoreErrors, PlanRestoreResponse, PlanRestoreResponses, PlanSourceBackup, PlanTarget, PlatformInfo, PluginManifest, PortMapping, PostDnsAckData, PostDnsAckErrors, PostDnsAckResponse, PostDnsAckResponses, PostgresWalHealth, PresetConfigSchema, PresetInfo, PresetResponse, PreviewAlertData, PreviewAlertError, PreviewAlertErrors, PreviewAlertResponse, PreviewAlertResponses, PreviewFunnelMetricsData, PreviewFunnelMetricsErrors, PreviewFunnelMetricsResponse, PreviewFunnelMetricsResponses, PreviewGatewaySettings, PreviewGatewaySettingsMasked, PreviewGatewaySettingsResponse, PreviewHostnameModeData, PreviewHostnameModeErrors, PreviewHostnameModeResponse, PreviewHostnameModeResponses, PreviewShareLinkBody, PreviewShareLinkResponse, PricingResponse, ProblemDetails, ProjectAccessResponse, ProjectConfiguration, ProjectDashboardAnalytics, ProjectDsnResponse, ProjectHealthSummary, ProjectInfo, ProjectMonitorHealth, ProjectPresetResponse, ProjectQuery, ProjectRef, ProjectResponse, ProjectSecretEnvironmentInfo, ProjectSecretResponse, ProjectServiceInfo, ProjectsHealthResponse, ProjectsMonitorHealthResponse, ProjectStatisticsResponse, ProjectStatsBreakdown, ProjectType, ProjectUsageInfoResponse, PromoteClusterMemberData, PromoteClusterMemberErrors, PromoteClusterMemberResponses, PromoteDeploymentData, PromoteDeploymentErrors, PromoteDeploymentRequest, PromoteDeploymentResponse, PromoteDeploymentResponses, PropertyBreakdownItem, PropertyBreakdownQuery, PropertyBreakdownResponse, PropertyColumn, PropertyTimelineItem, PropertyTimelineQuery, PropertyTimelineResponse, Protocol, ProviderCatalogDto, ProviderCatalogResponse, ProviderConfig, ProviderConfigMasked, ProviderDeletionCheckResponse, ProviderDescriptor, ProviderKeyResponse, ProviderMetadata, ProviderResponse, ProviderUsage, ProvisionDomainData, ProvisionDomainErrors, ProvisionDomainResponse, ProvisionDomainResponses, ProvisionResponse, ProxyLogResponse, ProxyLogsPaginatedResponse, PublicHostnameStrategy, PublicPresetResponse, PublicRepositoryInfo, PurgeLogsRequest, PurgeProjectLogsData, PurgeProjectLogsError, PurgeProjectLogsErrors, PurgeProjectLogsResponses, PushedExternalImageResponse, PushExternalImageData, PushExternalImageErrors, PushExternalImageResponse, PushExternalImageResponses, PushImageRequest, QueryDataData, QueryDataErrors, QueryDataRequest, QueryDataResponse, QueryDataResponse2, QueryDataResponses, QueryGenaiTracesData, QueryGenaiTracesError, QueryGenaiTracesErrors, QueryGenaiTracesResponse, QueryGenaiTracesResponses, QueryLogsData, QueryLogsError, QueryLogsErrors, QueryLogsResponse, QueryLogsResponses, QueryMetricsData, QueryMetricsError, QueryMetricsErrors, QueryMetricsResponse, QueryMetricsResponses, QueryTracesData, QueryTracesError, QueryTracesErrors, QueryTracesResponse, QueryTracesResponses, QueryTraceSummariesData, QueryTraceSummariesError, QueryTraceSummariesErrors, QueryTraceSummariesResponse, QueryTraceSummariesResponses, QuotaResponse, RateLimitConfig, RateLimitSettings, ReachabilityStatus, ReadFileData, ReadFileErrors, ReadFileResponse, ReadFileResponse2, ReadFileResponses, ReAnalyzeData, ReAnalyzeErrors, ReAnalyzeResponses, RebuildSandboxImageData, RebuildSandboxImageErrors, RebuildSandboxImageResponses, RecentActivityQuery, RecentActivityResponse, RecentEventResponse, RecentQueryParams, RecordConsoleEventData, RecordConsoleEventErrors, RecordConsoleEventResponses, RecordEventMetricsData, RecordEventMetricsErrors, RecordEventMetricsResponse, RecordEventMetricsResponses, RecordExposureRequest, RecordExposureResponse, RecordFlagExposureData, RecordFlagExposureErrors, RecordFlagExposureResponse, RecordFlagExposureResponses, RecordListResponse, RecordSpeedMetricsData, RecordSpeedMetricsError, RecordSpeedMetricsErrors, RecordSpeedMetricsResponse, RecordSpeedMetricsResponses, RecoveryTarget, ReferrerCount, ReferrersAnalyticsQuery, RefreshRouteTableData, RefreshRouteTableErrors, RefreshRouteTableResponse, RefreshRouteTableResponses, RegenerateDsnData, RegenerateDsnErrors, RegenerateDsnRequest, RegenerateDsnResponse, RegenerateDsnResponses, RegisterExternalImageData, RegisterExternalImageErrors, RegisterExternalImageResponse, RegisterExternalImageResponses, RegisterImageRequest, RegisterNodeApiRequest, RegisterNodeData, RegisterNodeErrors, RegisterNodeResponse, RegisterNodeResponse2, RegisterNodeResponses, RegisterRequest, ReinstallGitlabWebhookData, ReinstallGitlabWebhookErrors, ReinstallGitlabWebhookResponse, ReinstallGitlabWebhookResponses, ReinstallWebhookResponse, RejectPendingActionData, RejectPendingActionErrors, RejectPendingActionResponse, RejectPendingActionResponses, ReleaseListResponse, ReloadPluginsData, ReloadPluginsErrors, ReloadPluginsResponse, ReloadPluginsResponses, ReloadResponse, RemoteDeploymentResponse, RemoveClusterMemberData, RemoveClusterMemberErrors, RemoveClusterMemberResponse, RemoveClusterMemberResponses, RemoveManagedDomainData, RemoveManagedDomainErrors, RemoveManagedDomainResponse, RemoveManagedDomainResponses, RemoveNodeResponse, RemoveRoleData, RemoveRoleErrors, RemoveRoleResponse, RemoveRoleResponses, RemoveTeamMemberData, RemoveTeamMemberErrors, RemoveTeamMemberResponse, RemoveTeamMemberResponses, RenameConversationData, RenameConversationErrors, RenameConversationRequest, RenameConversationResponse, RenameConversationResponses, RenewDomainData, RenewDomainErrors, RenewDomainResponse, RenewDomainResponses, RepositoryListQuery, RepositoryListResponse, RepositoryPresetResponse, RepositoryResponse, RepositorySyncStartedResponse, RequestPasswordResetData, RequestPasswordResetErrors, RequestPasswordResetResponse, RequestPasswordResetResponses, RequestRow, ResetPasswordData, ResetPasswordErrors, ResetPasswordRequest, ResetPasswordResponse, ResetPasswordResponses, ResetPgStatStatementsRequest, ResetPgStatStatementsResponse, ResizeSandboxBody, ResizeSandboxData, ResizeSandboxErrors, ResizeSandboxResponse, ResizeSandboxResponses, ResolveAlarmData, ResolveAlarmErrors, ResolveAlarmResponses, ResolvedEnvVarResponse, ResolvedEnvVarSource, ResourceCounts, ResourceFootprint, ResourceInfo, ResourceLimitApplyResult, ResourceLimits, ResourceLimitsResponse, ResourceLimitsUpdateResponse, ResourcesBody, RestartContainerData, RestartContainerErrors, RestartContainerResponse, RestartContainerResponses, RestartPreviewGatewayData, RestartPreviewGatewayResponse, RestartPreviewGatewayResponses, RestartSandboxData, RestartSandboxErrors, RestartSandboxResponse, RestartSandboxResponses, RestoreCapabilities, RestoreCapabilitiesResponse, RestoreFlagData, RestoreFlagErrors, RestoreFlagResponse, RestoreFlagResponses, RestorePlan, RestoreRequestMode, RestoreRunView, RestoreUserData, RestoreUserErrors, RestoreUserResponse, RestoreUserResponses, ResumeDeploymentData, ResumeDeploymentErrors, ResumeDeploymentResponse, ResumeDeploymentResponses, ResumeSandboxData, ResumeSandboxErrors, ResumeSandboxResponse, ResumeSandboxResponses, RetentionCleanupFailure, RetentionCleanupReport, RetryClusterData, RetryClusterErrors, RetryClusterRequest, RetryClusterResponse, RetryClusterResponses, RetryDeliveryData, RetryDeliveryErrors, RetryDeliveryResponse, RetryDeliveryResponses, RetryPgUpgradeData, RetryPgUpgradeErrors, RetryPgUpgradeResponse, RetryPgUpgradeResponses, RetryRunData, RetryRunErrors, RetryRunResponse, RetryRunResponses, RevealGlobalMcpConfigData, RevealGlobalMcpConfigErrors, RevealGlobalMcpConfigResponse, RevealGlobalMcpConfigResponses, RevealMcpConfigData, RevealMcpConfigErrors, RevealMcpConfigResponse, RevealMcpConfigResponses, RevealNotificationProviderConfigData, RevealNotificationProviderConfigErrors, RevealNotificationProviderConfigResponse, RevealNotificationProviderConfigResponses, RevealServiceParameterData, RevealServiceParameterErrors, RevealServiceParameterResponse, RevealServiceParameterResponses, RevenueCreateIntegrationData, RevenueCreateIntegrationErrors, RevenueCreateIntegrationResponse, RevenueCreateIntegrationResponses, RevenueDeleteIntegrationData, RevenueDeleteIntegrationResponse, RevenueDeleteIntegrationResponses, RevenueGlobalEventsData, RevenueGlobalEventsResponse, RevenueGlobalEventsResponses, RevenueImportInvoicesCsvData, RevenueImportInvoicesCsvErrors, RevenueImportInvoicesCsvResponse, RevenueImportInvoicesCsvResponses, RevenueImportSubscriptionsCsvData, RevenueImportSubscriptionsCsvErrors, RevenueImportSubscriptionsCsvResponse, RevenueImportSubscriptionsCsvResponses, RevenueListIntegrationsData, RevenueListIntegrationsResponse, RevenueListIntegrationsResponses, RevenueListProvidersData, RevenueListProvidersResponse, RevenueListProvidersResponses, RevenueMetricsCustomersData, RevenueMetricsCustomersResponse, RevenueMetricsCustomersResponses, RevenueMetricsGlobalMrrData, RevenueMetricsGlobalMrrResponse, RevenueMetricsGlobalMrrResponses, RevenueMetricsGlobalSummaryData, RevenueMetricsGlobalSummaryResponse, RevenueMetricsGlobalSummaryResponses, RevenueMetricsMrrData, RevenueMetricsMrrResponse, RevenueMetricsMrrResponses, RevenueMetricsSummaryData, RevenueMetricsSummaryResponse, RevenueMetricsSummaryResponses, RevenueRecentEventsData, RevenueRecentEventsResponse, RevenueRecentEventsResponses, RevenueRotateTokenData, RevenueRotateTokenResponse, RevenueRotateTokenResponses, RevenueRow, RevenueUpdateConfigData, RevenueUpdateConfigErrors, RevenueUpdateConfigResponse, RevenueUpdateConfigResponses, RevenueUpdateSecretData, RevenueUpdateSecretErrors, RevenueUpdateSecretResponse, RevenueUpdateSecretResponses, RevokeDsnData, RevokeDsnErrors, RevokeDsnResponse, RevokeDsnResponses, RevokeEnrollmentTokenData, RevokeEnrollmentTokenErrors, RevokeEnrollmentTokenResponse, RevokeEnrollmentTokenResponses, RevokeJoinTokenData, RevokeJoinTokenErrors, RevokeJoinTokenResponse, RevokeJoinTokenResponses, RevokeProjectAccessData, RevokeProjectAccessErrors, RevokeProjectAccessResponse, RevokeProjectAccessResponses, RiskLevel, RoleInfo, RollbackPgUpgradeData, RollbackPgUpgradeErrors, RollbackPgUpgradeResponse, RollbackPgUpgradeResponses, RollbackToDeploymentData, RollbackToDeploymentErrors, RollbackToDeploymentResponse, RollbackToDeploymentResponses, RootfsCacheEntry, RootfsGcData, RootfsGcReport, RootfsGcResponses, RootfsReport, RootfsReportData, RootfsReportResponses, RootfsVmEntry, RotateApiKeyData, RotateApiKeyErrors, RotateApiKeyResponse, RotateApiKeyResponses, RotateDeploymentTokenData, RotateDeploymentTokenErrors, RotateDeploymentTokenResponse, RotateDeploymentTokenResponses, RouteRefreshResponse, RouteResponse, RouteRole, RouteUser, RouteUserWithRoles, RunBackupForSourceData, RunBackupForSourceError, RunBackupForSourceErrors, RunBackupForSourceResponse, RunBackupForSourceResponses, RunBackupRequest, RunConnectionHealthCheckData, RunConnectionHealthCheckErrors, RunConnectionHealthCheckResponse, RunConnectionHealthCheckResponses, RunExternalServiceBackupData, RunExternalServiceBackupError, RunExternalServiceBackupErrors, RunExternalServiceBackupRequest, RunExternalServiceBackupResponse, RunExternalServiceBackupResponses, RunScheduleNowData, RunScheduleNowError, RunScheduleNowErrors, RunScheduleNowResponse, RunScheduleNowResponses, S3ConnectionTestResponse, S3CredentialsResponse, S3SourceResponse, S3SourceResponseWritable, SandboxCreatePreviewLinkData, SandboxCreatePreviewLinkErrors, SandboxCreatePreviewLinkResponse, SandboxCreatePreviewLinkResponses, SandboxDomainResponse, SandboxEvent, SandboxEventsResponse, SandboxInner, SandboxResponse, SandboxRoute, SandboxStatusResponse, SaveAgentTokenData, SaveAgentTokenErrors, SaveAgentTokenRequest, SaveAgentTokenResponse, SaveAgentTokenResponse2, SaveAgentTokenResponses, SaveAiProviderCredentialData, SaveAiProviderCredentialErrors, SaveAiProviderCredentialResponse, SaveAiProviderCredentialResponses, SaveCredentialRequest, SaveCredentialResponse, ScalewayCredentialsRequest, ScanResponse, ScheduleRunEntry, ScheduleRunJobEntry, ScheduleRunListResponse, ScheduleRunResponse, ScheduleRunSummary, ScheduleRunSummaryList, ScreenshotSettings, SearchLogsData, SearchLogsError, SearchLogsErrors, SearchLogsRequest, SearchLogsResponse, SearchLogsResponse2, SearchLogsResponses, SearchMode, Seasonality, SecretResponse, SecurityConfig, SecurityHeadersConfig, SecurityHeadersSettings, SendEmailData, SendEmailErrors, SendEmailRequestBody, SendEmailResponse, SendEmailResponseBody, SendEmailResponses, SendMessageData, SendMessageErrors, SendMessageRequest, SendMessageResponses, SensitiveConfigValueResponse, SensitiveMcpConfigValueResponse, SensitiveValueResponse, SentryChunkUploadResponse, SentryCreateReleaseRequest, SentryEventRequest, SentryEventResponse, SentryReleaseFileResponse, SentryReleaseProjectRef, SentryReleaseResponse, SeriesStateEntry, ServiceAccessInfo, ServiceAction, ServiceAlertRuleResponse, ServiceBackupEntryResponse, ServiceBackupListResponse, ServiceCreateAlertRuleRequest, ServiceHealthResponse, ServiceHealthStatusBatchResponse, ServiceHealthStatusEntryResponse, ServiceMemberInfo, ServiceParameter, ServicePlan, ServiceResourceLimits, ServiceRuntimeReport, ServiceStatsReport, ServiceTypeInfo, ServiceTypeRoute, ServiceUpdateAlertRuleRequest, SesCredentialsRequest, SessionDetails, SessionDetailsQuery, SessionEvent, SessionEventDto, SessionEventsQuery, SessionEventsResponse, SessionLogsQuery, SessionLogsResponse, SessionReplayEventsRequest, SessionReplayInfoDto, SessionReplayInitRequest, SessionReplayInitResponse, SessionReplayWithEventsDto, SessionReplayWithVisitorDto, SessionRequestLog, SessionSummary, SetDefaultS3SourceData, SetDefaultS3SourceError, SetDefaultS3SourceErrors, SetDefaultS3SourceResponse, SetDefaultS3SourceResponses, SetFlagEnvironmentData, SetFlagEnvironmentErrors, SetFlagEnvironmentRequest, SetFlagEnvironmentResponse, SetFlagEnvironmentResponses, SetPreviewPasswordBody, SetPreviewPasswordData, SetPreviewPasswordErrors, SetPreviewPasswordResponse, SetPreviewPasswordResponse2, SetPreviewPasswordResponses, SetRequest, SetResponse, SettingsUpdateResponse, SetupDnsChallengeData, SetupDnsChallengeErrors, SetupDnsChallengeRequest, SetupDnsChallengeResponse, SetupDnsChallengeResponse2, SetupDnsChallengeResponses, SetupDnsData, SetupDnsErrors, SetupDnsRequest, SetupDnsResponse, SetupDnsResponse2, SetupDnsResponses, SetupEmailTrackingData, SetupEmailTrackingErrors, SetupEmailTrackingResponse, SetupEmailTrackingResponses, SetupMfaData, SetupMfaErrors, SetupMfaResponse, SetupMfaResponses, SiblingRef, SkillDefinitionResponse, SlackConfig, SleepEnvironmentData, SleepEnvironmentErrors, SleepEnvironmentResponse, SleepEnvironmentResponses, SlowQueriesResponse, SlowQueryRow, SmartFilter, SmokeTestAgentData, SmokeTestAgentErrors, SmokeTestAgentResponse, SmokeTestAgentResponses, SmokeTestResponse, SmtpCredentialsRequest, SmtpEncryptionRoute, SmtpResult, SourceArchiveUpload, SourceBackupEntry, SourceBackupIndexResponse, SourceBody, SourceFileListResponse, SourceFileResponse, SourceMapListResponse, SourceMapResponse, SourceSandboxData, SourceSandboxErrors, SourceSandboxResponse, SourceSandboxResponses, SourceType, SpanEvent, SpanKind, SpanRecord, SpanRow, SpanStatusCode, SpeedMetricsPayload, SpeedSegmentFilters, StaleSlot, StartAnalysisData, StartAnalysisErrors, StartAnalysisRequest, StartAnalysisResponse, StartAnalysisResponses, StartContainerData, StartContainerErrors, StartContainerResponse, StartContainerResponses, StartFixData, StartFixErrors, StartFixResponses, StartGitProviderOauthData, StartGitProviderOauthErrors, StartOidcLoginBySlugData, StartOidcLoginBySlugErrors, StartPgUpgradeData, StartPgUpgradeErrors, StartPgUpgradeRequest, StartPgUpgradeResponse, StartPgUpgradeResponses, StartRestoreData, StartRestoreError, StartRestoreErrors, StartRestoreRequest, StartRestoreResponse, StartRestoreResponses, StartServiceData, StartServiceErrors, StartServiceResponse, StartServiceResponses, StaticBundleResponse, StaticParams, StaticPresetConfig, StatPathData, StatPathErrors, StatPathResponse, StatPathResponses, StatResponse, StatsFilters, StatusBucket, StatusBucketedResponse, StatusCodeCount, StatusCodesQuery, StatusPageOverview, StepConversionResponse, StepResourceType, StepResult, StepUpResponse, StopContainerData, StopContainerErrors, StopContainerResponse, StopContainerResponses, StopSandboxData, StopSandboxErrors, StopSandboxResponse, StopSandboxResponses, StopSequence, StopServiceData, StopServiceErrors, StopServiceResponse, StopServiceResponses, StorageQuota, StreamContainerMetricsData, StreamContainerMetricsErrors, StreamContainerMetricsResponses, StreamEventsData, StreamEventsErrors, StreamEventsResponses, StreamRunEventsData, StreamRunEventsErrors, StreamRunEventsResponses, StripeConfig, SyncedRepositoryListQuery, SyncRepositoriesData, SyncRepositoriesErrors, SyncRepositoriesResponse, SyncRepositoriesResponses, SyntaxResult, TagInfo, TagListResponse, TailDeploymentJobLogsData, TailDeploymentJobLogsErrors, TailLogsData, TailLogsError, TailLogsErrors, TailLogsRequest, TailLogsResponses, TargetRecommendation, TeamListResponse, TeamMemberResponse, TeamResponse, TeamRole, TeardownDeploymentData, TeardownDeploymentErrors, TeardownDeploymentResponse, TeardownDeploymentResponses, TeardownEnvironmentData, TeardownEnvironmentErrors, TeardownEnvironmentResponse, TeardownEnvironmentResponses, TemplateResponse, TestEmailRequest, TestEmailResponse, TestNotificationProviderData, TestNotificationProviderErrors, TestNotificationProviderResponse, TestNotificationProviderResponses, TestOidcProviderData, TestOidcProviderResponse, TestOidcProviderResponses, TestProviderConnectionData, TestProviderConnectionErrors, TestProviderConnectionResponse, TestProviderConnectionResponses, TestProviderData, TestProviderErrors, TestProviderKeyByIdData, TestProviderKeyByIdError, TestProviderKeyByIdErrors, TestProviderKeyByIdResponse, TestProviderKeyByIdResponses, TestProviderKeyInlineData, TestProviderKeyInlineError, TestProviderKeyInlineErrors, TestProviderKeyInlineResponse, TestProviderKeyInlineResponses, TestProviderKeyRequest, TestProviderKeyResponse, TestProviderResponse, TestProviderResponse2, TestProviderResponses, TestS3ConnectionPreviewData, TestS3ConnectionPreviewError, TestS3ConnectionPreviewErrors, TestS3ConnectionPreviewResponse, TestS3ConnectionPreviewResponses, TestS3SourceConnectionData, TestS3SourceConnectionError, TestS3SourceConnectionErrors, TestS3SourceConnectionResponse, TestS3SourceConnectionResponses, TimeBucketStats, TimeBucketStatsResponse, TimeseriesBucket, TimeseriesQueryParams, TlsMode, TodayStatsResponse, ToggleDeploymentMetricsRequest, ToggleServiceMetricsRequest, TokenRenewalRequest, ToolCallEvent, ToolInfo, ToolResultEvent, TopModelsQueryParams, TraceProjectRef, TracesResponse, TraceSummariesResponse, TraceSummary, TrackClickData, TrackClickErrors, TrackedLinkResponse, TrackingEventResponse, TrackOpenData, TrackOpenErrors, TrackOpenResponses, TriggerAgentData, TriggerAgentErrors, TriggerAgentRequest, TriggerAgentResponse, TriggerAgentResponses, TriggerDigestResponse, TriggerPipelinePayload, TriggerPipelineResponse, TriggerProjectPipelineData, TriggerProjectPipelineErrors, TriggerProjectPipelineResponse, TriggerProjectPipelineResponses, TriggerScanData, TriggerScanError, TriggerScanErrors, TriggerScanRequest, TriggerScanResponse, TriggerScanResponse2, TriggerScanResponses, TriggerServiceHealthCheckData, TriggerServiceHealthCheckErrors, TriggerServiceHealthCheckResponse, TriggerServiceHealthCheckResponses, TriggerWeeklyDigestData, TriggerWeeklyDigestErrors, TriggerWeeklyDigestResponse, TriggerWeeklyDigestResponses, TtlRequest, TtlResponse, TxtRecord, UiManifest, UiRoute, UndrainNodeResponse, UnifiedTrace, UniqueCountsQuery, UniqueCountsResponse, UnlinkServiceFromProjectData, UnlinkServiceFromProjectErrors, UnlinkServiceFromProjectResponse, UnlinkServiceFromProjectResponses, UnsupportedFeature, UpdateAdminGateRequest, UpdateAgentData, UpdateAgentErrors, UpdateAgentResponse, UpdateAgentResponses, UpdateAiProviderData, UpdateAiProviderErrors, UpdateAiProviderRequest, UpdateAiProviderResponse, UpdateAiProviderResponse2, UpdateAiProviderResponses, UpdateAlertData, UpdateAlertError, UpdateAlertErrors, UpdateAlertResponse, UpdateAlertResponses, UpdateAlertRuleData, UpdateAlertRuleErrors, UpdateAlertRuleRequest, UpdateAlertRuleResponse, UpdateAlertRuleResponses, UpdateApiKeyData, UpdateApiKeyErrors, UpdateApiKeyRequest, UpdateApiKeyResponse, UpdateApiKeyResponses, UpdateAutomaticDeployData, UpdateAutomaticDeployErrors, UpdateAutomaticDeployRequest, UpdateAutomaticDeployResponse, UpdateAutomaticDeployResponses, UpdateBackupScheduleData, UpdateBackupScheduleError, UpdateBackupScheduleErrors, UpdateBackupScheduleRequest, UpdateBackupScheduleResponse, UpdateBackupScheduleResponses, UpdateBlobRequest, UpdateBlobResponse, UpdateCloudflareProviderData, UpdateCloudflareProviderErrors, UpdateCloudflareProviderRequest, UpdateCloudflareProviderResponse, UpdateCloudflareProviderResponses, UpdateConfigBody, UpdateConnectionTokenData, UpdateConnectionTokenErrors, UpdateConnectionTokenResponse, UpdateConnectionTokenResponses, UpdateCustomDomainData, UpdateCustomDomainErrors, UpdateCustomDomainRequest, UpdateCustomDomainResponse, UpdateCustomDomainResponses, UpdateDashboardData, UpdateDashboardError, UpdateDashboardErrors, UpdateDashboardRequest, UpdateDashboardResponse, UpdateDashboardResponses, UpdateDeploymentConfigRequest, UpdateDeploymentTokenData, UpdateDeploymentTokenErrors, UpdateDeploymentTokenRequest, UpdateDeploymentTokenResponse, UpdateDeploymentTokenResponses, UpdateDnsProviderRequest, UpdateEmailProviderData, UpdateEmailProviderErrors, UpdateEmailProviderRequest, UpdateEmailProviderResponse, UpdateEmailProviderResponses, UpdateEnvironmentSettingsData, UpdateEnvironmentSettingsErrors, UpdateEnvironmentSettingsRequest, UpdateEnvironmentSettingsResponse, UpdateEnvironmentSettingsResponses, UpdateEnvironmentSubdomainData, UpdateEnvironmentSubdomainErrors, UpdateEnvironmentSubdomainRequest, UpdateEnvironmentSubdomainResponse, UpdateEnvironmentSubdomainResponses, UpdateEnvironmentVariableData, UpdateEnvironmentVariableErrors, UpdateEnvironmentVariableRequest, UpdateEnvironmentVariableResponse, UpdateEnvironmentVariableResponses, UpdateErrorGroupData, UpdateErrorGroupErrors, UpdateErrorGroupRequest, UpdateErrorGroupResponses, UpdateExternalServiceRequest, UpdateFlagData, UpdateFlagErrors, UpdateFlagRequest, UpdateFlagResponse, UpdateFlagResponses, UpdateFunnelData, UpdateFunnelErrors, UpdateFunnelResponses, UpdateGitProviderCredentialsData, UpdateGitProviderCredentialsErrors, UpdateGitProviderCredentialsResponse, UpdateGitProviderCredentialsResponses, UpdateGitSettingsData, UpdateGitSettingsErrors, UpdateGitSettingsRequest, UpdateGitSettingsResponse, UpdateGitSettingsResponses, UpdateGlobalMcpData, UpdateGlobalMcpErrors, UpdateGlobalMcpResponse, UpdateGlobalMcpResponses, UpdateGlobalSkillData, UpdateGlobalSkillErrors, UpdateGlobalSkillResponse, UpdateGlobalSkillResponses, UpdateIncidentStatusData, UpdateIncidentStatusErrors, UpdateIncidentStatusRequest, UpdateIncidentStatusResponse, UpdateIncidentStatusResponses, UpdateIpAccessControlData, UpdateIpAccessControlError, UpdateIpAccessControlErrors, UpdateIpAccessControlRequest, UpdateIpAccessControlResponse, UpdateIpAccessControlResponses, UpdateKvRequest, UpdateKvResponse, UpdateManagedDomainApiRequest, UpdateManagedDomainData, UpdateManagedDomainErrors, UpdateManagedDomainResponse, UpdateManagedDomainResponses, UpdateMcpData, UpdateMcpErrors, UpdateMcpRequest, UpdateMcpResponse, UpdateMcpResponses, UpdateMemberRoleRequest, UpdateMetricAlertRequest, UpdateNotificationEmailProviderData, UpdateNotificationEmailProviderErrors, UpdateNotificationEmailProviderRequest, UpdateNotificationEmailProviderResponse, UpdateNotificationEmailProviderResponses, UpdateNotificationProviderData, UpdateNotificationProviderErrors, UpdateNotificationProviderResponse, UpdateNotificationProviderResponses, UpdateOidcProviderData, UpdateOidcProviderRequest, UpdateOidcProviderResponse, UpdateOidcProviderResponses, UpdatePreferencesData, UpdatePreferencesErrors, UpdatePreferencesRequest, UpdatePreferencesResponse, UpdatePreferencesResponses, UpdateProjectData, UpdateProjectDeploymentConfigData, UpdateProjectDeploymentConfigErrors, UpdateProjectDeploymentConfigResponse, UpdateProjectDeploymentConfigResponses, UpdateProjectErrors, UpdateProjectResponse, UpdateProjectResponses, UpdateProjectSecretData, UpdateProjectSecretErrors, UpdateProjectSecretRequest, UpdateProjectSecretResponse, UpdateProjectSecretResponses, UpdateProjectSettingsData, UpdateProjectSettingsErrors, UpdateProjectSettingsRequest, UpdateProjectSettingsResponse, UpdateProjectSettingsResponses, UpdateProviderCredentialsRequest, UpdateProviderData, UpdateProviderErrors, UpdateProviderKeyData, UpdateProviderKeyError, UpdateProviderKeyErrors, UpdateProviderKeyRequest, UpdateProviderKeyResponse, UpdateProviderKeyResponses, UpdateProviderRequest, UpdateProviderResponse, UpdateProviderResponses, UpdateRouteData, UpdateRouteErrors, UpdateRouteRequest, UpdateRouteResponse, UpdateRouteResponses, UpdateS3SourceData, UpdateS3SourceError, UpdateS3SourceErrors, UpdateS3SourceRequest, UpdateS3SourceResponse, UpdateS3SourceResponses, UpdateSecretBody, UpdateSelfData, UpdateSelfErrors, UpdateSelfRequest, UpdateSelfResponse, UpdateSelfResponses, UpdateServiceData, UpdateServiceErrors, UpdateServiceResourcesData, UpdateServiceResourcesErrors, UpdateServiceResourcesResponse, UpdateServiceResourcesResponses, UpdateServiceResponse, UpdateServiceResponses, UpdateSessionDurationData, UpdateSessionDurationError, UpdateSessionDurationErrors, UpdateSessionDurationRequest, UpdateSessionDurationResponse, UpdateSessionDurationResponse2, UpdateSessionDurationResponses, UpdateSettingsData, UpdateSettingsErrors, UpdateSettingsResponse, UpdateSettingsResponses, UpdateSkillData, UpdateSkillErrors, UpdateSkillRequest, UpdateSkillResponse, UpdateSkillResponses, UpdateSlackProviderData, UpdateSlackProviderErrors, UpdateSlackProviderRequest, UpdateSlackProviderResponse, UpdateSlackProviderResponses, UpdateSpeedMetricsData, UpdateSpeedMetricsError, UpdateSpeedMetricsErrors, UpdateSpeedMetricsPayload, UpdateSpeedMetricsResponse, UpdateSpeedMetricsResponses, UpdateStatusResponse, UpdateTeamData, UpdateTeamErrors, UpdateTeamMemberRoleData, UpdateTeamMemberRoleErrors, UpdateTeamMemberRoleResponse, UpdateTeamMemberRoleResponses, UpdateTeamRequest, UpdateTeamResponse, UpdateTeamResponses, UpdateTokenRequest, UpdateTokenResponse, UpdateUserData, UpdateUserErrors, UpdateUserRequest, UpdateUserResponse, UpdateUserResponses, UpdateWebhookData, UpdateWebhookErrors, UpdateWebhookProviderData, UpdateWebhookProviderErrors, UpdateWebhookProviderRequest, UpdateWebhookProviderResponse, UpdateWebhookProviderResponses, UpdateWebhookRequestBody, UpdateWebhookResponse, UpdateWebhookResponses, UpgradeExternalServiceRequest, UpgradePreviewGatewayData, UpgradePreviewGatewayResponse, UpgradePreviewGatewayResponses, UpgradeRequest, UpgradeServiceData, UpgradeServiceErrors, UpgradeServiceResponse, UpgradeServiceResponses, UploadGlobalSkillData, UploadGlobalSkillErrors, UploadGlobalSkillResponse, UploadGlobalSkillResponses, UploadReleaseFileData, UploadReleaseFileErrors, UploadReleaseFileResponse, UploadReleaseFileResponses, UploadSkillData, UploadSkillErrors, UploadSkillResponse, UploadSkillResponses, UploadSourceFileData, UploadSourceFileErrors, UploadSourceFileResponse, UploadSourceFileResponses, UploadSourceMapData, UploadSourceMapErrors, UploadSourceMapResponse, UploadSourceMapResponses, UploadStaticBundleData, UploadStaticBundleErrors, UploadStaticBundleResponse, UploadStaticBundleResponses, UpsertAgentRequest, UpsertSecretData, UpsertSecretErrors, UpsertSecretRequest, UpsertSecretResponse, UpsertSecretResponses, UptimeDataPoint, UptimeHistoryResponse, UsageFilter, UsageInfo, UsageLogEntry, UsageLogPage, UsageQueryParams, UsageSource, UsageSummary, UserResponse, ValidateConnectionData, ValidateConnectionErrors, ValidateConnectionResponse, ValidateConnectionResponses, ValidateEmailData, ValidateEmailErrors, ValidateEmailRequest, ValidateEmailResponse, ValidateEmailResponse2, ValidateEmailResponses, ValidationLevel, ValidationReport, ValidationResponse, ValidationResult, ValidationStatus, ValidationSummary, VerifyAndEnableMfaData, VerifyAndEnableMfaErrors, VerifyAndEnableMfaResponse, VerifyAndEnableMfaResponses, VerifyDomainData, VerifyDomainErrors, VerifyDomainResponse, VerifyDomainResponses, VerifyEmailData, VerifyEmailErrors, VerifyEmailResponse, VerifyEmailResponses, VerifyManagedDomainData, VerifyManagedDomainErrors, VerifyManagedDomainResponse, VerifyManagedDomainResponses, VerifyMfaChallengeData, VerifyMfaChallengeErrors, VerifyMfaChallengeResponse, VerifyMfaChallengeResponses, VerifyMfaRequest, VerifyStepUpData, VerifyStepUpErrors, VerifyStepUpRequest, VerifyStepUpResponse, VerifyStepUpResponses, ViewItem, ViewsOverTime, ViewsOverTimeQuery, VisitorDetails, VisitorFacets, VisitorFacetsQuery, VisitorFacetValue, VisitorInfo, VisitorJourneyQuery, VisitorJourneyResponse, VisitorLocationsQuery, VisitorRecord, VisitorSegmentFilters, VisitorSessionsQuery, VisitorSessionsResponse, VisitorsListQuery, VisitorsResponse, VisitorStats, VisitorWithGeolocation, VolumeMount, VolumeType, VulnerabilityResponse, WakeEnvironmentData, WakeEnvironmentErrors, WakeEnvironmentResponse, WakeEnvironmentResponses, WalWarning, WalWarningSeverity, WebhookConfig, WebhookDeliveryResponse, WebhookResponse, WebhookTriggerData, WebhookTriggerErrors, WebhookTriggerRequest, WebhookTriggerResponse, WebhookTriggerResponse2, WebhookTriggerResponses, WorkflowDryRunData, WorkflowDryRunErrors, WorkflowDryRunRequest, WorkflowDryRunResponse, WorkflowDryRunResponses, WorkloadDescriptor, WorkloadId, WorkloadStatus, WorkloadType, WriteFileBody, WriteFileData, WriteFileErrors, WriteFileResponse, WriteFileResponses, WriteFilesBody, WriteFilesData, WriteFilesErrors, WriteFilesResponse, WriteFilesResponse2, WriteFilesResponses, ZoneListResponse } from './types.gen'; diff --git a/apps/temps-cli/src/api/sdk.gen.ts b/apps/temps-cli/src/api/sdk.gen.ts index 4333323d2..0fb6aa08b 100644 --- a/apps/temps-cli/src/api/sdk.gen.ts +++ b/apps/temps-cli/src/api/sdk.gen.ts @@ -2,7 +2,7 @@ import { type Client, type ClientMeta, formDataBodySerializer, type Options as Options2, type RequestResult, type ServerSentEventsResult, type TDataShape } from './client'; import { client } from './client.gen'; -import type { AcknowledgeAlarmData, AcknowledgeAlarmErrors, AcknowledgeAlarmResponses, ActivateAiProviderData, ActivateAiProviderErrors, ActivateAiProviderResponses, ActivateApiKeyData, ActivateApiKeyErrors, ActivateApiKeyResponses, ActivateConnectionData, ActivateConnectionErrors, ActivateConnectionResponses, ActivateProviderData, ActivateProviderErrors, ActivateProviderResponses, AddClusterMemberData, AddClusterMemberErrors, AddClusterMemberResponses, AddContextData, AddContextErrors, AddContextResponses, AddEnvironmentDomainData, AddEnvironmentDomainErrors, AddEnvironmentDomainResponses, AddEventsData, AddEventsErrors, AddEventsResponses, AddManagedDomainData, AddManagedDomainErrors, AddManagedDomainResponses, AddSessionReplayEventsData, AddSessionReplayEventsErrors, AddSessionReplayEventsResponses, AddTeamMemberData, AddTeamMemberErrors, AddTeamMemberResponses, AdminDrainNodeData, AdminDrainNodeErrors, AdminDrainNodeResponses, AdminDrainStatusData, AdminDrainStatusErrors, AdminDrainStatusResponses, AdminGetNodeData, AdminGetNodeErrors, AdminGetNodeResponses, AdminListNodeContainersData, AdminListNodeContainersErrors, AdminListNodeContainersResponses, AdminListNodesData, AdminListNodesErrors, AdminListNodesResponses, AdminRemoveNodeData, AdminRemoveNodeErrors, AdminRemoveNodeResponses, AdminUndrainNodeData, AdminUndrainNodeErrors, AdminUndrainNodeResponses, ApplyHostnameModeData, ApplyHostnameModeErrors, ApplyHostnameModeResponses, ArchiveConversationData, ArchiveConversationErrors, ArchiveConversationResponses, ArchiveFlagData, ArchiveFlagErrors, ArchiveFlagResponses, AssignRoleData, AssignRoleErrors, AssignRoleResponses, AttachScheduleServicesData, AttachScheduleServicesErrors, AttachScheduleServicesResponses, BlobCopyData, BlobCopyErrors, BlobCopyResponses, BlobDeleteData, BlobDeleteErrors, BlobDeleteResponses, BlobDisableData, BlobDisableErrors, BlobDisableResponses, BlobDownloadData, BlobDownloadErrors, BlobDownloadResponses, BlobEnableData, BlobEnableErrors, BlobEnableResponses, BlobHeadData, BlobHeadErrors, BlobHeadResponses, BlobListData, BlobListErrors, BlobListResponses, BlobPutData, BlobPutErrors, BlobPutResponses, BlobStatusData, BlobStatusErrors, BlobStatusResponses, BlobUpdateData, BlobUpdateErrors, BlobUpdateResponses, CancelBackupData, CancelBackupErrors, CancelBackupResponses, CancelData, CancelDeploymentData, CancelDeploymentErrors, CancelDeploymentResponses, CancelDomainOrderData, CancelDomainOrderErrors, CancelDomainOrderResponses, CancelErrors, CancelPgUpgradeData, CancelPgUpgradeErrors, CancelPgUpgradeResponses, CancelResponses, CancelRunData, CancelRunErrors, CancelRunResponses, CancelScheduleRunData, CancelScheduleRunErrors, CancelScheduleRunResponses, ChangePasswordSelfData, ChangePasswordSelfErrors, ChangePasswordSelfResponses, ChangeProjectSourceData, ChangeProjectSourceErrors, ChangeProjectSourceResponses, ChatCompletionsData, ChatCompletionsErrors, ChatCompletionsResponses, CheckAnalyticsHasEventsData, CheckAnalyticsHasEventsErrors, CheckAnalyticsHasEventsResponses, CheckCommitExistsData, CheckCommitExistsErrors, CheckCommitExistsResponses, CheckDomainStatusData, CheckDomainStatusErrors, CheckDomainStatusResponses, CheckExplorerSupportData, CheckExplorerSupportErrors, CheckExplorerSupportResponses, CheckIpBlockedData, CheckIpBlockedErrors, CheckIpBlockedResponses, CheckProviderDeletionSafetyData, CheckProviderDeletionSafetyErrors, CheckProviderDeletionSafetyResponses, ChunkUploadOptionsData, ChunkUploadOptionsResponses, CleanupExpiredBackupsData, CleanupExpiredBackupsErrors, CleanupExpiredBackupsResponses, ClearPreviewPasswordData, ClearPreviewPasswordErrors, ClearPreviewPasswordResponses, CliDeviceApproveData, CliDeviceApproveErrors, CliDeviceApproveResponses, CliDeviceDenyData, CliDeviceDenyErrors, CliDeviceDenyResponses, CliDeviceLookupData, CliDeviceLookupErrors, CliDeviceLookupResponses, CliDevicePollData, CliDevicePollErrors, CliDevicePollResponses, CliDeviceStartData, CliDeviceStartErrors, CliDeviceStartResponses, CliLogoutData, CliLogoutErrors, CliLogoutResponses, CmdData, CmdErrors, CmdKillData, CmdKillErrors, CmdKillResponses, CmdLogsData, CmdLogsErrors, CmdLogsResponses, CmdResponses, ConfirmPendingActionData, ConfirmPendingActionErrors, ConfirmPendingActionResponses, ContainerMetricsGetHistoryData, ContainerMetricsGetHistoryErrors, ContainerMetricsGetHistoryResponses, CreateAgentData, CreateAgentErrors, CreateAgentResponses, CreateAlertData, CreateAlertErrors, CreateAlertResponses, CreateAlertRuleData, CreateAlertRuleErrors, CreateAlertRuleResponses, CreateApiKeyData, CreateApiKeyErrors, CreateApiKeyResponses, CreateBackupScheduleData, CreateBackupScheduleErrors, CreateBackupScheduleResponses, CreateBitbucketProviderData, CreateBitbucketProviderErrors, CreateBitbucketProviderResponses, CreateCloudflareProviderData, CreateCloudflareProviderErrors, CreateCloudflareProviderResponses, CreateConversationData, CreateConversationErrors, CreateConversationResponses, CreateCustomDomainData, CreateCustomDomainErrors, CreateCustomDomainResponses, CreateDashboardData, CreateDashboardErrors, CreateDashboardResponses, CreateDeploymentTokenData, CreateDeploymentTokenErrors, CreateDeploymentTokenResponses, CreateDnsProviderData, CreateDnsProviderErrors, CreateDnsProviderResponses, CreateDomainData, CreateDomainErrors, CreateDomainResponses, CreateDsnData, CreateDsnErrors, CreateDsnResponses, CreateEmailDomainData, CreateEmailDomainErrors, CreateEmailDomainResponses, CreateEmailProviderData, CreateEmailProviderErrors, CreateEmailProviderResponses, CreateEnvironmentData, CreateEnvironmentErrors, CreateEnvironmentResponses, CreateEnvironmentVariableData, CreateEnvironmentVariableErrors, CreateEnvironmentVariableResponses, CreateFlagData, CreateFlagErrors, CreateFlagResponses, CreateFunnelData, CreateFunnelErrors, CreateFunnelResponses, CreateGenericProviderData, CreateGenericProviderErrors, CreateGenericProviderResponses, CreateGiteaPatProviderData, CreateGiteaPatProviderErrors, CreateGiteaPatProviderResponses, CreateGithubPatProviderData, CreateGithubPatProviderErrors, CreateGithubPatProviderResponses, CreateGitlabOauthProviderData, CreateGitlabOauthProviderErrors, CreateGitlabOauthProviderResponses, CreateGitlabPatProviderData, CreateGitlabPatProviderErrors, CreateGitlabPatProviderResponses, CreateGitProviderData, CreateGitProviderErrors, CreateGitProviderResponses, CreateGlobalMcpData, CreateGlobalMcpErrors, CreateGlobalMcpResponses, CreateGlobalSkillData, CreateGlobalSkillErrors, CreateGlobalSkillResponses, CreateIncidentData, CreateIncidentErrors, CreateIncidentResponses, CreateIpAccessControlData, CreateIpAccessControlErrors, CreateIpAccessControlResponses, CreateMcpData, CreateMcpErrors, CreateMcpResponses, CreateMonitorData, CreateMonitorErrors, CreateMonitorResponses, CreateNotificationEmailProviderData, CreateNotificationEmailProviderErrors, CreateNotificationEmailProviderResponses, CreateNotificationProviderData, CreateNotificationProviderErrors, CreateNotificationProviderResponses, CreateOidcProviderData, CreateOidcProviderErrors, CreateOidcProviderResponses, CreateOidcRoleMappingData, CreateOidcRoleMappingResponses, CreateOrRecreateOrderData, CreateOrRecreateOrderErrors, CreateOrRecreateOrderResponses, CreatePlanData, CreatePlanErrors, CreatePlanResponses, CreatePrData, CreatePrErrors, CreateProjectData, CreateProjectErrors, CreateProjectFromTemplateData, CreateProjectFromTemplateErrors, CreateProjectFromTemplateResponses, CreateProjectReleaseData, CreateProjectReleaseErrors, CreateProjectReleaseResponses, CreateProjectResponses, CreateProjectSecretData, CreateProjectSecretErrors, CreateProjectSecretResponses, CreateProviderKeyData, CreateProviderKeyErrors, CreateProviderKeyResponses, CreatePrResponses, CreateReleaseData, CreateReleaseErrors, CreateReleaseResponses, CreateRouteData, CreateRouteErrors, CreateRouteResponses, CreateS3SourceData, CreateS3SourceErrors, CreateS3SourceResponses, CreateSandboxData, CreateSandboxErrors, CreateSandboxResponses, CreateServiceData, CreateServiceErrors, CreateServiceResponses, CreateSkillData, CreateSkillErrors, CreateSkillResponses, CreateSlackProviderData, CreateSlackProviderErrors, CreateSlackProviderResponses, CreateTeamData, CreateTeamErrors, CreateTeamResponses, CreateUserData, CreateUserErrors, CreateUserResponses, CreateWebhookData, CreateWebhookErrors, CreateWebhookProviderData, CreateWebhookProviderErrors, CreateWebhookProviderResponses, CreateWebhookResponses, DeactivateApiKeyData, DeactivateApiKeyErrors, DeactivateApiKeyResponses, DeactivateConnectionData, DeactivateConnectionErrors, DeactivateConnectionResponses, DeactivateProviderData, DeactivateProviderErrors, DeactivateProviderResponses, DeleteAgentData, DeleteAgentErrors, DeleteAgentResponses, DeleteAlertData, DeleteAlertErrors, DeleteAlertResponses, DeleteAlertRuleData, DeleteAlertRuleErrors, DeleteAlertRuleResponses, DeleteApiKeyData, DeleteApiKeyErrors, DeleteApiKeyResponses, DeleteBackupData, DeleteBackupErrors, DeleteBackupResponses, DeleteBackupScheduleData, DeleteBackupScheduleErrors, DeleteBackupScheduleResponses, DeleteConnectionData, DeleteConnectionErrors, DeleteConnectionResponses, DeleteCustomDomainData, DeleteCustomDomainErrors, DeleteCustomDomainResponses, DeleteDashboardData, DeleteDashboardErrors, DeleteDashboardResponses, DeleteDeploymentTokenData, DeleteDeploymentTokenErrors, DeleteDeploymentTokenResponses, DeleteDnsProviderData, DeleteDnsProviderErrors, DeleteDnsProviderResponses, DeleteDomainData, DeleteDomainErrors, DeleteDomainResponses, DeleteEmailDomainData, DeleteEmailDomainErrors, DeleteEmailDomainResponses, DeleteEmailProviderData, DeleteEmailProviderErrors, DeleteEmailProviderResponses, DeleteEnvironmentData, DeleteEnvironmentDomainData, DeleteEnvironmentDomainErrors, DeleteEnvironmentDomainResponses, DeleteEnvironmentErrors, DeleteEnvironmentResponses, DeleteEnvironmentVariableData, DeleteEnvironmentVariableErrors, DeleteEnvironmentVariableResponses, DeleteExternalImageData, DeleteExternalImageErrors, DeleteExternalImageResponses, DeleteFunnelData, DeleteFunnelErrors, DeleteFunnelResponses, DeleteGitProviderData, DeleteGitProviderErrors, DeleteGitProviderResponses, DeleteGlobalMcpData, DeleteGlobalMcpErrors, DeleteGlobalMcpResponses, DeleteGlobalSkillData, DeleteGlobalSkillErrors, DeleteGlobalSkillResponses, DeleteIpAccessControlData, DeleteIpAccessControlErrors, DeleteIpAccessControlResponses, DeleteMcpData, DeleteMcpErrors, DeleteMcpResponses, DeleteMonitorData, DeleteMonitorErrors, DeleteMonitorResponses, DeleteNotificationProviderData, DeleteNotificationProviderErrors, DeleteNotificationProviderResponses, DeleteOidcProviderData, DeleteOidcProviderResponses, DeleteOidcRoleMappingData, DeleteOidcRoleMappingResponses, DeletePreferencesData, DeletePreferencesErrors, DeletePreferencesResponses, DeleteProjectData, DeleteProjectErrors, DeleteProjectResponses, DeleteProjectSecretData, DeleteProjectSecretErrors, DeleteProjectSecretResponses, DeleteProviderKeyData, DeleteProviderKeyErrors, DeleteProviderKeyResponses, DeleteProviderSafelyData, DeleteProviderSafelyErrors, DeleteProviderSafelyResponses, DeleteReleaseSourceFilesData, DeleteReleaseSourceFilesErrors, DeleteReleaseSourceFilesResponses, DeleteReleaseSourceMapsData, DeleteReleaseSourceMapsErrors, DeleteReleaseSourceMapsResponses, DeleteRouteData, DeleteRouteErrors, DeleteRouteResponses, DeleteS3SourceData, DeleteS3SourceErrors, DeleteS3SourceResponses, DeleteScanData, DeleteScanErrors, DeleteScanResponses, DeleteSecretData, DeleteSecretErrors, DeleteSecretResponses, DeleteServiceData, DeleteServiceErrors, DeleteServiceResponses, DeleteSessionReplayData, DeleteSessionReplayErrors, DeleteSessionReplayResponses, DeleteSkillData, DeleteSkillErrors, DeleteSkillResponses, DeleteSourceMapData, DeleteSourceMapErrors, DeleteSourceMapResponses, DeleteStaticBundleData, DeleteStaticBundleErrors, DeleteStaticBundleResponses, DeleteTeamData, DeleteTeamErrors, DeleteTeamResponses, DeleteUserData, DeleteUserErrors, DeleteUserResponses, DeleteWebhookData, DeleteWebhookErrors, DeleteWebhookResponses, DeployFromImageData, DeployFromImageErrors, DeployFromImageResponses, DeployFromImageUploadData, DeployFromImageUploadErrors, DeployFromImageUploadResponses, DeployFromStaticData, DeployFromStaticErrors, DeployFromStaticResponses, DeploymentMetricsGetLatestData, DeploymentMetricsGetLatestErrors, DeploymentMetricsGetLatestResponses, DeploymentMetricsGetRangeData, DeploymentMetricsGetRangeErrors, DeploymentMetricsGetRangeResponses, DeploymentMetricsToggleData, DeploymentMetricsToggleErrors, DeploymentMetricsToggleResponses, DestroySandboxData, DestroySandboxErrors, DestroySandboxResponses, DetachScheduleServiceData, DetachScheduleServiceErrors, DetachScheduleServiceResponses, DetectPublicPresetsData, DetectPublicPresetsErrors, DetectPublicPresetsResponses, DisableBackupScheduleData, DisableBackupScheduleErrors, DisableBackupScheduleResponses, DisableMfaData, DisableMfaErrors, DisableMfaResponses, DiscoverWorkloadsData, DiscoverWorkloadsErrors, DiscoverWorkloadsResponses, DomainData, DomainErrors, DomainResponses, DownloadGlobalSkillArchiveData, DownloadGlobalSkillArchiveErrors, DownloadGlobalSkillArchiveResponses, DownloadObjectData, DownloadObjectErrors, DownloadObjectResponses, DownloadSkillArchiveData, DownloadSkillArchiveErrors, DownloadSkillArchiveResponses, EmailStatusData, EmailStatusErrors, EmailStatusResponses, EmbeddingsData, EmbeddingsErrors, EmbeddingsResponses, EnableBackupScheduleData, EnableBackupScheduleErrors, EnableBackupScheduleResponses, EnrichVisitorData, EnrichVisitorErrors, EnrichVisitorResponses, ExecData, ExecDetachedData, ExecDetachedErrors, ExecDetachedResponses, ExecErrors, ExecResponses, ExecuteDeploymentOperationData, ExecuteDeploymentOperationErrors, ExecuteDeploymentOperationResponses, ExecuteImportData, ExecuteImportErrors, ExecuteImportResponses, ExtendTimeoutData, ExtendTimeoutErrors, ExtendTimeoutResponses, ExternalServiceEnablePgStatStatementsData, ExternalServiceEnablePgStatStatementsErrors, ExternalServiceEnablePgStatStatementsResponses, ExternalServiceMetricsByDatabaseData, ExternalServiceMetricsByDatabaseErrors, ExternalServiceMetricsByDatabaseResponses, ExternalServiceMetricsCreateAlertRuleData, ExternalServiceMetricsCreateAlertRuleErrors, ExternalServiceMetricsCreateAlertRuleResponses, ExternalServiceMetricsDeleteAlertRuleData, ExternalServiceMetricsDeleteAlertRuleErrors, ExternalServiceMetricsDeleteAlertRuleResponses, ExternalServiceMetricsGetAlertRulesData, ExternalServiceMetricsGetAlertRulesErrors, ExternalServiceMetricsGetAlertRulesResponses, ExternalServiceMetricsGetLatestData, ExternalServiceMetricsGetLatestErrors, ExternalServiceMetricsGetLatestResponses, ExternalServiceMetricsGetRangeData, ExternalServiceMetricsGetRangeErrors, ExternalServiceMetricsGetRangeResponses, ExternalServiceMetricsStatusData, ExternalServiceMetricsStatusErrors, ExternalServiceMetricsStatusResponses, ExternalServiceMetricsToggleData, ExternalServiceMetricsToggleErrors, ExternalServiceMetricsToggleResponses, ExternalServiceMetricsUpdateAlertRuleData, ExternalServiceMetricsUpdateAlertRuleErrors, ExternalServiceMetricsUpdateAlertRuleResponses, ExternalServiceResetPgStatStatementsData, ExternalServiceResetPgStatStatementsErrors, ExternalServiceResetPgStatStatementsResponses, FinalizeOrderData, FinalizeOrderErrors, FinalizeOrderResponses, FinalizeProjectReleaseData, FinalizeProjectReleaseErrors, FinalizeProjectReleaseResponses, FindConversationData, FindConversationErrors, FindConversationResponses, GenerateJoinTokenData, GenerateJoinTokenErrors, GenerateJoinTokenResponses, GeneratePresetDockerfileData, GeneratePresetDockerfileErrors, GeneratePresetDockerfileResponses, GetAccessInfoData, GetAccessInfoErrors, GetAccessInfoResponses, GetActiveVisitorsData, GetActiveVisitorsErrors, GetActiveVisitorsResponses, GetActivityGraphData, GetActivityGraphErrors, GetActivityGraphResponses, GetAdminGateData, GetAdminGateErrors, GetAdminGateResponses, GetAgentData, GetAgentErrors, GetAgentResponses, GetAggregatedBucketsData, GetAggregatedBucketsErrors, GetAggregatedBucketsResponses, GetAiAgentBreakdownData, GetAiAgentBreakdownErrors, GetAiAgentBreakdownResponses, GetAiAgentPagesData, GetAiAgentPagesErrors, GetAiAgentPagesResponses, GetAiAgentTimelineData, GetAiAgentTimelineErrors, GetAiAgentTimelineResponses, GetAiPageBreakdownData, GetAiPageBreakdownErrors, GetAiPageBreakdownResponses, GetAiStatusBreakdownData, GetAiStatusBreakdownErrors, GetAiStatusBreakdownResponses, GetAlertData, GetAlertErrors, GetAlertResponses, GetAlertRuleData, GetAlertRuleErrors, GetAlertRuleResponses, GetAllRepositoriesByNameData, GetAllRepositoriesByNameErrors, GetAllRepositoriesByNameResponses, GetAnalyticsActiveVisitorsData, GetAnalyticsActiveVisitorsErrors, GetAnalyticsActiveVisitorsResponses, GetAnalyticsEventsCountData, GetAnalyticsEventsCountErrors, GetAnalyticsEventsCountResponses, GetAnalyticsSessionEventsData, GetAnalyticsSessionEventsErrors, GetAnalyticsSessionEventsResponses, GetAnalyticsVisitorSessionsData, GetAnalyticsVisitorSessionsErrors, GetAnalyticsVisitorSessionsResponses, GetApiKeyData, GetApiKeyErrors, GetApiKeyPermissionsData, GetApiKeyPermissionsErrors, GetApiKeyPermissionsResponses, GetApiKeyResponses, GetAuditLogData, GetAuditLogErrors, GetAuditLogResponses, GetBackupData, GetBackupErrors, GetBackupResponses, GetBackupScheduleData, GetBackupScheduleErrors, GetBackupScheduleResponses, GetBranchesByRepositoryIdData, GetBranchesByRepositoryIdErrors, GetBranchesByRepositoryIdResponses, GetBucketedIncidentsData, GetBucketedIncidentsErrors, GetBucketedIncidentsResponses, GetBucketedStatusData, GetBucketedStatusErrors, GetBucketedStatusResponses, GetChallengeTokenData, GetChallengeTokenErrors, GetChallengeTokenResponses, GetChatReadinessData, GetChatReadinessErrors, GetChatReadinessResponses, GetCliStatusData, GetCliStatusErrors, GetCliStatusResponses, GetClusterHealthData, GetClusterHealthErrors, GetClusterHealthResponses, GetClusterMemberData, GetClusterMemberErrors, GetClusterMemberResponses, GetCmdData, GetCmdErrors, GetCmdResponses, GetContainerDetailData, GetContainerDetailErrors, GetContainerDetailResponses, GetContainerEnvironmentVariableData, GetContainerEnvironmentVariableErrors, GetContainerEnvironmentVariableResponses, GetContainerInfoData, GetContainerInfoErrors, GetContainerInfoResponses, GetContainerLogsByIdData, GetContainerLogsByIdErrors, GetContainerLogsData, GetContainerLogsErrors, GetContainerMetricsData, GetContainerMetricsErrors, GetContainerMetricsResponses, GetConversationData, GetConversationDetailData, GetConversationDetailErrors, GetConversationDetailResponses, GetConversationErrors, GetConversationResponses, GetConversationsData, GetConversationsErrors, GetConversationsResponses, GetCronByIdData, GetCronByIdErrors, GetCronByIdResponses, GetCronExecutionsData, GetCronExecutionsErrors, GetCronExecutionsResponses, GetCrossProjectTraceSiblingsData, GetCrossProjectTraceSiblingsErrors, GetCrossProjectTraceSiblingsResponses, GetCurrentMonitorStatusData, GetCurrentMonitorStatusErrors, GetCurrentMonitorStatusResponses, GetCurrentUserData, GetCurrentUserErrors, GetCurrentUserResponses, GetCustomDomainData, GetCustomDomainErrors, GetCustomDomainResponses, GetDashboardData, GetDashboardErrors, GetDashboardProjectsAnalyticsData, GetDashboardProjectsAnalyticsErrors, GetDashboardProjectsAnalyticsResponses, GetDashboardResponses, GetDeliveryData, GetDeliveryErrors, GetDeliveryResponses, GetDeploymentContainerLogContentData, GetDeploymentContainerLogContentErrors, GetDeploymentContainerLogContentResponses, GetDeploymentData, GetDeploymentErrors, GetDeploymentJobLogsData, GetDeploymentJobLogsErrors, GetDeploymentJobLogsResponses, GetDeploymentJobsData, GetDeploymentJobsErrors, GetDeploymentJobsResponses, GetDeploymentOperationsData, GetDeploymentOperationsErrors, GetDeploymentOperationsResponses, GetDeploymentOperationStatusData, GetDeploymentOperationStatusErrors, GetDeploymentOperationStatusResponses, GetDeploymentResponses, GetDeploymentTokenData, GetDeploymentTokenErrors, GetDeploymentTokenResponses, GetDiskStatusData, GetDiskStatusErrors, GetDiskStatusResponses, GetDnsChangesData, GetDnsChangesErrors, GetDnsChangesResponses, GetDnsProviderData, GetDnsProviderErrors, GetDnsProviderResponses, GetDomainByHostData, GetDomainByHostErrors, GetDomainByHostResponses, GetDomainByIdData, GetDomainByIdErrors, GetDomainByIdResponses, GetDomainByNameData, GetDomainByNameErrors, GetDomainByNameResponses, GetDomainData, GetDomainDnsRecordsData, GetDomainDnsRecordsErrors, GetDomainDnsRecordsResponses, GetDomainErrors, GetDomainOrderData, GetDomainOrderErrors, GetDomainOrderResponses, GetDomainResponses, GetEmailData, GetEmailErrors, GetEmailEventsData, GetEmailEventsErrors, GetEmailEventsResponses, GetEmailLinksData, GetEmailLinksErrors, GetEmailLinksResponses, GetEmailProviderData, GetEmailProviderErrors, GetEmailProviderResponses, GetEmailResponses, GetEmailStatsData, GetEmailStatsErrors, GetEmailStatsResponses, GetEmailTrackingData, GetEmailTrackingErrors, GetEmailTrackingResponses, GetEmailTrackingStatusData, GetEmailTrackingStatusErrors, GetEmailTrackingStatusResponses, GetEntityInfoData, GetEntityInfoErrors, GetEntityInfoResponses, GetEnvironmentCronsData, GetEnvironmentCronsErrors, GetEnvironmentCronsResponses, GetEnvironmentData, GetEnvironmentDomainsData, GetEnvironmentDomainsErrors, GetEnvironmentDomainsResponses, GetEnvironmentErrors, GetEnvironmentResponses, GetEnvironmentsData, GetEnvironmentsErrors, GetEnvironmentsResponses, GetEnvironmentVariablesData, GetEnvironmentVariablesErrors, GetEnvironmentVariablesResponses, GetEnvironmentVariableValueData, GetEnvironmentVariableValueErrors, GetEnvironmentVariableValueResponses, GetErrorDashboardStatsData, GetErrorDashboardStatsErrors, GetErrorDashboardStatsResponses, GetErrorEventData, GetErrorEventErrors, GetErrorEventResponses, GetErrorGroupData, GetErrorGroupErrors, GetErrorGroupResponses, GetErrorStatsData, GetErrorStatsErrors, GetErrorStatsResponses, GetErrorTimeSeriesData, GetErrorTimeSeriesErrors, GetErrorTimeSeriesResponses, GetEventDetailData, GetEventDetailErrors, GetEventDetailResponses, GetEventEntriesData, GetEventEntriesErrors, GetEventEntriesResponses, GetEventsCountData, GetEventsCountErrors, GetEventsCountResponses, GetEventsTimelineData, GetEventsTimelineErrors, GetEventsTimelineResponses, GetEventTypeBreakdownData, GetEventTypeBreakdownErrors, GetEventTypeBreakdownResponses, GetEventVisitorsData, GetEventVisitorsErrors, GetEventVisitorsResponses, GetExternalImageData, GetExternalImageErrors, GetExternalImageResponses, GetFileData, GetFileErrors, GetFileResponses, GetFlagData, GetFlagErrors, GetFlagResponses, GetFlagSnapshotData, GetFlagSnapshotErrors, GetFlagSnapshotResponses, GetFunnelMetricsData, GetFunnelMetricsErrors, GetFunnelMetricsResponses, GetGenaiTraceData, GetGenaiTraceErrors, GetGenaiTraceResponses, GetGeneralStatsData, GetGeneralStatsErrors, GetGeneralStatsResponses, GetGitProviderData, GetGitProviderErrors, GetGitProviderResponses, GetGlobalEventsData, GetGlobalEventsErrors, GetGlobalEventsResponses, GetGlobalEventStatsData, GetGlobalEventStatsErrors, GetGlobalEventStatsResponses, GetGlobalMcpData, GetGlobalMcpErrors, GetGlobalMcpResponses, GetGlobalSandboxStatusData, GetGlobalSandboxStatusErrors, GetGlobalSandboxStatusResponses, GetGlobalSkillData, GetGlobalSkillErrors, GetGlobalSkillResponses, GetGroupedPageMetricsData, GetGroupedPageMetricsErrors, GetGroupedPageMetricsResponses, GetHealthData, GetHealthErrors, GetHealthResponses, GetHourlyVisitsData, GetHourlyVisitsErrors, GetHourlyVisitsResponses, GetHttpChallengeDebugData, GetHttpChallengeDebugErrors, GetHttpChallengeDebugResponses, GetImportStatusData, GetImportStatusErrors, GetImportStatusResponses, GetIncidentData, GetIncidentErrors, GetIncidentResponses, GetIncidentUpdatesData, GetIncidentUpdatesErrors, GetIncidentUpdatesResponses, GetIpAccessControlData, GetIpAccessControlErrors, GetIpAccessControlResponses, GetIpGeolocationData, GetIpGeolocationErrors, GetIpGeolocationResponses, GetJoinTokenStatusData, GetJoinTokenStatusErrors, GetJoinTokenStatusResponses, GetLastDeploymentData, GetLastDeploymentErrors, GetLastDeploymentResponses, GetLatestScanData, GetLatestScanErrors, GetLatestScanResponses, GetLatestScansPerEnvironmentData, GetLatestScansPerEnvironmentErrors, GetLatestScansPerEnvironmentResponses, GetLiveVisitorsListData, GetLiveVisitorsListErrors, GetLiveVisitorsListResponses, GetLogContextData, GetLogContextErrors, GetLogContextResponses, GetMcpData, GetMcpErrors, GetMcpResponses, GetMetricsOverTimeData, GetMetricsOverTimeErrors, GetMetricsOverTimeResponses, GetMonitorData, GetMonitorErrors, GetMonitorResponses, GetNotificationProviderData, GetNotificationProviderErrors, GetNotificationProviderResponses, GetOnDemandCertStatusData, GetOnDemandCertStatusErrors, GetOnDemandCertStatusResponses, GetOrCreateDsnData, GetOrCreateDsnErrors, GetOrCreateDsnResponses, GetPageFlowData, GetPageFlowErrors, GetPageFlowResponses, GetPageHourlySessionsData, GetPageHourlySessionsErrors, GetPageHourlySessionsResponses, GetPagePathDetailData, GetPagePathDetailErrors, GetPagePathDetailResponses, GetPagePathsData, GetPagePathsErrors, GetPagePathsResponses, GetPagePathsSparklinesData, GetPagePathsSparklinesErrors, GetPagePathsSparklinesResponses, GetPagePathVisitorsData, GetPagePathVisitorsErrors, GetPagePathVisitorsResponses, GetPendingActionData, GetPendingActionErrors, GetPendingActionResponses, GetPerformanceMetricsData, GetPerformanceMetricsErrors, GetPerformanceMetricsResponses, GetPgUpgradeData, GetPgUpgradeErrors, GetPgUpgradeLogsData, GetPgUpgradeLogsErrors, GetPgUpgradeLogsResponses, GetPgUpgradeResponses, GetPipelineStatsData, GetPipelineStatsErrors, GetPipelineStatsResponses, GetPlatformInfoData, GetPlatformInfoErrors, GetPlatformInfoResponses, GetPostgresWalHealthData, GetPostgresWalHealthErrors, GetPostgresWalHealthResponses, GetPreferencesData, GetPreferencesErrors, GetPreferencesResponses, GetPreviewGatewayLogsData, GetPreviewGatewayLogsResponses, GetPreviewGatewaySettingsData, GetPreviewGatewaySettingsResponses, GetPreviewGatewayStatusData, GetPreviewGatewayStatusResponses, GetPricingData, GetPricingErrors, GetPricingResponses, GetPrivateIpData, GetPrivateIpErrors, GetPrivateIpResponses, GetProjectAlarmsSummaryData, GetProjectAlarmsSummaryErrors, GetProjectAlarmsSummaryResponses, GetProjectBySlugData, GetProjectBySlugErrors, GetProjectBySlugResponses, GetProjectData, GetProjectDeploymentsData, GetProjectDeploymentsErrors, GetProjectDeploymentsResponses, GetProjectErrors, GetProjectResponses, GetProjectsData, GetProjectsErrors, GetProjectServiceEnvironmentVariablesData, GetProjectServiceEnvironmentVariablesErrors, GetProjectServiceEnvironmentVariablesResponses, GetProjectSessionReplaysData, GetProjectSessionReplaysErrors, GetProjectSessionReplaysResponses, GetProjectsHealthData, GetProjectsHealthErrors, GetProjectsHealthResponses, GetProjectsMonitorHealthData, GetProjectsMonitorHealthErrors, GetProjectsMonitorHealthResponses, GetProjectsResponses, GetProjectStatisticsData, GetProjectStatisticsErrors, GetProjectStatisticsResponses, GetProjectTemplateData, GetProjectTemplateErrors, GetProjectTemplateResponses, GetPropertyBreakdownData, GetPropertyBreakdownErrors, GetPropertyBreakdownResponses, GetPropertyTimelineData, GetPropertyTimelineErrors, GetPropertyTimelineResponses, GetProviderConnectionsData, GetProviderConnectionsErrors, GetProviderConnectionsResponses, GetProviderMetadataData, GetProviderMetadataErrors, GetProviderMetadataResponses, GetProvidersMetadataData, GetProvidersMetadataErrors, GetProvidersMetadataResponses, GetProxyLogByIdData, GetProxyLogByIdErrors, GetProxyLogByIdResponses, GetProxyLogByRequestIdData, GetProxyLogByRequestIdErrors, GetProxyLogByRequestIdResponses, GetProxyLogsData, GetProxyLogsErrors, GetProxyLogsResponses, GetPublicBranchesData, GetPublicBranchesErrors, GetPublicBranchesResponses, GetPublicIpData, GetPublicIpErrors, GetPublicIpResponses, GetPublicRepositoryData, GetPublicRepositoryErrors, GetPublicRepositoryResponses, GetQuotaData, GetQuotaErrors, GetQuotaResponses, GetRecentActivityData, GetRecentActivityErrors, GetRecentActivityResponses, GetRemoteExternalImageData, GetRemoteExternalImageErrors, GetRemoteExternalImageResponses, GetRepositoryBranchesData, GetRepositoryBranchesErrors, GetRepositoryBranchesResponses, GetRepositoryByIdData, GetRepositoryByIdErrors, GetRepositoryByIdResponses, GetRepositoryByNameData, GetRepositoryByNameErrors, GetRepositoryByNameResponses, GetRepositoryPresetByNameData, GetRepositoryPresetByNameErrors, GetRepositoryPresetByNameResponses, GetRepositoryPresetLiveData, GetRepositoryPresetLiveErrors, GetRepositoryPresetLiveResponses, GetRepositoryTagsData, GetRepositoryTagsErrors, GetRepositoryTagsResponses, GetResolvedEnvironmentVariablesData, GetResolvedEnvironmentVariablesErrors, GetResolvedEnvironmentVariablesResponses, GetResolvedEnvironmentVariableValueData, GetResolvedEnvironmentVariableValueErrors, GetResolvedEnvironmentVariableValueResponses, GetRestoreCapabilitiesData, GetRestoreCapabilitiesErrors, GetRestoreCapabilitiesResponses, GetRestoreRunData, GetRestoreRunErrors, GetRestoreRunResponses, GetRouteData, GetRouteErrors, GetRouteResponses, GetRunData, GetRunErrors, GetRunResponses, GetRunWithLogsData, GetRunWithLogsErrors, GetRunWithLogsResponses, GetS3CredentialsData, GetS3CredentialsErrors, GetS3CredentialsResponses, GetS3SourceData, GetS3SourceErrors, GetS3SourceResponses, GetSandboxData, GetSandboxErrors, GetSandboxResponses, GetSandboxStatusData, GetSandboxStatusErrors, GetSandboxStatusResponses, GetScanByDeploymentData, GetScanByDeploymentErrors, GetScanByDeploymentResponses, GetScanData, GetScanErrors, GetScanResponses, GetScanVulnerabilitiesData, GetScanVulnerabilitiesErrors, GetScanVulnerabilitiesResponses, GetServiceBySlugData, GetServiceBySlugErrors, GetServiceBySlugResponses, GetServiceData, GetServiceEnvironmentVariableData, GetServiceEnvironmentVariableErrors, GetServiceEnvironmentVariableResponses, GetServiceEnvironmentVariablesData, GetServiceEnvironmentVariablesErrors, GetServiceEnvironmentVariablesResponses, GetServiceErrors, GetServiceHealthStatusData, GetServiceHealthStatusErrors, GetServiceHealthStatusResponses, GetServicePreviewEnvironmentVariableNamesData, GetServicePreviewEnvironmentVariableNamesErrors, GetServicePreviewEnvironmentVariableNamesResponses, GetServicePreviewEnvironmentVariablesMaskedData, GetServicePreviewEnvironmentVariablesMaskedErrors, GetServicePreviewEnvironmentVariablesMaskedResponses, GetServiceResponses, GetServiceRuntimeData, GetServiceRuntimeErrors, GetServiceRuntimeResponses, GetServiceStatsData, GetServiceStatsErrors, GetServiceStatsResponses, GetServiceTypeParametersData, GetServiceTypeParametersErrors, GetServiceTypeParametersResponses, GetServiceTypesData, GetServiceTypesErrors, GetServiceTypesResponses, GetSessionDetailsData, GetSessionDetailsErrors, GetSessionDetailsResponses, GetSessionEventsData, GetSessionEventsErrors, GetSessionEventsResponses, GetSessionLogsData, GetSessionLogsErrors, GetSessionLogsResponses, GetSessionReplayData, GetSessionReplayErrors, GetSessionReplayEventsData, GetSessionReplayEventsErrors, GetSessionReplayEventsResponses, GetSessionReplayResponses, GetSettingsData, GetSettingsErrors, GetSettingsResponses, GetSkillData, GetSkillErrors, GetSkillResponses, GetSlowQueriesData, GetSlowQueriesErrors, GetSlowQueriesResponses, GetStaticBundleData, GetStaticBundleErrors, GetStaticBundleResponses, GetStatusOverviewData, GetStatusOverviewErrors, GetStatusOverviewResponses, GetTagsByRepositoryIdData, GetTagsByRepositoryIdErrors, GetTagsByRepositoryIdResponses, GetTeamData, GetTeamErrors, GetTeamResponses, GetTimeBucketStatsData, GetTimeBucketStatsErrors, GetTimeBucketStatsResponses, GetTodayStatsData, GetTodayStatsErrors, GetTodayStatsResponses, GetTraceData, GetTraceErrors, GetTraceResponses, GetUnifiedTraceData, GetUnifiedTraceErrors, GetUnifiedTraceResponses, GetUniqueCountsData, GetUniqueCountsErrors, GetUniqueCountsResponses, GetUniqueEventsData, GetUniqueEventsErrors, GetUniqueEventsResponses, GetUpdateStatusData, GetUpdateStatusErrors, GetUpdateStatusResponses, GetUptimeHistoryData, GetUptimeHistoryErrors, GetUptimeHistoryResponses, GetUsageByProviderData, GetUsageByProviderErrors, GetUsageByProviderResponses, GetUsageRecentData, GetUsageRecentErrors, GetUsageRecentResponses, GetUsageSummaryData, GetUsageSummaryErrors, GetUsageSummaryResponses, GetUsageTimeseriesData, GetUsageTimeseriesErrors, GetUsageTimeseriesResponses, GetUsageTopModelsData, GetUsageTopModelsErrors, GetUsageTopModelsResponses, GetVisitorByGuidData, GetVisitorByGuidErrors, GetVisitorByGuidResponses, GetVisitorByIdData, GetVisitorByIdErrors, GetVisitorByIdResponses, GetVisitorDetailsData, GetVisitorDetailsErrors, GetVisitorDetailsResponses, GetVisitorFacetsData, GetVisitorFacetsErrors, GetVisitorFacetsResponses, GetVisitorInfoData, GetVisitorInfoErrors, GetVisitorInfoResponses, GetVisitorJourneyData, GetVisitorJourneyErrors, GetVisitorJourneyResponses, GetVisitorsData, GetVisitorsErrors, GetVisitorSessionsData, GetVisitorSessionsErrors, GetVisitorSessionsResponses, GetVisitorsResponses, GetVisitorStatsData, GetVisitorStatsErrors, GetVisitorStatsResponses, GetWebhookData, GetWebhookErrors, GetWebhookResponses, GrantProjectAccessData, GrantProjectAccessErrors, GrantProjectAccessResponses, HandleGitProviderOauthCallbackData, HandleGitProviderOauthCallbackErrors, HasAnalyticsEventsData, HasAnalyticsEventsErrors, HasAnalyticsEventsResponses, HasErrorGroupsData, HasErrorGroupsErrors, HasErrorGroupsResponses, HasPerformanceMetricsData, HasPerformanceMetricsErrors, HasPerformanceMetricsResponses, ImportExternalServiceData, ImportExternalServiceErrors, ImportExternalServiceResponses, IngestLogsByPathData, IngestLogsByPathErrors, IngestLogsByPathResponses, IngestLogsData, IngestLogsErrors, IngestLogsResponses, IngestMetricsByPathData, IngestMetricsByPathErrors, IngestMetricsByPathResponses, IngestMetricsData, IngestMetricsErrors, IngestMetricsResponses, IngestSentryEnvelopeData, IngestSentryEnvelopeErrors, IngestSentryEnvelopeResponses, IngestSentryEventData, IngestSentryEventErrors, IngestSentryEventResponses, IngestTracesByPathData, IngestTracesByPathErrors, IngestTracesByPathResponses, IngestTracesData, IngestTracesErrors, IngestTracesResponses, InitSessionReplayData, InitSessionReplayErrors, InitSessionReplayResponses, JobLogsData, JobLogsErrors, JobLogsResponses, JobStatusData, JobStatusErrors, JobStatusResponses, KillJobData, KillJobErrors, KillJobResponses, KvDelData, KvDelErrors, KvDelResponses, KvDisableData, KvDisableErrors, KvDisableResponses, KvEnableData, KvEnableErrors, KvEnableResponses, KvExpireData, KvExpireErrors, KvExpireResponses, KvGetData, KvGetErrors, KvGetResponses, KvIncrData, KvIncrErrors, KvIncrResponses, KvKeysData, KvKeysErrors, KvKeysResponses, KvSetData, KvSetErrors, KvSetResponses, KvStatusData, KvStatusErrors, KvStatusResponses, KvTtlData, KvTtlErrors, KvTtlResponses, KvUpdateData, KvUpdateErrors, KvUpdateResponses, LatestRunForSourceData, LatestRunForSourceErrors, LatestRunForSourceResponses, LinkCustomDomainToCertificateData, LinkCustomDomainToCertificateErrors, LinkCustomDomainToCertificateResponses, LinkServiceToProjectData, LinkServiceToProjectErrors, LinkServiceToProjectResponses, ListAgentRunsData, ListAgentRunsErrors, ListAgentRunsResponses, ListAgentsData, ListAgentsErrors, ListAgentsResponses, ListAiProvidersData, ListAiProvidersErrors, ListAiProvidersResponses, ListAlertRulesData, ListAlertRulesErrors, ListAlertRulesResponses, ListAlertsData, ListAlertsErrors, ListAlertsResponses, ListAllConversationsData, ListAllConversationsErrors, ListAllConversationsResponses, ListAllRunsData, ListAllRunsErrors, ListAllRunsResponses, ListApiKeysData, ListApiKeysErrors, ListApiKeysResponses, ListAuditLogsData, ListAuditLogsErrors, ListAuditLogsResponses, ListAvailableContainersData, ListAvailableContainersErrors, ListAvailableContainersResponses, ListBackupAlertsData, ListBackupAlertsErrors, ListBackupAlertsResponses, ListBackupChildrenData, ListBackupChildrenErrors, ListBackupChildrenResponses, ListBackupSchedulesData, ListBackupSchedulesErrors, ListBackupSchedulesResponses, ListBackupsForScheduleData, ListBackupsForScheduleErrors, ListBackupsForScheduleResponses, ListCommitsByRepositoryIdData, ListCommitsByRepositoryIdErrors, ListCommitsByRepositoryIdResponses, ListConnectionsData, ListConnectionsErrors, ListConnectionsResponses, ListContainersAtPathData, ListContainersAtPathErrors, ListContainersAtPathResponses, ListContainersData, ListContainersErrors, ListContainersResponses, ListConversationsData, ListConversationsErrors, ListConversationsResponses, ListCustomDomainsForProjectData, ListCustomDomainsForProjectErrors, ListCustomDomainsForProjectResponses, ListDashboardsData, ListDashboardsErrors, ListDashboardsResponses, ListDeliveriesData, ListDeliveriesErrors, ListDeliveriesResponses, ListDeploymentContainerLogsData, ListDeploymentContainerLogsErrors, ListDeploymentContainerLogsResponses, ListDeploymentTokensData, ListDeploymentTokensErrors, ListDeploymentTokensResponses, ListDnsProvidersData, ListDnsProvidersErrors, ListDnsProvidersResponses, ListDomainsData, ListDomainsErrors, ListDomainsResponses, ListDsnsData, ListDsnsErrors, ListDsnsResponses, ListEmailDomainsData, ListEmailDomainsErrors, ListEmailDomainsResponses, ListEmailProvidersData, ListEmailProvidersErrors, ListEmailProvidersResponses, ListEmailsData, ListEmailsErrors, ListEmailsResponses, ListEnrollmentTokensData, ListEnrollmentTokensErrors, ListEnrollmentTokensResponses, ListEntitiesData, ListEntitiesErrors, ListEntitiesResponses, ListErrorEventsData, ListErrorEventsErrors, ListErrorEventsResponses, ListErrorGroupsData, ListErrorGroupsErrors, ListErrorGroupsResponses, ListEventsData, ListEventsResponses, ListEventTypesData, ListEventTypesResponses, ListExternalImagesData, ListExternalImagesErrors, ListExternalImagesResponses, ListExternalPluginsData, ListExternalPluginsErrors, ListExternalPluginsResponses, ListExternalServiceBackupsData, ListExternalServiceBackupsErrors, ListExternalServiceBackupsResponses, ListFlagsData, ListFlagsErrors, ListFlagsResponses, ListFunnelsData, ListFunnelsErrors, ListFunnelsResponses, ListGitProvidersData, ListGitProvidersErrors, ListGitProvidersResponses, ListGlobalMcpsData, ListGlobalMcpsErrors, ListGlobalMcpsResponses, ListGlobalSkillsData, ListGlobalSkillsErrors, ListGlobalSkillsResponses, ListIncidentsData, ListIncidentsErrors, ListIncidentsResponses, ListInsightsData, ListInsightsErrors, ListInsightsResponses, ListIpAccessControlData, ListIpAccessControlErrors, ListIpAccessControlResponses, ListJobsData, ListJobsErrors, ListJobsResponses, ListKnownAiAgentsData, ListKnownAiAgentsErrors, ListKnownAiAgentsResponses, ListManagedDomainsData, ListManagedDomainsErrors, ListManagedDomainsResponses, ListMcpsData, ListMcpsErrors, ListMcpsResponses, ListMetricLabelKeysData, ListMetricLabelKeysErrors, ListMetricLabelKeysResponses, ListMetricLabelValuesData, ListMetricLabelValuesErrors, ListMetricLabelValuesResponses, ListMetricNamesData, ListMetricNamesErrors, ListMetricNamesResponses, ListModelsData, ListModelsErrors, ListModelsResponses, ListMonitorsData, ListMonitorsErrors, ListMonitorsResponses, ListNotificationProvidersData, ListNotificationProvidersErrors, ListNotificationProvidersResponses, ListOidcProvidersData, ListOidcProvidersResponses, ListOidcProviderUsersData, ListOidcProviderUsersErrors, ListOidcProviderUsersResponses, ListOidcRoleMappingsData, ListOidcRoleMappingsResponses, ListOnDemandCertsData, ListOnDemandCertsErrors, ListOnDemandCertsResponses, ListOrdersData, ListOrdersErrors, ListOrdersResponses, ListPeersData, ListPeersErrors, ListPeersResponses, ListPendingActionsData, ListPendingActionsErrors, ListPendingActionsResponses, ListPgUpgradesData, ListPgUpgradesErrors, ListPgUpgradesResponses, ListPresetsData, ListPresetsErrors, ListPresetsResponses, ListProjectAccessData, ListProjectAccessErrors, ListProjectAccessResponses, ListProjectAlarmsData, ListProjectAlarmsErrors, ListProjectAlarmsResponses, ListProjectScansData, ListProjectScansErrors, ListProjectScansResponses, ListProjectSecretsData, ListProjectSecretsErrors, ListProjectSecretsResponses, ListProjectServicesData, ListProjectServicesErrors, ListProjectServicesResponses, ListProjectTemplatesData, ListProjectTemplatesErrors, ListProjectTemplatesResponses, ListProjectTemplateTagsData, ListProjectTemplateTagsErrors, ListProjectTemplateTagsResponses, ListProviderKeysData, ListProviderKeysErrors, ListProviderKeysResponses, ListProviderZonesData, ListProviderZonesErrors, ListProviderZonesResponses, ListPublicProvidersData, ListPublicProvidersResponses, ListReleaseFilesData, ListReleaseFilesErrors, ListReleaseFilesResponses, ListReleasesData, ListReleasesErrors, ListReleasesResponses, ListRemoteExternalImagesData, ListRemoteExternalImagesErrors, ListRemoteExternalImagesResponses, ListRepositoriesByConnectionData, ListRepositoriesByConnectionErrors, ListRepositoriesByConnectionResponses, ListRepositoriesByProviderData, ListRepositoriesByProviderErrors, ListRepositoriesByProviderResponses, ListRestoreRunsForServiceData, ListRestoreRunsForServiceResponses, ListRootContainersData, ListRootContainersErrors, ListRootContainersResponses, ListRoutesData, ListRoutesErrors, ListRoutesResponses, ListS3SourcesData, ListS3SourcesErrors, ListS3SourcesResponses, ListSandboxesData, ListSandboxesResponses, ListScheduleRunJobsData, ListScheduleRunJobsErrors, ListScheduleRunJobsResponses, ListScheduleRunsData, ListScheduleRunsErrors, ListScheduleRunsResponses, ListScheduleServicesData, ListScheduleServicesErrors, ListScheduleServicesResponses, ListSecretsData, ListSecretsErrors, ListSecretsResponses, ListServiceHealthStatusesData, ListServiceHealthStatusesErrors, ListServiceHealthStatusesResponses, ListServiceProjectsData, ListServiceProjectsErrors, ListServiceProjectsResponses, ListServiceSchedulesData, ListServiceSchedulesErrors, ListServiceSchedulesResponses, ListServicesData, ListServicesErrors, ListServicesResponses, ListSkillsData, ListSkillsErrors, ListSkillsResponses, ListSourceBackupsData, ListSourceBackupsErrors, ListSourceBackupsResponses, ListSourceFilesData, ListSourceFilesErrors, ListSourceFilesResponses, ListSourceMapsData, ListSourceMapsErrors, ListSourceMapsResponses, ListSourcesData, ListSourcesErrors, ListSourcesResponses, ListStaticBundlesData, ListStaticBundlesErrors, ListStaticBundlesResponses, ListSyncedRepositoriesData, ListSyncedRepositoriesErrors, ListSyncedRepositoriesResponses, ListTeamMembersData, ListTeamMembersErrors, ListTeamMembersResponses, ListTeamProjectsData, ListTeamProjectsErrors, ListTeamProjectsResponses, ListTeamsData, ListTeamsErrors, ListTeamsResponses, ListUsersData, ListUsersErrors, ListUsersResponses, ListWebhooksData, ListWebhooksErrors, ListWebhooksResponses, LoginData, LoginErrors, LoginResponses, LogoutData, LogoutErrors, LogoutResponses, LookupDnsARecordsData, LookupDnsARecordsErrors, LookupDnsARecordsResponses, MintEnrollmentTokenData, MintEnrollmentTokenErrors, MintEnrollmentTokenResponses, MkdirData, MkdirErrors, MkdirResponses, NodeHeartbeatData, NodeHeartbeatErrors, NodeHeartbeatResponses, NodeMetricsGetRangeData, NodeMetricsGetRangeErrors, NodeMetricsGetRangeResponses, ObservabilityFullEventData, ObservabilityFullEventErrors, ObservabilityFullEventResponses, ObservabilityListEventsData, ObservabilityListEventsErrors, ObservabilityListEventsResponses, OidcCallbackData, PatchAdminGateData, PatchAdminGateErrors, PatchAdminGateResponses, PatchPreviewGatewaySettingsData, PatchPreviewGatewaySettingsResponses, PauseDeploymentData, PauseDeploymentErrors, PauseDeploymentResponses, PauseSandboxData, PauseSandboxErrors, PauseSandboxResponses, PlanRestoreData, PlanRestoreErrors, PlanRestoreResponses, PostDnsAckData, PostDnsAckErrors, PostDnsAckResponses, PreviewAlertData, PreviewAlertErrors, PreviewAlertResponses, PreviewFunnelMetricsData, PreviewFunnelMetricsErrors, PreviewFunnelMetricsResponses, PreviewHostnameModeData, PreviewHostnameModeErrors, PreviewHostnameModeResponses, PromoteClusterMemberData, PromoteClusterMemberErrors, PromoteClusterMemberResponses, PromoteDeploymentData, PromoteDeploymentErrors, PromoteDeploymentResponses, ProvisionDomainData, ProvisionDomainErrors, ProvisionDomainResponses, PurgeProjectLogsData, PurgeProjectLogsErrors, PurgeProjectLogsResponses, PushExternalImageData, PushExternalImageErrors, PushExternalImageResponses, QueryDataData, QueryDataErrors, QueryDataResponses, QueryGenaiTracesData, QueryGenaiTracesErrors, QueryGenaiTracesResponses, QueryLogsData, QueryLogsErrors, QueryLogsResponses, QueryMetricsData, QueryMetricsErrors, QueryMetricsResponses, QueryTracesData, QueryTracesErrors, QueryTracesResponses, QueryTraceSummariesData, QueryTraceSummariesErrors, QueryTraceSummariesResponses, ReadFileData, ReadFileErrors, ReadFileResponses, ReAnalyzeData, ReAnalyzeErrors, ReAnalyzeResponses, RebuildSandboxImageData, RebuildSandboxImageErrors, RebuildSandboxImageResponses, RecordConsoleEventData, RecordConsoleEventErrors, RecordConsoleEventResponses, RecordEventMetricsData, RecordEventMetricsErrors, RecordEventMetricsResponses, RecordFlagExposureData, RecordFlagExposureErrors, RecordFlagExposureResponses, RecordSpeedMetricsData, RecordSpeedMetricsErrors, RecordSpeedMetricsResponses, RefreshRouteTableData, RefreshRouteTableErrors, RefreshRouteTableResponses, RegenerateDsnData, RegenerateDsnErrors, RegenerateDsnResponses, RegisterExternalImageData, RegisterExternalImageErrors, RegisterExternalImageResponses, RegisterNodeData, RegisterNodeErrors, RegisterNodeResponses, ReinstallGitlabWebhookData, ReinstallGitlabWebhookErrors, ReinstallGitlabWebhookResponses, RejectPendingActionData, RejectPendingActionErrors, RejectPendingActionResponses, ReloadPluginsData, ReloadPluginsErrors, ReloadPluginsResponses, RemoveClusterMemberData, RemoveClusterMemberErrors, RemoveClusterMemberResponses, RemoveManagedDomainData, RemoveManagedDomainErrors, RemoveManagedDomainResponses, RemoveRoleData, RemoveRoleErrors, RemoveRoleResponses, RemoveTeamMemberData, RemoveTeamMemberErrors, RemoveTeamMemberResponses, RenameConversationData, RenameConversationErrors, RenameConversationResponses, RenewDomainData, RenewDomainErrors, RenewDomainResponses, RequestPasswordResetData, RequestPasswordResetErrors, RequestPasswordResetResponses, ResetPasswordData, ResetPasswordErrors, ResetPasswordResponses, ResizeSandboxData, ResizeSandboxErrors, ResizeSandboxResponses, ResolveAlarmData, ResolveAlarmErrors, ResolveAlarmResponses, RestartContainerData, RestartContainerErrors, RestartContainerResponses, RestartPreviewGatewayData, RestartPreviewGatewayResponses, RestartSandboxData, RestartSandboxErrors, RestartSandboxResponses, RestoreFlagData, RestoreFlagErrors, RestoreFlagResponses, RestoreUserData, RestoreUserErrors, RestoreUserResponses, ResumeDeploymentData, ResumeDeploymentErrors, ResumeDeploymentResponses, ResumeSandboxData, ResumeSandboxErrors, ResumeSandboxResponses, RetryClusterData, RetryClusterErrors, RetryClusterResponses, RetryDeliveryData, RetryDeliveryErrors, RetryDeliveryResponses, RetryPgUpgradeData, RetryPgUpgradeErrors, RetryPgUpgradeResponses, RetryRunData, RetryRunErrors, RetryRunResponses, RevealGlobalMcpConfigData, RevealGlobalMcpConfigErrors, RevealGlobalMcpConfigResponses, RevealMcpConfigData, RevealMcpConfigErrors, RevealMcpConfigResponses, RevealNotificationProviderConfigData, RevealNotificationProviderConfigErrors, RevealNotificationProviderConfigResponses, RevealServiceParameterData, RevealServiceParameterErrors, RevealServiceParameterResponses, RevenueCreateIntegrationData, RevenueCreateIntegrationErrors, RevenueCreateIntegrationResponses, RevenueDeleteIntegrationData, RevenueDeleteIntegrationResponses, RevenueGlobalEventsData, RevenueGlobalEventsResponses, RevenueImportInvoicesCsvData, RevenueImportInvoicesCsvErrors, RevenueImportInvoicesCsvResponses, RevenueImportSubscriptionsCsvData, RevenueImportSubscriptionsCsvErrors, RevenueImportSubscriptionsCsvResponses, RevenueListIntegrationsData, RevenueListIntegrationsResponses, RevenueListProvidersData, RevenueListProvidersResponses, RevenueMetricsCustomersData, RevenueMetricsCustomersResponses, RevenueMetricsGlobalMrrData, RevenueMetricsGlobalMrrResponses, RevenueMetricsGlobalSummaryData, RevenueMetricsGlobalSummaryResponses, RevenueMetricsMrrData, RevenueMetricsMrrResponses, RevenueMetricsSummaryData, RevenueMetricsSummaryResponses, RevenueRecentEventsData, RevenueRecentEventsResponses, RevenueRotateTokenData, RevenueRotateTokenResponses, RevenueUpdateConfigData, RevenueUpdateConfigErrors, RevenueUpdateConfigResponses, RevenueUpdateSecretData, RevenueUpdateSecretErrors, RevenueUpdateSecretResponses, RevokeDsnData, RevokeDsnErrors, RevokeDsnResponses, RevokeEnrollmentTokenData, RevokeEnrollmentTokenErrors, RevokeEnrollmentTokenResponses, RevokeJoinTokenData, RevokeJoinTokenErrors, RevokeJoinTokenResponses, RevokeProjectAccessData, RevokeProjectAccessErrors, RevokeProjectAccessResponses, RollbackPgUpgradeData, RollbackPgUpgradeErrors, RollbackPgUpgradeResponses, RollbackToDeploymentData, RollbackToDeploymentErrors, RollbackToDeploymentResponses, RootfsGcData, RootfsGcResponses, RootfsReportData, RootfsReportResponses, RotateApiKeyData, RotateApiKeyErrors, RotateApiKeyResponses, RotateDeploymentTokenData, RotateDeploymentTokenErrors, RotateDeploymentTokenResponses, RunBackupForSourceData, RunBackupForSourceErrors, RunBackupForSourceResponses, RunConnectionHealthCheckData, RunConnectionHealthCheckErrors, RunConnectionHealthCheckResponses, RunExternalServiceBackupData, RunExternalServiceBackupErrors, RunExternalServiceBackupResponses, RunScheduleNowData, RunScheduleNowErrors, RunScheduleNowResponses, SandboxCreatePreviewLinkData, SandboxCreatePreviewLinkErrors, SandboxCreatePreviewLinkResponses, SaveAgentTokenData, SaveAgentTokenErrors, SaveAgentTokenResponses, SaveAiProviderCredentialData, SaveAiProviderCredentialErrors, SaveAiProviderCredentialResponses, SearchLogsData, SearchLogsErrors, SearchLogsResponses, SendEmailData, SendEmailErrors, SendEmailResponses, SendMessageData, SendMessageErrors, SendMessageResponses, SetDefaultS3SourceData, SetDefaultS3SourceErrors, SetDefaultS3SourceResponses, SetFlagEnvironmentData, SetFlagEnvironmentErrors, SetFlagEnvironmentResponses, SetPreviewPasswordData, SetPreviewPasswordErrors, SetPreviewPasswordResponses, SetupDnsChallengeData, SetupDnsChallengeErrors, SetupDnsChallengeResponses, SetupDnsData, SetupDnsErrors, SetupDnsResponses, SetupEmailTrackingData, SetupEmailTrackingErrors, SetupEmailTrackingResponses, SetupMfaData, SetupMfaErrors, SetupMfaResponses, SleepEnvironmentData, SleepEnvironmentErrors, SleepEnvironmentResponses, SmokeTestAgentData, SmokeTestAgentErrors, SmokeTestAgentResponses, SourceSandboxData, SourceSandboxErrors, SourceSandboxResponses, StartAnalysisData, StartAnalysisErrors, StartAnalysisResponses, StartContainerData, StartContainerErrors, StartContainerResponses, StartFixData, StartFixErrors, StartFixResponses, StartGitProviderOauthData, StartGitProviderOauthErrors, StartOidcLoginBySlugData, StartOidcLoginBySlugErrors, StartPgUpgradeData, StartPgUpgradeErrors, StartPgUpgradeResponses, StartRestoreData, StartRestoreErrors, StartRestoreResponses, StartServiceData, StartServiceErrors, StartServiceResponses, StatPathData, StatPathErrors, StatPathResponses, StopContainerData, StopContainerErrors, StopContainerResponses, StopSandboxData, StopSandboxErrors, StopSandboxResponses, StopServiceData, StopServiceErrors, StopServiceResponses, StreamContainerMetricsData, StreamContainerMetricsErrors, StreamContainerMetricsResponses, StreamEventsData, StreamEventsErrors, StreamEventsResponses, StreamRunEventsData, StreamRunEventsErrors, StreamRunEventsResponses, SyncRepositoriesData, SyncRepositoriesErrors, SyncRepositoriesResponses, TailDeploymentJobLogsData, TailDeploymentJobLogsErrors, TailLogsData, TailLogsErrors, TailLogsResponses, TeardownDeploymentData, TeardownDeploymentErrors, TeardownDeploymentResponses, TeardownEnvironmentData, TeardownEnvironmentErrors, TeardownEnvironmentResponses, TestNotificationProviderData, TestNotificationProviderErrors, TestNotificationProviderResponses, TestOidcProviderData, TestOidcProviderResponses, TestProviderConnectionData, TestProviderConnectionErrors, TestProviderConnectionResponses, TestProviderData, TestProviderErrors, TestProviderKeyByIdData, TestProviderKeyByIdErrors, TestProviderKeyByIdResponses, TestProviderKeyInlineData, TestProviderKeyInlineErrors, TestProviderKeyInlineResponses, TestProviderResponses, TestS3ConnectionPreviewData, TestS3ConnectionPreviewErrors, TestS3ConnectionPreviewResponses, TestS3SourceConnectionData, TestS3SourceConnectionErrors, TestS3SourceConnectionResponses, TrackClickData, TrackClickErrors, TrackOpenData, TrackOpenErrors, TrackOpenResponses, TriggerAgentData, TriggerAgentErrors, TriggerAgentResponses, TriggerProjectPipelineData, TriggerProjectPipelineErrors, TriggerProjectPipelineResponses, TriggerScanData, TriggerScanErrors, TriggerScanResponses, TriggerServiceHealthCheckData, TriggerServiceHealthCheckErrors, TriggerServiceHealthCheckResponses, TriggerWeeklyDigestData, TriggerWeeklyDigestErrors, TriggerWeeklyDigestResponses, UnlinkServiceFromProjectData, UnlinkServiceFromProjectErrors, UnlinkServiceFromProjectResponses, UpdateAgentData, UpdateAgentErrors, UpdateAgentResponses, UpdateAiProviderData, UpdateAiProviderErrors, UpdateAiProviderResponses, UpdateAlertData, UpdateAlertErrors, UpdateAlertResponses, UpdateAlertRuleData, UpdateAlertRuleErrors, UpdateAlertRuleResponses, UpdateApiKeyData, UpdateApiKeyErrors, UpdateApiKeyResponses, UpdateAutomaticDeployData, UpdateAutomaticDeployErrors, UpdateAutomaticDeployResponses, UpdateBackupScheduleData, UpdateBackupScheduleErrors, UpdateBackupScheduleResponses, UpdateCloudflareProviderData, UpdateCloudflareProviderErrors, UpdateCloudflareProviderResponses, UpdateConnectionTokenData, UpdateConnectionTokenErrors, UpdateConnectionTokenResponses, UpdateCustomDomainData, UpdateCustomDomainErrors, UpdateCustomDomainResponses, UpdateDashboardData, UpdateDashboardErrors, UpdateDashboardResponses, UpdateDeploymentTokenData, UpdateDeploymentTokenErrors, UpdateDeploymentTokenResponses, UpdateEmailProviderData, UpdateEmailProviderErrors, UpdateEmailProviderResponses, UpdateEnvironmentSettingsData, UpdateEnvironmentSettingsErrors, UpdateEnvironmentSettingsResponses, UpdateEnvironmentSubdomainData, UpdateEnvironmentSubdomainErrors, UpdateEnvironmentSubdomainResponses, UpdateEnvironmentVariableData, UpdateEnvironmentVariableErrors, UpdateEnvironmentVariableResponses, UpdateErrorGroupData, UpdateErrorGroupErrors, UpdateErrorGroupResponses, UpdateFlagData, UpdateFlagErrors, UpdateFlagResponses, UpdateFunnelData, UpdateFunnelErrors, UpdateFunnelResponses, UpdateGitProviderCredentialsData, UpdateGitProviderCredentialsErrors, UpdateGitProviderCredentialsResponses, UpdateGitSettingsData, UpdateGitSettingsErrors, UpdateGitSettingsResponses, UpdateGlobalMcpData, UpdateGlobalMcpErrors, UpdateGlobalMcpResponses, UpdateGlobalSkillData, UpdateGlobalSkillErrors, UpdateGlobalSkillResponses, UpdateIncidentStatusData, UpdateIncidentStatusErrors, UpdateIncidentStatusResponses, UpdateIpAccessControlData, UpdateIpAccessControlErrors, UpdateIpAccessControlResponses, UpdateManagedDomainData, UpdateManagedDomainErrors, UpdateManagedDomainResponses, UpdateMcpData, UpdateMcpErrors, UpdateMcpResponses, UpdateNotificationEmailProviderData, UpdateNotificationEmailProviderErrors, UpdateNotificationEmailProviderResponses, UpdateNotificationProviderData, UpdateNotificationProviderErrors, UpdateNotificationProviderResponses, UpdateOidcProviderData, UpdateOidcProviderResponses, UpdatePreferencesData, UpdatePreferencesErrors, UpdatePreferencesResponses, UpdateProjectData, UpdateProjectDeploymentConfigData, UpdateProjectDeploymentConfigErrors, UpdateProjectDeploymentConfigResponses, UpdateProjectErrors, UpdateProjectResponses, UpdateProjectSecretData, UpdateProjectSecretErrors, UpdateProjectSecretResponses, UpdateProjectSettingsData, UpdateProjectSettingsErrors, UpdateProjectSettingsResponses, UpdateProviderData, UpdateProviderErrors, UpdateProviderKeyData, UpdateProviderKeyErrors, UpdateProviderKeyResponses, UpdateProviderResponses, UpdateRouteData, UpdateRouteErrors, UpdateRouteResponses, UpdateS3SourceData, UpdateS3SourceErrors, UpdateS3SourceResponses, UpdateSelfData, UpdateSelfErrors, UpdateSelfResponses, UpdateServiceData, UpdateServiceErrors, UpdateServiceResourcesData, UpdateServiceResourcesErrors, UpdateServiceResourcesResponses, UpdateServiceResponses, UpdateSessionDurationData, UpdateSessionDurationErrors, UpdateSessionDurationResponses, UpdateSettingsData, UpdateSettingsErrors, UpdateSettingsResponses, UpdateSkillData, UpdateSkillErrors, UpdateSkillResponses, UpdateSlackProviderData, UpdateSlackProviderErrors, UpdateSlackProviderResponses, UpdateSpeedMetricsData, UpdateSpeedMetricsErrors, UpdateSpeedMetricsResponses, UpdateTeamData, UpdateTeamErrors, UpdateTeamMemberRoleData, UpdateTeamMemberRoleErrors, UpdateTeamMemberRoleResponses, UpdateTeamResponses, UpdateUserData, UpdateUserErrors, UpdateUserResponses, UpdateWebhookData, UpdateWebhookErrors, UpdateWebhookProviderData, UpdateWebhookProviderErrors, UpdateWebhookProviderResponses, UpdateWebhookResponses, UpgradePreviewGatewayData, UpgradePreviewGatewayResponses, UpgradeServiceData, UpgradeServiceErrors, UpgradeServiceResponses, UploadGlobalSkillData, UploadGlobalSkillErrors, UploadGlobalSkillResponses, UploadReleaseFileData, UploadReleaseFileErrors, UploadReleaseFileResponses, UploadSkillData, UploadSkillErrors, UploadSkillResponses, UploadSourceFileData, UploadSourceFileErrors, UploadSourceFileResponses, UploadSourceMapData, UploadSourceMapErrors, UploadSourceMapResponses, UploadStaticBundleData, UploadStaticBundleErrors, UploadStaticBundleResponses, UpsertSecretData, UpsertSecretErrors, UpsertSecretResponses, ValidateConnectionData, ValidateConnectionErrors, ValidateConnectionResponses, ValidateEmailData, ValidateEmailErrors, ValidateEmailResponses, VerifyAndEnableMfaData, VerifyAndEnableMfaErrors, VerifyAndEnableMfaResponses, VerifyDomainData, VerifyDomainErrors, VerifyDomainResponses, VerifyEmailData, VerifyEmailErrors, VerifyEmailResponses, VerifyManagedDomainData, VerifyManagedDomainErrors, VerifyManagedDomainResponses, VerifyMfaChallengeData, VerifyMfaChallengeErrors, VerifyMfaChallengeResponses, VerifyStepUpData, VerifyStepUpErrors, VerifyStepUpResponses, WakeEnvironmentData, WakeEnvironmentErrors, WakeEnvironmentResponses, WebhookTriggerData, WebhookTriggerErrors, WebhookTriggerResponses, WorkflowDryRunData, WorkflowDryRunErrors, WorkflowDryRunResponses, WriteFileData, WriteFileErrors, WriteFileResponses, WriteFilesData, WriteFilesErrors, WriteFilesResponses } from './types.gen'; +import type { AcknowledgeAlarmData, AcknowledgeAlarmErrors, AcknowledgeAlarmResponses, ActivateAiProviderData, ActivateAiProviderErrors, ActivateAiProviderResponses, ActivateApiKeyData, ActivateApiKeyErrors, ActivateApiKeyResponses, ActivateConnectionData, ActivateConnectionErrors, ActivateConnectionResponses, ActivateProviderData, ActivateProviderErrors, ActivateProviderResponses, AddClusterMemberData, AddClusterMemberErrors, AddClusterMemberResponses, AddContextData, AddContextErrors, AddContextResponses, AddEnvironmentDomainData, AddEnvironmentDomainErrors, AddEnvironmentDomainResponses, AddEventsData, AddEventsErrors, AddEventsResponses, AddManagedDomainData, AddManagedDomainErrors, AddManagedDomainResponses, AddSessionReplayEventsData, AddSessionReplayEventsErrors, AddSessionReplayEventsResponses, AddTeamMemberData, AddTeamMemberErrors, AddTeamMemberResponses, AdminDrainNodeData, AdminDrainNodeErrors, AdminDrainNodeResponses, AdminDrainStatusData, AdminDrainStatusErrors, AdminDrainStatusResponses, AdminGetNodeData, AdminGetNodeErrors, AdminGetNodeResponses, AdminListNodeContainersData, AdminListNodeContainersErrors, AdminListNodeContainersResponses, AdminListNodesData, AdminListNodesErrors, AdminListNodesResponses, AdminRemoveNodeData, AdminRemoveNodeErrors, AdminRemoveNodeResponses, AdminUndrainNodeData, AdminUndrainNodeErrors, AdminUndrainNodeResponses, ApplyHostnameModeData, ApplyHostnameModeErrors, ApplyHostnameModeResponses, ArchiveConversationData, ArchiveConversationErrors, ArchiveConversationResponses, ArchiveFlagData, ArchiveFlagErrors, ArchiveFlagResponses, AssignRoleData, AssignRoleErrors, AssignRoleResponses, AttachScheduleServicesData, AttachScheduleServicesErrors, AttachScheduleServicesResponses, BlobCopyData, BlobCopyErrors, BlobCopyResponses, BlobDeleteData, BlobDeleteErrors, BlobDeleteResponses, BlobDisableData, BlobDisableErrors, BlobDisableResponses, BlobDownloadData, BlobDownloadErrors, BlobDownloadResponses, BlobEnableData, BlobEnableErrors, BlobEnableResponses, BlobHeadData, BlobHeadErrors, BlobHeadResponses, BlobListData, BlobListErrors, BlobListResponses, BlobPutData, BlobPutErrors, BlobPutResponses, BlobStatusData, BlobStatusErrors, BlobStatusResponses, BlobUpdateData, BlobUpdateErrors, BlobUpdateResponses, CancelBackupData, CancelBackupErrors, CancelBackupResponses, CancelData, CancelDeploymentData, CancelDeploymentErrors, CancelDeploymentResponses, CancelDomainOrderData, CancelDomainOrderErrors, CancelDomainOrderResponses, CancelErrors, CancelPgUpgradeData, CancelPgUpgradeErrors, CancelPgUpgradeResponses, CancelResponses, CancelRunData, CancelRunErrors, CancelRunResponses, CancelScheduleRunData, CancelScheduleRunErrors, CancelScheduleRunResponses, ChangePasswordSelfData, ChangePasswordSelfErrors, ChangePasswordSelfResponses, ChangeProjectSourceData, ChangeProjectSourceErrors, ChangeProjectSourceResponses, ChatCompletionsData, ChatCompletionsErrors, ChatCompletionsResponses, CheckAnalyticsHasEventsData, CheckAnalyticsHasEventsErrors, CheckAnalyticsHasEventsResponses, CheckCommitExistsData, CheckCommitExistsErrors, CheckCommitExistsResponses, CheckDomainStatusData, CheckDomainStatusErrors, CheckDomainStatusResponses, CheckExplorerSupportData, CheckExplorerSupportErrors, CheckExplorerSupportResponses, CheckIpBlockedData, CheckIpBlockedErrors, CheckIpBlockedResponses, CheckProviderDeletionSafetyData, CheckProviderDeletionSafetyErrors, CheckProviderDeletionSafetyResponses, ChunkUploadOptionsData, ChunkUploadOptionsResponses, CleanupExpiredBackupsData, CleanupExpiredBackupsErrors, CleanupExpiredBackupsResponses, ClearPreviewPasswordData, ClearPreviewPasswordErrors, ClearPreviewPasswordResponses, CliDeviceApproveData, CliDeviceApproveErrors, CliDeviceApproveResponses, CliDeviceDenyData, CliDeviceDenyErrors, CliDeviceDenyResponses, CliDeviceLookupData, CliDeviceLookupErrors, CliDeviceLookupResponses, CliDevicePollData, CliDevicePollErrors, CliDevicePollResponses, CliDeviceStartData, CliDeviceStartErrors, CliDeviceStartResponses, CliLogoutData, CliLogoutErrors, CliLogoutResponses, CmdData, CmdErrors, CmdKillData, CmdKillErrors, CmdKillResponses, CmdLogsData, CmdLogsErrors, CmdLogsResponses, CmdResponses, ConfirmPendingActionData, ConfirmPendingActionErrors, ConfirmPendingActionResponses, ContainerMetricsGetHistoryData, ContainerMetricsGetHistoryErrors, ContainerMetricsGetHistoryResponses, CreateAgentData, CreateAgentErrors, CreateAgentResponses, CreateAlertData, CreateAlertErrors, CreateAlertResponses, CreateAlertRuleData, CreateAlertRuleErrors, CreateAlertRuleResponses, CreateApiKeyData, CreateApiKeyErrors, CreateApiKeyResponses, CreateBackupScheduleData, CreateBackupScheduleErrors, CreateBackupScheduleResponses, CreateBitbucketProviderData, CreateBitbucketProviderErrors, CreateBitbucketProviderResponses, CreateCloudflareProviderData, CreateCloudflareProviderErrors, CreateCloudflareProviderResponses, CreateConversationData, CreateConversationErrors, CreateConversationResponses, CreateCustomDomainData, CreateCustomDomainErrors, CreateCustomDomainResponses, CreateDashboardData, CreateDashboardErrors, CreateDashboardResponses, CreateDeploymentTokenData, CreateDeploymentTokenErrors, CreateDeploymentTokenResponses, CreateDnsProviderData, CreateDnsProviderErrors, CreateDnsProviderResponses, CreateDomainData, CreateDomainErrors, CreateDomainResponses, CreateDsnData, CreateDsnErrors, CreateDsnResponses, CreateEmailDomainData, CreateEmailDomainErrors, CreateEmailDomainResponses, CreateEmailProviderData, CreateEmailProviderErrors, CreateEmailProviderResponses, CreateEnvironmentData, CreateEnvironmentErrors, CreateEnvironmentResponses, CreateEnvironmentVariableData, CreateEnvironmentVariableErrors, CreateEnvironmentVariableResponses, CreateFlagData, CreateFlagErrors, CreateFlagResponses, CreateFunnelData, CreateFunnelErrors, CreateFunnelResponses, CreateGenericProviderData, CreateGenericProviderErrors, CreateGenericProviderResponses, CreateGiteaPatProviderData, CreateGiteaPatProviderErrors, CreateGiteaPatProviderResponses, CreateGithubPatProviderData, CreateGithubPatProviderErrors, CreateGithubPatProviderResponses, CreateGitlabOauthProviderData, CreateGitlabOauthProviderErrors, CreateGitlabOauthProviderResponses, CreateGitlabPatProviderData, CreateGitlabPatProviderErrors, CreateGitlabPatProviderResponses, CreateGitProviderData, CreateGitProviderErrors, CreateGitProviderResponses, CreateGlobalMcpData, CreateGlobalMcpErrors, CreateGlobalMcpResponses, CreateGlobalSkillData, CreateGlobalSkillErrors, CreateGlobalSkillResponses, CreateIncidentData, CreateIncidentErrors, CreateIncidentResponses, CreateIpAccessControlData, CreateIpAccessControlErrors, CreateIpAccessControlResponses, CreateMcpData, CreateMcpErrors, CreateMcpResponses, CreateMonitorData, CreateMonitorErrors, CreateMonitorResponses, CreateNotificationEmailProviderData, CreateNotificationEmailProviderErrors, CreateNotificationEmailProviderResponses, CreateNotificationProviderData, CreateNotificationProviderErrors, CreateNotificationProviderResponses, CreateOidcProviderData, CreateOidcProviderErrors, CreateOidcProviderResponses, CreateOidcRoleMappingData, CreateOidcRoleMappingResponses, CreateOrRecreateOrderData, CreateOrRecreateOrderErrors, CreateOrRecreateOrderResponses, CreatePlanData, CreatePlanErrors, CreatePlanResponses, CreatePrData, CreatePrErrors, CreateProjectData, CreateProjectErrors, CreateProjectFromTemplateData, CreateProjectFromTemplateErrors, CreateProjectFromTemplateResponses, CreateProjectReleaseData, CreateProjectReleaseErrors, CreateProjectReleaseResponses, CreateProjectResponses, CreateProjectSecretData, CreateProjectSecretErrors, CreateProjectSecretResponses, CreateProviderKeyData, CreateProviderKeyErrors, CreateProviderKeyResponses, CreatePrResponses, CreateReleaseData, CreateReleaseErrors, CreateReleaseResponses, CreateRouteData, CreateRouteErrors, CreateRouteResponses, CreateS3SourceData, CreateS3SourceErrors, CreateS3SourceResponses, CreateSandboxData, CreateSandboxErrors, CreateSandboxResponses, CreateServiceData, CreateServiceErrors, CreateServiceResponses, CreateSkillData, CreateSkillErrors, CreateSkillResponses, CreateSlackProviderData, CreateSlackProviderErrors, CreateSlackProviderResponses, CreateTeamData, CreateTeamErrors, CreateTeamResponses, CreateUserData, CreateUserErrors, CreateUserResponses, CreateWebhookData, CreateWebhookErrors, CreateWebhookProviderData, CreateWebhookProviderErrors, CreateWebhookProviderResponses, CreateWebhookResponses, DeactivateApiKeyData, DeactivateApiKeyErrors, DeactivateApiKeyResponses, DeactivateConnectionData, DeactivateConnectionErrors, DeactivateConnectionResponses, DeactivateProviderData, DeactivateProviderErrors, DeactivateProviderResponses, DeleteAgentData, DeleteAgentErrors, DeleteAgentResponses, DeleteAlertData, DeleteAlertErrors, DeleteAlertResponses, DeleteAlertRuleData, DeleteAlertRuleErrors, DeleteAlertRuleResponses, DeleteApiKeyData, DeleteApiKeyErrors, DeleteApiKeyResponses, DeleteBackupData, DeleteBackupErrors, DeleteBackupResponses, DeleteBackupScheduleData, DeleteBackupScheduleErrors, DeleteBackupScheduleResponses, DeleteConnectionData, DeleteConnectionErrors, DeleteConnectionResponses, DeleteCustomDomainData, DeleteCustomDomainErrors, DeleteCustomDomainResponses, DeleteDashboardData, DeleteDashboardErrors, DeleteDashboardResponses, DeleteDeploymentTokenData, DeleteDeploymentTokenErrors, DeleteDeploymentTokenResponses, DeleteDnsProviderData, DeleteDnsProviderErrors, DeleteDnsProviderResponses, DeleteDomainData, DeleteDomainErrors, DeleteDomainResponses, DeleteEmailDomainData, DeleteEmailDomainErrors, DeleteEmailDomainResponses, DeleteEmailProviderData, DeleteEmailProviderErrors, DeleteEmailProviderResponses, DeleteEnvironmentData, DeleteEnvironmentDomainData, DeleteEnvironmentDomainErrors, DeleteEnvironmentDomainResponses, DeleteEnvironmentErrors, DeleteEnvironmentResponses, DeleteEnvironmentVariableData, DeleteEnvironmentVariableErrors, DeleteEnvironmentVariableResponses, DeleteExternalImageData, DeleteExternalImageErrors, DeleteExternalImageResponses, DeleteFunnelData, DeleteFunnelErrors, DeleteFunnelResponses, DeleteGitProviderData, DeleteGitProviderErrors, DeleteGitProviderResponses, DeleteGlobalMcpData, DeleteGlobalMcpErrors, DeleteGlobalMcpResponses, DeleteGlobalSkillData, DeleteGlobalSkillErrors, DeleteGlobalSkillResponses, DeleteIpAccessControlData, DeleteIpAccessControlErrors, DeleteIpAccessControlResponses, DeleteMcpData, DeleteMcpErrors, DeleteMcpResponses, DeleteMonitorData, DeleteMonitorErrors, DeleteMonitorResponses, DeleteNotificationProviderData, DeleteNotificationProviderErrors, DeleteNotificationProviderResponses, DeleteOidcProviderData, DeleteOidcProviderResponses, DeleteOidcRoleMappingData, DeleteOidcRoleMappingResponses, DeletePreferencesData, DeletePreferencesErrors, DeletePreferencesResponses, DeleteProjectData, DeleteProjectErrors, DeleteProjectResponses, DeleteProjectSecretData, DeleteProjectSecretErrors, DeleteProjectSecretResponses, DeleteProviderKeyData, DeleteProviderKeyErrors, DeleteProviderKeyResponses, DeleteProviderSafelyData, DeleteProviderSafelyErrors, DeleteProviderSafelyResponses, DeleteReleaseSourceFilesData, DeleteReleaseSourceFilesErrors, DeleteReleaseSourceFilesResponses, DeleteReleaseSourceMapsData, DeleteReleaseSourceMapsErrors, DeleteReleaseSourceMapsResponses, DeleteRouteData, DeleteRouteErrors, DeleteRouteResponses, DeleteS3SourceData, DeleteS3SourceErrors, DeleteS3SourceResponses, DeleteScanData, DeleteScanErrors, DeleteScanResponses, DeleteSecretData, DeleteSecretErrors, DeleteSecretResponses, DeleteServiceData, DeleteServiceErrors, DeleteServiceResponses, DeleteSessionReplayData, DeleteSessionReplayErrors, DeleteSessionReplayResponses, DeleteSkillData, DeleteSkillErrors, DeleteSkillResponses, DeleteSourceMapData, DeleteSourceMapErrors, DeleteSourceMapResponses, DeleteStaticBundleData, DeleteStaticBundleErrors, DeleteStaticBundleResponses, DeleteTeamData, DeleteTeamErrors, DeleteTeamResponses, DeleteUserData, DeleteUserErrors, DeleteUserResponses, DeleteWebhookData, DeleteWebhookErrors, DeleteWebhookResponses, DeployFromImageData, DeployFromImageErrors, DeployFromImageResponses, DeployFromImageUploadData, DeployFromImageUploadErrors, DeployFromImageUploadResponses, DeployFromStaticData, DeployFromStaticErrors, DeployFromStaticResponses, DeployFromUploadedSourceData, DeployFromUploadedSourceErrors, DeployFromUploadedSourceResponses, DeploymentMetricsGetLatestData, DeploymentMetricsGetLatestErrors, DeploymentMetricsGetLatestResponses, DeploymentMetricsGetRangeData, DeploymentMetricsGetRangeErrors, DeploymentMetricsGetRangeResponses, DeploymentMetricsToggleData, DeploymentMetricsToggleErrors, DeploymentMetricsToggleResponses, DestroySandboxData, DestroySandboxErrors, DestroySandboxResponses, DetachScheduleServiceData, DetachScheduleServiceErrors, DetachScheduleServiceResponses, DetectPublicPresetsData, DetectPublicPresetsErrors, DetectPublicPresetsResponses, DisableBackupScheduleData, DisableBackupScheduleErrors, DisableBackupScheduleResponses, DisableMfaData, DisableMfaErrors, DisableMfaResponses, DiscoverWorkloadsData, DiscoverWorkloadsErrors, DiscoverWorkloadsResponses, DomainData, DomainErrors, DomainResponses, DownloadGlobalSkillArchiveData, DownloadGlobalSkillArchiveErrors, DownloadGlobalSkillArchiveResponses, DownloadObjectData, DownloadObjectErrors, DownloadObjectResponses, DownloadSkillArchiveData, DownloadSkillArchiveErrors, DownloadSkillArchiveResponses, EmailStatusData, EmailStatusErrors, EmailStatusResponses, EmbeddingsData, EmbeddingsErrors, EmbeddingsResponses, EnableBackupScheduleData, EnableBackupScheduleErrors, EnableBackupScheduleResponses, EnrichVisitorData, EnrichVisitorErrors, EnrichVisitorResponses, ExecData, ExecDetachedData, ExecDetachedErrors, ExecDetachedResponses, ExecErrors, ExecResponses, ExecuteDeploymentOperationData, ExecuteDeploymentOperationErrors, ExecuteDeploymentOperationResponses, ExecuteImportData, ExecuteImportErrors, ExecuteImportResponses, ExtendTimeoutData, ExtendTimeoutErrors, ExtendTimeoutResponses, ExternalServiceEnablePgStatStatementsData, ExternalServiceEnablePgStatStatementsErrors, ExternalServiceEnablePgStatStatementsResponses, ExternalServiceMetricsByDatabaseData, ExternalServiceMetricsByDatabaseErrors, ExternalServiceMetricsByDatabaseResponses, ExternalServiceMetricsCreateAlertRuleData, ExternalServiceMetricsCreateAlertRuleErrors, ExternalServiceMetricsCreateAlertRuleResponses, ExternalServiceMetricsDeleteAlertRuleData, ExternalServiceMetricsDeleteAlertRuleErrors, ExternalServiceMetricsDeleteAlertRuleResponses, ExternalServiceMetricsGetAlertRulesData, ExternalServiceMetricsGetAlertRulesErrors, ExternalServiceMetricsGetAlertRulesResponses, ExternalServiceMetricsGetLatestData, ExternalServiceMetricsGetLatestErrors, ExternalServiceMetricsGetLatestResponses, ExternalServiceMetricsGetRangeData, ExternalServiceMetricsGetRangeErrors, ExternalServiceMetricsGetRangeResponses, ExternalServiceMetricsStatusData, ExternalServiceMetricsStatusErrors, ExternalServiceMetricsStatusResponses, ExternalServiceMetricsToggleData, ExternalServiceMetricsToggleErrors, ExternalServiceMetricsToggleResponses, ExternalServiceMetricsUpdateAlertRuleData, ExternalServiceMetricsUpdateAlertRuleErrors, ExternalServiceMetricsUpdateAlertRuleResponses, ExternalServiceResetPgStatStatementsData, ExternalServiceResetPgStatStatementsErrors, ExternalServiceResetPgStatStatementsResponses, FinalizeOrderData, FinalizeOrderErrors, FinalizeOrderResponses, FinalizeProjectReleaseData, FinalizeProjectReleaseErrors, FinalizeProjectReleaseResponses, FindConversationData, FindConversationErrors, FindConversationResponses, GenerateJoinTokenData, GenerateJoinTokenErrors, GenerateJoinTokenResponses, GeneratePresetDockerfileData, GeneratePresetDockerfileErrors, GeneratePresetDockerfileResponses, GetAccessInfoData, GetAccessInfoErrors, GetAccessInfoResponses, GetActiveVisitorsData, GetActiveVisitorsErrors, GetActiveVisitorsResponses, GetActivityGraphData, GetActivityGraphErrors, GetActivityGraphResponses, GetAdminGateData, GetAdminGateErrors, GetAdminGateResponses, GetAgentData, GetAgentErrors, GetAgentResponses, GetAggregatedBucketsData, GetAggregatedBucketsErrors, GetAggregatedBucketsResponses, GetAiAgentBreakdownData, GetAiAgentBreakdownErrors, GetAiAgentBreakdownResponses, GetAiAgentPagesData, GetAiAgentPagesErrors, GetAiAgentPagesResponses, GetAiAgentTimelineData, GetAiAgentTimelineErrors, GetAiAgentTimelineResponses, GetAiPageBreakdownData, GetAiPageBreakdownErrors, GetAiPageBreakdownResponses, GetAiStatusBreakdownData, GetAiStatusBreakdownErrors, GetAiStatusBreakdownResponses, GetAlertData, GetAlertErrors, GetAlertResponses, GetAlertRuleData, GetAlertRuleErrors, GetAlertRuleResponses, GetAllRepositoriesByNameData, GetAllRepositoriesByNameErrors, GetAllRepositoriesByNameResponses, GetAnalyticsActiveVisitorsData, GetAnalyticsActiveVisitorsErrors, GetAnalyticsActiveVisitorsResponses, GetAnalyticsEventsCountData, GetAnalyticsEventsCountErrors, GetAnalyticsEventsCountResponses, GetAnalyticsSessionEventsData, GetAnalyticsSessionEventsErrors, GetAnalyticsSessionEventsResponses, GetAnalyticsVisitorSessionsData, GetAnalyticsVisitorSessionsErrors, GetAnalyticsVisitorSessionsResponses, GetApiKeyData, GetApiKeyErrors, GetApiKeyPermissionsData, GetApiKeyPermissionsErrors, GetApiKeyPermissionsResponses, GetApiKeyResponses, GetAuditLogData, GetAuditLogErrors, GetAuditLogResponses, GetBackupData, GetBackupErrors, GetBackupResponses, GetBackupScheduleData, GetBackupScheduleErrors, GetBackupScheduleResponses, GetBranchesByRepositoryIdData, GetBranchesByRepositoryIdErrors, GetBranchesByRepositoryIdResponses, GetBucketedIncidentsData, GetBucketedIncidentsErrors, GetBucketedIncidentsResponses, GetBucketedStatusData, GetBucketedStatusErrors, GetBucketedStatusResponses, GetChallengeTokenData, GetChallengeTokenErrors, GetChallengeTokenResponses, GetChatReadinessData, GetChatReadinessErrors, GetChatReadinessResponses, GetCliStatusData, GetCliStatusErrors, GetCliStatusResponses, GetClusterHealthData, GetClusterHealthErrors, GetClusterHealthResponses, GetClusterMemberData, GetClusterMemberErrors, GetClusterMemberResponses, GetCmdData, GetCmdErrors, GetCmdResponses, GetContainerDetailData, GetContainerDetailErrors, GetContainerDetailResponses, GetContainerEnvironmentVariableData, GetContainerEnvironmentVariableErrors, GetContainerEnvironmentVariableResponses, GetContainerInfoData, GetContainerInfoErrors, GetContainerInfoResponses, GetContainerLogsByIdData, GetContainerLogsByIdErrors, GetContainerLogsData, GetContainerLogsErrors, GetContainerMetricsData, GetContainerMetricsErrors, GetContainerMetricsResponses, GetConversationData, GetConversationDetailData, GetConversationDetailErrors, GetConversationDetailResponses, GetConversationErrors, GetConversationResponses, GetConversationsData, GetConversationsErrors, GetConversationsResponses, GetCronByIdData, GetCronByIdErrors, GetCronByIdResponses, GetCronExecutionsData, GetCronExecutionsErrors, GetCronExecutionsResponses, GetCrossProjectTraceSiblingsData, GetCrossProjectTraceSiblingsErrors, GetCrossProjectTraceSiblingsResponses, GetCurrentMonitorStatusData, GetCurrentMonitorStatusErrors, GetCurrentMonitorStatusResponses, GetCurrentUserData, GetCurrentUserErrors, GetCurrentUserResponses, GetCustomDomainData, GetCustomDomainErrors, GetCustomDomainResponses, GetDashboardData, GetDashboardErrors, GetDashboardProjectsAnalyticsData, GetDashboardProjectsAnalyticsErrors, GetDashboardProjectsAnalyticsResponses, GetDashboardResponses, GetDeliveryData, GetDeliveryErrors, GetDeliveryResponses, GetDeploymentContainerLogContentData, GetDeploymentContainerLogContentErrors, GetDeploymentContainerLogContentResponses, GetDeploymentData, GetDeploymentErrors, GetDeploymentJobLogsData, GetDeploymentJobLogsErrors, GetDeploymentJobLogsResponses, GetDeploymentJobsData, GetDeploymentJobsErrors, GetDeploymentJobsResponses, GetDeploymentOperationsData, GetDeploymentOperationsErrors, GetDeploymentOperationsResponses, GetDeploymentOperationStatusData, GetDeploymentOperationStatusErrors, GetDeploymentOperationStatusResponses, GetDeploymentResponses, GetDeploymentTokenData, GetDeploymentTokenErrors, GetDeploymentTokenResponses, GetDiskStatusData, GetDiskStatusErrors, GetDiskStatusResponses, GetDnsChangesData, GetDnsChangesErrors, GetDnsChangesResponses, GetDnsProviderData, GetDnsProviderErrors, GetDnsProviderResponses, GetDomainByHostData, GetDomainByHostErrors, GetDomainByHostResponses, GetDomainByIdData, GetDomainByIdErrors, GetDomainByIdResponses, GetDomainByNameData, GetDomainByNameErrors, GetDomainByNameResponses, GetDomainData, GetDomainDnsRecordsData, GetDomainDnsRecordsErrors, GetDomainDnsRecordsResponses, GetDomainErrors, GetDomainOrderData, GetDomainOrderErrors, GetDomainOrderResponses, GetDomainResponses, GetEmailData, GetEmailErrors, GetEmailEventsData, GetEmailEventsErrors, GetEmailEventsResponses, GetEmailLinksData, GetEmailLinksErrors, GetEmailLinksResponses, GetEmailProviderData, GetEmailProviderErrors, GetEmailProviderResponses, GetEmailResponses, GetEmailStatsData, GetEmailStatsErrors, GetEmailStatsResponses, GetEmailTrackingData, GetEmailTrackingErrors, GetEmailTrackingResponses, GetEmailTrackingStatusData, GetEmailTrackingStatusErrors, GetEmailTrackingStatusResponses, GetEntityInfoData, GetEntityInfoErrors, GetEntityInfoResponses, GetEnvironmentCronsData, GetEnvironmentCronsErrors, GetEnvironmentCronsResponses, GetEnvironmentData, GetEnvironmentDomainsData, GetEnvironmentDomainsErrors, GetEnvironmentDomainsResponses, GetEnvironmentErrors, GetEnvironmentResponses, GetEnvironmentsData, GetEnvironmentsErrors, GetEnvironmentsResponses, GetEnvironmentVariablesData, GetEnvironmentVariablesErrors, GetEnvironmentVariablesResponses, GetEnvironmentVariableValueData, GetEnvironmentVariableValueErrors, GetEnvironmentVariableValueResponses, GetErrorDashboardStatsData, GetErrorDashboardStatsErrors, GetErrorDashboardStatsResponses, GetErrorEventData, GetErrorEventErrors, GetErrorEventResponses, GetErrorGroupData, GetErrorGroupErrors, GetErrorGroupResponses, GetErrorStatsData, GetErrorStatsErrors, GetErrorStatsResponses, GetErrorTimeSeriesData, GetErrorTimeSeriesErrors, GetErrorTimeSeriesResponses, GetEventDetailData, GetEventDetailErrors, GetEventDetailResponses, GetEventEntriesData, GetEventEntriesErrors, GetEventEntriesResponses, GetEventsCountData, GetEventsCountErrors, GetEventsCountResponses, GetEventsTimelineData, GetEventsTimelineErrors, GetEventsTimelineResponses, GetEventTypeBreakdownData, GetEventTypeBreakdownErrors, GetEventTypeBreakdownResponses, GetEventVisitorsData, GetEventVisitorsErrors, GetEventVisitorsResponses, GetExternalImageData, GetExternalImageErrors, GetExternalImageResponses, GetFileData, GetFileErrors, GetFileResponses, GetFlagData, GetFlagErrors, GetFlagResponses, GetFlagSnapshotData, GetFlagSnapshotErrors, GetFlagSnapshotResponses, GetFunnelMetricsData, GetFunnelMetricsErrors, GetFunnelMetricsResponses, GetGenaiTraceData, GetGenaiTraceErrors, GetGenaiTraceResponses, GetGeneralStatsData, GetGeneralStatsErrors, GetGeneralStatsResponses, GetGitProviderData, GetGitProviderErrors, GetGitProviderResponses, GetGlobalEventsData, GetGlobalEventsErrors, GetGlobalEventsResponses, GetGlobalEventStatsData, GetGlobalEventStatsErrors, GetGlobalEventStatsResponses, GetGlobalMcpData, GetGlobalMcpErrors, GetGlobalMcpResponses, GetGlobalSandboxStatusData, GetGlobalSandboxStatusErrors, GetGlobalSandboxStatusResponses, GetGlobalSkillData, GetGlobalSkillErrors, GetGlobalSkillResponses, GetGroupedPageMetricsData, GetGroupedPageMetricsErrors, GetGroupedPageMetricsResponses, GetHealthData, GetHealthErrors, GetHealthResponses, GetHourlyVisitsData, GetHourlyVisitsErrors, GetHourlyVisitsResponses, GetHttpChallengeDebugData, GetHttpChallengeDebugErrors, GetHttpChallengeDebugResponses, GetImportStatusData, GetImportStatusErrors, GetImportStatusResponses, GetIncidentData, GetIncidentErrors, GetIncidentResponses, GetIncidentUpdatesData, GetIncidentUpdatesErrors, GetIncidentUpdatesResponses, GetIpAccessControlData, GetIpAccessControlErrors, GetIpAccessControlResponses, GetIpGeolocationData, GetIpGeolocationErrors, GetIpGeolocationResponses, GetJoinTokenStatusData, GetJoinTokenStatusErrors, GetJoinTokenStatusResponses, GetLastDeploymentData, GetLastDeploymentErrors, GetLastDeploymentResponses, GetLatestScanData, GetLatestScanErrors, GetLatestScanResponses, GetLatestScansPerEnvironmentData, GetLatestScansPerEnvironmentErrors, GetLatestScansPerEnvironmentResponses, GetLiveVisitorsListData, GetLiveVisitorsListErrors, GetLiveVisitorsListResponses, GetLogContextData, GetLogContextErrors, GetLogContextResponses, GetMcpData, GetMcpErrors, GetMcpResponses, GetMetricsOverTimeData, GetMetricsOverTimeErrors, GetMetricsOverTimeResponses, GetMonitorData, GetMonitorErrors, GetMonitorResponses, GetNotificationProviderData, GetNotificationProviderErrors, GetNotificationProviderResponses, GetOnDemandCertStatusData, GetOnDemandCertStatusErrors, GetOnDemandCertStatusResponses, GetOrCreateDsnData, GetOrCreateDsnErrors, GetOrCreateDsnResponses, GetPageFlowData, GetPageFlowErrors, GetPageFlowResponses, GetPageHourlySessionsData, GetPageHourlySessionsErrors, GetPageHourlySessionsResponses, GetPagePathDetailData, GetPagePathDetailErrors, GetPagePathDetailResponses, GetPagePathsData, GetPagePathsErrors, GetPagePathsResponses, GetPagePathsSparklinesData, GetPagePathsSparklinesErrors, GetPagePathsSparklinesResponses, GetPagePathVisitorsData, GetPagePathVisitorsErrors, GetPagePathVisitorsResponses, GetPendingActionData, GetPendingActionErrors, GetPendingActionResponses, GetPerformanceMetricsData, GetPerformanceMetricsErrors, GetPerformanceMetricsResponses, GetPgUpgradeData, GetPgUpgradeErrors, GetPgUpgradeLogsData, GetPgUpgradeLogsErrors, GetPgUpgradeLogsResponses, GetPgUpgradeResponses, GetPipelineStatsData, GetPipelineStatsErrors, GetPipelineStatsResponses, GetPlatformInfoData, GetPlatformInfoErrors, GetPlatformInfoResponses, GetPostgresWalHealthData, GetPostgresWalHealthErrors, GetPostgresWalHealthResponses, GetPreferencesData, GetPreferencesErrors, GetPreferencesResponses, GetPreviewGatewayLogsData, GetPreviewGatewayLogsResponses, GetPreviewGatewaySettingsData, GetPreviewGatewaySettingsResponses, GetPreviewGatewayStatusData, GetPreviewGatewayStatusResponses, GetPricingData, GetPricingErrors, GetPricingResponses, GetPrivateIpData, GetPrivateIpErrors, GetPrivateIpResponses, GetProjectAlarmsSummaryData, GetProjectAlarmsSummaryErrors, GetProjectAlarmsSummaryResponses, GetProjectBySlugData, GetProjectBySlugErrors, GetProjectBySlugResponses, GetProjectData, GetProjectDeploymentsData, GetProjectDeploymentsErrors, GetProjectDeploymentsResponses, GetProjectErrors, GetProjectResponses, GetProjectsData, GetProjectsErrors, GetProjectServiceEnvironmentVariablesData, GetProjectServiceEnvironmentVariablesErrors, GetProjectServiceEnvironmentVariablesResponses, GetProjectSessionReplaysData, GetProjectSessionReplaysErrors, GetProjectSessionReplaysResponses, GetProjectsHealthData, GetProjectsHealthErrors, GetProjectsHealthResponses, GetProjectsMonitorHealthData, GetProjectsMonitorHealthErrors, GetProjectsMonitorHealthResponses, GetProjectsResponses, GetProjectStatisticsData, GetProjectStatisticsErrors, GetProjectStatisticsResponses, GetProjectTemplateData, GetProjectTemplateErrors, GetProjectTemplateResponses, GetPropertyBreakdownData, GetPropertyBreakdownErrors, GetPropertyBreakdownResponses, GetPropertyTimelineData, GetPropertyTimelineErrors, GetPropertyTimelineResponses, GetProviderConnectionsData, GetProviderConnectionsErrors, GetProviderConnectionsResponses, GetProviderMetadataData, GetProviderMetadataErrors, GetProviderMetadataResponses, GetProvidersMetadataData, GetProvidersMetadataErrors, GetProvidersMetadataResponses, GetProxyLogByIdData, GetProxyLogByIdErrors, GetProxyLogByIdResponses, GetProxyLogByRequestIdData, GetProxyLogByRequestIdErrors, GetProxyLogByRequestIdResponses, GetProxyLogsData, GetProxyLogsErrors, GetProxyLogsResponses, GetPublicBranchesData, GetPublicBranchesErrors, GetPublicBranchesResponses, GetPublicIpData, GetPublicIpErrors, GetPublicIpResponses, GetPublicRepositoryData, GetPublicRepositoryErrors, GetPublicRepositoryResponses, GetQuotaData, GetQuotaErrors, GetQuotaResponses, GetRecentActivityData, GetRecentActivityErrors, GetRecentActivityResponses, GetRemoteExternalImageData, GetRemoteExternalImageErrors, GetRemoteExternalImageResponses, GetRepositoryBranchesData, GetRepositoryBranchesErrors, GetRepositoryBranchesResponses, GetRepositoryByIdData, GetRepositoryByIdErrors, GetRepositoryByIdResponses, GetRepositoryByNameData, GetRepositoryByNameErrors, GetRepositoryByNameResponses, GetRepositoryPresetByNameData, GetRepositoryPresetByNameErrors, GetRepositoryPresetByNameResponses, GetRepositoryPresetLiveData, GetRepositoryPresetLiveErrors, GetRepositoryPresetLiveResponses, GetRepositoryTagsData, GetRepositoryTagsErrors, GetRepositoryTagsResponses, GetResolvedEnvironmentVariablesData, GetResolvedEnvironmentVariablesErrors, GetResolvedEnvironmentVariablesResponses, GetResolvedEnvironmentVariableValueData, GetResolvedEnvironmentVariableValueErrors, GetResolvedEnvironmentVariableValueResponses, GetRestoreCapabilitiesData, GetRestoreCapabilitiesErrors, GetRestoreCapabilitiesResponses, GetRestoreRunData, GetRestoreRunErrors, GetRestoreRunResponses, GetRouteData, GetRouteErrors, GetRouteResponses, GetRunData, GetRunErrors, GetRunResponses, GetRunWithLogsData, GetRunWithLogsErrors, GetRunWithLogsResponses, GetS3CredentialsData, GetS3CredentialsErrors, GetS3CredentialsResponses, GetS3SourceData, GetS3SourceErrors, GetS3SourceResponses, GetSandboxData, GetSandboxErrors, GetSandboxResponses, GetSandboxStatusData, GetSandboxStatusErrors, GetSandboxStatusResponses, GetScanByDeploymentData, GetScanByDeploymentErrors, GetScanByDeploymentResponses, GetScanData, GetScanErrors, GetScanResponses, GetScanVulnerabilitiesData, GetScanVulnerabilitiesErrors, GetScanVulnerabilitiesResponses, GetServiceBySlugData, GetServiceBySlugErrors, GetServiceBySlugResponses, GetServiceData, GetServiceEnvironmentVariableData, GetServiceEnvironmentVariableErrors, GetServiceEnvironmentVariableResponses, GetServiceEnvironmentVariablesData, GetServiceEnvironmentVariablesErrors, GetServiceEnvironmentVariablesResponses, GetServiceErrors, GetServiceHealthStatusData, GetServiceHealthStatusErrors, GetServiceHealthStatusResponses, GetServicePreviewEnvironmentVariableNamesData, GetServicePreviewEnvironmentVariableNamesErrors, GetServicePreviewEnvironmentVariableNamesResponses, GetServicePreviewEnvironmentVariablesMaskedData, GetServicePreviewEnvironmentVariablesMaskedErrors, GetServicePreviewEnvironmentVariablesMaskedResponses, GetServiceResponses, GetServiceRuntimeData, GetServiceRuntimeErrors, GetServiceRuntimeResponses, GetServiceStatsData, GetServiceStatsErrors, GetServiceStatsResponses, GetServiceTypeParametersData, GetServiceTypeParametersErrors, GetServiceTypeParametersResponses, GetServiceTypesData, GetServiceTypesErrors, GetServiceTypesResponses, GetSessionDetailsData, GetSessionDetailsErrors, GetSessionDetailsResponses, GetSessionEventsData, GetSessionEventsErrors, GetSessionEventsResponses, GetSessionLogsData, GetSessionLogsErrors, GetSessionLogsResponses, GetSessionReplayData, GetSessionReplayErrors, GetSessionReplayEventsData, GetSessionReplayEventsErrors, GetSessionReplayEventsResponses, GetSessionReplayResponses, GetSettingsData, GetSettingsErrors, GetSettingsResponses, GetSkillData, GetSkillErrors, GetSkillResponses, GetSlowQueriesData, GetSlowQueriesErrors, GetSlowQueriesResponses, GetStaticBundleData, GetStaticBundleErrors, GetStaticBundleResponses, GetStatusOverviewData, GetStatusOverviewErrors, GetStatusOverviewResponses, GetTagsByRepositoryIdData, GetTagsByRepositoryIdErrors, GetTagsByRepositoryIdResponses, GetTeamData, GetTeamErrors, GetTeamResponses, GetTimeBucketStatsData, GetTimeBucketStatsErrors, GetTimeBucketStatsResponses, GetTodayStatsData, GetTodayStatsErrors, GetTodayStatsResponses, GetTraceData, GetTraceErrors, GetTraceResponses, GetUnifiedTraceData, GetUnifiedTraceErrors, GetUnifiedTraceResponses, GetUniqueCountsData, GetUniqueCountsErrors, GetUniqueCountsResponses, GetUniqueEventsData, GetUniqueEventsErrors, GetUniqueEventsResponses, GetUpdateStatusData, GetUpdateStatusErrors, GetUpdateStatusResponses, GetUptimeHistoryData, GetUptimeHistoryErrors, GetUptimeHistoryResponses, GetUsageByProviderData, GetUsageByProviderErrors, GetUsageByProviderResponses, GetUsageRecentData, GetUsageRecentErrors, GetUsageRecentResponses, GetUsageSummaryData, GetUsageSummaryErrors, GetUsageSummaryResponses, GetUsageTimeseriesData, GetUsageTimeseriesErrors, GetUsageTimeseriesResponses, GetUsageTopModelsData, GetUsageTopModelsErrors, GetUsageTopModelsResponses, GetVisitorByGuidData, GetVisitorByGuidErrors, GetVisitorByGuidResponses, GetVisitorByIdData, GetVisitorByIdErrors, GetVisitorByIdResponses, GetVisitorDetailsData, GetVisitorDetailsErrors, GetVisitorDetailsResponses, GetVisitorFacetsData, GetVisitorFacetsErrors, GetVisitorFacetsResponses, GetVisitorInfoData, GetVisitorInfoErrors, GetVisitorInfoResponses, GetVisitorJourneyData, GetVisitorJourneyErrors, GetVisitorJourneyResponses, GetVisitorsData, GetVisitorsErrors, GetVisitorSessionsData, GetVisitorSessionsErrors, GetVisitorSessionsResponses, GetVisitorsResponses, GetVisitorStatsData, GetVisitorStatsErrors, GetVisitorStatsResponses, GetWebhookData, GetWebhookErrors, GetWebhookResponses, GrantProjectAccessData, GrantProjectAccessErrors, GrantProjectAccessResponses, HandleGitProviderOauthCallbackData, HandleGitProviderOauthCallbackErrors, HasAnalyticsEventsData, HasAnalyticsEventsErrors, HasAnalyticsEventsResponses, HasErrorGroupsData, HasErrorGroupsErrors, HasErrorGroupsResponses, HasPerformanceMetricsData, HasPerformanceMetricsErrors, HasPerformanceMetricsResponses, ImportExternalServiceData, ImportExternalServiceErrors, ImportExternalServiceResponses, IngestLogsByPathData, IngestLogsByPathErrors, IngestLogsByPathResponses, IngestLogsData, IngestLogsErrors, IngestLogsResponses, IngestMetricsByPathData, IngestMetricsByPathErrors, IngestMetricsByPathResponses, IngestMetricsData, IngestMetricsErrors, IngestMetricsResponses, IngestSentryEnvelopeData, IngestSentryEnvelopeErrors, IngestSentryEnvelopeResponses, IngestSentryEventData, IngestSentryEventErrors, IngestSentryEventResponses, IngestTracesByPathData, IngestTracesByPathErrors, IngestTracesByPathResponses, IngestTracesData, IngestTracesErrors, IngestTracesResponses, InitSessionReplayData, InitSessionReplayErrors, InitSessionReplayResponses, InspectDropArchiveData, InspectDropArchiveErrors, InspectDropArchiveResponses, JobLogsData, JobLogsErrors, JobLogsResponses, JobStatusData, JobStatusErrors, JobStatusResponses, KillJobData, KillJobErrors, KillJobResponses, KvDelData, KvDelErrors, KvDelResponses, KvDisableData, KvDisableErrors, KvDisableResponses, KvEnableData, KvEnableErrors, KvEnableResponses, KvExpireData, KvExpireErrors, KvExpireResponses, KvGetData, KvGetErrors, KvGetResponses, KvIncrData, KvIncrErrors, KvIncrResponses, KvKeysData, KvKeysErrors, KvKeysResponses, KvSetData, KvSetErrors, KvSetResponses, KvStatusData, KvStatusErrors, KvStatusResponses, KvTtlData, KvTtlErrors, KvTtlResponses, KvUpdateData, KvUpdateErrors, KvUpdateResponses, LatestRunForSourceData, LatestRunForSourceErrors, LatestRunForSourceResponses, LinkCustomDomainToCertificateData, LinkCustomDomainToCertificateErrors, LinkCustomDomainToCertificateResponses, LinkServiceToProjectData, LinkServiceToProjectErrors, LinkServiceToProjectResponses, ListAgentRunsData, ListAgentRunsErrors, ListAgentRunsResponses, ListAgentsData, ListAgentsErrors, ListAgentsResponses, ListAiProvidersData, ListAiProvidersErrors, ListAiProvidersResponses, ListAlertRulesData, ListAlertRulesErrors, ListAlertRulesResponses, ListAlertsData, ListAlertsErrors, ListAlertsResponses, ListAllConversationsData, ListAllConversationsErrors, ListAllConversationsResponses, ListAllRunsData, ListAllRunsErrors, ListAllRunsResponses, ListApiKeysData, ListApiKeysErrors, ListApiKeysResponses, ListAuditLogsData, ListAuditLogsErrors, ListAuditLogsResponses, ListAvailableContainersData, ListAvailableContainersErrors, ListAvailableContainersResponses, ListBackupAlertsData, ListBackupAlertsErrors, ListBackupAlertsResponses, ListBackupChildrenData, ListBackupChildrenErrors, ListBackupChildrenResponses, ListBackupSchedulesData, ListBackupSchedulesErrors, ListBackupSchedulesResponses, ListBackupsForScheduleData, ListBackupsForScheduleErrors, ListBackupsForScheduleResponses, ListCommitsByRepositoryIdData, ListCommitsByRepositoryIdErrors, ListCommitsByRepositoryIdResponses, ListConnectionsData, ListConnectionsErrors, ListConnectionsResponses, ListContainersAtPathData, ListContainersAtPathErrors, ListContainersAtPathResponses, ListContainersData, ListContainersErrors, ListContainersResponses, ListConversationsData, ListConversationsErrors, ListConversationsResponses, ListCustomDomainsForProjectData, ListCustomDomainsForProjectErrors, ListCustomDomainsForProjectResponses, ListDashboardsData, ListDashboardsErrors, ListDashboardsResponses, ListDeliveriesData, ListDeliveriesErrors, ListDeliveriesResponses, ListDeploymentContainerLogsData, ListDeploymentContainerLogsErrors, ListDeploymentContainerLogsResponses, ListDeploymentTokensData, ListDeploymentTokensErrors, ListDeploymentTokensResponses, ListDnsProvidersData, ListDnsProvidersErrors, ListDnsProvidersResponses, ListDomainsData, ListDomainsErrors, ListDomainsResponses, ListDsnsData, ListDsnsErrors, ListDsnsResponses, ListEmailDomainsData, ListEmailDomainsErrors, ListEmailDomainsResponses, ListEmailProvidersData, ListEmailProvidersErrors, ListEmailProvidersResponses, ListEmailsData, ListEmailsErrors, ListEmailsResponses, ListEnrollmentTokensData, ListEnrollmentTokensErrors, ListEnrollmentTokensResponses, ListEntitiesData, ListEntitiesErrors, ListEntitiesResponses, ListErrorEventsData, ListErrorEventsErrors, ListErrorEventsResponses, ListErrorGroupsData, ListErrorGroupsErrors, ListErrorGroupsResponses, ListEventsData, ListEventsResponses, ListEventTypesData, ListEventTypesResponses, ListExternalImagesData, ListExternalImagesErrors, ListExternalImagesResponses, ListExternalPluginsData, ListExternalPluginsErrors, ListExternalPluginsResponses, ListExternalServiceBackupsData, ListExternalServiceBackupsErrors, ListExternalServiceBackupsResponses, ListFlagsData, ListFlagsErrors, ListFlagsResponses, ListFunnelsData, ListFunnelsErrors, ListFunnelsResponses, ListGitProvidersData, ListGitProvidersErrors, ListGitProvidersResponses, ListGlobalMcpsData, ListGlobalMcpsErrors, ListGlobalMcpsResponses, ListGlobalSkillsData, ListGlobalSkillsErrors, ListGlobalSkillsResponses, ListIncidentsData, ListIncidentsErrors, ListIncidentsResponses, ListInsightsData, ListInsightsErrors, ListInsightsResponses, ListIpAccessControlData, ListIpAccessControlErrors, ListIpAccessControlResponses, ListJobsData, ListJobsErrors, ListJobsResponses, ListKnownAiAgentsData, ListKnownAiAgentsErrors, ListKnownAiAgentsResponses, ListManagedDomainsData, ListManagedDomainsErrors, ListManagedDomainsResponses, ListMcpsData, ListMcpsErrors, ListMcpsResponses, ListMetricLabelKeysData, ListMetricLabelKeysErrors, ListMetricLabelKeysResponses, ListMetricLabelValuesData, ListMetricLabelValuesErrors, ListMetricLabelValuesResponses, ListMetricNamesData, ListMetricNamesErrors, ListMetricNamesResponses, ListModelsData, ListModelsErrors, ListModelsResponses, ListMonitorsData, ListMonitorsErrors, ListMonitorsResponses, ListNotificationProvidersData, ListNotificationProvidersErrors, ListNotificationProvidersResponses, ListOidcProvidersData, ListOidcProvidersResponses, ListOidcProviderUsersData, ListOidcProviderUsersErrors, ListOidcProviderUsersResponses, ListOidcRoleMappingsData, ListOidcRoleMappingsResponses, ListOnDemandCertsData, ListOnDemandCertsErrors, ListOnDemandCertsResponses, ListOrdersData, ListOrdersErrors, ListOrdersResponses, ListPeersData, ListPeersErrors, ListPeersResponses, ListPendingActionsData, ListPendingActionsErrors, ListPendingActionsResponses, ListPgUpgradesData, ListPgUpgradesErrors, ListPgUpgradesResponses, ListPresetsData, ListPresetsErrors, ListPresetsResponses, ListProjectAccessData, ListProjectAccessErrors, ListProjectAccessResponses, ListProjectAlarmsData, ListProjectAlarmsErrors, ListProjectAlarmsResponses, ListProjectScansData, ListProjectScansErrors, ListProjectScansResponses, ListProjectSecretsData, ListProjectSecretsErrors, ListProjectSecretsResponses, ListProjectServicesData, ListProjectServicesErrors, ListProjectServicesResponses, ListProjectTemplatesData, ListProjectTemplatesErrors, ListProjectTemplatesResponses, ListProjectTemplateTagsData, ListProjectTemplateTagsErrors, ListProjectTemplateTagsResponses, ListProviderKeysData, ListProviderKeysErrors, ListProviderKeysResponses, ListProviderZonesData, ListProviderZonesErrors, ListProviderZonesResponses, ListPublicProvidersData, ListPublicProvidersResponses, ListReleaseFilesData, ListReleaseFilesErrors, ListReleaseFilesResponses, ListReleasesData, ListReleasesErrors, ListReleasesResponses, ListRemoteExternalImagesData, ListRemoteExternalImagesErrors, ListRemoteExternalImagesResponses, ListRepositoriesByConnectionData, ListRepositoriesByConnectionErrors, ListRepositoriesByConnectionResponses, ListRepositoriesByProviderData, ListRepositoriesByProviderErrors, ListRepositoriesByProviderResponses, ListRestoreRunsForServiceData, ListRestoreRunsForServiceResponses, ListRootContainersData, ListRootContainersErrors, ListRootContainersResponses, ListRoutesData, ListRoutesErrors, ListRoutesResponses, ListS3SourcesData, ListS3SourcesErrors, ListS3SourcesResponses, ListSandboxesData, ListSandboxesResponses, ListScheduleRunJobsData, ListScheduleRunJobsErrors, ListScheduleRunJobsResponses, ListScheduleRunsData, ListScheduleRunsErrors, ListScheduleRunsResponses, ListScheduleServicesData, ListScheduleServicesErrors, ListScheduleServicesResponses, ListSecretsData, ListSecretsErrors, ListSecretsResponses, ListServiceHealthStatusesData, ListServiceHealthStatusesErrors, ListServiceHealthStatusesResponses, ListServiceProjectsData, ListServiceProjectsErrors, ListServiceProjectsResponses, ListServiceSchedulesData, ListServiceSchedulesErrors, ListServiceSchedulesResponses, ListServicesData, ListServicesErrors, ListServicesResponses, ListSkillsData, ListSkillsErrors, ListSkillsResponses, ListSourceBackupsData, ListSourceBackupsErrors, ListSourceBackupsResponses, ListSourceFilesData, ListSourceFilesErrors, ListSourceFilesResponses, ListSourceMapsData, ListSourceMapsErrors, ListSourceMapsResponses, ListSourcesData, ListSourcesErrors, ListSourcesResponses, ListStaticBundlesData, ListStaticBundlesErrors, ListStaticBundlesResponses, ListSyncedRepositoriesData, ListSyncedRepositoriesErrors, ListSyncedRepositoriesResponses, ListTeamMembersData, ListTeamMembersErrors, ListTeamMembersResponses, ListTeamProjectsData, ListTeamProjectsErrors, ListTeamProjectsResponses, ListTeamsData, ListTeamsErrors, ListTeamsResponses, ListUsersData, ListUsersErrors, ListUsersResponses, ListWebhooksData, ListWebhooksErrors, ListWebhooksResponses, LoginData, LoginErrors, LoginResponses, LogoutData, LogoutErrors, LogoutResponses, LookupDnsARecordsData, LookupDnsARecordsErrors, LookupDnsARecordsResponses, MintEnrollmentTokenData, MintEnrollmentTokenErrors, MintEnrollmentTokenResponses, MkdirData, MkdirErrors, MkdirResponses, NodeHeartbeatData, NodeHeartbeatErrors, NodeHeartbeatResponses, NodeMetricsGetRangeData, NodeMetricsGetRangeErrors, NodeMetricsGetRangeResponses, ObservabilityFullEventData, ObservabilityFullEventErrors, ObservabilityFullEventResponses, ObservabilityListEventsData, ObservabilityListEventsErrors, ObservabilityListEventsResponses, OidcCallbackData, PatchAdminGateData, PatchAdminGateErrors, PatchAdminGateResponses, PatchPreviewGatewaySettingsData, PatchPreviewGatewaySettingsResponses, PauseDeploymentData, PauseDeploymentErrors, PauseDeploymentResponses, PauseSandboxData, PauseSandboxErrors, PauseSandboxResponses, PlanRestoreData, PlanRestoreErrors, PlanRestoreResponses, PostDnsAckData, PostDnsAckErrors, PostDnsAckResponses, PreviewAlertData, PreviewAlertErrors, PreviewAlertResponses, PreviewFunnelMetricsData, PreviewFunnelMetricsErrors, PreviewFunnelMetricsResponses, PreviewHostnameModeData, PreviewHostnameModeErrors, PreviewHostnameModeResponses, PromoteClusterMemberData, PromoteClusterMemberErrors, PromoteClusterMemberResponses, PromoteDeploymentData, PromoteDeploymentErrors, PromoteDeploymentResponses, ProvisionDomainData, ProvisionDomainErrors, ProvisionDomainResponses, PurgeProjectLogsData, PurgeProjectLogsErrors, PurgeProjectLogsResponses, PushExternalImageData, PushExternalImageErrors, PushExternalImageResponses, QueryDataData, QueryDataErrors, QueryDataResponses, QueryGenaiTracesData, QueryGenaiTracesErrors, QueryGenaiTracesResponses, QueryLogsData, QueryLogsErrors, QueryLogsResponses, QueryMetricsData, QueryMetricsErrors, QueryMetricsResponses, QueryTracesData, QueryTracesErrors, QueryTracesResponses, QueryTraceSummariesData, QueryTraceSummariesErrors, QueryTraceSummariesResponses, ReadFileData, ReadFileErrors, ReadFileResponses, ReAnalyzeData, ReAnalyzeErrors, ReAnalyzeResponses, RebuildSandboxImageData, RebuildSandboxImageErrors, RebuildSandboxImageResponses, RecordConsoleEventData, RecordConsoleEventErrors, RecordConsoleEventResponses, RecordEventMetricsData, RecordEventMetricsErrors, RecordEventMetricsResponses, RecordFlagExposureData, RecordFlagExposureErrors, RecordFlagExposureResponses, RecordSpeedMetricsData, RecordSpeedMetricsErrors, RecordSpeedMetricsResponses, RefreshRouteTableData, RefreshRouteTableErrors, RefreshRouteTableResponses, RegenerateDsnData, RegenerateDsnErrors, RegenerateDsnResponses, RegisterExternalImageData, RegisterExternalImageErrors, RegisterExternalImageResponses, RegisterNodeData, RegisterNodeErrors, RegisterNodeResponses, ReinstallGitlabWebhookData, ReinstallGitlabWebhookErrors, ReinstallGitlabWebhookResponses, RejectPendingActionData, RejectPendingActionErrors, RejectPendingActionResponses, ReloadPluginsData, ReloadPluginsErrors, ReloadPluginsResponses, RemoveClusterMemberData, RemoveClusterMemberErrors, RemoveClusterMemberResponses, RemoveManagedDomainData, RemoveManagedDomainErrors, RemoveManagedDomainResponses, RemoveRoleData, RemoveRoleErrors, RemoveRoleResponses, RemoveTeamMemberData, RemoveTeamMemberErrors, RemoveTeamMemberResponses, RenameConversationData, RenameConversationErrors, RenameConversationResponses, RenewDomainData, RenewDomainErrors, RenewDomainResponses, RequestPasswordResetData, RequestPasswordResetErrors, RequestPasswordResetResponses, ResetPasswordData, ResetPasswordErrors, ResetPasswordResponses, ResizeSandboxData, ResizeSandboxErrors, ResizeSandboxResponses, ResolveAlarmData, ResolveAlarmErrors, ResolveAlarmResponses, RestartContainerData, RestartContainerErrors, RestartContainerResponses, RestartPreviewGatewayData, RestartPreviewGatewayResponses, RestartSandboxData, RestartSandboxErrors, RestartSandboxResponses, RestoreFlagData, RestoreFlagErrors, RestoreFlagResponses, RestoreUserData, RestoreUserErrors, RestoreUserResponses, ResumeDeploymentData, ResumeDeploymentErrors, ResumeDeploymentResponses, ResumeSandboxData, ResumeSandboxErrors, ResumeSandboxResponses, RetryClusterData, RetryClusterErrors, RetryClusterResponses, RetryDeliveryData, RetryDeliveryErrors, RetryDeliveryResponses, RetryPgUpgradeData, RetryPgUpgradeErrors, RetryPgUpgradeResponses, RetryRunData, RetryRunErrors, RetryRunResponses, RevealGlobalMcpConfigData, RevealGlobalMcpConfigErrors, RevealGlobalMcpConfigResponses, RevealMcpConfigData, RevealMcpConfigErrors, RevealMcpConfigResponses, RevealNotificationProviderConfigData, RevealNotificationProviderConfigErrors, RevealNotificationProviderConfigResponses, RevealServiceParameterData, RevealServiceParameterErrors, RevealServiceParameterResponses, RevenueCreateIntegrationData, RevenueCreateIntegrationErrors, RevenueCreateIntegrationResponses, RevenueDeleteIntegrationData, RevenueDeleteIntegrationResponses, RevenueGlobalEventsData, RevenueGlobalEventsResponses, RevenueImportInvoicesCsvData, RevenueImportInvoicesCsvErrors, RevenueImportInvoicesCsvResponses, RevenueImportSubscriptionsCsvData, RevenueImportSubscriptionsCsvErrors, RevenueImportSubscriptionsCsvResponses, RevenueListIntegrationsData, RevenueListIntegrationsResponses, RevenueListProvidersData, RevenueListProvidersResponses, RevenueMetricsCustomersData, RevenueMetricsCustomersResponses, RevenueMetricsGlobalMrrData, RevenueMetricsGlobalMrrResponses, RevenueMetricsGlobalSummaryData, RevenueMetricsGlobalSummaryResponses, RevenueMetricsMrrData, RevenueMetricsMrrResponses, RevenueMetricsSummaryData, RevenueMetricsSummaryResponses, RevenueRecentEventsData, RevenueRecentEventsResponses, RevenueRotateTokenData, RevenueRotateTokenResponses, RevenueUpdateConfigData, RevenueUpdateConfigErrors, RevenueUpdateConfigResponses, RevenueUpdateSecretData, RevenueUpdateSecretErrors, RevenueUpdateSecretResponses, RevokeDsnData, RevokeDsnErrors, RevokeDsnResponses, RevokeEnrollmentTokenData, RevokeEnrollmentTokenErrors, RevokeEnrollmentTokenResponses, RevokeJoinTokenData, RevokeJoinTokenErrors, RevokeJoinTokenResponses, RevokeProjectAccessData, RevokeProjectAccessErrors, RevokeProjectAccessResponses, RollbackPgUpgradeData, RollbackPgUpgradeErrors, RollbackPgUpgradeResponses, RollbackToDeploymentData, RollbackToDeploymentErrors, RollbackToDeploymentResponses, RootfsGcData, RootfsGcResponses, RootfsReportData, RootfsReportResponses, RotateApiKeyData, RotateApiKeyErrors, RotateApiKeyResponses, RotateDeploymentTokenData, RotateDeploymentTokenErrors, RotateDeploymentTokenResponses, RunBackupForSourceData, RunBackupForSourceErrors, RunBackupForSourceResponses, RunConnectionHealthCheckData, RunConnectionHealthCheckErrors, RunConnectionHealthCheckResponses, RunExternalServiceBackupData, RunExternalServiceBackupErrors, RunExternalServiceBackupResponses, RunScheduleNowData, RunScheduleNowErrors, RunScheduleNowResponses, SandboxCreatePreviewLinkData, SandboxCreatePreviewLinkErrors, SandboxCreatePreviewLinkResponses, SaveAgentTokenData, SaveAgentTokenErrors, SaveAgentTokenResponses, SaveAiProviderCredentialData, SaveAiProviderCredentialErrors, SaveAiProviderCredentialResponses, SearchLogsData, SearchLogsErrors, SearchLogsResponses, SendEmailData, SendEmailErrors, SendEmailResponses, SendMessageData, SendMessageErrors, SendMessageResponses, SetDefaultS3SourceData, SetDefaultS3SourceErrors, SetDefaultS3SourceResponses, SetFlagEnvironmentData, SetFlagEnvironmentErrors, SetFlagEnvironmentResponses, SetPreviewPasswordData, SetPreviewPasswordErrors, SetPreviewPasswordResponses, SetupDnsChallengeData, SetupDnsChallengeErrors, SetupDnsChallengeResponses, SetupDnsData, SetupDnsErrors, SetupDnsResponses, SetupEmailTrackingData, SetupEmailTrackingErrors, SetupEmailTrackingResponses, SetupMfaData, SetupMfaErrors, SetupMfaResponses, SleepEnvironmentData, SleepEnvironmentErrors, SleepEnvironmentResponses, SmokeTestAgentData, SmokeTestAgentErrors, SmokeTestAgentResponses, SourceSandboxData, SourceSandboxErrors, SourceSandboxResponses, StartAnalysisData, StartAnalysisErrors, StartAnalysisResponses, StartContainerData, StartContainerErrors, StartContainerResponses, StartFixData, StartFixErrors, StartFixResponses, StartGitProviderOauthData, StartGitProviderOauthErrors, StartOidcLoginBySlugData, StartOidcLoginBySlugErrors, StartPgUpgradeData, StartPgUpgradeErrors, StartPgUpgradeResponses, StartRestoreData, StartRestoreErrors, StartRestoreResponses, StartServiceData, StartServiceErrors, StartServiceResponses, StatPathData, StatPathErrors, StatPathResponses, StopContainerData, StopContainerErrors, StopContainerResponses, StopSandboxData, StopSandboxErrors, StopSandboxResponses, StopServiceData, StopServiceErrors, StopServiceResponses, StreamContainerMetricsData, StreamContainerMetricsErrors, StreamContainerMetricsResponses, StreamEventsData, StreamEventsErrors, StreamEventsResponses, StreamRunEventsData, StreamRunEventsErrors, StreamRunEventsResponses, SyncRepositoriesData, SyncRepositoriesErrors, SyncRepositoriesResponses, TailDeploymentJobLogsData, TailDeploymentJobLogsErrors, TailLogsData, TailLogsErrors, TailLogsResponses, TeardownDeploymentData, TeardownDeploymentErrors, TeardownDeploymentResponses, TeardownEnvironmentData, TeardownEnvironmentErrors, TeardownEnvironmentResponses, TestNotificationProviderData, TestNotificationProviderErrors, TestNotificationProviderResponses, TestOidcProviderData, TestOidcProviderResponses, TestProviderConnectionData, TestProviderConnectionErrors, TestProviderConnectionResponses, TestProviderData, TestProviderErrors, TestProviderKeyByIdData, TestProviderKeyByIdErrors, TestProviderKeyByIdResponses, TestProviderKeyInlineData, TestProviderKeyInlineErrors, TestProviderKeyInlineResponses, TestProviderResponses, TestS3ConnectionPreviewData, TestS3ConnectionPreviewErrors, TestS3ConnectionPreviewResponses, TestS3SourceConnectionData, TestS3SourceConnectionErrors, TestS3SourceConnectionResponses, TrackClickData, TrackClickErrors, TrackOpenData, TrackOpenErrors, TrackOpenResponses, TriggerAgentData, TriggerAgentErrors, TriggerAgentResponses, TriggerProjectPipelineData, TriggerProjectPipelineErrors, TriggerProjectPipelineResponses, TriggerScanData, TriggerScanErrors, TriggerScanResponses, TriggerServiceHealthCheckData, TriggerServiceHealthCheckErrors, TriggerServiceHealthCheckResponses, TriggerWeeklyDigestData, TriggerWeeklyDigestErrors, TriggerWeeklyDigestResponses, UnlinkServiceFromProjectData, UnlinkServiceFromProjectErrors, UnlinkServiceFromProjectResponses, UpdateAgentData, UpdateAgentErrors, UpdateAgentResponses, UpdateAiProviderData, UpdateAiProviderErrors, UpdateAiProviderResponses, UpdateAlertData, UpdateAlertErrors, UpdateAlertResponses, UpdateAlertRuleData, UpdateAlertRuleErrors, UpdateAlertRuleResponses, UpdateApiKeyData, UpdateApiKeyErrors, UpdateApiKeyResponses, UpdateAutomaticDeployData, UpdateAutomaticDeployErrors, UpdateAutomaticDeployResponses, UpdateBackupScheduleData, UpdateBackupScheduleErrors, UpdateBackupScheduleResponses, UpdateCloudflareProviderData, UpdateCloudflareProviderErrors, UpdateCloudflareProviderResponses, UpdateConnectionTokenData, UpdateConnectionTokenErrors, UpdateConnectionTokenResponses, UpdateCustomDomainData, UpdateCustomDomainErrors, UpdateCustomDomainResponses, UpdateDashboardData, UpdateDashboardErrors, UpdateDashboardResponses, UpdateDeploymentTokenData, UpdateDeploymentTokenErrors, UpdateDeploymentTokenResponses, UpdateEmailProviderData, UpdateEmailProviderErrors, UpdateEmailProviderResponses, UpdateEnvironmentSettingsData, UpdateEnvironmentSettingsErrors, UpdateEnvironmentSettingsResponses, UpdateEnvironmentSubdomainData, UpdateEnvironmentSubdomainErrors, UpdateEnvironmentSubdomainResponses, UpdateEnvironmentVariableData, UpdateEnvironmentVariableErrors, UpdateEnvironmentVariableResponses, UpdateErrorGroupData, UpdateErrorGroupErrors, UpdateErrorGroupResponses, UpdateFlagData, UpdateFlagErrors, UpdateFlagResponses, UpdateFunnelData, UpdateFunnelErrors, UpdateFunnelResponses, UpdateGitProviderCredentialsData, UpdateGitProviderCredentialsErrors, UpdateGitProviderCredentialsResponses, UpdateGitSettingsData, UpdateGitSettingsErrors, UpdateGitSettingsResponses, UpdateGlobalMcpData, UpdateGlobalMcpErrors, UpdateGlobalMcpResponses, UpdateGlobalSkillData, UpdateGlobalSkillErrors, UpdateGlobalSkillResponses, UpdateIncidentStatusData, UpdateIncidentStatusErrors, UpdateIncidentStatusResponses, UpdateIpAccessControlData, UpdateIpAccessControlErrors, UpdateIpAccessControlResponses, UpdateManagedDomainData, UpdateManagedDomainErrors, UpdateManagedDomainResponses, UpdateMcpData, UpdateMcpErrors, UpdateMcpResponses, UpdateNotificationEmailProviderData, UpdateNotificationEmailProviderErrors, UpdateNotificationEmailProviderResponses, UpdateNotificationProviderData, UpdateNotificationProviderErrors, UpdateNotificationProviderResponses, UpdateOidcProviderData, UpdateOidcProviderResponses, UpdatePreferencesData, UpdatePreferencesErrors, UpdatePreferencesResponses, UpdateProjectData, UpdateProjectDeploymentConfigData, UpdateProjectDeploymentConfigErrors, UpdateProjectDeploymentConfigResponses, UpdateProjectErrors, UpdateProjectResponses, UpdateProjectSecretData, UpdateProjectSecretErrors, UpdateProjectSecretResponses, UpdateProjectSettingsData, UpdateProjectSettingsErrors, UpdateProjectSettingsResponses, UpdateProviderData, UpdateProviderErrors, UpdateProviderKeyData, UpdateProviderKeyErrors, UpdateProviderKeyResponses, UpdateProviderResponses, UpdateRouteData, UpdateRouteErrors, UpdateRouteResponses, UpdateS3SourceData, UpdateS3SourceErrors, UpdateS3SourceResponses, UpdateSelfData, UpdateSelfErrors, UpdateSelfResponses, UpdateServiceData, UpdateServiceErrors, UpdateServiceResourcesData, UpdateServiceResourcesErrors, UpdateServiceResourcesResponses, UpdateServiceResponses, UpdateSessionDurationData, UpdateSessionDurationErrors, UpdateSessionDurationResponses, UpdateSettingsData, UpdateSettingsErrors, UpdateSettingsResponses, UpdateSkillData, UpdateSkillErrors, UpdateSkillResponses, UpdateSlackProviderData, UpdateSlackProviderErrors, UpdateSlackProviderResponses, UpdateSpeedMetricsData, UpdateSpeedMetricsErrors, UpdateSpeedMetricsResponses, UpdateTeamData, UpdateTeamErrors, UpdateTeamMemberRoleData, UpdateTeamMemberRoleErrors, UpdateTeamMemberRoleResponses, UpdateTeamResponses, UpdateUserData, UpdateUserErrors, UpdateUserResponses, UpdateWebhookData, UpdateWebhookErrors, UpdateWebhookProviderData, UpdateWebhookProviderErrors, UpdateWebhookProviderResponses, UpdateWebhookResponses, UpgradePreviewGatewayData, UpgradePreviewGatewayResponses, UpgradeServiceData, UpgradeServiceErrors, UpgradeServiceResponses, UploadGlobalSkillData, UploadGlobalSkillErrors, UploadGlobalSkillResponses, UploadReleaseFileData, UploadReleaseFileErrors, UploadReleaseFileResponses, UploadSkillData, UploadSkillErrors, UploadSkillResponses, UploadSourceFileData, UploadSourceFileErrors, UploadSourceFileResponses, UploadSourceMapData, UploadSourceMapErrors, UploadSourceMapResponses, UploadStaticBundleData, UploadStaticBundleErrors, UploadStaticBundleResponses, UpsertSecretData, UpsertSecretErrors, UpsertSecretResponses, ValidateConnectionData, ValidateConnectionErrors, ValidateConnectionResponses, ValidateEmailData, ValidateEmailErrors, ValidateEmailResponses, VerifyAndEnableMfaData, VerifyAndEnableMfaErrors, VerifyAndEnableMfaResponses, VerifyDomainData, VerifyDomainErrors, VerifyDomainResponses, VerifyEmailData, VerifyEmailErrors, VerifyEmailResponses, VerifyManagedDomainData, VerifyManagedDomainErrors, VerifyManagedDomainResponses, VerifyMfaChallengeData, VerifyMfaChallengeErrors, VerifyMfaChallengeResponses, VerifyStepUpData, VerifyStepUpErrors, VerifyStepUpResponses, WakeEnvironmentData, WakeEnvironmentErrors, WakeEnvironmentResponses, WebhookTriggerData, WebhookTriggerErrors, WebhookTriggerResponses, WorkflowDryRunData, WorkflowDryRunErrors, WorkflowDryRunResponses, WriteFileData, WriteFileErrors, WriteFileResponses, WriteFilesData, WriteFilesErrors, WriteFilesResponses } from './types.gen'; export type Options = Options2 & { /** @@ -1748,6 +1748,20 @@ export const checkDomainStatus = (options: ...options }); +/** + * Inspect a source ZIP without creating a project or retaining the upload. + */ +export const inspectDropArchive = (options: Options): RequestResult => (options.client ?? client).post({ + ...formDataBodySerializer, + security: [{ scheme: 'bearer', type: 'http' }], + url: '/drop/inspect', + ...options, + headers: { + 'Content-Type': null, + ...options.headers + } +}); + /** * List all email domains */ @@ -5509,6 +5523,20 @@ export const deployFromImageUpload = (opti ...options }); +/** + * Upload source code and immediately start a preset-based deployment. + */ +export const deployFromUploadedSource = (options: Options): RequestResult => (options.client ?? client).post({ + ...formDataBodySerializer, + security: [{ scheme: 'bearer', type: 'http' }], + url: '/projects/{project_id}/environments/{environment_id}/deploy/source', + ...options, + headers: { + 'Content-Type': null, + ...options.headers + } +}); + /** * Deploy from an uploaded static bundle * diff --git a/apps/temps-cli/src/api/types.gen.ts b/apps/temps-cli/src/api/types.gen.ts index 5f4afc128..ecd8daf63 100644 --- a/apps/temps-cli/src/api/types.gen.ts +++ b/apps/temps-cli/src/api/types.gen.ts @@ -5615,6 +5615,15 @@ export type DrainStatusResponse = { status: string; }; +export type DropArchiveUpload = { + file: Blob | File; +}; + +export type DropInspectionResponse = { + candidates: Array; + suggestedName: string; +}; + /** * Drop-off point: pages where visitors leave the site */ @@ -5637,6 +5646,15 @@ export type DropOffPoint = { total_views: number; }; +export type DropPresetCandidate = { + confidence: string; + directory: string; + isStatic: boolean; + label: string; + preset: string; + reason: string; +}; + export type EmailConfig = { accept_invalid_certs?: boolean; from_address: string; @@ -15572,6 +15590,10 @@ export type SmtpResult = { is_disabled: boolean; }; +export type SourceArchiveUpload = { + file: Blob | File; +}; + /** * Entry in the source backup index. Covers both DB-tracked backups * (have a row in `backups`) and S3-scan discoveries (raw S3 objects with @@ -15723,9 +15745,10 @@ export type SourceMapResponse = { * - `Git`: Source code from a Git repository (traditional flow) * - `DockerImage`: Pre-built Docker image from external registry * - `StaticFiles`: Pre-built static files uploaded as a bundle + * - `UploadedSource`: Source archive uploaded without a Git repository * - `Manual`: Flexible type that accepts any deployment method */ -export type SourceType = 'git' | 'docker_image' | 'static_files' | 'manual'; +export type SourceType = 'git' | 'docker_image' | 'static_files' | 'uploaded_source' | 'manual'; /** * A span event (log-like annotation on a span). @@ -25434,6 +25457,29 @@ export type CheckDomainStatusResponses = { export type CheckDomainStatusResponse = CheckDomainStatusResponses[keyof CheckDomainStatusResponses]; +export type InspectDropArchiveData = { + body: DropArchiveUpload; + path?: never; + query?: never; + url: '/drop/inspect'; +}; + +export type InspectDropArchiveErrors = { + /** + * Invalid or unsupported archive + */ + 400: unknown; +}; + +export type InspectDropArchiveResponses = { + /** + * Detected deployable project roots + */ + 200: DropInspectionResponse; +}; + +export type InspectDropArchiveResponse = InspectDropArchiveResponses[keyof InspectDropArchiveResponses]; + export type ListEmailDomainsData = { body?: never; path?: never; @@ -40042,6 +40088,36 @@ export type DeployFromImageUploadResponses = { export type DeployFromImageUploadResponse = DeployFromImageUploadResponses[keyof DeployFromImageUploadResponses]; +export type DeployFromUploadedSourceData = { + body: SourceArchiveUpload; + path: { + project_id: number; + environment_id: number; + }; + query?: never; + url: '/projects/{project_id}/environments/{environment_id}/deploy/source'; +}; + +export type DeployFromUploadedSourceErrors = { + /** + * Invalid source archive + */ + 400: unknown; + /** + * Project or environment not found + */ + 404: unknown; +}; + +export type DeployFromUploadedSourceResponses = { + /** + * Source deployment started + */ + 202: RemoteDeploymentResponse; +}; + +export type DeployFromUploadedSourceResponse = DeployFromUploadedSourceResponses[keyof DeployFromUploadedSourceResponses]; + export type DeployFromStaticData = { body: DeployFromStaticRequest; path: { diff --git a/apps/temps-cli/src/commands/deploy/drop.test.ts b/apps/temps-cli/src/commands/deploy/drop.test.ts new file mode 100644 index 000000000..1a7e00a66 --- /dev/null +++ b/apps/temps-cli/src/commands/deploy/drop.test.ts @@ -0,0 +1,61 @@ +import { afterEach, describe, expect, test } from 'bun:test' +import { mkdtemp, mkdir, rm, symlink, writeFile } from 'node:fs/promises' +import { tmpdir } from 'node:os' +import { join } from 'node:path' +import { slugName, zipDirectory } from './drop' + +const temporaryDirectories: string[] = [] + +afterEach(async () => { + await Promise.all( + temporaryDirectories.splice(0).map((path) => + rm(path, { recursive: true, force: true }) + ) + ) +}) + +async function fixtureDirectory(): Promise { + const directory = await mkdtemp(join(tmpdir(), 'temps-drop-test-')) + temporaryDirectories.push(directory) + return directory +} + +describe('drop archive preparation', () => { + test('slugifies names and falls back when no usable name exists', () => { + expect(slugName(' My Project! ')).toBe('my-project') + expect(slugName('🔥')).toMatch(/^drop-[a-z0-9]{8}$/) + }) + + test('rejects symbolic links instead of following them', async () => { + const directory = await fixtureDirectory() + await writeFile(join(directory, 'index.html'), 'ok') + await symlink('/etc/passwd', join(directory, 'passwd')) + + await expect(zipDirectory(directory)).rejects.toThrow( + 'does not follow symbolic links' + ) + }) + + test('does not package common secrets or dependency trees', async () => { + const directory = await fixtureDirectory() + await mkdir(join(directory, 'node_modules/pkg'), { recursive: true }) + await mkdir(join(directory, '.git'), { recursive: true }) + await writeFile(join(directory, 'index.html'), 'ok') + await writeFile(join(directory, '.env'), 'TOKEN=secret') + await writeFile(join(directory, 'server.key'), 'secret') + await writeFile(join(directory, '.git/config'), 'secret') + await writeFile(join(directory, 'node_modules/pkg/index.js'), 'secret') + + const archive = await zipDirectory(directory) + try { + const archiveText = archive.data.toString('latin1') + expect(archiveText).toContain('index.html') + expect(archiveText).not.toContain('.env') + expect(archiveText).not.toContain('server.key') + expect(archiveText).not.toContain('.git/config') + expect(archiveText).not.toContain('node_modules') + } finally { + await archive.cleanup() + } + }) +}) diff --git a/apps/temps-cli/src/commands/deploy/drop.ts b/apps/temps-cli/src/commands/deploy/drop.ts new file mode 100644 index 000000000..5da8ac19a --- /dev/null +++ b/apps/temps-cli/src/commands/deploy/drop.ts @@ -0,0 +1,216 @@ +import { existsSync, statSync } from 'node:fs' +import { lstat, mkdtemp, readFile, readdir, rm } from 'node:fs/promises' +import { basename, join, resolve } from 'node:path' +import { tmpdir } from 'node:os' +import { spawn } from 'node:child_process' +import { + createProject, + deleteProject, + deployFromUploadedSource, + getEnvironments, + inspectDropArchive, +} from '../../api/sdk.gen.js' +import { requireAuth, config, credentials } from '../../config/store.js' +import { client, normalizeApiUrl, setupClient } from '../../lib/api-client.js' +import { watchDeployment } from '../../lib/deployment-watcher.jsx' +import { failSpinner, startSpinner, succeedSpinner } from '../../ui/spinner.js' +import { info, success, warning } from '../../ui/output.js' + +interface DropOptions { + name?: string + preset?: string + directory?: string + wait?: boolean + timeout?: string +} + +interface Candidate { + directory: string + preset: string + label: string + confidence: string + reason: string + isStatic: boolean +} + +interface Inspection { + suggestedName: string + candidates: Candidate[] +} + +export function slugName(value: string): string { + const slug = value + .toLowerCase() + .replace(/[^a-z0-9]+/g, '-') + .replace(/^-+|-+$/g, '') + .slice(0, 63) + return slug || `drop-${Math.random().toString(36).slice(2, 10)}` +} + +export async function zipDirectory(directory: string): Promise<{ data: Buffer; cleanup: () => Promise }> { + async function rejectSymlinks(current: string): Promise { + for (const entry of await readdir(current, { withFileTypes: true })) { + const path = join(current, entry.name) + const metadata = await lstat(path) + if (metadata.isSymbolicLink()) { + throw new Error(`Drop does not follow symbolic links: ${path}`) + } + if (metadata.isDirectory() && !['.git', 'node_modules'].includes(entry.name)) { + await rejectSymlinks(path) + } + } + } + + await rejectSymlinks(directory) + const temporaryDirectory = await mkdtemp(join(tmpdir(), 'temps-drop-')) + const archivePath = join(temporaryDirectory, 'source.zip') + await new Promise((resolvePromise, reject) => { + const child = spawn('zip', [ + '-q', '-r', '-y', archivePath, '.', + '-x', '.git/*', '*/.git/*', 'node_modules/*', '*/node_modules/*', + '.env', '.env.*', '*/.env', '*/.env.*', '*.pem', '*.key', + 'credentials.json', '*/credentials.json', '.DS_Store', '*/.DS_Store', + ], { cwd: directory, stdio: 'ignore' }) + child.once('error', reject) + child.once('exit', (code) => { + if (code === 0) resolvePromise() + else reject(new Error(`zip exited with status ${code ?? 'unknown'}`)) + }) + }) + return { + data: await readFile(archivePath), + cleanup: () => rm(temporaryDirectory, { recursive: true, force: true }), + } +} + +export async function drop(path: string, options: DropOptions): Promise { + await requireAuth() + await setupClient() + const sourcePath = resolve(path) + if (!existsSync(sourcePath)) throw new Error(`Path does not exist: ${sourcePath}`) + + const isDirectory = statSync(sourcePath).isDirectory() + if (!isDirectory && !sourcePath.toLowerCase().endsWith('.zip')) { + throw new Error('Source drop accepts a directory or .zip archive') + } + + startSpinner('Preparing source archive...') + let cleanup = async () => {} + let data: Buffer + if (isDirectory) { + const prepared = await zipDirectory(sourcePath) + data = prepared.data + cleanup = prepared.cleanup + } else { + data = await readFile(sourcePath) + } + + const apiUrl = normalizeApiUrl(config.get('apiUrl')) + const apiKey = await credentials.getApiKey() + const headers = { Authorization: `Bearer ${apiKey}` } + const archive = new Blob([new Uint8Array(data)], { type: 'application/zip' }) + + let projectId: number | undefined + try { + succeedSpinner(`Prepared ${(data.length / 1024 / 1024).toFixed(2)} MiB ZIP`) + startSpinner('Detecting project preset...') + const inspected = await inspectDropArchive({ + client, + body: { + file: new File( + [archive], + isDirectory ? `${basename(sourcePath)}.zip` : basename(sourcePath), + { type: 'application/zip' }, + ), + }, + }) + if (inspected.error || !inspected.data) { + throw new Error(JSON.stringify(inspected.error || 'Preset inspection returned no data')) + } + const inspection = inspected.data as Inspection + const candidate = inspection.candidates.find((item) => + (!options.preset || item.preset === options.preset) && + (!options.directory || item.directory === options.directory) + ) + if (!candidate) throw new Error('No detected project matches --preset/--directory') + succeedSpinner(`${candidate.label} (${candidate.confidence}): ${candidate.reason}`) + + const name = slugName(options.name || inspection.suggestedName || basename(sourcePath)) + startSpinner(`Creating project ${name}...`) + const created = await createProject({ + client, + body: { + name, + directory: candidate.directory, + main_branch: 'main', + preset: candidate.preset, + source_type: candidate.isStatic ? 'static_files' : 'uploaded_source', + automatic_deploy: false, + storage_service_ids: [], + }, + }) + if (created.error || !created.data) throw new Error(JSON.stringify(created.error || 'Project creation returned no data')) + projectId = created.data.id + + const environments = await getEnvironments({ client, path: { project_id: projectId } }) + const environmentList = Array.isArray(environments.data) ? environments.data : [] + const environment = environmentList.find((item) => item.name === 'production') || environmentList[0] + if (!environment) throw new Error('Created project has no environment') + succeedSpinner(`Created ${created.data.slug}`) + + startSpinner(candidate.isStatic ? 'Uploading static site...' : 'Uploading source and starting deployment...') + const deployForm = new FormData() + deployForm.append('file', archive, 'source.zip') + let deployment: { id: number; slug: string } + if (candidate.isStatic) { + const upload = await fetch(`${apiUrl}/projects/${projectId}/upload/static`, { + method: 'POST', headers, body: deployForm, + }) + if (!upload.ok) throw new Error(await upload.text()) + const bundle = (await upload.json()) as { id: number } + const response = await fetch( + `${apiUrl}/projects/${projectId}/environments/${environment.id}/deploy/static`, + { + method: 'POST', + headers: { ...headers, 'Content-Type': 'application/json' }, + body: JSON.stringify({ static_bundle_id: bundle.id }), + }, + ) + if (!response.ok) throw new Error(await response.text()) + deployment = (await response.json()) as { id: number; slug: string } + } else { + const sourceDeployment = await deployFromUploadedSource({ + client, + path: { project_id: projectId, environment_id: environment.id }, + body: { file: new File([archive], 'source.zip', { type: 'application/zip' }) }, + }) + if (sourceDeployment.error || !sourceDeployment.data) { + throw new Error(JSON.stringify(sourceDeployment.error || 'Deployment returned no data')) + } + deployment = sourceDeployment.data + } + succeedSpinner(`Deployment started: ${deployment.slug}`) + info(`Dashboard: ${config.get('apiUrl').replace(/\/api\/?$/, '')}/projects/${created.data.slug}/deployments/${deployment.id}`) + if (options.wait !== false) { + const result = await watchDeployment({ + projectId, + deploymentId: deployment.id, + timeoutSecs: Number(options.timeout || '600'), + projectName: created.data.slug, + }) + if (!result.success) process.exitCode = 1 + } else { + success('Source deployment is running in the background.') + } + } catch (error) { + failSpinner('Drop failed') + if (projectId) { + const deleted = await deleteProject({ client, path: { id: projectId } }) + if (deleted.error) warning(`Could not remove incomplete project ${projectId}`) + else info(`Removed incomplete project ${projectId}`) + } + throw error + } finally { + await cleanup() + } +} diff --git a/apps/temps-cli/src/commands/deploy/index.ts b/apps/temps-cli/src/commands/deploy/index.ts index f9fe56501..964dce1ff 100644 --- a/apps/temps-cli/src/commands/deploy/index.ts +++ b/apps/temps-cli/src/commands/deploy/index.ts @@ -7,9 +7,20 @@ import { list } from './list.js' import { logs } from './logs.js' import { rollback } from './rollback.js' import { status } from './status.js' +import { drop } from './drop.js' import { cancelDeploymentAction, pauseDeploymentAction, resumeDeploymentAction, teardownDeploymentAction } from './actions.js' export function registerDeployCommands(program: Command): void { + program + .command('drop ') + .description('Detect and deploy a local source directory or ZIP without Git') + .option('--name ', 'Project name (slugified automatically)') + .option('--preset ', 'Select a detected preset') + .option('--directory ', 'Select a detected project root') + .option('--no-wait', 'Do not wait for deployment to complete') + .option('--timeout ', 'Deployment timeout', '600') + .action(drop) + // Main deploy command - git-based deployment program .command('deploy [project]') diff --git a/crates/temps-core/src/archive_security.rs b/crates/temps-core/src/archive_security.rs new file mode 100644 index 000000000..ed84c2319 --- /dev/null +++ b/crates/temps-core/src/archive_security.rs @@ -0,0 +1,152 @@ +//! Cheap archive metadata checks that run before allocation-heavy decoders. + +use std::io::{Read, Seek, SeekFrom}; + +pub const MAX_ARCHIVE_ENTRIES: u64 = 20_000; +pub const MAX_ZIP_CENTRAL_DIRECTORY_BYTES: u64 = 64 * 1024 * 1024; + +fn invalid(message: impl Into) -> std::io::Error { + std::io::Error::new(std::io::ErrorKind::InvalidData, message.into()) +} + +fn u16_at(bytes: &[u8], offset: usize) -> Result { + let value = bytes + .get(offset..offset + 2) + .ok_or_else(|| invalid("truncated ZIP end record"))?; + Ok(u16::from_le_bytes([value[0], value[1]])) +} + +fn u32_at(bytes: &[u8], offset: usize) -> Result { + let value = bytes + .get(offset..offset + 4) + .ok_or_else(|| invalid("truncated ZIP end record"))?; + Ok(u32::from_le_bytes( + value + .try_into() + .map_err(|_| invalid("truncated ZIP end record"))?, + )) +} + +fn u64_at(bytes: &[u8], offset: usize) -> Result { + let value = bytes + .get(offset..offset + 8) + .ok_or_else(|| invalid("truncated ZIP64 end record"))?; + Ok(u64::from_le_bytes( + value + .try_into() + .map_err(|_| invalid("truncated ZIP64 end record"))?, + )) +} + +/// Reject ZIPs whose central directory can force excessive decoder allocation. +/// The ordinary or ZIP64 end record is read before constructing `ZipArchive`. +pub fn validate_zip_metadata(reader: &mut R) -> Result<(), std::io::Error> { + let archive_len = reader.seek(SeekFrom::End(0))?; + let tail_len = archive_len.min(65_557) as usize; + reader.seek(SeekFrom::End(-(tail_len as i64)))?; + let mut tail = vec![0; tail_len]; + reader.read_exact(&mut tail)?; + + let eocd = tail + .windows(4) + .enumerate() + .rev() + .find_map(|(offset, window)| { + if window != b"PK\x05\x06" || offset + 22 > tail.len() { + return None; + } + let comment_len = u16_at(&tail, offset + 20).ok()? as usize; + (offset + 22 + comment_len == tail.len()).then_some(offset) + }) + .ok_or_else(|| invalid("ZIP end-of-central-directory record not found"))?; + let disk = u16_at(&tail, eocd + 4)?; + let central_disk = u16_at(&tail, eocd + 6)?; + let entries_on_disk = u16_at(&tail, eocd + 8)?; + let entries16 = u16_at(&tail, eocd + 10)?; + let size32 = u32_at(&tail, eocd + 12)?; + let offset32 = u32_at(&tail, eocd + 16)?; + if disk != 0 || central_disk != 0 || entries_on_disk != entries16 { + return Err(invalid("multi-disk ZIP archives are not supported")); + } + + let eocd_absolute = archive_len - tail_len as u64 + eocd as u64; + let (entries, central_size, central_offset, directory_end) = + if entries16 == u16::MAX || size32 == u32::MAX || offset32 == u32::MAX { + if eocd < 20 || tail.get(eocd - 20..eocd - 16) != Some(b"PK\x06\x07") { + return Err(invalid("ZIP64 locator is missing")); + } + let zip64_offset = u64_at(&tail, eocd - 12)?; + if zip64_offset > archive_len.saturating_sub(56) { + return Err(invalid("ZIP64 end record points outside the archive")); + } + reader.seek(SeekFrom::Start(zip64_offset))?; + let mut record = [0u8; 56]; + reader.read_exact(&mut record)?; + if &record[..4] != b"PK\x06\x06" { + return Err(invalid("ZIP64 end record is invalid")); + } + ( + u64_at(&record, 32)?, + u64_at(&record, 40)?, + u64_at(&record, 48)?, + zip64_offset, + ) + } else { + ( + entries16 as u64, + size32 as u64, + offset32 as u64, + eocd_absolute, + ) + }; + + if entries > MAX_ARCHIVE_ENTRIES { + return Err(invalid(format!( + "ZIP declares {entries} entries; maximum is {MAX_ARCHIVE_ENTRIES}" + ))); + } + if central_size > MAX_ZIP_CENTRAL_DIRECTORY_BYTES { + return Err(invalid(format!( + "ZIP central directory is {central_size} bytes; maximum is {MAX_ZIP_CENTRAL_DIRECTORY_BYTES}" + ))); + } + if central_offset + .checked_add(central_size) + .is_none_or(|end| end != directory_end) + { + return Err(invalid( + "ZIP central directory does not end at its authoritative end record", + )); + } + reader.seek(SeekFrom::Start(0))?; + Ok(()) +} + +#[cfg(test)] +mod tests { + use super::*; + use std::io::Cursor; + + #[test] + fn rejects_declared_entry_count_before_decoder_construction() { + let mut bytes = vec![0u8; 22]; + bytes[..4].copy_from_slice(b"PK\x05\x06"); + bytes[8..10].copy_from_slice(&(MAX_ARCHIVE_ENTRIES as u16 + 1).to_le_bytes()); + bytes[10..12].copy_from_slice(&(MAX_ARCHIVE_ENTRIES as u16 + 1).to_le_bytes()); + let error = validate_zip_metadata(&mut Cursor::new(bytes)).unwrap_err(); + assert!(error.to_string().contains("maximum")); + } + + #[test] + fn ignores_fake_end_record_signature_inside_comment() { + let mut bytes = vec![0u8; 22 + 22]; + bytes[..4].copy_from_slice(b"PK\x05\x06"); + let too_many = MAX_ARCHIVE_ENTRIES as u16 + 1; + bytes[8..10].copy_from_slice(&too_many.to_le_bytes()); + bytes[10..12].copy_from_slice(&too_many.to_le_bytes()); + bytes[20..22].copy_from_slice(&22u16.to_le_bytes()); + bytes[22..26].copy_from_slice(b"PK\x05\x06"); + let error = validate_zip_metadata(&mut Cursor::new(bytes)).unwrap_err(); + assert!(error.to_string().contains("authoritative end record")); + } +} diff --git a/crates/temps-core/src/deployment.rs b/crates/temps-core/src/deployment.rs index fd46a47d7..ddda0e70a 100644 --- a/crates/temps-core/src/deployment.rs +++ b/crates/temps-core/src/deployment.rs @@ -90,6 +90,22 @@ pub trait DeploymentCanceller: Send + Sync { ) -> Result>; } +/// Removes source/static archives owned by a project before its database rows +/// are deleted. +/// +/// The trait lives in `temps-core` so the projects crate can require cleanup +/// without depending on the deployments crate. Implementations must be +/// idempotent: retrying after a partial cleanup must safely continue. +#[async_trait] +pub trait ProjectArchiveCleaner: Send + Sync { + /// Remove all persisted upload archives known to belong to `project_id`. + /// A failure must leave the project row intact so callers can retry. + async fn cleanup_project_archives( + &self, + project_id: i32, + ) -> Result>; +} + /// The result of a [`DeploymentGate`] check. #[derive(Debug, Clone, PartialEq, Eq)] pub enum GateDecision { diff --git a/crates/temps-core/src/lib.rs b/crates/temps-core/src/lib.rs index 304261760..8d880902e 100644 --- a/crates/temps-core/src/lib.rs +++ b/crates/temps-core/src/lib.rs @@ -125,3 +125,4 @@ pub use workflow_memory::{ // Re-export standard datetime type for use across all crates pub use types::UtcDateTime; +pub mod archive_security; diff --git a/crates/temps-core/src/workflow.rs b/crates/temps-core/src/workflow.rs index c1edc1002..a55561f5c 100644 --- a/crates/temps-core/src/workflow.rs +++ b/crates/temps-core/src/workflow.rs @@ -418,6 +418,12 @@ pub trait WorkflowTask: Send + Sync + std::fmt::Debug { async fn cleanup(&self, _context: &WorkflowContext) -> Result<(), WorkflowError> { Ok(()) } + + /// Whether cleanup must also run after the entire workflow reaches a + /// terminal state. This is for temporary inputs used by downstream jobs. + fn cleanup_after_workflow(&self) -> bool { + false + } } /// Configuration for a job in a workflow diff --git a/crates/temps-core/src/workflow_executor.rs b/crates/temps-core/src/workflow_executor.rs index 2a5321029..35e316e17 100644 --- a/crates/temps-core/src/workflow_executor.rs +++ b/crates/temps-core/src/workflow_executor.rs @@ -88,6 +88,20 @@ impl WorkflowExecutor { ) } + async fn cleanup_terminal_resources(&self, jobs: &[JobConfig], context: &WorkflowContext) { + for config in jobs { + if config.job.cleanup_after_workflow() { + if let Err(error) = config.job.cleanup(context).await { + error!( + job_id = config.job.job_id(), + %error, + "Failed to clean up workflow-scoped resources" + ); + } + } + } + } + /// Execute a workflow with proper dependency resolution and parallel execution pub async fn execute_workflow( &self, @@ -124,10 +138,23 @@ impl WorkflowExecutor { // Execute jobs in dependency order for batch in execution_order { // Check for cancellation - if cancellation_provider + let cancelled = match cancellation_provider .is_cancelled(&config.workflow_run_id) - .await? + .await { + Ok(cancelled) => cancelled, + Err(error) => { + self.cancel_remaining_pending( + &config.workflow_run_id, + format!("Cancellation status check failed: {error}"), + ) + .await; + self.cleanup_terminal_resources(&config.jobs, &context) + .await; + return Err(error); + } + }; + if cancelled { warn!("🚫 Workflow {} was cancelled", config.workflow_run_id); self.cancel_remaining_pending( @@ -136,6 +163,9 @@ impl WorkflowExecutor { ) .await; + self.cleanup_terminal_resources(&config.jobs, &context) + .await; + return Err(WorkflowError::WorkflowCancelled); } @@ -162,6 +192,8 @@ impl WorkflowExecutor { format!("Workflow aborted: {}", e), ) .await; + self.cleanup_terminal_resources(&config.jobs, &context) + .await; return Err(e); } }; @@ -191,6 +223,9 @@ impl WorkflowExecutor { for (key, value) in result.context.vars { context.vars.insert(key, value); } + if result.context.work_dir.is_some() { + context.work_dir = result.context.work_dir; + } // Update job tracker with completion status if let Some(ref tracker) = self.job_tracker { @@ -281,6 +316,9 @@ impl WorkflowExecutor { } } + self.cleanup_terminal_resources(&config.jobs, &context) + .await; + return Err(WorkflowError::JobExecutionFailed(format!( "Required job '{}' failed: {:?}", job_id, result.message @@ -297,6 +335,8 @@ impl WorkflowExecutor { "🎉 Workflow {} completed successfully", config.workflow_run_id ); + self.cleanup_terminal_resources(&config.jobs, &context) + .await; Ok(context) } @@ -804,6 +844,11 @@ mod tests { cancelled: bool, } + struct FailingCancellationProvider { + calls: AtomicUsize, + fail_on: usize, + } + #[test] fn test_cancellation_errors_are_not_failures() { assert!(WorkflowExecutor::is_cancellation_error( @@ -823,6 +868,20 @@ mod tests { } } + #[async_trait::async_trait] + impl WorkflowCancellationProvider for FailingCancellationProvider { + async fn is_cancelled(&self, _workflow_run_id: &str) -> Result { + let call = self.calls.fetch_add(1, Ordering::SeqCst) + 1; + if call == self.fail_on { + Err(WorkflowError::JobExecutionFailed( + "cancellation backend unavailable".to_string(), + )) + } else { + Ok(false) + } + } + } + // Mock LogWriter for testing struct MockLogWriter; @@ -1302,4 +1361,110 @@ mod tests { message ); } + + #[derive(Debug)] + struct TerminalCleanupJob { + cleaned: Arc, + } + + #[derive(Debug)] + struct AfterTemporarySourceJob; + + #[async_trait::async_trait] + impl WorkflowTask for AfterTemporarySourceJob { + fn job_id(&self) -> &str { + "after_temporary_source" + } + fn name(&self) -> &str { + "After temporary source" + } + fn description(&self) -> &str { + "Creates a second workflow batch" + } + fn depends_on(&self) -> Vec { + vec!["temporary_source".to_string()] + } + async fn execute(&self, context: WorkflowContext) -> Result { + Ok(JobResult::success(context)) + } + } + + #[async_trait::async_trait] + impl WorkflowTask for TerminalCleanupJob { + fn job_id(&self) -> &str { + "temporary_source" + } + + fn name(&self) -> &str { + "Temporary source" + } + + fn description(&self) -> &str { + "Creates a workflow-scoped temporary input" + } + + async fn execute(&self, context: WorkflowContext) -> Result { + Ok(JobResult::success(context)) + } + + async fn cleanup(&self, _context: &WorkflowContext) -> Result<(), WorkflowError> { + self.cleaned.fetch_add(1, Ordering::SeqCst); + Ok(()) + } + + fn cleanup_after_workflow(&self) -> bool { + true + } + } + + #[tokio::test] + async fn workflow_scoped_resources_are_cleaned_after_success() { + let cleaned = Arc::new(AtomicUsize::new(0)); + let config = WorkflowBuilder::new() + .with_workflow_run_id("cleanup-workflow".to_string()) + .with_deployment_context(1, 1, 1) + .with_log_writer(Arc::new(MockLogWriter)) + .with_job(Arc::new(TerminalCleanupJob { + cleaned: cleaned.clone(), + })) + .build() + .expect("workflow config should build"); + + WorkflowExecutor::new(None) + .execute_workflow( + config, + Arc::new(TestCancellationProvider { cancelled: false }), + ) + .await + .expect("workflow should succeed"); + + assert_eq!(cleaned.load(Ordering::SeqCst), 1); + } + + #[tokio::test] + async fn cancellation_provider_error_still_runs_terminal_cleanup() { + let cleaned = Arc::new(AtomicUsize::new(0)); + let config = WorkflowBuilder::new() + .with_workflow_run_id("cleanup-provider-error".to_string()) + .with_deployment_context(1, 1, 1) + .with_log_writer(Arc::new(MockLogWriter)) + .with_job(Arc::new(TerminalCleanupJob { + cleaned: cleaned.clone(), + })) + .with_job(Arc::new(AfterTemporarySourceJob)) + .build() + .expect("workflow config should build"); + + let result = WorkflowExecutor::new(None) + .execute_workflow( + config, + Arc::new(FailingCancellationProvider { + calls: AtomicUsize::new(0), + fail_on: 1, + }), + ) + .await; + assert!(result.is_err()); + assert_eq!(cleaned.load(Ordering::SeqCst), 1); + } } diff --git a/crates/temps-deployer/src/compose.rs b/crates/temps-deployer/src/compose.rs index 93c2a5ec1..35ca3d52c 100644 --- a/crates/temps-deployer/src/compose.rs +++ b/crates/temps-deployer/src/compose.rs @@ -235,27 +235,76 @@ impl ComposeExecutor { /// Tear down containers before a redeploy. Preserves volumes (database data, /// uploads, etc.) so they survive between deployments. pub async fn teardown_for_redeploy(&self, project_name: &str) -> Result<(), ComposeError> { - let project_dir = self.project_dir(project_name); + self.teardown_at(project_name, None, None, &HashMap::new()) + .await + } + + /// Tear down a Compose stack from the exact directory used for `up`. + /// Uploaded/Git deployments run Compose inside their checkout rather than + /// the data-dir fallback, so compensation must retain that location. + pub async fn teardown_at( + &self, + project_name: &str, + repo_dir: Option<&Path>, + compose_path: Option<&str>, + environment_vars: &HashMap, + ) -> Result<(), ComposeError> { + if let Some(compose_path) = compose_path { + Self::validate_relative_path(compose_path, "compose_path")?; + } + let project_dir = repo_dir + .map(Path::to_path_buf) + .unwrap_or_else(|| self.project_dir(project_name)); if !project_dir.exists() { debug!(project = %project_name, "Project directory does not exist, nothing to tear down"); return Ok(()); } - let compose_file = self.find_compose_file(&project_dir); + let compose_file = compose_path + .map(ToString::to_string) + .unwrap_or_else(|| self.find_compose_file(&project_dir)); // down WITHOUT --volumes: removes containers and networks, keeps volumes - let output = tokio::process::Command::new("docker") + let mut command = tokio::process::Command::new("docker"); + command .args(["compose", "-p", project_name]) - .args(["-f", &compose_file]) - .args(["down", "--remove-orphans"]) + .args(["-f", &compose_file]); + for generated in [ + "docker-compose.temps-env.yml", + "docker-compose.temps-override.yml", + "docker-compose.temps-labels.yml", + "docker-compose.temps-security.yml", + ] { + if project_dir.join(generated).exists() { + command.args(["-f", generated]); + } + } + for env_file in [".env.temps", ".env"] { + if project_dir.join(env_file).exists() { + command.args(["--env-file", env_file]); + } + } + for (key, value) in environment_vars { + command.env(key, value); + } + command + .args(["down", "--remove-orphans", "--timeout", "30"]) .current_dir(&project_dir) - .output() - .await?; + .kill_on_drop(true); + let output = tokio::time::timeout(std::time::Duration::from_secs(35), command.output()) + .await + .map_err(|_| ComposeError::CommandFailed { + project: project_name.to_string(), + reason: "docker compose down timed out after 35 seconds".to_string(), + })??; if !output.status.success() { let stderr = String::from_utf8_lossy(&output.stderr); - warn!(project = %project_name, stderr = %stderr, "docker compose down failed (best-effort)"); + return Err(ComposeError::CommandFailed { + project: project_name.to_string(), + reason: format!("docker compose down failed: {stderr}"), + }); } info!(project = %project_name, "Compose stack torn down (volumes preserved)"); @@ -1944,6 +1993,7 @@ impl ComposeExecutor { "shm_size", "tmpfs", "ulimits", + "labels", ]; for key in service.keys().filter_map(Self::yaml_key) { @@ -2054,18 +2104,19 @@ impl ComposeExecutor { cmd.args(["-f", "docker-compose.temps-env.yml"]); } - // Include Temps labels override (injects sh.temps.* labels for log collection) - let labels_override = project_dir.join("docker-compose.temps-labels.yml"); - if labels_override.exists() { - cmd.args(["-f", "docker-compose.temps-labels.yml"]); - } - // Include user-provided override (ports, volumes, etc.) let user_override = project_dir.join("docker-compose.temps-override.yml"); if user_override.exists() { cmd.args(["-f", "docker-compose.temps-override.yml"]); } + // Apply reserved ownership labels after all tenant-controlled files so + // an inline override cannot erase or spoof the cleanup boundary. + let labels_override = project_dir.join("docker-compose.temps-labels.yml"); + if labels_override.exists() { + cmd.args(["-f", "docker-compose.temps-labels.yml"]); + } + // Include Temps security override LAST so its sandbox hardening // (cap_drop, no-new-privileges, pids_limit, init) wins over anything a // user/preset override tried to weaken. Compose applies `-f` files in @@ -2105,6 +2156,10 @@ impl ComposeExecutor { cmd.env(key, value); } + // Cancellation drops the command future; terminate the Compose CLI so + // compensating `compose down` cannot race a still-running `compose up`. + cmd.kill_on_drop(true); + debug!(project = %project_name, "Running docker compose up"); let output = cmd.output().await?; @@ -2822,6 +2877,7 @@ services: "sysctls: {net.ipv4.ip_forward: '1'}", "volumes: ['/:/host:rw']", "volumes_from: ['container:temps-db']", + "labels: {sh.temps.managed: 'false'}", ]; for dangerous_override in dangerous_overrides { diff --git a/crates/temps-deployer/src/remote.rs b/crates/temps-deployer/src/remote.rs index 202270120..e3058de23 100644 --- a/crates/temps-deployer/src/remote.rs +++ b/crates/temps-deployer/src/remote.rs @@ -285,6 +285,11 @@ impl RemoteNodeDeployer { self.node_name, url, e )) })?; + let status = response.status(); + + if status == reqwest::StatusCode::NOT_FOUND { + return Err(DeployerError::ContainerNotFound(path.to_string())); + } let status = response.status(); diff --git a/crates/temps-deployments/Cargo.toml b/crates/temps-deployments/Cargo.toml index 932f8b30d..b8adbc74a 100644 --- a/crates/temps-deployments/Cargo.toml +++ b/crates/temps-deployments/Cargo.toml @@ -61,6 +61,8 @@ zip = { workspace = true } rand = { workspace = true } sha2 = { workspace = true } hex = { workspace = true } +libc = { workspace = true } +tempfile = { workspace = true } urlencoding = { workspace = true } tokio-tungstenite = { workspace = true } # mTLS for the terminal WebSocket proxy (ADR-020 WS-2.1): build a rustls @@ -74,7 +76,6 @@ tokio-test = "0.4" mockall = "0.15" tower = { workspace = true } env_logger = "0.11" -tempfile = "3.8" [features] default = [] diff --git a/crates/temps-deployments/src/handlers/audit.rs b/crates/temps-deployments/src/handlers/audit.rs index effc511c3..f4beee510 100644 --- a/crates/temps-deployments/src/handlers/audit.rs +++ b/crates/temps-deployments/src/handlers/audit.rs @@ -110,6 +110,15 @@ pub struct DeployFromStaticAudit { pub deployment_id: i32, } +#[derive(Debug, Clone, Serialize)] +pub struct DeployFromUploadedSourceAudit { + pub context: AuditContext, + pub project_id: i32, + pub environment_id: i32, + pub deployment_id: i32, + pub source_bundle_id: i32, +} + #[derive(Debug, Clone, Serialize)] pub struct DeployFromImageUploadAudit { pub context: AuditContext, @@ -219,6 +228,7 @@ impl_audit_operation!(ExternalImagePushedAudit, "EXTERNAL_IMAGE_PUSHED"); impl_audit_operation!(DeploymentOperationAudit, "DEPLOYMENT_OPERATION_EXECUTED"); impl_audit_operation!(DeployFromImageAudit, "DEPLOY_FROM_IMAGE"); impl_audit_operation!(DeployFromStaticAudit, "DEPLOY_FROM_STATIC"); +impl_audit_operation!(DeployFromUploadedSourceAudit, "DEPLOY_FROM_UPLOADED_SOURCE"); impl_audit_operation!(DeployFromImageUploadAudit, "DEPLOY_FROM_IMAGE_UPLOAD"); impl_audit_operation!(StaticBundleUploadedAudit, "STATIC_BUNDLE_UPLOADED"); impl_audit_operation!(ExternalImageRegisteredAudit, "EXTERNAL_IMAGE_REGISTERED"); diff --git a/crates/temps-deployments/src/handlers/remote_deployments.rs b/crates/temps-deployments/src/handlers/remote_deployments.rs index b3b6b5ae8..a1dd5844e 100644 --- a/crates/temps-deployments/src/handlers/remote_deployments.rs +++ b/crates/temps-deployments/src/handlers/remote_deployments.rs @@ -3,12 +3,13 @@ //! Handles remote deployments from pre-built Docker images and static file bundles. //! These endpoints enable external CI/CD systems to deploy to Temps without Git integration. +use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::Arc; use super::audit::{ DeployFromImageAudit, DeployFromImageUploadAudit, DeployFromStaticAudit, - ExternalImageDeletedAudit, ExternalImageRegisteredAudit, StaticBundleDeletedAudit, - StaticBundleUploadedAudit, + DeployFromUploadedSourceAudit, ExternalImageDeletedAudit, ExternalImageRegisteredAudit, + StaticBundleDeletedAudit, StaticBundleUploadedAudit, }; use super::types::AppState; use axum::{ @@ -19,7 +20,9 @@ use axum::{ Json, Router, }; use chrono::Utc; -use sea_orm::{ActiveModelTrait, ColumnTrait, EntityTrait, PaginatorTrait, QueryFilter, Set}; +use sea_orm::{ + ActiveModelTrait, ColumnTrait, EntityTrait, PaginatorTrait, QueryFilter, Set, TransactionTrait, +}; use serde::{Deserialize, Serialize}; use temps_auth::{permission_guard, project_access_guard, project_permission_guard, RequireAuth}; use temps_core::problemdetails::{self, Problem}; @@ -27,7 +30,8 @@ use temps_core::{AuditContext, DeploymentCreatedJob, Job, RequestMetadata, UtcDa use temps_entities::deployments::DeploymentMetadata; use temps_entities::source_type::SourceType; use temps_entities::types::PipelineStatus; -use temps_entities::{deployments, environments, projects}; +use temps_entities::{deployments, environments, projects, source_bundles}; +use tokio::io::AsyncWriteExt; use tracing::{debug, error, info, warn}; use utoipa::{IntoParams, OpenApi, ToSchema}; @@ -39,6 +43,7 @@ use crate::services::{ExternalImageInfo, RegisterExternalImageRequest, StaticBun deploy_from_image, deploy_from_image_upload, deploy_from_static, + deploy_from_uploaded_source, upload_static_bundle, register_external_image, list_remote_external_images, @@ -66,6 +71,408 @@ use crate::services::{ExternalImageInfo, RegisterExternalImageRequest, StaticBun )] pub struct RemoteDeploymentsApiDoc; +#[derive(ToSchema)] +pub struct SourceArchiveUpload { + #[schema(value_type = String, format = Binary)] + pub file: String, +} + +static ARCHIVE_UPLOADS_IN_FLIGHT: AtomicUsize = AtomicUsize::new(0); + +struct ArchiveUploadPermit; + +impl ArchiveUploadPermit { + fn acquire() -> Result { + ARCHIVE_UPLOADS_IN_FLIGHT + .fetch_update(Ordering::AcqRel, Ordering::Acquire, |current| { + (current < 4).then_some(current + 1) + }) + .map_err(|_| { + problemdetails::new(StatusCode::TOO_MANY_REQUESTS) + .with_title("Too Many Archive Uploads") + .with_detail( + "At most four source or static archives may be uploaded concurrently", + ) + })?; + Ok(Self) + } +} + +impl Drop for ArchiveUploadPermit { + fn drop(&mut self) { + ARCHIVE_UPLOADS_IN_FLIGHT.fetch_sub(1, Ordering::AcqRel); + } +} + +async fn read_bounded_multipart_text( + mut field: axum::extract::multipart::Field<'_>, + label: &str, + max_bytes: usize, +) -> Result { + let mut bytes = Vec::new(); + while let Some(chunk) = field.chunk().await.map_err(|error| { + problemdetails::new(StatusCode::BAD_REQUEST) + .with_title("Multipart Field Error") + .with_detail(format!("Failed to read {label}: {error}")) + })? { + if bytes.len().saturating_add(chunk.len()) > max_bytes { + return Err(problemdetails::new(StatusCode::PAYLOAD_TOO_LARGE) + .with_title("Multipart Field Too Large") + .with_detail(format!("{label} exceeds {max_bytes} bytes"))); + } + bytes.extend_from_slice(&chunk); + } + String::from_utf8(bytes).map_err(|error| { + problemdetails::new(StatusCode::BAD_REQUEST) + .with_title("Invalid Multipart Text") + .with_detail(format!("{label} is not valid UTF-8: {error}")) + }) +} + +async fn rollback_uploaded_source( + state: &AppState, + deployment_id: Option, + bundle_id: Option, + archive_path: &std::path::Path, +) { + if let Some(deployment_id) = deployment_id { + if let Err(error) = deployments::Entity::delete_by_id(deployment_id) + .exec(state.db.as_ref()) + .await + { + error!(deployment_id, %error, "Failed to roll back uploaded-source deployment"); + } + } + if let Some(bundle_id) = bundle_id { + if let Err(error) = source_bundles::Entity::delete_by_id(bundle_id) + .exec(state.db.as_ref()) + .await + { + error!(bundle_id, %error, "Failed to roll back source-bundle row"); + } + } + if let Err(error) = tokio::fs::remove_file(archive_path).await { + if error.kind() != std::io::ErrorKind::NotFound { + error!(path = %archive_path.display(), %error, "Failed to roll back source archive"); + } + } +} + +/// Upload source code and immediately start a preset-based deployment. +#[utoipa::path( + post, + tag = "Deployments", + path = "/projects/{project_id}/environments/{environment_id}/deploy/source", + request_body(content = SourceArchiveUpload, content_type = "multipart/form-data"), + responses( + (status = 202, description = "Source deployment started", body = RemoteDeploymentResponse), + (status = 400, description = "Invalid source archive"), + (status = 404, description = "Project or environment not found") + ), + security(("bearer_auth" = [])) +)] +pub async fn deploy_from_uploaded_source( + RequireAuth(auth): RequireAuth, + State(state): State>, + Path((project_id, environment_id)): Path<(i32, i32)>, + Extension(metadata): Extension, + mut multipart: Multipart, +) -> Result { + project_permission_guard!( + auth, + DeploymentsCreate, + project_id, + state.project_access_checker + ); + let upload_permit = ArchiveUploadPermit::acquire()?; + + let project = projects::Entity::find_by_id(project_id) + .filter(projects::Column::IsDeleted.eq(false)) + .one(state.db.as_ref()) + .await + .map_err(|error| { + problemdetails::new(StatusCode::INTERNAL_SERVER_ERROR) + .with_title("Database Error") + .with_detail(error.to_string()) + })? + .ok_or_else(|| { + problemdetails::new(StatusCode::NOT_FOUND) + .with_title("Project Not Found") + .with_detail(format!("Project {project_id} not found")) + })?; + if project.source_type != SourceType::UploadedSource { + return Err(problemdetails::new(StatusCode::BAD_REQUEST) + .with_title("Invalid Project Type") + .with_detail("Source archives require a project with source_type 'uploaded_source'")); + } + let environment = environments::Entity::find_by_id(environment_id) + .filter(environments::Column::DeletedAt.is_null()) + .one(state.db.as_ref()) + .await + .map_err(|error| { + problemdetails::new(StatusCode::INTERNAL_SERVER_ERROR) + .with_title("Database Error") + .with_detail(error.to_string()) + })? + .filter(|environment| environment.project_id == project_id) + .ok_or_else(|| { + problemdetails::new(StatusCode::NOT_FOUND) + .with_title("Environment Not Found") + .with_detail("Environment does not belong to the project") + })?; + + const MAX_SOURCE_BYTES: u64 = 500 * 1024 * 1024; + let relative_path = format!("source-bundles/{}.zip", uuid::Uuid::new_v4()); + let absolute_path = state.data_dir.join(&relative_path); + if let Some(parent) = absolute_path.parent() { + tokio::fs::create_dir_all(parent).await.map_err(|error| { + problemdetails::new(StatusCode::INTERNAL_SERVER_ERROR) + .with_title("Source Storage Failed") + .with_detail(error.to_string()) + })?; + } + let staging_directory = absolute_path.parent().ok_or_else(|| { + problemdetails::new(StatusCode::INTERNAL_SERVER_ERROR) + .with_title("Source Storage Failed") + .with_detail("Source archive path has no storage directory") + })?; + let staged_archive = tempfile::NamedTempFile::new_in(staging_directory).map_err(|error| { + problemdetails::new(StatusCode::INTERNAL_SERVER_ERROR) + .with_title("Source Storage Failed") + .with_detail(error.to_string()) + })?; + + use sha2::{Digest, Sha256}; + let mut hasher = Sha256::new(); + let mut size_bytes = 0u64; + let mut archive_received = false; + let mut original_filename = None; + while let Some(field) = multipart.next_field().await.map_err(|error| { + problemdetails::new(StatusCode::BAD_REQUEST) + .with_title("Multipart Error") + .with_detail(error.to_string()) + })? { + if field.name() == Some("file") { + original_filename = field.file_name().map(ToString::to_string); + let staging_file = staged_archive.reopen().map_err(|error| { + problemdetails::new(StatusCode::INTERNAL_SERVER_ERROR) + .with_title("Source Storage Failed") + .with_detail(error.to_string()) + })?; + let mut output = tokio::fs::File::from_std(staging_file); + let mut field = field; + while let Some(chunk) = field.chunk().await.map_err(|error| { + problemdetails::new(StatusCode::BAD_REQUEST) + .with_title("File Read Error") + .with_detail(error.to_string()) + })? { + size_bytes = size_bytes.saturating_add(chunk.len() as u64); + if size_bytes > MAX_SOURCE_BYTES { + return Err(problemdetails::new(StatusCode::PAYLOAD_TOO_LARGE) + .with_title("Source Archive Too Large") + .with_detail("Source archive exceeds 500 MiB")); + } + hasher.update(&chunk); + output.write_all(&chunk).await.map_err(|error| { + problemdetails::new(StatusCode::INTERNAL_SERVER_ERROR) + .with_title("Source Storage Failed") + .with_detail(error.to_string()) + })?; + } + output.flush().await.map_err(|error| { + problemdetails::new(StatusCode::INTERNAL_SERVER_ERROR) + .with_title("Source Storage Failed") + .with_detail(error.to_string()) + })?; + archive_received = true; + break; + } + } + if !archive_received { + return Err(problemdetails::new(StatusCode::BAD_REQUEST) + .with_title("Missing Source Archive") + .with_detail("Expected a ZIP archive in multipart field 'file'")); + } + let validation_path = staged_archive.path().to_path_buf(); + tokio::task::spawn_blocking(move || { + let _upload_permit = upload_permit; + let mut file = std::fs::File::open(&validation_path)?; + temps_core::archive_security::validate_zip_metadata(&mut file)?; + zip::ZipArchive::new(file) + .map(|_| ()) + .map_err(std::io::Error::other) + }) + .await + .map_err(|error| { + problemdetails::new(StatusCode::INTERNAL_SERVER_ERROR) + .with_title("ZIP Validation Failed") + .with_detail(error.to_string()) + })? + .map_err(|error| { + problemdetails::new(StatusCode::BAD_REQUEST) + .with_title("Invalid ZIP Archive") + .with_detail(error.to_string()) + })?; + + staged_archive.persist(&absolute_path).map_err(|error| { + problemdetails::new(StatusCode::INTERNAL_SERVER_ERROR) + .with_title("Source Storage Failed") + .with_detail(error.error.to_string()) + })?; + + let checksum = format!("sha256:{}", hex::encode(hasher.finalize())); + + let transaction = state.db.begin().await.map_err(|error| { + problemdetails::new(StatusCode::INTERNAL_SERVER_ERROR) + .with_title("Source Registration Failed") + .with_detail(error.to_string()) + })?; + let now = Utc::now(); + let bundle = match (source_bundles::ActiveModel { + project_id: Set(project_id), + archive_path: Set(relative_path.clone()), + original_filename: Set(original_filename), + content_type: Set("application/zip".to_string()), + size_bytes: Set(size_bytes as i64), + checksum: Set(checksum), + directory: Set(project.directory.clone()), + preset: Set(project.preset.as_str().to_string()), + metadata: Set(None), + uploaded_at: Set(now), + created_at: Set(now), + ..Default::default() + }) + .insert(&transaction) + .await + { + Ok(bundle) => bundle, + Err(error) => { + rollback_uploaded_source(&state, None, None, &absolute_path).await; + return Err(problemdetails::new(StatusCode::INTERNAL_SERVER_ERROR) + .with_title("Source Registration Failed") + .with_detail(error.to_string())); + } + }; + + let deployment = match (deployments::ActiveModel { + project_id: Set(project_id), + environment_id: Set(environment_id), + slug: Set(format!( + "{}-{}", + project.slug, + &uuid::Uuid::new_v4().simple().to_string()[..12] + )), + state: Set("pending".to_string()), + metadata: Set(Some(DeploymentMetadata { + source_bundle_id: Some(bundle.id), + source_bundle_path: Some(relative_path), + source_bundle_content_type: Some("application/zip".to_string()), + deployment_source_type: Some(SourceType::UploadedSource), + ..Default::default() + })), + context_vars: Set(Some( + serde_json::json!({"trigger":"drop","source":"uploaded_source","bundle_id":bundle.id}), + )), + created_at: Set(now), + updated_at: Set(now), + ..Default::default() + }) + .insert(&transaction) + .await + { + Ok(deployment) => deployment, + Err(error) => { + let _ = transaction.rollback().await; + rollback_uploaded_source(&state, None, None, &absolute_path).await; + return Err(problemdetails::new(StatusCode::INTERNAL_SERVER_ERROR) + .with_title("Deployment Creation Failed") + .with_detail(error.to_string())); + } + }; + + if let Err(error) = transaction.commit().await { + rollback_uploaded_source(&state, None, None, &absolute_path).await; + return Err(problemdetails::new(StatusCode::INTERNAL_SERVER_ERROR) + .with_title("Source Registration Failed") + .with_detail(format!("Failed to commit source deployment: {error}"))); + } + + if let Err(error) = state + .workflow_planner + .create_deployment_jobs(deployment.id) + .await + { + rollback_uploaded_source(&state, Some(deployment.id), Some(bundle.id), &absolute_path) + .await; + return Err(problemdetails::new(StatusCode::INTERNAL_SERVER_ERROR) + .with_title("Job Creation Failed") + .with_detail(error.to_string())); + } + + if let Err(error) = state + .queue_service + .send(Job::DeploymentCreated(DeploymentCreatedJob { + deployment_id: deployment.id, + project_id, + environment_id, + environment_name: environment.name.clone(), + branch: None, + commit_sha: None, + })) + .await + { + rollback_uploaded_source(&state, Some(deployment.id), Some(bundle.id), &absolute_path) + .await; + return Err(problemdetails::new(StatusCode::INTERNAL_SERVER_ERROR) + .with_title("Deployment Queue Failed") + .with_detail(error.to_string())); + } + let workflow_executor = state.workflow_executor.clone(); + let deployment_gate = state.deployment_gate.clone(); + let db = state.db.clone(); + let environment_name = environment.name.clone(); + let deployment_id = deployment.id; + tokio::spawn(async move { + crate::services::job_processor::JobProcessorService::gate_check_then_run( + &db, + &workflow_executor, + &deployment_gate, + project_id, + &environment_name, + deployment_id, + ) + .await; + }); + + let audit = DeployFromUploadedSourceAudit { + context: AuditContext { + user_id: auth.user_id(), + ip_address: Some(metadata.ip_address.clone()), + user_agent: metadata.user_agent.clone(), + }, + project_id, + environment_id, + deployment_id, + source_bundle_id: bundle.id, + }; + if let Err(error) = state.audit_service.create_audit_log(&audit).await { + error!("Failed to create uploaded-source audit log: {error}"); + } + + Ok(( + StatusCode::ACCEPTED, + Json(RemoteDeploymentResponse { + id: deployment.id, + project_id, + environment_id, + slug: deployment.slug, + state: deployment.state, + source_type: "uploaded_source".to_string(), + created_at: deployment.created_at, + }), + )) +} + // Request Types #[derive(Debug, Clone, Deserialize, ToSchema)] @@ -1380,6 +1787,7 @@ pub async fn upload_static_bundle( project_id, state.project_access_checker ); + let _static_upload_permit = ArchiveUploadPermit::acquire()?; debug!("Uploading static bundle for project {}", project_id); @@ -1413,15 +1821,31 @@ pub async fn upload_static_bundle( ))); } - // 2. Read the uploaded file from multipart - let mut file_data: Option = None; + // 2. Stream the uploaded file into the static-bundle storage directory. + let staging_directory = state.data_dir.join("static-bundles"); + tokio::fs::create_dir_all(&staging_directory) + .await + .map_err(|error| { + problemdetails::new(StatusCode::INTERNAL_SERVER_ERROR) + .with_title("Upload Failed") + .with_detail(format!("Failed to create storage directory: {error}")) + })?; + let staged_bundle = tempfile::NamedTempFile::new_in(&staging_directory).map_err(|error| { + problemdetails::new(StatusCode::INTERNAL_SERVER_ERROR) + .with_title("Upload Failed") + .with_detail(format!("Failed to create upload staging file: {error}")) + })?; + let mut file_received = false; + let mut size_bytes = 0u64; + use sha2::{Digest, Sha256}; + let mut hasher = Sha256::new(); let mut original_filename: Option = None; let mut content_type: Option = None; let mut explicit_content_type: Option = None; // From form field let mut metadata: Option = None; // Maximum file size: 500MB - const MAX_FILE_SIZE: usize = 500 * 1024 * 1024; + const MAX_FILE_SIZE: u64 = 500 * 1024 * 1024; while let Some(field) = multipart.next_field().await.map_err(|e| { error!("Multipart error: {}", e); @@ -1433,46 +1857,54 @@ pub async fn upload_static_bundle( match name.as_str() { "file" => { + if file_received { + return Err(problemdetails::new(StatusCode::BAD_REQUEST) + .with_title("Duplicate File") + .with_detail("Only one static bundle may be uploaded per request")); + } original_filename = field.file_name().map(|s| s.to_string()); content_type = field.content_type().map(|s| s.to_string()); - let data = field.bytes().await.map_err(|e| { - error!("Failed to read file data: {}", e); + let staging_file = staged_bundle.reopen().map_err(|error| { + problemdetails::new(StatusCode::INTERNAL_SERVER_ERROR) + .with_title("Upload Failed") + .with_detail(format!("Failed to open upload staging file: {error}")) + })?; + let mut output = tokio::fs::File::from_std(staging_file); + let mut field = field; + while let Some(chunk) = field.chunk().await.map_err(|error| { problemdetails::new(StatusCode::BAD_REQUEST) .with_title("File Read Error") - .with_detail(e.to_string()) - })?; - - if data.len() > MAX_FILE_SIZE { - return Err(problemdetails::new(StatusCode::PAYLOAD_TOO_LARGE) - .with_title("File Too Large") - .with_detail(format!( - "File size {} exceeds maximum allowed size of {}", - data.len(), - MAX_FILE_SIZE - ))); + .with_detail(error.to_string()) + })? { + size_bytes = size_bytes.saturating_add(chunk.len() as u64); + if size_bytes > MAX_FILE_SIZE { + return Err(problemdetails::new(StatusCode::PAYLOAD_TOO_LARGE) + .with_title("File Too Large") + .with_detail("Static bundle exceeds 500 MiB")); + } + hasher.update(&chunk); + output.write_all(&chunk).await.map_err(|error| { + problemdetails::new(StatusCode::INTERNAL_SERVER_ERROR) + .with_title("Upload Failed") + .with_detail(format!("Failed to stage static bundle: {error}")) + })?; } - - file_data = Some(data); + output.flush().await.map_err(|error| { + problemdetails::new(StatusCode::INTERNAL_SERVER_ERROR) + .with_title("Upload Failed") + .with_detail(format!("Failed to flush static bundle: {error}")) + })?; + file_received = true; } "metadata" => { - let data = field.text().await.map_err(|e| { - error!("Failed to read metadata: {}", e); - problemdetails::new(StatusCode::BAD_REQUEST) - .with_title("Metadata Error") - .with_detail(e.to_string()) - })?; + let data = read_bounded_multipart_text(field, "metadata", 64 * 1024).await?; metadata = serde_json::from_str(&data).ok(); } "content_type" => { // Explicit content_type field from CLI (more reliable than multipart header) - let data = field.text().await.map_err(|e| { - error!("Failed to read content_type field: {}", e); - problemdetails::new(StatusCode::BAD_REQUEST) - .with_title("Content Type Error") - .with_detail(e.to_string()) - })?; + let data = read_bounded_multipart_text(field, "content_type", 256).await?; explicit_content_type = Some(data); } _ => { @@ -1487,13 +1919,11 @@ pub async fn upload_static_bundle( } // Ensure file was provided - let file_bytes = file_data.ok_or_else(|| { - problemdetails::new(StatusCode::BAD_REQUEST) + if !file_received { + return Err(problemdetails::new(StatusCode::BAD_REQUEST) .with_title("Missing File") - .with_detail("No file was provided in the multipart request") - })?; - - let size_bytes = file_bytes.len() as i64; + .with_detail("No file was provided in the multipart request")); + } // 3. Validate content type (tar.gz or zip) // Detect from filename if content type is missing or generic (application/octet-stream) @@ -1590,34 +2020,24 @@ pub async fn upload_static_bundle( } } - // Calculate checksum - use sha2::{Digest, Sha256}; - let mut hasher = Sha256::new(); - hasher.update(&file_bytes); + // Calculate checksum accumulated while streaming the upload. let checksum = format!("sha256:{}", hex::encode(hasher.finalize())); // Store static bundle in local data directory let local_path = state.data_dir.join(&blob_path); - // Ensure parent directory exists - if let Some(parent) = local_path.parent() { - tokio::fs::create_dir_all(parent).await.map_err(|e| { - error!("Failed to create directory for static bundle: {}", e); - problemdetails::new(StatusCode::INTERNAL_SERVER_ERROR) - .with_title("Upload Failed") - .with_detail(format!("Failed to create storage directory: {}", e)) - })?; - } - - // Write file to local filesystem - tokio::fs::write(&local_path, &file_bytes) - .await - .map_err(|e| { - error!("Failed to write static bundle to local storage: {}", e); - problemdetails::new(StatusCode::INTERNAL_SERVER_ERROR) - .with_title("Upload Failed") - .with_detail(format!("Failed to write file to local storage: {}", e)) - })?; + staged_bundle.persist(&local_path).map_err(|error| { + error!( + "Failed to persist static bundle to local storage: {}", + error.error + ); + problemdetails::new(StatusCode::INTERNAL_SERVER_ERROR) + .with_title("Upload Failed") + .with_detail(format!( + "Failed to persist file to local storage: {}", + error.error + )) + })?; info!( "Uploaded static bundle to local storage: {} ({} bytes)", @@ -1637,7 +2057,7 @@ pub async fn upload_static_bundle( .register_static_bundle( project_id, blob_path, - size_bytes, + size_bytes as i64, upload_request, Some(checksum), ) @@ -2077,6 +2497,10 @@ pub fn configure_routes() -> Router> { "/projects/{project_id}/environments/{environment_id}/deploy/static", post(deploy_from_static), ) + .route( + "/projects/{project_id}/environments/{environment_id}/deploy/source", + post(deploy_from_uploaded_source).layer(DefaultBodyLimit::max(501 * 1024 * 1024)), + ) // Upload endpoints with increased body limit .route( "/projects/{project_id}/environments/{environment_id}/deploy/image-upload", diff --git a/crates/temps-deployments/src/jobs/build_image.rs b/crates/temps-deployments/src/jobs/build_image.rs index beb3c6bce..88d7a3298 100644 --- a/crates/temps-deployments/src/jobs/build_image.rs +++ b/crates/temps-deployments/src/jobs/build_image.rs @@ -6,6 +6,7 @@ use async_trait::async_trait; use serde::{Deserialize, Serialize}; use std::collections::HashMap; use std::fs; +use std::io::{Read, Write}; use std::path::{Path, PathBuf}; use std::sync::Arc; use temps_core::{ @@ -18,6 +19,126 @@ use temps_logs::{LogLevel, LogService}; use temps_presets; use tokio::time::{sleep, Duration}; +fn validate_relative_build_path(path: &Path, label: &str) -> Result<(), WorkflowError> { + if path.as_os_str().is_empty() + || path.is_absolute() + || path.components().any(|component| { + matches!( + component, + std::path::Component::ParentDir + | std::path::Component::RootDir + | std::path::Component::Prefix(_) + ) + }) + { + return Err(WorkflowError::JobValidationFailed(format!( + "{label} '{}' must be relative and contained by the build context", + path.display() + ))); + } + Ok(()) +} + +fn validate_confined_regular_file(root: &Path, path: &Path) -> Result<(), WorkflowError> { + let metadata = fs::symlink_metadata(path).map_err(WorkflowError::IoError)?; + if metadata.file_type().is_symlink() || !metadata.is_file() { + return Err(WorkflowError::JobValidationFailed(format!( + "Build input '{}' must be a regular non-symlink file", + path.display() + ))); + } + let canonical = path.canonicalize().map_err(WorkflowError::IoError)?; + if !canonical.starts_with(root) { + return Err(WorkflowError::JobValidationFailed(format!( + "Build input '{}' escapes build context '{}'", + canonical.display(), + root.display() + ))); + } + Ok(()) +} + +fn write_no_follow(path: &Path, contents: &[u8], create_new: bool) -> Result<(), WorkflowError> { + let mut options = fs::OpenOptions::new(); + options.write(true); + if create_new { + options.create_new(true); + } else { + options.create(true).truncate(true); + } + #[cfg(unix)] + { + use std::os::unix::fs::OpenOptionsExt; + options.custom_flags(libc::O_NOFOLLOW); + } + let mut file = options.open(path).map_err(WorkflowError::IoError)?; + if !file.metadata().map_err(WorkflowError::IoError)?.is_file() { + return Err(WorkflowError::JobValidationFailed(format!( + "Build output '{}' must be a regular file", + path.display() + ))); + } + file.write_all(contents).map_err(WorkflowError::IoError) +} + +fn read_confined_control_file( + root: &Path, + path: &Path, + max_bytes: u64, +) -> Result, WorkflowError> { + let canonical_root = root.canonicalize().map_err(WorkflowError::IoError)?; + let metadata = match fs::symlink_metadata(path) { + Ok(metadata) => metadata, + Err(error) if error.kind() == std::io::ErrorKind::NotFound => return Ok(None), + Err(error) => return Err(WorkflowError::IoError(error)), + }; + if metadata.file_type().is_symlink() || !metadata.is_file() { + return Err(WorkflowError::JobValidationFailed(format!( + "Build control file '{}' must be a regular non-symlink file", + path.display() + ))); + } + let canonical = path.canonicalize().map_err(WorkflowError::IoError)?; + if !canonical.starts_with(&canonical_root) { + return Err(WorkflowError::JobValidationFailed(format!( + "Build control file '{}' escapes build context '{}'", + canonical.display(), + canonical_root.display() + ))); + } + if metadata.len() > max_bytes { + return Err(WorkflowError::JobValidationFailed(format!( + "Build control file '{}' exceeds the {max_bytes} byte limit", + path.display() + ))); + } + let mut contents = String::new(); + let mut options = fs::OpenOptions::new(); + options.read(true); + #[cfg(unix)] + { + use std::os::unix::fs::OpenOptionsExt; + options.custom_flags(libc::O_NOFOLLOW); + } + let file = options.open(path).map_err(WorkflowError::IoError)?; + if !file.metadata().map_err(WorkflowError::IoError)?.is_file() { + return Err(WorkflowError::JobValidationFailed(format!( + "Build control file '{}' must remain a regular file", + path.display() + ))); + } + file.take(max_bytes + 1) + .read_to_string(&mut contents) + .map_err(WorkflowError::IoError)?; + if contents.len() as u64 > max_bytes { + return Err(WorkflowError::JobValidationFailed(format!( + "Build control file '{}' exceeds the {max_bytes} byte limit", + path.display() + ))); + } + Ok(Some(contents)) +} + /// Typed output from DownloadRepoJob #[derive(Debug, Clone, Serialize, Deserialize)] pub struct RepositoryOutput { @@ -307,25 +428,30 @@ impl BuildImageJob { build_context_dir: &Path, ) -> Result<(), WorkflowError> { let nixpacks_toml_path = build_context_dir.join("nixpacks.toml"); + let hidden_nixpacks_toml_path = build_context_dir.join(".nixpacks.toml"); let package_json_path = build_context_dir.join("package.json"); - // Skip if nixpacks.toml already exists (user provided) - if nixpacks_toml_path.exists() { - self.log( - context, - "Custom nixpacks.toml found, skipping framework detection".to_string(), - ) - .await?; - return Ok(()); + // Validate user-provided Nixpacks config before any host-side planner + // can follow it, then preserve it unchanged. + for config_path in [&nixpacks_toml_path, &hidden_nixpacks_toml_path] { + if read_confined_control_file(build_context_dir, config_path, 1024 * 1024)?.is_some() { + self.log( + context, + "Custom nixpacks.toml found, skipping framework detection".to_string(), + ) + .await?; + return Ok(()); + } } - // Skip if not a Node.js project - if !package_json_path.exists() { + let Some(package_json) = + read_confined_control_file(build_context_dir, &package_json_path, 5 * 1024 * 1024)? + else { return Ok(()); - } + }; // Detect framework - let framework = temps_presets::detect_node_framework(build_context_dir); + let framework = temps_presets::detect_node_framework_from_package_json(&package_json); self.log( context, @@ -335,7 +461,15 @@ impl BuildImageJob { // Generate nixpacks.toml if framework has specific configuration if let Some(config) = framework.nixpacks_config() { - fs::write(&nixpacks_toml_path, config).map_err(WorkflowError::IoError)?; + if let Ok(metadata) = fs::symlink_metadata(&nixpacks_toml_path) { + if metadata.file_type().is_symlink() || !metadata.is_file() { + return Err(WorkflowError::JobValidationFailed(format!( + "nixpacks config '{}' must be a regular non-symlink file", + nixpacks_toml_path.display() + ))); + } + } + write_no_follow(&nixpacks_toml_path, config.as_bytes(), false)?; self.log( context, @@ -358,13 +492,24 @@ impl BuildImageJob { /// Load and parse .temps.yaml from the build context directory. /// Returns None if the file does not exist or cannot be parsed. - fn load_temps_config(&self, build_context_dir: &Path) -> Option { + fn load_temps_config( + &self, + build_context_dir: &Path, + ) -> Result, WorkflowError> { let config_path = build_context_dir.join(".temps.yaml"); - if !config_path.exists() { - return None; - } - let contents = fs::read_to_string(&config_path).ok()?; - TempsConfig::from_yaml(&contents).ok() + let Some(contents) = + read_confined_control_file(build_context_dir, &config_path, 1024 * 1024)? + else { + return Ok(None); + }; + TempsConfig::from_yaml(&contents) + .map(Some) + .map_err(|error| { + WorkflowError::JobValidationFailed(format!( + "Invalid .temps.yaml at '{}': {error}", + config_path.display() + )) + }) } async fn ensure_dockerfile( @@ -374,7 +519,7 @@ impl BuildImageJob { dockerfile_path: &PathBuf, ) -> Result, WorkflowError> { // If Dockerfile exists, we're done (no preset build args) - if dockerfile_path.exists() { + if fs::symlink_metadata(dockerfile_path).is_ok() { return Ok(std::collections::HashMap::new()); } @@ -419,11 +564,8 @@ impl BuildImageJob { // Try to read package.json for more accurate detection let package_json_path = build_context_dir.join("package.json"); - let package_json_content = if package_json_path.exists() { - fs::read_to_string(&package_json_path).ok() - } else { - None - }; + let package_json_content = + read_confined_control_file(build_context_dir, &package_json_path, 5 * 1024 * 1024)?; // Check for Create React App by looking for react-scripts in package.json let detected_slug = if let Some(content) = &package_json_content { @@ -491,7 +633,7 @@ impl BuildImageJob { let project_slug = repo_output.repo_name.replace("-", "_").to_lowercase(); // Load .temps.yaml for build overrides (install_command, build_command, output_dir) - let temps_config = self.load_temps_config(build_context_dir); + let temps_config = self.load_temps_config(build_context_dir)?; let build_overrides = temps_config.as_ref().and_then(|c| c.build.as_ref()); let install_cmd_owned = build_overrides.and_then(|b| b.install_command.clone()); @@ -525,8 +667,11 @@ impl BuildImageJob { .await; // Write the Dockerfile - fs::write(dockerfile_path, &dockerfile_with_args.content) - .map_err(WorkflowError::IoError)?; + write_no_follow( + dockerfile_path, + dockerfile_with_args.content.as_bytes(), + true, + )?; self.log( context, @@ -573,7 +718,15 @@ impl BuildImageJob { }; let npmrc_path = build_context_dir.join(".npmrc"); - fs::write(&npmrc_path, &plan.contents).map_err(|e| { + if let Ok(metadata) = fs::symlink_metadata(&npmrc_path) { + if metadata.file_type().is_symlink() || !metadata.is_file() { + return Err(WorkflowError::JobValidationFailed(format!( + ".npmrc '{}' must be a regular non-symlink file", + npmrc_path.display() + ))); + } + } + write_no_follow(&npmrc_path, plan.contents.as_bytes(), false).map_err(|e| { WorkflowError::JobExecutionFailed(format!( "Failed to write .npmrc to {}: {}", npmrc_path.display(), @@ -608,17 +761,67 @@ impl BuildImageJob { // Determine build context first (needed for Dockerfile path) let build_context = if let Some(ref context_path) = self.build_config.build_context { + let context_path = Path::new(context_path); + if context_path.is_absolute() + || context_path.components().any(|component| { + matches!( + component, + std::path::Component::ParentDir + | std::path::Component::RootDir + | std::path::Component::Prefix(_) + ) + }) + { + return Err(WorkflowError::JobValidationFailed(format!( + "Build context '{}' must be relative and contained by the source root", + context_path.display() + ))); + } repo_output.repo_dir.join(context_path) } else { repo_output.repo_dir.clone() }; + let canonical_root = repo_output + .repo_dir + .canonicalize() + .map_err(WorkflowError::IoError)?; + let canonical_context = build_context + .canonicalize() + .map_err(WorkflowError::IoError)?; + if !canonical_context.starts_with(&canonical_root) { + return Err(WorkflowError::JobValidationFailed(format!( + "Build context '{}' escapes source root '{}'", + canonical_context.display(), + canonical_root.display() + ))); + } + // Determine dockerfile path relative to build context - let dockerfile_path = if let Some(ref dockerfile) = self.build_config.dockerfile_path { - build_context.join(dockerfile) - } else { - build_context.join("Dockerfile") - }; + let dockerfile_relative = self + .build_config + .dockerfile_path + .as_deref() + .map(Path::new) + .unwrap_or_else(|| Path::new("Dockerfile")); + validate_relative_build_path(dockerfile_relative, "Dockerfile path")?; + let dockerfile_path = build_context.join(dockerfile_relative); + let dockerfile_parent = dockerfile_path.parent().ok_or_else(|| { + WorkflowError::JobValidationFailed("Dockerfile path has no parent".to_string()) + })?; + let canonical_parent = dockerfile_parent + .canonicalize() + .map_err(WorkflowError::IoError)?; + if !canonical_parent.starts_with(&canonical_context) { + return Err(WorkflowError::JobValidationFailed(format!( + "Dockerfile parent '{}' escapes build context '{}'", + canonical_parent.display(), + canonical_context.display() + ))); + } + if fs::symlink_metadata(&dockerfile_path).is_ok() { + validate_confined_regular_file(&canonical_context, &dockerfile_path)?; + } self.log( context, @@ -1024,7 +1227,7 @@ impl WorkflowTask for BuildImageJob { // Read .temps.yaml health config and pass it to downstream jobs // The DeployImageJob will use this to configure its health check path let build_context_dir = &image_output.build_context; - if let Some(temps_config) = self.load_temps_config(build_context_dir) { + if let Some(temps_config) = self.load_temps_config(build_context_dir)? { if let Some(health) = &temps_config.health { context.set_output(&self.job_id, "health_check_path", &health.path)?; context.set_output(&self.job_id, "health_check_timeout", health.timeout)?; @@ -1494,6 +1697,90 @@ mod tests { (dir, repo) } + #[tokio::test] + async fn rejects_dockerfile_path_traversal() { + let builder = Arc::new(RecordingImageBuilder::default()); + let job = BuildImageJobBuilder::new() + .job_id("build".to_string()) + .download_job_id("download_repo".to_string()) + .image_tag("myapp:latest".to_string()) + .dockerfile_path("../Dockerfile".to_string()) + .build(builder) + .unwrap(); + let (_dir, repo) = repo_with_dockerfile(); + let context = crate::test_utils::create_test_context("wf".to_string(), 1, 1, 1); + + let error = job.build_image(&repo, &context).await.unwrap_err(); + assert!(matches!(error, WorkflowError::JobValidationFailed(_))); + } + + #[cfg(unix)] + #[tokio::test] + async fn rejects_dockerfile_and_npmrc_symlinks() { + use std::os::unix::fs::symlink; + + let builder = Arc::new(RecordingImageBuilder::default()); + let dir = tempfile::tempdir().unwrap(); + let outside = tempfile::tempdir().unwrap(); + let outside_file = outside.path().join("outside"); + std::fs::write(&outside_file, "unchanged").unwrap(); + symlink(&outside_file, dir.path().join("Dockerfile")).unwrap(); + let repo = RepositoryOutput { + repo_dir: dir.path().to_path_buf(), + checkout_ref: "main".to_string(), + repo_owner: "owner".to_string(), + repo_name: "repo".to_string(), + }; + let context = crate::test_utils::create_test_context("wf".to_string(), 1, 1, 1); + let job = BuildImageJobBuilder::new() + .job_id("build".to_string()) + .download_job_id("download_repo".to_string()) + .image_tag("myapp:latest".to_string()) + .build(builder.clone()) + .unwrap(); + assert!(matches!( + job.build_image(&repo, &context).await, + Err(WorkflowError::JobValidationFailed(_)) + )); + + std::fs::remove_file(dir.path().join("Dockerfile")).unwrap(); + std::fs::write(dir.path().join("Dockerfile"), "FROM scratch\n").unwrap(); + symlink(&outside_file, dir.path().join(".npmrc")).unwrap(); + let npm_job = BuildImageJobBuilder::new() + .job_id("build".to_string()) + .download_job_id("download_repo".to_string()) + .image_tag("myapp:latest".to_string()) + .build_args(vec![("NPM_TOKEN".to_string(), "secret".to_string())]) + .build(builder) + .unwrap(); + assert!(matches!( + npm_job.build_image(&repo, &context).await, + Err(WorkflowError::JobValidationFailed(_)) + )); + assert_eq!(std::fs::read_to_string(outside_file).unwrap(), "unchanged"); + } + + #[cfg(unix)] + #[test] + fn rejects_symlinked_build_control_files_before_reading_them() { + use std::os::unix::fs::symlink; + + let directory = tempfile::tempdir().unwrap(); + for name in [ + "package.json", + ".temps.yaml", + "nixpacks.toml", + ".nixpacks.toml", + ] { + let path = directory.path().join(name); + symlink("/dev/zero", &path).unwrap(); + assert!(matches!( + read_confined_control_file(directory.path(), &path, 1024), + Err(WorkflowError::JobValidationFailed(_)) + )); + } + } + /// Single-platform builds must keep behaving exactly as before: one build, /// the plain tag, no per-platform map. #[tokio::test] diff --git a/crates/temps-deployments/src/jobs/deploy_compose.rs b/crates/temps-deployments/src/jobs/deploy_compose.rs index bc0b6912d..87b31bfd6 100644 --- a/crates/temps-deployments/src/jobs/deploy_compose.rs +++ b/crates/temps-deployments/src/jobs/deploy_compose.rs @@ -8,7 +8,9 @@ use async_trait::async_trait; use std::collections::HashMap; use std::path::{Component, Path, PathBuf}; use std::sync::Arc; -use temps_core::{JobResult, WorkflowContext, WorkflowError, WorkflowTask}; +use temps_core::{ + JobResult, WorkflowCancellationProvider, WorkflowContext, WorkflowError, WorkflowTask, +}; use temps_deployer::compose::{ComposeDeployRequest, ComposeExecutor}; use temps_logs::LogService; use tracing::debug; @@ -369,7 +371,12 @@ impl WorkflowTask for DeployComposeJob { } if let Err(e) = self .compose_executor - .teardown_for_redeploy(&project_name) + .teardown_at( + &project_name, + repo_path.as_deref(), + Some(compose_file_name), + &self.environment_vars, + ) .await { debug!( @@ -388,7 +395,7 @@ impl WorkflowTask for DeployComposeJob { environment_vars: self.environment_vars.clone(), build_args: self.build_args.clone(), labels, - repo_dir: repo_path, + repo_dir: repo_path.clone(), compose_override: self.compose_override.clone(), }; @@ -396,6 +403,16 @@ impl WorkflowTask for DeployComposeJob { let services = match self.compose_executor.deploy(request).await { Ok(s) => s, Err(e) => { + let cleanup_error = self + .compose_executor + .teardown_at( + &project_name, + repo_path.as_deref(), + Some(compose_file_name), + &self.environment_vars, + ) + .await + .err(); let error_msg = format!("Compose deploy failed: {}", e); tracing::error!(error = %error_msg, "Docker Compose deployment failed"); if let Some(ref log_id) = self.log_id { @@ -403,11 +420,23 @@ impl WorkflowTask for DeployComposeJob { tracing::error!("Failed to write error to log stream: {}", log_err); } } + if let Some(cleanup_error) = cleanup_error { + tracing::error!(project = %project_name, error = %cleanup_error, "Compose compensation cleanup failed"); + } return Err(WorkflowError::JobExecutionFailed(error_msg)); } }; if services.is_empty() { + let _ = self + .compose_executor + .teardown_at( + &project_name, + repo_path.as_deref(), + Some(compose_file_name), + &self.environment_vars, + ) + .await; let error_msg = "No containers found after docker compose up".to_string(); tracing::error!(error = %error_msg, "Docker Compose deployment produced no containers"); if let Some(ref log_id) = self.log_id { @@ -514,6 +543,61 @@ impl WorkflowTask for DeployComposeJob { Ok(JobResult::success(context)) } + + async fn execute_with_cancellation( + &self, + context: WorkflowContext, + cancellation_provider: &dyn WorkflowCancellationProvider, + ) -> Result { + let workflow_run_id = context.workflow_run_id.clone(); + let project_name = format!("temps-{}-{}", self.project_id, self.environment_id); + let compose_file_name = self.compose_path.as_deref().unwrap_or("docker-compose.yml"); + validate_relative_path(compose_file_name, "compose_path")?; + validate_relative_path(&self.directory, "directory")?; + let cleanup_repo_path = if self.compose_content.is_none() { + let repo_dir: Option = context + .get_output(&self.download_job_id, "repo_dir") + .map_err(|error| WorkflowError::JobExecutionFailed(error.to_string()))?; + repo_dir + .map(|repo_dir| { + canonicalize_confined_repo_path( + Path::new(&repo_dir), + Path::new(&self.directory), + "directory", + ) + }) + .transpose()? + } else { + None + }; + let cancellation_check = async { + loop { + tokio::time::sleep(std::time::Duration::from_secs(1)).await; + match cancellation_provider.is_cancelled(&workflow_run_id).await { + Ok(false) => continue, + Ok(true) | Err(_) => return, + } + } + }; + + tokio::select! { + result = self.execute(context) => result, + _ = cancellation_check => { + self.compose_executor + .teardown_at( + &project_name, + cleanup_repo_path.as_deref(), + Some(compose_file_name), + &self.environment_vars, + ) + .await + .map_err(|error| WorkflowError::JobExecutionFailed(format!( + "Compose deployment was cancelled, but stack cleanup failed for {project_name}: {error}" + )))?; + Err(WorkflowError::WorkflowCancelled) + } + } + } } /// Confine a user-supplied path (`compose_path`, `directory`) to the repo diff --git a/crates/temps-deployments/src/jobs/deploy_static_bundle.rs b/crates/temps-deployments/src/jobs/deploy_static_bundle.rs index 62f6302d1..eb165e73e 100644 --- a/crates/temps-deployments/src/jobs/deploy_static_bundle.rs +++ b/crates/temps-deployments/src/jobs/deploy_static_bundle.rs @@ -7,7 +7,9 @@ use async_trait::async_trait; use flate2::read::GzDecoder; use serde::{Deserialize, Serialize}; -use std::io::{Cursor, Read}; +#[cfg(test)] +use std::io::Cursor; +use std::io::Read; use std::path::{Component, Path, PathBuf}; use std::sync::Arc; use tar::EntryType; @@ -65,6 +67,7 @@ impl DeployStaticBundleOutput { } /// Job that deploys a static bundle from local storage +#[derive(Clone)] pub struct DeployStaticBundleJob { /// Unique job identifier job_id: String, @@ -82,6 +85,8 @@ pub struct DeployStaticBundleJob { environment_slug: String, /// Deployment slug for organizing files deployment_slug: String, + /// Directory within the uploaded archive selected by preset detection. + source_directory: String, /// Data directory for reading the bundle data_dir: PathBuf, /// Static deployer for deploying files @@ -158,6 +163,24 @@ fn validate_zip_entry_name(name: &str) -> Result<(), WorkflowError> { Ok(()) } +fn confined_static_source(root: &Path, source_directory: &str) -> Result { + validate_archive_entry_path(Path::new(source_directory))?; + let canonical_root = root.canonicalize().map_err(WorkflowError::IoError)?; + let source = root.join(source_directory); + let canonical_source = source.canonicalize().map_err(|error| { + WorkflowError::JobExecutionFailed(format!( + "Detected static project directory '{source_directory}' is unavailable: {error}" + )) + })?; + if !canonical_source.starts_with(&canonical_root) || !canonical_source.is_dir() { + return Err(WorkflowError::InvalidArchiveEntry { + path: source_directory.to_string(), + reason: "detected static project directory escapes the archive root".to_string(), + }); + } + Ok(canonical_source) +} + impl DeployStaticBundleJob { #[allow(clippy::too_many_arguments)] pub fn new( @@ -169,6 +192,7 @@ impl DeployStaticBundleJob { project_slug: String, environment_slug: String, deployment_slug: String, + source_directory: String, data_dir: PathBuf, static_deployer: Arc, ) -> Self { @@ -181,6 +205,7 @@ impl DeployStaticBundleJob { project_slug, environment_slug, deployment_slug, + source_directory, data_dir, static_deployer, log_service: None, @@ -234,6 +259,18 @@ impl DeployStaticBundleJob { pub const MAX_EXTRACTED_BYTES: u64 = 2 * 1024 * 1024 * 1024; // 2 GiB /// Maximum decompressed bytes for a single archive entry (Fix #27). pub const MAX_ENTRY_BYTES: u64 = 500 * 1024 * 1024; // 500 MiB + pub const MAX_ENTRIES: u32 = 20_000; + + fn count_archive_entry(entry_count: &mut u32) -> Result<(), WorkflowError> { + *entry_count = entry_count.saturating_add(1); + if *entry_count > Self::MAX_ENTRIES { + return Err(WorkflowError::JobExecutionFailed(format!( + "Static archive exceeds the {} entry limit", + Self::MAX_ENTRIES + ))); + } + Ok(()) + } /// Extract tar.gz bundle to the target directory. /// @@ -242,17 +279,18 @@ impl DeployStaticBundleJob { /// - Fix #19: skips symlink and hardlink entries (they can escape the sandbox). /// - Fix #27: rejects entries whose declared size exceeds per-entry or /// aggregate limits, and wraps the decoder in `io::Take` as a backstop. - fn extract_tar_gz( + fn extract_tar_gz_reader( &self, - data: &[u8], + reader: R, target_dir: &std::path::Path, ) -> Result { // Fix #27: io::Take backstop so any read past the aggregate limit // returns EOF and tar parsing fails before we accumulate unbounded data. - let decoder = GzDecoder::new(Cursor::new(data)); + let decoder = GzDecoder::new(reader); let limited = decoder.take(Self::MAX_EXTRACTED_BYTES); let mut archive = tar::Archive::new(limited); + let mut entry_count = 0u32; let mut file_count = 0u32; let mut extracted_total: u64 = 0; @@ -262,6 +300,7 @@ impl DeployStaticBundleJob { let mut entry = entry.map_err(|e| { WorkflowError::JobExecutionFailed(format!("Failed to read tar entry: {}", e)) })?; + Self::count_archive_entry(&mut entry_count)?; let path = entry.path().map_err(|e| { WorkflowError::JobExecutionFailed(format!("Failed to get entry path: {}", e)) @@ -358,16 +397,25 @@ impl DeployStaticBundleJob { /// - Fix #18: validates every entry path via component walk before joining. /// - Fix #27: rejects entries whose declared uncompressed size exceeds /// per-entry or aggregate limits. - fn extract_zip(&self, data: &[u8], target_dir: &std::path::Path) -> Result { - let cursor = Cursor::new(data); - let mut archive = ZipArchive::new(cursor).map_err(|e| { + fn extract_zip_reader( + &self, + mut reader: R, + target_dir: &std::path::Path, + ) -> Result { + temps_core::archive_security::validate_zip_metadata(&mut reader).map_err(|error| { + WorkflowError::JobExecutionFailed(format!("Unsafe static ZIP metadata: {error}")) + })?; + let mut archive = ZipArchive::new(reader).map_err(|e| { WorkflowError::JobExecutionFailed(format!("Failed to open zip archive: {}", e)) })?; + let mut entry_count = 0u32; let mut file_count = 0u32; let mut extracted_total: u64 = 0; + let mut written_total: u64 = 0; for i in 0..archive.len() { + Self::count_archive_entry(&mut entry_count)?; let mut file = archive.by_index(i).map_err(|e| { WorkflowError::JobExecutionFailed(format!("Failed to read zip entry {}: {}", i, e)) })?; @@ -431,22 +479,33 @@ impl DeployStaticBundleJob { } } - // Read file contents - let mut contents = Vec::new(); - file.read_to_end(&mut contents).map_err(|e| { + let mut output = std::fs::File::create(&outpath).map_err(|e| { WorkflowError::JobExecutionFailed(format!( - "Failed to read zip file contents: {}", - e + "Failed to create file {:?}: {}", + outpath, e )) })?; - - // Write to destination - std::fs::write(&outpath, contents).map_err(|e| { + let written = std::io::copy( + &mut file.by_ref().take(Self::MAX_ENTRY_BYTES + 1), + &mut output, + ) + .map_err(|e| { WorkflowError::JobExecutionFailed(format!( - "Failed to write file {:?}: {}", + "Failed to extract file {:?}: {}", outpath, e )) })?; + if written > Self::MAX_ENTRY_BYTES { + return Err(WorkflowError::ArchiveTooLarge { + limit_bytes: Self::MAX_ENTRY_BYTES, + }); + } + written_total = written_total.saturating_add(written); + if written_total > Self::MAX_EXTRACTED_BYTES { + return Err(WorkflowError::ArchiveTooLarge { + limit_bytes: Self::MAX_EXTRACTED_BYTES, + }); + } file_count += 1; } @@ -455,17 +514,25 @@ impl DeployStaticBundleJob { Ok(file_count) } - /// Read the bundle data from local storage. - /// - /// Canonicalizes both the data_dir root and the resolved bundle path and - /// verifies the result is still inside data_dir (defense-in-depth against - /// a tampered bundle_path in the database). - async fn download_bundle(&self) -> Result, WorkflowError> { + #[cfg(test)] + fn extract_tar_gz( + &self, + data: &[u8], + target_dir: &std::path::Path, + ) -> Result { + self.extract_tar_gz_reader(Cursor::new(data), target_dir) + } + + #[cfg(test)] + fn extract_zip(&self, data: &[u8], target_dir: &std::path::Path) -> Result { + self.extract_zip_reader(Cursor::new(data), target_dir) + } + + fn resolve_bundle_path(&self) -> Result { let local_path = self.data_dir.join(&self.bundle_path); debug!("Reading bundle from local storage: {:?}", local_path); - // Canonicalize the data_dir root (must already exist). let canonical_root = self.data_dir .canonicalize() @@ -473,8 +540,6 @@ impl DeployStaticBundleJob { path: self.data_dir.display().to_string(), reason: format!("data_dir canonicalization failed: {e}"), })?; - - // Canonicalize the resolved bundle path (file must exist). let canonical = local_path .canonicalize() @@ -482,14 +547,23 @@ impl DeployStaticBundleJob { path: local_path.display().to_string(), reason: format!("canonicalization failed: {e}"), })?; - - // Reject any path that escapes the data directory. if !canonical.starts_with(&canonical_root) { return Err(WorkflowError::InvalidBundlePath { path: canonical.display().to_string(), reason: format!("escapes data_dir {}", canonical_root.display()), }); } + Ok(canonical) + } + + /// Read the bundle data from local storage. + /// + /// Canonicalizes both the data_dir root and the resolved bundle path and + /// verifies the result is still inside data_dir (defense-in-depth against + /// a tampered bundle_path in the database). + #[cfg(test)] + async fn download_bundle(&self) -> Result, WorkflowError> { + let canonical = self.resolve_bundle_path()?; tokio::fs::read(&canonical).await.map_err(|e| { WorkflowError::JobExecutionFailed(format!( @@ -534,21 +608,23 @@ impl WorkflowTask for DeployStaticBundleJob { self.log(LogLevel::Info, "Reading bundle from local storage...") .await; - let bundle_data = self.download_bundle().await?; + let bundle_path = self.resolve_bundle_path()?; + let bundle_size = std::fs::metadata(&bundle_path) + .map_err(WorkflowError::IoError)? + .len(); self.log( LogLevel::Success, - &format!("Read {} bytes from local storage", bundle_data.len()), + &format!("Opened {} bytes from local storage", bundle_size), ) .await; // Create temporary directory for extraction - let temp_dir = std::env::temp_dir().join(format!("temps-bundle-{}", uuid::Uuid::new_v4())); - std::fs::create_dir_all(&temp_dir).map_err(|e| { + let temp_dir = tempfile::tempdir().map_err(|e| { WorkflowError::JobExecutionFailed(format!("Failed to create temp directory: {}", e)) })?; - debug!("Extracting bundle to: {:?}", temp_dir); + debug!("Extracting bundle to: {:?}", temp_dir.path()); self.log( LogLevel::Info, "Extracting bundle to temporary directory...", @@ -557,13 +633,23 @@ impl WorkflowTask for DeployStaticBundleJob { // Extract based on content type. // Note: Must check for exact "application/zip" since "application/gzip" also contains "zip". - let content_type = self.detect_content_type(); - let file_count = if content_type == "application/zip" { - self.extract_zip(&bundle_data, &temp_dir)? - } else { - // Default to tar.gz (application/gzip, application/x-gzip, etc.) - self.extract_tar_gz(&bundle_data, &temp_dir)? - }; + let content_type = self.detect_content_type().to_string(); + let extraction_target = temp_dir.path().to_path_buf(); + let extraction_job = self.clone(); + let extraction_permit = super::acquire_archive_extraction_permit().await?; + let file_count = tokio::task::spawn_blocking(move || { + let _extraction_permit = extraction_permit; + let file = std::fs::File::open(&bundle_path).map_err(WorkflowError::IoError)?; + if content_type == "application/zip" { + extraction_job.extract_zip_reader(file, &extraction_target) + } else { + extraction_job.extract_tar_gz_reader(file, &extraction_target) + } + }) + .await + .map_err(|error| { + WorkflowError::JobExecutionFailed(format!("Static extraction task failed: {error}")) + })??; self.log( LogLevel::Success, @@ -572,8 +658,10 @@ impl WorkflowTask for DeployStaticBundleJob { .await; // Deploy using StaticDeployer + let canonical_source = confined_static_source(temp_dir.path(), &self.source_directory)?; + let request = StaticDeployRequest { - source_dir: temp_dir.clone(), + source_dir: canonical_source, project_slug: self.project_slug.clone(), environment_slug: self.environment_slug.clone(), deployment_slug: self.deployment_slug.clone(), @@ -591,11 +679,6 @@ impl WorkflowTask for DeployStaticBundleJob { ) .await; - // Clean up temporary directory - if let Err(e) = std::fs::remove_dir_all(&temp_dir) { - debug!("Warning: Failed to clean up temp directory: {}", e); - } - // Store outputs in context context.set_output(&self.job_id, "static_dir_location", &result.storage_path)?; context.set_output(&self.job_id, "file_count", result.file_count)?; @@ -631,6 +714,27 @@ mod tests { // ── Archive builders ────────────────────────────────────────────────────── + #[test] + fn serves_the_detected_nested_static_directory() { + let temporary = TempDir::new().expect("tempdir"); + let nested = temporary.path().join("examples/site"); + std::fs::create_dir_all(&nested).expect("nested directory"); + std::fs::write(nested.join("index.html"), "ok").expect("fixture"); + + let selected = confined_static_source(temporary.path(), "examples/site") + .expect("nested static root should be selected"); + assert_eq!(selected, nested.canonicalize().expect("canonical nested")); + } + + #[test] + fn rejects_static_directory_traversal() { + let temporary = TempDir::new().expect("tempdir"); + assert!(matches!( + confined_static_source(temporary.path(), "../outside"), + Err(WorkflowError::InvalidArchiveEntry { .. }) + )); + } + /// Build a raw (uncompressed) POSIX ustar tar archive with a single entry. /// /// Writes header bytes verbatim — bypassing the tar crate's `set_path` / @@ -797,6 +901,7 @@ mod tests { project_slug: "proj".to_string(), environment_slug: "env".to_string(), deployment_slug: "dep".to_string(), + source_directory: ".".to_string(), data_dir: tmp.clone(), static_deployer: Arc::new(FilesystemStaticDeployer::new(tmp)), log_service: None, @@ -815,6 +920,7 @@ mod tests { project_slug: "proj".to_string(), environment_slug: "env".to_string(), deployment_slug: "dep".to_string(), + source_directory: ".".to_string(), data_dir: data_dir.to_path_buf(), static_deployer: Arc::new(FilesystemStaticDeployer::new(data_dir.to_path_buf())), log_service: None, @@ -1159,4 +1265,11 @@ mod tests { "expected InvalidBundlePath (canonicalization failed), got: {err:?}" ); } + + #[test] + fn archive_entry_counter_rejects_more_than_twenty_thousand_entries() { + let mut count = DeployStaticBundleJob::MAX_ENTRIES; + let error = DeployStaticBundleJob::count_archive_entry(&mut count).unwrap_err(); + assert!(error.to_string().contains("entry limit")); + } } diff --git a/crates/temps-deployments/src/jobs/download_repo.rs b/crates/temps-deployments/src/jobs/download_repo.rs index bb9875c23..36782dee5 100644 --- a/crates/temps-deployments/src/jobs/download_repo.rs +++ b/crates/temps-deployments/src/jobs/download_repo.rs @@ -628,6 +628,10 @@ impl WorkflowTask for DownloadRepoJob { } Ok(()) } + + fn cleanup_after_workflow(&self) -> bool { + true + } } /// Builder for DownloadRepoJob diff --git a/crates/temps-deployments/src/jobs/mod.rs b/crates/temps-deployments/src/jobs/mod.rs index 88b3905ac..c18cea86e 100644 --- a/crates/temps-deployments/src/jobs/mod.rs +++ b/crates/temps-deployments/src/jobs/mod.rs @@ -2,6 +2,52 @@ //! //! This module provides ready-to-use job implementations for common deployment tasks. +use std::sync::{Arc, LazyLock}; +use temps_core::WorkflowError; +use tokio::sync::{OwnedSemaphorePermit, Semaphore}; + +static ARCHIVE_EXTRACTION_SEMAPHORE: LazyLock> = + LazyLock::new(|| Arc::new(Semaphore::new(2))); + +pub(crate) async fn acquire_archive_extraction_permit( +) -> Result { + ARCHIVE_EXTRACTION_SEMAPHORE + .clone() + .acquire_owned() + .await + .map_err(|_| { + WorkflowError::JobExecutionFailed( + "Archive extraction concurrency limiter was closed".to_string(), + ) + }) +} + +#[cfg(test)] +mod extraction_limit_tests { + use super::*; + + #[tokio::test] + async fn extraction_limit_holds_at_two_until_work_releases_a_permit() { + let first = acquire_archive_extraction_permit().await.unwrap(); + let second = acquire_archive_extraction_permit().await.unwrap(); + assert!(tokio::time::timeout( + std::time::Duration::from_millis(20), + acquire_archive_extraction_permit() + ) + .await + .is_err()); + drop(first); + let third = tokio::time::timeout( + std::time::Duration::from_secs(1), + acquire_archive_extraction_permit(), + ) + .await + .expect("released extraction slot") + .unwrap(); + drop((second, third)); + } +} + pub mod build_image; pub mod capture_source_files; pub mod capture_source_maps; @@ -18,6 +64,7 @@ pub mod node_health_check; pub mod npmrc; pub mod persist_static_assets; pub mod pipeline_validation; +pub mod prepare_source_bundle; pub mod pull_external_image; pub mod scan_vulnerabilities; pub mod take_screenshot; @@ -36,6 +83,7 @@ pub use deploy_static_bundle::*; pub use download_repo::*; pub use mark_deployment_complete::*; pub use persist_static_assets::*; +pub use prepare_source_bundle::*; pub use pull_external_image::*; pub use scan_vulnerabilities::*; pub use take_screenshot::*; diff --git a/crates/temps-deployments/src/jobs/prepare_source_bundle.rs b/crates/temps-deployments/src/jobs/prepare_source_bundle.rs new file mode 100644 index 000000000..6faf47e98 --- /dev/null +++ b/crates/temps-deployments/src/jobs/prepare_source_bundle.rs @@ -0,0 +1,276 @@ +//! Prepare an uploaded source archive for the normal preset build pipeline. + +use async_trait::async_trait; +use std::fs; +use std::io::{self, Read}; +use std::path::{Component, Path, PathBuf}; +use temps_core::{JobResult, WorkflowContext, WorkflowError, WorkflowTask}; + +#[derive(Debug)] +pub struct PrepareSourceBundleJob { + job_id: String, + archive_path: PathBuf, + project_slug: String, + extraction_id: uuid::Uuid, +} + +impl PrepareSourceBundleJob { + pub fn new(job_id: String, archive_path: PathBuf, project_slug: String) -> Self { + Self { + job_id, + archive_path, + project_slug, + extraction_id: uuid::Uuid::new_v4(), + } + } + + fn target_path(&self, context: &WorkflowContext) -> PathBuf { + let work_root = context.work_dir.clone().unwrap_or_else(std::env::temp_dir); + work_root.join(format!( + "uploaded-source-{}-{}", + self.project_slug, self.extraction_id + )) + } + + fn validate_path(path: &Path) -> Result<(), WorkflowError> { + if path.is_absolute() + || path.components().any(|component| { + matches!( + component, + Component::ParentDir | Component::RootDir | Component::Prefix(_) + ) + }) + { + return Err(WorkflowError::InvalidArchiveEntry { + path: path.display().to_string(), + reason: "entry path escapes the source root".to_string(), + }); + } + if path.components().any(|component| { + let Component::Normal(value) = component else { + return false; + }; + let name = value.to_string_lossy(); + name == ".git" + || name == "node_modules" + || name == ".env" + || name.starts_with(".env.") + || name.ends_with(".pem") + || name.ends_with(".key") + || name == "credentials.json" + }) { + return Err(WorkflowError::InvalidArchiveEntry { + path: path.display().to_string(), + reason: "sensitive or generated paths are not accepted in Drop uploads".to_string(), + }); + } + Ok(()) + } + + fn extract_archive(archive_path: &Path, target: &Path) -> Result { + const MAX_ENTRIES: u32 = 20_000; + const MAX_ENTRY_BYTES: u64 = 500 * 1024 * 1024; + const MAX_TOTAL_BYTES: u64 = 2 * 1024 * 1024 * 1024; + + let mut file = fs::File::open(archive_path).map_err(WorkflowError::IoError)?; + temps_core::archive_security::validate_zip_metadata(&mut file).map_err(|error| { + WorkflowError::JobExecutionFailed(format!("Unsafe source ZIP metadata: {error}")) + })?; + let mut archive = zip::ZipArchive::new(file).map_err(|error| { + WorkflowError::JobExecutionFailed(format!( + "Failed to open source archive '{}': {error}", + archive_path.display() + )) + })?; + let mut entry_count = 0u32; + let mut file_count = 0u32; + let mut total = 0u64; + let mut written_total = 0u64; + for index in 0..archive.len() { + entry_count = entry_count.saturating_add(1); + if entry_count > MAX_ENTRIES { + return Err(WorkflowError::JobExecutionFailed( + "Source archive exceeds the 20,000 entry extraction limit".to_string(), + )); + } + let mut entry = archive.by_index(index).map_err(|error| { + WorkflowError::JobExecutionFailed(format!( + "Failed to read ZIP entry {index}: {error}" + )) + })?; + let enclosed = + entry + .enclosed_name() + .ok_or_else(|| WorkflowError::InvalidArchiveEntry { + path: entry.name().to_string(), + reason: "entry path escapes the source root".to_string(), + })?; + Self::validate_path(&enclosed)?; + if entry + .unix_mode() + .is_some_and(|mode| mode & 0o170000 == 0o120000) + { + return Err(WorkflowError::InvalidArchiveEntry { + path: entry.name().to_string(), + reason: "symbolic links are not allowed".to_string(), + }); + } + if entry.is_dir() { + fs::create_dir_all(target.join(&enclosed)).map_err(WorkflowError::IoError)?; + continue; + } + file_count = file_count.saturating_add(1); + total = total.saturating_add(entry.size()); + if entry.size() > MAX_ENTRY_BYTES || total > MAX_TOTAL_BYTES { + return Err(WorkflowError::JobExecutionFailed( + "Source archive exceeds extraction safety limits".to_string(), + )); + } + let destination = target.join(&enclosed); + if let Some(parent) = destination.parent() { + fs::create_dir_all(parent).map_err(WorkflowError::IoError)?; + } + let mut output = fs::File::create(&destination).map_err(WorkflowError::IoError)?; + let written = io::copy(&mut entry.by_ref().take(MAX_ENTRY_BYTES + 1), &mut output) + .map_err(WorkflowError::IoError)?; + if written > MAX_ENTRY_BYTES { + return Err(WorkflowError::JobExecutionFailed(format!( + "ZIP entry '{}' exceeds the 500 MiB extraction limit", + enclosed.display() + ))); + } + written_total = written_total.saturating_add(written); + if written_total > MAX_TOTAL_BYTES { + return Err(WorkflowError::JobExecutionFailed( + "Source archive exceeds the 2 GiB extraction limit".to_string(), + )); + } + } + Ok(file_count) + } +} + +#[async_trait] +impl WorkflowTask for PrepareSourceBundleJob { + fn job_id(&self) -> &str { + &self.job_id + } + fn name(&self) -> &str { + "Prepare Uploaded Source" + } + fn description(&self) -> &str { + "Securely extracts uploaded source code for the preset builder" + } + + async fn execute(&self, mut context: WorkflowContext) -> Result { + let target = self.target_path(&context); + let archive_path = self.archive_path.clone(); + let extraction_target = target.clone(); + let extraction_permit = super::acquire_archive_extraction_permit().await?; + let file_count = tokio::task::spawn_blocking(move || { + let _extraction_permit = extraction_permit; + fs::create_dir_all(&extraction_target).map_err(WorkflowError::IoError)?; + Self::extract_archive(&archive_path, &extraction_target) + }) + .await + .map_err(|error| { + WorkflowError::JobExecutionFailed(format!("Source extraction task failed: {error}")) + })??; + if file_count == 0 { + return Err(WorkflowError::JobExecutionFailed( + "Uploaded source archive is empty".to_string(), + )); + } + + context.set_output( + &self.job_id, + "repo_dir", + target.to_string_lossy().to_string(), + )?; + context.set_output(&self.job_id, "checkout_ref", "uploaded-source")?; + context.set_output(&self.job_id, "repo_owner", "drop")?; + context.set_output(&self.job_id, "repo_name", &self.project_slug)?; + context.set_artifact(&self.job_id, "source_code", target.clone()); + Ok(JobResult::success(context)) + } + + async fn validate_prerequisites( + &self, + _context: &WorkflowContext, + ) -> Result<(), WorkflowError> { + if !self.archive_path.is_file() { + return Err(WorkflowError::JobValidationFailed(format!( + "Uploaded source archive '{}' does not exist", + self.archive_path.display() + ))); + } + Ok(()) + } + + async fn cleanup(&self, context: &WorkflowContext) -> Result<(), WorkflowError> { + let target = self.target_path(context); + match tokio::fs::remove_dir_all(&target).await { + Ok(()) => {} + Err(error) if error.kind() == io::ErrorKind::NotFound => {} + Err(error) => return Err(WorkflowError::IoError(error)), + } + Ok(()) + } + + fn cleanup_after_workflow(&self) -> bool { + true + } +} + +#[cfg(test)] +mod tests { + use super::*; + use std::io::Write; + + #[test] + fn rejects_parent_directory_entries() { + let error = PrepareSourceBundleJob::validate_path(Path::new("../secret")); + assert!(matches!( + error, + Err(WorkflowError::InvalidArchiveEntry { .. }) + )); + } + + #[test] + fn rejects_sensitive_entries() { + for path in [".env", "app/.env.local", ".git/config", "server.key"] { + assert!(matches!( + PrepareSourceBundleJob::validate_path(Path::new(path)), + Err(WorkflowError::InvalidArchiveEntry { .. }) + )); + } + } + + #[test] + fn extracts_regular_files_and_rejects_directory_only_archives_as_empty() { + let temporary = tempfile::tempdir().expect("tempdir"); + let archive_path = temporary.path().join("source.zip"); + let file = fs::File::create(&archive_path).expect("archive file"); + let mut archive = zip::ZipWriter::new(file); + let options = zip::write::SimpleFileOptions::default(); + archive + .add_directory("empty/", options) + .expect("directory entry"); + archive + .start_file("src/main.rs", options) + .expect("file entry"); + archive.write_all(b"fn main() {}").expect("file content"); + archive.finish().expect("complete archive"); + + let target = temporary.path().join("extracted"); + fs::create_dir_all(&target).expect("target"); + let count = PrepareSourceBundleJob::extract_archive(&archive_path, &target) + .expect("archive should extract"); + + assert_eq!(count, 1); + assert_eq!( + fs::read_to_string(target.join("src/main.rs")).expect("extracted file"), + "fn main() {}" + ); + } +} diff --git a/crates/temps-deployments/src/plugin.rs b/crates/temps-deployments/src/plugin.rs index af4ec2c14..662b6bb50 100644 --- a/crates/temps-deployments/src/plugin.rs +++ b/crates/temps-deployments/src/plugin.rs @@ -92,6 +92,12 @@ impl TempsPlugin for DeploymentsPlugin { deployment_service.set_telemetry(telemetry.clone()); context.register_service(deployment_service.clone()); + // Preserve uploaded archives until runtime cleanup succeeds, then + // remove them before the project rows cascade away. + let project_cleanup = + deployment_service.clone() as Arc; + context.register_service(project_cleanup); + // Also register as DeploymentCanceller trait for temps-environments let deployment_canceller = deployment_service.clone() as Arc; diff --git a/crates/temps-deployments/src/services/services.rs b/crates/temps-deployments/src/services/services.rs index d856ca5c0..5e3ad5d36 100644 --- a/crates/temps-deployments/src/services/services.rs +++ b/crates/temps-deployments/src/services/services.rs @@ -88,6 +88,29 @@ impl From for DeploymentError { } } +fn confined_archive_path( + data_dir: &std::path::Path, + stored_path: &str, +) -> Result { + let relative = std::path::Path::new(stored_path); + if relative.is_absolute() + || relative.components().any(|component| { + matches!( + component, + std::path::Component::ParentDir + | std::path::Component::RootDir + | std::path::Component::Prefix(_) + ) + }) + { + return Err(DeploymentError::InvalidBundlePath { + path: stored_path.to_string(), + reason: "stored archive path escapes the Temps data directory".to_string(), + }); + } + Ok(data_dir.join(relative)) +} + #[derive(Clone)] pub struct DeploymentService { db: Arc, @@ -130,9 +153,10 @@ impl DeploymentService { } })?; - if containers.is_empty() { - return Ok(0); - } + let recorded_container_ids: std::collections::HashSet = containers + .iter() + .map(|container| container.container_id.clone()) + .collect(); let deployment_ids: Vec = containers .iter() @@ -213,6 +237,42 @@ impl DeploymentService { } }; + match deployer.get_container_info(&container_id).await { + Ok(info) => { + let expected_project = project_id.to_string(); + let expected_environment = container_environment_id.to_string(); + if info.labels.get("sh.temps.managed").map(String::as_str) != Some("true") + || info.labels.get("sh.temps.project_id") != Some(&expected_project) + || info.labels.get("sh.temps.environment") != Some(&expected_environment) + { + let reason = "runtime container labels do not match the project and environment being deleted".to_string(); + let _ = self + .restore_cleanup_marker(&original, already_prepared) + .await; + return Err(temps_core::ContainerCleanupError::Removal { + project_id, + environment_id: container_environment_id, + container_id, + node_id, + reason, + }); + } + } + Err(temps_deployer::DeployerError::ContainerNotFound(_)) => {} + Err(error) => { + let _ = self + .restore_cleanup_marker(&original, already_prepared) + .await; + return Err(temps_core::ContainerCleanupError::Removal { + project_id, + environment_id: container_environment_id, + container_id, + node_id, + reason: format!("failed to verify runtime container ownership: {error}"), + }); + } + } + let removal_error = match tokio::time::timeout( std::time::Duration::from_secs(30), deployer.remove_container(&container_id), @@ -258,6 +318,70 @@ impl DeploymentService { ); } + // Compose can create labeled containers before the deployment rows are + // registered. Discover those runtime-owned containers as well so a + // concurrent cancellation/deletion cannot orphan an unrecorded stack. + let runtime_containers = self.deployer.list_containers().await.map_err(|error| { + temps_core::ContainerCleanupError::Discovery { + project_id, + environment_id, + reason: format!("failed to discover labeled runtime containers: {error}"), + } + })?; + let expected_project = project_id.to_string(); + let expected_environment = environment_id.map(|id| id.to_string()); + for container in runtime_containers { + if recorded_container_ids.contains(&container.container_id) + || container.labels.get("sh.temps.managed").map(String::as_str) != Some("true") + || container.labels.get("sh.temps.project_id") != Some(&expected_project) + || expected_environment.as_ref().is_some_and(|expected| { + container.labels.get("sh.temps.environment") != Some(expected) + }) + { + continue; + } + let container_environment_id = container + .labels + .get("sh.temps.environment") + .and_then(|value| value.parse::().ok()) + .ok_or_else(|| temps_core::ContainerCleanupError::Discovery { + project_id, + environment_id, + reason: format!( + "managed container '{}' has an invalid environment label", + container.container_id + ), + })?; + match tokio::time::timeout( + std::time::Duration::from_secs(30), + self.deployer.remove_container(&container.container_id), + ) + .await + { + Ok(Ok(())) | Ok(Err(temps_deployer::DeployerError::ContainerNotFound(_))) => { + removed += 1; + } + Ok(Err(error)) => { + return Err(temps_core::ContainerCleanupError::Removal { + project_id, + environment_id: container_environment_id, + container_id: container.container_id, + node_id: None, + reason: error.to_string(), + }); + } + Err(_) => { + return Err(temps_core::ContainerCleanupError::Removal { + project_id, + environment_id: container_environment_id, + container_id: container.container_id, + node_id: None, + reason: "runtime container removal timed out after 30 seconds".to_string(), + }); + } + } + } + Ok(removed) } @@ -3359,6 +3483,53 @@ impl DeploymentService { Ok(count) } + /// Remove every uploaded archive recorded for a project before deletion. + /// Runtime containers are handled by `DeploymentContainerCleaner`. + pub async fn cleanup_project_archives(&self, project_id: i32) -> Result { + let data_dir = self.config_service.data_dir(); + let source_archives = temps_entities::source_bundles::Entity::find() + .filter(temps_entities::source_bundles::Column::ProjectId.eq(project_id)) + .all(self.db.as_ref()) + .await?; + let static_archives = temps_entities::static_bundles::Entity::find() + .filter(temps_entities::static_bundles::Column::ProjectId.eq(project_id)) + .all(self.db.as_ref()) + .await?; + let archive_paths: Vec = source_archives + .into_iter() + .map(|bundle| bundle.archive_path) + .chain(static_archives.into_iter().map(|bundle| bundle.blob_path)) + .collect(); + let removed = archive_paths.len() as u64; + for relative_path in archive_paths { + let archive_path = + confined_archive_path(&data_dir, &relative_path).map_err(|error| { + DeploymentError::InvalidBundlePath { + path: relative_path.clone(), + reason: format!("stored path for project {project_id} is invalid: {error}"), + } + })?; + match tokio::fs::remove_file(&archive_path).await { + Ok(()) => {} + Err(error) if error.kind() == std::io::ErrorKind::NotFound => {} + Err(error) => { + return Err(DeploymentError::Other(format!( + "Failed to remove archive '{}' for project {}: {}", + archive_path.display(), + project_id, + error + ))); + } + } + } + + info!( + "Removed {} uploaded archive(s) before deleting project {}", + removed, project_id + ); + Ok(removed) + } + /// Cancel a specific deployment pub async fn cancel_deployment( &self, @@ -3946,6 +4117,18 @@ impl temps_core::DeploymentCanceller for DeploymentService { } } +#[async_trait::async_trait] +impl temps_core::ProjectArchiveCleaner for DeploymentService { + async fn cleanup_project_archives( + &self, + project_id: i32, + ) -> Result> { + self.cleanup_project_archives(project_id) + .await + .map_err(|error| Box::new(error) as Box) + } +} + #[async_trait::async_trait] impl temps_core::DeploymentContainerCleaner for DeploymentService { async fn cleanup_project_containers( @@ -3975,6 +4158,25 @@ mod tests { use std::sync::Arc; use temps_core::EncryptionService; + + #[test] + fn archive_cleanup_paths_are_lexically_confined() { + let root = std::path::Path::new("/var/lib/temps"); + assert_eq!( + confined_archive_path(root, "source-bundles/archive.zip").unwrap(), + root.join("source-bundles/archive.zip") + ); + for path in [ + "../archive.zip", + "source-bundles/../../archive.zip", + "/tmp/archive.zip", + ] { + assert!(matches!( + confined_archive_path(root, path), + Err(DeploymentError::InvalidBundlePath { .. }) + )); + } + } use temps_database::test_utils::TestDatabase; use temps_entities::{ deployment_config::DeploymentConfig, deployments, env_vars, environments, @@ -4355,6 +4557,42 @@ mod tests { } } + /// Stub `get_container_info` so the runtime ownership check in + /// `cleanup_project_containers` sees a container whose labels match the + /// project/environment being deleted. + /// + /// Cleanup refuses to remove a container that is not provably ours, so + /// every cleanup test has to present the labels a real managed container + /// would carry — otherwise the test fails on the guard rather than on the + /// behaviour it is actually asserting. + fn expect_owned_container_info( + deployer: &mut MockContainerDeployer, + project_id: i32, + environment_id: i32, + ) { + deployer.expect_get_container_info().returning(move |id| { + Ok(temps_deployer::ContainerInfo { + container_id: id.to_string(), + container_name: id.to_string(), + image_name: "nginx:latest".to_string(), + created_at: Utc::now(), + ports: vec![], + environment_vars: std::collections::HashMap::new(), + status: temps_deployer::ContainerStatus::Running, + restart_count: Some(0), + labels: std::collections::HashMap::from([ + ("sh.temps.managed".to_string(), "true".to_string()), + ("sh.temps.project_id".to_string(), project_id.to_string()), + ( + "sh.temps.environment".to_string(), + environment_id.to_string(), + ), + ]), + ..Default::default() + }) + }); + } + fn create_cleanup_service_for_test( db: Arc, deployer: Arc, @@ -4408,10 +4646,12 @@ mod tests { let test_db = TestDatabase::with_migrations().await?; let db = test_db.connection_arc(); - let (project, _environment, _deployment, container) = setup_test_deployment(&db).await?; + let (project, environment, _deployment, container) = setup_test_deployment(&db).await?; let expected_container_id = container.container_id.clone(); let mut deployer = MockContainerDeployer::new(); + deployer.expect_list_containers().returning(|| Ok(vec![])); + expect_owned_container_info(&mut deployer, project.id, environment.id); deployer .expect_remove_container() .withf(move |container_id| container_id == expected_container_id) @@ -4456,9 +4696,11 @@ mod tests { let test_db = TestDatabase::with_migrations().await?; let db = test_db.connection_arc(); - let (project, _environment, _deployment, container) = setup_test_deployment(&db).await?; + let (project, environment, _deployment, container) = setup_test_deployment(&db).await?; let mut deployer = MockContainerDeployer::new(); + deployer.expect_list_containers().returning(|| Ok(vec![])); + expect_owned_container_info(&mut deployer, project.id, environment.id); deployer.expect_remove_container().times(1).returning(|_| { Err(temps_deployer::DeployerError::NetworkError( "worker unavailable".to_string(), @@ -4492,6 +4734,55 @@ mod tests { Ok(()) } + /// The runtime ownership guard is the last line of defence against + /// deleting a container that merely *recorded* a matching id: if the + /// container Docker actually has under that id belongs to someone else, + /// cleanup must refuse to touch it rather than remove another tenant's + /// workload. + #[tokio::test] + async fn cleanup_refuses_to_remove_a_container_owned_by_another_project( + ) -> Result<(), Box> { + if !database_integration_tests_available().await { + eprintln!("Docker unavailable; skipping cleanup ownership integration test"); + return Ok(()); + } + + let test_db = TestDatabase::with_migrations().await?; + let db = test_db.connection_arc(); + let (project, environment, _deployment, container) = setup_test_deployment(&db).await?; + + let mut deployer = MockContainerDeployer::new(); + deployer.expect_list_containers().returning(|| Ok(vec![])); + // Same container id, but the running container claims a different project. + expect_owned_container_info(&mut deployer, project.id + 1, environment.id); + // The whole point: removal must never be attempted. + deployer.expect_remove_container().never(); + let service = create_cleanup_service_for_test(db.clone(), Arc::new(deployer)); + + let result = temps_core::DeploymentContainerCleaner::cleanup_project_containers( + &service, project.id, + ) + .await; + assert!( + matches!( + result, + Err(temps_core::ContainerCleanupError::Removal { .. }) + ), + "cleanup must fail closed when runtime labels do not match, got {result:?}" + ); + + let preserved = deployment_containers::Entity::find_by_id(container.id) + .one(db.as_ref()) + .await? + .expect("a refused cleanup must preserve the container record"); + assert!( + preserved.deleted_at.is_none(), + "a container we refused to touch must not be marked deleted" + ); + + Ok(()) + } + #[tokio::test] async fn interrupted_cleanup_is_idempotent_when_container_is_already_absent( ) -> Result<(), Box> { @@ -4502,7 +4793,7 @@ mod tests { let test_db = TestDatabase::with_migrations().await?; let db = test_db.connection_arc(); - let (project, _environment, _deployment, container) = setup_test_deployment(&db).await?; + let (project, environment, _deployment, container) = setup_test_deployment(&db).await?; let mut interrupted: deployment_containers::ActiveModel = container.clone().into(); interrupted.status = Set(Some("removing".to_string())); @@ -4510,6 +4801,8 @@ mod tests { interrupted.update(db.as_ref()).await?; let mut deployer = MockContainerDeployer::new(); + deployer.expect_list_containers().returning(|| Ok(vec![])); + expect_owned_container_info(&mut deployer, project.id, environment.id); deployer.expect_remove_container().times(1).returning(|_| { Err(temps_deployer::DeployerError::ContainerNotFound( "already removed".to_string(), diff --git a/crates/temps-deployments/src/services/workflow_execution_service.rs b/crates/temps-deployments/src/services/workflow_execution_service.rs index 2b16087e1..f3d55a0d3 100644 --- a/crates/temps-deployments/src/services/workflow_execution_service.rs +++ b/crates/temps-deployments/src/services/workflow_execution_service.rs @@ -20,7 +20,8 @@ use crate::jobs::{ AgentSyncService, BuildImageJobBuilder, ConfigureAgentsJobBuilder, ConfigureCronsJobBuilder, ConfigureMetricAlertsJobBuilder, CronConfigService, DeployImageJobBuilder, DeployStaticBundleJob, DeployStaticJob, DeploymentTarget, DownloadRepoBuilder, - MetricAlertConfigService, PullExternalImageJob, ResourceUsage, VerifyLocalImageJob, + MetricAlertConfigService, PrepareSourceBundleJob, PullExternalImageJob, ResourceUsage, + VerifyLocalImageJob, }; use crate::services::DeploymentJobTracker; use temps_screenshots::ScreenshotService; @@ -2217,6 +2218,11 @@ impl WorkflowExecutionService { .get("static_bundle_id") .and_then(|v| v.as_i64()) .map(|id| id as i32); + let source_directory = config + .get("source_directory") + .and_then(|value| value.as_str()) + .unwrap_or(".") + .to_string(); // Get data directory from config service for local storage let data_dir = self.config_service.data_dir(); @@ -2230,6 +2236,7 @@ impl WorkflowExecutionService { project.slug.clone(), environment.slug.clone(), deployment.slug.clone(), + source_directory, data_dir, self.static_deployer.clone(), ) @@ -2238,6 +2245,42 @@ impl WorkflowExecutionService { Ok(Arc::new(job)) } + "PrepareSourceBundleJob" => { + let config = db_job.job_config.as_ref().ok_or_else(|| { + WorkflowExecutionError::MissingJobConfig(db_job.job_id.clone()) + })?; + let archive_path = config + .get("archive_path") + .and_then(|value| value.as_str()) + .ok_or_else(|| { + WorkflowExecutionError::InvalidJobConfig( + "archive_path is required".to_string(), + ) + })?; + let archive_path = std::path::Path::new(archive_path); + if archive_path.is_absolute() + || archive_path.components().any(|component| { + matches!( + component, + std::path::Component::ParentDir + | std::path::Component::RootDir + | std::path::Component::Prefix(_) + ) + }) + { + return Err(WorkflowExecutionError::InvalidJobConfig( + "source archive path must remain inside the Temps data directory" + .to_string(), + )); + } + let absolute_path = self.config_service.data_dir().join(archive_path); + Ok(Arc::new(PrepareSourceBundleJob::new( + db_job.job_id.clone(), + absolute_path, + project.slug.clone(), + ))) + } + // Unsupported job types - log warning but don't fail the entire workflow "HealthCheckJob" | "DeployBasicJob" | "BuildStaticJob" => { warn!( diff --git a/crates/temps-deployments/src/services/workflow_planner.rs b/crates/temps-deployments/src/services/workflow_planner.rs index fe416c99c..8c8251dbf 100644 --- a/crates/temps-deployments/src/services/workflow_planner.rs +++ b/crates/temps-deployments/src/services/workflow_planner.rs @@ -997,6 +997,11 @@ impl WorkflowPlanner { debug!("Inferred StaticFiles deployment from static_bundle_path in metadata"); return SourceType::StaticFiles; } + + if metadata.source_bundle_path.is_some() { + debug!("Inferred UploadedSource deployment from source_bundle_path in metadata"); + return SourceType::UploadedSource; + } } // 4. Non-flexible projects: use project source type @@ -1132,6 +1137,17 @@ impl WorkflowPlanner { ) .await } + SourceType::UploadedSource => { + self.plan_git_deployment( + project, + environment, + deployment, + env_vars, + remote_env_vars, + secrets, + ) + .await + } SourceType::Manual => { // Manual projects without explicit deployment method // This happens when someone tries to deploy a Manual project without specifying @@ -1165,6 +1181,16 @@ impl WorkflowPlanner { ) -> anyhow::Result> { let mut jobs = Vec::new(); + let source_bundle_path = deployment + .metadata + .as_ref() + .and_then(|metadata| metadata.source_bundle_path.clone()); + let source_job_id = if source_bundle_path.is_some() { + "prepare_source_bundle" + } else { + "download_repo" + }; + // BuildKit's predefined BUILDKIT_CACHE_MOUNT_NS argument is applied to // every RUN --mount=type=cache ID. Scope it by project, environment, // and checked-out ref so unrelated tenants and preview branches cannot @@ -1208,7 +1234,17 @@ impl WorkflowPlanner { let has_git_info = !project.repo_owner.is_empty() && !project.repo_name.is_empty(); // Job 1: Download repository (only if git info is available) - if has_git_info { + if let Some(archive_path) = source_bundle_path { + jobs.push(JobDefinition { + job_id: source_job_id.to_string(), + job_type: "PrepareSourceBundleJob".to_string(), + name: "Prepare Uploaded Source".to_string(), + description: Some("Securely extract uploaded source code".to_string()), + dependencies: vec![], + job_config: Some(serde_json::json!({ "archive_path": archive_path })), + required_for_completion: true, + }); + } else if has_git_info { // Determine which branch/commit to use for this deployment // Priority: deployment.branch_ref > deployment.commit_sha > project.main_branch let branch_or_commit = deployment @@ -1261,8 +1297,8 @@ impl WorkflowPlanner { // Job 2: Build container image (skip for static deployments) // The BuildImageJob will generate Dockerfile from preset if it doesn't exist // Depends on download_repo only if git info is available - let build_dependencies = if has_git_info { - vec!["download_repo".to_string()] + let build_dependencies = if has_git_info || source_job_id == "prepare_source_bundle" { + vec![source_job_id.to_string()] } else { vec![] }; @@ -1597,7 +1633,7 @@ impl WorkflowPlanner { job_config: Some(serde_json::json!({ "project_id": project.id, "environment_id": deployment.environment_id, - "download_job_id": "download_repo" + "download_job_id": source_job_id })), required_for_completion: false, // Post-deployment job - not required for deployment success }); @@ -1619,7 +1655,7 @@ impl WorkflowPlanner { job_config: Some(serde_json::json!({ "project_id": project.id, "environment_id": deployment.environment_id, - "download_job_id": "download_repo" + "download_job_id": source_job_id })), required_for_completion: false, }); @@ -1637,7 +1673,7 @@ impl WorkflowPlanner { dependencies: vec!["mark_deployment_complete".to_string()], job_config: Some(serde_json::json!({ "project_id": project.id, - "download_job_id": "download_repo" + "download_job_id": source_job_id })), required_for_completion: false, }); @@ -1688,7 +1724,7 @@ impl WorkflowPlanner { "environment_id": deployment.environment_id, "branch": deployment.branch_ref, "commit_hash": deployment.commit_sha, - "download_job_id": "download_repo", + "download_job_id": source_job_id, "build_job_id": "build_image" })), required_for_completion: false, // Post-deployment job - not required for deployment success @@ -1776,7 +1812,7 @@ impl WorkflowPlanner { job_config: Some(serde_json::json!({ "project_id": project.id, "release": release, - "download_job_id": "download_repo", + "download_job_id": source_job_id, "build_job_id": "build_image", // None = default to the Docker build context; a set value // (or .temps.yaml sourceContext.root) overrides it. @@ -1814,11 +1850,26 @@ impl WorkflowPlanner { ) -> anyhow::Result> { let mut jobs = Vec::new(); + let source_bundle_path = deployment + .metadata + .as_ref() + .and_then(|metadata| metadata.source_bundle_path.clone()); + // Check if git info is available let has_git_info = !project.repo_owner.is_empty() && !project.repo_name.is_empty(); - // Job 1: Download repository (only if git-backed) - if has_git_info { + // Job 1: prepare either the uploaded archive or the Git checkout. + if let Some(archive_path) = source_bundle_path { + jobs.push(JobDefinition { + job_id: "prepare_source_bundle".to_string(), + job_type: "PrepareSourceBundleJob".to_string(), + name: "Prepare Uploaded Source".to_string(), + description: Some("Securely extract uploaded source code".to_string()), + dependencies: vec![], + job_config: Some(serde_json::json!({ "archive_path": archive_path })), + required_for_completion: true, + }); + } else if has_git_info { let branch_or_commit = deployment .branch_ref .as_ref() @@ -1860,7 +1911,14 @@ impl WorkflowPlanner { .unwrap_or_else(|| "docker-compose.yml".to_string()); // Job 2: Deploy Compose Stack (no build step) - let deploy_dependencies = if has_git_info { + let deploy_dependencies = if deployment + .metadata + .as_ref() + .and_then(|metadata| metadata.source_bundle_path.as_ref()) + .is_some() + { + vec!["prepare_source_bundle".to_string()] + } else if has_git_info { vec!["download_repo".to_string()] } else { vec![] @@ -2198,6 +2256,7 @@ impl WorkflowPlanner { "project_slug": project.slug, "environment_slug": environment.slug, "deployment_slug": deployment.slug, + "source_directory": project.directory, })), required_for_completion: true, }); @@ -2995,6 +3054,73 @@ mod tests { Ok(()) } + #[tokio::test] + async fn uploaded_compose_uses_prepared_archive_as_its_repository( + ) -> Result<(), Box> { + if std::env::var_os("TEMPS_TEST_DATABASE_URL").is_none() + && !tokio::process::Command::new("docker") + .arg("info") + .output() + .await + .map(|output| output.status.success()) + .unwrap_or(false) + { + eprintln!("Docker unavailable; skipping uploaded Compose planner test"); + return Ok(()); + } + + let test_db = TestDatabase::with_migrations().await?; + let db = test_db.connection_arc(); + let planner = WorkflowPlanner::new( + db.clone(), + Arc::new(LogService::new(std::env::temp_dir())), + create_test_external_service_manager(db.clone()), + create_test_config_service(db.clone()), + create_test_dsn_service(db.clone()), + create_test_encryption_service(), + ); + let (project, _environment, deployment) = + create_test_project(db.as_ref(), Preset::DockerCompose).await?; + + let mut project_update: projects::ActiveModel = project.into(); + project_update.source_type = Set(temps_entities::source_type::SourceType::UploadedSource); + project_update.repo_owner = Set(String::new()); + project_update.repo_name = Set(String::new()); + project_update.update(db.as_ref()).await?; + + let mut deployment_update: deployments::ActiveModel = deployment.into(); + deployment_update.metadata = Set(Some(temps_entities::deployments::DeploymentMetadata { + source_bundle_path: Some("source-bundles/fixture.zip".to_string()), + deployment_source_type: Some(temps_entities::source_type::SourceType::UploadedSource), + ..Default::default() + })); + let deployment = deployment_update.update(db.as_ref()).await?; + + let jobs = planner.create_deployment_jobs(deployment.id).await?; + let prepare = jobs + .iter() + .find(|job| job.job_id == "prepare_source_bundle") + .expect("uploaded Compose must prepare its source archive"); + assert_eq!( + prepare + .job_config + .as_ref() + .and_then(|config| config.get("archive_path")) + .and_then(serde_json::Value::as_str), + Some("source-bundles/fixture.zip") + ); + let compose = jobs + .iter() + .find(|job| job.job_id == "deploy_compose") + .expect("uploaded Compose must deploy the stack"); + assert_eq!( + compose.dependencies, + Some(serde_json::json!(["prepare_source_bundle"])) + ); + + Ok(()) + } + #[tokio::test] async fn test_log_id_format() -> Result<(), Box> { let test_db = TestDatabase::with_migrations().await?; diff --git a/crates/temps-entities/src/deployments.rs b/crates/temps-entities/src/deployments.rs index b4396d408..5162334f5 100644 --- a/crates/temps-entities/src/deployments.rs +++ b/crates/temps-entities/src/deployments.rs @@ -90,6 +90,19 @@ pub struct DeploymentMetadata { #[serde(skip_serializing_if = "Option::is_none")] pub static_bundle_content_type: Option, + /// Uploaded source archive ID. Source archives are extracted before the + /// regular preset build pipeline and do not require Git metadata. + #[serde(skip_serializing_if = "Option::is_none")] + pub source_bundle_id: Option, + + /// Uploaded source archive path in the Temps data directory. + #[serde(skip_serializing_if = "Option::is_none")] + pub source_bundle_path: Option, + + /// Uploaded source archive content type. + #[serde(skip_serializing_if = "Option::is_none")] + pub source_bundle_content_type: Option, + /// Source type for THIS specific deployment (for Manual/flexible projects) /// This allows Manual projects to have deployments via different methods /// (docker_image, static_files, or git) while keeping per-deployment tracking diff --git a/crates/temps-entities/src/lib.rs b/crates/temps-entities/src/lib.rs index 5b2c0ead4..af58d7dce 100644 --- a/crates/temps-entities/src/lib.rs +++ b/crates/temps-entities/src/lib.rs @@ -93,6 +93,7 @@ pub mod secrets; pub mod service_endpoints; pub mod service_members; pub mod sessions; +pub mod source_bundles; pub mod source_type; pub mod static_asset_cache; pub mod static_bundles; diff --git a/crates/temps-entities/src/prelude.rs b/crates/temps-entities/src/prelude.rs index 9e20e6308..c3f38f87e 100644 --- a/crates/temps-entities/src/prelude.rs +++ b/crates/temps-entities/src/prelude.rs @@ -51,6 +51,7 @@ pub use super::session_replay_events::Entity as SessionReplayEvents; pub use super::session_replay_sessions::Entity as SessionReplaySessions; pub use super::sessions::Entity as Sessions; pub use super::settings::Entity as Settings; +pub use super::source_bundles::Entity as SourceBundles; pub use super::source_type::SourceType; pub use super::static_bundles::{BundleFormat, Entity as StaticBundles}; pub use super::team_members::Entity as TeamMembers; diff --git a/crates/temps-entities/src/source_bundles.rs b/crates/temps-entities/src/source_bundles.rs new file mode 100644 index 000000000..714d75154 --- /dev/null +++ b/crates/temps-entities/src/source_bundles.rs @@ -0,0 +1,60 @@ +//! Uploaded source archives used by Git-less preset builds. + +use async_trait::async_trait; +use sea_orm::entity::prelude::*; +use sea_orm::{ActiveValue::Set, ConnectionTrait, DbErr}; +use serde::{Deserialize, Serialize}; +use temps_core::DBDateTime; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Serialize, Deserialize)] +#[sea_orm(table_name = "source_bundles")] +pub struct Model { + #[sea_orm(primary_key)] + pub id: i32, + pub project_id: i32, + pub archive_path: String, + pub original_filename: Option, + pub content_type: String, + pub size_bytes: i64, + pub checksum: String, + pub directory: String, + pub preset: String, + pub metadata: Option, + pub uploaded_at: DBDateTime, + pub created_at: DBDateTime, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm( + belongs_to = "super::projects::Entity", + from = "Column::ProjectId", + to = "super::projects::Column::Id" + )] + Project, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Project.def() + } +} + +#[async_trait] +impl ActiveModelBehavior for ActiveModel { + async fn before_save(mut self, _db: &C, insert: bool) -> Result + where + C: ConnectionTrait, + { + if insert { + let now = chrono::Utc::now(); + if self.created_at.is_not_set() { + self.created_at = Set(now); + } + if self.uploaded_at.is_not_set() { + self.uploaded_at = Set(now); + } + } + Ok(self) + } +} diff --git a/crates/temps-entities/src/source_type.rs b/crates/temps-entities/src/source_type.rs index 91a98dff9..7750d0d56 100644 --- a/crates/temps-entities/src/source_type.rs +++ b/crates/temps-entities/src/source_type.rs @@ -13,6 +13,7 @@ use utoipa::ToSchema; /// - `Git`: Source code from a Git repository (traditional flow) /// - `DockerImage`: Pre-built Docker image from external registry /// - `StaticFiles`: Pre-built static files uploaded as a bundle +/// - `UploadedSource`: Source archive uploaded without a Git repository /// - `Manual`: Flexible type that accepts any deployment method #[derive( Debug, @@ -47,6 +48,11 @@ pub enum SourceType { #[sea_orm(string_value = "static_files")] StaticFiles, + /// Source code uploaded as an archive, built with the selected preset, + /// and deployed through the normal source build pipeline. + #[sea_orm(string_value = "uploaded_source")] + UploadedSource, + /// Manual/Flexible deployments /// Accepts any deployment method: Docker images, static files, or Git-based /// Allows switching between deployment methods without recreating the project @@ -60,6 +66,7 @@ impl std::fmt::Display for SourceType { SourceType::Git => write!(f, "git"), SourceType::DockerImage => write!(f, "docker_image"), SourceType::StaticFiles => write!(f, "static_files"), + SourceType::UploadedSource => write!(f, "uploaded_source"), SourceType::Manual => write!(f, "manual"), } } @@ -75,7 +82,10 @@ impl SourceType { pub fn supports_crons(&self) -> bool { matches!( self, - SourceType::Git | SourceType::DockerImage | SourceType::Manual + SourceType::Git + | SourceType::DockerImage + | SourceType::UploadedSource + | SourceType::Manual ) } @@ -83,7 +93,10 @@ impl SourceType { pub fn is_container_based(&self) -> bool { matches!( self, - SourceType::Git | SourceType::DockerImage | SourceType::Manual + SourceType::Git + | SourceType::DockerImage + | SourceType::UploadedSource + | SourceType::Manual ) } @@ -127,6 +140,7 @@ mod tests { assert_eq!(SourceType::Git.to_string(), "git"); assert_eq!(SourceType::DockerImage.to_string(), "docker_image"); assert_eq!(SourceType::StaticFiles.to_string(), "static_files"); + assert_eq!(SourceType::UploadedSource.to_string(), "uploaded_source"); assert_eq!(SourceType::Manual.to_string(), "manual"); } @@ -135,6 +149,7 @@ mod tests { assert!(SourceType::Git.requires_git_info()); assert!(!SourceType::DockerImage.requires_git_info()); assert!(!SourceType::StaticFiles.requires_git_info()); + assert!(!SourceType::UploadedSource.requires_git_info()); assert!(!SourceType::Manual.requires_git_info()); } @@ -143,6 +158,7 @@ mod tests { assert!(SourceType::Git.is_container_based()); assert!(SourceType::DockerImage.is_container_based()); assert!(!SourceType::StaticFiles.is_container_based()); + assert!(SourceType::UploadedSource.is_container_based()); assert!(SourceType::Manual.is_container_based()); } @@ -151,6 +167,7 @@ mod tests { assert!(!SourceType::Git.is_static()); assert!(!SourceType::DockerImage.is_static()); assert!(SourceType::StaticFiles.is_static()); + assert!(!SourceType::UploadedSource.is_static()); assert!(!SourceType::Manual.is_static()); } @@ -159,6 +176,7 @@ mod tests { assert!(!SourceType::Git.is_flexible()); assert!(!SourceType::DockerImage.is_flexible()); assert!(!SourceType::StaticFiles.is_flexible()); + assert!(!SourceType::UploadedSource.is_flexible()); assert!(SourceType::Manual.is_flexible()); } @@ -187,6 +205,7 @@ mod tests { assert!(SourceType::StaticFiles.allows_deployment_method(&SourceType::StaticFiles)); assert!(SourceType::StaticFiles.allows_deployment_method(&SourceType::Git)); assert!(SourceType::StaticFiles.allows_deployment_method(&SourceType::DockerImage)); + assert!(SourceType::UploadedSource.allows_deployment_method(&SourceType::UploadedSource)); } #[test] @@ -204,6 +223,10 @@ mod tests { serde_json::to_string(&SourceType::Manual).unwrap(), "\"manual\"" ); + assert_eq!( + serde_json::to_string(&SourceType::UploadedSource).unwrap(), + "\"uploaded_source\"" + ); } #[test] @@ -224,5 +247,9 @@ mod tests { serde_json::from_str::("\"manual\"").unwrap(), SourceType::Manual ); + assert_eq!( + serde_json::from_str::("\"uploaded_source\"").unwrap(), + SourceType::UploadedSource + ); } } diff --git a/crates/temps-migrations/src/migration/m20260731_000001_create_source_bundles.rs b/crates/temps-migrations/src/migration/m20260731_000001_create_source_bundles.rs new file mode 100644 index 000000000..978f45cb2 --- /dev/null +++ b/crates/temps-migrations/src/migration/m20260731_000001_create_source_bundles.rs @@ -0,0 +1,130 @@ +use sea_orm_migration::prelude::*; + +#[derive(DeriveMigrationName)] +pub struct Migration; + +#[async_trait::async_trait] +impl MigrationTrait for Migration { + async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> { + manager + .create_table( + Table::create() + .table(SourceBundles::Table) + .if_not_exists() + .col( + ColumnDef::new(SourceBundles::Id) + .integer() + .not_null() + .auto_increment() + .primary_key(), + ) + .col( + ColumnDef::new(SourceBundles::ProjectId) + .integer() + .not_null(), + ) + .col( + ColumnDef::new(SourceBundles::ArchivePath) + .string_len(500) + .not_null(), + ) + .col( + ColumnDef::new(SourceBundles::OriginalFilename) + .string_len(255) + .null(), + ) + .col( + ColumnDef::new(SourceBundles::ContentType) + .string_len(100) + .not_null(), + ) + .col( + ColumnDef::new(SourceBundles::SizeBytes) + .big_integer() + .not_null(), + ) + .col( + ColumnDef::new(SourceBundles::Checksum) + .string_len(80) + .not_null(), + ) + .col( + ColumnDef::new(SourceBundles::Directory) + .string_len(500) + .not_null(), + ) + .col( + ColumnDef::new(SourceBundles::Preset) + .string_len(50) + .not_null(), + ) + .col(ColumnDef::new(SourceBundles::Metadata).json_binary().null()) + .col( + ColumnDef::new(SourceBundles::UploadedAt) + .timestamp_with_time_zone() + .not_null() + .default(Expr::current_timestamp()), + ) + .col( + ColumnDef::new(SourceBundles::CreatedAt) + .timestamp_with_time_zone() + .not_null() + .default(Expr::current_timestamp()), + ) + .foreign_key( + ForeignKey::create() + .name("fk_source_bundles_project") + .from(SourceBundles::Table, SourceBundles::ProjectId) + .to(Projects::Table, Projects::Id) + .on_delete(ForeignKeyAction::Cascade), + ) + .to_owned(), + ) + .await?; + manager + .create_index( + Index::create() + .name("idx_source_bundles_project_uploaded") + .if_not_exists() + .table(SourceBundles::Table) + .col(SourceBundles::ProjectId) + .col(SourceBundles::UploadedAt) + .to_owned(), + ) + .await + } + + async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> { + manager + .drop_table( + Table::drop() + .table(SourceBundles::Table) + .if_exists() + .to_owned(), + ) + .await + } +} + +#[derive(DeriveIden)] +enum SourceBundles { + Table, + Id, + ProjectId, + ArchivePath, + OriginalFilename, + ContentType, + SizeBytes, + Checksum, + Directory, + Preset, + Metadata, + UploadedAt, + CreatedAt, +} + +#[derive(DeriveIden)] +enum Projects { + Table, + Id, +} diff --git a/crates/temps-migrations/src/migration/mod.rs b/crates/temps-migrations/src/migration/mod.rs index 3c7ea0fd2..5c25655c7 100644 --- a/crates/temps-migrations/src/migration/mod.rs +++ b/crates/temps-migrations/src/migration/mod.rs @@ -166,6 +166,7 @@ mod m20260725_000001_sandboxes_agent_run_link; mod m20260728_000001_add_environment_id_to_metric_alert_rules; mod m20260730_000001_add_architecture_to_nodes; mod m20260730_000001_create_teams_rbac; +mod m20260731_000001_create_source_bundles; mod m20260802_000001_add_environment_force_https; mod m20260802_000002_create_feature_flags; mod m20260803_000001_add_flag_last_evaluated_at; @@ -344,6 +345,7 @@ impl MigratorTrait for Migrator { ), Box::new(m20260730_000001_add_architecture_to_nodes::Migration), Box::new(m20260730_000001_create_teams_rbac::Migration), + Box::new(m20260731_000001_create_source_bundles::Migration), Box::new(m20260802_000001_add_environment_force_https::Migration), Box::new(m20260802_000002_create_feature_flags::Migration), Box::new(m20260803_000001_add_flag_last_evaluated_at::Migration), diff --git a/crates/temps-presets/src/framework_detector.rs b/crates/temps-presets/src/framework_detector.rs index 603fd602c..e51aca15d 100644 --- a/crates/temps-presets/src/framework_detector.rs +++ b/crates/temps-presets/src/framework_detector.rs @@ -198,7 +198,12 @@ pub fn detect_node_framework(project_path: &Path) -> NodeFramework { } }; - let package_json: PackageJson = match serde_json::from_str(&package_json_content) { + detect_node_framework_from_package_json(&package_json_content) +} + +/// Detect a framework from already-confined, size-bounded package.json text. +pub fn detect_node_framework_from_package_json(package_json_content: &str) -> NodeFramework { + let package_json: PackageJson = match serde_json::from_str(package_json_content) { Ok(pkg) => pkg, Err(e) => { warn!("Failed to parse package.json: {}", e); diff --git a/crates/temps-presets/src/lib.rs b/crates/temps-presets/src/lib.rs index e3838399e..4516d3025 100644 --- a/crates/temps-presets/src/lib.rs +++ b/crates/temps-presets/src/lib.rs @@ -13,11 +13,11 @@ mod mod_rs { // Re-export main types for easy access pub use { - all_presets, detect_all_presets_from_files, detect_node_framework, detect_preset_from_files, - get_preset_by_slug, get_preset_for_storage, resolve_preset_slug, runtime_slug, - validate_preset_config, DockerfileWithArgs, JavaPreset, NixpacksPreset, NixpacksProvider, - NodeFramework, PackageManager, Preset, PresetConfig, PresetResolutionError, ProjectType, - StoredPreset, + all_presets, detect_all_presets_from_files, detect_node_framework, + detect_node_framework_from_package_json, detect_preset_from_files, get_preset_by_slug, + get_preset_for_storage, resolve_preset_slug, runtime_slug, validate_preset_config, + DockerfileWithArgs, JavaPreset, NixpacksPreset, NixpacksProvider, NodeFramework, + PackageManager, Preset, PresetConfig, PresetResolutionError, ProjectType, StoredPreset, }; #[cfg(test)] diff --git a/crates/temps-presets/src/mod.rs b/crates/temps-presets/src/mod.rs index a7a9e0660..62b700b18 100644 --- a/crates/temps-presets/src/mod.rs +++ b/crates/temps-presets/src/mod.rs @@ -1,55 +1,57 @@ -use std::{fmt, path::Path}; use async_trait::async_trait; +use std::{fmt, path::Path}; +mod autopack_preset; +mod build_system; mod docker; mod docker_compose; mod docker_custom; mod docusaurus; +mod framework_detector; +mod go_preset; +mod java_preset; mod nextjs; -mod autopack_preset; mod nixpacks_preset; +mod preset_config; +mod python_preset; mod react_app; mod rsbuild; -mod vite; -mod build_system; -mod preset_config; -mod framework_detector; mod rust_preset; -mod go_preset; -mod python_preset; -mod java_preset; +mod vite; // Preset configuration schemas // Source abstraction for file access -pub mod source; pub mod preset_config_schema; +pub mod source; // New preset provider system pub mod preset_provider; pub mod providers; // Re-export Preset enum from temps-entities -pub use temps_entities::preset::Preset as PresetType; -use temps_entities::preset::{ - DockerfileVariant, NixpacksConfig, PresetConfig as StoredPresetConfig, -}; +pub use autopack_preset::AutopackPreset; use build_system::BuildSystem; -use docusaurus::Docusaurus; +pub use build_system::MonorepoTool; use docker::DockerfilePreset; use docker_custom::DockerCustomPreset; +use docusaurus::Docusaurus; +pub use framework_detector::{ + detect_node_framework, detect_node_framework_from_package_json, NodeFramework, +}; +pub use go_preset::GoPreset; +pub use java_preset::JavaPreset; pub use nextjs::NextJs; -pub use autopack_preset::AutopackPreset; pub use nixpacks_preset::{NixpacksPreset, NixpacksProvider}; +pub use preset_config::PresetConfig; +pub use python_preset::PythonPreset; pub use react_app::CreateReactApp; use rsbuild::Rsbuild; -pub use vite::Vite; -pub use build_system::MonorepoTool; -pub use preset_config::PresetConfig; -pub use framework_detector::{detect_node_framework, NodeFramework}; pub use rust_preset::RustPreset; -pub use go_preset::GoPreset; -pub use python_preset::PythonPreset; -pub use java_preset::JavaPreset; +pub use temps_entities::preset::Preset as PresetType; +use temps_entities::preset::{ + DockerfileVariant, NixpacksConfig, PresetConfig as StoredPresetConfig, +}; +pub use vite::Vite; #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum ProjectType { @@ -170,11 +172,7 @@ pub struct DockerfileConfig<'a> { impl<'a> DockerfileConfig<'a> { /// Create a new DockerfileConfig with default values (BuildKit disabled) - pub fn new( - root_local_path: &'a Path, - local_path: &'a Path, - project_slug: &'a str, - ) -> Self { + pub fn new(root_local_path: &'a Path, local_path: &'a Path, project_slug: &'a str) -> Self { Self { root_local_path, local_path, @@ -238,7 +236,10 @@ impl DockerfileWithArgs { } /// Create a new DockerfileWithArgs with content and build args - pub fn with_args(content: String, build_args: std::collections::HashMap) -> Self { + pub fn with_args( + content: String, + build_args: std::collections::HashMap, + ) -> Self { Self { content, build_args, @@ -359,10 +360,9 @@ pub fn resolve_preset_slug( slug: &str, config: Option, ) -> Result { - let preset = - get_preset_by_slug(slug).ok_or_else(|| PresetResolutionError::UnknownSlug { - slug: slug.to_string(), - })?; + let preset = get_preset_by_slug(slug).ok_or_else(|| PresetResolutionError::UnknownSlug { + slug: slug.to_string(), + })?; preset.resolve_storage(config) } @@ -402,9 +402,7 @@ pub fn get_preset_for_storage( Some(StoredPresetConfig::Nixpacks(config)) => config.clone(), _ => NixpacksConfig::default(), }; - return Ok(Some(Box::new(NixpacksPreset::from_config( - nixpacks_config, - )))); + return Ok(Some(Box::new(NixpacksPreset::from_config(nixpacks_config)))); } if preset == PresetType::Dockerfile { @@ -430,10 +428,7 @@ pub fn get_preset_for_storage( /// /// Multi-provider Nixpacks configurations intentionally use the canonical /// `nixpacks` slug because no single catalog variant can represent them. -pub fn runtime_slug( - preset: PresetType, - config: Option<&StoredPresetConfig>, -) -> String { +pub fn runtime_slug(preset: PresetType, config: Option<&StoredPresetConfig>) -> String { get_preset_for_storage(preset, config) .ok() .flatten() @@ -558,6 +553,234 @@ pub struct DetectedPreset { pub compose_files: Option>, } +/// Detection result with the evidence that selected the preset. This is used +/// by archive uploads where file contents (especially package.json) are +/// available without a Git checkout. +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct ProjectCandidate { + pub path: String, + pub preset: PresetType, + pub confidence: &'static str, + pub reason: String, +} + +impl ProjectCandidate { + /// Return the public preset catalog slug that can be passed to project + /// creation for this detected candidate. + /// + /// Some canonical framework identifiers do not have a dedicated build + /// preset yet. Those projects are still zero-config deployable through + /// the matching Nixpacks provider. + pub fn catalog_slug(&self) -> &'static str { + match self.preset { + PresetType::Astro + | PresetType::Nuxt + | PresetType::Remix + | PresetType::SvelteKit + | PresetType::SolidStart + | PresetType::Angular + | PresetType::Vue + | PresetType::NodeJs => "nixpacks-node", + PresetType::Static => "nixpacks-static", + _ => self.preset.as_str(), + } + } +} + +/// Detect deployable project roots from normalized archive entries. +/// +/// `files` maps slash-separated relative paths to the contents of small text +/// manifests. Binary and large files may be represented by an empty string. +pub fn detect_project_candidates( + files: &std::collections::BTreeMap, +) -> Vec { + use std::collections::{BTreeMap, BTreeSet}; + + /// Directories that never contain a *deployable* root — they hold + /// dependencies, build output, or VCS metadata. Without this a ZIP that + /// shipped its `node_modules` offers thousands of bogus candidates. + const SKIP_SEGMENTS: [&str; 8] = [ + "node_modules", + ".git", + "dist", + "build", + "vendor", + "target", + ".next", + "__pycache__", + ]; + /// Deployable roots live near the top of an archive. Bounding depth keeps + /// a pathological archive from turning detection into an O(n^2) walk. + const MAX_ROOT_DEPTH: usize = 4; + + // Index every path by its directory ONCE. The previous implementation + // rescanned all of `files` for each root, which is O(roots x files) — a + // 20k-entry archive turned into ~4x10^8 string comparisons per request. + let mut by_directory: BTreeMap<&str, Vec<&str>> = BTreeMap::new(); + for path in files.keys() { + let (directory, name) = match path.rsplit_once('/') { + Some((directory, name)) => (directory, name), + None => (".", path.as_str()), + }; + if directory + .split('/') + .any(|segment| SKIP_SEGMENTS.contains(&segment)) + { + continue; + } + if directory != "." && directory.split('/').count() > MAX_ROOT_DEPTH { + continue; + } + by_directory.entry(directory).or_default().push(name); + } + + let mut roots = BTreeSet::new(); + for (directory, names) in &by_directory { + if names.iter().any(|name| { + matches!( + *name, + "package.json" + | "Dockerfile" + | "docker-compose.yml" + | "docker-compose.yaml" + | "compose.yml" + | "compose.yaml" + | "Cargo.toml" + | "go.mod" + | "requirements.txt" + | "pyproject.toml" + | "pom.xml" + | "build.gradle" + | "index.html" + ) || name.ends_with(".csproj") + || name.starts_with("next.config.") + || name.starts_with("vite.config.") + || name.starts_with("astro.config.") + }) { + roots.insert(*directory); + } + } + + let mut candidates = Vec::new(); + for root in roots { + let at_root = |name: &str| { + if root == "." { + name.to_string() + } else { + format!("{root}/{name}") + } + }; + let names = by_directory.get(root).map(Vec::as_slice).unwrap_or(&[]); + let has = |name: &str| names.contains(&name); + let has_extension = + |extension: &str| names.iter().any(|name| name.ends_with(extension)); + + let detected = if has("docker-compose.yml") + || has("docker-compose.yaml") + || has("compose.yml") + || has("compose.yaml") + { + Some(( + PresetType::DockerCompose, + "high", + "Docker Compose file found".to_string(), + )) + } else if has("Dockerfile") { + Some(( + PresetType::Dockerfile, + "high", + "Dockerfile found".to_string(), + )) + } else if let Some(package_json) = files.get(&at_root("package.json")) { + detect_package_json_preset(package_json) + } else if has("Cargo.toml") { + Some((PresetType::Rust, "high", "Cargo.toml found".to_string())) + } else if has("go.mod") { + Some((PresetType::Go, "high", "go.mod found".to_string())) + } else if has("requirements.txt") || has("pyproject.toml") { + Some(( + PresetType::Python, + "medium", + "Python manifest found".to_string(), + )) + } else if has("pom.xml") || has("build.gradle") { + Some(( + PresetType::Java, + "high", + "Java build manifest found".to_string(), + )) + } else if has_extension(".csproj") { + Some(( + PresetType::Nixpacks, + "high", + ".NET project file found".to_string(), + )) + } else if has("index.html") { + Some((PresetType::Static, "medium", "index.html found".to_string())) + } else { + None + }; + + if let Some((preset, confidence, reason)) = detected { + candidates.push(ProjectCandidate { + path: root.to_string(), + preset, + confidence, + reason, + }); + } + } + + candidates.sort_by(|left, right| { + let left_root = left.path == "."; + let right_root = right.path == "."; + right_root + .cmp(&left_root) + .then_with(|| left.path.cmp(&right.path)) + }); + candidates +} + +fn detect_package_json_preset(content: &str) -> Option<(PresetType, &'static str, String)> { + let package: serde_json::Value = serde_json::from_str(content).ok()?; + let has_dependency = |name: &str| { + package + .get("dependencies") + .and_then(|value| value.get(name)) + .is_some() + || package + .get("devDependencies") + .and_then(|value| value.get(name)) + .is_some() + }; + + let (preset, label) = if has_dependency("next") { + (PresetType::NextJs, "next") + } else if has_dependency("astro") { + (PresetType::Astro, "astro") + } else if has_dependency("nuxt") { + (PresetType::Nuxt, "nuxt") + } else if has_dependency("@remix-run/react") { + (PresetType::Remix, "@remix-run/react") + } else if has_dependency("@sveltejs/kit") { + (PresetType::SvelteKit, "@sveltejs/kit") + } else if has_dependency("vite") { + (PresetType::Vite, "vite") + } else { + return Some(( + PresetType::NodeJs, + "medium", + "package.json found".to_string(), + )); + }; + + Some(( + preset, + "high", + format!("{label} dependency found in package.json"), + )) +} + /// Detect all presets in a file tree /// /// This function analyzes a complete file tree and identifies presets in different directories. @@ -687,3 +910,199 @@ pub fn detect_presets_from_file_tree(files: &[String]) -> Vec { presets } + +#[cfg(test)] +mod uploaded_source_detection_tests { + use super::*; + use std::collections::BTreeMap; + + #[test] + fn detects_next_without_a_next_config_file() { + let files = BTreeMap::from([( + "package.json".to_string(), + r#"{"dependencies":{"next":"15.0.0","react":"19.0.0"}}"#.to_string(), + )]); + + let candidates = detect_project_candidates(&files); + + assert_eq!(candidates.len(), 1); + assert_eq!(candidates[0].preset, PresetType::NextJs); + assert_eq!(candidates[0].path, "."); + assert_eq!(candidates[0].confidence, "high"); + } + + #[test] + fn detects_nested_node_and_vite_projects_in_stable_order() { + let files = BTreeMap::from([ + ( + "apps/api/package.json".to_string(), + r#"{"dependencies":{"express":"5.0.0"}}"#.to_string(), + ), + ( + "apps/web/package.json".to_string(), + r#"{"devDependencies":{"vite":"7.0.0"}}"#.to_string(), + ), + ]); + + let candidates = detect_project_candidates(&files); + + assert_eq!(candidates.len(), 2); + assert_eq!(candidates[0].path, "apps/api"); + assert_eq!(candidates[0].preset, PresetType::NodeJs); + assert_eq!(candidates[1].path, "apps/web"); + assert_eq!(candidates[1].preset, PresetType::Vite); + } + + #[test] + fn dockerfile_takes_priority_over_package_json() { + let files = BTreeMap::from([ + ("Dockerfile".to_string(), "FROM node:22".to_string()), + ("package.json".to_string(), "{}".to_string()), + ]); + + let candidates = detect_project_candidates(&files); + + assert_eq!(candidates[0].preset, PresetType::Dockerfile); + } + + #[test] + fn detects_dotnet_project_in_nested_directory() { + let files = BTreeMap::from([( + "services/api/Api.csproj".to_string(), + r#""#.to_string(), + )]); + + let candidates = detect_project_candidates(&files); + + assert_eq!(candidates.len(), 1); + assert_eq!(candidates[0].path, "services/api"); + assert_eq!(candidates[0].preset, PresetType::Nixpacks); + assert!(candidates[0].reason.contains(".NET")); + } + + #[test] + fn every_detected_candidate_exposes_a_resolvable_catalog_slug() { + let fixtures = [ + BTreeMap::from([( + "package.json".to_string(), + r#"{"dependencies":{"express":"5.0.0"}}"#.to_string(), + )]), + BTreeMap::from([( + "package.json".to_string(), + r#"{"dependencies":{"astro":"5.0.0"}}"#.to_string(), + )]), + BTreeMap::from([("index.html".to_string(), "".to_string())]), + ]; + + for files in fixtures { + let candidate = detect_project_candidates(&files) + .into_iter() + .next() + .expect("fixture should produce a candidate"); + + resolve_preset_slug(candidate.catalog_slug(), None).unwrap_or_else(|error| { + panic!( + "detected {:?} emitted invalid catalog slug '{}': {error}", + candidate.preset, + candidate.catalog_slug() + ) + }); + } + } + + #[test] + fn detects_docker_compose_at_the_archive_root() { + for name in [ + "docker-compose.yml", + "docker-compose.yaml", + "compose.yml", + "compose.yaml", + ] { + let files = BTreeMap::from([ + (name.to_string(), "services:\n web:\n image: nginx".to_string()), + ("package.json".to_string(), "{}".to_string()), + ]); + + let candidates = detect_project_candidates(&files); + + assert_eq!(candidates.len(), 1, "{name} should yield one candidate"); + assert_eq!( + candidates[0].preset, + PresetType::DockerCompose, + "{name} should win over package.json" + ); + assert_eq!(candidates[0].path, "."); + } + } + + #[test] + fn detects_project_wrapped_in_a_single_top_level_directory() { + // GitHub-style archives wrap everything in `-/`. + let files = BTreeMap::from([( + "my-app-main/package.json".to_string(), + r#"{"dependencies":{"next":"15.0.0"}}"#.to_string(), + )]); + + let candidates = detect_project_candidates(&files); + + assert_eq!(candidates.len(), 1); + assert_eq!(candidates[0].path, "my-app-main"); + assert_eq!(candidates[0].preset, PresetType::NextJs); + } + + #[test] + fn ignores_dependency_and_build_output_directories() { + let files = BTreeMap::from([ + ( + "package.json".to_string(), + r#"{"dependencies":{"vite":"7.0.0"}}"#.to_string(), + ), + ("node_modules/left-pad/package.json".to_string(), "{}".to_string()), + ("dist/index.html".to_string(), "".to_string()), + ("vendor/thing/go.mod".to_string(), "module thing".to_string()), + ("target/debug/Cargo.toml".to_string(), "[package]".to_string()), + (".git/config".to_string(), String::new()), + ]); + + let candidates = detect_project_candidates(&files); + + assert_eq!( + candidates.len(), + 1, + "only the real root is deployable, got {candidates:?}" + ); + assert_eq!(candidates[0].path, "."); + assert_eq!(candidates[0].preset, PresetType::Vite); + } + + #[test] + fn deeply_nested_directories_do_not_become_candidates() { + let files = BTreeMap::from([( + "a/b/c/d/e/package.json".to_string(), + r#"{"dependencies":{"express":"5.0.0"}}"#.to_string(), + )]); + + assert!(detect_project_candidates(&files).is_empty()); + } + + /// Regression guard for the O(roots x files) scan: this fixture used to + /// cost ~4x10^8 string comparisons. It must now stay linear enough to + /// finish effectively instantly. + #[test] + fn wide_archives_do_not_blow_up_detection() { + let mut files = BTreeMap::new(); + for i in 0..5_000 { + files.insert(format!("site{i}/index.html"), "".to_string()); + } + + let started = std::time::Instant::now(); + let candidates = detect_project_candidates(&files); + let elapsed = started.elapsed(); + + assert_eq!(candidates.len(), 5_000); + assert!( + elapsed < std::time::Duration::from_secs(2), + "detection took {elapsed:?} — the per-root full scan is back" + ); + } +} diff --git a/crates/temps-presets/src/nextjs.rs b/crates/temps-presets/src/nextjs.rs index 04497141d..1b91269e2 100644 --- a/crates/temps-presets/src/nextjs.rs +++ b/crates/temps-presets/src/nextjs.rs @@ -1,8 +1,8 @@ use super::build_system::{BuildSystem, MonorepoTool}; use super::{DockerfileWithArgs, PackageManager, Preset, ProjectType}; use async_trait::async_trait; -use tracing::debug; use std::path::Path; +use tracing::debug; /// Security hardening for Node.js Alpine runner /// This approach provides security while maintaining compatibility: @@ -48,7 +48,8 @@ impl Preset for NextJs { // Calculate relative path from root to project directory for monorepos let relative_path = if config.local_path != config.root_local_path { - config.local_path + config + .local_path .strip_prefix(config.root_local_path) .map(|p| p.to_string_lossy().to_string()) .unwrap_or_default() @@ -60,9 +61,15 @@ impl Preset for NextJs { // Use provided commands or fall back to build system commands let build_system_install_cmd = &build_system.get_install_command(); - let mut install_cmd = config.install_command.unwrap_or(build_system_install_cmd).to_string(); + let mut install_cmd = config + .install_command + .unwrap_or(build_system_install_cmd) + .to_string(); let build_system_build_cmd = &build_system.get_build_command(Some(&project_slug)); - let mut build_cmd = config.build_command.unwrap_or(build_system_build_cmd).to_string(); + let mut build_cmd = config + .build_command + .unwrap_or(build_system_build_cmd) + .to_string(); // For Bun, ensure we use the full path in cache mount contexts if matches!(package_manager, PackageManager::Bun) { @@ -72,11 +79,14 @@ impl Preset for NextJs { // Use explicit path to Next.js binary with node // Alpine has node available, so we use exec form with node - let start_cmd = format!("node\", \"/{}/node_modules/next/dist/bin/next\", \"start", project_slug); + let start_cmd = format!( + "node\", \"/{}/node_modules/next/dist/bin/next\", \"start", + project_slug + ); // Build stage uses full Node.js image with package managers let base_image = match package_manager { - PackageManager::Bun => "node:22", // Bun needs apt for installation + PackageManager::Bun => "node:22", // Bun needs apt for installation PackageManager::Yarn => "node:22-alpine", _ => "node:22", }; @@ -108,7 +118,6 @@ RUN corepack enable } else if matches!(package_manager, PackageManager::Pnpm) { r#"# Enable corepack for pnpm RUN corepack enable -RUN corepack prepare pnpm@latest --activate "# } else { @@ -117,7 +126,9 @@ RUN corepack prepare pnpm@latest --activate // Determine the working directory - for monorepos with subdirectories, // we copy everything to /{project_slug} but then work in the subdirectory - let workdir = if !relative_path.is_empty() && !matches!(build_system.monorepo_tool, MonorepoTool::None) { + let workdir = if !relative_path.is_empty() + && !matches!(build_system.monorepo_tool, MonorepoTool::None) + { format!("/{project_slug}/{relative_path}") } else { format!("/{project_slug}") @@ -163,7 +174,7 @@ WORKDIR /{project_slug} // Copy Yarn Berry configuration files if they exist dockerfile.push_str("COPY .yarnrc.yml* .\n"); dockerfile.push_str("COPY .yarn* ./.yarn/\n"); - }, + } PackageManager::Pnpm => dockerfile.push_str("COPY pnpm-lock.yaml .\n"), _ => {} } @@ -173,7 +184,10 @@ WORKDIR /{project_slug} // Change to subdirectory if this is a monorepo subproject if !relative_path.is_empty() { - dockerfile.push_str(&format!("\n# Change to project subdirectory\nWORKDIR {}\n", workdir)); + dockerfile.push_str(&format!( + "\n# Change to project subdirectory\nWORKDIR {}\n", + workdir + )); } } } @@ -294,7 +308,8 @@ EXPOSE 3000 async fn dockerfile_with_build_dir(&self, _local_path: &Path) -> DockerfileWithArgs { // Use hardened Alpine for security with full CA certificate support - let content = format!(r#" + let content = format!( + r#" # Use hardened Alpine Node.js image # Secure: non-root user, package manager removed, full CA certificates for HTTPS FROM node:22-alpine AS runner @@ -317,7 +332,9 @@ EXPOSE 3000 # Start the Next.js application CMD ["node", "server.js"] -"#, alpine_hardening = NODEJS_ALPINE_SECURITY_HARDENING); +"#, + alpine_hardening = NODEJS_ALPINE_SECURITY_HARDENING + ); DockerfileWithArgs::new(content) } @@ -343,7 +360,6 @@ CMD ["node", "server.js"] } } - impl std::fmt::Display for NextJs { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{}", self.label()) @@ -363,20 +379,26 @@ mod tests { std::fs::write(temp_dir.join("bun.lock"), "").unwrap(); let preset = NextJs; - let result = preset.dockerfile(DockerfileConfig { - use_buildkit: true, - root_local_path: &temp_dir, - local_path: &temp_dir, - install_command: None, - build_command: None, - output_dir: None, - build_vars: None, - project_slug: "test-project", - }).await; + let result = preset + .dockerfile(DockerfileConfig { + use_buildkit: true, + root_local_path: &temp_dir, + local_path: &temp_dir, + install_command: None, + build_command: None, + output_dir: None, + build_vars: None, + project_slug: "test-project", + }) + .await; // Verify Bun is installed - assert!(result.content.contains("curl -fsSL https://bun.sh/install | bash")); - assert!(result.content.contains("ENV PATH=\"/root/.bun/bin:${PATH}\"")); + assert!(result + .content + .contains("curl -fsSL https://bun.sh/install | bash")); + assert!(result + .content + .contains("ENV PATH=\"/root/.bun/bin:${PATH}\"")); // Verify commands use full path to bun assert!(result.content.contains("/root/.bun/bin/bun install")); @@ -394,19 +416,23 @@ mod tests { std::fs::write(temp_dir.join("package-lock.json"), "").unwrap(); let preset = NextJs; - let result = preset.dockerfile(DockerfileConfig { - use_buildkit: true, - root_local_path: &temp_dir, - local_path: &temp_dir, - install_command: None, - build_command: None, - output_dir: None, - build_vars: None, - project_slug: "test-project", - }).await; + let result = preset + .dockerfile(DockerfileConfig { + use_buildkit: true, + root_local_path: &temp_dir, + local_path: &temp_dir, + install_command: None, + build_command: None, + output_dir: None, + build_vars: None, + project_slug: "test-project", + }) + .await; // Verify Bun is NOT installed - assert!(!result.content.contains("curl -fsSL https://bun.sh/install | bash")); + assert!(!result + .content + .contains("curl -fsSL https://bun.sh/install | bash")); // Verify npm commands are used assert!(result.content.contains("npm install") || result.content.contains("npm ci")); @@ -427,19 +453,23 @@ mod tests { std::fs::write(subproject_dir.join("package.json"), "{}").unwrap(); let preset = NextJs; - let result = preset.dockerfile(DockerfileConfig { - use_buildkit: true, - root_local_path: &temp_dir, - local_path: &subproject_dir, - install_command: None, - build_command: None, - output_dir: None, - build_vars: None, - project_slug: "test-project", - }).await; + let result = preset + .dockerfile(DockerfileConfig { + use_buildkit: true, + root_local_path: &temp_dir, + local_path: &subproject_dir, + install_command: None, + build_command: None, + output_dir: None, + build_vars: None, + project_slug: "test-project", + }) + .await; // Verify the entire repository is copied for monorepos - assert!(result.content.contains("# Copy entire repository for monorepo build")); + assert!(result + .content + .contains("# Copy entire repository for monorepo build")); assert!(result.content.contains("COPY . .")); // Verify WORKDIR is set to the subdirectory in build stage @@ -447,13 +477,19 @@ mod tests { assert!(result.content.contains("WORKDIR /test_project/apps/web")); // Verify entire project directory is copied in production stage (not selective files) - assert!(result.content.contains("# Copy entire project directory to ensure all runtime files are available")); + assert!(result + .content + .contains("# Copy entire project directory to ensure all runtime files are available")); assert!(result.content.contains("# This includes: node_modules, .next, public, and ANY custom directories (drizzle, mydata, etc.)")); // Verify the copy is from the subdirectory path (apps/web) with nodejs user ownership - assert!(result.content.contains("COPY --from=build --chown=nodejs:nodejs /test_project/apps/web /test_project")); + assert!(result.content.contains( + "COPY --from=build --chown=nodejs:nodejs /test_project/apps/web /test_project" + )); // Verify we do NOT prune devDependencies (TypeScript needed at runtime) - assert!(result.content.contains("# NOTE: We do NOT prune devDependencies for Next.js projects")); + assert!(result + .content + .contains("# NOTE: We do NOT prune devDependencies for Next.js projects")); assert!(!result.content.contains("npm prune --production")); assert!(!result.content.contains("yarn install --production")); @@ -469,16 +505,18 @@ mod tests { std::fs::write(temp_dir.join("package.json"), "{}").unwrap(); let preset = NextJs; - let result = preset.dockerfile(DockerfileConfig { - use_buildkit: true, - root_local_path: &temp_dir, - local_path: &temp_dir, - install_command: None, - build_command: None, - output_dir: None, - build_vars: None, - project_slug: "test-project", - }).await; + let result = preset + .dockerfile(DockerfileConfig { + use_buildkit: true, + root_local_path: &temp_dir, + local_path: &temp_dir, + install_command: None, + build_command: None, + output_dir: None, + build_vars: None, + project_slug: "test-project", + }) + .await; // Verify only one WORKDIR is set (the initial one) - no subdirectory WORKDIR let workdir_count = result.content.matches("WORKDIR /test_project").count(); @@ -498,21 +536,25 @@ mod tests { std::fs::write(temp_dir.join("package-lock.json"), "").unwrap(); let preset = NextJs; - let result = preset.dockerfile(DockerfileConfig { - use_buildkit: true, - root_local_path: &temp_dir, - local_path: &temp_dir, - install_command: None, - build_command: None, - output_dir: None, - build_vars: None, - project_slug: "test-project", - }).await; + let result = preset + .dockerfile(DockerfileConfig { + use_buildkit: true, + root_local_path: &temp_dir, + local_path: &temp_dir, + install_command: None, + build_command: None, + output_dir: None, + build_vars: None, + project_slug: "test-project", + }) + .await; // Verify Alpine is used for runner stage assert!(result.content.contains("FROM node:22-alpine AS runner")); // Verify CMD uses node with explicit path to next start - assert!(result.content.contains(r#"CMD ["node", "/test_project/node_modules/next/dist/bin/next", "start"]"#)); + assert!(result + .content + .contains(r#"CMD ["node", "/test_project/node_modules/next/dist/bin/next", "start"]"#)); // Verify npm is used in build stage assert!(result.content.contains("npm install") || result.content.contains("npm ci")); @@ -527,23 +569,29 @@ mod tests { std::fs::write(temp_dir.join("bun.lock"), "").unwrap(); let preset = NextJs; - let result = preset.dockerfile(DockerfileConfig { - use_buildkit: true, - root_local_path: &temp_dir, - local_path: &temp_dir, - install_command: None, - build_command: None, - output_dir: None, - build_vars: None, - project_slug: "test-project", - }).await; + let result = preset + .dockerfile(DockerfileConfig { + use_buildkit: true, + root_local_path: &temp_dir, + local_path: &temp_dir, + install_command: None, + build_command: None, + output_dir: None, + build_vars: None, + project_slug: "test-project", + }) + .await; // Verify Alpine is used for runner stage assert!(result.content.contains("FROM node:22-alpine AS runner")); // Verify CMD uses node with explicit path to next start - assert!(result.content.contains(r#"CMD ["node", "/test_project/node_modules/next/dist/bin/next", "start"]"#)); + assert!(result + .content + .contains(r#"CMD ["node", "/test_project/node_modules/next/dist/bin/next", "start"]"#)); // Verify bun is installed in build stage - assert!(result.content.contains("curl -fsSL https://bun.sh/install | bash")); + assert!(result + .content + .contains("curl -fsSL https://bun.sh/install | bash")); // Cleanup std::fs::remove_dir_all(&temp_dir).ok(); @@ -556,21 +604,25 @@ mod tests { std::fs::write(temp_dir.join("yarn.lock"), "").unwrap(); let preset = NextJs; - let result = preset.dockerfile(DockerfileConfig { - use_buildkit: true, - root_local_path: &temp_dir, - local_path: &temp_dir, - install_command: None, - build_command: None, - output_dir: None, - build_vars: None, - project_slug: "test-project", - }).await; + let result = preset + .dockerfile(DockerfileConfig { + use_buildkit: true, + root_local_path: &temp_dir, + local_path: &temp_dir, + install_command: None, + build_command: None, + output_dir: None, + build_vars: None, + project_slug: "test-project", + }) + .await; // Verify Alpine is used for runner stage assert!(result.content.contains("FROM node:22-alpine AS runner")); // Verify CMD uses node with explicit path to next start - assert!(result.content.contains(r#"CMD ["node", "/test_project/node_modules/next/dist/bin/next", "start"]"#)); + assert!(result + .content + .contains(r#"CMD ["node", "/test_project/node_modules/next/dist/bin/next", "start"]"#)); // Verify corepack is enabled for yarn in build stage assert!(result.content.contains("corepack enable")); @@ -578,6 +630,37 @@ mod tests { std::fs::remove_dir_all(&temp_dir).ok(); } + #[tokio::test] + async fn test_pnpm_project_respects_package_manager_version() { + let temp_dir = std::env::temp_dir().join("test_nextjs_pnpm_version"); + std::fs::create_dir_all(&temp_dir).unwrap(); + std::fs::write(temp_dir.join("pnpm-lock.yaml"), "lockfileVersion: '9.0'").unwrap(); + std::fs::write( + temp_dir.join("package.json"), + r#"{"packageManager":"pnpm@9.15.0"}"#, + ) + .unwrap(); + + let result = NextJs + .dockerfile(DockerfileConfig { + use_buildkit: true, + root_local_path: &temp_dir, + local_path: &temp_dir, + install_command: None, + build_command: None, + output_dir: None, + build_vars: None, + project_slug: "test-project", + }) + .await; + + assert!(result.content.contains("corepack enable")); + assert!(result.content.contains("pnpm install --frozen-lockfile")); + assert!(!result.content.contains("pnpm@latest")); + + std::fs::remove_dir_all(&temp_dir).ok(); + } + #[tokio::test] async fn test_custom_install_and_build_commands_with_bun() { let temp_dir = std::env::temp_dir().join("test_nextjs_custom_bun"); @@ -585,19 +668,23 @@ mod tests { std::fs::write(temp_dir.join("bun.lock"), "").unwrap(); let preset = NextJs; - let result = preset.dockerfile(DockerfileConfig { - use_buildkit: true, - root_local_path: &temp_dir, - local_path: &temp_dir, - install_command: Some("bun install --frozen-lockfile"), - build_command: Some("bun run build:prod"), - output_dir: None, - build_vars: None, - project_slug: "test-project", - }).await; + let result = preset + .dockerfile(DockerfileConfig { + use_buildkit: true, + root_local_path: &temp_dir, + local_path: &temp_dir, + install_command: Some("bun install --frozen-lockfile"), + build_command: Some("bun run build:prod"), + output_dir: None, + build_vars: None, + project_slug: "test-project", + }) + .await; // Verify custom commands are used with full bun path - assert!(result.content.contains("/root/.bun/bin/bun install --frozen-lockfile")); + assert!(result + .content + .contains("/root/.bun/bin/bun install --frozen-lockfile")); assert!(result.content.contains("/root/.bun/bin/bun run build:prod")); // Cleanup @@ -610,16 +697,18 @@ mod tests { std::fs::create_dir_all(&temp_dir).unwrap(); let preset = NextJs; - let result = preset.dockerfile(DockerfileConfig { - use_buildkit: true, - root_local_path: &temp_dir, - local_path: &temp_dir, - install_command: None, - build_command: None, - output_dir: None, - build_vars: None, - project_slug: "test-project", - }).await; + let result = preset + .dockerfile(DockerfileConfig { + use_buildkit: true, + root_local_path: &temp_dir, + local_path: &temp_dir, + install_command: None, + build_command: None, + output_dir: None, + build_vars: None, + project_slug: "test-project", + }) + .await; // Verify Alpine is used for runner stage assert!( @@ -629,7 +718,9 @@ mod tests { // Security: Creates non-root user nodejs with UID 1001 assert!( - result.content.contains("adduser --system --uid 1001 nodejs"), + result + .content + .contains("adduser --system --uid 1001 nodejs"), "Should create nodejs user with UID 1001" ); @@ -671,7 +762,9 @@ mod tests { // Security: Creates non-root user nodejs with UID 1001 assert!( - result.content.contains("adduser --system --uid 1001 nodejs"), + result + .content + .contains("adduser --system --uid 1001 nodejs"), "Should create nodejs user with UID 1001" ); @@ -706,9 +799,7 @@ mod tests { use std::time::Duration; // Check if Docker is available - let docker_check = Command::new("docker") - .args(["info"]) - .output(); + let docker_check = Command::new("docker").args(["info"]).output(); if docker_check.is_err() || !docker_check.unwrap().status.success() { println!("Docker is not available, skipping test"); @@ -716,10 +807,9 @@ mod tests { } // Get the fixture path - let manifest_dir = std::env::var("CARGO_MANIFEST_DIR") - .expect("CARGO_MANIFEST_DIR not set"); - let fixture_path = std::path::PathBuf::from(&manifest_dir) - .join("tests/fixtures/nextjs-hello-world"); + let manifest_dir = std::env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR not set"); + let fixture_path = + std::path::PathBuf::from(&manifest_dir).join("tests/fixtures/nextjs-hello-world"); if !fixture_path.exists() { panic!("Fixture not found at {:?}", fixture_path); @@ -735,12 +825,19 @@ mod tests { // Copy fixture files to temp directory let copy_result = Command::new("cp") - .args(["-r", fixture_path.to_str().unwrap(), temp_dir.to_str().unwrap()]) + .args([ + "-r", + fixture_path.to_str().unwrap(), + temp_dir.to_str().unwrap(), + ]) .output() .expect("Failed to copy fixture"); if !copy_result.status.success() { - panic!("Failed to copy fixture: {:?}", String::from_utf8_lossy(©_result.stderr)); + panic!( + "Failed to copy fixture: {:?}", + String::from_utf8_lossy(©_result.stderr) + ); } let project_dir = temp_dir.join("nextjs-hello-world"); @@ -750,24 +847,23 @@ mod tests { let _ = std::fs::remove_dir_all(project_dir.join("node_modules")); // Write .dockerignore to prevent node_modules from leaking into build context - std::fs::write( - project_dir.join(".dockerignore"), - "node_modules\n.next\n", - ) - .expect("Failed to write .dockerignore"); + std::fs::write(project_dir.join(".dockerignore"), "node_modules\n.next\n") + .expect("Failed to write .dockerignore"); // Generate Dockerfile using the preset let preset = NextJs; - let dockerfile_result = preset.dockerfile(DockerfileConfig { - use_buildkit: true, - root_local_path: &project_dir, - local_path: &project_dir, - install_command: None, - build_command: None, - output_dir: None, - build_vars: None, - project_slug: "nextjs-test", - }).await; + let dockerfile_result = preset + .dockerfile(DockerfileConfig { + use_buildkit: true, + root_local_path: &project_dir, + local_path: &project_dir, + install_command: None, + build_command: None, + output_dir: None, + build_vars: None, + project_slug: "nextjs-test", + }) + .await; // Write the Dockerfile let dockerfile_path = project_dir.join("Dockerfile"); @@ -784,15 +880,23 @@ mod tests { .args([ "build", "--no-cache", - "-t", &image_name, - "-f", dockerfile_path.to_str().unwrap(), + "-t", + &image_name, + "-f", + dockerfile_path.to_str().unwrap(), project_dir.to_str().unwrap(), ]) .output() .expect("Failed to execute docker build"); - println!("Build stdout:\n{}", String::from_utf8_lossy(&build_result.stdout)); - println!("Build stderr:\n{}", String::from_utf8_lossy(&build_result.stderr)); + println!( + "Build stdout:\n{}", + String::from_utf8_lossy(&build_result.stdout) + ); + println!( + "Build stderr:\n{}", + String::from_utf8_lossy(&build_result.stderr) + ); if !build_result.status.success() { let stderr = String::from_utf8_lossy(&build_result.stderr); @@ -827,8 +931,10 @@ mod tests { .args([ "run", "-d", - "--name", &container_name, - "-p", &format!("{}:3000", host_port), + "--name", + &container_name, + "-p", + &format!("{}:3000", host_port), &image_name, ]) .output() @@ -836,9 +942,15 @@ mod tests { if !run_result.status.success() { // Cleanup - Command::new("docker").args(["rmi", "-f", &image_name]).output().ok(); + Command::new("docker") + .args(["rmi", "-f", &image_name]) + .output() + .ok(); std::fs::remove_dir_all(&temp_dir).ok(); - panic!("Docker run failed: {}", String::from_utf8_lossy(&run_result.stderr)); + panic!( + "Docker run failed: {}", + String::from_utf8_lossy(&run_result.stderr) + ); } // Wait for the container to start and become healthy @@ -860,18 +972,31 @@ mod tests { let logs = String::from_utf8_lossy(&logs_result.stdout); let logs_stderr = String::from_utf8_lossy(&logs_result.stderr); - println!("Attempt {}/{} - Logs: {} {}", attempts, max_attempts, logs, logs_stderr); + println!( + "Attempt {}/{} - Logs: {} {}", + attempts, max_attempts, logs, logs_stderr + ); // Check if Next.js is ready - if logs.contains("Ready") || logs_stderr.contains("Ready") || - logs.contains("started server") || logs_stderr.contains("started server") { + if logs.contains("Ready") + || logs_stderr.contains("Ready") + || logs.contains("started server") + || logs_stderr.contains("started server") + { is_healthy = true; break; } // Also try HTTP request let curl_result = Command::new("curl") - .args(["-s", "-o", "/dev/null", "-w", "%{http_code}", &format!("http://localhost:{}", host_port)]) + .args([ + "-s", + "-o", + "/dev/null", + "-w", + "%{http_code}", + &format!("http://localhost:{}", host_port), + ]) .output(); if let Ok(output) = curl_result { @@ -890,8 +1015,14 @@ mod tests { .output() .expect("Failed to get final logs"); - println!("Final container stdout:\n{}", String::from_utf8_lossy(&final_logs.stdout)); - println!("Final container stderr:\n{}", String::from_utf8_lossy(&final_logs.stderr)); + println!( + "Final container stdout:\n{}", + String::from_utf8_lossy(&final_logs.stdout) + ); + println!( + "Final container stderr:\n{}", + String::from_utf8_lossy(&final_logs.stderr) + ); // Check container status let inspect_result = Command::new("docker") @@ -899,14 +1030,25 @@ mod tests { .output() .expect("Failed to inspect container"); - let container_status = String::from_utf8_lossy(&inspect_result.stdout).trim().to_string(); + let container_status = String::from_utf8_lossy(&inspect_result.stdout) + .trim() + .to_string(); println!("Container status: {}", container_status); // Cleanup: Stop and remove container, remove image println!("Cleaning up..."); - Command::new("docker").args(["stop", &container_name]).output().ok(); - Command::new("docker").args(["rm", "-f", &container_name]).output().ok(); - Command::new("docker").args(["rmi", "-f", &image_name]).output().ok(); + Command::new("docker") + .args(["stop", &container_name]) + .output() + .ok(); + Command::new("docker") + .args(["rm", "-f", &container_name]) + .output() + .ok(); + Command::new("docker") + .args(["rmi", "-f", &image_name]) + .output() + .ok(); std::fs::remove_dir_all(&temp_dir).ok(); // Assert the container was healthy diff --git a/crates/temps-projects/Cargo.toml b/crates/temps-projects/Cargo.toml index 7f444297e..f102b86db 100644 --- a/crates/temps-projects/Cargo.toml +++ b/crates/temps-projects/Cargo.toml @@ -42,3 +42,4 @@ futures-util = { workspace = true } slug = { workspace = true } tempfile = { workspace = true } url = { workspace = true } +zip = { workspace = true } diff --git a/crates/temps-projects/src/handlers/handlers.rs b/crates/temps-projects/src/handlers/handlers.rs index bcca7ceeb..2570429ad 100644 --- a/crates/temps-projects/src/handlers/handlers.rs +++ b/crates/temps-projects/src/handlers/handlers.rs @@ -7,12 +7,13 @@ use utoipa::OpenApi; use super::AppState; use axum::Router; use axum::{ - extract::{Extension, Path, Query, State}, + extract::{Extension, Multipart, Path, Query, State}, http::StatusCode, response::IntoResponse, routing::{delete, get, patch, post, put}, Json, }; +use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::Arc; use temps_auth::RequireAuth; use temps_auth::{ @@ -28,11 +29,16 @@ use super::types::{ UpdateGitSettingsRequest, UpdateProjectSettingsRequest, }; use sea_orm::{ColumnTrait, EntityTrait, QueryFilter}; +use serde::Serialize; +use std::collections::BTreeMap; +use std::io::Read; use temps_core::problemdetails; use temps_core::problemdetails::Problem; use temps_entities::source_type::SourceType; +use tokio::io::AsyncWriteExt; pub fn configure_routes() -> Router> { + use axum::extract::DefaultBodyLimit; let custom_domain_routes = super::custom_domains::configure_routes(); Router::new() @@ -44,6 +50,10 @@ pub fn configure_routes() -> Router> { .route("/projects/{id}", delete(delete_project)) .route("/projects", post(create_project)) .route("/projects", get(get_projects)) + .route( + "/drop/inspect", + post(inspect_drop_archive).layer(DefaultBodyLimit::max(501 * 1024 * 1024)), + ) .route("/projects/statistics", get(get_project_statistics)) // Create project from template .route( @@ -90,6 +100,7 @@ pub fn configure_routes() -> Router> { #[openapi( paths( create_project, + inspect_drop_archive, get_project, update_project, change_project_source, @@ -113,6 +124,8 @@ pub fn configure_routes() -> Router> { components( schemas( CreateProjectRequest, + DropInspectionResponse, + DropPresetCandidate, ChangeProjectSourceRequest, ProjectResponse, PaginatedProjectList, @@ -151,6 +164,335 @@ pub fn configure_routes() -> Router> { )] pub struct ApiDoc; +static DROP_INSPECTIONS_IN_FLIGHT: AtomicUsize = AtomicUsize::new(0); + +/// Upper bound on how many deployable roots a single Drop inspection reports. +/// The response drives a picker, so a 20k-entry list is neither usable nor +/// safe to serialise. +const MAX_DROP_CANDIDATES: usize = 50; + +struct DropInspectionPermit; + +impl DropInspectionPermit { + fn acquire() -> Result { + DROP_INSPECTIONS_IN_FLIGHT + .fetch_update(Ordering::AcqRel, Ordering::Acquire, |current| { + (current < 4).then_some(current + 1) + }) + .map_err(|_| { + problemdetails::new(StatusCode::TOO_MANY_REQUESTS) + .with_title("Too Many Drop Inspections") + .with_detail("At most four Drop archives may be inspected concurrently") + })?; + Ok(Self) + } +} + +impl Drop for DropInspectionPermit { + fn drop(&mut self) { + DROP_INSPECTIONS_IN_FLIGHT.fetch_sub(1, Ordering::AcqRel); + } +} + +#[derive(Debug, Serialize, utoipa::ToSchema)] +#[serde(rename_all = "camelCase")] +pub struct DropPresetCandidate { + pub directory: String, + pub preset: String, + pub label: String, + pub confidence: String, + pub reason: String, + pub is_static: bool, +} + +#[derive(Debug, Serialize, utoipa::ToSchema)] +#[serde(rename_all = "camelCase")] +pub struct DropInspectionResponse { + pub suggested_name: String, + pub candidates: Vec, +} + +#[derive(utoipa::ToSchema)] +pub struct DropArchiveUpload { + #[schema(value_type = String, format = Binary)] + pub file: String, +} + +/// Inspect a source ZIP without creating a project or retaining the upload. +#[utoipa::path( + post, + path = "/drop/inspect", + tag = "Projects", + request_body(content = DropArchiveUpload, content_type = "multipart/form-data"), + responses( + (status = 200, description = "Detected deployable project roots", body = DropInspectionResponse), + (status = 400, description = "Invalid or unsupported archive") + ), + security(("bearer_auth" = [])) +)] +pub async fn inspect_drop_archive( + RequireAuth(auth): RequireAuth, + mut multipart: Multipart, +) -> Result, Problem> { + permission_guard!(auth, ProjectsCreate); + let inspection_permit = DropInspectionPermit::acquire()?; + + const MAX_ARCHIVE_BYTES: u64 = 500 * 1024 * 1024; + let temporary = tempfile::tempdir().map_err(|error| { + problemdetails::new(StatusCode::INTERNAL_SERVER_ERROR) + .with_title("Upload Staging Failed") + .with_detail(error.to_string()) + })?; + let archive_path = temporary.path().join("drop-inspect.zip"); + let mut archive_received = false; + let mut filename = None; + while let Some(field) = multipart.next_field().await.map_err(|error| { + problemdetails::new(StatusCode::BAD_REQUEST) + .with_title("Invalid Upload") + .with_detail(format!("Failed to read multipart upload: {error}")) + })? { + if field.name() == Some("file") { + filename = field.file_name().map(ToString::to_string); + let mut output = tokio::fs::File::create(&archive_path) + .await + .map_err(|error| { + problemdetails::new(StatusCode::INTERNAL_SERVER_ERROR) + .with_title("Upload Staging Failed") + .with_detail(error.to_string()) + })?; + let mut field = field; + let mut size = 0u64; + while let Some(chunk) = field.chunk().await.map_err(|error| { + problemdetails::new(StatusCode::BAD_REQUEST) + .with_title("Invalid Upload") + .with_detail(format!("Failed to read uploaded archive: {error}")) + })? { + size = size.saturating_add(chunk.len() as u64); + if size > MAX_ARCHIVE_BYTES { + return Err(problemdetails::new(StatusCode::PAYLOAD_TOO_LARGE) + .with_title("Archive Too Large") + .with_detail("Drop archive exceeds 500 MiB")); + } + output.write_all(&chunk).await.map_err(|error| { + problemdetails::new(StatusCode::INTERNAL_SERVER_ERROR) + .with_title("Upload Staging Failed") + .with_detail(error.to_string()) + })?; + } + output.flush().await.map_err(|error| { + problemdetails::new(StatusCode::INTERNAL_SERVER_ERROR) + .with_title("Upload Staging Failed") + .with_detail(error.to_string()) + })?; + archive_received = true; + break; + } + } + + if !archive_received { + return Err(problemdetails::new(StatusCode::BAD_REQUEST) + .with_title("Missing Archive") + .with_detail("Expected a ZIP archive in multipart field 'file'")); + } + // Detection is CPU-bound and O(roots x files); it must run inside the same + // `spawn_blocking` as the ZIP walk so it stays off the async runtime AND + // stays covered by `inspection_permit`, which is released when this closure + // returns. + let candidates = tokio::task::spawn_blocking(move || { + let _inspection_permit = inspection_permit; + let manifests = inspect_zip_manifests(&archive_path)?; + let mut candidates = temps_presets::detect_project_candidates(&manifests) + .into_iter() + .map(|candidate| { + let preset = candidate.catalog_slug().to_string(); + DropPresetCandidate { + directory: candidate.path, + preset, + label: candidate.preset.display_name().to_string(), + confidence: candidate.confidence.to_string(), + reason: candidate.reason, + is_static: candidate.preset == temps_entities::preset::Preset::Static, + } + }) + .collect::>(); + // The response is rendered as a picker; an unbounded list is neither + // useful to a human nor safe to serialise. + candidates.truncate(MAX_DROP_CANDIDATES); + Ok::<_, Problem>(candidates) + }) + .await + .map_err(|error| { + problemdetails::new(StatusCode::INTERNAL_SERVER_ERROR) + .with_title("Archive Inspection Failed") + .with_detail(error.to_string()) + })??; + + if candidates.is_empty() { + return Err(problemdetails::new(StatusCode::BAD_REQUEST) + .with_title("No Deployable Project Found") + .with_detail( + "The archive does not contain a supported project manifest or index.html", + )); + } + + let suggested_name = filename + .as_deref() + .and_then(|name| name.strip_suffix(".zip")) + .filter(|name| !name.trim().is_empty()) + .unwrap_or("drop-project") + .to_string(); + + Ok(Json(DropInspectionResponse { + suggested_name, + candidates, + })) +} + +fn inspect_zip_manifests(path: &std::path::Path) -> Result, Problem> { + const MAX_FILES: usize = 20_000; + const MAX_MANIFEST_BYTES: u64 = 1024 * 1024; + /// Aggregate budget across every manifest we buffer. `MAX_FILES` x + /// `MAX_MANIFEST_BYTES` is 20 GiB, and manifests compress ~1000:1, so a + /// ~15 MB upload could otherwise pin gigabytes of `String` per request and + /// OOM the whole binary on the 4 GB reference box. + const MAX_TOTAL_MANIFEST_BYTES: u64 = 16 * 1024 * 1024; + /// Independent cap on how many manifests we are willing to buffer at all. + const MAX_MANIFESTS: usize = 512; + /// Aggregate budget for the entry *paths* we retain as map keys. The ZIP + /// central directory may legitimately be tens of MiB on its own. + const MAX_TOTAL_PATH_BYTES: usize = 4 * 1024 * 1024; + + let mut file = std::fs::File::open(path).map_err(|error| { + problemdetails::new(StatusCode::BAD_REQUEST) + .with_title("Invalid ZIP Archive") + .with_detail(format!("Could not read ZIP archive: {error}")) + })?; + temps_core::archive_security::validate_zip_metadata(&mut file).map_err(|error| { + problemdetails::new(StatusCode::BAD_REQUEST) + .with_title("Invalid ZIP Archive") + .with_detail(error.to_string()) + })?; + let mut archive = zip::ZipArchive::new(file).map_err(|error| { + problemdetails::new(StatusCode::BAD_REQUEST) + .with_title("Invalid ZIP Archive") + .with_detail(format!("Could not open ZIP archive: {error}")) + })?; + if archive.len() > MAX_FILES { + return Err(problemdetails::new(StatusCode::PAYLOAD_TOO_LARGE) + .with_title("Archive Has Too Many Files") + .with_detail(format!("Archive contains more than {MAX_FILES} entries"))); + } + + let mut manifests = BTreeMap::new(); + let mut total_manifest_bytes: u64 = 0; + let mut manifest_count: usize = 0; + let mut total_path_bytes: usize = 0; + for index in 0..archive.len() { + let entry = archive.by_index(index).map_err(|error| { + problemdetails::new(StatusCode::BAD_REQUEST) + .with_title("Invalid ZIP Entry") + .with_detail(format!("Could not inspect ZIP entry {index}: {error}")) + })?; + if entry.is_dir() { + continue; + } + let path = entry.enclosed_name().ok_or_else(|| { + problemdetails::new(StatusCode::BAD_REQUEST) + .with_title("Unsafe ZIP Entry") + .with_detail(format!( + "Archive entry '{}' escapes the project root", + entry.name() + )) + })?; + if path.components().any(|component| { + let std::path::Component::Normal(value) = component else { + return false; + }; + let name = value.to_string_lossy(); + name == ".git" + || name == "node_modules" + || name == ".env" + || name.starts_with(".env.") + || name.ends_with(".pem") + || name.ends_with(".key") + || name == "credentials.json" + }) { + return Err(problemdetails::new(StatusCode::BAD_REQUEST) + .with_title("Sensitive ZIP Entry") + .with_detail(format!( + "Archive entry '{}' must be excluded from Drop uploads", + entry.name() + ))); + } + if entry + .unix_mode() + .is_some_and(|mode| mode & 0o170000 == 0o120000) + { + return Err(problemdetails::new(StatusCode::BAD_REQUEST) + .with_title("Unsupported ZIP Entry") + .with_detail(format!("Symbolic link '{}' is not allowed", entry.name()))); + } + let normalized = path.to_string_lossy().replace('\\', "/"); + let basename = normalized.rsplit('/').next().unwrap_or(&normalized); + let should_read = matches!( + basename, + "package.json" + | "requirements.txt" + | "pyproject.toml" + | "Cargo.toml" + | "go.mod" + | "pom.xml" + | "build.gradle" + ) || basename.ends_with(".csproj"); + total_path_bytes = total_path_bytes.saturating_add(normalized.len()); + if total_path_bytes > MAX_TOTAL_PATH_BYTES { + return Err(problemdetails::new(StatusCode::PAYLOAD_TOO_LARGE) + .with_title("Archive Manifest Too Large") + .with_detail(format!( + "Combined entry paths exceed {MAX_TOTAL_PATH_BYTES} bytes" + ))); + } + let mut contents = String::new(); + if should_read { + if entry.size() > MAX_MANIFEST_BYTES { + return Err(problemdetails::new(StatusCode::PAYLOAD_TOO_LARGE) + .with_title("Manifest Is Too Large") + .with_detail(format!("Manifest '{normalized}' exceeds 1 MiB"))); + } + manifest_count += 1; + if manifest_count > MAX_MANIFESTS { + return Err(problemdetails::new(StatusCode::PAYLOAD_TOO_LARGE) + .with_title("Too Many Manifests") + .with_detail(format!( + "Archive contains more than {MAX_MANIFESTS} project manifests" + ))); + } + // Budget against bytes *actually read*, not the declared header + // size, so a lying local header cannot get us to over-allocate. + let remaining = MAX_TOTAL_MANIFEST_BYTES.saturating_sub(total_manifest_bytes); + let read = entry + .take(remaining.min(MAX_MANIFEST_BYTES) + 1) + .read_to_string(&mut contents) + .map_err(|error| { + problemdetails::new(StatusCode::BAD_REQUEST) + .with_title("Invalid Manifest") + .with_detail(format!("Could not read '{normalized}': {error}")) + })? as u64; + total_manifest_bytes = total_manifest_bytes.saturating_add(read); + if total_manifest_bytes > MAX_TOTAL_MANIFEST_BYTES { + return Err(problemdetails::new(StatusCode::PAYLOAD_TOO_LARGE) + .with_title("Archive Manifests Too Large") + .with_detail(format!( + "Combined project manifests exceed {} MiB", + MAX_TOTAL_MANIFEST_BYTES / (1024 * 1024) + ))); + } + } + manifests.insert(normalized, contents); + } + Ok(manifests) +} + /// Create a new project #[utoipa::path( post, @@ -626,6 +968,19 @@ pub async fn delete_project( .with_detail(error.to_string()) })?; + state + .project_archive_cleaner + .cleanup_project_archives(id) + .await + .map_err(|error| { + error!(project_id = id, %error, "Failed to clean up project archives"); + problemdetails::new(StatusCode::INTERNAL_SERVER_ERROR) + .with_title("Project Archive Cleanup Failed") + .with_detail(format!( + "Failed to remove uploaded archives for project {id}: {error}" + )) + })?; + state .project_service .delete_project(id, &project.name) diff --git a/crates/temps-projects/src/handlers/types.rs b/crates/temps-projects/src/handlers/types.rs index 6b85fe650..9add861d4 100644 --- a/crates/temps-projects/src/handlers/types.rs +++ b/crates/temps-projects/src/handlers/types.rs @@ -22,6 +22,7 @@ pub struct AppState { pub custom_domain_service: Arc, pub audit_service: Arc, pub template_service: Arc, + pub project_archive_cleaner: Arc, pub telemetry: Arc, /// Optional checker enforcing team-based project access for human sessions. /// @@ -913,6 +914,12 @@ impl From for Problem { .with_detail(msg) } + ProjectError::DeploymentCleanupFailed { .. } => { + problemdetails::new(StatusCode::INTERNAL_SERVER_ERROR) + .with_title("Project Runtime Cleanup Failed") + .with_detail(error.to_string()) + } + ProjectError::Other(msg) => problemdetails::new(StatusCode::INTERNAL_SERVER_ERROR) .with_title("Internal Server Error") .with_detail(msg), diff --git a/crates/temps-projects/src/plugin.rs b/crates/temps-projects/src/plugin.rs index 60c11e6c2..372239dbd 100644 --- a/crates/temps-projects/src/plugin.rs +++ b/crates/temps-projects/src/plugin.rs @@ -77,6 +77,8 @@ impl TempsPlugin for ProjectsPlugin { let custom_domain_service = context.require_service::(); let audit_service = context.require_service::(); let template_service = context.require_service::(); + let project_archive_cleaner = + context.require_service::(); let telemetry = context .get_service::() .unwrap_or_else(|| Arc::new(temps_core::telemetry::NoopTelemetryReporter)); @@ -93,6 +95,7 @@ impl TempsPlugin for ProjectsPlugin { custom_domain_service, audit_service, template_service, + project_archive_cleaner, telemetry, project_access_checker, }); diff --git a/crates/temps-projects/src/services/project.rs b/crates/temps-projects/src/services/project.rs index 1ee192a2b..67a0e7c1d 100644 --- a/crates/temps-projects/src/services/project.rs +++ b/crates/temps-projects/src/services/project.rs @@ -183,6 +183,35 @@ fn validate_preset_config( Ok(config) } +fn normalize_project_directory(directory: &str) -> Result { + let normalized = directory + .trim() + .replace('\\', "/") + .trim_start_matches('/') + .to_string(); + if normalized.is_empty() || normalized == "." { + return Ok(".".to_string()); + } + let path = std::path::Path::new(&normalized); + let has_windows_drive_prefix = normalized.as_bytes().get(1) == Some(&b':'); + if has_windows_drive_prefix + || path.is_absolute() + || path.components().any(|component| { + matches!( + component, + std::path::Component::ParentDir + | std::path::Component::RootDir + | std::path::Component::Prefix(_) + ) + }) + { + return Err(ProjectError::InvalidInput(format!( + "Project directory '{directory}' must be a relative path inside the source root" + ))); + } + Ok(normalized.trim_start_matches("./").to_string()) +} + /// Resolve an explicit catalog selection for create/update. /// /// Existing config is retained when it belongs to the same canonical preset. @@ -298,20 +327,7 @@ impl ProjectService { } } - // Normalize directory to ensure it's a relative path - let normalized_directory = if request.directory.starts_with('/') { - // Remove leading slash to make it relative - request.directory.trim_start_matches('/').to_string() - } else { - request.directory.clone() - }; - - // If directory is empty after normalization, use current directory marker - let normalized_directory = if normalized_directory.is_empty() { - ".".to_string() - } else { - normalized_directory - }; + let normalized_directory = normalize_project_directory(&request.directory)?; let project_slug = self.generate_unique_project_slug(&request.name).await?; let resolved = resolve_preset_selection( @@ -836,20 +852,7 @@ impl ProjectService { project_id )))?; - // Normalize directory to ensure it's a relative path - let normalized_directory = if request.directory.starts_with('/') { - // Remove leading slash to make it relative - request.directory.trim_start_matches('/').to_string() - } else { - request.directory.clone() - }; - - // If directory is empty after normalization, use current directory marker - let normalized_directory = if normalized_directory.is_empty() { - ".".to_string() - } else { - normalized_directory - }; + let normalized_directory = normalize_project_directory(&request.directory)?; let resolved = resolve_preset_selection( request.preset.as_str(), @@ -4761,4 +4764,25 @@ mod tests { "caller_user_id with no connection_id must not be rejected by the ownership guard" ); } + + #[test] + fn project_directory_must_remain_inside_source_root() { + assert_eq!(normalize_project_directory("").unwrap(), "."); + assert_eq!( + normalize_project_directory("./apps/web").unwrap(), + "apps/web" + ); + assert!(matches!( + normalize_project_directory("../secrets"), + Err(ProjectError::InvalidInput(_)) + )); + assert_eq!( + normalize_project_directory("/apps/web").unwrap(), + "apps/web" + ); + assert!(matches!( + normalize_project_directory("apps/../../etc"), + Err(ProjectError::InvalidInput(_)) + )); + } } diff --git a/crates/temps-projects/src/services/types.rs b/crates/temps-projects/src/services/types.rs index c0905aa42..d2a6c2d4c 100644 --- a/crates/temps-projects/src/services/types.rs +++ b/crates/temps-projects/src/services/types.rs @@ -183,6 +183,9 @@ pub enum ProjectError { #[error("Deployment error: {0}")] DeploymentError(String), + #[error("Failed to remove deployment containers for project {project_id}: {reason}")] + DeploymentCleanupFailed { project_id: i32, reason: String }, + #[error("Other error: {0}")] Other(String), diff --git a/scripts/test-zero-config-compat.sh b/scripts/test-zero-config-compat.sh new file mode 100755 index 000000000..76031b878 --- /dev/null +++ b/scripts/test-zero-config-compat.sh @@ -0,0 +1,71 @@ +#!/usr/bin/env bash +set -euo pipefail + +SCRIPT_DIR=$(cd -- "$(dirname -- "$0")" && pwd) +TEST_DIR=$(mktemp -d "${TMPDIR:-/tmp}/temps-zero-config-test.XXXXXX") +trap 'rm -rf -- "$TEST_DIR"' EXIT +mkdir -p "$TEST_DIR/bin" + +export TEMPS_COMPAT_TEST_LOG="$TEST_DIR/calls.log" + +cat >"$TEST_DIR/bin/curl" <<'EOF' +#!/usr/bin/env bash +set -euo pipefail +method=GET +output= +url= +while (($#)); do + case "$1" in + --request) method=$2; shift 2 ;; + --output) output=$2; shift 2 ;; + --write-out|--header|--data|--retry|--retry-delay) shift 2 ;; + --silent|--show-error|--insecure|--fail|--retry-all-errors) shift ;; + *) url=$1; shift ;; + esac +done +printf '%s %s\n' "$method" "$url" >>"$TEMPS_COMPAT_TEST_LOG" +case "$method $url" in + "POST "*/projects) + printf '%s\n' '{"id":42,"slug":"compat-nextjs-app-playground"}' >"$output" + ;; + "GET "*/projects/42/deployments*) + printf '%s\n' '{"deployments":[{"status":"deployed","url":""}]}' >"$output" + ;; + "DELETE "*/projects/42) + printf '%s\n' '{}' >"$output" + ;; +esac +[[ -z $output ]] || printf '200' +EOF + +cat >"$TEST_DIR/bin/docker" <<'EOF' +#!/usr/bin/env bash +set -euo pipefail +printf 'docker %s\n' "$*" >>"$TEMPS_COMPAT_TEST_LOG" +if [[ $1 == image && $2 == ls && $* == *"reference=temps-"* ]]; then + printf '%s\n' compat-image-id +fi +EOF + +chmod +x "$TEST_DIR/bin/curl" "$TEST_DIR/bin/docker" + +PATH="$TEST_DIR/bin:$PATH" \ + TEMPS_API_TOKEN=test-token \ + TEMPS_COMPAT_POLL_INTERVAL=0 \ + "$SCRIPT_DIR/zero-config-compat.sh" nextjs-app-playground >/dev/null + +delete_line=$(grep -n 'DELETE .*/projects/42' "$TEMPS_COMPAT_TEST_LOG" | cut -d: -f1) +container_check_line=$(grep -n 'docker container ls.*sh.temps.project_id=42' "$TEMPS_COMPAT_TEST_LOG" | cut -d: -f1) +image_remove_line=$(grep -n 'docker image rm compat-image-id' "$TEMPS_COMPAT_TEST_LOG" | cut -d: -f1) + +if [[ -z $delete_line || -z $container_check_line || -z $image_remove_line ]]; then + echo "Expected delete, container verification, and image cleanup calls" >&2 + exit 1 +fi + +if (( delete_line >= container_check_line || container_check_line >= image_remove_line )); then + echo "Cleanup calls happened in the wrong order" >&2 + exit 1 +fi + +echo "zero-config compatibility harness test passed" diff --git a/scripts/zero-config-compat.json b/scripts/zero-config-compat.json new file mode 100644 index 000000000..ec7d3cfc2 --- /dev/null +++ b/scripts/zero-config-compat.json @@ -0,0 +1,74 @@ +[ + { + "name": "nextjs-app-playground", + "repo_owner": "vercel", + "repo_name": "app-playground", + "git_url": "https://github.com/vercel/app-playground.git", + "branch": "main", + "directory": ".", + "preset": "nextjs" + }, + { + "name": "nextjs-tailwind-blog", + "repo_owner": "timlrx", + "repo_name": "tailwind-nextjs-starter-blog", + "git_url": "https://github.com/timlrx/tailwind-nextjs-starter-blog.git", + "branch": "main", + "directory": ".", + "preset": "nextjs" + }, + { + "name": "nextjs-boilerplate", + "repo_owner": "ixartz", + "repo_name": "Next-js-Boilerplate", + "git_url": "https://github.com/ixartz/Next-js-Boilerplate.git", + "branch": "main", + "directory": ".", + "preset": "nextjs" + }, + { + "name": "nextjs-enterprise", + "repo_owner": "Blazity", + "repo_name": "next-enterprise", + "git_url": "https://github.com/Blazity/next-enterprise.git", + "branch": "main", + "directory": ".", + "preset": "nextjs" + }, + { + "name": "node-express", + "repo_owner": "IBM", + "repo_name": "nodejs-express-app", + "git_url": "https://github.com/IBM/nodejs-express-app.git", + "branch": "master", + "directory": ".", + "preset": "nodejs" + }, + { + "name": "node-fastify", + "repo_owner": "fastify", + "repo_name": "example", + "git_url": "https://github.com/fastify/example.git", + "branch": "main", + "directory": "typescript-decorators", + "preset": "nodejs" + }, + { + "name": "node-nestjs", + "repo_owner": "nestjs", + "repo_name": "typescript-starter", + "git_url": "https://github.com/nestjs/typescript-starter.git", + "branch": "master", + "directory": ".", + "preset": "nodejs" + }, + { + "name": "vite-react", + "repo_owner": "SafdarJamal", + "repo_name": "vite-template-react", + "git_url": "https://github.com/SafdarJamal/vite-template-react.git", + "branch": "main", + "directory": ".", + "preset": "vite" + } +] diff --git a/scripts/zero-config-compat.sh b/scripts/zero-config-compat.sh new file mode 100755 index 000000000..7cf43befd --- /dev/null +++ b/scripts/zero-config-compat.sh @@ -0,0 +1,227 @@ +#!/usr/bin/env bash +set -uo pipefail + +SCRIPT_DIR=$(cd -- "$(dirname -- "$0")" && pwd) +MANIFEST=${TEMPS_COMPAT_MANIFEST:-"$SCRIPT_DIR/zero-config-compat.json"} +API_URL=${TEMPS_API_URL:-http://localhost:8130/api} +DEPLOY_TIMEOUT=${TEMPS_COMPAT_DEPLOY_TIMEOUT:-1200} +POLL_INTERVAL=${TEMPS_COMPAT_POLL_INTERVAL:-5} +FILTER=${1:-} + +for command_name in curl docker jq; do + if ! command -v "$command_name" >/dev/null 2>&1; then + echo "Missing required command: $command_name" >&2 + exit 2 + fi +done + +if [[ -z ${TEMPS_API_TOKEN:-} ]]; then + echo "TEMPS_API_TOKEN is required" >&2 + exit 2 +fi + +if ! jq -e 'type == "array" and all(.[]; .name and .repo_owner and .repo_name and .git_url and .branch and .directory and .preset)' "$MANIFEST" >/dev/null; then + echo "Invalid compatibility manifest: $MANIFEST" >&2 + exit 2 +fi + +WORK_DIR=$(mktemp -d "${TMPDIR:-/tmp}/temps-zero-config.XXXXXX") +CURRENT_PROJECT_ID= +CURRENT_PROJECT_SLUG= +CURRENT_CASE= +CURRENT_CONTAINER_BASELINE= +cleanup_errors=0 + +api_request() { + local method=$1 + local path=$2 + local body=${3:-} + local output=$4 + local status + local args=(--silent --show-error --output "$output" --write-out '%{http_code}' --request "$method" + --header "Authorization: Bearer $TEMPS_API_TOKEN" --header 'Accept: application/json') + + if [[ -n $body ]]; then + args+=(--header 'Content-Type: application/json' --data "$body") + fi + + status=$(curl "${args[@]}" "$API_URL$path") || return 1 + if [[ $status -lt 200 || $status -ge 300 ]]; then + echo "Temps API $method $path returned HTTP $status" >&2 + jq . "$output" 2>/dev/null || sed -n '1,20p' "$output" >&2 + return 1 + fi +} + +project_container_ids() { + docker container ls --all --quiet --filter "label=sh.temps.project_id=$1" +} + +new_project_container_ids() { + local current="$WORK_DIR/current-containers" + project_container_ids "$CURRENT_PROJECT_ID" | sort -u >"$current" || return 1 + comm -13 "$CURRENT_CONTAINER_BASELINE" "$current" +} + +remove_project_images() { + local slug=$1 + local image_id + local image_list="$WORK_DIR/images" + local reference + [[ -n $slug ]] || return 0 + for reference in "temps-$slug:*" "$slug-*:*"; do + docker image ls --quiet --filter "reference=$reference" >"$image_list" || return 1 + while IFS= read -r image_id; do + [[ -z $image_id ]] || docker image rm "$image_id" >/dev/null || return 1 + done <"$image_list" + done +} + +print_deployment_failure() { + local deployment_id=$1 + local jobs_response="$WORK_DIR/jobs.json" + if api_request GET "/projects/$CURRENT_PROJECT_ID/deployments/$deployment_id/jobs" '' "$jobs_response"; then + jq -r '.jobs[] | select(.status == "failure") | "[" + .name + "] " + (.error_message // "failed without an error message")' "$jobs_response" >&2 + fi +} + +cleanup_current_project() { + local response="$WORK_DIR/delete.json" + local deadline + local remaining + local failed=0 + + [[ -n $CURRENT_PROJECT_ID ]] || return 0 + echo "[$CURRENT_CASE] deleting project $CURRENT_PROJECT_ID" + if ! api_request DELETE "/projects/$CURRENT_PROJECT_ID" '' "$response"; then + failed=1 + else + deadline=$((SECONDS + 60)) + while :; do + remaining=$(new_project_container_ids) || { + failed=1 + break + } + [[ -z $remaining ]] && break + if (( SECONDS >= deadline )); then + echo "[$CURRENT_CASE] containers remain after project deletion: $remaining" >&2 + failed=1 + break + fi + sleep 1 + done + fi + + if ! remove_project_images "$CURRENT_PROJECT_SLUG"; then + echo "[$CURRENT_CASE] failed to remove project images" >&2 + failed=1 + fi + + CURRENT_PROJECT_ID= + CURRENT_PROJECT_SLUG= + CURRENT_CONTAINER_BASELINE= + (( failed == 0 )) || cleanup_errors=$((cleanup_errors + 1)) + return "$failed" +} + +on_exit() { + cleanup_current_project || true + rm -rf -- "$WORK_DIR" +} +trap on_exit EXIT +trap 'exit 130' INT +trap 'exit 143' TERM + +run_case() { + local case_json=$1 + local create_response="$WORK_DIR/create.json" + local deployments_response="$WORK_DIR/deployments.json" + local create_body + local deadline + local status + local deployment_url + + CURRENT_CASE=$(jq -r .name <<<"$case_json") + CURRENT_CONTAINER_BASELINE="$WORK_DIR/baseline-containers" + docker container ls --all --quiet | sort -u >"$CURRENT_CONTAINER_BASELINE" || return 1 + create_body=$(jq -n --argjson case "$case_json" '{ + name: ("compat-" + $case.name), + repo_name: $case.repo_name, + repo_owner: $case.repo_owner, + directory: $case.directory, + main_branch: $case.branch, + preset: $case.preset, + preset_config: null, + output_dir: null, + build_command: null, + install_command: null, + environment_variables: null, + automatic_deploy: false, + project_type: "web", + is_web_app: true, + performance_metrics_enabled: false, + storage_service_ids: [], + use_default_wildcard: true, + custom_domain: null, + is_public_repo: true, + git_url: $case.git_url, + git_provider_connection_id: null, + is_on_demand: false, + exposed_port: null, + source_type: "git" + }') + + echo "[$CURRENT_CASE] creating project" + api_request POST /projects "$create_body" "$create_response" || return 1 + CURRENT_PROJECT_ID=$(jq -er .id "$create_response") || return 1 + CURRENT_PROJECT_SLUG=$(jq -er .slug "$create_response") || return 1 + + deadline=$((SECONDS + DEPLOY_TIMEOUT)) + while :; do + if ! api_request GET "/projects/$CURRENT_PROJECT_ID/deployments?page=1&per_page=1" '' "$deployments_response"; then + return 1 + fi + status=$(jq -r '.deployments[0].status // "waiting"' "$deployments_response") + case "$status" in + deployed|completed) + deployment_url=$(jq -r '.deployments[0].url // empty' "$deployments_response") + if [[ -n $deployment_url ]]; then + curl --insecure --fail --silent --show-error --retry 6 --retry-all-errors --retry-delay 2 "$deployment_url" >/dev/null || return 1 + fi + echo "[$CURRENT_CASE] deployed successfully" + return 0 + ;; + failed|cancelled|canceled|stopped) + echo "[$CURRENT_CASE] deployment ended with status: $status" >&2 + deployment_id=$(jq -r '.deployments[0].id' "$deployments_response") + print_deployment_failure "$deployment_id" || true + return 1 + ;; + esac + if (( SECONDS >= deadline )); then + echo "[$CURRENT_CASE] deployment timed out in status: $status" >&2 + return 1 + fi + sleep "$POLL_INTERVAL" + done +} + +selected_cases=$(jq -c --arg filter "$FILTER" '.[] | select($filter == "" or (.name | contains($filter)))' "$MANIFEST") +if [[ -z $selected_cases ]]; then + echo "No compatibility cases matched: $FILTER" >&2 + exit 2 +fi + +passed=0 +failed=0 +while IFS= read -r case_json; do + if run_case "$case_json"; then + passed=$((passed + 1)) + else + failed=$((failed + 1)) + fi + cleanup_current_project || true +done <<<"$selected_cases" + +echo "Compatibility results: $passed passed, $failed deployment failures, $cleanup_errors cleanup failures" +(( failed == 0 && cleanup_errors == 0 )) diff --git a/web/src/App.tsx b/web/src/App.tsx index 8e456d843..e9bd48ca4 100644 --- a/web/src/App.tsx +++ b/web/src/App.tsx @@ -51,6 +51,9 @@ const Setup = lazy(() => const Projects = lazy(() => import('./pages/Projects').then((m) => ({ default: m.Projects })) ) +const Drop = lazy(() => + import('./pages/Drop').then((m) => ({ default: m.Drop })) +) const Alarms = lazy(() => import('./pages/Alarms').then((m) => ({ default: m.Alarms })) ) @@ -481,6 +484,7 @@ const FullAppRoutes = () => { } /> } /> } /> + } /> } /> } /> } /> diff --git a/web/src/api/client/@tanstack/react-query.gen.ts b/web/src/api/client/@tanstack/react-query.gen.ts index 12154e96f..487105279 100644 --- a/web/src/api/client/@tanstack/react-query.gen.ts +++ b/web/src/api/client/@tanstack/react-query.gen.ts @@ -3,8 +3,8 @@ import { type DefaultError, type InfiniteData, infiniteQueryOptions, queryOptions, type UseMutationOptions } from '@tanstack/react-query'; import { client } from '../client.gen'; -import { acknowledgeAlarm, activateAiProvider, activateApiKey, activateConnection, activateProvider, addClusterMember, addContext, addEnvironmentDomain, addEvents, addManagedDomain, addSessionReplayEvents, addTeamMember, adminDrainNode, adminDrainStatus, adminGetNode, adminListNodeContainers, adminListNodes, adminRemoveNode, adminUndrainNode, applyHostnameMode, archiveConversation, archiveFlag, assignRole, attachScheduleServices, blobCopy, blobDelete, blobDisable, blobDownload, blobEnable, blobList, blobPut, blobStatus, blobUpdate, cancel, cancelBackup, cancelDeployment, cancelDomainOrder, cancelPgUpgrade, cancelRun, cancelScheduleRun, changePasswordSelf, changeProjectSource, chatCompletions, checkAnalyticsHasEvents, checkCommitExists, checkDomainStatus, checkExplorerSupport, checkIpBlocked, checkProviderDeletionSafety, chunkUploadOptions, cleanupExpiredBackups, clearPreviewPassword, cliDeviceApprove, cliDeviceDeny, cliDeviceLookup, cliDevicePoll, cliDeviceStart, cliLogout, cmd, cmdKill, cmdLogs, confirmPendingAction, containerMetricsGetHistory, createAgent, createAlert, createAlertRule, createApiKey, createBackupSchedule, createBitbucketProvider, createCloudflareProvider, createConversation, createCustomDomain, createDashboard, createDeploymentToken, createDnsProvider, createDomain, createDsn, createEmailDomain, createEmailProvider, createEnvironment, createEnvironmentVariable, createFlag, createFunnel, createGenericProvider, createGiteaPatProvider, createGithubPatProvider, createGitlabOauthProvider, createGitlabPatProvider, createGitProvider, createGlobalMcp, createGlobalSkill, createIncident, createIpAccessControl, createMcp, createMonitor, createNotificationEmailProvider, createNotificationProvider, createOidcProvider, createOidcRoleMapping, createOrRecreateOrder, createPlan, createPr, createProject, createProjectFromTemplate, createProjectRelease, createProjectSecret, createProviderKey, createRelease, createRoute, createS3Source, createSandbox, createService, createSkill, createSlackProvider, createTeam, createUser, createWebhook, createWebhookProvider, deactivateApiKey, deactivateConnection, deactivateProvider, deleteAgent, deleteAlert, deleteAlertRule, deleteApiKey, deleteBackup, deleteBackupSchedule, deleteConnection, deleteCustomDomain, deleteDashboard, deleteDeploymentToken, deleteDnsProvider, deleteDomain, deleteEmailDomain, deleteEmailProvider, deleteEnvironment, deleteEnvironmentDomain, deleteEnvironmentVariable, deleteExternalImage, deleteFunnel, deleteGitProvider, deleteGlobalMcp, deleteGlobalSkill, deleteIpAccessControl, deleteMcp, deleteMonitor, deleteNotificationProvider, deleteOidcProvider, deleteOidcRoleMapping, deletePreferences, deleteProject, deleteProjectSecret, deleteProviderKey, deleteProviderSafely, deleteReleaseSourceFiles, deleteReleaseSourceMaps, deleteRoute, deleteS3Source, deleteScan, deleteSecret, deleteService, deleteSessionReplay, deleteSkill, deleteSourceMap, deleteStaticBundle, deleteTeam, deleteUser, deleteWebhook, deployFromImage, deployFromImageUpload, deployFromStatic, deploymentMetricsGetLatest, deploymentMetricsGetRange, deploymentMetricsToggle, destroySandbox, detachScheduleService, detectPublicPresets, disableBackupSchedule, disableMfa, discoverWorkloads, domain, downloadGlobalSkillArchive, downloadObject, downloadSkillArchive, emailStatus, embeddings, enableBackupSchedule, enrichVisitor, exec, execDetached, executeDeploymentOperation, executeImport, extendTimeout, externalServiceEnablePgStatStatements, externalServiceMetricsByDatabase, externalServiceMetricsCreateAlertRule, externalServiceMetricsDeleteAlertRule, externalServiceMetricsGetAlertRules, externalServiceMetricsGetLatest, externalServiceMetricsGetRange, externalServiceMetricsStatus, externalServiceMetricsToggle, externalServiceMetricsUpdateAlertRule, externalServiceResetPgStatStatements, finalizeOrder, finalizeProjectRelease, findConversation, generateJoinToken, generatePresetDockerfile, getAccessInfo, getActiveVisitors, getActivityGraph, getAdminGate, getAgent, getAggregatedBuckets, getAiAgentBreakdown, getAiAgentPages, getAiAgentTimeline, getAiPageBreakdown, getAiStatusBreakdown, getAlert, getAlertRule, getAllRepositoriesByName, getAnalyticsActiveVisitors, getAnalyticsEventsCount, getAnalyticsSessionEvents, getAnalyticsVisitorSessions, getApiKey, getApiKeyPermissions, getAuditLog, getBackup, getBackupSchedule, getBranchesByRepositoryId, getBucketedIncidents, getBucketedStatus, getChallengeToken, getChatReadiness, getCliStatus, getClusterHealth, getClusterMember, getCmd, getContainerDetail, getContainerEnvironmentVariable, getContainerInfo, getContainerLogs, getContainerLogsById, getContainerMetrics, getConversation, getConversationDetail, getConversations, getCronById, getCronExecutions, getCrossProjectTraceSiblings, getCurrentMonitorStatus, getCurrentUser, getCustomDomain, getDashboard, getDashboardProjectsAnalytics, getDelivery, getDeployment, getDeploymentContainerLogContent, getDeploymentJobLogs, getDeploymentJobs, getDeploymentOperations, getDeploymentOperationStatus, getDeploymentToken, getDiskStatus, getDnsChanges, getDnsProvider, getDomain, getDomainByHost, getDomainById, getDomainByName, getDomainDnsRecords, getDomainOrder, getEmail, getEmailEvents, getEmailLinks, getEmailProvider, getEmailStats, getEmailTracking, getEmailTrackingStatus, getEntityInfo, getEnvironment, getEnvironmentCrons, getEnvironmentDomains, getEnvironments, getEnvironmentVariables, getEnvironmentVariableValue, getErrorDashboardStats, getErrorEvent, getErrorGroup, getErrorStats, getErrorTimeSeries, getEventDetail, getEventEntries, getEventsCount, getEventsTimeline, getEventTypeBreakdown, getEventVisitors, getExternalImage, getFile, getFlag, getFlagSnapshot, getFunnelMetrics, getGenaiTrace, getGeneralStats, getGitProvider, getGlobalEvents, getGlobalEventStats, getGlobalMcp, getGlobalSandboxStatus, getGlobalSkill, getGroupedPageMetrics, getHealth, getHourlyVisits, getHttpChallengeDebug, getImportStatus, getIncident, getIncidentUpdates, getIpAccessControl, getIpGeolocation, getJoinTokenStatus, getLastDeployment, getLatestScan, getLatestScansPerEnvironment, getLiveVisitorsList, getLogContext, getMcp, getMetricsOverTime, getMonitor, getNotificationProvider, getOnDemandCertStatus, getOrCreateDsn, getPageFlow, getPageHourlySessions, getPagePathDetail, getPagePaths, getPagePathsSparklines, getPagePathVisitors, getPendingAction, getPerformanceMetrics, getPgUpgrade, getPgUpgradeLogs, getPipelineStats, getPlatformInfo, getPostgresWalHealth, getPreferences, getPreviewGatewayLogs, getPreviewGatewaySettings, getPreviewGatewayStatus, getPricing, getPrivateIp, getProject, getProjectAlarmsSummary, getProjectBySlug, getProjectDeployments, getProjects, getProjectServiceEnvironmentVariables, getProjectSessionReplays, getProjectsHealth, getProjectsMonitorHealth, getProjectStatistics, getProjectTemplate, getPropertyBreakdown, getPropertyTimeline, getProviderConnections, getProviderMetadata, getProvidersMetadata, getProxyLogById, getProxyLogByRequestId, getProxyLogs, getPublicBranches, getPublicIp, getPublicRepository, getQuota, getRecentActivity, getRemoteExternalImage, getRepositoryBranches, getRepositoryById, getRepositoryByName, getRepositoryPresetByName, getRepositoryPresetLive, getRepositoryTags, getResolvedEnvironmentVariables, getResolvedEnvironmentVariableValue, getRestoreCapabilities, getRestoreRun, getRoute, getRun, getRunWithLogs, getS3Credentials, getS3Source, getSandbox, getSandboxStatus, getScan, getScanByDeployment, getScanVulnerabilities, getService, getServiceBySlug, getServiceEnvironmentVariable, getServiceEnvironmentVariables, getServiceHealthStatus, getServicePreviewEnvironmentVariableNames, getServicePreviewEnvironmentVariablesMasked, getServiceRuntime, getServiceStats, getServiceTypeParameters, getServiceTypes, getSessionDetails, getSessionEvents, getSessionLogs, getSessionReplay, getSessionReplayEvents, getSettings, getSkill, getSlowQueries, getStaticBundle, getStatusOverview, getTagsByRepositoryId, getTeam, getTimeBucketStats, getTodayStats, getTrace, getUnifiedTrace, getUniqueCounts, getUniqueEvents, getUpdateStatus, getUptimeHistory, getUsageByProvider, getUsageRecent, getUsageSummary, getUsageTimeseries, getUsageTopModels, getVisitorByGuid, getVisitorById, getVisitorDetails, getVisitorFacets, getVisitorInfo, getVisitorJourney, getVisitors, getVisitorSessions, getVisitorStats, getWebhook, grantProjectAccess, handleGitProviderOauthCallback, hasAnalyticsEvents, hasErrorGroups, hasPerformanceMetrics, importExternalService, ingestLogs, ingestLogsByPath, ingestMetrics, ingestMetricsByPath, ingestSentryEnvelope, ingestSentryEvent, ingestTraces, ingestTracesByPath, initSessionReplay, jobLogs, jobStatus, killJob, kvDel, kvDisable, kvEnable, kvExpire, kvGet, kvIncr, kvKeys, kvSet, kvStatus, kvTtl, kvUpdate, latestRunForSource, linkCustomDomainToCertificate, linkServiceToProject, listAgentRuns, listAgents, listAiProviders, listAlertRules, listAlerts, listAllConversations, listAllRuns, listApiKeys, listAuditLogs, listAvailableContainers, listBackupAlerts, listBackupChildren, listBackupSchedules, listBackupsForSchedule, listCommitsByRepositoryId, listConnections, listContainers, listContainersAtPath, listConversations, listCustomDomainsForProject, listDashboards, listDeliveries, listDeploymentContainerLogs, listDeploymentTokens, listDnsProviders, listDomains, listDsns, listEmailDomains, listEmailProviders, listEmails, listEnrollmentTokens, listEntities, listErrorEvents, listErrorGroups, listEvents, listEventTypes, listExternalImages, listExternalPlugins, listExternalServiceBackups, listFlags, listFunnels, listGitProviders, listGlobalMcps, listGlobalSkills, listIncidents, listInsights, listIpAccessControl, listJobs, listKnownAiAgents, listManagedDomains, listMcps, listMetricLabelKeys, listMetricLabelValues, listMetricNames, listModels, listMonitors, listNotificationProviders, listOidcProviders, listOidcProviderUsers, listOidcRoleMappings, listOnDemandCerts, listOrders, listPeers, listPendingActions, listPgUpgrades, listPresets, listProjectAccess, listProjectAlarms, listProjectScans, listProjectSecrets, listProjectServices, listProjectTemplates, listProjectTemplateTags, listProviderKeys, listProviderZones, listPublicProviders, listReleaseFiles, listReleases, listRemoteExternalImages, listRepositoriesByConnection, listRepositoriesByProvider, listRestoreRunsForService, listRootContainers, listRoutes, listS3Sources, listSandboxes, listScheduleRunJobs, listScheduleRuns, listScheduleServices, listSecrets, listServiceHealthStatuses, listServiceProjects, listServices, listServiceSchedules, listSkills, listSourceBackups, listSourceFiles, listSourceMaps, listSources, listStaticBundles, listSyncedRepositories, listTeamMembers, listTeamProjects, listTeams, listUsers, listWebhooks, login, logout, lookupDnsARecords, mintEnrollmentToken, mkdir, nodeHeartbeat, nodeMetricsGetRange, observabilityFullEvent, observabilityListEvents, oidcCallback, type Options, patchAdminGate, patchPreviewGatewaySettings, pauseDeployment, pauseSandbox, planRestore, postDnsAck, previewAlert, previewFunnelMetrics, previewHostnameMode, promoteClusterMember, promoteDeployment, provisionDomain, purgeProjectLogs, pushExternalImage, queryData, queryGenaiTraces, queryLogs, queryMetrics, queryTraces, queryTraceSummaries, readFile, reAnalyze, recordConsoleEvent, recordEventMetrics, recordFlagExposure, recordSpeedMetrics, refreshRouteTable, regenerateDsn, registerExternalImage, registerNode, reinstallGitlabWebhook, rejectPendingAction, reloadPlugins, removeClusterMember, removeManagedDomain, removeRole, removeTeamMember, renameConversation, renewDomain, requestPasswordReset, resetPassword, resizeSandbox, resolveAlarm, restartContainer, restartPreviewGateway, restartSandbox, restoreFlag, restoreUser, resumeDeployment, resumeSandbox, retryCluster, retryDelivery, retryPgUpgrade, retryRun, revealGlobalMcpConfig, revealMcpConfig, revealNotificationProviderConfig, revealServiceParameter, revenueCreateIntegration, revenueDeleteIntegration, revenueGlobalEvents, revenueImportInvoicesCsv, revenueImportSubscriptionsCsv, revenueListIntegrations, revenueListProviders, revenueMetricsCustomers, revenueMetricsGlobalMrr, revenueMetricsGlobalSummary, revenueMetricsMrr, revenueMetricsSummary, revenueRecentEvents, revenueRotateToken, revenueUpdateConfig, revenueUpdateSecret, revokeDsn, revokeEnrollmentToken, revokeJoinToken, revokeProjectAccess, rollbackPgUpgrade, rollbackToDeployment, rootfsGc, rootfsReport, rotateApiKey, rotateDeploymentToken, runBackupForSource, runConnectionHealthCheck, runExternalServiceBackup, runScheduleNow, sandboxCreatePreviewLink, saveAgentToken, saveAiProviderCredential, searchLogs, sendEmail, setDefaultS3Source, setFlagEnvironment, setPreviewPassword, setupDns, setupDnsChallenge, setupEmailTracking, setupMfa, sleepEnvironment, smokeTestAgent, sourceSandbox, startAnalysis, startContainer, startFix, startGitProviderOauth, startOidcLoginBySlug, startPgUpgrade, startRestore, startService, statPath, stopContainer, stopSandbox, stopService, streamContainerMetrics, syncRepositories, tailDeploymentJobLogs, tailLogs, teardownDeployment, teardownEnvironment, testNotificationProvider, testOidcProvider, testProvider, testProviderConnection, testProviderKeyById, testProviderKeyInline, testS3ConnectionPreview, testS3SourceConnection, trackClick, trackOpen, triggerAgent, triggerProjectPipeline, triggerScan, triggerServiceHealthCheck, triggerWeeklyDigest, unlinkServiceFromProject, updateAgent, updateAiProvider, updateAlert, updateAlertRule, updateApiKey, updateAutomaticDeploy, updateBackupSchedule, updateCloudflareProvider, updateConnectionToken, updateCustomDomain, updateDashboard, updateDeploymentToken, updateEmailProvider, updateEnvironmentSettings, updateEnvironmentSubdomain, updateEnvironmentVariable, updateErrorGroup, updateFlag, updateFunnel, updateGitProviderCredentials, updateGitSettings, updateGlobalMcp, updateGlobalSkill, updateIncidentStatus, updateIpAccessControl, updateManagedDomain, updateMcp, updateNotificationEmailProvider, updateNotificationProvider, updateOidcProvider, updatePreferences, updateProject, updateProjectDeploymentConfig, updateProjectSecret, updateProjectSettings, updateProvider, updateProviderKey, updateRoute, updateS3Source, updateSelf, updateService, updateServiceResources, updateSessionDuration, updateSettings, updateSkill, updateSlackProvider, updateSpeedMetrics, updateTeam, updateTeamMemberRole, updateUser, updateWebhook, updateWebhookProvider, upgradePreviewGateway, upgradeService, uploadGlobalSkill, uploadReleaseFile, uploadSkill, uploadSourceFile, uploadSourceMap, uploadStaticBundle, upsertSecret, validateConnection, validateEmail, verifyAndEnableMfa, verifyDomain, verifyEmail, verifyManagedDomain, verifyMfaChallenge, verifyStepUp, wakeEnvironment, webhookTrigger, workflowDryRun, writeFile, writeFiles } from '../sdk.gen'; -import type { AcknowledgeAlarmData, ActivateAiProviderData, ActivateAiProviderResponse, ActivateApiKeyData, ActivateApiKeyResponse, ActivateConnectionData, ActivateProviderData, AddClusterMemberData, AddClusterMemberResponse, AddContextData, AddEnvironmentDomainData, AddEnvironmentDomainResponse, AddEventsData, AddEventsError, AddEventsResponse2, AddManagedDomainData, AddManagedDomainResponse, AddSessionReplayEventsData, AddSessionReplayEventsError, AddSessionReplayEventsResponse, AddTeamMemberData, AddTeamMemberResponse, AdminDrainNodeData, AdminDrainNodeResponse, AdminDrainStatusData, AdminDrainStatusResponse, AdminGetNodeData, AdminGetNodeResponse, AdminListNodeContainersData, AdminListNodeContainersResponse, AdminListNodesData, AdminListNodesResponse, AdminRemoveNodeData, AdminRemoveNodeResponse, AdminUndrainNodeData, AdminUndrainNodeResponse, ApplyHostnameModeData, ApplyHostnameModeResponse, ArchiveConversationData, ArchiveConversationResponse, ArchiveFlagData, ArchiveFlagResponse2, AssignRoleData, AttachScheduleServicesData, AttachScheduleServicesError, AttachScheduleServicesResponse2, BlobCopyData, BlobCopyError, BlobCopyResponse, BlobDeleteData, BlobDeleteError, BlobDeleteResponse, BlobDisableData, BlobDisableResponse, BlobDownloadData, BlobDownloadError, BlobEnableData, BlobEnableResponse, BlobListData, BlobListError, BlobListResponse, BlobPutData, BlobPutError, BlobPutResponse, BlobStatusData, BlobStatusResponse2, BlobUpdateData, BlobUpdateResponse, CancelBackupData, CancelBackupError, CancelBackupResponse2, CancelData, CancelDeploymentData, CancelDeploymentResponse, CancelDomainOrderData, CancelDomainOrderResponse, CancelPgUpgradeData, CancelPgUpgradeResponse, CancelRunData, CancelRunResponse, CancelScheduleRunData, CancelScheduleRunError, CancelScheduleRunResponse, ChangePasswordSelfData, ChangePasswordSelfResponse, ChangeProjectSourceData, ChangeProjectSourceResponse, ChatCompletionsData, ChatCompletionsError, ChatCompletionsResponse, CheckAnalyticsHasEventsData, CheckAnalyticsHasEventsResponse, CheckCommitExistsData, CheckCommitExistsResponse, CheckDomainStatusData, CheckDomainStatusResponse, CheckExplorerSupportData, CheckExplorerSupportResponse, CheckIpBlockedData, CheckIpBlockedError, CheckProviderDeletionSafetyData, CheckProviderDeletionSafetyResponse, ChunkUploadOptionsData, ChunkUploadOptionsResponse, CleanupExpiredBackupsData, CleanupExpiredBackupsError, CleanupExpiredBackupsResponse, ClearPreviewPasswordData, ClearPreviewPasswordResponse, CliDeviceApproveData, CliDeviceApproveResponse2, CliDeviceDenyData, CliDeviceDenyResponse, CliDeviceLookupData, CliDeviceLookupResponse2, CliDevicePollData, CliDevicePollResponse2, CliDeviceStartData, CliDeviceStartResponse2, CliLogoutData, CliLogoutResponse, CmdData, CmdKillData, CmdKillResponse, CmdLogsData, CmdResponse2, ConfirmPendingActionData, ConfirmPendingActionResponse, ContainerMetricsGetHistoryData, ContainerMetricsGetHistoryResponse, CreateAgentData, CreateAgentResponse, CreateAlertData, CreateAlertError, CreateAlertResponse, CreateAlertRuleData, CreateAlertRuleResponse, CreateApiKeyData, CreateApiKeyResponse2, CreateBackupScheduleData, CreateBackupScheduleError, CreateBackupScheduleResponse, CreateBitbucketProviderData, CreateBitbucketProviderResponse, CreateCloudflareProviderData, CreateCloudflareProviderResponse, CreateConversationData, CreateConversationResponse, CreateCustomDomainData, CreateCustomDomainResponse, CreateDashboardData, CreateDashboardError, CreateDashboardResponse, CreateDeploymentTokenData, CreateDeploymentTokenResponse2, CreateDnsProviderData, CreateDnsProviderResponse, CreateDomainData, CreateDomainResponse, CreateDsnData, CreateDsnResponse, CreateEmailDomainData, CreateEmailDomainResponse, CreateEmailProviderData, CreateEmailProviderResponse, CreateEnvironmentData, CreateEnvironmentResponse, CreateEnvironmentVariableData, CreateEnvironmentVariableResponse, CreateFlagData, CreateFlagResponse, CreateFunnelData, CreateFunnelResponse2, CreateGenericProviderData, CreateGenericProviderResponse, CreateGiteaPatProviderData, CreateGiteaPatProviderResponse, CreateGithubPatProviderData, CreateGithubPatProviderResponse, CreateGitlabOauthProviderData, CreateGitlabOauthProviderResponse, CreateGitlabPatProviderData, CreateGitlabPatProviderResponse, CreateGitProviderData, CreateGitProviderResponse, CreateGlobalMcpData, CreateGlobalMcpResponse, CreateGlobalSkillData, CreateGlobalSkillResponse, CreateIncidentData, CreateIncidentResponse, CreateIpAccessControlData, CreateIpAccessControlError, CreateIpAccessControlResponse, CreateMcpData, CreateMcpResponse, CreateMonitorData, CreateMonitorResponse, CreateNotificationEmailProviderData, CreateNotificationEmailProviderResponse, CreateNotificationProviderData, CreateNotificationProviderResponse, CreateOidcProviderData, CreateOidcProviderResponse, CreateOidcRoleMappingData, CreateOidcRoleMappingResponse, CreateOrRecreateOrderData, CreateOrRecreateOrderResponse, CreatePlanData, CreatePlanResponse2, CreatePrData, CreateProjectData, CreateProjectFromTemplateData, CreateProjectFromTemplateResponse2, CreateProjectReleaseData, CreateProjectReleaseResponse, CreateProjectResponse, CreateProjectSecretData, CreateProjectSecretResponse, CreateProviderKeyData, CreateProviderKeyError, CreateProviderKeyResponse, CreatePrResponse2, CreateReleaseData, CreateReleaseResponse, CreateRouteData, CreateRouteResponse, CreateS3SourceData, CreateS3SourceError, CreateS3SourceResponse, CreateSandboxData, CreateSandboxResponse, CreateServiceData, CreateServiceResponse, CreateSkillData, CreateSkillResponse, CreateSlackProviderData, CreateSlackProviderResponse, CreateTeamData, CreateTeamResponse, CreateUserData, CreateUserResponse, CreateWebhookData, CreateWebhookProviderData, CreateWebhookProviderResponse, CreateWebhookResponse, DeactivateApiKeyData, DeactivateApiKeyResponse, DeactivateConnectionData, DeactivateProviderData, DeleteAgentData, DeleteAgentResponse, DeleteAlertData, DeleteAlertError, DeleteAlertResponse, DeleteAlertRuleData, DeleteAlertRuleResponse, DeleteApiKeyData, DeleteApiKeyResponse, DeleteBackupData, DeleteBackupError, DeleteBackupResponse, DeleteBackupScheduleData, DeleteBackupScheduleError, DeleteBackupScheduleResponse, DeleteConnectionData, DeleteConnectionResponse, DeleteCustomDomainData, DeleteCustomDomainResponse, DeleteDashboardData, DeleteDashboardError, DeleteDashboardResponse, DeleteDeploymentTokenData, DeleteDeploymentTokenResponse, DeleteDnsProviderData, DeleteDnsProviderResponse, DeleteDomainData, DeleteDomainResponse, DeleteEmailDomainData, DeleteEmailDomainResponse, DeleteEmailProviderData, DeleteEmailProviderResponse, DeleteEnvironmentData, DeleteEnvironmentDomainData, DeleteEnvironmentDomainResponse, DeleteEnvironmentResponse, DeleteEnvironmentVariableData, DeleteEnvironmentVariableResponse, DeleteExternalImageData, DeleteExternalImageResponse, DeleteFunnelData, DeleteGitProviderData, DeleteGitProviderResponse, DeleteGlobalMcpData, DeleteGlobalMcpResponse, DeleteGlobalSkillData, DeleteGlobalSkillResponse, DeleteIpAccessControlData, DeleteIpAccessControlError, DeleteIpAccessControlResponse, DeleteMcpData, DeleteMcpResponse, DeleteMonitorData, DeleteMonitorResponse, DeleteNotificationProviderData, DeleteNotificationProviderResponse, DeleteOidcProviderData, DeleteOidcProviderResponse, DeleteOidcRoleMappingData, DeleteOidcRoleMappingResponse, DeletePreferencesData, DeletePreferencesResponse, DeleteProjectData, DeleteProjectResponse, DeleteProjectSecretData, DeleteProjectSecretResponse, DeleteProviderKeyData, DeleteProviderKeyError, DeleteProviderKeyResponse, DeleteProviderSafelyData, DeleteProviderSafelyResponse, DeleteReleaseSourceFilesData, DeleteReleaseSourceFilesResponse, DeleteReleaseSourceMapsData, DeleteReleaseSourceMapsResponse, DeleteRouteData, DeleteRouteResponse, DeleteS3SourceData, DeleteS3SourceError, DeleteS3SourceResponse, DeleteScanData, DeleteScanError, DeleteScanResponse, DeleteSecretData, DeleteSecretResponse, DeleteServiceData, DeleteServiceResponse, DeleteSessionReplayData, DeleteSessionReplayError, DeleteSkillData, DeleteSkillResponse, DeleteSourceMapData, DeleteSourceMapResponse, DeleteStaticBundleData, DeleteStaticBundleResponse, DeleteTeamData, DeleteTeamResponse, DeleteUserData, DeleteUserResponse, DeleteWebhookData, DeleteWebhookResponse, DeployFromImageData, DeployFromImageResponse, DeployFromImageUploadData, DeployFromImageUploadResponse, DeployFromStaticData, DeployFromStaticResponse, DeploymentMetricsGetLatestData, DeploymentMetricsGetLatestResponse, DeploymentMetricsGetRangeData, DeploymentMetricsGetRangeResponse, DeploymentMetricsToggleData, DestroySandboxData, DestroySandboxResponse, DetachScheduleServiceData, DetachScheduleServiceError, DetachScheduleServiceResponse, DetectPublicPresetsData, DetectPublicPresetsResponse, DisableBackupScheduleData, DisableBackupScheduleResponse, DisableMfaData, DisableMfaResponse, DiscoverWorkloadsData, DiscoverWorkloadsResponse, DomainData, DomainResponse2, DownloadGlobalSkillArchiveData, DownloadGlobalSkillArchiveResponse, DownloadObjectData, DownloadObjectResponse, DownloadSkillArchiveData, DownloadSkillArchiveResponse, EmailStatusData, EmailStatusResponse2, EmbeddingsData, EmbeddingsError, EmbeddingsResponse, EnableBackupScheduleData, EnableBackupScheduleResponse, EnrichVisitorData, EnrichVisitorResponse2, ExecData, ExecDetachedData, ExecDetachedResponse2, ExecResponse2, ExecuteDeploymentOperationData, ExecuteDeploymentOperationResponse, ExecuteImportData, ExecuteImportResponse2, ExtendTimeoutData, ExtendTimeoutResponse, ExternalServiceEnablePgStatStatementsData, ExternalServiceEnablePgStatStatementsResponse, ExternalServiceMetricsByDatabaseData, ExternalServiceMetricsByDatabaseResponse, ExternalServiceMetricsCreateAlertRuleData, ExternalServiceMetricsCreateAlertRuleResponse, ExternalServiceMetricsDeleteAlertRuleData, ExternalServiceMetricsDeleteAlertRuleResponse, ExternalServiceMetricsGetAlertRulesData, ExternalServiceMetricsGetAlertRulesResponse, ExternalServiceMetricsGetLatestData, ExternalServiceMetricsGetLatestResponse, ExternalServiceMetricsGetRangeData, ExternalServiceMetricsGetRangeResponse, ExternalServiceMetricsStatusData, ExternalServiceMetricsStatusResponse, ExternalServiceMetricsToggleData, ExternalServiceMetricsUpdateAlertRuleData, ExternalServiceMetricsUpdateAlertRuleResponse, ExternalServiceResetPgStatStatementsData, ExternalServiceResetPgStatStatementsResponse, FinalizeOrderData, FinalizeOrderResponse, FinalizeProjectReleaseData, FinalizeProjectReleaseResponse, FindConversationData, FindConversationResponse, GenerateJoinTokenData, GenerateJoinTokenResponse2, GeneratePresetDockerfileData, GeneratePresetDockerfileResponse, GetAccessInfoData, GetAccessInfoResponse, GetActiveVisitorsData, GetActiveVisitorsResponse, GetActivityGraphData, GetActivityGraphResponse, GetAdminGateData, GetAdminGateResponse, GetAgentData, GetAgentResponse, GetAggregatedBucketsData, GetAggregatedBucketsResponse, GetAiAgentBreakdownData, GetAiAgentBreakdownError, GetAiAgentBreakdownResponse, GetAiAgentPagesData, GetAiAgentPagesError, GetAiAgentPagesResponse, GetAiAgentTimelineData, GetAiAgentTimelineError, GetAiAgentTimelineResponse, GetAiPageBreakdownData, GetAiPageBreakdownError, GetAiPageBreakdownResponse, GetAiStatusBreakdownData, GetAiStatusBreakdownError, GetAiStatusBreakdownResponse, GetAlertData, GetAlertError, GetAlertResponse, GetAlertRuleData, GetAlertRuleResponse, GetAllRepositoriesByNameData, GetAllRepositoriesByNameResponse, GetAnalyticsActiveVisitorsData, GetAnalyticsActiveVisitorsResponse, GetAnalyticsEventsCountData, GetAnalyticsEventsCountResponse, GetAnalyticsSessionEventsData, GetAnalyticsSessionEventsResponse, GetAnalyticsVisitorSessionsData, GetAnalyticsVisitorSessionsResponse, GetApiKeyData, GetApiKeyPermissionsData, GetApiKeyPermissionsResponse, GetApiKeyResponse, GetAuditLogData, GetAuditLogResponse, GetBackupData, GetBackupError, GetBackupResponse, GetBackupScheduleData, GetBackupScheduleResponse, GetBranchesByRepositoryIdData, GetBranchesByRepositoryIdResponse, GetBucketedIncidentsData, GetBucketedIncidentsResponse, GetBucketedStatusData, GetBucketedStatusResponse, GetChallengeTokenData, GetChallengeTokenResponse, GetChatReadinessData, GetChatReadinessResponse, GetCliStatusData, GetClusterHealthData, GetClusterHealthResponse, GetClusterMemberData, GetClusterMemberResponse, GetCmdData, GetCmdResponse, GetContainerDetailData, GetContainerDetailResponse, GetContainerEnvironmentVariableData, GetContainerEnvironmentVariableResponse, GetContainerInfoData, GetContainerInfoResponse, GetContainerLogsByIdData, GetContainerLogsData, GetContainerMetricsData, GetContainerMetricsResponse, GetConversationData, GetConversationDetailData, GetConversationDetailError, GetConversationDetailResponse, GetConversationResponse, GetConversationsData, GetConversationsError, GetConversationsResponse, GetCronByIdData, GetCronByIdResponse, GetCronExecutionsData, GetCronExecutionsResponse, GetCrossProjectTraceSiblingsData, GetCrossProjectTraceSiblingsError, GetCrossProjectTraceSiblingsResponse, GetCurrentMonitorStatusData, GetCurrentMonitorStatusResponse, GetCurrentUserData, GetCurrentUserResponse, GetCustomDomainData, GetCustomDomainResponse, GetDashboardData, GetDashboardError, GetDashboardProjectsAnalyticsData, GetDashboardProjectsAnalyticsResponse, GetDashboardResponse, GetDeliveryData, GetDeliveryResponse, GetDeploymentContainerLogContentData, GetDeploymentContainerLogContentResponse, GetDeploymentData, GetDeploymentJobLogsData, GetDeploymentJobLogsResponse, GetDeploymentJobsData, GetDeploymentJobsResponse, GetDeploymentOperationsData, GetDeploymentOperationsResponse, GetDeploymentOperationStatusData, GetDeploymentOperationStatusResponse, GetDeploymentResponse, GetDeploymentTokenData, GetDeploymentTokenResponse, GetDiskStatusData, GetDiskStatusResponse, GetDnsChangesData, GetDnsChangesResponse, GetDnsProviderData, GetDnsProviderResponse, GetDomainByHostData, GetDomainByHostResponse, GetDomainByIdData, GetDomainByIdResponse, GetDomainByNameData, GetDomainByNameResponse, GetDomainData, GetDomainDnsRecordsData, GetDomainDnsRecordsResponse, GetDomainOrderData, GetDomainOrderResponse, GetDomainResponse, GetEmailData, GetEmailEventsData, GetEmailEventsResponse, GetEmailLinksData, GetEmailLinksResponse, GetEmailProviderData, GetEmailProviderResponse, GetEmailResponse, GetEmailStatsData, GetEmailStatsResponse, GetEmailTrackingData, GetEmailTrackingResponse, GetEmailTrackingStatusData, GetEmailTrackingStatusResponse, GetEntityInfoData, GetEntityInfoResponse, GetEnvironmentCronsData, GetEnvironmentCronsResponse, GetEnvironmentData, GetEnvironmentDomainsData, GetEnvironmentDomainsResponse, GetEnvironmentResponse, GetEnvironmentsData, GetEnvironmentsResponse, GetEnvironmentVariablesData, GetEnvironmentVariablesResponse, GetEnvironmentVariableValueData, GetEnvironmentVariableValueResponse, GetErrorDashboardStatsData, GetErrorDashboardStatsResponse, GetErrorEventData, GetErrorEventResponse, GetErrorGroupData, GetErrorGroupResponse, GetErrorStatsData, GetErrorStatsResponse, GetErrorTimeSeriesData, GetErrorTimeSeriesResponse, GetEventDetailData, GetEventDetailResponse, GetEventEntriesData, GetEventEntriesResponse, GetEventsCountData, GetEventsCountResponse, GetEventsTimelineData, GetEventsTimelineResponse, GetEventTypeBreakdownData, GetEventTypeBreakdownResponse, GetEventVisitorsData, GetEventVisitorsResponse, GetExternalImageData, GetExternalImageResponse, GetFileData, GetFileResponse, GetFlagData, GetFlagResponse, GetFlagSnapshotData, GetFlagSnapshotResponse, GetFunnelMetricsData, GetFunnelMetricsResponse, GetGenaiTraceData, GetGenaiTraceError, GetGenaiTraceResponse, GetGeneralStatsData, GetGeneralStatsResponse, GetGitProviderData, GetGitProviderResponse, GetGlobalEventsData, GetGlobalEventsResponse, GetGlobalEventStatsData, GetGlobalEventStatsResponse, GetGlobalMcpData, GetGlobalMcpResponse, GetGlobalSandboxStatusData, GetGlobalSandboxStatusResponse, GetGlobalSkillData, GetGlobalSkillResponse, GetGroupedPageMetricsData, GetGroupedPageMetricsError, GetGroupedPageMetricsResponse, GetHealthData, GetHealthError, GetHealthResponse, GetHourlyVisitsData, GetHourlyVisitsResponse, GetHttpChallengeDebugData, GetHttpChallengeDebugResponse, GetImportStatusData, GetImportStatusResponse, GetIncidentData, GetIncidentResponse, GetIncidentUpdatesData, GetIncidentUpdatesResponse, GetIpAccessControlData, GetIpAccessControlError, GetIpAccessControlResponse, GetIpGeolocationData, GetIpGeolocationError, GetIpGeolocationResponse, GetJoinTokenStatusData, GetJoinTokenStatusResponse, GetLastDeploymentData, GetLastDeploymentResponse, GetLatestScanData, GetLatestScanError, GetLatestScanResponse, GetLatestScansPerEnvironmentData, GetLatestScansPerEnvironmentError, GetLatestScansPerEnvironmentResponse, GetLiveVisitorsListData, GetLiveVisitorsListResponse, GetLogContextData, GetLogContextError, GetLogContextResponse, GetMcpData, GetMcpResponse, GetMetricsOverTimeData, GetMetricsOverTimeError, GetMetricsOverTimeResponse, GetMonitorData, GetMonitorResponse, GetNotificationProviderData, GetNotificationProviderResponse, GetOnDemandCertStatusData, GetOnDemandCertStatusResponse, GetOrCreateDsnData, GetOrCreateDsnResponse, GetPageFlowData, GetPageFlowResponse, GetPageHourlySessionsData, GetPageHourlySessionsResponse, GetPagePathDetailData, GetPagePathDetailResponse, GetPagePathsData, GetPagePathsResponse, GetPagePathsSparklinesData, GetPagePathsSparklinesResponse, GetPagePathVisitorsData, GetPagePathVisitorsResponse, GetPendingActionData, GetPendingActionResponse, GetPerformanceMetricsData, GetPerformanceMetricsError, GetPerformanceMetricsResponse, GetPgUpgradeData, GetPgUpgradeLogsData, GetPgUpgradeLogsResponse, GetPgUpgradeResponse, GetPipelineStatsData, GetPipelineStatsError, GetPipelineStatsResponse, GetPlatformInfoData, GetPlatformInfoResponse, GetPostgresWalHealthData, GetPostgresWalHealthResponse, GetPreferencesData, GetPreferencesResponse, GetPreviewGatewayLogsData, GetPreviewGatewayLogsResponse, GetPreviewGatewaySettingsData, GetPreviewGatewaySettingsResponse, GetPreviewGatewayStatusData, GetPreviewGatewayStatusResponse, GetPricingData, GetPricingError, GetPricingResponse, GetPrivateIpData, GetProjectAlarmsSummaryData, GetProjectAlarmsSummaryResponse, GetProjectBySlugData, GetProjectBySlugResponse, GetProjectData, GetProjectDeploymentsData, GetProjectDeploymentsResponse, GetProjectResponse, GetProjectsData, GetProjectServiceEnvironmentVariablesData, GetProjectServiceEnvironmentVariablesResponse, GetProjectSessionReplaysData, GetProjectSessionReplaysError, GetProjectSessionReplaysResponse2, GetProjectsHealthData, GetProjectsHealthError, GetProjectsHealthResponse, GetProjectsMonitorHealthData, GetProjectsMonitorHealthResponse, GetProjectsResponse, GetProjectStatisticsData, GetProjectStatisticsResponse, GetProjectTemplateData, GetProjectTemplateResponse, GetPropertyBreakdownData, GetPropertyBreakdownResponse, GetPropertyTimelineData, GetPropertyTimelineResponse, GetProviderConnectionsData, GetProviderConnectionsResponse, GetProviderMetadataData, GetProviderMetadataResponse, GetProvidersMetadataData, GetProvidersMetadataResponse, GetProxyLogByIdData, GetProxyLogByIdError, GetProxyLogByIdResponse, GetProxyLogByRequestIdData, GetProxyLogByRequestIdError, GetProxyLogByRequestIdResponse, GetProxyLogsData, GetProxyLogsError, GetProxyLogsResponse, GetPublicBranchesData, GetPublicBranchesResponse, GetPublicIpData, GetPublicRepositoryData, GetPublicRepositoryResponse, GetQuotaData, GetQuotaError, GetQuotaResponse, GetRecentActivityData, GetRecentActivityResponse, GetRemoteExternalImageData, GetRemoteExternalImageResponse, GetRepositoryBranchesData, GetRepositoryBranchesResponse, GetRepositoryByIdData, GetRepositoryByIdResponse, GetRepositoryByNameData, GetRepositoryByNameResponse, GetRepositoryPresetByNameData, GetRepositoryPresetByNameResponse, GetRepositoryPresetLiveData, GetRepositoryPresetLiveResponse, GetRepositoryTagsData, GetRepositoryTagsResponse, GetResolvedEnvironmentVariablesData, GetResolvedEnvironmentVariablesResponse, GetResolvedEnvironmentVariableValueData, GetResolvedEnvironmentVariableValueResponse, GetRestoreCapabilitiesData, GetRestoreCapabilitiesError, GetRestoreCapabilitiesResponse, GetRestoreRunData, GetRestoreRunError, GetRestoreRunResponse, GetRouteData, GetRouteResponse, GetRunData, GetRunResponse, GetRunWithLogsData, GetRunWithLogsResponse, GetS3CredentialsData, GetS3CredentialsResponse, GetS3SourceData, GetS3SourceError, GetS3SourceResponse, GetSandboxData, GetSandboxResponse, GetSandboxStatusData, GetSandboxStatusResponse, GetScanByDeploymentData, GetScanByDeploymentError, GetScanByDeploymentResponse, GetScanData, GetScanError, GetScanResponse, GetScanVulnerabilitiesData, GetScanVulnerabilitiesError, GetScanVulnerabilitiesResponse, GetServiceBySlugData, GetServiceBySlugResponse, GetServiceData, GetServiceEnvironmentVariableData, GetServiceEnvironmentVariableResponse, GetServiceEnvironmentVariablesData, GetServiceEnvironmentVariablesResponse, GetServiceHealthStatusData, GetServiceHealthStatusResponse, GetServicePreviewEnvironmentVariableNamesData, GetServicePreviewEnvironmentVariableNamesResponse, GetServicePreviewEnvironmentVariablesMaskedData, GetServicePreviewEnvironmentVariablesMaskedResponse, GetServiceResponse, GetServiceRuntimeData, GetServiceRuntimeResponse, GetServiceStatsData, GetServiceStatsResponse, GetServiceTypeParametersData, GetServiceTypesData, GetServiceTypesResponse, GetSessionDetailsData, GetSessionDetailsResponse, GetSessionEventsData, GetSessionEventsResponse, GetSessionLogsData, GetSessionLogsResponse, GetSessionReplayData, GetSessionReplayError, GetSessionReplayEventsData, GetSessionReplayEventsError, GetSessionReplayEventsResponse, GetSessionReplayResponse2, GetSettingsData, GetSettingsResponse, GetSkillData, GetSkillResponse, GetSlowQueriesData, GetSlowQueriesResponse, GetStaticBundleData, GetStaticBundleResponse, GetStatusOverviewData, GetStatusOverviewResponse, GetTagsByRepositoryIdData, GetTagsByRepositoryIdResponse, GetTeamData, GetTeamResponse, GetTimeBucketStatsData, GetTimeBucketStatsError, GetTimeBucketStatsResponse, GetTodayStatsData, GetTodayStatsError, GetTodayStatsResponse, GetTraceData, GetTraceError, GetTraceResponse, GetUnifiedTraceData, GetUnifiedTraceError, GetUnifiedTraceResponse, GetUniqueCountsData, GetUniqueCountsResponse, GetUniqueEventsData, GetUniqueEventsResponse, GetUpdateStatusData, GetUpdateStatusResponse, GetUptimeHistoryData, GetUptimeHistoryResponse, GetUsageByProviderData, GetUsageByProviderError, GetUsageByProviderResponse, GetUsageRecentData, GetUsageRecentError, GetUsageRecentResponse, GetUsageSummaryData, GetUsageSummaryError, GetUsageSummaryResponse, GetUsageTimeseriesData, GetUsageTimeseriesError, GetUsageTimeseriesResponse, GetUsageTopModelsData, GetUsageTopModelsError, GetUsageTopModelsResponse, GetVisitorByGuidData, GetVisitorByGuidResponse, GetVisitorByIdData, GetVisitorByIdResponse, GetVisitorDetailsData, GetVisitorDetailsResponse, GetVisitorFacetsData, GetVisitorFacetsResponse, GetVisitorInfoData, GetVisitorInfoResponse, GetVisitorJourneyData, GetVisitorJourneyResponse, GetVisitorsData, GetVisitorSessionsData, GetVisitorSessionsError, GetVisitorSessionsResponse2, GetVisitorsResponse, GetVisitorStatsData, GetVisitorStatsResponse, GetWebhookData, GetWebhookResponse, GrantProjectAccessData, GrantProjectAccessResponse, HandleGitProviderOauthCallbackData, HasAnalyticsEventsData, HasAnalyticsEventsResponse2, HasErrorGroupsData, HasErrorGroupsResponse2, HasPerformanceMetricsData, HasPerformanceMetricsError, HasPerformanceMetricsResponse, ImportExternalServiceData, ImportExternalServiceResponse, IngestLogsByPathData, IngestLogsByPathError, IngestLogsData, IngestLogsError, IngestMetricsByPathData, IngestMetricsByPathError, IngestMetricsData, IngestMetricsError, IngestSentryEnvelopeData, IngestSentryEventData, IngestSentryEventResponse, IngestTracesByPathData, IngestTracesByPathError, IngestTracesData, IngestTracesError, InitSessionReplayData, InitSessionReplayError, InitSessionReplayResponse, JobLogsData, JobStatusData, JobStatusResponse2, KillJobData, KillJobResponse, KvDelData, KvDelResponse, KvDisableData, KvDisableResponse, KvEnableData, KvEnableResponse, KvExpireData, KvExpireResponse, KvGetData, KvGetResponse, KvIncrData, KvIncrResponse, KvKeysData, KvKeysResponse, KvSetData, KvSetResponse, KvStatusData, KvStatusResponse2, KvTtlData, KvTtlResponse, KvUpdateData, KvUpdateResponse, LatestRunForSourceData, LatestRunForSourceResponse, LinkCustomDomainToCertificateData, LinkCustomDomainToCertificateResponse, LinkServiceToProjectData, LinkServiceToProjectResponse, ListAgentRunsData, ListAgentRunsResponse, ListAgentsData, ListAgentsResponse2, ListAiProvidersData, ListAiProvidersResponse, ListAlertRulesData, ListAlertRulesResponse, ListAlertsData, ListAlertsError, ListAlertsResponse, ListAllConversationsData, ListAllConversationsResponse, ListAllRunsData, ListAllRunsResponse, ListApiKeysData, ListApiKeysResponse, ListAuditLogsData, ListAuditLogsResponse, ListAvailableContainersData, ListAvailableContainersResponse, ListBackupAlertsData, ListBackupAlertsError, ListBackupAlertsResponse, ListBackupChildrenData, ListBackupChildrenError, ListBackupChildrenResponse, ListBackupSchedulesData, ListBackupSchedulesError, ListBackupSchedulesResponse, ListBackupsForScheduleData, ListBackupsForScheduleResponse, ListCommitsByRepositoryIdData, ListCommitsByRepositoryIdResponse, ListConnectionsData, ListConnectionsResponse, ListContainersAtPathData, ListContainersAtPathResponse, ListContainersData, ListContainersResponse, ListConversationsData, ListConversationsResponse, ListCustomDomainsForProjectData, ListCustomDomainsForProjectResponse, ListDashboardsData, ListDashboardsError, ListDashboardsResponse, ListDeliveriesData, ListDeliveriesResponse, ListDeploymentContainerLogsData, ListDeploymentContainerLogsResponse, ListDeploymentTokensData, ListDeploymentTokensResponse, ListDnsProvidersData, ListDnsProvidersResponse, ListDomainsData, ListDomainsResponse2, ListDsnsData, ListDsnsResponse, ListEmailDomainsData, ListEmailDomainsResponse, ListEmailProvidersData, ListEmailProvidersResponse, ListEmailsData, ListEmailsResponse, ListEnrollmentTokensData, ListEnrollmentTokensResponse, ListEntitiesData, ListEntitiesResponse, ListErrorEventsData, ListErrorEventsResponse, ListErrorGroupsData, ListErrorGroupsResponse, ListEventsData, ListEventsResponse, ListEventTypesData, ListEventTypesResponse, ListExternalImagesData, ListExternalImagesResponse, ListExternalPluginsData, ListExternalPluginsResponse, ListExternalServiceBackupsData, ListExternalServiceBackupsError, ListExternalServiceBackupsResponse, ListFlagsData, ListFlagsResponse, ListFunnelsData, ListFunnelsResponse, ListGitProvidersData, ListGitProvidersResponse, ListGlobalMcpsData, ListGlobalMcpsResponse, ListGlobalSkillsData, ListGlobalSkillsResponse, ListIncidentsData, ListInsightsData, ListInsightsError, ListInsightsResponse, ListIpAccessControlData, ListIpAccessControlError, ListIpAccessControlResponse, ListJobsData, ListJobsResponse2, ListKnownAiAgentsData, ListKnownAiAgentsError, ListKnownAiAgentsResponse, ListManagedDomainsData, ListManagedDomainsResponse, ListMcpsData, ListMcpsResponse2, ListMetricLabelKeysData, ListMetricLabelKeysError, ListMetricLabelKeysResponse, ListMetricLabelValuesData, ListMetricLabelValuesError, ListMetricLabelValuesResponse, ListMetricNamesData, ListMetricNamesError, ListMetricNamesResponse, ListModelsData, ListModelsError, ListModelsResponse, ListMonitorsData, ListMonitorsResponse, ListNotificationProvidersData, ListNotificationProvidersResponse, ListOidcProvidersData, ListOidcProvidersResponse, ListOidcProviderUsersData, ListOidcProviderUsersResponse, ListOidcRoleMappingsData, ListOidcRoleMappingsResponse, ListOnDemandCertsData, ListOnDemandCertsResponse2, ListOrdersData, ListOrdersResponse2, ListPeersData, ListPeersResponse, ListPendingActionsData, ListPendingActionsResponse, ListPgUpgradesData, ListPgUpgradesResponse, ListPresetsData, ListPresetsResponse2, ListProjectAccessData, ListProjectAccessResponse, ListProjectAlarmsData, ListProjectAlarmsResponse, ListProjectScansData, ListProjectScansError, ListProjectScansResponse, ListProjectSecretsData, ListProjectSecretsResponse, ListProjectServicesData, ListProjectServicesResponse, ListProjectTemplatesData, ListProjectTemplatesResponse, ListProjectTemplateTagsData, ListProjectTemplateTagsResponse, ListProviderKeysData, ListProviderKeysError, ListProviderKeysResponse, ListProviderZonesData, ListProviderZonesResponse, ListPublicProvidersData, ListPublicProvidersResponse, ListReleaseFilesData, ListReleaseFilesResponse, ListReleasesData, ListReleasesResponse, ListRemoteExternalImagesData, ListRemoteExternalImagesResponse, ListRepositoriesByConnectionData, ListRepositoriesByConnectionResponse, ListRepositoriesByProviderData, ListRepositoriesByProviderResponse, ListRestoreRunsForServiceData, ListRestoreRunsForServiceResponse, ListRootContainersData, ListRootContainersResponse, ListRoutesData, ListRoutesResponse, ListS3SourcesData, ListS3SourcesError, ListS3SourcesResponse, ListSandboxesData, ListSandboxesResponse2, ListScheduleRunJobsData, ListScheduleRunJobsError, ListScheduleRunJobsResponse, ListScheduleRunsData, ListScheduleRunsError, ListScheduleRunsResponse, ListScheduleServicesData, ListScheduleServicesError, ListScheduleServicesResponse, ListSecretsData, ListSecretsResponse2, ListServiceHealthStatusesData, ListServiceHealthStatusesResponse, ListServiceProjectsData, ListServiceProjectsResponse, ListServiceSchedulesData, ListServiceSchedulesError, ListServiceSchedulesResponse, ListServicesData, ListServicesResponse, ListSkillsData, ListSkillsResponse2, ListSourceBackupsData, ListSourceBackupsError, ListSourceBackupsResponse, ListSourceFilesData, ListSourceFilesResponse, ListSourceMapsData, ListSourceMapsResponse, ListSourcesData, ListSourcesResponse, ListStaticBundlesData, ListStaticBundlesResponse, ListSyncedRepositoriesData, ListSyncedRepositoriesResponse, ListTeamMembersData, ListTeamMembersResponse, ListTeamProjectsData, ListTeamProjectsResponse, ListTeamsData, ListTeamsResponse, ListUsersData, ListUsersResponse, ListWebhooksData, ListWebhooksResponse, LoginData, LoginResponse, LogoutData, LookupDnsARecordsData, LookupDnsARecordsError, LookupDnsARecordsResponse, MintEnrollmentTokenData, MintEnrollmentTokenResponse2, MkdirData, MkdirResponse, NodeHeartbeatData, NodeHeartbeatResponse, NodeMetricsGetRangeData, NodeMetricsGetRangeResponse, ObservabilityFullEventData, ObservabilityFullEventError, ObservabilityFullEventResponse, ObservabilityListEventsData, ObservabilityListEventsError, ObservabilityListEventsResponse, OidcCallbackData, PatchAdminGateData, PatchAdminGateResponse, PatchPreviewGatewaySettingsData, PatchPreviewGatewaySettingsResponse, PauseDeploymentData, PauseDeploymentResponse, PauseSandboxData, PauseSandboxResponse, PlanRestoreData, PlanRestoreError, PlanRestoreResponse, PostDnsAckData, PostDnsAckResponse, PreviewAlertData, PreviewAlertError, PreviewAlertResponse, PreviewFunnelMetricsData, PreviewFunnelMetricsResponse, PreviewHostnameModeData, PreviewHostnameModeResponse, PromoteClusterMemberData, PromoteDeploymentData, PromoteDeploymentResponse, ProvisionDomainData, ProvisionDomainResponse, PurgeProjectLogsData, PurgeProjectLogsError, PushExternalImageData, PushExternalImageResponse, QueryDataData, QueryDataResponse2, QueryGenaiTracesData, QueryGenaiTracesError, QueryGenaiTracesResponse, QueryLogsData, QueryLogsError, QueryLogsResponse, QueryMetricsData, QueryMetricsError, QueryMetricsResponse, QueryTracesData, QueryTracesError, QueryTracesResponse, QueryTraceSummariesData, QueryTraceSummariesError, QueryTraceSummariesResponse, ReadFileData, ReadFileResponse2, ReAnalyzeData, RecordConsoleEventData, RecordEventMetricsData, RecordEventMetricsResponse, RecordFlagExposureData, RecordFlagExposureResponse, RecordSpeedMetricsData, RecordSpeedMetricsError, RecordSpeedMetricsResponse, RefreshRouteTableData, RefreshRouteTableResponse, RegenerateDsnData, RegenerateDsnResponse, RegisterExternalImageData, RegisterExternalImageResponse, RegisterNodeData, RegisterNodeResponse2, ReinstallGitlabWebhookData, ReinstallGitlabWebhookResponse, RejectPendingActionData, RejectPendingActionResponse, ReloadPluginsData, ReloadPluginsResponse, RemoveClusterMemberData, RemoveClusterMemberResponse, RemoveManagedDomainData, RemoveManagedDomainResponse, RemoveRoleData, RemoveRoleResponse, RemoveTeamMemberData, RemoveTeamMemberResponse, RenameConversationData, RenameConversationResponse, RenewDomainData, RenewDomainResponse, RequestPasswordResetData, RequestPasswordResetResponse, ResetPasswordData, ResetPasswordResponse, ResizeSandboxData, ResizeSandboxResponse, ResolveAlarmData, RestartContainerData, RestartContainerResponse, RestartPreviewGatewayData, RestartPreviewGatewayResponse, RestartSandboxData, RestartSandboxResponse, RestoreFlagData, RestoreFlagResponse, RestoreUserData, RestoreUserResponse, ResumeDeploymentData, ResumeDeploymentResponse, ResumeSandboxData, ResumeSandboxResponse, RetryClusterData, RetryClusterResponse, RetryDeliveryData, RetryDeliveryResponse, RetryPgUpgradeData, RetryPgUpgradeResponse, RetryRunData, RetryRunResponse, RevealGlobalMcpConfigData, RevealGlobalMcpConfigResponse, RevealMcpConfigData, RevealMcpConfigResponse, RevealNotificationProviderConfigData, RevealNotificationProviderConfigResponse, RevealServiceParameterData, RevealServiceParameterResponse, RevenueCreateIntegrationData, RevenueCreateIntegrationResponse, RevenueDeleteIntegrationData, RevenueDeleteIntegrationResponse, RevenueGlobalEventsData, RevenueGlobalEventsResponse, RevenueImportInvoicesCsvData, RevenueImportInvoicesCsvResponse, RevenueImportSubscriptionsCsvData, RevenueImportSubscriptionsCsvResponse, RevenueListIntegrationsData, RevenueListIntegrationsResponse, RevenueListProvidersData, RevenueListProvidersResponse, RevenueMetricsCustomersData, RevenueMetricsCustomersResponse, RevenueMetricsGlobalMrrData, RevenueMetricsGlobalMrrResponse, RevenueMetricsGlobalSummaryData, RevenueMetricsGlobalSummaryResponse, RevenueMetricsMrrData, RevenueMetricsMrrResponse, RevenueMetricsSummaryData, RevenueMetricsSummaryResponse, RevenueRecentEventsData, RevenueRecentEventsResponse, RevenueRotateTokenData, RevenueRotateTokenResponse, RevenueUpdateConfigData, RevenueUpdateConfigResponse, RevenueUpdateSecretData, RevenueUpdateSecretResponse, RevokeDsnData, RevokeDsnResponse, RevokeEnrollmentTokenData, RevokeEnrollmentTokenResponse, RevokeJoinTokenData, RevokeJoinTokenResponse, RevokeProjectAccessData, RevokeProjectAccessResponse, RollbackPgUpgradeData, RollbackPgUpgradeResponse, RollbackToDeploymentData, RollbackToDeploymentResponse, RootfsGcData, RootfsReportData, RotateApiKeyData, RotateApiKeyResponse, RotateDeploymentTokenData, RotateDeploymentTokenResponse, RunBackupForSourceData, RunBackupForSourceError, RunBackupForSourceResponse, RunConnectionHealthCheckData, RunConnectionHealthCheckResponse, RunExternalServiceBackupData, RunExternalServiceBackupError, RunExternalServiceBackupResponse, RunScheduleNowData, RunScheduleNowError, RunScheduleNowResponse, SandboxCreatePreviewLinkData, SandboxCreatePreviewLinkResponse, SaveAgentTokenData, SaveAgentTokenResponse2, SaveAiProviderCredentialData, SaveAiProviderCredentialResponse, SearchLogsData, SearchLogsError, SearchLogsResponse2, SendEmailData, SendEmailResponse, SetDefaultS3SourceData, SetDefaultS3SourceError, SetDefaultS3SourceResponse, SetFlagEnvironmentData, SetFlagEnvironmentResponse, SetPreviewPasswordData, SetPreviewPasswordResponse2, SetupDnsChallengeData, SetupDnsChallengeResponse2, SetupDnsData, SetupDnsResponse2, SetupEmailTrackingData, SetupEmailTrackingResponse, SetupMfaData, SetupMfaResponse, SleepEnvironmentData, SleepEnvironmentResponse, SmokeTestAgentData, SmokeTestAgentResponse, SourceSandboxData, SourceSandboxResponse, StartAnalysisData, StartAnalysisResponse, StartContainerData, StartContainerResponse, StartFixData, StartGitProviderOauthData, StartOidcLoginBySlugData, StartPgUpgradeData, StartPgUpgradeResponse, StartRestoreData, StartRestoreError, StartRestoreResponse, StartServiceData, StartServiceResponse, StatPathData, StatPathResponse, StopContainerData, StopContainerResponse, StopSandboxData, StopSandboxResponse, StopServiceData, StopServiceResponse, StreamContainerMetricsData, SyncRepositoriesData, SyncRepositoriesResponse, TailDeploymentJobLogsData, TailLogsData, TailLogsError, TeardownDeploymentData, TeardownDeploymentResponse, TeardownEnvironmentData, TeardownEnvironmentResponse, TestNotificationProviderData, TestNotificationProviderResponse, TestOidcProviderData, TestOidcProviderResponse, TestProviderConnectionData, TestProviderConnectionResponse, TestProviderData, TestProviderKeyByIdData, TestProviderKeyByIdError, TestProviderKeyByIdResponse, TestProviderKeyInlineData, TestProviderKeyInlineError, TestProviderKeyInlineResponse, TestProviderResponse2, TestS3ConnectionPreviewData, TestS3ConnectionPreviewError, TestS3ConnectionPreviewResponse, TestS3SourceConnectionData, TestS3SourceConnectionError, TestS3SourceConnectionResponse, TrackClickData, TrackOpenData, TriggerAgentData, TriggerAgentResponse, TriggerProjectPipelineData, TriggerProjectPipelineResponse, TriggerScanData, TriggerScanError, TriggerScanResponse2, TriggerServiceHealthCheckData, TriggerServiceHealthCheckResponse, TriggerWeeklyDigestData, TriggerWeeklyDigestResponse, UnlinkServiceFromProjectData, UnlinkServiceFromProjectResponse, UpdateAgentData, UpdateAgentResponse, UpdateAiProviderData, UpdateAiProviderResponse2, UpdateAlertData, UpdateAlertError, UpdateAlertResponse, UpdateAlertRuleData, UpdateAlertRuleResponse, UpdateApiKeyData, UpdateApiKeyResponse, UpdateAutomaticDeployData, UpdateAutomaticDeployResponse, UpdateBackupScheduleData, UpdateBackupScheduleError, UpdateBackupScheduleResponse, UpdateCloudflareProviderData, UpdateCloudflareProviderResponse, UpdateConnectionTokenData, UpdateConnectionTokenResponse, UpdateCustomDomainData, UpdateCustomDomainResponse, UpdateDashboardData, UpdateDashboardError, UpdateDashboardResponse, UpdateDeploymentTokenData, UpdateDeploymentTokenResponse, UpdateEmailProviderData, UpdateEmailProviderResponse, UpdateEnvironmentSettingsData, UpdateEnvironmentSettingsResponse, UpdateEnvironmentSubdomainData, UpdateEnvironmentSubdomainResponse, UpdateEnvironmentVariableData, UpdateEnvironmentVariableResponse, UpdateErrorGroupData, UpdateFlagData, UpdateFlagResponse, UpdateFunnelData, UpdateGitProviderCredentialsData, UpdateGitProviderCredentialsResponse, UpdateGitSettingsData, UpdateGitSettingsResponse, UpdateGlobalMcpData, UpdateGlobalMcpResponse, UpdateGlobalSkillData, UpdateGlobalSkillResponse, UpdateIncidentStatusData, UpdateIncidentStatusResponse, UpdateIpAccessControlData, UpdateIpAccessControlError, UpdateIpAccessControlResponse, UpdateManagedDomainData, UpdateManagedDomainResponse, UpdateMcpData, UpdateMcpResponse, UpdateNotificationEmailProviderData, UpdateNotificationEmailProviderResponse, UpdateNotificationProviderData, UpdateNotificationProviderResponse, UpdateOidcProviderData, UpdateOidcProviderResponse, UpdatePreferencesData, UpdatePreferencesResponse, UpdateProjectData, UpdateProjectDeploymentConfigData, UpdateProjectDeploymentConfigResponse, UpdateProjectResponse, UpdateProjectSecretData, UpdateProjectSecretResponse, UpdateProjectSettingsData, UpdateProjectSettingsResponse, UpdateProviderData, UpdateProviderKeyData, UpdateProviderKeyError, UpdateProviderKeyResponse, UpdateProviderResponse, UpdateRouteData, UpdateRouteResponse, UpdateS3SourceData, UpdateS3SourceError, UpdateS3SourceResponse, UpdateSelfData, UpdateSelfResponse, UpdateServiceData, UpdateServiceResourcesData, UpdateServiceResourcesResponse, UpdateServiceResponse, UpdateSessionDurationData, UpdateSessionDurationError, UpdateSessionDurationResponse2, UpdateSettingsData, UpdateSettingsResponse, UpdateSkillData, UpdateSkillResponse, UpdateSlackProviderData, UpdateSlackProviderResponse, UpdateSpeedMetricsData, UpdateSpeedMetricsError, UpdateSpeedMetricsResponse, UpdateTeamData, UpdateTeamMemberRoleData, UpdateTeamMemberRoleResponse, UpdateTeamResponse, UpdateUserData, UpdateUserResponse, UpdateWebhookData, UpdateWebhookProviderData, UpdateWebhookProviderResponse, UpdateWebhookResponse, UpgradePreviewGatewayData, UpgradePreviewGatewayResponse, UpgradeServiceData, UpgradeServiceResponse, UploadGlobalSkillData, UploadGlobalSkillResponse, UploadReleaseFileData, UploadReleaseFileResponse, UploadSkillData, UploadSkillResponse, UploadSourceFileData, UploadSourceFileResponse, UploadSourceMapData, UploadSourceMapResponse, UploadStaticBundleData, UploadStaticBundleResponse, UpsertSecretData, UpsertSecretResponse, ValidateConnectionData, ValidateConnectionResponse, ValidateEmailData, ValidateEmailResponse2, VerifyAndEnableMfaData, VerifyAndEnableMfaResponse, VerifyDomainData, VerifyDomainResponse, VerifyEmailData, VerifyEmailResponse, VerifyManagedDomainData, VerifyManagedDomainResponse, VerifyMfaChallengeData, VerifyMfaChallengeResponse, VerifyStepUpData, VerifyStepUpResponse, WakeEnvironmentData, WakeEnvironmentResponse, WebhookTriggerData, WebhookTriggerResponse2, WorkflowDryRunData, WorkflowDryRunResponse, WriteFileData, WriteFileResponse, WriteFilesData, WriteFilesResponse2 } from '../types.gen'; +import { acknowledgeAlarm, activateAiProvider, activateApiKey, activateConnection, activateProvider, addClusterMember, addContext, addEnvironmentDomain, addEvents, addManagedDomain, addSessionReplayEvents, addTeamMember, adminDrainNode, adminDrainStatus, adminGetNode, adminListNodeContainers, adminListNodes, adminRemoveNode, adminUndrainNode, applyHostnameMode, archiveConversation, archiveFlag, assignRole, attachScheduleServices, blobCopy, blobDelete, blobDisable, blobDownload, blobEnable, blobList, blobPut, blobStatus, blobUpdate, cancel, cancelBackup, cancelDeployment, cancelDomainOrder, cancelPgUpgrade, cancelRun, cancelScheduleRun, changePasswordSelf, changeProjectSource, chatCompletions, checkAnalyticsHasEvents, checkCommitExists, checkDomainStatus, checkExplorerSupport, checkIpBlocked, checkProviderDeletionSafety, chunkUploadOptions, cleanupExpiredBackups, clearPreviewPassword, cliDeviceApprove, cliDeviceDeny, cliDeviceLookup, cliDevicePoll, cliDeviceStart, cliLogout, cmd, cmdKill, cmdLogs, confirmPendingAction, containerMetricsGetHistory, createAgent, createAlert, createAlertRule, createApiKey, createBackupSchedule, createBitbucketProvider, createCloudflareProvider, createConversation, createCustomDomain, createDashboard, createDeploymentToken, createDnsProvider, createDomain, createDsn, createEmailDomain, createEmailProvider, createEnvironment, createEnvironmentVariable, createFlag, createFunnel, createGenericProvider, createGiteaPatProvider, createGithubPatProvider, createGitlabOauthProvider, createGitlabPatProvider, createGitProvider, createGlobalMcp, createGlobalSkill, createIncident, createIpAccessControl, createMcp, createMonitor, createNotificationEmailProvider, createNotificationProvider, createOidcProvider, createOidcRoleMapping, createOrRecreateOrder, createPlan, createPr, createProject, createProjectFromTemplate, createProjectRelease, createProjectSecret, createProviderKey, createRelease, createRoute, createS3Source, createSandbox, createService, createSkill, createSlackProvider, createTeam, createUser, createWebhook, createWebhookProvider, deactivateApiKey, deactivateConnection, deactivateProvider, deleteAgent, deleteAlert, deleteAlertRule, deleteApiKey, deleteBackup, deleteBackupSchedule, deleteConnection, deleteCustomDomain, deleteDashboard, deleteDeploymentToken, deleteDnsProvider, deleteDomain, deleteEmailDomain, deleteEmailProvider, deleteEnvironment, deleteEnvironmentDomain, deleteEnvironmentVariable, deleteExternalImage, deleteFunnel, deleteGitProvider, deleteGlobalMcp, deleteGlobalSkill, deleteIpAccessControl, deleteMcp, deleteMonitor, deleteNotificationProvider, deleteOidcProvider, deleteOidcRoleMapping, deletePreferences, deleteProject, deleteProjectSecret, deleteProviderKey, deleteProviderSafely, deleteReleaseSourceFiles, deleteReleaseSourceMaps, deleteRoute, deleteS3Source, deleteScan, deleteSecret, deleteService, deleteSessionReplay, deleteSkill, deleteSourceMap, deleteStaticBundle, deleteTeam, deleteUser, deleteWebhook, deployFromImage, deployFromImageUpload, deployFromStatic, deployFromUploadedSource, deploymentMetricsGetLatest, deploymentMetricsGetRange, deploymentMetricsToggle, destroySandbox, detachScheduleService, detectPublicPresets, disableBackupSchedule, disableMfa, discoverWorkloads, domain, downloadGlobalSkillArchive, downloadObject, downloadSkillArchive, emailStatus, embeddings, enableBackupSchedule, enrichVisitor, exec, execDetached, executeDeploymentOperation, executeImport, extendTimeout, externalServiceEnablePgStatStatements, externalServiceMetricsByDatabase, externalServiceMetricsCreateAlertRule, externalServiceMetricsDeleteAlertRule, externalServiceMetricsGetAlertRules, externalServiceMetricsGetLatest, externalServiceMetricsGetRange, externalServiceMetricsStatus, externalServiceMetricsToggle, externalServiceMetricsUpdateAlertRule, externalServiceResetPgStatStatements, finalizeOrder, finalizeProjectRelease, findConversation, generateJoinToken, generatePresetDockerfile, getAccessInfo, getActiveVisitors, getActivityGraph, getAdminGate, getAgent, getAggregatedBuckets, getAiAgentBreakdown, getAiAgentPages, getAiAgentTimeline, getAiPageBreakdown, getAiStatusBreakdown, getAlert, getAlertRule, getAllRepositoriesByName, getAnalyticsActiveVisitors, getAnalyticsEventsCount, getAnalyticsSessionEvents, getAnalyticsVisitorSessions, getApiKey, getApiKeyPermissions, getAuditLog, getBackup, getBackupSchedule, getBranchesByRepositoryId, getBucketedIncidents, getBucketedStatus, getChallengeToken, getChatReadiness, getCliStatus, getClusterHealth, getClusterMember, getCmd, getContainerDetail, getContainerEnvironmentVariable, getContainerInfo, getContainerLogs, getContainerLogsById, getContainerMetrics, getConversation, getConversationDetail, getConversations, getCronById, getCronExecutions, getCrossProjectTraceSiblings, getCurrentMonitorStatus, getCurrentUser, getCustomDomain, getDashboard, getDashboardProjectsAnalytics, getDelivery, getDeployment, getDeploymentContainerLogContent, getDeploymentJobLogs, getDeploymentJobs, getDeploymentOperations, getDeploymentOperationStatus, getDeploymentToken, getDiskStatus, getDnsChanges, getDnsProvider, getDomain, getDomainByHost, getDomainById, getDomainByName, getDomainDnsRecords, getDomainOrder, getEmail, getEmailEvents, getEmailLinks, getEmailProvider, getEmailStats, getEmailTracking, getEmailTrackingStatus, getEntityInfo, getEnvironment, getEnvironmentCrons, getEnvironmentDomains, getEnvironments, getEnvironmentVariables, getEnvironmentVariableValue, getErrorDashboardStats, getErrorEvent, getErrorGroup, getErrorStats, getErrorTimeSeries, getEventDetail, getEventEntries, getEventsCount, getEventsTimeline, getEventTypeBreakdown, getEventVisitors, getExternalImage, getFile, getFlag, getFlagSnapshot, getFunnelMetrics, getGenaiTrace, getGeneralStats, getGitProvider, getGlobalEvents, getGlobalEventStats, getGlobalMcp, getGlobalSandboxStatus, getGlobalSkill, getGroupedPageMetrics, getHealth, getHourlyVisits, getHttpChallengeDebug, getImportStatus, getIncident, getIncidentUpdates, getIpAccessControl, getIpGeolocation, getJoinTokenStatus, getLastDeployment, getLatestScan, getLatestScansPerEnvironment, getLiveVisitorsList, getLogContext, getMcp, getMetricsOverTime, getMonitor, getNotificationProvider, getOnDemandCertStatus, getOrCreateDsn, getPageFlow, getPageHourlySessions, getPagePathDetail, getPagePaths, getPagePathsSparklines, getPagePathVisitors, getPendingAction, getPerformanceMetrics, getPgUpgrade, getPgUpgradeLogs, getPipelineStats, getPlatformInfo, getPostgresWalHealth, getPreferences, getPreviewGatewayLogs, getPreviewGatewaySettings, getPreviewGatewayStatus, getPricing, getPrivateIp, getProject, getProjectAlarmsSummary, getProjectBySlug, getProjectDeployments, getProjects, getProjectServiceEnvironmentVariables, getProjectSessionReplays, getProjectsHealth, getProjectsMonitorHealth, getProjectStatistics, getProjectTemplate, getPropertyBreakdown, getPropertyTimeline, getProviderConnections, getProviderMetadata, getProvidersMetadata, getProxyLogById, getProxyLogByRequestId, getProxyLogs, getPublicBranches, getPublicIp, getPublicRepository, getQuota, getRecentActivity, getRemoteExternalImage, getRepositoryBranches, getRepositoryById, getRepositoryByName, getRepositoryPresetByName, getRepositoryPresetLive, getRepositoryTags, getResolvedEnvironmentVariables, getResolvedEnvironmentVariableValue, getRestoreCapabilities, getRestoreRun, getRoute, getRun, getRunWithLogs, getS3Credentials, getS3Source, getSandbox, getSandboxStatus, getScan, getScanByDeployment, getScanVulnerabilities, getService, getServiceBySlug, getServiceEnvironmentVariable, getServiceEnvironmentVariables, getServiceHealthStatus, getServicePreviewEnvironmentVariableNames, getServicePreviewEnvironmentVariablesMasked, getServiceRuntime, getServiceStats, getServiceTypeParameters, getServiceTypes, getSessionDetails, getSessionEvents, getSessionLogs, getSessionReplay, getSessionReplayEvents, getSettings, getSkill, getSlowQueries, getStaticBundle, getStatusOverview, getTagsByRepositoryId, getTeam, getTimeBucketStats, getTodayStats, getTrace, getUnifiedTrace, getUniqueCounts, getUniqueEvents, getUpdateStatus, getUptimeHistory, getUsageByProvider, getUsageRecent, getUsageSummary, getUsageTimeseries, getUsageTopModels, getVisitorByGuid, getVisitorById, getVisitorDetails, getVisitorFacets, getVisitorInfo, getVisitorJourney, getVisitors, getVisitorSessions, getVisitorStats, getWebhook, grantProjectAccess, handleGitProviderOauthCallback, hasAnalyticsEvents, hasErrorGroups, hasPerformanceMetrics, importExternalService, ingestLogs, ingestLogsByPath, ingestMetrics, ingestMetricsByPath, ingestSentryEnvelope, ingestSentryEvent, ingestTraces, ingestTracesByPath, initSessionReplay, inspectDropArchive, jobLogs, jobStatus, killJob, kvDel, kvDisable, kvEnable, kvExpire, kvGet, kvIncr, kvKeys, kvSet, kvStatus, kvTtl, kvUpdate, latestRunForSource, linkCustomDomainToCertificate, linkServiceToProject, listAgentRuns, listAgents, listAiProviders, listAlertRules, listAlerts, listAllConversations, listAllRuns, listApiKeys, listAuditLogs, listAvailableContainers, listBackupAlerts, listBackupChildren, listBackupSchedules, listBackupsForSchedule, listCommitsByRepositoryId, listConnections, listContainers, listContainersAtPath, listConversations, listCustomDomainsForProject, listDashboards, listDeliveries, listDeploymentContainerLogs, listDeploymentTokens, listDnsProviders, listDomains, listDsns, listEmailDomains, listEmailProviders, listEmails, listEnrollmentTokens, listEntities, listErrorEvents, listErrorGroups, listEvents, listEventTypes, listExternalImages, listExternalPlugins, listExternalServiceBackups, listFlags, listFunnels, listGitProviders, listGlobalMcps, listGlobalSkills, listIncidents, listInsights, listIpAccessControl, listJobs, listKnownAiAgents, listManagedDomains, listMcps, listMetricLabelKeys, listMetricLabelValues, listMetricNames, listModels, listMonitors, listNotificationProviders, listOidcProviders, listOidcProviderUsers, listOidcRoleMappings, listOnDemandCerts, listOrders, listPeers, listPendingActions, listPgUpgrades, listPresets, listProjectAccess, listProjectAlarms, listProjectScans, listProjectSecrets, listProjectServices, listProjectTemplates, listProjectTemplateTags, listProviderKeys, listProviderZones, listPublicProviders, listReleaseFiles, listReleases, listRemoteExternalImages, listRepositoriesByConnection, listRepositoriesByProvider, listRestoreRunsForService, listRootContainers, listRoutes, listS3Sources, listSandboxes, listScheduleRunJobs, listScheduleRuns, listScheduleServices, listSecrets, listServiceHealthStatuses, listServiceProjects, listServices, listServiceSchedules, listSkills, listSourceBackups, listSourceFiles, listSourceMaps, listSources, listStaticBundles, listSyncedRepositories, listTeamMembers, listTeamProjects, listTeams, listUsers, listWebhooks, login, logout, lookupDnsARecords, mintEnrollmentToken, mkdir, nodeHeartbeat, nodeMetricsGetRange, observabilityFullEvent, observabilityListEvents, oidcCallback, type Options, patchAdminGate, patchPreviewGatewaySettings, pauseDeployment, pauseSandbox, planRestore, postDnsAck, previewAlert, previewFunnelMetrics, previewHostnameMode, promoteClusterMember, promoteDeployment, provisionDomain, purgeProjectLogs, pushExternalImage, queryData, queryGenaiTraces, queryLogs, queryMetrics, queryTraces, queryTraceSummaries, readFile, reAnalyze, recordConsoleEvent, recordEventMetrics, recordFlagExposure, recordSpeedMetrics, refreshRouteTable, regenerateDsn, registerExternalImage, registerNode, reinstallGitlabWebhook, rejectPendingAction, reloadPlugins, removeClusterMember, removeManagedDomain, removeRole, removeTeamMember, renameConversation, renewDomain, requestPasswordReset, resetPassword, resizeSandbox, resolveAlarm, restartContainer, restartPreviewGateway, restartSandbox, restoreFlag, restoreUser, resumeDeployment, resumeSandbox, retryCluster, retryDelivery, retryPgUpgrade, retryRun, revealGlobalMcpConfig, revealMcpConfig, revealNotificationProviderConfig, revealServiceParameter, revenueCreateIntegration, revenueDeleteIntegration, revenueGlobalEvents, revenueImportInvoicesCsv, revenueImportSubscriptionsCsv, revenueListIntegrations, revenueListProviders, revenueMetricsCustomers, revenueMetricsGlobalMrr, revenueMetricsGlobalSummary, revenueMetricsMrr, revenueMetricsSummary, revenueRecentEvents, revenueRotateToken, revenueUpdateConfig, revenueUpdateSecret, revokeDsn, revokeEnrollmentToken, revokeJoinToken, revokeProjectAccess, rollbackPgUpgrade, rollbackToDeployment, rootfsGc, rootfsReport, rotateApiKey, rotateDeploymentToken, runBackupForSource, runConnectionHealthCheck, runExternalServiceBackup, runScheduleNow, sandboxCreatePreviewLink, saveAgentToken, saveAiProviderCredential, searchLogs, sendEmail, setDefaultS3Source, setFlagEnvironment, setPreviewPassword, setupDns, setupDnsChallenge, setupEmailTracking, setupMfa, sleepEnvironment, smokeTestAgent, sourceSandbox, startAnalysis, startContainer, startFix, startGitProviderOauth, startOidcLoginBySlug, startPgUpgrade, startRestore, startService, statPath, stopContainer, stopSandbox, stopService, streamContainerMetrics, syncRepositories, tailDeploymentJobLogs, tailLogs, teardownDeployment, teardownEnvironment, testNotificationProvider, testOidcProvider, testProvider, testProviderConnection, testProviderKeyById, testProviderKeyInline, testS3ConnectionPreview, testS3SourceConnection, trackClick, trackOpen, triggerAgent, triggerProjectPipeline, triggerScan, triggerServiceHealthCheck, triggerWeeklyDigest, unlinkServiceFromProject, updateAgent, updateAiProvider, updateAlert, updateAlertRule, updateApiKey, updateAutomaticDeploy, updateBackupSchedule, updateCloudflareProvider, updateConnectionToken, updateCustomDomain, updateDashboard, updateDeploymentToken, updateEmailProvider, updateEnvironmentSettings, updateEnvironmentSubdomain, updateEnvironmentVariable, updateErrorGroup, updateFlag, updateFunnel, updateGitProviderCredentials, updateGitSettings, updateGlobalMcp, updateGlobalSkill, updateIncidentStatus, updateIpAccessControl, updateManagedDomain, updateMcp, updateNotificationEmailProvider, updateNotificationProvider, updateOidcProvider, updatePreferences, updateProject, updateProjectDeploymentConfig, updateProjectSecret, updateProjectSettings, updateProvider, updateProviderKey, updateRoute, updateS3Source, updateSelf, updateService, updateServiceResources, updateSessionDuration, updateSettings, updateSkill, updateSlackProvider, updateSpeedMetrics, updateTeam, updateTeamMemberRole, updateUser, updateWebhook, updateWebhookProvider, upgradePreviewGateway, upgradeService, uploadGlobalSkill, uploadReleaseFile, uploadSkill, uploadSourceFile, uploadSourceMap, uploadStaticBundle, upsertSecret, validateConnection, validateEmail, verifyAndEnableMfa, verifyDomain, verifyEmail, verifyManagedDomain, verifyMfaChallenge, verifyStepUp, wakeEnvironment, webhookTrigger, workflowDryRun, writeFile, writeFiles } from '../sdk.gen'; +import type { AcknowledgeAlarmData, ActivateAiProviderData, ActivateAiProviderResponse, ActivateApiKeyData, ActivateApiKeyResponse, ActivateConnectionData, ActivateProviderData, AddClusterMemberData, AddClusterMemberResponse, AddContextData, AddEnvironmentDomainData, AddEnvironmentDomainResponse, AddEventsData, AddEventsError, AddEventsResponse2, AddManagedDomainData, AddManagedDomainResponse, AddSessionReplayEventsData, AddSessionReplayEventsError, AddSessionReplayEventsResponse, AddTeamMemberData, AddTeamMemberResponse, AdminDrainNodeData, AdminDrainNodeResponse, AdminDrainStatusData, AdminDrainStatusResponse, AdminGetNodeData, AdminGetNodeResponse, AdminListNodeContainersData, AdminListNodeContainersResponse, AdminListNodesData, AdminListNodesResponse, AdminRemoveNodeData, AdminRemoveNodeResponse, AdminUndrainNodeData, AdminUndrainNodeResponse, ApplyHostnameModeData, ApplyHostnameModeResponse, ArchiveConversationData, ArchiveConversationResponse, ArchiveFlagData, ArchiveFlagResponse2, AssignRoleData, AttachScheduleServicesData, AttachScheduleServicesError, AttachScheduleServicesResponse2, BlobCopyData, BlobCopyError, BlobCopyResponse, BlobDeleteData, BlobDeleteError, BlobDeleteResponse, BlobDisableData, BlobDisableResponse, BlobDownloadData, BlobDownloadError, BlobEnableData, BlobEnableResponse, BlobListData, BlobListError, BlobListResponse, BlobPutData, BlobPutError, BlobPutResponse, BlobStatusData, BlobStatusResponse2, BlobUpdateData, BlobUpdateResponse, CancelBackupData, CancelBackupError, CancelBackupResponse2, CancelData, CancelDeploymentData, CancelDeploymentResponse, CancelDomainOrderData, CancelDomainOrderResponse, CancelPgUpgradeData, CancelPgUpgradeResponse, CancelRunData, CancelRunResponse, CancelScheduleRunData, CancelScheduleRunError, CancelScheduleRunResponse, ChangePasswordSelfData, ChangePasswordSelfResponse, ChangeProjectSourceData, ChangeProjectSourceResponse, ChatCompletionsData, ChatCompletionsError, ChatCompletionsResponse, CheckAnalyticsHasEventsData, CheckAnalyticsHasEventsResponse, CheckCommitExistsData, CheckCommitExistsResponse, CheckDomainStatusData, CheckDomainStatusResponse, CheckExplorerSupportData, CheckExplorerSupportResponse, CheckIpBlockedData, CheckIpBlockedError, CheckProviderDeletionSafetyData, CheckProviderDeletionSafetyResponse, ChunkUploadOptionsData, ChunkUploadOptionsResponse, CleanupExpiredBackupsData, CleanupExpiredBackupsError, CleanupExpiredBackupsResponse, ClearPreviewPasswordData, ClearPreviewPasswordResponse, CliDeviceApproveData, CliDeviceApproveResponse2, CliDeviceDenyData, CliDeviceDenyResponse, CliDeviceLookupData, CliDeviceLookupResponse2, CliDevicePollData, CliDevicePollResponse2, CliDeviceStartData, CliDeviceStartResponse2, CliLogoutData, CliLogoutResponse, CmdData, CmdKillData, CmdKillResponse, CmdLogsData, CmdResponse2, ConfirmPendingActionData, ConfirmPendingActionResponse, ContainerMetricsGetHistoryData, ContainerMetricsGetHistoryResponse, CreateAgentData, CreateAgentResponse, CreateAlertData, CreateAlertError, CreateAlertResponse, CreateAlertRuleData, CreateAlertRuleResponse, CreateApiKeyData, CreateApiKeyResponse2, CreateBackupScheduleData, CreateBackupScheduleError, CreateBackupScheduleResponse, CreateBitbucketProviderData, CreateBitbucketProviderResponse, CreateCloudflareProviderData, CreateCloudflareProviderResponse, CreateConversationData, CreateConversationResponse, CreateCustomDomainData, CreateCustomDomainResponse, CreateDashboardData, CreateDashboardError, CreateDashboardResponse, CreateDeploymentTokenData, CreateDeploymentTokenResponse2, CreateDnsProviderData, CreateDnsProviderResponse, CreateDomainData, CreateDomainResponse, CreateDsnData, CreateDsnResponse, CreateEmailDomainData, CreateEmailDomainResponse, CreateEmailProviderData, CreateEmailProviderResponse, CreateEnvironmentData, CreateEnvironmentResponse, CreateEnvironmentVariableData, CreateEnvironmentVariableResponse, CreateFlagData, CreateFlagResponse, CreateFunnelData, CreateFunnelResponse2, CreateGenericProviderData, CreateGenericProviderResponse, CreateGiteaPatProviderData, CreateGiteaPatProviderResponse, CreateGithubPatProviderData, CreateGithubPatProviderResponse, CreateGitlabOauthProviderData, CreateGitlabOauthProviderResponse, CreateGitlabPatProviderData, CreateGitlabPatProviderResponse, CreateGitProviderData, CreateGitProviderResponse, CreateGlobalMcpData, CreateGlobalMcpResponse, CreateGlobalSkillData, CreateGlobalSkillResponse, CreateIncidentData, CreateIncidentResponse, CreateIpAccessControlData, CreateIpAccessControlError, CreateIpAccessControlResponse, CreateMcpData, CreateMcpResponse, CreateMonitorData, CreateMonitorResponse, CreateNotificationEmailProviderData, CreateNotificationEmailProviderResponse, CreateNotificationProviderData, CreateNotificationProviderResponse, CreateOidcProviderData, CreateOidcProviderResponse, CreateOidcRoleMappingData, CreateOidcRoleMappingResponse, CreateOrRecreateOrderData, CreateOrRecreateOrderResponse, CreatePlanData, CreatePlanResponse2, CreatePrData, CreateProjectData, CreateProjectFromTemplateData, CreateProjectFromTemplateResponse2, CreateProjectReleaseData, CreateProjectReleaseResponse, CreateProjectResponse, CreateProjectSecretData, CreateProjectSecretResponse, CreateProviderKeyData, CreateProviderKeyError, CreateProviderKeyResponse, CreatePrResponse2, CreateReleaseData, CreateReleaseResponse, CreateRouteData, CreateRouteResponse, CreateS3SourceData, CreateS3SourceError, CreateS3SourceResponse, CreateSandboxData, CreateSandboxResponse, CreateServiceData, CreateServiceResponse, CreateSkillData, CreateSkillResponse, CreateSlackProviderData, CreateSlackProviderResponse, CreateTeamData, CreateTeamResponse, CreateUserData, CreateUserResponse, CreateWebhookData, CreateWebhookProviderData, CreateWebhookProviderResponse, CreateWebhookResponse, DeactivateApiKeyData, DeactivateApiKeyResponse, DeactivateConnectionData, DeactivateProviderData, DeleteAgentData, DeleteAgentResponse, DeleteAlertData, DeleteAlertError, DeleteAlertResponse, DeleteAlertRuleData, DeleteAlertRuleResponse, DeleteApiKeyData, DeleteApiKeyResponse, DeleteBackupData, DeleteBackupError, DeleteBackupResponse, DeleteBackupScheduleData, DeleteBackupScheduleError, DeleteBackupScheduleResponse, DeleteConnectionData, DeleteConnectionResponse, DeleteCustomDomainData, DeleteCustomDomainResponse, DeleteDashboardData, DeleteDashboardError, DeleteDashboardResponse, DeleteDeploymentTokenData, DeleteDeploymentTokenResponse, DeleteDnsProviderData, DeleteDnsProviderResponse, DeleteDomainData, DeleteDomainResponse, DeleteEmailDomainData, DeleteEmailDomainResponse, DeleteEmailProviderData, DeleteEmailProviderResponse, DeleteEnvironmentData, DeleteEnvironmentDomainData, DeleteEnvironmentDomainResponse, DeleteEnvironmentResponse, DeleteEnvironmentVariableData, DeleteEnvironmentVariableResponse, DeleteExternalImageData, DeleteExternalImageResponse, DeleteFunnelData, DeleteGitProviderData, DeleteGitProviderResponse, DeleteGlobalMcpData, DeleteGlobalMcpResponse, DeleteGlobalSkillData, DeleteGlobalSkillResponse, DeleteIpAccessControlData, DeleteIpAccessControlError, DeleteIpAccessControlResponse, DeleteMcpData, DeleteMcpResponse, DeleteMonitorData, DeleteMonitorResponse, DeleteNotificationProviderData, DeleteNotificationProviderResponse, DeleteOidcProviderData, DeleteOidcProviderResponse, DeleteOidcRoleMappingData, DeleteOidcRoleMappingResponse, DeletePreferencesData, DeletePreferencesResponse, DeleteProjectData, DeleteProjectResponse, DeleteProjectSecretData, DeleteProjectSecretResponse, DeleteProviderKeyData, DeleteProviderKeyError, DeleteProviderKeyResponse, DeleteProviderSafelyData, DeleteProviderSafelyResponse, DeleteReleaseSourceFilesData, DeleteReleaseSourceFilesResponse, DeleteReleaseSourceMapsData, DeleteReleaseSourceMapsResponse, DeleteRouteData, DeleteRouteResponse, DeleteS3SourceData, DeleteS3SourceError, DeleteS3SourceResponse, DeleteScanData, DeleteScanError, DeleteScanResponse, DeleteSecretData, DeleteSecretResponse, DeleteServiceData, DeleteServiceResponse, DeleteSessionReplayData, DeleteSessionReplayError, DeleteSkillData, DeleteSkillResponse, DeleteSourceMapData, DeleteSourceMapResponse, DeleteStaticBundleData, DeleteStaticBundleResponse, DeleteTeamData, DeleteTeamResponse, DeleteUserData, DeleteUserResponse, DeleteWebhookData, DeleteWebhookResponse, DeployFromImageData, DeployFromImageResponse, DeployFromImageUploadData, DeployFromImageUploadResponse, DeployFromStaticData, DeployFromStaticResponse, DeployFromUploadedSourceData, DeployFromUploadedSourceResponse, DeploymentMetricsGetLatestData, DeploymentMetricsGetLatestResponse, DeploymentMetricsGetRangeData, DeploymentMetricsGetRangeResponse, DeploymentMetricsToggleData, DestroySandboxData, DestroySandboxResponse, DetachScheduleServiceData, DetachScheduleServiceError, DetachScheduleServiceResponse, DetectPublicPresetsData, DetectPublicPresetsResponse, DisableBackupScheduleData, DisableBackupScheduleResponse, DisableMfaData, DisableMfaResponse, DiscoverWorkloadsData, DiscoverWorkloadsResponse, DomainData, DomainResponse2, DownloadGlobalSkillArchiveData, DownloadGlobalSkillArchiveResponse, DownloadObjectData, DownloadObjectResponse, DownloadSkillArchiveData, DownloadSkillArchiveResponse, EmailStatusData, EmailStatusResponse2, EmbeddingsData, EmbeddingsError, EmbeddingsResponse, EnableBackupScheduleData, EnableBackupScheduleResponse, EnrichVisitorData, EnrichVisitorResponse2, ExecData, ExecDetachedData, ExecDetachedResponse2, ExecResponse2, ExecuteDeploymentOperationData, ExecuteDeploymentOperationResponse, ExecuteImportData, ExecuteImportResponse2, ExtendTimeoutData, ExtendTimeoutResponse, ExternalServiceEnablePgStatStatementsData, ExternalServiceEnablePgStatStatementsResponse, ExternalServiceMetricsByDatabaseData, ExternalServiceMetricsByDatabaseResponse, ExternalServiceMetricsCreateAlertRuleData, ExternalServiceMetricsCreateAlertRuleResponse, ExternalServiceMetricsDeleteAlertRuleData, ExternalServiceMetricsDeleteAlertRuleResponse, ExternalServiceMetricsGetAlertRulesData, ExternalServiceMetricsGetAlertRulesResponse, ExternalServiceMetricsGetLatestData, ExternalServiceMetricsGetLatestResponse, ExternalServiceMetricsGetRangeData, ExternalServiceMetricsGetRangeResponse, ExternalServiceMetricsStatusData, ExternalServiceMetricsStatusResponse, ExternalServiceMetricsToggleData, ExternalServiceMetricsUpdateAlertRuleData, ExternalServiceMetricsUpdateAlertRuleResponse, ExternalServiceResetPgStatStatementsData, ExternalServiceResetPgStatStatementsResponse, FinalizeOrderData, FinalizeOrderResponse, FinalizeProjectReleaseData, FinalizeProjectReleaseResponse, FindConversationData, FindConversationResponse, GenerateJoinTokenData, GenerateJoinTokenResponse2, GeneratePresetDockerfileData, GeneratePresetDockerfileResponse, GetAccessInfoData, GetAccessInfoResponse, GetActiveVisitorsData, GetActiveVisitorsResponse, GetActivityGraphData, GetActivityGraphResponse, GetAdminGateData, GetAdminGateResponse, GetAgentData, GetAgentResponse, GetAggregatedBucketsData, GetAggregatedBucketsResponse, GetAiAgentBreakdownData, GetAiAgentBreakdownError, GetAiAgentBreakdownResponse, GetAiAgentPagesData, GetAiAgentPagesError, GetAiAgentPagesResponse, GetAiAgentTimelineData, GetAiAgentTimelineError, GetAiAgentTimelineResponse, GetAiPageBreakdownData, GetAiPageBreakdownError, GetAiPageBreakdownResponse, GetAiStatusBreakdownData, GetAiStatusBreakdownError, GetAiStatusBreakdownResponse, GetAlertData, GetAlertError, GetAlertResponse, GetAlertRuleData, GetAlertRuleResponse, GetAllRepositoriesByNameData, GetAllRepositoriesByNameResponse, GetAnalyticsActiveVisitorsData, GetAnalyticsActiveVisitorsResponse, GetAnalyticsEventsCountData, GetAnalyticsEventsCountResponse, GetAnalyticsSessionEventsData, GetAnalyticsSessionEventsResponse, GetAnalyticsVisitorSessionsData, GetAnalyticsVisitorSessionsResponse, GetApiKeyData, GetApiKeyPermissionsData, GetApiKeyPermissionsResponse, GetApiKeyResponse, GetAuditLogData, GetAuditLogResponse, GetBackupData, GetBackupError, GetBackupResponse, GetBackupScheduleData, GetBackupScheduleResponse, GetBranchesByRepositoryIdData, GetBranchesByRepositoryIdResponse, GetBucketedIncidentsData, GetBucketedIncidentsResponse, GetBucketedStatusData, GetBucketedStatusResponse, GetChallengeTokenData, GetChallengeTokenResponse, GetChatReadinessData, GetChatReadinessResponse, GetCliStatusData, GetClusterHealthData, GetClusterHealthResponse, GetClusterMemberData, GetClusterMemberResponse, GetCmdData, GetCmdResponse, GetContainerDetailData, GetContainerDetailResponse, GetContainerEnvironmentVariableData, GetContainerEnvironmentVariableResponse, GetContainerInfoData, GetContainerInfoResponse, GetContainerLogsByIdData, GetContainerLogsData, GetContainerMetricsData, GetContainerMetricsResponse, GetConversationData, GetConversationDetailData, GetConversationDetailError, GetConversationDetailResponse, GetConversationResponse, GetConversationsData, GetConversationsError, GetConversationsResponse, GetCronByIdData, GetCronByIdResponse, GetCronExecutionsData, GetCronExecutionsResponse, GetCrossProjectTraceSiblingsData, GetCrossProjectTraceSiblingsError, GetCrossProjectTraceSiblingsResponse, GetCurrentMonitorStatusData, GetCurrentMonitorStatusResponse, GetCurrentUserData, GetCurrentUserResponse, GetCustomDomainData, GetCustomDomainResponse, GetDashboardData, GetDashboardError, GetDashboardProjectsAnalyticsData, GetDashboardProjectsAnalyticsResponse, GetDashboardResponse, GetDeliveryData, GetDeliveryResponse, GetDeploymentContainerLogContentData, GetDeploymentContainerLogContentResponse, GetDeploymentData, GetDeploymentJobLogsData, GetDeploymentJobLogsResponse, GetDeploymentJobsData, GetDeploymentJobsResponse, GetDeploymentOperationsData, GetDeploymentOperationsResponse, GetDeploymentOperationStatusData, GetDeploymentOperationStatusResponse, GetDeploymentResponse, GetDeploymentTokenData, GetDeploymentTokenResponse, GetDiskStatusData, GetDiskStatusResponse, GetDnsChangesData, GetDnsChangesResponse, GetDnsProviderData, GetDnsProviderResponse, GetDomainByHostData, GetDomainByHostResponse, GetDomainByIdData, GetDomainByIdResponse, GetDomainByNameData, GetDomainByNameResponse, GetDomainData, GetDomainDnsRecordsData, GetDomainDnsRecordsResponse, GetDomainOrderData, GetDomainOrderResponse, GetDomainResponse, GetEmailData, GetEmailEventsData, GetEmailEventsResponse, GetEmailLinksData, GetEmailLinksResponse, GetEmailProviderData, GetEmailProviderResponse, GetEmailResponse, GetEmailStatsData, GetEmailStatsResponse, GetEmailTrackingData, GetEmailTrackingResponse, GetEmailTrackingStatusData, GetEmailTrackingStatusResponse, GetEntityInfoData, GetEntityInfoResponse, GetEnvironmentCronsData, GetEnvironmentCronsResponse, GetEnvironmentData, GetEnvironmentDomainsData, GetEnvironmentDomainsResponse, GetEnvironmentResponse, GetEnvironmentsData, GetEnvironmentsResponse, GetEnvironmentVariablesData, GetEnvironmentVariablesResponse, GetEnvironmentVariableValueData, GetEnvironmentVariableValueResponse, GetErrorDashboardStatsData, GetErrorDashboardStatsResponse, GetErrorEventData, GetErrorEventResponse, GetErrorGroupData, GetErrorGroupResponse, GetErrorStatsData, GetErrorStatsResponse, GetErrorTimeSeriesData, GetErrorTimeSeriesResponse, GetEventDetailData, GetEventDetailResponse, GetEventEntriesData, GetEventEntriesResponse, GetEventsCountData, GetEventsCountResponse, GetEventsTimelineData, GetEventsTimelineResponse, GetEventTypeBreakdownData, GetEventTypeBreakdownResponse, GetEventVisitorsData, GetEventVisitorsResponse, GetExternalImageData, GetExternalImageResponse, GetFileData, GetFileResponse, GetFlagData, GetFlagResponse, GetFlagSnapshotData, GetFlagSnapshotResponse, GetFunnelMetricsData, GetFunnelMetricsResponse, GetGenaiTraceData, GetGenaiTraceError, GetGenaiTraceResponse, GetGeneralStatsData, GetGeneralStatsResponse, GetGitProviderData, GetGitProviderResponse, GetGlobalEventsData, GetGlobalEventsResponse, GetGlobalEventStatsData, GetGlobalEventStatsResponse, GetGlobalMcpData, GetGlobalMcpResponse, GetGlobalSandboxStatusData, GetGlobalSandboxStatusResponse, GetGlobalSkillData, GetGlobalSkillResponse, GetGroupedPageMetricsData, GetGroupedPageMetricsError, GetGroupedPageMetricsResponse, GetHealthData, GetHealthError, GetHealthResponse, GetHourlyVisitsData, GetHourlyVisitsResponse, GetHttpChallengeDebugData, GetHttpChallengeDebugResponse, GetImportStatusData, GetImportStatusResponse, GetIncidentData, GetIncidentResponse, GetIncidentUpdatesData, GetIncidentUpdatesResponse, GetIpAccessControlData, GetIpAccessControlError, GetIpAccessControlResponse, GetIpGeolocationData, GetIpGeolocationError, GetIpGeolocationResponse, GetJoinTokenStatusData, GetJoinTokenStatusResponse, GetLastDeploymentData, GetLastDeploymentResponse, GetLatestScanData, GetLatestScanError, GetLatestScanResponse, GetLatestScansPerEnvironmentData, GetLatestScansPerEnvironmentError, GetLatestScansPerEnvironmentResponse, GetLiveVisitorsListData, GetLiveVisitorsListResponse, GetLogContextData, GetLogContextError, GetLogContextResponse, GetMcpData, GetMcpResponse, GetMetricsOverTimeData, GetMetricsOverTimeError, GetMetricsOverTimeResponse, GetMonitorData, GetMonitorResponse, GetNotificationProviderData, GetNotificationProviderResponse, GetOnDemandCertStatusData, GetOnDemandCertStatusResponse, GetOrCreateDsnData, GetOrCreateDsnResponse, GetPageFlowData, GetPageFlowResponse, GetPageHourlySessionsData, GetPageHourlySessionsResponse, GetPagePathDetailData, GetPagePathDetailResponse, GetPagePathsData, GetPagePathsResponse, GetPagePathsSparklinesData, GetPagePathsSparklinesResponse, GetPagePathVisitorsData, GetPagePathVisitorsResponse, GetPendingActionData, GetPendingActionResponse, GetPerformanceMetricsData, GetPerformanceMetricsError, GetPerformanceMetricsResponse, GetPgUpgradeData, GetPgUpgradeLogsData, GetPgUpgradeLogsResponse, GetPgUpgradeResponse, GetPipelineStatsData, GetPipelineStatsError, GetPipelineStatsResponse, GetPlatformInfoData, GetPlatformInfoResponse, GetPostgresWalHealthData, GetPostgresWalHealthResponse, GetPreferencesData, GetPreferencesResponse, GetPreviewGatewayLogsData, GetPreviewGatewayLogsResponse, GetPreviewGatewaySettingsData, GetPreviewGatewaySettingsResponse, GetPreviewGatewayStatusData, GetPreviewGatewayStatusResponse, GetPricingData, GetPricingError, GetPricingResponse, GetPrivateIpData, GetProjectAlarmsSummaryData, GetProjectAlarmsSummaryResponse, GetProjectBySlugData, GetProjectBySlugResponse, GetProjectData, GetProjectDeploymentsData, GetProjectDeploymentsResponse, GetProjectResponse, GetProjectsData, GetProjectServiceEnvironmentVariablesData, GetProjectServiceEnvironmentVariablesResponse, GetProjectSessionReplaysData, GetProjectSessionReplaysError, GetProjectSessionReplaysResponse2, GetProjectsHealthData, GetProjectsHealthError, GetProjectsHealthResponse, GetProjectsMonitorHealthData, GetProjectsMonitorHealthResponse, GetProjectsResponse, GetProjectStatisticsData, GetProjectStatisticsResponse, GetProjectTemplateData, GetProjectTemplateResponse, GetPropertyBreakdownData, GetPropertyBreakdownResponse, GetPropertyTimelineData, GetPropertyTimelineResponse, GetProviderConnectionsData, GetProviderConnectionsResponse, GetProviderMetadataData, GetProviderMetadataResponse, GetProvidersMetadataData, GetProvidersMetadataResponse, GetProxyLogByIdData, GetProxyLogByIdError, GetProxyLogByIdResponse, GetProxyLogByRequestIdData, GetProxyLogByRequestIdError, GetProxyLogByRequestIdResponse, GetProxyLogsData, GetProxyLogsError, GetProxyLogsResponse, GetPublicBranchesData, GetPublicBranchesResponse, GetPublicIpData, GetPublicRepositoryData, GetPublicRepositoryResponse, GetQuotaData, GetQuotaError, GetQuotaResponse, GetRecentActivityData, GetRecentActivityResponse, GetRemoteExternalImageData, GetRemoteExternalImageResponse, GetRepositoryBranchesData, GetRepositoryBranchesResponse, GetRepositoryByIdData, GetRepositoryByIdResponse, GetRepositoryByNameData, GetRepositoryByNameResponse, GetRepositoryPresetByNameData, GetRepositoryPresetByNameResponse, GetRepositoryPresetLiveData, GetRepositoryPresetLiveResponse, GetRepositoryTagsData, GetRepositoryTagsResponse, GetResolvedEnvironmentVariablesData, GetResolvedEnvironmentVariablesResponse, GetResolvedEnvironmentVariableValueData, GetResolvedEnvironmentVariableValueResponse, GetRestoreCapabilitiesData, GetRestoreCapabilitiesError, GetRestoreCapabilitiesResponse, GetRestoreRunData, GetRestoreRunError, GetRestoreRunResponse, GetRouteData, GetRouteResponse, GetRunData, GetRunResponse, GetRunWithLogsData, GetRunWithLogsResponse, GetS3CredentialsData, GetS3CredentialsResponse, GetS3SourceData, GetS3SourceError, GetS3SourceResponse, GetSandboxData, GetSandboxResponse, GetSandboxStatusData, GetSandboxStatusResponse, GetScanByDeploymentData, GetScanByDeploymentError, GetScanByDeploymentResponse, GetScanData, GetScanError, GetScanResponse, GetScanVulnerabilitiesData, GetScanVulnerabilitiesError, GetScanVulnerabilitiesResponse, GetServiceBySlugData, GetServiceBySlugResponse, GetServiceData, GetServiceEnvironmentVariableData, GetServiceEnvironmentVariableResponse, GetServiceEnvironmentVariablesData, GetServiceEnvironmentVariablesResponse, GetServiceHealthStatusData, GetServiceHealthStatusResponse, GetServicePreviewEnvironmentVariableNamesData, GetServicePreviewEnvironmentVariableNamesResponse, GetServicePreviewEnvironmentVariablesMaskedData, GetServicePreviewEnvironmentVariablesMaskedResponse, GetServiceResponse, GetServiceRuntimeData, GetServiceRuntimeResponse, GetServiceStatsData, GetServiceStatsResponse, GetServiceTypeParametersData, GetServiceTypesData, GetServiceTypesResponse, GetSessionDetailsData, GetSessionDetailsResponse, GetSessionEventsData, GetSessionEventsResponse, GetSessionLogsData, GetSessionLogsResponse, GetSessionReplayData, GetSessionReplayError, GetSessionReplayEventsData, GetSessionReplayEventsError, GetSessionReplayEventsResponse, GetSessionReplayResponse2, GetSettingsData, GetSettingsResponse, GetSkillData, GetSkillResponse, GetSlowQueriesData, GetSlowQueriesResponse, GetStaticBundleData, GetStaticBundleResponse, GetStatusOverviewData, GetStatusOverviewResponse, GetTagsByRepositoryIdData, GetTagsByRepositoryIdResponse, GetTeamData, GetTeamResponse, GetTimeBucketStatsData, GetTimeBucketStatsError, GetTimeBucketStatsResponse, GetTodayStatsData, GetTodayStatsError, GetTodayStatsResponse, GetTraceData, GetTraceError, GetTraceResponse, GetUnifiedTraceData, GetUnifiedTraceError, GetUnifiedTraceResponse, GetUniqueCountsData, GetUniqueCountsResponse, GetUniqueEventsData, GetUniqueEventsResponse, GetUpdateStatusData, GetUpdateStatusResponse, GetUptimeHistoryData, GetUptimeHistoryResponse, GetUsageByProviderData, GetUsageByProviderError, GetUsageByProviderResponse, GetUsageRecentData, GetUsageRecentError, GetUsageRecentResponse, GetUsageSummaryData, GetUsageSummaryError, GetUsageSummaryResponse, GetUsageTimeseriesData, GetUsageTimeseriesError, GetUsageTimeseriesResponse, GetUsageTopModelsData, GetUsageTopModelsError, GetUsageTopModelsResponse, GetVisitorByGuidData, GetVisitorByGuidResponse, GetVisitorByIdData, GetVisitorByIdResponse, GetVisitorDetailsData, GetVisitorDetailsResponse, GetVisitorFacetsData, GetVisitorFacetsResponse, GetVisitorInfoData, GetVisitorInfoResponse, GetVisitorJourneyData, GetVisitorJourneyResponse, GetVisitorsData, GetVisitorSessionsData, GetVisitorSessionsError, GetVisitorSessionsResponse2, GetVisitorsResponse, GetVisitorStatsData, GetVisitorStatsResponse, GetWebhookData, GetWebhookResponse, GrantProjectAccessData, GrantProjectAccessResponse, HandleGitProviderOauthCallbackData, HasAnalyticsEventsData, HasAnalyticsEventsResponse2, HasErrorGroupsData, HasErrorGroupsResponse2, HasPerformanceMetricsData, HasPerformanceMetricsError, HasPerformanceMetricsResponse, ImportExternalServiceData, ImportExternalServiceResponse, IngestLogsByPathData, IngestLogsByPathError, IngestLogsData, IngestLogsError, IngestMetricsByPathData, IngestMetricsByPathError, IngestMetricsData, IngestMetricsError, IngestSentryEnvelopeData, IngestSentryEventData, IngestSentryEventResponse, IngestTracesByPathData, IngestTracesByPathError, IngestTracesData, IngestTracesError, InitSessionReplayData, InitSessionReplayError, InitSessionReplayResponse, InspectDropArchiveData, InspectDropArchiveResponse, JobLogsData, JobStatusData, JobStatusResponse2, KillJobData, KillJobResponse, KvDelData, KvDelResponse, KvDisableData, KvDisableResponse, KvEnableData, KvEnableResponse, KvExpireData, KvExpireResponse, KvGetData, KvGetResponse, KvIncrData, KvIncrResponse, KvKeysData, KvKeysResponse, KvSetData, KvSetResponse, KvStatusData, KvStatusResponse2, KvTtlData, KvTtlResponse, KvUpdateData, KvUpdateResponse, LatestRunForSourceData, LatestRunForSourceResponse, LinkCustomDomainToCertificateData, LinkCustomDomainToCertificateResponse, LinkServiceToProjectData, LinkServiceToProjectResponse, ListAgentRunsData, ListAgentRunsResponse, ListAgentsData, ListAgentsResponse2, ListAiProvidersData, ListAiProvidersResponse, ListAlertRulesData, ListAlertRulesResponse, ListAlertsData, ListAlertsError, ListAlertsResponse, ListAllConversationsData, ListAllConversationsResponse, ListAllRunsData, ListAllRunsResponse, ListApiKeysData, ListApiKeysResponse, ListAuditLogsData, ListAuditLogsResponse, ListAvailableContainersData, ListAvailableContainersResponse, ListBackupAlertsData, ListBackupAlertsError, ListBackupAlertsResponse, ListBackupChildrenData, ListBackupChildrenError, ListBackupChildrenResponse, ListBackupSchedulesData, ListBackupSchedulesError, ListBackupSchedulesResponse, ListBackupsForScheduleData, ListBackupsForScheduleResponse, ListCommitsByRepositoryIdData, ListCommitsByRepositoryIdResponse, ListConnectionsData, ListConnectionsResponse, ListContainersAtPathData, ListContainersAtPathResponse, ListContainersData, ListContainersResponse, ListConversationsData, ListConversationsResponse, ListCustomDomainsForProjectData, ListCustomDomainsForProjectResponse, ListDashboardsData, ListDashboardsError, ListDashboardsResponse, ListDeliveriesData, ListDeliveriesResponse, ListDeploymentContainerLogsData, ListDeploymentContainerLogsResponse, ListDeploymentTokensData, ListDeploymentTokensResponse, ListDnsProvidersData, ListDnsProvidersResponse, ListDomainsData, ListDomainsResponse2, ListDsnsData, ListDsnsResponse, ListEmailDomainsData, ListEmailDomainsResponse, ListEmailProvidersData, ListEmailProvidersResponse, ListEmailsData, ListEmailsResponse, ListEnrollmentTokensData, ListEnrollmentTokensResponse, ListEntitiesData, ListEntitiesResponse, ListErrorEventsData, ListErrorEventsResponse, ListErrorGroupsData, ListErrorGroupsResponse, ListEventsData, ListEventsResponse, ListEventTypesData, ListEventTypesResponse, ListExternalImagesData, ListExternalImagesResponse, ListExternalPluginsData, ListExternalPluginsResponse, ListExternalServiceBackupsData, ListExternalServiceBackupsError, ListExternalServiceBackupsResponse, ListFlagsData, ListFlagsResponse, ListFunnelsData, ListFunnelsResponse, ListGitProvidersData, ListGitProvidersResponse, ListGlobalMcpsData, ListGlobalMcpsResponse, ListGlobalSkillsData, ListGlobalSkillsResponse, ListIncidentsData, ListInsightsData, ListInsightsError, ListInsightsResponse, ListIpAccessControlData, ListIpAccessControlError, ListIpAccessControlResponse, ListJobsData, ListJobsResponse2, ListKnownAiAgentsData, ListKnownAiAgentsError, ListKnownAiAgentsResponse, ListManagedDomainsData, ListManagedDomainsResponse, ListMcpsData, ListMcpsResponse2, ListMetricLabelKeysData, ListMetricLabelKeysError, ListMetricLabelKeysResponse, ListMetricLabelValuesData, ListMetricLabelValuesError, ListMetricLabelValuesResponse, ListMetricNamesData, ListMetricNamesError, ListMetricNamesResponse, ListModelsData, ListModelsError, ListModelsResponse, ListMonitorsData, ListMonitorsResponse, ListNotificationProvidersData, ListNotificationProvidersResponse, ListOidcProvidersData, ListOidcProvidersResponse, ListOidcProviderUsersData, ListOidcProviderUsersResponse, ListOidcRoleMappingsData, ListOidcRoleMappingsResponse, ListOnDemandCertsData, ListOnDemandCertsResponse2, ListOrdersData, ListOrdersResponse2, ListPeersData, ListPeersResponse, ListPendingActionsData, ListPendingActionsResponse, ListPgUpgradesData, ListPgUpgradesResponse, ListPresetsData, ListPresetsResponse2, ListProjectAccessData, ListProjectAccessResponse, ListProjectAlarmsData, ListProjectAlarmsResponse, ListProjectScansData, ListProjectScansError, ListProjectScansResponse, ListProjectSecretsData, ListProjectSecretsResponse, ListProjectServicesData, ListProjectServicesResponse, ListProjectTemplatesData, ListProjectTemplatesResponse, ListProjectTemplateTagsData, ListProjectTemplateTagsResponse, ListProviderKeysData, ListProviderKeysError, ListProviderKeysResponse, ListProviderZonesData, ListProviderZonesResponse, ListPublicProvidersData, ListPublicProvidersResponse, ListReleaseFilesData, ListReleaseFilesResponse, ListReleasesData, ListReleasesResponse, ListRemoteExternalImagesData, ListRemoteExternalImagesResponse, ListRepositoriesByConnectionData, ListRepositoriesByConnectionResponse, ListRepositoriesByProviderData, ListRepositoriesByProviderResponse, ListRestoreRunsForServiceData, ListRestoreRunsForServiceResponse, ListRootContainersData, ListRootContainersResponse, ListRoutesData, ListRoutesResponse, ListS3SourcesData, ListS3SourcesError, ListS3SourcesResponse, ListSandboxesData, ListSandboxesResponse2, ListScheduleRunJobsData, ListScheduleRunJobsError, ListScheduleRunJobsResponse, ListScheduleRunsData, ListScheduleRunsError, ListScheduleRunsResponse, ListScheduleServicesData, ListScheduleServicesError, ListScheduleServicesResponse, ListSecretsData, ListSecretsResponse2, ListServiceHealthStatusesData, ListServiceHealthStatusesResponse, ListServiceProjectsData, ListServiceProjectsResponse, ListServiceSchedulesData, ListServiceSchedulesError, ListServiceSchedulesResponse, ListServicesData, ListServicesResponse, ListSkillsData, ListSkillsResponse2, ListSourceBackupsData, ListSourceBackupsError, ListSourceBackupsResponse, ListSourceFilesData, ListSourceFilesResponse, ListSourceMapsData, ListSourceMapsResponse, ListSourcesData, ListSourcesResponse, ListStaticBundlesData, ListStaticBundlesResponse, ListSyncedRepositoriesData, ListSyncedRepositoriesResponse, ListTeamMembersData, ListTeamMembersResponse, ListTeamProjectsData, ListTeamProjectsResponse, ListTeamsData, ListTeamsResponse, ListUsersData, ListUsersResponse, ListWebhooksData, ListWebhooksResponse, LoginData, LoginResponse, LogoutData, LookupDnsARecordsData, LookupDnsARecordsError, LookupDnsARecordsResponse, MintEnrollmentTokenData, MintEnrollmentTokenResponse2, MkdirData, MkdirResponse, NodeHeartbeatData, NodeHeartbeatResponse, NodeMetricsGetRangeData, NodeMetricsGetRangeResponse, ObservabilityFullEventData, ObservabilityFullEventError, ObservabilityFullEventResponse, ObservabilityListEventsData, ObservabilityListEventsError, ObservabilityListEventsResponse, OidcCallbackData, PatchAdminGateData, PatchAdminGateResponse, PatchPreviewGatewaySettingsData, PatchPreviewGatewaySettingsResponse, PauseDeploymentData, PauseDeploymentResponse, PauseSandboxData, PauseSandboxResponse, PlanRestoreData, PlanRestoreError, PlanRestoreResponse, PostDnsAckData, PostDnsAckResponse, PreviewAlertData, PreviewAlertError, PreviewAlertResponse, PreviewFunnelMetricsData, PreviewFunnelMetricsResponse, PreviewHostnameModeData, PreviewHostnameModeResponse, PromoteClusterMemberData, PromoteDeploymentData, PromoteDeploymentResponse, ProvisionDomainData, ProvisionDomainResponse, PurgeProjectLogsData, PurgeProjectLogsError, PushExternalImageData, PushExternalImageResponse, QueryDataData, QueryDataResponse2, QueryGenaiTracesData, QueryGenaiTracesError, QueryGenaiTracesResponse, QueryLogsData, QueryLogsError, QueryLogsResponse, QueryMetricsData, QueryMetricsError, QueryMetricsResponse, QueryTracesData, QueryTracesError, QueryTracesResponse, QueryTraceSummariesData, QueryTraceSummariesError, QueryTraceSummariesResponse, ReadFileData, ReadFileResponse2, ReAnalyzeData, RecordConsoleEventData, RecordEventMetricsData, RecordEventMetricsResponse, RecordFlagExposureData, RecordFlagExposureResponse, RecordSpeedMetricsData, RecordSpeedMetricsError, RecordSpeedMetricsResponse, RefreshRouteTableData, RefreshRouteTableResponse, RegenerateDsnData, RegenerateDsnResponse, RegisterExternalImageData, RegisterExternalImageResponse, RegisterNodeData, RegisterNodeResponse2, ReinstallGitlabWebhookData, ReinstallGitlabWebhookResponse, RejectPendingActionData, RejectPendingActionResponse, ReloadPluginsData, ReloadPluginsResponse, RemoveClusterMemberData, RemoveClusterMemberResponse, RemoveManagedDomainData, RemoveManagedDomainResponse, RemoveRoleData, RemoveRoleResponse, RemoveTeamMemberData, RemoveTeamMemberResponse, RenameConversationData, RenameConversationResponse, RenewDomainData, RenewDomainResponse, RequestPasswordResetData, RequestPasswordResetResponse, ResetPasswordData, ResetPasswordResponse, ResizeSandboxData, ResizeSandboxResponse, ResolveAlarmData, RestartContainerData, RestartContainerResponse, RestartPreviewGatewayData, RestartPreviewGatewayResponse, RestartSandboxData, RestartSandboxResponse, RestoreFlagData, RestoreFlagResponse, RestoreUserData, RestoreUserResponse, ResumeDeploymentData, ResumeDeploymentResponse, ResumeSandboxData, ResumeSandboxResponse, RetryClusterData, RetryClusterResponse, RetryDeliveryData, RetryDeliveryResponse, RetryPgUpgradeData, RetryPgUpgradeResponse, RetryRunData, RetryRunResponse, RevealGlobalMcpConfigData, RevealGlobalMcpConfigResponse, RevealMcpConfigData, RevealMcpConfigResponse, RevealNotificationProviderConfigData, RevealNotificationProviderConfigResponse, RevealServiceParameterData, RevealServiceParameterResponse, RevenueCreateIntegrationData, RevenueCreateIntegrationResponse, RevenueDeleteIntegrationData, RevenueDeleteIntegrationResponse, RevenueGlobalEventsData, RevenueGlobalEventsResponse, RevenueImportInvoicesCsvData, RevenueImportInvoicesCsvResponse, RevenueImportSubscriptionsCsvData, RevenueImportSubscriptionsCsvResponse, RevenueListIntegrationsData, RevenueListIntegrationsResponse, RevenueListProvidersData, RevenueListProvidersResponse, RevenueMetricsCustomersData, RevenueMetricsCustomersResponse, RevenueMetricsGlobalMrrData, RevenueMetricsGlobalMrrResponse, RevenueMetricsGlobalSummaryData, RevenueMetricsGlobalSummaryResponse, RevenueMetricsMrrData, RevenueMetricsMrrResponse, RevenueMetricsSummaryData, RevenueMetricsSummaryResponse, RevenueRecentEventsData, RevenueRecentEventsResponse, RevenueRotateTokenData, RevenueRotateTokenResponse, RevenueUpdateConfigData, RevenueUpdateConfigResponse, RevenueUpdateSecretData, RevenueUpdateSecretResponse, RevokeDsnData, RevokeDsnResponse, RevokeEnrollmentTokenData, RevokeEnrollmentTokenResponse, RevokeJoinTokenData, RevokeJoinTokenResponse, RevokeProjectAccessData, RevokeProjectAccessResponse, RollbackPgUpgradeData, RollbackPgUpgradeResponse, RollbackToDeploymentData, RollbackToDeploymentResponse, RootfsGcData, RootfsReportData, RotateApiKeyData, RotateApiKeyResponse, RotateDeploymentTokenData, RotateDeploymentTokenResponse, RunBackupForSourceData, RunBackupForSourceError, RunBackupForSourceResponse, RunConnectionHealthCheckData, RunConnectionHealthCheckResponse, RunExternalServiceBackupData, RunExternalServiceBackupError, RunExternalServiceBackupResponse, RunScheduleNowData, RunScheduleNowError, RunScheduleNowResponse, SandboxCreatePreviewLinkData, SandboxCreatePreviewLinkResponse, SaveAgentTokenData, SaveAgentTokenResponse2, SaveAiProviderCredentialData, SaveAiProviderCredentialResponse, SearchLogsData, SearchLogsError, SearchLogsResponse2, SendEmailData, SendEmailResponse, SetDefaultS3SourceData, SetDefaultS3SourceError, SetDefaultS3SourceResponse, SetFlagEnvironmentData, SetFlagEnvironmentResponse, SetPreviewPasswordData, SetPreviewPasswordResponse2, SetupDnsChallengeData, SetupDnsChallengeResponse2, SetupDnsData, SetupDnsResponse2, SetupEmailTrackingData, SetupEmailTrackingResponse, SetupMfaData, SetupMfaResponse, SleepEnvironmentData, SleepEnvironmentResponse, SmokeTestAgentData, SmokeTestAgentResponse, SourceSandboxData, SourceSandboxResponse, StartAnalysisData, StartAnalysisResponse, StartContainerData, StartContainerResponse, StartFixData, StartGitProviderOauthData, StartOidcLoginBySlugData, StartPgUpgradeData, StartPgUpgradeResponse, StartRestoreData, StartRestoreError, StartRestoreResponse, StartServiceData, StartServiceResponse, StatPathData, StatPathResponse, StopContainerData, StopContainerResponse, StopSandboxData, StopSandboxResponse, StopServiceData, StopServiceResponse, StreamContainerMetricsData, SyncRepositoriesData, SyncRepositoriesResponse, TailDeploymentJobLogsData, TailLogsData, TailLogsError, TeardownDeploymentData, TeardownDeploymentResponse, TeardownEnvironmentData, TeardownEnvironmentResponse, TestNotificationProviderData, TestNotificationProviderResponse, TestOidcProviderData, TestOidcProviderResponse, TestProviderConnectionData, TestProviderConnectionResponse, TestProviderData, TestProviderKeyByIdData, TestProviderKeyByIdError, TestProviderKeyByIdResponse, TestProviderKeyInlineData, TestProviderKeyInlineError, TestProviderKeyInlineResponse, TestProviderResponse2, TestS3ConnectionPreviewData, TestS3ConnectionPreviewError, TestS3ConnectionPreviewResponse, TestS3SourceConnectionData, TestS3SourceConnectionError, TestS3SourceConnectionResponse, TrackClickData, TrackOpenData, TriggerAgentData, TriggerAgentResponse, TriggerProjectPipelineData, TriggerProjectPipelineResponse, TriggerScanData, TriggerScanError, TriggerScanResponse2, TriggerServiceHealthCheckData, TriggerServiceHealthCheckResponse, TriggerWeeklyDigestData, TriggerWeeklyDigestResponse, UnlinkServiceFromProjectData, UnlinkServiceFromProjectResponse, UpdateAgentData, UpdateAgentResponse, UpdateAiProviderData, UpdateAiProviderResponse2, UpdateAlertData, UpdateAlertError, UpdateAlertResponse, UpdateAlertRuleData, UpdateAlertRuleResponse, UpdateApiKeyData, UpdateApiKeyResponse, UpdateAutomaticDeployData, UpdateAutomaticDeployResponse, UpdateBackupScheduleData, UpdateBackupScheduleError, UpdateBackupScheduleResponse, UpdateCloudflareProviderData, UpdateCloudflareProviderResponse, UpdateConnectionTokenData, UpdateConnectionTokenResponse, UpdateCustomDomainData, UpdateCustomDomainResponse, UpdateDashboardData, UpdateDashboardError, UpdateDashboardResponse, UpdateDeploymentTokenData, UpdateDeploymentTokenResponse, UpdateEmailProviderData, UpdateEmailProviderResponse, UpdateEnvironmentSettingsData, UpdateEnvironmentSettingsResponse, UpdateEnvironmentSubdomainData, UpdateEnvironmentSubdomainResponse, UpdateEnvironmentVariableData, UpdateEnvironmentVariableResponse, UpdateErrorGroupData, UpdateFlagData, UpdateFlagResponse, UpdateFunnelData, UpdateGitProviderCredentialsData, UpdateGitProviderCredentialsResponse, UpdateGitSettingsData, UpdateGitSettingsResponse, UpdateGlobalMcpData, UpdateGlobalMcpResponse, UpdateGlobalSkillData, UpdateGlobalSkillResponse, UpdateIncidentStatusData, UpdateIncidentStatusResponse, UpdateIpAccessControlData, UpdateIpAccessControlError, UpdateIpAccessControlResponse, UpdateManagedDomainData, UpdateManagedDomainResponse, UpdateMcpData, UpdateMcpResponse, UpdateNotificationEmailProviderData, UpdateNotificationEmailProviderResponse, UpdateNotificationProviderData, UpdateNotificationProviderResponse, UpdateOidcProviderData, UpdateOidcProviderResponse, UpdatePreferencesData, UpdatePreferencesResponse, UpdateProjectData, UpdateProjectDeploymentConfigData, UpdateProjectDeploymentConfigResponse, UpdateProjectResponse, UpdateProjectSecretData, UpdateProjectSecretResponse, UpdateProjectSettingsData, UpdateProjectSettingsResponse, UpdateProviderData, UpdateProviderKeyData, UpdateProviderKeyError, UpdateProviderKeyResponse, UpdateProviderResponse, UpdateRouteData, UpdateRouteResponse, UpdateS3SourceData, UpdateS3SourceError, UpdateS3SourceResponse, UpdateSelfData, UpdateSelfResponse, UpdateServiceData, UpdateServiceResourcesData, UpdateServiceResourcesResponse, UpdateServiceResponse, UpdateSessionDurationData, UpdateSessionDurationError, UpdateSessionDurationResponse2, UpdateSettingsData, UpdateSettingsResponse, UpdateSkillData, UpdateSkillResponse, UpdateSlackProviderData, UpdateSlackProviderResponse, UpdateSpeedMetricsData, UpdateSpeedMetricsError, UpdateSpeedMetricsResponse, UpdateTeamData, UpdateTeamMemberRoleData, UpdateTeamMemberRoleResponse, UpdateTeamResponse, UpdateUserData, UpdateUserResponse, UpdateWebhookData, UpdateWebhookProviderData, UpdateWebhookProviderResponse, UpdateWebhookResponse, UpgradePreviewGatewayData, UpgradePreviewGatewayResponse, UpgradeServiceData, UpgradeServiceResponse, UploadGlobalSkillData, UploadGlobalSkillResponse, UploadReleaseFileData, UploadReleaseFileResponse, UploadSkillData, UploadSkillResponse, UploadSourceFileData, UploadSourceFileResponse, UploadSourceMapData, UploadSourceMapResponse, UploadStaticBundleData, UploadStaticBundleResponse, UpsertSecretData, UpsertSecretResponse, ValidateConnectionData, ValidateConnectionResponse, ValidateEmailData, ValidateEmailResponse2, VerifyAndEnableMfaData, VerifyAndEnableMfaResponse, VerifyDomainData, VerifyDomainResponse, VerifyEmailData, VerifyEmailResponse, VerifyManagedDomainData, VerifyManagedDomainResponse, VerifyMfaChallengeData, VerifyMfaChallengeResponse, VerifyStepUpData, VerifyStepUpResponse, WakeEnvironmentData, WakeEnvironmentResponse, WebhookTriggerData, WebhookTriggerResponse2, WorkflowDryRunData, WorkflowDryRunResponse, WriteFileData, WriteFileResponse, WriteFilesData, WriteFilesResponse2 } from '../types.gen'; export type QueryKey = [ Pick & { @@ -3539,6 +3539,23 @@ export const checkDomainStatusOptions = (options: Options queryKey: checkDomainStatusQueryKey(options) }); +/** + * Inspect a source ZIP without creating a project or retaining the upload. + */ +export const inspectDropArchiveMutation = (options?: Partial>): UseMutationOptions> => { + const mutationOptions: UseMutationOptions> = { + mutationFn: async (fnOptions) => { + const { data } = await inspectDropArchive({ + ...options, + ...fnOptions, + throwOnError: true + }); + return data; + } + }; + return mutationOptions; +}; + export const listEmailDomainsQueryKey = (options?: Options) => createQueryKey('listEmailDomains', options); /** @@ -11093,6 +11110,23 @@ export const deployFromImageUploadMutation = (options?: Partial>): UseMutationOptions> => { + const mutationOptions: UseMutationOptions> = { + mutationFn: async (fnOptions) => { + const { data } = await deployFromUploadedSource({ + ...options, + ...fnOptions, + throwOnError: true + }); + return data; + } + }; + return mutationOptions; +}; + /** * Deploy from an uploaded static bundle * diff --git a/web/src/api/client/index.ts b/web/src/api/client/index.ts index aeac5a7fc..88eb76c4a 100644 --- a/web/src/api/client/index.ts +++ b/web/src/api/client/index.ts @@ -1,4 +1,4 @@ // This file is auto-generated by @hey-api/openapi-ts -export { acknowledgeAlarm, activateAiProvider, activateApiKey, activateConnection, activateProvider, addClusterMember, addContext, addEnvironmentDomain, addEvents, addManagedDomain, addSessionReplayEvents, addTeamMember, adminDrainNode, adminDrainStatus, adminGetNode, adminListNodeContainers, adminListNodes, adminRemoveNode, adminUndrainNode, applyHostnameMode, archiveConversation, archiveFlag, assignRole, attachScheduleServices, blobCopy, blobDelete, blobDisable, blobDownload, blobEnable, blobHead, blobList, blobPut, blobStatus, blobUpdate, cancel, cancelBackup, cancelDeployment, cancelDomainOrder, cancelPgUpgrade, cancelRun, cancelScheduleRun, changePasswordSelf, changeProjectSource, chatCompletions, checkAnalyticsHasEvents, checkCommitExists, checkDomainStatus, checkExplorerSupport, checkIpBlocked, checkProviderDeletionSafety, chunkUploadOptions, cleanupExpiredBackups, clearPreviewPassword, cliDeviceApprove, cliDeviceDeny, cliDeviceLookup, cliDevicePoll, cliDeviceStart, cliLogout, cmd, cmdKill, cmdLogs, confirmPendingAction, containerMetricsGetHistory, createAgent, createAlert, createAlertRule, createApiKey, createBackupSchedule, createBitbucketProvider, createCloudflareProvider, createConversation, createCustomDomain, createDashboard, createDeploymentToken, createDnsProvider, createDomain, createDsn, createEmailDomain, createEmailProvider, createEnvironment, createEnvironmentVariable, createFlag, createFunnel, createGenericProvider, createGiteaPatProvider, createGithubPatProvider, createGitlabOauthProvider, createGitlabPatProvider, createGitProvider, createGlobalMcp, createGlobalSkill, createIncident, createIpAccessControl, createMcp, createMonitor, createNotificationEmailProvider, createNotificationProvider, createOidcProvider, createOidcRoleMapping, createOrRecreateOrder, createPlan, createPr, createProject, createProjectFromTemplate, createProjectRelease, createProjectSecret, createProviderKey, createRelease, createRoute, createS3Source, createSandbox, createService, createSkill, createSlackProvider, createTeam, createUser, createWebhook, createWebhookProvider, deactivateApiKey, deactivateConnection, deactivateProvider, deleteAgent, deleteAlert, deleteAlertRule, deleteApiKey, deleteBackup, deleteBackupSchedule, deleteConnection, deleteCustomDomain, deleteDashboard, deleteDeploymentToken, deleteDnsProvider, deleteDomain, deleteEmailDomain, deleteEmailProvider, deleteEnvironment, deleteEnvironmentDomain, deleteEnvironmentVariable, deleteExternalImage, deleteFunnel, deleteGitProvider, deleteGlobalMcp, deleteGlobalSkill, deleteIpAccessControl, deleteMcp, deleteMonitor, deleteNotificationProvider, deleteOidcProvider, deleteOidcRoleMapping, deletePreferences, deleteProject, deleteProjectSecret, deleteProviderKey, deleteProviderSafely, deleteReleaseSourceFiles, deleteReleaseSourceMaps, deleteRoute, deleteS3Source, deleteScan, deleteSecret, deleteService, deleteSessionReplay, deleteSkill, deleteSourceMap, deleteStaticBundle, deleteTeam, deleteUser, deleteWebhook, deployFromImage, deployFromImageUpload, deployFromStatic, deploymentMetricsGetLatest, deploymentMetricsGetRange, deploymentMetricsToggle, destroySandbox, detachScheduleService, detectPublicPresets, disableBackupSchedule, disableMfa, discoverWorkloads, domain, downloadGlobalSkillArchive, downloadObject, downloadSkillArchive, emailStatus, embeddings, enableBackupSchedule, enrichVisitor, exec, execDetached, executeDeploymentOperation, executeImport, extendTimeout, externalServiceEnablePgStatStatements, externalServiceMetricsByDatabase, externalServiceMetricsCreateAlertRule, externalServiceMetricsDeleteAlertRule, externalServiceMetricsGetAlertRules, externalServiceMetricsGetLatest, externalServiceMetricsGetRange, externalServiceMetricsStatus, externalServiceMetricsToggle, externalServiceMetricsUpdateAlertRule, externalServiceResetPgStatStatements, finalizeOrder, finalizeProjectRelease, findConversation, generateJoinToken, generatePresetDockerfile, getAccessInfo, getActiveVisitors, getActivityGraph, getAdminGate, getAgent, getAggregatedBuckets, getAiAgentBreakdown, getAiAgentPages, getAiAgentTimeline, getAiPageBreakdown, getAiStatusBreakdown, getAlert, getAlertRule, getAllRepositoriesByName, getAnalyticsActiveVisitors, getAnalyticsEventsCount, getAnalyticsSessionEvents, getAnalyticsVisitorSessions, getApiKey, getApiKeyPermissions, getAuditLog, getBackup, getBackupSchedule, getBranchesByRepositoryId, getBucketedIncidents, getBucketedStatus, getChallengeToken, getChatReadiness, getCliStatus, getClusterHealth, getClusterMember, getCmd, getContainerDetail, getContainerEnvironmentVariable, getContainerInfo, getContainerLogs, getContainerLogsById, getContainerMetrics, getConversation, getConversationDetail, getConversations, getCronById, getCronExecutions, getCrossProjectTraceSiblings, getCurrentMonitorStatus, getCurrentUser, getCustomDomain, getDashboard, getDashboardProjectsAnalytics, getDelivery, getDeployment, getDeploymentContainerLogContent, getDeploymentJobLogs, getDeploymentJobs, getDeploymentOperations, getDeploymentOperationStatus, getDeploymentToken, getDiskStatus, getDnsChanges, getDnsProvider, getDomain, getDomainByHost, getDomainById, getDomainByName, getDomainDnsRecords, getDomainOrder, getEmail, getEmailEvents, getEmailLinks, getEmailProvider, getEmailStats, getEmailTracking, getEmailTrackingStatus, getEntityInfo, getEnvironment, getEnvironmentCrons, getEnvironmentDomains, getEnvironments, getEnvironmentVariables, getEnvironmentVariableValue, getErrorDashboardStats, getErrorEvent, getErrorGroup, getErrorStats, getErrorTimeSeries, getEventDetail, getEventEntries, getEventsCount, getEventsTimeline, getEventTypeBreakdown, getEventVisitors, getExternalImage, getFile, getFlag, getFlagSnapshot, getFunnelMetrics, getGenaiTrace, getGeneralStats, getGitProvider, getGlobalEvents, getGlobalEventStats, getGlobalMcp, getGlobalSandboxStatus, getGlobalSkill, getGroupedPageMetrics, getHealth, getHourlyVisits, getHttpChallengeDebug, getImportStatus, getIncident, getIncidentUpdates, getIpAccessControl, getIpGeolocation, getJoinTokenStatus, getLastDeployment, getLatestScan, getLatestScansPerEnvironment, getLiveVisitorsList, getLogContext, getMcp, getMetricsOverTime, getMonitor, getNotificationProvider, getOnDemandCertStatus, getOrCreateDsn, getPageFlow, getPageHourlySessions, getPagePathDetail, getPagePaths, getPagePathsSparklines, getPagePathVisitors, getPendingAction, getPerformanceMetrics, getPgUpgrade, getPgUpgradeLogs, getPipelineStats, getPlatformInfo, getPostgresWalHealth, getPreferences, getPreviewGatewayLogs, getPreviewGatewaySettings, getPreviewGatewayStatus, getPricing, getPrivateIp, getProject, getProjectAlarmsSummary, getProjectBySlug, getProjectDeployments, getProjects, getProjectServiceEnvironmentVariables, getProjectSessionReplays, getProjectsHealth, getProjectsMonitorHealth, getProjectStatistics, getProjectTemplate, getPropertyBreakdown, getPropertyTimeline, getProviderConnections, getProviderMetadata, getProvidersMetadata, getProxyLogById, getProxyLogByRequestId, getProxyLogs, getPublicBranches, getPublicIp, getPublicRepository, getQuota, getRecentActivity, getRemoteExternalImage, getRepositoryBranches, getRepositoryById, getRepositoryByName, getRepositoryPresetByName, getRepositoryPresetLive, getRepositoryTags, getResolvedEnvironmentVariables, getResolvedEnvironmentVariableValue, getRestoreCapabilities, getRestoreRun, getRoute, getRun, getRunWithLogs, getS3Credentials, getS3Source, getSandbox, getSandboxStatus, getScan, getScanByDeployment, getScanVulnerabilities, getService, getServiceBySlug, getServiceEnvironmentVariable, getServiceEnvironmentVariables, getServiceHealthStatus, getServicePreviewEnvironmentVariableNames, getServicePreviewEnvironmentVariablesMasked, getServiceRuntime, getServiceStats, getServiceTypeParameters, getServiceTypes, getSessionDetails, getSessionEvents, getSessionLogs, getSessionReplay, getSessionReplayEvents, getSettings, getSkill, getSlowQueries, getStaticBundle, getStatusOverview, getTagsByRepositoryId, getTeam, getTimeBucketStats, getTodayStats, getTrace, getUnifiedTrace, getUniqueCounts, getUniqueEvents, getUpdateStatus, getUptimeHistory, getUsageByProvider, getUsageRecent, getUsageSummary, getUsageTimeseries, getUsageTopModels, getVisitorByGuid, getVisitorById, getVisitorDetails, getVisitorFacets, getVisitorInfo, getVisitorJourney, getVisitors, getVisitorSessions, getVisitorStats, getWebhook, grantProjectAccess, handleGitProviderOauthCallback, hasAnalyticsEvents, hasErrorGroups, hasPerformanceMetrics, importExternalService, ingestLogs, ingestLogsByPath, ingestMetrics, ingestMetricsByPath, ingestSentryEnvelope, ingestSentryEvent, ingestTraces, ingestTracesByPath, initSessionReplay, jobLogs, jobStatus, killJob, kvDel, kvDisable, kvEnable, kvExpire, kvGet, kvIncr, kvKeys, kvSet, kvStatus, kvTtl, kvUpdate, latestRunForSource, linkCustomDomainToCertificate, linkServiceToProject, listAgentRuns, listAgents, listAiProviders, listAlertRules, listAlerts, listAllConversations, listAllRuns, listApiKeys, listAuditLogs, listAvailableContainers, listBackupAlerts, listBackupChildren, listBackupSchedules, listBackupsForSchedule, listCommitsByRepositoryId, listConnections, listContainers, listContainersAtPath, listConversations, listCustomDomainsForProject, listDashboards, listDeliveries, listDeploymentContainerLogs, listDeploymentTokens, listDnsProviders, listDomains, listDsns, listEmailDomains, listEmailProviders, listEmails, listEnrollmentTokens, listEntities, listErrorEvents, listErrorGroups, listEvents, listEventTypes, listExternalImages, listExternalPlugins, listExternalServiceBackups, listFlags, listFunnels, listGitProviders, listGlobalMcps, listGlobalSkills, listIncidents, listInsights, listIpAccessControl, listJobs, listKnownAiAgents, listManagedDomains, listMcps, listMetricLabelKeys, listMetricLabelValues, listMetricNames, listModels, listMonitors, listNotificationProviders, listOidcProviders, listOidcProviderUsers, listOidcRoleMappings, listOnDemandCerts, listOrders, listPeers, listPendingActions, listPgUpgrades, listPresets, listProjectAccess, listProjectAlarms, listProjectScans, listProjectSecrets, listProjectServices, listProjectTemplates, listProjectTemplateTags, listProviderKeys, listProviderZones, listPublicProviders, listReleaseFiles, listReleases, listRemoteExternalImages, listRepositoriesByConnection, listRepositoriesByProvider, listRestoreRunsForService, listRootContainers, listRoutes, listS3Sources, listSandboxes, listScheduleRunJobs, listScheduleRuns, listScheduleServices, listSecrets, listServiceHealthStatuses, listServiceProjects, listServices, listServiceSchedules, listSkills, listSourceBackups, listSourceFiles, listSourceMaps, listSources, listStaticBundles, listSyncedRepositories, listTeamMembers, listTeamProjects, listTeams, listUsers, listWebhooks, login, logout, lookupDnsARecords, mintEnrollmentToken, mkdir, nodeHeartbeat, nodeMetricsGetRange, observabilityFullEvent, observabilityListEvents, oidcCallback, type Options, patchAdminGate, patchPreviewGatewaySettings, pauseDeployment, pauseSandbox, planRestore, postDnsAck, previewAlert, previewFunnelMetrics, previewHostnameMode, promoteClusterMember, promoteDeployment, provisionDomain, purgeProjectLogs, pushExternalImage, queryData, queryGenaiTraces, queryLogs, queryMetrics, queryTraces, queryTraceSummaries, readFile, reAnalyze, recordConsoleEvent, recordEventMetrics, recordFlagExposure, recordSpeedMetrics, refreshRouteTable, regenerateDsn, registerExternalImage, registerNode, reinstallGitlabWebhook, rejectPendingAction, reloadPlugins, removeClusterMember, removeManagedDomain, removeRole, removeTeamMember, renameConversation, renewDomain, requestPasswordReset, resetPassword, resizeSandbox, resolveAlarm, restartContainer, restartPreviewGateway, restartSandbox, restoreFlag, restoreUser, resumeDeployment, resumeSandbox, retryCluster, retryDelivery, retryPgUpgrade, retryRun, revealGlobalMcpConfig, revealMcpConfig, revealNotificationProviderConfig, revealServiceParameter, revenueCreateIntegration, revenueDeleteIntegration, revenueGlobalEvents, revenueImportInvoicesCsv, revenueImportSubscriptionsCsv, revenueListIntegrations, revenueListProviders, revenueMetricsCustomers, revenueMetricsGlobalMrr, revenueMetricsGlobalSummary, revenueMetricsMrr, revenueMetricsSummary, revenueRecentEvents, revenueRotateToken, revenueUpdateConfig, revenueUpdateSecret, revokeDsn, revokeEnrollmentToken, revokeJoinToken, revokeProjectAccess, rollbackPgUpgrade, rollbackToDeployment, rootfsGc, rootfsReport, rotateApiKey, rotateDeploymentToken, runBackupForSource, runConnectionHealthCheck, runExternalServiceBackup, runScheduleNow, sandboxCreatePreviewLink, saveAgentToken, saveAiProviderCredential, searchLogs, sendEmail, setDefaultS3Source, setFlagEnvironment, setPreviewPassword, setupDns, setupDnsChallenge, setupEmailTracking, setupMfa, sleepEnvironment, smokeTestAgent, sourceSandbox, startAnalysis, startContainer, startFix, startGitProviderOauth, startOidcLoginBySlug, startPgUpgrade, startRestore, startService, statPath, stopContainer, stopSandbox, stopService, streamContainerMetrics, streamEvents, streamRunEvents, syncRepositories, tailDeploymentJobLogs, tailLogs, teardownDeployment, teardownEnvironment, testNotificationProvider, testOidcProvider, testProvider, testProviderConnection, testProviderKeyById, testProviderKeyInline, testS3ConnectionPreview, testS3SourceConnection, trackClick, trackOpen, triggerAgent, triggerProjectPipeline, triggerScan, triggerServiceHealthCheck, triggerWeeklyDigest, unlinkServiceFromProject, updateAgent, updateAiProvider, updateAlert, updateAlertRule, updateApiKey, updateAutomaticDeploy, updateBackupSchedule, updateCloudflareProvider, updateConnectionToken, updateCustomDomain, updateDashboard, updateDeploymentToken, updateEmailProvider, updateEnvironmentSettings, updateEnvironmentSubdomain, updateEnvironmentVariable, updateErrorGroup, updateFlag, updateFunnel, updateGitProviderCredentials, updateGitSettings, updateGlobalMcp, updateGlobalSkill, updateIncidentStatus, updateIpAccessControl, updateManagedDomain, updateMcp, updateNotificationEmailProvider, updateNotificationProvider, updateOidcProvider, updatePreferences, updateProject, updateProjectDeploymentConfig, updateProjectSecret, updateProjectSettings, updateProvider, updateProviderKey, updateRoute, updateS3Source, updateSelf, updateService, updateServiceResources, updateSessionDuration, updateSettings, updateSkill, updateSlackProvider, updateSpeedMetrics, updateTeam, updateTeamMemberRole, updateUser, updateWebhook, updateWebhookProvider, upgradePreviewGateway, upgradeService, uploadGlobalSkill, uploadReleaseFile, uploadSkill, uploadSourceFile, uploadSourceMap, uploadStaticBundle, upsertSecret, validateConnection, validateEmail, verifyAndEnableMfa, verifyDomain, verifyEmail, verifyManagedDomain, verifyMfaChallenge, verifyStepUp, wakeEnvironment, webhookTrigger, workflowDryRun, writeFile, writeFiles } from './sdk.gen'; -export type { AcknowledgeAlarmData, AcknowledgeAlarmErrors, AcknowledgeAlarmResponses, AcmeOrderResponse, ActivateAiProviderData, ActivateAiProviderErrors, ActivateAiProviderResponse, ActivateAiProviderResponses, ActivateApiKeyData, ActivateApiKeyErrors, ActivateApiKeyResponse, ActivateApiKeyResponses, ActivateConnectionData, ActivateConnectionErrors, ActivateConnectionResponses, ActivateProviderData, ActivateProviderErrors, ActivateProviderResponse, ActivateProviderResponses, ActiveVisitor, ActiveVisitorsQuery, ActiveVisitorsResponse, ActivityDay, ActivityEvent, ActivityGraphQuery, ActivityGraphResponse, AddClusterMemberData, AddClusterMemberErrors, AddClusterMemberRequest, AddClusterMemberResponse, AddClusterMemberResponses, AddContextData, AddContextErrors, AddContextRequest, AddContextResponses, AddEnvironmentDomainData, AddEnvironmentDomainErrors, AddEnvironmentDomainRequest, AddEnvironmentDomainResponse, AddEnvironmentDomainResponses, AddEventsData, AddEventsError, AddEventsErrors, AddEventsRequest, AddEventsResponse, AddEventsResponse2, AddEventsResponses, AddManagedDomainApiRequest, AddManagedDomainData, AddManagedDomainErrors, AddManagedDomainResponse, AddManagedDomainResponses, AddSessionReplayEventsData, AddSessionReplayEventsError, AddSessionReplayEventsErrors, AddSessionReplayEventsResponse, AddSessionReplayEventsResponses, AddTeamMemberData, AddTeamMemberErrors, AddTeamMemberResponse, AddTeamMemberResponses, AdminDrainNodeData, AdminDrainNodeErrors, AdminDrainNodeResponse, AdminDrainNodeResponses, AdminDrainStatusData, AdminDrainStatusErrors, AdminDrainStatusResponse, AdminDrainStatusResponses, AdminGateResponse, AdminGateSource, AdminGetNodeData, AdminGetNodeErrors, AdminGetNodeResponse, AdminGetNodeResponses, AdminListNodeContainersData, AdminListNodeContainersErrors, AdminListNodeContainersResponse, AdminListNodeContainersResponses, AdminListNodesData, AdminListNodesErrors, AdminListNodesResponse, AdminListNodesResponses, AdminRemoveNodeData, AdminRemoveNodeErrors, AdminRemoveNodeResponse, AdminRemoveNodeResponses, AdminUndrainNodeData, AdminUndrainNodeErrors, AdminUndrainNodeResponse, AdminUndrainNodeResponses, AgentConfigResponse, AgentRunLogResponse, AgentRunResponse, AgentRunWithLogsResponse, AgentSandboxSettings, AgentSandboxSettingsMasked, AggregatedBucketItem, AggregatedBucketsQuery, AggregatedBucketsResponse, AggregationLevel, AggregationTemporality, AiAgentBreakdownResponse, AiAgentBreakdownRow, AiAgentDescriptor, AiAgentPageRow, AiAgentPagesResponse, AiAgentTimelineResponse, AiAgentTimelineRow, AiChatLimitsSettings, AiConfigSettings, AiPageBreakdownResponse, AiPageBreakdownRow, AiStatusBreakdownResponse, AiStatusBreakdownRow, AlarmListResponse, AlarmResponse, AlarmSummaryResponse, AlertRuleResponse, AllocEntry, AnalyticsSessionEventsResponse, AnnotatedSpan, AnomalyAlgorithm, AnomalyParams, AnomalyPreviewPointResponse, AnomalyPreviewRequest, AnomalyPreviewResponse, ApiKeyListResponse, ApiKeyResponse, ApplyHostnameModeData, ApplyHostnameModeErrors, ApplyHostnameModeRequest, ApplyHostnameModeResponse, ApplyHostnameModeResponses, AppSettings, AppSettingsResponse, ArchiveConversationData, ArchiveConversationErrors, ArchiveConversationResponse, ArchiveConversationResponses, ArchiveFlagData, ArchiveFlagErrors, ArchiveFlagResponse, ArchiveFlagResponse2, ArchiveFlagResponses, ArchiveMode, AssignRoleData, AssignRoleErrors, AssignRoleRequest, AssignRoleResponses, AttachScheduleServicesData, AttachScheduleServicesError, AttachScheduleServicesErrors, AttachScheduleServicesRequest, AttachScheduleServicesResponse, AttachScheduleServicesResponse2, AttachScheduleServicesResponses, AuditLogIpInfo, AuditLogResponse, AuditLogUserInfo, AuthFlavorDto, AuthResponse, AuthStatusResponse, AuthTokenResponse, AutofixerRunResponse, AutofixerRunWithLogsResponse, AutofixRunConfig, AutoWatchParams, AvailableContainerInfo, AvailablePermissions, BackupAlertListResponse, BackupAlertResponse, BackupResponse, BackupScheduleResponse, BitbucketAuthInput, BlobCopyData, BlobCopyError, BlobCopyErrors, BlobCopyResponse, BlobCopyResponses, BlobDeleteData, BlobDeleteError, BlobDeleteErrors, BlobDeleteResponse, BlobDeleteResponses, BlobDisableData, BlobDisableErrors, BlobDisableResponse, BlobDisableResponses, BlobDownloadData, BlobDownloadError, BlobDownloadErrors, BlobDownloadResponses, BlobEnableData, BlobEnableErrors, BlobEnableResponse, BlobEnableResponses, BlobHeadData, BlobHeadError, BlobHeadErrors, BlobHeadResponses, BlobListData, BlobListError, BlobListErrors, BlobListResponse, BlobListResponses, BlobPutData, BlobPutError, BlobPutErrors, BlobPutResponse, BlobPutResponses, BlobResponse, BlobStatusData, BlobStatusErrors, BlobStatusResponse, BlobStatusResponse2, BlobStatusResponses, BlobUpdateData, BlobUpdateErrors, BlobUpdateResponse, BlobUpdateResponses, BranchInfo, BranchListResponse, BrowserCount, BrowsersQuery, BuildConfiguration, BuildLimitsSettings, CancelBackupData, CancelBackupError, CancelBackupErrors, CancelBackupResponse, CancelBackupResponse2, CancelBackupResponses, CancelData, CancelDeploymentData, CancelDeploymentErrors, CancelDeploymentResponse, CancelDeploymentResponses, CancelDomainOrderData, CancelDomainOrderErrors, CancelDomainOrderResponse, CancelDomainOrderResponses, CancelErrors, CancelPgUpgradeData, CancelPgUpgradeErrors, CancelPgUpgradeResponse, CancelPgUpgradeResponses, CancelResponses, CancelRunData, CancelRunErrors, CancelRunResponse, CancelRunResponses, CancelScheduleRunData, CancelScheduleRunError, CancelScheduleRunErrors, CancelScheduleRunResponse, CancelScheduleRunResponses, CertStatusResponse, ChallengeConfig, ChallengeError, ChallengeValidationStatus, ChangePasswordRequest, ChangePasswordSelfData, ChangePasswordSelfErrors, ChangePasswordSelfResponse, ChangePasswordSelfResponses, ChangeProjectSourceData, ChangeProjectSourceErrors, ChangeProjectSourceRequest, ChangeProjectSourceResponse, ChangeProjectSourceResponses, ChatCompletionChoice, ChatCompletionRequest, ChatCompletionResponse, ChatCompletionsData, ChatCompletionsError, ChatCompletionsErrors, ChatCompletionsResponse, ChatCompletionsResponses, ChatMessage, ChatReadinessResponse, CheckAnalyticsHasEventsData, CheckAnalyticsHasEventsErrors, CheckAnalyticsHasEventsResponse, CheckAnalyticsHasEventsResponses, CheckCommitExistsData, CheckCommitExistsErrors, CheckCommitExistsResponse, CheckCommitExistsResponses, CheckDomainStatusData, CheckDomainStatusErrors, CheckDomainStatusResponse, CheckDomainStatusResponses, CheckExplorerSupportData, CheckExplorerSupportErrors, CheckExplorerSupportResponse, CheckExplorerSupportResponses, CheckIpBlockedData, CheckIpBlockedError, CheckIpBlockedErrors, CheckIpBlockedResponses, CheckProviderDeletionSafetyData, CheckProviderDeletionSafetyErrors, CheckProviderDeletionSafetyResponse, CheckProviderDeletionSafetyResponses, ChildBackupEntryResponse, ChildBackupListResponse, ChunkUploadOptionsData, ChunkUploadOptionsResponse, ChunkUploadOptionsResponses, CleanupExpiredBackupsData, CleanupExpiredBackupsError, CleanupExpiredBackupsErrors, CleanupExpiredBackupsRequest, CleanupExpiredBackupsResponse, CleanupExpiredBackupsResponses, ClearPreviewPasswordData, ClearPreviewPasswordErrors, ClearPreviewPasswordResponse, ClearPreviewPasswordResponses, CliDeviceApproveData, CliDeviceApproveErrors, CliDeviceApproveRequest, CliDeviceApproveResponse, CliDeviceApproveResponse2, CliDeviceApproveResponses, CliDeviceDenyData, CliDeviceDenyErrors, CliDeviceDenyResponse, CliDeviceDenyResponses, CliDeviceLookupData, CliDeviceLookupErrors, CliDeviceLookupResponse, CliDeviceLookupResponse2, CliDeviceLookupResponses, CliDevicePollData, CliDevicePollErrors, CliDevicePollRequest, CliDevicePollResponse, CliDevicePollResponse2, CliDevicePollResponses, CliDeviceStartData, CliDeviceStartErrors, CliDeviceStartRequest, CliDeviceStartResponse, CliDeviceStartResponse2, CliDeviceStartResponses, ClientOptions, CliLoginRequest, CliLogoutData, CliLogoutErrors, CliLogoutResponse, CliLogoutResponses, CloudflareConfig, CloudProvider, ClusterCapacity, ClusterDnsSettings, ClusterHealthReportResponse, ClusterMemberHealthResponse, ClusterMemberRequest, CmdBody, CmdData, CmdErrors, CmdInner, CmdKillBody, CmdKillData, CmdKillErrors, CmdKillResponse, CmdKillResponses, CmdLogsData, CmdLogsErrors, CmdLogsResponses, CmdResponse, CmdResponse2, CmdResponses, CommitExistsResponse, CommitInfo, CommitListResponse, Comparator, ComposePublicPort, ConfirmPendingActionData, ConfirmPendingActionErrors, ConfirmPendingActionResponse, ConfirmPendingActionResponses, ConnectionListQuery, ConnectionListResponse, ConnectionResponse, ConnectionTestResult, ConsoleEventPayload, ContainerActionResponse, ContainerDetailResponse, ContainerEnvironmentVariableValueResponse, ContainerInfoResponse, ContainerInventoryItem, ContainerListResponse, ContainerLogSettings, ContainerLogsQuery, ContainerMetricHistoryPoint, ContainerMetricsGetHistoryData, ContainerMetricsGetHistoryErrors, ContainerMetricsGetHistoryResponse, ContainerMetricsGetHistoryResponses, ContainerMetricsHistoryQuery, ContainerMetricsResponse, ContainerResponse, ContainerRuntimeInfo, ContainerStatsSample, ContentPart, ContextLine, ContextLogsRequest, ContextLogsResponse, ConversationDetailResponse, ConversationResponse, ConversationsQueryParams, ConversationSummary, CopyBlobRequest, CostAnalysis, CreateAgentData, CreateAgentErrors, CreateAgentResponse, CreateAgentResponses, CreateAlertData, CreateAlertError, CreateAlertErrors, CreateAlertResponse, CreateAlertResponses, CreateAlertRuleData, CreateAlertRuleErrors, CreateAlertRuleRequest, CreateAlertRuleResponse, CreateAlertRuleResponses, CreateApiKeyData, CreateApiKeyErrors, CreateApiKeyRequest, CreateApiKeyResponse, CreateApiKeyResponse2, CreateApiKeyResponses, CreateBackupScheduleData, CreateBackupScheduleError, CreateBackupScheduleErrors, CreateBackupScheduleRequest, CreateBackupScheduleResponse, CreateBackupScheduleResponses, CreateBitbucketProviderData, CreateBitbucketProviderErrors, CreateBitbucketProviderResponse, CreateBitbucketProviderResponses, CreateBitbucketRequest, CreateCloudflareProviderData, CreateCloudflareProviderErrors, CreateCloudflareProviderRequest, CreateCloudflareProviderResponse, CreateCloudflareProviderResponses, CreateConversationData, CreateConversationErrors, CreateConversationRequest, CreateConversationResponse, CreateConversationResponses, CreateCustomDomainData, CreateCustomDomainErrors, CreateCustomDomainResponse, CreateCustomDomainResponses, CreateDashboardData, CreateDashboardError, CreateDashboardErrors, CreateDashboardRequest, CreateDashboardResponse, CreateDashboardResponses, CreateDeploymentTokenData, CreateDeploymentTokenErrors, CreateDeploymentTokenRequest, CreateDeploymentTokenResponse, CreateDeploymentTokenResponse2, CreateDeploymentTokenResponses, CreateDnsProviderData, CreateDnsProviderErrors, CreateDnsProviderRequest, CreateDnsProviderResponse, CreateDnsProviderResponses, CreateDomainData, CreateDomainErrors, CreateDomainRequest, CreateDomainResponse, CreateDomainResponses, CreatedResource, CreateDsnData, CreateDsnErrors, CreateDsnRequest, CreateDsnResponse, CreateDsnResponses, CreateEmailDomainData, CreateEmailDomainErrors, CreateEmailDomainRequest, CreateEmailDomainResponse, CreateEmailDomainResponses, CreateEmailProviderData, CreateEmailProviderErrors, CreateEmailProviderRequest, CreateEmailProviderResponse, CreateEmailProviderResponses, CreateEnvironmentData, CreateEnvironmentErrors, CreateEnvironmentRequest, CreateEnvironmentResponse, CreateEnvironmentResponses, CreateEnvironmentVariableData, CreateEnvironmentVariableErrors, CreateEnvironmentVariableRequest, CreateEnvironmentVariableResponse, CreateEnvironmentVariableResponses, CreateExternalServiceRequest, CreateFlagData, CreateFlagErrors, CreateFlagRequest, CreateFlagResponse, CreateFlagResponses, CreateFunnelData, CreateFunnelErrors, CreateFunnelRequest, CreateFunnelResponse, CreateFunnelResponse2, CreateFunnelResponses, CreateFunnelStep, CreateGenericProviderData, CreateGenericProviderErrors, CreateGenericProviderResponse, CreateGenericProviderResponses, CreateGenericRequest, CreateGiteaPatProviderData, CreateGiteaPatProviderErrors, CreateGiteaPatProviderResponse, CreateGiteaPatProviderResponses, CreateGiteaPatRequest, CreateGithubPatProviderData, CreateGithubPatProviderErrors, CreateGithubPatProviderResponse, CreateGithubPatProviderResponses, CreateGitHubPatRequest, CreateGitlabOauthProviderData, CreateGitlabOauthProviderErrors, CreateGitlabOauthProviderResponse, CreateGitlabOauthProviderResponses, CreateGitLabOAuthRequest, CreateGitlabPatProviderData, CreateGitlabPatProviderErrors, CreateGitlabPatProviderResponse, CreateGitlabPatProviderResponses, CreateGitLabPatRequest, CreateGitProviderData, CreateGitProviderErrors, CreateGitProviderResponse, CreateGitProviderResponses, CreateGlobalMcpData, CreateGlobalMcpErrors, CreateGlobalMcpResponse, CreateGlobalMcpResponses, CreateGlobalSkillData, CreateGlobalSkillErrors, CreateGlobalSkillResponse, CreateGlobalSkillResponses, CreateIncidentData, CreateIncidentErrors, CreateIncidentRequest, CreateIncidentResponse, CreateIncidentResponses, CreateIntegrationBody, CreateIpAccessControlData, CreateIpAccessControlError, CreateIpAccessControlErrors, CreateIpAccessControlRequest, CreateIpAccessControlResponse, CreateIpAccessControlResponses, CreateMcpData, CreateMcpErrors, CreateMcpRequest, CreateMcpResponse, CreateMcpResponses, CreateMetricAlertRequest, CreateMonitorData, CreateMonitorErrors, CreateMonitorRequest, CreateMonitorResponse, CreateMonitorResponses, CreateNotificationEmailProviderData, CreateNotificationEmailProviderErrors, CreateNotificationEmailProviderRequest, CreateNotificationEmailProviderResponse, CreateNotificationEmailProviderResponses, CreateNotificationProviderData, CreateNotificationProviderErrors, CreateNotificationProviderResponse, CreateNotificationProviderResponses, CreateOidcProviderData, CreateOidcProviderErrors, CreateOidcProviderRequest, CreateOidcProviderResponse, CreateOidcProviderResponses, CreateOidcRoleMappingData, CreateOidcRoleMappingRequest, CreateOidcRoleMappingResponse, CreateOidcRoleMappingResponses, CreateOrRecreateOrderData, CreateOrRecreateOrderErrors, CreateOrRecreateOrderResponse, CreateOrRecreateOrderResponses, CreatePlanData, CreatePlanErrors, CreatePlanRequest, CreatePlanResponse, CreatePlanResponse2, CreatePlanResponses, CreatePrData, CreatePrErrors, CreateProjectAccessRequest, CreateProjectData, CreateProjectErrors, CreateProjectFromTemplateData, CreateProjectFromTemplateErrors, CreateProjectFromTemplateRequest, CreateProjectFromTemplateResponse, CreateProjectFromTemplateResponse2, CreateProjectFromTemplateResponses, CreateProjectReleaseData, CreateProjectReleaseErrors, CreateProjectReleaseResponse, CreateProjectReleaseResponses, CreateProjectRequest, CreateProjectResponse, CreateProjectResponses, CreateProjectSecretData, CreateProjectSecretErrors, CreateProjectSecretRequest, CreateProjectSecretResponse, CreateProjectSecretResponses, CreateProviderKeyData, CreateProviderKeyError, CreateProviderKeyErrors, CreateProviderKeyRequest, CreateProviderKeyResponse, CreateProviderKeyResponses, CreateProviderRequest, CreatePrResponse, CreatePrResponse2, CreatePrResponses, CreateReleaseData, CreateReleaseErrors, CreateReleaseResponse, CreateReleaseResponses, CreateRouteData, CreateRouteErrors, CreateRouteRequest, CreateRouteResponse, CreateRouteResponses, CreateS3SourceData, CreateS3SourceError, CreateS3SourceErrors, CreateS3SourceRequest, CreateS3SourceResponse, CreateS3SourceResponses, CreateSandboxBody, CreateSandboxData, CreateSandboxErrors, CreateSandboxResponse, CreateSandboxResponses, CreateServiceData, CreateServiceErrors, CreateServiceResponse, CreateServiceResponses, CreateSkillData, CreateSkillErrors, CreateSkillRequest, CreateSkillResponse, CreateSkillResponses, CreateSlackProviderData, CreateSlackProviderErrors, CreateSlackProviderRequest, CreateSlackProviderResponse, CreateSlackProviderResponses, CreateTeamData, CreateTeamErrors, CreateTeamMemberRequest, CreateTeamRequest, CreateTeamResponse, CreateTeamResponses, CreateUserData, CreateUserErrors, CreateUserRequest, CreateUserResponse, CreateUserResponses, CreateWebhookData, CreateWebhookErrors, CreateWebhookProviderData, CreateWebhookProviderErrors, CreateWebhookProviderRequest, CreateWebhookProviderResponse, CreateWebhookProviderResponses, CreateWebhookRequestBody, CreateWebhookResponse, CreateWebhookResponses, CronExecutionInfo, CronInfo, CrossProjectSiblingRef, CrossProjectTraceResponse, CurrentStatusResponse, CustomDomainRequest, CustomDomainResponse, CustomerMovementResponse, DashboardLayout, DashboardProjectsAnalyticsQuery, DashboardProjectsAnalyticsResponse, DashboardSection, DashboardTile, DatabaseMetricsResponse, DatabaseMetricsRow, DataImplication, DataImplicationSeverity, DeactivateApiKeyData, DeactivateApiKeyErrors, DeactivateApiKeyResponse, DeactivateApiKeyResponses, DeactivateConnectionData, DeactivateConnectionErrors, DeactivateConnectionResponses, DeactivateProviderData, DeactivateProviderErrors, DeactivateProviderResponses, DeleteAgentData, DeleteAgentErrors, DeleteAgentResponse, DeleteAgentResponses, DeleteAlertData, DeleteAlertError, DeleteAlertErrors, DeleteAlertResponse, DeleteAlertResponses, DeleteAlertRuleData, DeleteAlertRuleErrors, DeleteAlertRuleResponse, DeleteAlertRuleResponses, DeleteApiKeyData, DeleteApiKeyErrors, DeleteApiKeyResponse, DeleteApiKeyResponses, DeleteBackupData, DeleteBackupError, DeleteBackupErrors, DeleteBackupResponse, DeleteBackupResponses, DeleteBackupScheduleData, DeleteBackupScheduleError, DeleteBackupScheduleErrors, DeleteBackupScheduleResponse, DeleteBackupScheduleResponses, DeleteBlobRequest, DeleteBlobResponse, DeleteConnectionData, DeleteConnectionErrors, DeleteConnectionResponse, DeleteConnectionResponses, DeleteCustomDomainData, DeleteCustomDomainErrors, DeleteCustomDomainResponse, DeleteCustomDomainResponses, DeleteDashboardData, DeleteDashboardError, DeleteDashboardErrors, DeleteDashboardResponse, DeleteDashboardResponses, DeleteDeploymentTokenData, DeleteDeploymentTokenErrors, DeleteDeploymentTokenResponse, DeleteDeploymentTokenResponses, DeleteDnsProviderData, DeleteDnsProviderErrors, DeleteDnsProviderResponse, DeleteDnsProviderResponses, DeleteDomainData, DeleteDomainErrors, DeleteDomainResponse, DeleteDomainResponses, DeleteEmailDomainData, DeleteEmailDomainErrors, DeleteEmailDomainResponse, DeleteEmailDomainResponses, DeleteEmailProviderData, DeleteEmailProviderErrors, DeleteEmailProviderResponse, DeleteEmailProviderResponses, DeleteEnvironmentData, DeleteEnvironmentDomainData, DeleteEnvironmentDomainErrors, DeleteEnvironmentDomainResponse, DeleteEnvironmentDomainResponses, DeleteEnvironmentErrors, DeleteEnvironmentResponse, DeleteEnvironmentResponses, DeleteEnvironmentVariableData, DeleteEnvironmentVariableErrors, DeleteEnvironmentVariableResponse, DeleteEnvironmentVariableResponses, DeleteExternalImageData, DeleteExternalImageErrors, DeleteExternalImageResponse, DeleteExternalImageResponses, DeleteFunnelData, DeleteFunnelErrors, DeleteFunnelResponses, DeleteGitProviderData, DeleteGitProviderErrors, DeleteGitProviderResponse, DeleteGitProviderResponses, DeleteGlobalMcpData, DeleteGlobalMcpErrors, DeleteGlobalMcpResponse, DeleteGlobalMcpResponses, DeleteGlobalSkillData, DeleteGlobalSkillErrors, DeleteGlobalSkillResponse, DeleteGlobalSkillResponses, DeleteIpAccessControlData, DeleteIpAccessControlError, DeleteIpAccessControlErrors, DeleteIpAccessControlResponse, DeleteIpAccessControlResponses, DeleteMcpData, DeleteMcpErrors, DeleteMcpResponse, DeleteMcpResponses, DeleteMonitorData, DeleteMonitorErrors, DeleteMonitorResponse, DeleteMonitorResponses, DeleteNotificationProviderData, DeleteNotificationProviderErrors, DeleteNotificationProviderResponse, DeleteNotificationProviderResponses, DeleteOidcProviderData, DeleteOidcProviderResponse, DeleteOidcProviderResponses, DeleteOidcRoleMappingData, DeleteOidcRoleMappingResponse, DeleteOidcRoleMappingResponses, DeletePreferencesData, DeletePreferencesErrors, DeletePreferencesResponse, DeletePreferencesResponses, DeleteProjectData, DeleteProjectErrors, DeleteProjectResponse, DeleteProjectResponses, DeleteProjectSecretData, DeleteProjectSecretErrors, DeleteProjectSecretResponse, DeleteProjectSecretResponses, DeleteProviderKeyData, DeleteProviderKeyError, DeleteProviderKeyErrors, DeleteProviderKeyResponse, DeleteProviderKeyResponses, DeleteProviderSafelyData, DeleteProviderSafelyErrors, DeleteProviderSafelyResponse, DeleteProviderSafelyResponses, DeleteReleaseSourceFilesData, DeleteReleaseSourceFilesErrors, DeleteReleaseSourceFilesResponse, DeleteReleaseSourceFilesResponses, DeleteReleaseSourceMapsData, DeleteReleaseSourceMapsErrors, DeleteReleaseSourceMapsResponse, DeleteReleaseSourceMapsResponses, DeleteResponse, DeleteRouteData, DeleteRouteErrors, DeleteRouteResponse, DeleteRouteResponses, DeleteS3SourceData, DeleteS3SourceError, DeleteS3SourceErrors, DeleteS3SourceResponse, DeleteS3SourceResponses, DeleteScanData, DeleteScanError, DeleteScanErrors, DeleteScanResponse, DeleteScanResponses, DeleteSecretData, DeleteSecretErrors, DeleteSecretResponse, DeleteSecretResponses, DeleteServiceData, DeleteServiceErrors, DeleteServiceResponse, DeleteServiceResponses, DeleteSessionReplayData, DeleteSessionReplayError, DeleteSessionReplayErrors, DeleteSessionReplayResponses, DeleteSkillData, DeleteSkillErrors, DeleteSkillResponse, DeleteSkillResponses, DeleteSourceMapData, DeleteSourceMapErrors, DeleteSourceMapResponse, DeleteSourceMapResponses, DeleteStaticBundleData, DeleteStaticBundleErrors, DeleteStaticBundleResponse, DeleteStaticBundleResponses, DeleteTeamData, DeleteTeamErrors, DeleteTeamResponse, DeleteTeamResponses, DeleteUserData, DeleteUserErrors, DeleteUserResponse, DeleteUserResponses, DeleteWebhookData, DeleteWebhookErrors, DeleteWebhookResponse, DeleteWebhookResponses, DelRequest, DelResponse, DeployFromImageData, DeployFromImageErrors, DeployFromImageRequest, DeployFromImageResponse, DeployFromImageResponses, DeployFromImageUploadData, DeployFromImageUploadErrors, DeployFromImageUploadQuery, DeployFromImageUploadResponse, DeployFromImageUploadResponses, DeployFromStaticData, DeployFromStaticErrors, DeployFromStaticRequest, DeployFromStaticResponse, DeployFromStaticResponses, DeploymentConfig, DeploymentConfigSnapshot, DeploymentConfiguration, DeploymentContainerLogContentResponse, DeploymentContainerLogResponse, DeploymentContainerLogsListResponse, DeploymentEnvironmentResponse, DeploymentJobResponse, DeploymentJobsResponse, DeploymentListResponse, DeploymentMetadata, DeploymentMetricsGetLatestData, DeploymentMetricsGetLatestErrors, DeploymentMetricsGetLatestResponse, DeploymentMetricsGetLatestResponses, DeploymentMetricsGetRangeData, DeploymentMetricsGetRangeErrors, DeploymentMetricsGetRangeResponse, DeploymentMetricsGetRangeResponses, DeploymentMetricsToggleData, DeploymentMetricsToggleErrors, DeploymentMetricsToggleResponses, DeploymentResponse, DeploymentStateResponse, DeploymentStrategy, DeploymentTokenListResponse, DeploymentTokenResponse, DestroySandboxData, DestroySandboxErrors, DestroySandboxResponse, DestroySandboxResponses, DetachScheduleServiceData, DetachScheduleServiceError, DetachScheduleServiceErrors, DetachScheduleServiceResponse, DetachScheduleServiceResponses, DetectionConfig, DetectPublicPresetsData, DetectPublicPresetsErrors, DetectPublicPresetsResponse, DetectPublicPresetsResponses, DeviceCount, DigestSections, Direction, DisableBackupScheduleData, DisableBackupScheduleErrors, DisableBackupScheduleResponse, DisableBackupScheduleResponses, DisableBlobResponse, DisableKvResponse, DisableMfaData, DisableMfaErrors, DisableMfaRequest, DisableMfaResponse, DisableMfaResponses, DiscoverRequest, DiscoverResponse, DiscoverWorkloadsData, DiscoverWorkloadsErrors, DiscoverWorkloadsResponse, DiscoverWorkloadsResponses, DiskInfo, DiskSpaceAlert, DiskSpaceAlertSettings, DiskSpaceCheckResult, DnsAckRequest, DnsAckResponse, DnsChallengeRecordResult, DnsChangesResponse, DnsCompletionResponse, DnsLookupError, DnsLookupRequest, DnsLookupResponse, DnsProviderCredentials, DnsProviderResponse, DnsProviderSettings, DnsProviderSettingsMasked, DnsProviderType, DnsRecord, DnsRecordChange, DnsRecordContent, DnsRecordResponse, DnsRecordSetupResult, DnsRecordStatusResponse, DnsZone, DockerComposePresetConfig, DockerfilePresetConfig, DockerfileVariant, DockerRegistrySettings, DockerRegistrySettingsMasked, DomainAction, DomainChallengeResponse, DomainData, DomainEnvironmentResponse, DomainError, DomainErrors, DomainPlan, DomainResponse, DomainResponse2, DomainResponses, DownloadGlobalSkillArchiveData, DownloadGlobalSkillArchiveErrors, DownloadGlobalSkillArchiveResponse, DownloadGlobalSkillArchiveResponses, DownloadObjectData, DownloadObjectErrors, DownloadObjectResponse, DownloadObjectResponses, DownloadSkillArchiveData, DownloadSkillArchiveErrors, DownloadSkillArchiveResponse, DownloadSkillArchiveResponses, DrainNodeResponse, DrainStatusResponse, DropOffPoint, EmailConfig, EmailDomainResponse, EmailDomainWithDnsResponse, EmailProviderResponse, EmailProviderTypeRoute, EmailRequest, EmailResponse, EmailStatsResponse, EmailStatusData, EmailStatusErrors, EmailStatusResponse, EmailStatusResponse2, EmailStatusResponses, EmailTrackingResponse, EmailTrackingSetupResponse, EmailTrackingStatusResponse, EmbeddingData, EmbeddingInput, EmbeddingRequest, EmbeddingResponse, EmbeddingsData, EmbeddingsError, EmbeddingsErrors, EmbeddingsResponse, EmbeddingsResponses, EmbeddingUsage, EnableBackupScheduleData, EnableBackupScheduleErrors, EnableBackupScheduleResponse, EnableBackupScheduleResponses, EnableBlobRequest, EnableBlobResponse, EnableKvRequest, EnableKvResponse, EnablePgStatStatementsResponse, EndpointDto, EnqueuedJob, EnrichVisitorData, EnrichVisitorErrors, EnrichVisitorRequest, EnrichVisitorResponse, EnrichVisitorResponse2, EnrichVisitorResponses, EnrollmentTokenInfo, EnrollmentTokenListResponse, EntityInfoResponse, EntityResponse, EnvironmentConfiguration, EnvironmentDomainResponse, EnvironmentInfo, EnvironmentResponse, EnvironmentVariable, EnvironmentVariableInfo, EnvironmentVariableResponse, EnvironmentVariableValueResponse, EnvVarInput, EnvVarIntegrationInfo, EnvVarResponse, EnvVarTemplateResponse, ErrorDashboardStatsQuery, ErrorDashboardStatsResponse, ErrorEventResponse, ErrorGroupResponse, ErrorGroupStatsResponse, ErrorResponse, ErrorRow, ErrorTimeSeriesDataResponse, ErrorTimeSeriesQuery, EventActivityBucket, EventBreakdown, EventBrowserStats, EventCount, EventCountryStats, EventDetailQuery, EventDetailResponse, EventEntriesQuery, EventEntriesResponse, EventEntryInfo, EventKind, EventMetricsPayload, EventReferrerStats, EventsCountQuery, EventsResponse, EventTimeline, EventTimelineQuery, EventType, EventTypeBreakdown, EventTypeBreakdownQuery, EventTypeResponse, EventTypesResponse, EventVisitorInfo, EventVisitorsQuery, EventVisitorsResponse, ExecBody, ExecData, ExecDetachedData, ExecDetachedErrors, ExecDetachedResponse, ExecDetachedResponse2, ExecDetachedResponses, ExecErrors, ExecResponse, ExecResponse2, ExecResponses, ExecuteDeploymentOperationData, ExecuteDeploymentOperationErrors, ExecuteDeploymentOperationResponse, ExecuteDeploymentOperationResponses, ExecuteImportData, ExecuteImportErrors, ExecuteImportRequest, ExecuteImportResponse, ExecuteImportResponse2, ExecuteImportResponses, ExecuteOperationRequest, ExpireRequest, ExpireResponse, ExplorerSupportResponse, ExtendTimeoutBody, ExtendTimeoutData, ExtendTimeoutErrors, ExtendTimeoutResponse, ExtendTimeoutResponses, ExternalImageResponse, ExternalServiceBackupResponse, ExternalServiceDetails, ExternalServiceEnablePgStatStatementsData, ExternalServiceEnablePgStatStatementsErrors, ExternalServiceEnablePgStatStatementsResponse, ExternalServiceEnablePgStatStatementsResponses, ExternalServiceInfo, ExternalServiceMetricsByDatabaseData, ExternalServiceMetricsByDatabaseErrors, ExternalServiceMetricsByDatabaseResponse, ExternalServiceMetricsByDatabaseResponses, ExternalServiceMetricsCreateAlertRuleData, ExternalServiceMetricsCreateAlertRuleErrors, ExternalServiceMetricsCreateAlertRuleResponse, ExternalServiceMetricsCreateAlertRuleResponses, ExternalServiceMetricsDeleteAlertRuleData, ExternalServiceMetricsDeleteAlertRuleErrors, ExternalServiceMetricsDeleteAlertRuleResponse, ExternalServiceMetricsDeleteAlertRuleResponses, ExternalServiceMetricsGetAlertRulesData, ExternalServiceMetricsGetAlertRulesErrors, ExternalServiceMetricsGetAlertRulesResponse, ExternalServiceMetricsGetAlertRulesResponses, ExternalServiceMetricsGetLatestData, ExternalServiceMetricsGetLatestErrors, ExternalServiceMetricsGetLatestResponse, ExternalServiceMetricsGetLatestResponses, ExternalServiceMetricsGetRangeData, ExternalServiceMetricsGetRangeErrors, ExternalServiceMetricsGetRangeResponse, ExternalServiceMetricsGetRangeResponses, ExternalServiceMetricsStatusData, ExternalServiceMetricsStatusErrors, ExternalServiceMetricsStatusResponse, ExternalServiceMetricsStatusResponses, ExternalServiceMetricsToggleData, ExternalServiceMetricsToggleErrors, ExternalServiceMetricsToggleResponses, ExternalServiceMetricsUpdateAlertRuleData, ExternalServiceMetricsUpdateAlertRuleErrors, ExternalServiceMetricsUpdateAlertRuleResponse, ExternalServiceMetricsUpdateAlertRuleResponses, ExternalServiceResetPgStatStatementsData, ExternalServiceResetPgStatStatementsErrors, ExternalServiceResetPgStatStatementsResponse, ExternalServiceResetPgStatStatementsResponses, ExternalServiceSummary, FieldResponse, FinalizeOrderData, FinalizeOrderErrors, FinalizeOrderResponse, FinalizeOrderResponses, FinalizeProjectReleaseData, FinalizeProjectReleaseErrors, FinalizeProjectReleaseResponse, FinalizeProjectReleaseResponses, FindConversationData, FindConversationErrors, FindConversationResponse, FindConversationResponses, FiringSeriesEntry, FlagEnvironmentResponse, FlagListResponse, FlagResponse, FlagSnapshot, FlagSnapshotResponse, FlagValueType, ForecastAlgorithm, ForecastParams, FullError, FullEvent, FullRequest, FunnelMetricsResponse, FunnelResponse, GatewayStatus, GenAiEvent, GenAiSpanDetail, GenAiTraceDetailResponse, GenAiTraceSummariesResponse, GenAiTraceSummary, GeneralStatsQuery, GeneralStatsResponse, GenerateDockerfileRequest, GenerateDockerfileResponse, GenerateJoinTokenData, GenerateJoinTokenErrors, GenerateJoinTokenResponse, GenerateJoinTokenResponse2, GenerateJoinTokenResponses, GeneratePresetDockerfileData, GeneratePresetDockerfileErrors, GeneratePresetDockerfileResponse, GeneratePresetDockerfileResponses, GeoLocationResponse, GeoRestrictionsConfig, GetAccessInfoData, GetAccessInfoErrors, GetAccessInfoResponse, GetAccessInfoResponses, GetActiveVisitorsData, GetActiveVisitorsErrors, GetActiveVisitorsResponse, GetActiveVisitorsResponses, GetActivityGraphData, GetActivityGraphErrors, GetActivityGraphResponse, GetActivityGraphResponses, GetAdminGateData, GetAdminGateErrors, GetAdminGateResponse, GetAdminGateResponses, GetAgentData, GetAgentErrors, GetAgentResponse, GetAgentResponses, GetAggregatedBucketsData, GetAggregatedBucketsErrors, GetAggregatedBucketsResponse, GetAggregatedBucketsResponses, GetAiAgentBreakdownData, GetAiAgentBreakdownError, GetAiAgentBreakdownErrors, GetAiAgentBreakdownResponse, GetAiAgentBreakdownResponses, GetAiAgentPagesData, GetAiAgentPagesError, GetAiAgentPagesErrors, GetAiAgentPagesResponse, GetAiAgentPagesResponses, GetAiAgentTimelineData, GetAiAgentTimelineError, GetAiAgentTimelineErrors, GetAiAgentTimelineResponse, GetAiAgentTimelineResponses, GetAiPageBreakdownData, GetAiPageBreakdownError, GetAiPageBreakdownErrors, GetAiPageBreakdownResponse, GetAiPageBreakdownResponses, GetAiStatusBreakdownData, GetAiStatusBreakdownError, GetAiStatusBreakdownErrors, GetAiStatusBreakdownResponse, GetAiStatusBreakdownResponses, GetAlertData, GetAlertError, GetAlertErrors, GetAlertResponse, GetAlertResponses, GetAlertRuleData, GetAlertRuleErrors, GetAlertRuleResponse, GetAlertRuleResponses, GetAllRepositoriesByNameData, GetAllRepositoriesByNameErrors, GetAllRepositoriesByNameResponse, GetAllRepositoriesByNameResponses, GetAnalyticsActiveVisitorsData, GetAnalyticsActiveVisitorsErrors, GetAnalyticsActiveVisitorsResponse, GetAnalyticsActiveVisitorsResponses, GetAnalyticsEventsCountData, GetAnalyticsEventsCountErrors, GetAnalyticsEventsCountResponse, GetAnalyticsEventsCountResponses, GetAnalyticsSessionEventsData, GetAnalyticsSessionEventsErrors, GetAnalyticsSessionEventsResponse, GetAnalyticsSessionEventsResponses, GetAnalyticsVisitorSessionsData, GetAnalyticsVisitorSessionsErrors, GetAnalyticsVisitorSessionsResponse, GetAnalyticsVisitorSessionsResponses, GetApiKeyData, GetApiKeyErrors, GetApiKeyPermissionsData, GetApiKeyPermissionsErrors, GetApiKeyPermissionsResponse, GetApiKeyPermissionsResponses, GetApiKeyResponse, GetApiKeyResponses, GetAuditLogData, GetAuditLogErrors, GetAuditLogResponse, GetAuditLogResponses, GetBackupData, GetBackupError, GetBackupErrors, GetBackupResponse, GetBackupResponses, GetBackupScheduleData, GetBackupScheduleErrors, GetBackupScheduleResponse, GetBackupScheduleResponses, GetBranchesByRepositoryIdData, GetBranchesByRepositoryIdErrors, GetBranchesByRepositoryIdResponse, GetBranchesByRepositoryIdResponses, GetBucketedIncidentsData, GetBucketedIncidentsErrors, GetBucketedIncidentsResponse, GetBucketedIncidentsResponses, GetBucketedStatusData, GetBucketedStatusErrors, GetBucketedStatusResponse, GetBucketedStatusResponses, GetChallengeTokenData, GetChallengeTokenErrors, GetChallengeTokenResponse, GetChallengeTokenResponses, GetChatReadinessData, GetChatReadinessErrors, GetChatReadinessResponse, GetChatReadinessResponses, GetCliStatusData, GetCliStatusErrors, GetCliStatusResponses, GetClusterHealthData, GetClusterHealthErrors, GetClusterHealthResponse, GetClusterHealthResponses, GetClusterMemberData, GetClusterMemberErrors, GetClusterMemberResponse, GetClusterMemberResponses, GetCmdData, GetCmdErrors, GetCmdResponse, GetCmdResponses, GetContainerDetailData, GetContainerDetailErrors, GetContainerDetailResponse, GetContainerDetailResponses, GetContainerEnvironmentVariableData, GetContainerEnvironmentVariableErrors, GetContainerEnvironmentVariableResponse, GetContainerEnvironmentVariableResponses, GetContainerInfoData, GetContainerInfoErrors, GetContainerInfoResponse, GetContainerInfoResponses, GetContainerLogsByIdData, GetContainerLogsByIdErrors, GetContainerLogsData, GetContainerLogsErrors, GetContainerMetricsData, GetContainerMetricsErrors, GetContainerMetricsResponse, GetContainerMetricsResponses, GetConversationData, GetConversationDetailData, GetConversationDetailError, GetConversationDetailErrors, GetConversationDetailResponse, GetConversationDetailResponses, GetConversationErrors, GetConversationResponse, GetConversationResponses, GetConversationsData, GetConversationsError, GetConversationsErrors, GetConversationsResponse, GetConversationsResponses, GetCronByIdData, GetCronByIdErrors, GetCronByIdResponse, GetCronByIdResponses, GetCronExecutionsData, GetCronExecutionsErrors, GetCronExecutionsResponse, GetCronExecutionsResponses, GetCrossProjectTraceSiblingsData, GetCrossProjectTraceSiblingsError, GetCrossProjectTraceSiblingsErrors, GetCrossProjectTraceSiblingsResponse, GetCrossProjectTraceSiblingsResponses, GetCurrentMonitorStatusData, GetCurrentMonitorStatusErrors, GetCurrentMonitorStatusResponse, GetCurrentMonitorStatusResponses, GetCurrentUserData, GetCurrentUserErrors, GetCurrentUserResponse, GetCurrentUserResponses, GetCustomDomainData, GetCustomDomainErrors, GetCustomDomainResponse, GetCustomDomainResponses, GetDashboardData, GetDashboardError, GetDashboardErrors, GetDashboardProjectsAnalyticsData, GetDashboardProjectsAnalyticsErrors, GetDashboardProjectsAnalyticsResponse, GetDashboardProjectsAnalyticsResponses, GetDashboardResponse, GetDashboardResponses, GetDeliveryData, GetDeliveryErrors, GetDeliveryResponse, GetDeliveryResponses, GetDeploymentContainerLogContentData, GetDeploymentContainerLogContentErrors, GetDeploymentContainerLogContentResponse, GetDeploymentContainerLogContentResponses, GetDeploymentData, GetDeploymentErrors, GetDeploymentJobLogsData, GetDeploymentJobLogsErrors, GetDeploymentJobLogsResponse, GetDeploymentJobLogsResponses, GetDeploymentJobsData, GetDeploymentJobsErrors, GetDeploymentJobsResponse, GetDeploymentJobsResponses, GetDeploymentOperationsData, GetDeploymentOperationsErrors, GetDeploymentOperationsResponse, GetDeploymentOperationsResponses, GetDeploymentOperationStatusData, GetDeploymentOperationStatusErrors, GetDeploymentOperationStatusResponse, GetDeploymentOperationStatusResponses, GetDeploymentResponse, GetDeploymentResponses, GetDeploymentsParams, GetDeploymentTokenData, GetDeploymentTokenErrors, GetDeploymentTokenResponse, GetDeploymentTokenResponses, GetDiskStatusData, GetDiskStatusErrors, GetDiskStatusResponse, GetDiskStatusResponses, GetDnsChangesData, GetDnsChangesErrors, GetDnsChangesResponse, GetDnsChangesResponses, GetDnsProviderData, GetDnsProviderErrors, GetDnsProviderResponse, GetDnsProviderResponses, GetDomainByHostData, GetDomainByHostErrors, GetDomainByHostResponse, GetDomainByHostResponses, GetDomainByIdData, GetDomainByIdErrors, GetDomainByIdResponse, GetDomainByIdResponses, GetDomainByNameData, GetDomainByNameErrors, GetDomainByNameResponse, GetDomainByNameResponses, GetDomainData, GetDomainDnsRecordsData, GetDomainDnsRecordsErrors, GetDomainDnsRecordsResponse, GetDomainDnsRecordsResponses, GetDomainErrors, GetDomainOrderData, GetDomainOrderErrors, GetDomainOrderResponse, GetDomainOrderResponses, GetDomainResponse, GetDomainResponses, GetEmailData, GetEmailErrors, GetEmailEventsData, GetEmailEventsErrors, GetEmailEventsResponse, GetEmailEventsResponses, GetEmailLinksData, GetEmailLinksErrors, GetEmailLinksResponse, GetEmailLinksResponses, GetEmailProviderData, GetEmailProviderErrors, GetEmailProviderResponse, GetEmailProviderResponses, GetEmailResponse, GetEmailResponses, GetEmailStatsData, GetEmailStatsErrors, GetEmailStatsResponse, GetEmailStatsResponses, GetEmailTrackingData, GetEmailTrackingErrors, GetEmailTrackingResponse, GetEmailTrackingResponses, GetEmailTrackingStatusData, GetEmailTrackingStatusErrors, GetEmailTrackingStatusResponse, GetEmailTrackingStatusResponses, GetEntityInfoData, GetEntityInfoErrors, GetEntityInfoResponse, GetEntityInfoResponses, GetEnvironmentCronsData, GetEnvironmentCronsErrors, GetEnvironmentCronsResponse, GetEnvironmentCronsResponses, GetEnvironmentData, GetEnvironmentDomainsData, GetEnvironmentDomainsErrors, GetEnvironmentDomainsResponse, GetEnvironmentDomainsResponses, GetEnvironmentErrors, GetEnvironmentResponse, GetEnvironmentResponses, GetEnvironmentsData, GetEnvironmentsErrors, GetEnvironmentsResponse, GetEnvironmentsResponses, GetEnvironmentVariablesData, GetEnvironmentVariablesErrors, GetEnvironmentVariablesQuery, GetEnvironmentVariablesResponse, GetEnvironmentVariablesResponses, GetEnvironmentVariableValueData, GetEnvironmentVariableValueErrors, GetEnvironmentVariableValueResponse, GetEnvironmentVariableValueResponses, GetErrorDashboardStatsData, GetErrorDashboardStatsErrors, GetErrorDashboardStatsResponse, GetErrorDashboardStatsResponses, GetErrorEventData, GetErrorEventErrors, GetErrorEventResponse, GetErrorEventResponses, GetErrorGroupData, GetErrorGroupErrors, GetErrorGroupResponse, GetErrorGroupResponses, GetErrorStatsData, GetErrorStatsErrors, GetErrorStatsResponse, GetErrorStatsResponses, GetErrorTimeSeriesData, GetErrorTimeSeriesErrors, GetErrorTimeSeriesResponse, GetErrorTimeSeriesResponses, GetEventDetailData, GetEventDetailErrors, GetEventDetailResponse, GetEventDetailResponses, GetEventEntriesData, GetEventEntriesErrors, GetEventEntriesResponse, GetEventEntriesResponses, GetEventsCountData, GetEventsCountErrors, GetEventsCountResponse, GetEventsCountResponses, GetEventsTimelineData, GetEventsTimelineErrors, GetEventsTimelineResponse, GetEventsTimelineResponses, GetEventTypeBreakdownData, GetEventTypeBreakdownErrors, GetEventTypeBreakdownResponse, GetEventTypeBreakdownResponses, GetEventVisitorsData, GetEventVisitorsErrors, GetEventVisitorsResponse, GetEventVisitorsResponses, GetExternalImageData, GetExternalImageErrors, GetExternalImageResponse, GetExternalImageResponses, GetFileData, GetFileErrors, GetFileResponse, GetFileResponses, GetFlagData, GetFlagErrors, GetFlagResponse, GetFlagResponses, GetFlagSnapshotData, GetFlagSnapshotErrors, GetFlagSnapshotResponse, GetFlagSnapshotResponses, GetFunnelMetricsData, GetFunnelMetricsErrors, GetFunnelMetricsQuery, GetFunnelMetricsResponse, GetFunnelMetricsResponses, GetGenaiTraceData, GetGenaiTraceError, GetGenaiTraceErrors, GetGenaiTraceResponse, GetGenaiTraceResponses, GetGeneralStatsData, GetGeneralStatsErrors, GetGeneralStatsResponse, GetGeneralStatsResponses, GetGitProviderData, GetGitProviderErrors, GetGitProviderResponse, GetGitProviderResponses, GetGlobalEventsData, GetGlobalEventsErrors, GetGlobalEventsResponse, GetGlobalEventsResponses, GetGlobalEventStatsData, GetGlobalEventStatsErrors, GetGlobalEventStatsResponse, GetGlobalEventStatsResponses, GetGlobalMcpData, GetGlobalMcpErrors, GetGlobalMcpResponse, GetGlobalMcpResponses, GetGlobalSandboxStatusData, GetGlobalSandboxStatusErrors, GetGlobalSandboxStatusResponse, GetGlobalSandboxStatusResponses, GetGlobalSkillData, GetGlobalSkillErrors, GetGlobalSkillResponse, GetGlobalSkillResponses, GetGroupedPageMetricsData, GetGroupedPageMetricsError, GetGroupedPageMetricsErrors, GetGroupedPageMetricsResponse, GetGroupedPageMetricsResponses, GetHealthData, GetHealthError, GetHealthErrors, GetHealthResponse, GetHealthResponses, GetHourlyVisitsData, GetHourlyVisitsErrors, GetHourlyVisitsResponse, GetHourlyVisitsResponses, GetHttpChallengeDebugData, GetHttpChallengeDebugErrors, GetHttpChallengeDebugResponse, GetHttpChallengeDebugResponses, GetImportStatusData, GetImportStatusErrors, GetImportStatusResponse, GetImportStatusResponses, GetIncidentData, GetIncidentErrors, GetIncidentResponse, GetIncidentResponses, GetIncidentUpdatesData, GetIncidentUpdatesErrors, GetIncidentUpdatesResponse, GetIncidentUpdatesResponses, GetIpAccessControlData, GetIpAccessControlError, GetIpAccessControlErrors, GetIpAccessControlResponse, GetIpAccessControlResponses, GetIpGeolocationData, GetIpGeolocationError, GetIpGeolocationErrors, GetIpGeolocationResponse, GetIpGeolocationResponses, GetJoinTokenStatusData, GetJoinTokenStatusErrors, GetJoinTokenStatusResponse, GetJoinTokenStatusResponses, GetLastDeploymentData, GetLastDeploymentErrors, GetLastDeploymentResponse, GetLastDeploymentResponses, GetLatestScanData, GetLatestScanError, GetLatestScanErrors, GetLatestScanResponse, GetLatestScanResponses, GetLatestScansPerEnvironmentData, GetLatestScansPerEnvironmentError, GetLatestScansPerEnvironmentErrors, GetLatestScansPerEnvironmentResponse, GetLatestScansPerEnvironmentResponses, GetLiveVisitorsListData, GetLiveVisitorsListErrors, GetLiveVisitorsListResponse, GetLiveVisitorsListResponses, GetLogContextData, GetLogContextError, GetLogContextErrors, GetLogContextResponse, GetLogContextResponses, GetMcpData, GetMcpErrors, GetMcpResponse, GetMcpResponses, GetMetricsOverTimeData, GetMetricsOverTimeError, GetMetricsOverTimeErrors, GetMetricsOverTimeResponse, GetMetricsOverTimeResponses, GetMonitorData, GetMonitorErrors, GetMonitorResponse, GetMonitorResponses, GetNotificationProviderData, GetNotificationProviderErrors, GetNotificationProviderResponse, GetNotificationProviderResponses, GetOnDemandCertStatusData, GetOnDemandCertStatusErrors, GetOnDemandCertStatusResponse, GetOnDemandCertStatusResponses, GetOrCreateDsnData, GetOrCreateDsnErrors, GetOrCreateDsnRequest, GetOrCreateDsnResponse, GetOrCreateDsnResponses, GetPageFlowData, GetPageFlowErrors, GetPageFlowResponse, GetPageFlowResponses, GetPageHourlySessionsData, GetPageHourlySessionsErrors, GetPageHourlySessionsResponse, GetPageHourlySessionsResponses, GetPagePathDetailData, GetPagePathDetailErrors, GetPagePathDetailResponse, GetPagePathDetailResponses, GetPagePathsData, GetPagePathsErrors, GetPagePathsResponse, GetPagePathsResponses, GetPagePathsSparklinesData, GetPagePathsSparklinesErrors, GetPagePathsSparklinesResponse, GetPagePathsSparklinesResponses, GetPagePathVisitorsData, GetPagePathVisitorsErrors, GetPagePathVisitorsResponse, GetPagePathVisitorsResponses, GetPendingActionData, GetPendingActionErrors, GetPendingActionResponse, GetPendingActionResponses, GetPerformanceMetricsData, GetPerformanceMetricsError, GetPerformanceMetricsErrors, GetPerformanceMetricsResponse, GetPerformanceMetricsResponses, GetPgUpgradeData, GetPgUpgradeErrors, GetPgUpgradeLogsData, GetPgUpgradeLogsErrors, GetPgUpgradeLogsResponse, GetPgUpgradeLogsResponses, GetPgUpgradeResponse, GetPgUpgradeResponses, GetPipelineStatsData, GetPipelineStatsError, GetPipelineStatsErrors, GetPipelineStatsResponse, GetPipelineStatsResponses, GetPlatformInfoData, GetPlatformInfoErrors, GetPlatformInfoResponse, GetPlatformInfoResponses, GetPostgresWalHealthData, GetPostgresWalHealthErrors, GetPostgresWalHealthResponse, GetPostgresWalHealthResponses, GetPreferencesData, GetPreferencesErrors, GetPreferencesResponse, GetPreferencesResponses, GetPreviewGatewayLogsData, GetPreviewGatewayLogsResponse, GetPreviewGatewayLogsResponses, GetPreviewGatewaySettingsData, GetPreviewGatewaySettingsResponse, GetPreviewGatewaySettingsResponses, GetPreviewGatewayStatusData, GetPreviewGatewayStatusResponse, GetPreviewGatewayStatusResponses, GetPricingData, GetPricingError, GetPricingErrors, GetPricingResponse, GetPricingResponses, GetPrivateIpData, GetPrivateIpErrors, GetPrivateIpResponses, GetProjectAlarmsSummaryData, GetProjectAlarmsSummaryErrors, GetProjectAlarmsSummaryResponse, GetProjectAlarmsSummaryResponses, GetProjectBySlugData, GetProjectBySlugErrors, GetProjectBySlugResponse, GetProjectBySlugResponses, GetProjectData, GetProjectDeploymentsData, GetProjectDeploymentsErrors, GetProjectDeploymentsResponse, GetProjectDeploymentsResponses, GetProjectErrors, GetProjectResponse, GetProjectResponses, GetProjectsData, GetProjectSecretsQuery, GetProjectsErrors, GetProjectServiceEnvironmentVariablesData, GetProjectServiceEnvironmentVariablesErrors, GetProjectServiceEnvironmentVariablesResponse, GetProjectServiceEnvironmentVariablesResponses, GetProjectSessionReplaysData, GetProjectSessionReplaysError, GetProjectSessionReplaysErrors, GetProjectSessionReplaysQuery, GetProjectSessionReplaysResponse, GetProjectSessionReplaysResponse2, GetProjectSessionReplaysResponses, GetProjectsHealthData, GetProjectsHealthError, GetProjectsHealthErrors, GetProjectsHealthResponse, GetProjectsHealthResponses, GetProjectsMonitorHealthData, GetProjectsMonitorHealthErrors, GetProjectsMonitorHealthResponse, GetProjectsMonitorHealthResponses, GetProjectsResponse, GetProjectsResponses, GetProjectStatisticsData, GetProjectStatisticsErrors, GetProjectStatisticsResponse, GetProjectStatisticsResponses, GetProjectTemplateData, GetProjectTemplateErrors, GetProjectTemplateResponse, GetProjectTemplateResponses, GetPropertyBreakdownData, GetPropertyBreakdownErrors, GetPropertyBreakdownResponse, GetPropertyBreakdownResponses, GetPropertyTimelineData, GetPropertyTimelineErrors, GetPropertyTimelineResponse, GetPropertyTimelineResponses, GetProviderConnectionsData, GetProviderConnectionsErrors, GetProviderConnectionsResponse, GetProviderConnectionsResponses, GetProviderMetadataData, GetProviderMetadataErrors, GetProviderMetadataResponse, GetProviderMetadataResponses, GetProvidersMetadataData, GetProvidersMetadataErrors, GetProvidersMetadataResponse, GetProvidersMetadataResponses, GetProxyLogByIdData, GetProxyLogByIdError, GetProxyLogByIdErrors, GetProxyLogByIdResponse, GetProxyLogByIdResponses, GetProxyLogByRequestIdData, GetProxyLogByRequestIdError, GetProxyLogByRequestIdErrors, GetProxyLogByRequestIdResponse, GetProxyLogByRequestIdResponses, GetProxyLogsData, GetProxyLogsError, GetProxyLogsErrors, GetProxyLogsResponse, GetProxyLogsResponses, GetPublicBranchesData, GetPublicBranchesErrors, GetPublicBranchesResponse, GetPublicBranchesResponses, GetPublicIpData, GetPublicIpErrors, GetPublicIpResponses, GetPublicRepositoryData, GetPublicRepositoryErrors, GetPublicRepositoryResponse, GetPublicRepositoryResponses, GetQuotaData, GetQuotaError, GetQuotaErrors, GetQuotaResponse, GetQuotaResponses, GetRecentActivityData, GetRecentActivityErrors, GetRecentActivityResponse, GetRecentActivityResponses, GetRemoteExternalImageData, GetRemoteExternalImageErrors, GetRemoteExternalImageResponse, GetRemoteExternalImageResponses, GetRepositoryBranchesData, GetRepositoryBranchesErrors, GetRepositoryBranchesResponse, GetRepositoryBranchesResponses, GetRepositoryByIdData, GetRepositoryByIdErrors, GetRepositoryByIdResponse, GetRepositoryByIdResponses, GetRepositoryByNameData, GetRepositoryByNameErrors, GetRepositoryByNameResponse, GetRepositoryByNameResponses, GetRepositoryPresetByNameData, GetRepositoryPresetByNameErrors, GetRepositoryPresetByNameResponse, GetRepositoryPresetByNameResponses, GetRepositoryPresetLiveData, GetRepositoryPresetLiveErrors, GetRepositoryPresetLiveResponse, GetRepositoryPresetLiveResponses, GetRepositoryTagsData, GetRepositoryTagsErrors, GetRepositoryTagsResponse, GetRepositoryTagsResponses, GetRequest, GetResolvedEnvironmentVariablesData, GetResolvedEnvironmentVariablesErrors, GetResolvedEnvironmentVariablesResponse, GetResolvedEnvironmentVariablesResponses, GetResolvedEnvironmentVariableValueData, GetResolvedEnvironmentVariableValueErrors, GetResolvedEnvironmentVariableValueResponse, GetResolvedEnvironmentVariableValueResponses, GetResponse, GetRestoreCapabilitiesData, GetRestoreCapabilitiesError, GetRestoreCapabilitiesErrors, GetRestoreCapabilitiesResponse, GetRestoreCapabilitiesResponses, GetRestoreRunData, GetRestoreRunError, GetRestoreRunErrors, GetRestoreRunResponse, GetRestoreRunResponses, GetRouteData, GetRouteErrors, GetRouteResponse, GetRouteResponses, GetRunData, GetRunErrors, GetRunResponse, GetRunResponses, GetRunWithLogsData, GetRunWithLogsErrors, GetRunWithLogsResponse, GetRunWithLogsResponses, GetS3CredentialsData, GetS3CredentialsErrors, GetS3CredentialsResponse, GetS3CredentialsResponses, GetS3SourceData, GetS3SourceError, GetS3SourceErrors, GetS3SourceResponse, GetS3SourceResponses, GetSandboxData, GetSandboxErrors, GetSandboxResponse, GetSandboxResponses, GetSandboxStatusData, GetSandboxStatusErrors, GetSandboxStatusResponse, GetSandboxStatusResponses, GetScanByDeploymentData, GetScanByDeploymentError, GetScanByDeploymentErrors, GetScanByDeploymentResponse, GetScanByDeploymentResponses, GetScanData, GetScanError, GetScanErrors, GetScanResponse, GetScanResponses, GetScanVulnerabilitiesData, GetScanVulnerabilitiesError, GetScanVulnerabilitiesErrors, GetScanVulnerabilitiesResponse, GetScanVulnerabilitiesResponses, GetServiceBySlugData, GetServiceBySlugErrors, GetServiceBySlugResponse, GetServiceBySlugResponses, GetServiceData, GetServiceEnvironmentVariableData, GetServiceEnvironmentVariableErrors, GetServiceEnvironmentVariableResponse, GetServiceEnvironmentVariableResponses, GetServiceEnvironmentVariablesData, GetServiceEnvironmentVariablesErrors, GetServiceEnvironmentVariablesResponse, GetServiceEnvironmentVariablesResponses, GetServiceErrors, GetServiceHealthStatusData, GetServiceHealthStatusErrors, GetServiceHealthStatusResponse, GetServiceHealthStatusResponses, GetServicePreviewEnvironmentVariableNamesData, GetServicePreviewEnvironmentVariableNamesErrors, GetServicePreviewEnvironmentVariableNamesResponse, GetServicePreviewEnvironmentVariableNamesResponses, GetServicePreviewEnvironmentVariablesMaskedData, GetServicePreviewEnvironmentVariablesMaskedErrors, GetServicePreviewEnvironmentVariablesMaskedResponse, GetServicePreviewEnvironmentVariablesMaskedResponses, GetServiceResponse, GetServiceResponses, GetServiceRuntimeData, GetServiceRuntimeErrors, GetServiceRuntimeResponse, GetServiceRuntimeResponses, GetServiceStatsData, GetServiceStatsErrors, GetServiceStatsResponse, GetServiceStatsResponses, GetServiceTypeParametersData, GetServiceTypeParametersErrors, GetServiceTypeParametersResponses, GetServiceTypesData, GetServiceTypesErrors, GetServiceTypesResponse, GetServiceTypesResponses, GetSessionDetailsData, GetSessionDetailsErrors, GetSessionDetailsResponse, GetSessionDetailsResponses, GetSessionEventsData, GetSessionEventsErrors, GetSessionEventsResponse, GetSessionEventsResponses, GetSessionLogsData, GetSessionLogsErrors, GetSessionLogsResponse, GetSessionLogsResponses, GetSessionReplayData, GetSessionReplayError, GetSessionReplayErrors, GetSessionReplayEventsData, GetSessionReplayEventsError, GetSessionReplayEventsErrors, GetSessionReplayEventsResponse, GetSessionReplayEventsResponses, GetSessionReplayResponse, GetSessionReplayResponse2, GetSessionReplayResponses, GetSettingsData, GetSettingsErrors, GetSettingsResponse, GetSettingsResponses, GetSkillData, GetSkillErrors, GetSkillResponse, GetSkillResponses, GetSlowQueriesData, GetSlowQueriesErrors, GetSlowQueriesResponse, GetSlowQueriesResponses, GetStaticBundleData, GetStaticBundleErrors, GetStaticBundleResponse, GetStaticBundleResponses, GetStatusOverviewData, GetStatusOverviewErrors, GetStatusOverviewResponse, GetStatusOverviewResponses, GetTagsByRepositoryIdData, GetTagsByRepositoryIdErrors, GetTagsByRepositoryIdResponse, GetTagsByRepositoryIdResponses, GetTeamData, GetTeamErrors, GetTeamResponse, GetTeamResponses, GetTimeBucketStatsData, GetTimeBucketStatsError, GetTimeBucketStatsErrors, GetTimeBucketStatsResponse, GetTimeBucketStatsResponses, GetTodayStatsData, GetTodayStatsError, GetTodayStatsErrors, GetTodayStatsResponse, GetTodayStatsResponses, GetTraceData, GetTraceError, GetTraceErrors, GetTraceResponse, GetTraceResponses, GetUnifiedTraceData, GetUnifiedTraceError, GetUnifiedTraceErrors, GetUnifiedTraceResponse, GetUnifiedTraceResponses, GetUniqueCountsData, GetUniqueCountsErrors, GetUniqueCountsResponse, GetUniqueCountsResponses, GetUniqueEventsData, GetUniqueEventsErrors, GetUniqueEventsQuery, GetUniqueEventsResponse, GetUniqueEventsResponses, GetUpdateStatusData, GetUpdateStatusErrors, GetUpdateStatusResponse, GetUpdateStatusResponses, GetUptimeHistoryData, GetUptimeHistoryErrors, GetUptimeHistoryResponse, GetUptimeHistoryResponses, GetUsageByProviderData, GetUsageByProviderError, GetUsageByProviderErrors, GetUsageByProviderResponse, GetUsageByProviderResponses, GetUsageRecentData, GetUsageRecentError, GetUsageRecentErrors, GetUsageRecentResponse, GetUsageRecentResponses, GetUsageSummaryData, GetUsageSummaryError, GetUsageSummaryErrors, GetUsageSummaryResponse, GetUsageSummaryResponses, GetUsageTimeseriesData, GetUsageTimeseriesError, GetUsageTimeseriesErrors, GetUsageTimeseriesResponse, GetUsageTimeseriesResponses, GetUsageTopModelsData, GetUsageTopModelsError, GetUsageTopModelsErrors, GetUsageTopModelsResponse, GetUsageTopModelsResponses, GetVisitorByGuidData, GetVisitorByGuidErrors, GetVisitorByGuidResponse, GetVisitorByGuidResponses, GetVisitorByIdData, GetVisitorByIdErrors, GetVisitorByIdResponse, GetVisitorByIdResponses, GetVisitorDetailsData, GetVisitorDetailsErrors, GetVisitorDetailsResponse, GetVisitorDetailsResponses, GetVisitorFacetsData, GetVisitorFacetsErrors, GetVisitorFacetsResponse, GetVisitorFacetsResponses, GetVisitorInfoData, GetVisitorInfoErrors, GetVisitorInfoResponse, GetVisitorInfoResponses, GetVisitorJourneyData, GetVisitorJourneyErrors, GetVisitorJourneyResponse, GetVisitorJourneyResponses, GetVisitorsData, GetVisitorsErrors, GetVisitorSessionsData, GetVisitorSessionsError, GetVisitorSessionsErrors, GetVisitorSessionsQuery, GetVisitorSessionsResponse, GetVisitorSessionsResponse2, GetVisitorSessionsResponses, GetVisitorsResponse, GetVisitorsResponses, GetVisitorStatsData, GetVisitorStatsErrors, GetVisitorStatsResponse, GetVisitorStatsResponses, GetWebhookData, GetWebhookErrors, GetWebhookResponse, GetWebhookResponses, GitPushEvent, GitRefResponse, GitSourcePlan, GlobalConversationResponse, GlobalEventStatsResponse, GlobalMrrResponse, GlobalRecentEventResponse, GlobalRevenueSummaryResponse, GrantProjectAccessData, GrantProjectAccessErrors, GrantProjectAccessResponse, GrantProjectAccessResponses, GroupedPageMetric, GroupedPageMetricsQuery, GroupedPageMetricsResponse, HandleGitProviderOauthCallbackData, HandleGitProviderOauthCallbackErrors, HasAnalyticsEventsData, HasAnalyticsEventsErrors, HasAnalyticsEventsResponse, HasAnalyticsEventsResponse2, HasAnalyticsEventsResponses, HasErrorGroupsData, HasErrorGroupsErrors, HasErrorGroupsResponse, HasErrorGroupsResponse2, HasErrorGroupsResponses, HasEventsQuery, HasEventsResponse, HasMetricsQuery, HasMetricsResponse, HasPerformanceMetricsData, HasPerformanceMetricsError, HasPerformanceMetricsErrors, HasPerformanceMetricsResponse, HasPerformanceMetricsResponses, HealthCheckConfiguration, HealthCheckEntryResponse, HealthResponse, HealthStatus, HealthSummary, HeartbeatApiRequest, HeartbeatResponse, HierarchyLevel, HistogramSummary, HostnameChange, HostnamePreviewResponse, HourlyPageSessions, HourlyVisitsQuery, HttpChallengeDebugResponse, ImportCredentials, ImportExecutionStatus, ImportExternalServiceData, ImportExternalServiceErrors, ImportExternalServiceRequest, ImportExternalServiceResponse, ImportExternalServiceResponses, ImportOutcomeResponse, ImportPlan, ImportRowErrorResponse, ImportSelector, ImportSource, ImportSourceCapabilities, ImportSourceInfo, ImportStatusResponse, IncidentBucket, IncidentBucketedResponse, IncidentResponse, IncidentUpdateResponse, IncrRequest, IncrResponse, IngestLogsByPathData, IngestLogsByPathError, IngestLogsByPathErrors, IngestLogsByPathResponses, IngestLogsData, IngestLogsError, IngestLogsErrors, IngestLogsResponses, IngestMetricsByPathData, IngestMetricsByPathError, IngestMetricsByPathErrors, IngestMetricsByPathResponses, IngestMetricsData, IngestMetricsError, IngestMetricsErrors, IngestMetricsResponses, IngestSentryEnvelopeData, IngestSentryEnvelopeErrors, IngestSentryEnvelopeResponses, IngestSentryEventData, IngestSentryEventErrors, IngestSentryEventResponse, IngestSentryEventResponses, IngestTracesByPathData, IngestTracesByPathError, IngestTracesByPathErrors, IngestTracesByPathResponses, IngestTracesData, IngestTracesError, IngestTracesErrors, IngestTracesResponses, InitAuthResponse, InitSessionReplayData, InitSessionReplayError, InitSessionReplayErrors, InitSessionReplayResponse, InitSessionReplayResponses, Insight, InsightSeverity, InsightsResponse, InsightStatus, IntegrationResponse, IpAccessControlQuery, IpAccessControlResponse, JobLogsData, JobLogsErrors, JobLogsResponses, JobStatusData, JobStatusErrors, JobStatusResponse, JobStatusResponse2, JobStatusResponses, JobSummaryResponse, JoinTokenStatusResponse, JourneyEvent, JourneySession, KeysRequest, KeysResponse, KillJobBody, KillJobData, KillJobErrors, KillJobResponse, KillJobResponses, KnownAiAgentsResponse, KvDelData, KvDelErrors, KvDelResponse, KvDelResponses, KvDisableData, KvDisableErrors, KvDisableResponse, KvDisableResponses, KvEnableData, KvEnableErrors, KvEnableResponse, KvEnableResponses, KvExpireData, KvExpireErrors, KvExpireResponse, KvExpireResponses, KvGetData, KvGetErrors, KvGetResponse, KvGetResponses, KvIncrData, KvIncrErrors, KvIncrResponse, KvIncrResponses, KvKeysData, KvKeysErrors, KvKeysResponse, KvKeysResponses, KvSetData, KvSetErrors, KvSetResponse, KvSetResponses, KvStatusData, KvStatusErrors, KvStatusResponse, KvStatusResponse2, KvStatusResponses, KvTtlData, KvTtlErrors, KvTtlResponse, KvTtlResponses, KvUpdateData, KvUpdateErrors, KvUpdateResponse, KvUpdateResponses, LatestRunForSourceData, LatestRunForSourceErrors, LatestRunForSourceResponse, LatestRunForSourceResponses, LemonSqueezyConfig, LetsEncryptSettings, LineContext, LinkCustomDomainToCertificateData, LinkCustomDomainToCertificateErrors, LinkCustomDomainToCertificateResponse, LinkCustomDomainToCertificateResponses, LinkServiceRequest, LinkServiceToProjectData, LinkServiceToProjectErrors, LinkServiceToProjectResponse, LinkServiceToProjectResponses, ListAgentRunsData, ListAgentRunsErrors, ListAgentRunsResponse, ListAgentRunsResponses, ListAgentsData, ListAgentsErrors, ListAgentsResponse, ListAgentsResponse2, ListAgentsResponses, ListAiProvidersData, ListAiProvidersErrors, ListAiProvidersResponse, ListAiProvidersResponses, ListAlertRulesData, ListAlertRulesErrors, ListAlertRulesResponse, ListAlertRulesResponses, ListAlertsData, ListAlertsError, ListAlertsErrors, ListAlertsResponse, ListAlertsResponses, ListAllConversationsData, ListAllConversationsErrors, ListAllConversationsResponse, ListAllConversationsResponses, ListAllRunsData, ListAllRunsErrors, ListAllRunsResponse, ListAllRunsResponses, ListApiKeysData, ListApiKeysErrors, ListApiKeysQuery, ListApiKeysResponse, ListApiKeysResponses, ListAuditLogsData, ListAuditLogsErrors, ListAuditLogsQuery, ListAuditLogsResponse, ListAuditLogsResponses, ListAvailableContainersData, ListAvailableContainersErrors, ListAvailableContainersResponse, ListAvailableContainersResponses, ListBackupAlertsData, ListBackupAlertsError, ListBackupAlertsErrors, ListBackupAlertsResponse, ListBackupAlertsResponses, ListBackupChildrenData, ListBackupChildrenError, ListBackupChildrenErrors, ListBackupChildrenResponse, ListBackupChildrenResponses, ListBackupSchedulesData, ListBackupSchedulesError, ListBackupSchedulesErrors, ListBackupSchedulesResponse, ListBackupSchedulesResponses, ListBackupsForScheduleData, ListBackupsForScheduleErrors, ListBackupsForScheduleResponse, ListBackupsForScheduleResponses, ListBlobsQuery, ListBlobsResponse, ListCommitsByRepositoryIdData, ListCommitsByRepositoryIdErrors, ListCommitsByRepositoryIdResponse, ListCommitsByRepositoryIdResponses, ListConnectionsData, ListConnectionsErrors, ListConnectionsResponse, ListConnectionsResponses, ListContainersAtPathData, ListContainersAtPathErrors, ListContainersAtPathResponse, ListContainersAtPathResponses, ListContainersData, ListContainersErrors, ListContainersResponse, ListContainersResponses, ListConversationsData, ListConversationsErrors, ListConversationsResponse, ListConversationsResponses, ListCustomDomainsForProjectData, ListCustomDomainsForProjectErrors, ListCustomDomainsForProjectResponse, ListCustomDomainsForProjectResponses, ListCustomDomainsResponse, ListDashboardsData, ListDashboardsError, ListDashboardsErrors, ListDashboardsResponse, ListDashboardsResponses, ListDeliveriesData, ListDeliveriesErrors, ListDeliveriesResponse, ListDeliveriesResponses, ListDeploymentContainerLogsData, ListDeploymentContainerLogsErrors, ListDeploymentContainerLogsResponse, ListDeploymentContainerLogsResponses, ListDeploymentTokensData, ListDeploymentTokensErrors, ListDeploymentTokensQuery, ListDeploymentTokensResponse, ListDeploymentTokensResponses, ListDnsProvidersData, ListDnsProvidersErrors, ListDnsProvidersResponse, ListDnsProvidersResponses, ListDomainsData, ListDomainsErrors, ListDomainsResponse, ListDomainsResponse2, ListDomainsResponses, ListDsnsData, ListDsnsErrors, ListDsnsResponse, ListDsnsResponses, ListEmailDomainsData, ListEmailDomainsErrors, ListEmailDomainsResponse, ListEmailDomainsResponses, ListEmailProvidersData, ListEmailProvidersErrors, ListEmailProvidersResponse, ListEmailProvidersResponses, ListEmailsData, ListEmailsErrors, ListEmailsResponse, ListEmailsResponses, ListEnrollmentTokensData, ListEnrollmentTokensErrors, ListEnrollmentTokensResponse, ListEnrollmentTokensResponses, ListEntitiesData, ListEntitiesErrors, ListEntitiesQuery, ListEntitiesResponse, ListEntitiesResponses, ListErrorEventsData, ListErrorEventsErrors, ListErrorEventsQuery, ListErrorEventsResponse, ListErrorEventsResponses, ListErrorGroupsData, ListErrorGroupsErrors, ListErrorGroupsQuery, ListErrorGroupsResponse, ListErrorGroupsResponses, ListEventsData, ListEventsResponse, ListEventsResponses, ListEventTypesData, ListEventTypesResponse, ListEventTypesResponses, ListExternalImagesData, ListExternalImagesErrors, ListExternalImagesResponse, ListExternalImagesResponses, ListExternalPluginsData, ListExternalPluginsErrors, ListExternalPluginsResponse, ListExternalPluginsResponses, ListExternalServiceBackupsData, ListExternalServiceBackupsError, ListExternalServiceBackupsErrors, ListExternalServiceBackupsResponse, ListExternalServiceBackupsResponses, ListFlagsData, ListFlagsErrors, ListFlagsResponse, ListFlagsResponses, ListFunnelsData, ListFunnelsErrors, ListFunnelsResponse, ListFunnelsResponses, ListGitProvidersData, ListGitProvidersErrors, ListGitProvidersResponse, ListGitProvidersResponses, ListGlobalMcpsData, ListGlobalMcpsErrors, ListGlobalMcpsResponse, ListGlobalMcpsResponses, ListGlobalSkillsData, ListGlobalSkillsErrors, ListGlobalSkillsResponse, ListGlobalSkillsResponses, ListIncidentsData, ListIncidentsErrors, ListIncidentsResponses, ListInsightsData, ListInsightsError, ListInsightsErrors, ListInsightsResponse, ListInsightsResponses, ListIpAccessControlData, ListIpAccessControlError, ListIpAccessControlErrors, ListIpAccessControlResponse, ListIpAccessControlResponses, ListJobsData, ListJobsErrors, ListJobsResponse, ListJobsResponse2, ListJobsResponses, ListKnownAiAgentsData, ListKnownAiAgentsError, ListKnownAiAgentsErrors, ListKnownAiAgentsResponse, ListKnownAiAgentsResponses, ListManagedDomainsData, ListManagedDomainsErrors, ListManagedDomainsResponse, ListManagedDomainsResponses, ListMcpsData, ListMcpsErrors, ListMcpsResponse, ListMcpsResponse2, ListMcpsResponses, ListMetricLabelKeysData, ListMetricLabelKeysError, ListMetricLabelKeysErrors, ListMetricLabelKeysResponse, ListMetricLabelKeysResponses, ListMetricLabelValuesData, ListMetricLabelValuesError, ListMetricLabelValuesErrors, ListMetricLabelValuesResponse, ListMetricLabelValuesResponses, ListMetricNamesData, ListMetricNamesError, ListMetricNamesErrors, ListMetricNamesResponse, ListMetricNamesResponses, ListModelsData, ListModelsError, ListModelsErrors, ListModelsResponse, ListModelsResponses, ListMonitorsData, ListMonitorsErrors, ListMonitorsResponse, ListMonitorsResponses, ListNotificationProvidersData, ListNotificationProvidersErrors, ListNotificationProvidersResponse, ListNotificationProvidersResponses, ListOidcProvidersData, ListOidcProvidersResponse, ListOidcProvidersResponses, ListOidcProviderUsersData, ListOidcProviderUsersErrors, ListOidcProviderUsersResponse, ListOidcProviderUsersResponses, ListOidcRoleMappingsData, ListOidcRoleMappingsResponse, ListOidcRoleMappingsResponses, ListOnDemandCertsData, ListOnDemandCertsErrors, ListOnDemandCertsResponse, ListOnDemandCertsResponse2, ListOnDemandCertsResponses, ListOrdersData, ListOrdersErrors, ListOrdersResponse, ListOrdersResponse2, ListOrdersResponses, ListPeersData, ListPeersErrors, ListPeersResponse, ListPeersResponses, ListPendingActionsData, ListPendingActionsErrors, ListPendingActionsResponse, ListPendingActionsResponses, ListPgUpgradesData, ListPgUpgradesErrors, ListPgUpgradesResponse, ListPgUpgradesResponses, ListPresetsData, ListPresetsErrors, ListPresetsResponse, ListPresetsResponse2, ListPresetsResponses, ListProjectAccessData, ListProjectAccessErrors, ListProjectAccessResponse, ListProjectAccessResponses, ListProjectAlarmsData, ListProjectAlarmsErrors, ListProjectAlarmsResponse, ListProjectAlarmsResponses, ListProjectScansData, ListProjectScansError, ListProjectScansErrors, ListProjectScansResponse, ListProjectScansResponses, ListProjectSecretsData, ListProjectSecretsErrors, ListProjectSecretsResponse, ListProjectSecretsResponses, ListProjectServicesData, ListProjectServicesErrors, ListProjectServicesResponse, ListProjectServicesResponses, ListProjectTemplatesData, ListProjectTemplatesErrors, ListProjectTemplatesResponse, ListProjectTemplatesResponses, ListProjectTemplateTagsData, ListProjectTemplateTagsErrors, ListProjectTemplateTagsResponse, ListProjectTemplateTagsResponses, ListProviderKeysData, ListProviderKeysError, ListProviderKeysErrors, ListProviderKeysResponse, ListProviderKeysResponses, ListProviderZonesData, ListProviderZonesErrors, ListProviderZonesResponse, ListProviderZonesResponses, ListPublicProvidersData, ListPublicProvidersResponse, ListPublicProvidersResponses, ListReleaseFilesData, ListReleaseFilesErrors, ListReleaseFilesResponse, ListReleaseFilesResponses, ListReleasesData, ListReleasesErrors, ListReleasesResponse, ListReleasesResponses, ListRemoteExternalImagesData, ListRemoteExternalImagesErrors, ListRemoteExternalImagesResponse, ListRemoteExternalImagesResponses, ListRepositoriesByConnectionData, ListRepositoriesByConnectionErrors, ListRepositoriesByConnectionResponse, ListRepositoriesByConnectionResponses, ListRepositoriesByProviderData, ListRepositoriesByProviderErrors, ListRepositoriesByProviderResponse, ListRepositoriesByProviderResponses, ListRestoreRunsForServiceData, ListRestoreRunsForServiceResponse, ListRestoreRunsForServiceResponses, ListRootContainersData, ListRootContainersErrors, ListRootContainersResponse, ListRootContainersResponses, ListRoutesData, ListRoutesErrors, ListRoutesResponse, ListRoutesResponses, ListRunsResponse, ListS3SourcesData, ListS3SourcesError, ListS3SourcesErrors, ListS3SourcesResponse, ListS3SourcesResponses, ListSandboxesData, ListSandboxesResponse, ListSandboxesResponse2, ListSandboxesResponses, ListScansQuery, ListScheduleRunJobsData, ListScheduleRunJobsError, ListScheduleRunJobsErrors, ListScheduleRunJobsResponse, ListScheduleRunJobsResponses, ListScheduleRunsData, ListScheduleRunsError, ListScheduleRunsErrors, ListScheduleRunsResponse, ListScheduleRunsResponses, ListScheduleServicesData, ListScheduleServicesError, ListScheduleServicesErrors, ListScheduleServicesResponse, ListScheduleServicesResponses, ListSecretsData, ListSecretsErrors, ListSecretsResponse, ListSecretsResponse2, ListSecretsResponses, ListServiceHealthStatusesData, ListServiceHealthStatusesErrors, ListServiceHealthStatusesResponse, ListServiceHealthStatusesResponses, ListServiceProjectsData, ListServiceProjectsErrors, ListServiceProjectsResponse, ListServiceProjectsResponses, ListServiceSchedulesData, ListServiceSchedulesError, ListServiceSchedulesErrors, ListServiceSchedulesResponse, ListServiceSchedulesResponses, ListServicesData, ListServicesErrors, ListServicesResponse, ListServicesResponses, ListSkillsData, ListSkillsErrors, ListSkillsResponse, ListSkillsResponse2, ListSkillsResponses, ListSourceBackupsData, ListSourceBackupsError, ListSourceBackupsErrors, ListSourceBackupsResponse, ListSourceBackupsResponses, ListSourceFilesData, ListSourceFilesErrors, ListSourceFilesResponse, ListSourceFilesResponses, ListSourceMapsData, ListSourceMapsErrors, ListSourceMapsResponse, ListSourceMapsResponses, ListSourcesData, ListSourcesErrors, ListSourcesResponse, ListSourcesResponses, ListStaticBundlesData, ListStaticBundlesErrors, ListStaticBundlesResponse, ListStaticBundlesResponses, ListSyncedRepositoriesData, ListSyncedRepositoriesErrors, ListSyncedRepositoriesResponse, ListSyncedRepositoriesResponses, ListTagsResponse, ListTeamMembersData, ListTeamMembersErrors, ListTeamMembersResponse, ListTeamMembersResponses, ListTeamProjectsData, ListTeamProjectsErrors, ListTeamProjectsResponse, ListTeamProjectsResponses, ListTeamsData, ListTeamsErrors, ListTeamsResponse, ListTeamsResponses, ListTemplatesQuery, ListTemplatesResponse, ListUsersData, ListUsersErrors, ListUsersResponse, ListUsersResponses, ListVulnerabilitiesQuery, ListWebhooksData, ListWebhooksErrors, ListWebhooksResponse, ListWebhooksResponses, LiveVisitorInfo, LiveVisitorsListResponse, LocationCount, LocationGranularity, LocationInfo, LoginData, LoginErrors, LoginRequest, LoginResponse, LoginResponses, LogLevel, LogoutData, LogoutErrors, LogoutResponses, LogRecord, LogSearchLine, LogSeverity, LogSource, LogsQuery, LogsResponse, LogStream, LookupDnsARecordsData, LookupDnsARecordsError, LookupDnsARecordsErrors, LookupDnsARecordsResponse, LookupDnsARecordsResponses, ManagedDomainResponse, ManualAction, ManualActionTiming, McpDefinitionResponse, MessageContent, MessagePart, MessageResponse, MeteredMode, MetricAggregation, MetricBucket, MetricDataPoint, MetricsOverTimeResponse, MetricsQuery, MetricsRangeQuery, MetricsStatusResponse, MetricsStoreKind, MetricsSummaryResponse, MetricType, MfaRequiredResponse, MfaSetupResponse, MfaVerificationRequest, MigrationStep, MigrationSummary, MintEnrollmentTokenData, MintEnrollmentTokenErrors, MintEnrollmentTokenRequest, MintEnrollmentTokenResponse, MintEnrollmentTokenResponse2, MintEnrollmentTokenResponses, MiscResult, MkdirBody, MkdirData, MkdirErrors, MkdirResponse, MkdirResponses, ModelInfo, ModelListResponse, ModelPricing, ModelUsage, MonitoringSettings, MonitoringSettingsMasked, MonitorResponse, MonitorStatus, MrrBucketResponse, MultiNodeSettings, MultiNodeSettingsMasked, MxResult, NavEntry, NavSection, NetworkConfiguration, NetworkMode, NixpacksPresetConfig, NixpacksProvider, NodeContainerListResponse, NodeContainerResponse, NodeCostInfo, NodeHeartbeatData, NodeHeartbeatErrors, NodeHeartbeatResponse, NodeHeartbeatResponses, NodeInfoResponse, NodeListResponse, NodeMetricsGetRangeData, NodeMetricsGetRangeErrors, NodeMetricsGetRangeResponse, NodeMetricsGetRangeResponses, NotificationPreferencesResponse, NotificationProviderResponse, ObservabilityCompressionSettings, ObservabilityEvent, ObservabilityFullEventData, ObservabilityFullEventError, ObservabilityFullEventErrors, ObservabilityFullEventResponse, ObservabilityFullEventResponses, ObservabilityListEventsData, ObservabilityListEventsError, ObservabilityListEventsErrors, ObservabilityListEventsResponse, ObservabilityListEventsResponses, ObservabilityRetentionSettings, OidcCallbackData, OidcProviderResponse, OidcProvidersListResponse, OidcProviderSummary, OidcProviderUserResponse, OidcRoleMappingResponse, OidcTestConnectionResponse, OnDemandCertAttemptResponse, OnDemandCertRow, OnDemandTlsSettings, OpenAiError, OpenAiErrorResponse, OperatingSystemCount, OperationResultResponse, OperationResultsResponse, OtelDashboardResponse, OtelDashboardsResponse, OtelMetricAlertRuleResponse, OtelMetricAlertsResponse, OtelMetricLabelKeysResponse, OtelMetricLabelValuesResponse, OtelMetricNamesResponse, OtelMetricsResponse, OutlierAlgorithm, OutlierParams, OverprovisioningAssessment, OverprovisioningVerdict, PageActivityBucket, PageCountryStats, PageFlowEntry, PageFlowQuery, PageFlowResponse, PageHourlySessionsQuery, PageHourlySessionsResponse, PagePathDetailQuery, PagePathDetailResponse, PagePathInfo, PagePathSparkline, PagePathSparklinePoint, PagePathsQuery, PagePathsResponse, PagePathsSparklineQuery, PagePathsSparklineResponse, PagePathVisitorsQuery, PagePathVisitorsResponse, PageReferrerStats, PagesComparisonResponse, PageSessionComparison, PageSessionStats, PageSessionStatsQuery, PageTransition, PageVisit, PageVisitorSession, PaginatedEmailsResponse, PaginatedEntitiesResponse, PaginatedErrorEventsResponse, PaginatedErrorGroupsResponse, PaginatedEventsResponse, PaginatedExternalImagesResponse, PaginatedProjectList, PaginatedStaticBundlesResponse, Pagination, PaginationMeta, PaginationParams, PasswordProtectionConfig, PatchAdminGateData, PatchAdminGateErrors, PatchAdminGateResponse, PatchAdminGateResponses, PatchPreviewGatewaySettingsData, PatchPreviewGatewaySettingsResponse, PatchPreviewGatewaySettingsResponses, PatchSettingsRequest, PathVisitors, PathVisitorsAnalyticsQuery, PathVisitorsResponse, PauseDeploymentData, PauseDeploymentErrors, PauseDeploymentResponse, PauseDeploymentResponses, PauseSandboxData, PauseSandboxErrors, PauseSandboxResponse, PauseSandboxResponses, PeerEntry, PeerListResponse, PendingActionResponse, PerformanceMetricsQuery, PerformanceMetricsResponse, PermissionInfo, PgUpgradeLogResponse, PgUpgradeResponse, PipelineStats, PipelineStatsResponse, PlanComplexity, PlanMetadata, PlanRestoreData, PlanRestoreError, PlanRestoreErrors, PlanRestoreResponse, PlanRestoreResponses, PlanSourceBackup, PlanTarget, PlatformInfo, PluginManifest, PortMapping, PostDnsAckData, PostDnsAckErrors, PostDnsAckResponse, PostDnsAckResponses, PostgresWalHealth, PresetConfigSchema, PresetInfo, PresetResponse, PreviewAlertData, PreviewAlertError, PreviewAlertErrors, PreviewAlertResponse, PreviewAlertResponses, PreviewFunnelMetricsData, PreviewFunnelMetricsErrors, PreviewFunnelMetricsResponse, PreviewFunnelMetricsResponses, PreviewGatewaySettings, PreviewGatewaySettingsMasked, PreviewGatewaySettingsResponse, PreviewHostnameModeData, PreviewHostnameModeErrors, PreviewHostnameModeResponse, PreviewHostnameModeResponses, PreviewShareLinkBody, PreviewShareLinkResponse, PricingResponse, ProblemDetails, ProjectAccessResponse, ProjectConfiguration, ProjectDashboardAnalytics, ProjectDsnResponse, ProjectHealthSummary, ProjectInfo, ProjectMonitorHealth, ProjectPresetResponse, ProjectQuery, ProjectRef, ProjectResponse, ProjectSecretEnvironmentInfo, ProjectSecretResponse, ProjectServiceInfo, ProjectsHealthResponse, ProjectsMonitorHealthResponse, ProjectStatisticsResponse, ProjectStatsBreakdown, ProjectType, ProjectUsageInfoResponse, PromoteClusterMemberData, PromoteClusterMemberErrors, PromoteClusterMemberResponses, PromoteDeploymentData, PromoteDeploymentErrors, PromoteDeploymentRequest, PromoteDeploymentResponse, PromoteDeploymentResponses, PropertyBreakdownItem, PropertyBreakdownQuery, PropertyBreakdownResponse, PropertyColumn, PropertyTimelineItem, PropertyTimelineQuery, PropertyTimelineResponse, Protocol, ProviderCatalogDto, ProviderCatalogResponse, ProviderConfig, ProviderConfigMasked, ProviderDeletionCheckResponse, ProviderDescriptor, ProviderKeyResponse, ProviderMetadata, ProviderResponse, ProviderUsage, ProvisionDomainData, ProvisionDomainErrors, ProvisionDomainResponse, ProvisionDomainResponses, ProvisionResponse, ProxyLogResponse, ProxyLogsPaginatedResponse, PublicHostnameStrategy, PublicPresetResponse, PublicRepositoryInfo, PurgeLogsRequest, PurgeProjectLogsData, PurgeProjectLogsError, PurgeProjectLogsErrors, PurgeProjectLogsResponses, PushedExternalImageResponse, PushExternalImageData, PushExternalImageErrors, PushExternalImageResponse, PushExternalImageResponses, PushImageRequest, QueryDataData, QueryDataErrors, QueryDataRequest, QueryDataResponse, QueryDataResponse2, QueryDataResponses, QueryGenaiTracesData, QueryGenaiTracesError, QueryGenaiTracesErrors, QueryGenaiTracesResponse, QueryGenaiTracesResponses, QueryLogsData, QueryLogsError, QueryLogsErrors, QueryLogsResponse, QueryLogsResponses, QueryMetricsData, QueryMetricsError, QueryMetricsErrors, QueryMetricsResponse, QueryMetricsResponses, QueryTracesData, QueryTracesError, QueryTracesErrors, QueryTracesResponse, QueryTracesResponses, QueryTraceSummariesData, QueryTraceSummariesError, QueryTraceSummariesErrors, QueryTraceSummariesResponse, QueryTraceSummariesResponses, QuotaResponse, RateLimitConfig, RateLimitSettings, ReachabilityStatus, ReadFileData, ReadFileErrors, ReadFileResponse, ReadFileResponse2, ReadFileResponses, ReAnalyzeData, ReAnalyzeErrors, ReAnalyzeResponses, RecentActivityQuery, RecentActivityResponse, RecentEventResponse, RecentQueryParams, RecordConsoleEventData, RecordConsoleEventErrors, RecordConsoleEventResponses, RecordEventMetricsData, RecordEventMetricsErrors, RecordEventMetricsResponse, RecordEventMetricsResponses, RecordExposureRequest, RecordExposureResponse, RecordFlagExposureData, RecordFlagExposureErrors, RecordFlagExposureResponse, RecordFlagExposureResponses, RecordListResponse, RecordSpeedMetricsData, RecordSpeedMetricsError, RecordSpeedMetricsErrors, RecordSpeedMetricsResponse, RecordSpeedMetricsResponses, RecoveryTarget, ReferrerCount, ReferrersAnalyticsQuery, RefreshRouteTableData, RefreshRouteTableErrors, RefreshRouteTableResponse, RefreshRouteTableResponses, RegenerateDsnData, RegenerateDsnErrors, RegenerateDsnRequest, RegenerateDsnResponse, RegenerateDsnResponses, RegisterExternalImageData, RegisterExternalImageErrors, RegisterExternalImageResponse, RegisterExternalImageResponses, RegisterImageRequest, RegisterNodeApiRequest, RegisterNodeData, RegisterNodeErrors, RegisterNodeResponse, RegisterNodeResponse2, RegisterNodeResponses, RegisterRequest, ReinstallGitlabWebhookData, ReinstallGitlabWebhookErrors, ReinstallGitlabWebhookResponse, ReinstallGitlabWebhookResponses, ReinstallWebhookResponse, RejectPendingActionData, RejectPendingActionErrors, RejectPendingActionResponse, RejectPendingActionResponses, ReleaseListResponse, ReloadPluginsData, ReloadPluginsErrors, ReloadPluginsResponse, ReloadPluginsResponses, ReloadResponse, RemoteDeploymentResponse, RemoveClusterMemberData, RemoveClusterMemberErrors, RemoveClusterMemberResponse, RemoveClusterMemberResponses, RemoveManagedDomainData, RemoveManagedDomainErrors, RemoveManagedDomainResponse, RemoveManagedDomainResponses, RemoveNodeResponse, RemoveRoleData, RemoveRoleErrors, RemoveRoleResponse, RemoveRoleResponses, RemoveTeamMemberData, RemoveTeamMemberErrors, RemoveTeamMemberResponse, RemoveTeamMemberResponses, RenameConversationData, RenameConversationErrors, RenameConversationRequest, RenameConversationResponse, RenameConversationResponses, RenewDomainData, RenewDomainErrors, RenewDomainResponse, RenewDomainResponses, RepositoryListQuery, RepositoryListResponse, RepositoryPresetResponse, RepositoryResponse, RepositorySyncStartedResponse, RequestPasswordResetData, RequestPasswordResetErrors, RequestPasswordResetResponse, RequestPasswordResetResponses, RequestRow, ResetPasswordData, ResetPasswordErrors, ResetPasswordRequest, ResetPasswordResponse, ResetPasswordResponses, ResetPgStatStatementsRequest, ResetPgStatStatementsResponse, ResizeSandboxBody, ResizeSandboxData, ResizeSandboxErrors, ResizeSandboxResponse, ResizeSandboxResponses, ResolveAlarmData, ResolveAlarmErrors, ResolveAlarmResponses, ResolvedEnvVarResponse, ResolvedEnvVarSource, ResourceCounts, ResourceFootprint, ResourceInfo, ResourceLimitApplyResult, ResourceLimits, ResourceLimitsResponse, ResourceLimitsUpdateResponse, ResourcesBody, RestartContainerData, RestartContainerErrors, RestartContainerResponse, RestartContainerResponses, RestartPreviewGatewayData, RestartPreviewGatewayResponse, RestartPreviewGatewayResponses, RestartSandboxData, RestartSandboxErrors, RestartSandboxResponse, RestartSandboxResponses, RestoreCapabilities, RestoreCapabilitiesResponse, RestoreFlagData, RestoreFlagErrors, RestoreFlagResponse, RestoreFlagResponses, RestorePlan, RestoreRequestMode, RestoreRunView, RestoreUserData, RestoreUserErrors, RestoreUserResponse, RestoreUserResponses, ResumeDeploymentData, ResumeDeploymentErrors, ResumeDeploymentResponse, ResumeDeploymentResponses, ResumeSandboxData, ResumeSandboxErrors, ResumeSandboxResponse, ResumeSandboxResponses, RetentionCleanupFailure, RetentionCleanupReport, RetryClusterData, RetryClusterErrors, RetryClusterRequest, RetryClusterResponse, RetryClusterResponses, RetryDeliveryData, RetryDeliveryErrors, RetryDeliveryResponse, RetryDeliveryResponses, RetryPgUpgradeData, RetryPgUpgradeErrors, RetryPgUpgradeResponse, RetryPgUpgradeResponses, RetryRunData, RetryRunErrors, RetryRunResponse, RetryRunResponses, RevealGlobalMcpConfigData, RevealGlobalMcpConfigErrors, RevealGlobalMcpConfigResponse, RevealGlobalMcpConfigResponses, RevealMcpConfigData, RevealMcpConfigErrors, RevealMcpConfigResponse, RevealMcpConfigResponses, RevealNotificationProviderConfigData, RevealNotificationProviderConfigErrors, RevealNotificationProviderConfigResponse, RevealNotificationProviderConfigResponses, RevealServiceParameterData, RevealServiceParameterErrors, RevealServiceParameterResponse, RevealServiceParameterResponses, RevenueCreateIntegrationData, RevenueCreateIntegrationErrors, RevenueCreateIntegrationResponse, RevenueCreateIntegrationResponses, RevenueDeleteIntegrationData, RevenueDeleteIntegrationResponse, RevenueDeleteIntegrationResponses, RevenueGlobalEventsData, RevenueGlobalEventsResponse, RevenueGlobalEventsResponses, RevenueImportInvoicesCsvData, RevenueImportInvoicesCsvErrors, RevenueImportInvoicesCsvResponse, RevenueImportInvoicesCsvResponses, RevenueImportSubscriptionsCsvData, RevenueImportSubscriptionsCsvErrors, RevenueImportSubscriptionsCsvResponse, RevenueImportSubscriptionsCsvResponses, RevenueListIntegrationsData, RevenueListIntegrationsResponse, RevenueListIntegrationsResponses, RevenueListProvidersData, RevenueListProvidersResponse, RevenueListProvidersResponses, RevenueMetricsCustomersData, RevenueMetricsCustomersResponse, RevenueMetricsCustomersResponses, RevenueMetricsGlobalMrrData, RevenueMetricsGlobalMrrResponse, RevenueMetricsGlobalMrrResponses, RevenueMetricsGlobalSummaryData, RevenueMetricsGlobalSummaryResponse, RevenueMetricsGlobalSummaryResponses, RevenueMetricsMrrData, RevenueMetricsMrrResponse, RevenueMetricsMrrResponses, RevenueMetricsSummaryData, RevenueMetricsSummaryResponse, RevenueMetricsSummaryResponses, RevenueRecentEventsData, RevenueRecentEventsResponse, RevenueRecentEventsResponses, RevenueRotateTokenData, RevenueRotateTokenResponse, RevenueRotateTokenResponses, RevenueRow, RevenueUpdateConfigData, RevenueUpdateConfigErrors, RevenueUpdateConfigResponse, RevenueUpdateConfigResponses, RevenueUpdateSecretData, RevenueUpdateSecretErrors, RevenueUpdateSecretResponse, RevenueUpdateSecretResponses, RevokeDsnData, RevokeDsnErrors, RevokeDsnResponse, RevokeDsnResponses, RevokeEnrollmentTokenData, RevokeEnrollmentTokenErrors, RevokeEnrollmentTokenResponse, RevokeEnrollmentTokenResponses, RevokeJoinTokenData, RevokeJoinTokenErrors, RevokeJoinTokenResponse, RevokeJoinTokenResponses, RevokeProjectAccessData, RevokeProjectAccessErrors, RevokeProjectAccessResponse, RevokeProjectAccessResponses, RiskLevel, RoleInfo, RollbackPgUpgradeData, RollbackPgUpgradeErrors, RollbackPgUpgradeResponse, RollbackPgUpgradeResponses, RollbackToDeploymentData, RollbackToDeploymentErrors, RollbackToDeploymentResponse, RollbackToDeploymentResponses, RootfsCacheEntry, RootfsGcData, RootfsGcReport, RootfsGcResponses, RootfsReport, RootfsReportData, RootfsReportResponses, RootfsVmEntry, RotateApiKeyData, RotateApiKeyErrors, RotateApiKeyResponse, RotateApiKeyResponses, RotateDeploymentTokenData, RotateDeploymentTokenErrors, RotateDeploymentTokenResponse, RotateDeploymentTokenResponses, RouteRefreshResponse, RouteResponse, RouteRole, RouteUser, RouteUserWithRoles, RunBackupForSourceData, RunBackupForSourceError, RunBackupForSourceErrors, RunBackupForSourceResponse, RunBackupForSourceResponses, RunBackupRequest, RunConnectionHealthCheckData, RunConnectionHealthCheckErrors, RunConnectionHealthCheckResponse, RunConnectionHealthCheckResponses, RunExternalServiceBackupData, RunExternalServiceBackupError, RunExternalServiceBackupErrors, RunExternalServiceBackupRequest, RunExternalServiceBackupResponse, RunExternalServiceBackupResponses, RunScheduleNowData, RunScheduleNowError, RunScheduleNowErrors, RunScheduleNowResponse, RunScheduleNowResponses, S3ConnectionTestResponse, S3CredentialsResponse, S3SourceResponse, S3SourceResponseWritable, SandboxCreatePreviewLinkData, SandboxCreatePreviewLinkErrors, SandboxCreatePreviewLinkResponse, SandboxCreatePreviewLinkResponses, SandboxDomainResponse, SandboxEvent, SandboxEventsResponse, SandboxInner, SandboxResponse, SandboxRoute, SandboxStatusResponse, SaveAgentTokenData, SaveAgentTokenErrors, SaveAgentTokenRequest, SaveAgentTokenResponse, SaveAgentTokenResponse2, SaveAgentTokenResponses, SaveAiProviderCredentialData, SaveAiProviderCredentialErrors, SaveAiProviderCredentialResponse, SaveAiProviderCredentialResponses, SaveCredentialRequest, SaveCredentialResponse, ScalewayCredentialsRequest, ScanResponse, ScheduleRunEntry, ScheduleRunJobEntry, ScheduleRunListResponse, ScheduleRunResponse, ScheduleRunSummary, ScheduleRunSummaryList, ScreenshotSettings, SearchLogsData, SearchLogsError, SearchLogsErrors, SearchLogsRequest, SearchLogsResponse, SearchLogsResponse2, SearchLogsResponses, SearchMode, Seasonality, SecretResponse, SecurityConfig, SecurityHeadersConfig, SecurityHeadersSettings, SendEmailData, SendEmailErrors, SendEmailRequestBody, SendEmailResponse, SendEmailResponseBody, SendEmailResponses, SendMessageRequest, SensitiveConfigValueResponse, SensitiveMcpConfigValueResponse, SensitiveValueResponse, SentryChunkUploadResponse, SentryCreateReleaseRequest, SentryEventRequest, SentryEventResponse, SentryReleaseFileResponse, SentryReleaseProjectRef, SentryReleaseResponse, SeriesStateEntry, ServiceAccessInfo, ServiceAction, ServiceAlertRuleResponse, ServiceBackupEntryResponse, ServiceBackupListResponse, ServiceCreateAlertRuleRequest, ServiceHealthResponse, ServiceHealthStatusBatchResponse, ServiceHealthStatusEntryResponse, ServiceMemberInfo, ServiceParameter, ServicePlan, ServiceResourceLimits, ServiceRuntimeReport, ServiceStatsReport, ServiceTypeInfo, ServiceTypeRoute, ServiceUpdateAlertRuleRequest, SesCredentialsRequest, SessionDetails, SessionDetailsQuery, SessionEvent, SessionEventDto, SessionEventsQuery, SessionEventsResponse, SessionLogsQuery, SessionLogsResponse, SessionReplayEventsRequest, SessionReplayInfoDto, SessionReplayInitRequest, SessionReplayInitResponse, SessionReplayWithEventsDto, SessionReplayWithVisitorDto, SessionRequestLog, SessionSummary, SetDefaultS3SourceData, SetDefaultS3SourceError, SetDefaultS3SourceErrors, SetDefaultS3SourceResponse, SetDefaultS3SourceResponses, SetFlagEnvironmentData, SetFlagEnvironmentErrors, SetFlagEnvironmentRequest, SetFlagEnvironmentResponse, SetFlagEnvironmentResponses, SetPreviewPasswordBody, SetPreviewPasswordData, SetPreviewPasswordErrors, SetPreviewPasswordResponse, SetPreviewPasswordResponse2, SetPreviewPasswordResponses, SetRequest, SetResponse, SettingsUpdateResponse, SetupDnsChallengeData, SetupDnsChallengeErrors, SetupDnsChallengeRequest, SetupDnsChallengeResponse, SetupDnsChallengeResponse2, SetupDnsChallengeResponses, SetupDnsData, SetupDnsErrors, SetupDnsRequest, SetupDnsResponse, SetupDnsResponse2, SetupDnsResponses, SetupEmailTrackingData, SetupEmailTrackingErrors, SetupEmailTrackingResponse, SetupEmailTrackingResponses, SetupMfaData, SetupMfaErrors, SetupMfaResponse, SetupMfaResponses, SiblingRef, SkillDefinitionResponse, SlackConfig, SleepEnvironmentData, SleepEnvironmentErrors, SleepEnvironmentResponse, SleepEnvironmentResponses, SlowQueriesResponse, SlowQueryRow, SmartFilter, SmokeTestAgentData, SmokeTestAgentErrors, SmokeTestAgentResponse, SmokeTestAgentResponses, SmokeTestResponse, SmtpCredentialsRequest, SmtpEncryptionRoute, SmtpResult, SourceBackupEntry, SourceBackupIndexResponse, SourceBody, SourceFileListResponse, SourceFileResponse, SourceMapListResponse, SourceMapResponse, SourceSandboxData, SourceSandboxErrors, SourceSandboxResponse, SourceSandboxResponses, SourceType, SpanEvent, SpanKind, SpanRecord, SpanRow, SpanStatusCode, SpeedMetricsPayload, SpeedSegmentFilters, StaleSlot, StartAnalysisData, StartAnalysisErrors, StartAnalysisRequest, StartAnalysisResponse, StartAnalysisResponses, StartContainerData, StartContainerErrors, StartContainerResponse, StartContainerResponses, StartFixData, StartFixErrors, StartFixResponses, StartGitProviderOauthData, StartGitProviderOauthErrors, StartOidcLoginBySlugData, StartOidcLoginBySlugErrors, StartPgUpgradeData, StartPgUpgradeErrors, StartPgUpgradeRequest, StartPgUpgradeResponse, StartPgUpgradeResponses, StartRestoreData, StartRestoreError, StartRestoreErrors, StartRestoreRequest, StartRestoreResponse, StartRestoreResponses, StartServiceData, StartServiceErrors, StartServiceResponse, StartServiceResponses, StaticBundleResponse, StaticParams, StaticPresetConfig, StatPathData, StatPathErrors, StatPathResponse, StatPathResponses, StatResponse, StatsFilters, StatusBucket, StatusBucketedResponse, StatusCodeCount, StatusCodesQuery, StatusPageOverview, StepConversionResponse, StepResourceType, StepResult, StepUpResponse, StopContainerData, StopContainerErrors, StopContainerResponse, StopContainerResponses, StopSandboxData, StopSandboxErrors, StopSandboxResponse, StopSandboxResponses, StopSequence, StopServiceData, StopServiceErrors, StopServiceResponse, StopServiceResponses, StorageQuota, StreamContainerMetricsData, StreamContainerMetricsErrors, StreamContainerMetricsResponses, StreamEventsData, StreamEventsErrors, StreamEventsResponses, StreamRunEventsData, StreamRunEventsErrors, StreamRunEventsResponses, StripeConfig, SyncedRepositoryListQuery, SyncRepositoriesData, SyncRepositoriesErrors, SyncRepositoriesResponse, SyncRepositoriesResponses, SyntaxResult, TagInfo, TagListResponse, TailDeploymentJobLogsData, TailDeploymentJobLogsErrors, TailLogsData, TailLogsError, TailLogsErrors, TailLogsRequest, TailLogsResponses, TargetRecommendation, TeamListResponse, TeamMemberResponse, TeamResponse, TeamRole, TeardownDeploymentData, TeardownDeploymentErrors, TeardownDeploymentResponse, TeardownDeploymentResponses, TeardownEnvironmentData, TeardownEnvironmentErrors, TeardownEnvironmentResponse, TeardownEnvironmentResponses, TemplateResponse, TestEmailRequest, TestEmailResponse, TestNotificationProviderData, TestNotificationProviderErrors, TestNotificationProviderResponse, TestNotificationProviderResponses, TestOidcProviderData, TestOidcProviderResponse, TestOidcProviderResponses, TestProviderConnectionData, TestProviderConnectionErrors, TestProviderConnectionResponse, TestProviderConnectionResponses, TestProviderData, TestProviderErrors, TestProviderKeyByIdData, TestProviderKeyByIdError, TestProviderKeyByIdErrors, TestProviderKeyByIdResponse, TestProviderKeyByIdResponses, TestProviderKeyInlineData, TestProviderKeyInlineError, TestProviderKeyInlineErrors, TestProviderKeyInlineResponse, TestProviderKeyInlineResponses, TestProviderKeyRequest, TestProviderKeyResponse, TestProviderResponse, TestProviderResponse2, TestProviderResponses, TestS3ConnectionPreviewData, TestS3ConnectionPreviewError, TestS3ConnectionPreviewErrors, TestS3ConnectionPreviewResponse, TestS3ConnectionPreviewResponses, TestS3SourceConnectionData, TestS3SourceConnectionError, TestS3SourceConnectionErrors, TestS3SourceConnectionResponse, TestS3SourceConnectionResponses, TimeBucketStats, TimeBucketStatsResponse, TimeseriesBucket, TimeseriesQueryParams, TlsMode, TodayStatsResponse, ToggleDeploymentMetricsRequest, ToggleServiceMetricsRequest, TokenRenewalRequest, ToolCallEvent, ToolInfo, ToolResultEvent, TopModelsQueryParams, TraceProjectRef, TracesResponse, TraceSummariesResponse, TraceSummary, TrackClickData, TrackClickErrors, TrackedLinkResponse, TrackingEventResponse, TrackOpenData, TrackOpenErrors, TrackOpenResponses, TriggerAgentData, TriggerAgentErrors, TriggerAgentRequest, TriggerAgentResponse, TriggerAgentResponses, TriggerDigestResponse, TriggerPipelinePayload, TriggerPipelineResponse, TriggerProjectPipelineData, TriggerProjectPipelineErrors, TriggerProjectPipelineResponse, TriggerProjectPipelineResponses, TriggerScanData, TriggerScanError, TriggerScanErrors, TriggerScanRequest, TriggerScanResponse, TriggerScanResponse2, TriggerScanResponses, TriggerServiceHealthCheckData, TriggerServiceHealthCheckErrors, TriggerServiceHealthCheckResponse, TriggerServiceHealthCheckResponses, TriggerWeeklyDigestData, TriggerWeeklyDigestErrors, TriggerWeeklyDigestResponse, TriggerWeeklyDigestResponses, TtlRequest, TtlResponse, TxtRecord, UiManifest, UiRoute, UndrainNodeResponse, UnifiedTrace, UniqueCountsQuery, UniqueCountsResponse, UnlinkServiceFromProjectData, UnlinkServiceFromProjectErrors, UnlinkServiceFromProjectResponse, UnlinkServiceFromProjectResponses, UnsupportedFeature, UpdateAdminGateRequest, UpdateAgentData, UpdateAgentErrors, UpdateAgentResponse, UpdateAgentResponses, UpdateAiProviderData, UpdateAiProviderErrors, UpdateAiProviderRequest, UpdateAiProviderResponse, UpdateAiProviderResponse2, UpdateAiProviderResponses, UpdateAlertData, UpdateAlertError, UpdateAlertErrors, UpdateAlertResponse, UpdateAlertResponses, UpdateAlertRuleData, UpdateAlertRuleErrors, UpdateAlertRuleRequest, UpdateAlertRuleResponse, UpdateAlertRuleResponses, UpdateApiKeyData, UpdateApiKeyErrors, UpdateApiKeyRequest, UpdateApiKeyResponse, UpdateApiKeyResponses, UpdateAutomaticDeployData, UpdateAutomaticDeployErrors, UpdateAutomaticDeployRequest, UpdateAutomaticDeployResponse, UpdateAutomaticDeployResponses, UpdateBackupScheduleData, UpdateBackupScheduleError, UpdateBackupScheduleErrors, UpdateBackupScheduleRequest, UpdateBackupScheduleResponse, UpdateBackupScheduleResponses, UpdateBlobRequest, UpdateBlobResponse, UpdateCloudflareProviderData, UpdateCloudflareProviderErrors, UpdateCloudflareProviderRequest, UpdateCloudflareProviderResponse, UpdateCloudflareProviderResponses, UpdateConfigBody, UpdateConnectionTokenData, UpdateConnectionTokenErrors, UpdateConnectionTokenResponse, UpdateConnectionTokenResponses, UpdateCustomDomainData, UpdateCustomDomainErrors, UpdateCustomDomainRequest, UpdateCustomDomainResponse, UpdateCustomDomainResponses, UpdateDashboardData, UpdateDashboardError, UpdateDashboardErrors, UpdateDashboardRequest, UpdateDashboardResponse, UpdateDashboardResponses, UpdateDeploymentConfigRequest, UpdateDeploymentTokenData, UpdateDeploymentTokenErrors, UpdateDeploymentTokenRequest, UpdateDeploymentTokenResponse, UpdateDeploymentTokenResponses, UpdateDnsProviderRequest, UpdateEmailProviderData, UpdateEmailProviderErrors, UpdateEmailProviderRequest, UpdateEmailProviderResponse, UpdateEmailProviderResponses, UpdateEnvironmentSettingsData, UpdateEnvironmentSettingsErrors, UpdateEnvironmentSettingsRequest, UpdateEnvironmentSettingsResponse, UpdateEnvironmentSettingsResponses, UpdateEnvironmentSubdomainData, UpdateEnvironmentSubdomainErrors, UpdateEnvironmentSubdomainRequest, UpdateEnvironmentSubdomainResponse, UpdateEnvironmentSubdomainResponses, UpdateEnvironmentVariableData, UpdateEnvironmentVariableErrors, UpdateEnvironmentVariableRequest, UpdateEnvironmentVariableResponse, UpdateEnvironmentVariableResponses, UpdateErrorGroupData, UpdateErrorGroupErrors, UpdateErrorGroupRequest, UpdateErrorGroupResponses, UpdateExternalServiceRequest, UpdateFlagData, UpdateFlagErrors, UpdateFlagRequest, UpdateFlagResponse, UpdateFlagResponses, UpdateFunnelData, UpdateFunnelErrors, UpdateFunnelResponses, UpdateGitProviderCredentialsData, UpdateGitProviderCredentialsErrors, UpdateGitProviderCredentialsResponse, UpdateGitProviderCredentialsResponses, UpdateGitSettingsData, UpdateGitSettingsErrors, UpdateGitSettingsRequest, UpdateGitSettingsResponse, UpdateGitSettingsResponses, UpdateGlobalMcpData, UpdateGlobalMcpErrors, UpdateGlobalMcpResponse, UpdateGlobalMcpResponses, UpdateGlobalSkillData, UpdateGlobalSkillErrors, UpdateGlobalSkillResponse, UpdateGlobalSkillResponses, UpdateIncidentStatusData, UpdateIncidentStatusErrors, UpdateIncidentStatusRequest, UpdateIncidentStatusResponse, UpdateIncidentStatusResponses, UpdateIpAccessControlData, UpdateIpAccessControlError, UpdateIpAccessControlErrors, UpdateIpAccessControlRequest, UpdateIpAccessControlResponse, UpdateIpAccessControlResponses, UpdateKvRequest, UpdateKvResponse, UpdateManagedDomainApiRequest, UpdateManagedDomainData, UpdateManagedDomainErrors, UpdateManagedDomainResponse, UpdateManagedDomainResponses, UpdateMcpData, UpdateMcpErrors, UpdateMcpRequest, UpdateMcpResponse, UpdateMcpResponses, UpdateMemberRoleRequest, UpdateMetricAlertRequest, UpdateNotificationEmailProviderData, UpdateNotificationEmailProviderErrors, UpdateNotificationEmailProviderRequest, UpdateNotificationEmailProviderResponse, UpdateNotificationEmailProviderResponses, UpdateNotificationProviderData, UpdateNotificationProviderErrors, UpdateNotificationProviderResponse, UpdateNotificationProviderResponses, UpdateOidcProviderData, UpdateOidcProviderRequest, UpdateOidcProviderResponse, UpdateOidcProviderResponses, UpdatePreferencesData, UpdatePreferencesErrors, UpdatePreferencesRequest, UpdatePreferencesResponse, UpdatePreferencesResponses, UpdateProjectData, UpdateProjectDeploymentConfigData, UpdateProjectDeploymentConfigErrors, UpdateProjectDeploymentConfigResponse, UpdateProjectDeploymentConfigResponses, UpdateProjectErrors, UpdateProjectResponse, UpdateProjectResponses, UpdateProjectSecretData, UpdateProjectSecretErrors, UpdateProjectSecretRequest, UpdateProjectSecretResponse, UpdateProjectSecretResponses, UpdateProjectSettingsData, UpdateProjectSettingsErrors, UpdateProjectSettingsRequest, UpdateProjectSettingsResponse, UpdateProjectSettingsResponses, UpdateProviderCredentialsRequest, UpdateProviderData, UpdateProviderErrors, UpdateProviderKeyData, UpdateProviderKeyError, UpdateProviderKeyErrors, UpdateProviderKeyRequest, UpdateProviderKeyResponse, UpdateProviderKeyResponses, UpdateProviderRequest, UpdateProviderResponse, UpdateProviderResponses, UpdateRouteData, UpdateRouteErrors, UpdateRouteRequest, UpdateRouteResponse, UpdateRouteResponses, UpdateS3SourceData, UpdateS3SourceError, UpdateS3SourceErrors, UpdateS3SourceRequest, UpdateS3SourceResponse, UpdateS3SourceResponses, UpdateSecretBody, UpdateSelfData, UpdateSelfErrors, UpdateSelfRequest, UpdateSelfResponse, UpdateSelfResponses, UpdateServiceData, UpdateServiceErrors, UpdateServiceResourcesData, UpdateServiceResourcesErrors, UpdateServiceResourcesResponse, UpdateServiceResourcesResponses, UpdateServiceResponse, UpdateServiceResponses, UpdateSessionDurationData, UpdateSessionDurationError, UpdateSessionDurationErrors, UpdateSessionDurationRequest, UpdateSessionDurationResponse, UpdateSessionDurationResponse2, UpdateSessionDurationResponses, UpdateSettingsData, UpdateSettingsErrors, UpdateSettingsResponse, UpdateSettingsResponses, UpdateSkillData, UpdateSkillErrors, UpdateSkillRequest, UpdateSkillResponse, UpdateSkillResponses, UpdateSlackProviderData, UpdateSlackProviderErrors, UpdateSlackProviderRequest, UpdateSlackProviderResponse, UpdateSlackProviderResponses, UpdateSpeedMetricsData, UpdateSpeedMetricsError, UpdateSpeedMetricsErrors, UpdateSpeedMetricsPayload, UpdateSpeedMetricsResponse, UpdateSpeedMetricsResponses, UpdateStatusResponse, UpdateTeamData, UpdateTeamErrors, UpdateTeamMemberRoleData, UpdateTeamMemberRoleErrors, UpdateTeamMemberRoleResponse, UpdateTeamMemberRoleResponses, UpdateTeamRequest, UpdateTeamResponse, UpdateTeamResponses, UpdateTokenRequest, UpdateTokenResponse, UpdateUserData, UpdateUserErrors, UpdateUserRequest, UpdateUserResponse, UpdateUserResponses, UpdateWebhookData, UpdateWebhookErrors, UpdateWebhookProviderData, UpdateWebhookProviderErrors, UpdateWebhookProviderRequest, UpdateWebhookProviderResponse, UpdateWebhookProviderResponses, UpdateWebhookRequestBody, UpdateWebhookResponse, UpdateWebhookResponses, UpgradeExternalServiceRequest, UpgradePreviewGatewayData, UpgradePreviewGatewayResponse, UpgradePreviewGatewayResponses, UpgradeRequest, UpgradeServiceData, UpgradeServiceErrors, UpgradeServiceResponse, UpgradeServiceResponses, UploadGlobalSkillData, UploadGlobalSkillErrors, UploadGlobalSkillResponse, UploadGlobalSkillResponses, UploadReleaseFileData, UploadReleaseFileErrors, UploadReleaseFileResponse, UploadReleaseFileResponses, UploadSkillData, UploadSkillErrors, UploadSkillResponse, UploadSkillResponses, UploadSourceFileData, UploadSourceFileErrors, UploadSourceFileResponse, UploadSourceFileResponses, UploadSourceMapData, UploadSourceMapErrors, UploadSourceMapResponse, UploadSourceMapResponses, UploadStaticBundleData, UploadStaticBundleErrors, UploadStaticBundleResponse, UploadStaticBundleResponses, UpsertAgentRequest, UpsertSecretData, UpsertSecretErrors, UpsertSecretRequest, UpsertSecretResponse, UpsertSecretResponses, UptimeDataPoint, UptimeHistoryResponse, UsageFilter, UsageInfo, UsageLogEntry, UsageLogPage, UsageQueryParams, UsageSource, UsageSummary, UserResponse, ValidateConnectionData, ValidateConnectionErrors, ValidateConnectionResponse, ValidateConnectionResponses, ValidateEmailData, ValidateEmailErrors, ValidateEmailRequest, ValidateEmailResponse, ValidateEmailResponse2, ValidateEmailResponses, ValidationLevel, ValidationReport, ValidationResponse, ValidationResult, ValidationStatus, ValidationSummary, VerifyAndEnableMfaData, VerifyAndEnableMfaErrors, VerifyAndEnableMfaResponse, VerifyAndEnableMfaResponses, VerifyDomainData, VerifyDomainErrors, VerifyDomainResponse, VerifyDomainResponses, VerifyEmailData, VerifyEmailErrors, VerifyEmailResponse, VerifyEmailResponses, VerifyManagedDomainData, VerifyManagedDomainErrors, VerifyManagedDomainResponse, VerifyManagedDomainResponses, VerifyMfaChallengeData, VerifyMfaChallengeErrors, VerifyMfaChallengeResponse, VerifyMfaChallengeResponses, VerifyMfaRequest, VerifyStepUpData, VerifyStepUpErrors, VerifyStepUpRequest, VerifyStepUpResponse, VerifyStepUpResponses, ViewItem, ViewsOverTime, ViewsOverTimeQuery, VisitorDetails, VisitorFacets, VisitorFacetsQuery, VisitorFacetValue, VisitorInfo, VisitorJourneyQuery, VisitorJourneyResponse, VisitorLocationsQuery, VisitorRecord, VisitorSegmentFilters, VisitorSessionsQuery, VisitorSessionsResponse, VisitorsListQuery, VisitorsResponse, VisitorStats, VisitorWithGeolocation, VolumeMount, VolumeType, VulnerabilityResponse, WakeEnvironmentData, WakeEnvironmentErrors, WakeEnvironmentResponse, WakeEnvironmentResponses, WalWarning, WalWarningSeverity, WebhookConfig, WebhookDeliveryResponse, WebhookResponse, WebhookTriggerData, WebhookTriggerErrors, WebhookTriggerRequest, WebhookTriggerResponse, WebhookTriggerResponse2, WebhookTriggerResponses, WorkflowDryRunData, WorkflowDryRunErrors, WorkflowDryRunRequest, WorkflowDryRunResponse, WorkflowDryRunResponses, WorkloadDescriptor, WorkloadId, WorkloadStatus, WorkloadType, WriteFileBody, WriteFileData, WriteFileErrors, WriteFileResponse, WriteFileResponses, WriteFilesBody, WriteFilesData, WriteFilesErrors, WriteFilesResponse, WriteFilesResponse2, WriteFilesResponses, ZoneListResponse } from './types.gen'; +export { acknowledgeAlarm, activateAiProvider, activateApiKey, activateConnection, activateProvider, addClusterMember, addContext, addEnvironmentDomain, addEvents, addManagedDomain, addSessionReplayEvents, addTeamMember, adminDrainNode, adminDrainStatus, adminGetNode, adminListNodeContainers, adminListNodes, adminRemoveNode, adminUndrainNode, applyHostnameMode, archiveConversation, archiveFlag, assignRole, attachScheduleServices, blobCopy, blobDelete, blobDisable, blobDownload, blobEnable, blobHead, blobList, blobPut, blobStatus, blobUpdate, cancel, cancelBackup, cancelDeployment, cancelDomainOrder, cancelPgUpgrade, cancelRun, cancelScheduleRun, changePasswordSelf, changeProjectSource, chatCompletions, checkAnalyticsHasEvents, checkCommitExists, checkDomainStatus, checkExplorerSupport, checkIpBlocked, checkProviderDeletionSafety, chunkUploadOptions, cleanupExpiredBackups, clearPreviewPassword, cliDeviceApprove, cliDeviceDeny, cliDeviceLookup, cliDevicePoll, cliDeviceStart, cliLogout, cmd, cmdKill, cmdLogs, confirmPendingAction, containerMetricsGetHistory, createAgent, createAlert, createAlertRule, createApiKey, createBackupSchedule, createBitbucketProvider, createCloudflareProvider, createConversation, createCustomDomain, createDashboard, createDeploymentToken, createDnsProvider, createDomain, createDsn, createEmailDomain, createEmailProvider, createEnvironment, createEnvironmentVariable, createFlag, createFunnel, createGenericProvider, createGiteaPatProvider, createGithubPatProvider, createGitlabOauthProvider, createGitlabPatProvider, createGitProvider, createGlobalMcp, createGlobalSkill, createIncident, createIpAccessControl, createMcp, createMonitor, createNotificationEmailProvider, createNotificationProvider, createOidcProvider, createOidcRoleMapping, createOrRecreateOrder, createPlan, createPr, createProject, createProjectFromTemplate, createProjectRelease, createProjectSecret, createProviderKey, createRelease, createRoute, createS3Source, createSandbox, createService, createSkill, createSlackProvider, createTeam, createUser, createWebhook, createWebhookProvider, deactivateApiKey, deactivateConnection, deactivateProvider, deleteAgent, deleteAlert, deleteAlertRule, deleteApiKey, deleteBackup, deleteBackupSchedule, deleteConnection, deleteCustomDomain, deleteDashboard, deleteDeploymentToken, deleteDnsProvider, deleteDomain, deleteEmailDomain, deleteEmailProvider, deleteEnvironment, deleteEnvironmentDomain, deleteEnvironmentVariable, deleteExternalImage, deleteFunnel, deleteGitProvider, deleteGlobalMcp, deleteGlobalSkill, deleteIpAccessControl, deleteMcp, deleteMonitor, deleteNotificationProvider, deleteOidcProvider, deleteOidcRoleMapping, deletePreferences, deleteProject, deleteProjectSecret, deleteProviderKey, deleteProviderSafely, deleteReleaseSourceFiles, deleteReleaseSourceMaps, deleteRoute, deleteS3Source, deleteScan, deleteSecret, deleteService, deleteSessionReplay, deleteSkill, deleteSourceMap, deleteStaticBundle, deleteTeam, deleteUser, deleteWebhook, deployFromImage, deployFromImageUpload, deployFromStatic, deployFromUploadedSource, deploymentMetricsGetLatest, deploymentMetricsGetRange, deploymentMetricsToggle, destroySandbox, detachScheduleService, detectPublicPresets, disableBackupSchedule, disableMfa, discoverWorkloads, domain, downloadGlobalSkillArchive, downloadObject, downloadSkillArchive, emailStatus, embeddings, enableBackupSchedule, enrichVisitor, exec, execDetached, executeDeploymentOperation, executeImport, extendTimeout, externalServiceEnablePgStatStatements, externalServiceMetricsByDatabase, externalServiceMetricsCreateAlertRule, externalServiceMetricsDeleteAlertRule, externalServiceMetricsGetAlertRules, externalServiceMetricsGetLatest, externalServiceMetricsGetRange, externalServiceMetricsStatus, externalServiceMetricsToggle, externalServiceMetricsUpdateAlertRule, externalServiceResetPgStatStatements, finalizeOrder, finalizeProjectRelease, findConversation, generateJoinToken, generatePresetDockerfile, getAccessInfo, getActiveVisitors, getActivityGraph, getAdminGate, getAgent, getAggregatedBuckets, getAiAgentBreakdown, getAiAgentPages, getAiAgentTimeline, getAiPageBreakdown, getAiStatusBreakdown, getAlert, getAlertRule, getAllRepositoriesByName, getAnalyticsActiveVisitors, getAnalyticsEventsCount, getAnalyticsSessionEvents, getAnalyticsVisitorSessions, getApiKey, getApiKeyPermissions, getAuditLog, getBackup, getBackupSchedule, getBranchesByRepositoryId, getBucketedIncidents, getBucketedStatus, getChallengeToken, getChatReadiness, getCliStatus, getClusterHealth, getClusterMember, getCmd, getContainerDetail, getContainerEnvironmentVariable, getContainerInfo, getContainerLogs, getContainerLogsById, getContainerMetrics, getConversation, getConversationDetail, getConversations, getCronById, getCronExecutions, getCrossProjectTraceSiblings, getCurrentMonitorStatus, getCurrentUser, getCustomDomain, getDashboard, getDashboardProjectsAnalytics, getDelivery, getDeployment, getDeploymentContainerLogContent, getDeploymentJobLogs, getDeploymentJobs, getDeploymentOperations, getDeploymentOperationStatus, getDeploymentToken, getDiskStatus, getDnsChanges, getDnsProvider, getDomain, getDomainByHost, getDomainById, getDomainByName, getDomainDnsRecords, getDomainOrder, getEmail, getEmailEvents, getEmailLinks, getEmailProvider, getEmailStats, getEmailTracking, getEmailTrackingStatus, getEntityInfo, getEnvironment, getEnvironmentCrons, getEnvironmentDomains, getEnvironments, getEnvironmentVariables, getEnvironmentVariableValue, getErrorDashboardStats, getErrorEvent, getErrorGroup, getErrorStats, getErrorTimeSeries, getEventDetail, getEventEntries, getEventsCount, getEventsTimeline, getEventTypeBreakdown, getEventVisitors, getExternalImage, getFile, getFlag, getFlagSnapshot, getFunnelMetrics, getGenaiTrace, getGeneralStats, getGitProvider, getGlobalEvents, getGlobalEventStats, getGlobalMcp, getGlobalSandboxStatus, getGlobalSkill, getGroupedPageMetrics, getHealth, getHourlyVisits, getHttpChallengeDebug, getImportStatus, getIncident, getIncidentUpdates, getIpAccessControl, getIpGeolocation, getJoinTokenStatus, getLastDeployment, getLatestScan, getLatestScansPerEnvironment, getLiveVisitorsList, getLogContext, getMcp, getMetricsOverTime, getMonitor, getNotificationProvider, getOnDemandCertStatus, getOrCreateDsn, getPageFlow, getPageHourlySessions, getPagePathDetail, getPagePaths, getPagePathsSparklines, getPagePathVisitors, getPendingAction, getPerformanceMetrics, getPgUpgrade, getPgUpgradeLogs, getPipelineStats, getPlatformInfo, getPostgresWalHealth, getPreferences, getPreviewGatewayLogs, getPreviewGatewaySettings, getPreviewGatewayStatus, getPricing, getPrivateIp, getProject, getProjectAlarmsSummary, getProjectBySlug, getProjectDeployments, getProjects, getProjectServiceEnvironmentVariables, getProjectSessionReplays, getProjectsHealth, getProjectsMonitorHealth, getProjectStatistics, getProjectTemplate, getPropertyBreakdown, getPropertyTimeline, getProviderConnections, getProviderMetadata, getProvidersMetadata, getProxyLogById, getProxyLogByRequestId, getProxyLogs, getPublicBranches, getPublicIp, getPublicRepository, getQuota, getRecentActivity, getRemoteExternalImage, getRepositoryBranches, getRepositoryById, getRepositoryByName, getRepositoryPresetByName, getRepositoryPresetLive, getRepositoryTags, getResolvedEnvironmentVariables, getResolvedEnvironmentVariableValue, getRestoreCapabilities, getRestoreRun, getRoute, getRun, getRunWithLogs, getS3Credentials, getS3Source, getSandbox, getSandboxStatus, getScan, getScanByDeployment, getScanVulnerabilities, getService, getServiceBySlug, getServiceEnvironmentVariable, getServiceEnvironmentVariables, getServiceHealthStatus, getServicePreviewEnvironmentVariableNames, getServicePreviewEnvironmentVariablesMasked, getServiceRuntime, getServiceStats, getServiceTypeParameters, getServiceTypes, getSessionDetails, getSessionEvents, getSessionLogs, getSessionReplay, getSessionReplayEvents, getSettings, getSkill, getSlowQueries, getStaticBundle, getStatusOverview, getTagsByRepositoryId, getTeam, getTimeBucketStats, getTodayStats, getTrace, getUnifiedTrace, getUniqueCounts, getUniqueEvents, getUpdateStatus, getUptimeHistory, getUsageByProvider, getUsageRecent, getUsageSummary, getUsageTimeseries, getUsageTopModels, getVisitorByGuid, getVisitorById, getVisitorDetails, getVisitorFacets, getVisitorInfo, getVisitorJourney, getVisitors, getVisitorSessions, getVisitorStats, getWebhook, grantProjectAccess, handleGitProviderOauthCallback, hasAnalyticsEvents, hasErrorGroups, hasPerformanceMetrics, importExternalService, ingestLogs, ingestLogsByPath, ingestMetrics, ingestMetricsByPath, ingestSentryEnvelope, ingestSentryEvent, ingestTraces, ingestTracesByPath, initSessionReplay, inspectDropArchive, jobLogs, jobStatus, killJob, kvDel, kvDisable, kvEnable, kvExpire, kvGet, kvIncr, kvKeys, kvSet, kvStatus, kvTtl, kvUpdate, latestRunForSource, linkCustomDomainToCertificate, linkServiceToProject, listAgentRuns, listAgents, listAiProviders, listAlertRules, listAlerts, listAllConversations, listAllRuns, listApiKeys, listAuditLogs, listAvailableContainers, listBackupAlerts, listBackupChildren, listBackupSchedules, listBackupsForSchedule, listCommitsByRepositoryId, listConnections, listContainers, listContainersAtPath, listConversations, listCustomDomainsForProject, listDashboards, listDeliveries, listDeploymentContainerLogs, listDeploymentTokens, listDnsProviders, listDomains, listDsns, listEmailDomains, listEmailProviders, listEmails, listEnrollmentTokens, listEntities, listErrorEvents, listErrorGroups, listEvents, listEventTypes, listExternalImages, listExternalPlugins, listExternalServiceBackups, listFlags, listFunnels, listGitProviders, listGlobalMcps, listGlobalSkills, listIncidents, listInsights, listIpAccessControl, listJobs, listKnownAiAgents, listManagedDomains, listMcps, listMetricLabelKeys, listMetricLabelValues, listMetricNames, listModels, listMonitors, listNotificationProviders, listOidcProviders, listOidcProviderUsers, listOidcRoleMappings, listOnDemandCerts, listOrders, listPeers, listPendingActions, listPgUpgrades, listPresets, listProjectAccess, listProjectAlarms, listProjectScans, listProjectSecrets, listProjectServices, listProjectTemplates, listProjectTemplateTags, listProviderKeys, listProviderZones, listPublicProviders, listReleaseFiles, listReleases, listRemoteExternalImages, listRepositoriesByConnection, listRepositoriesByProvider, listRestoreRunsForService, listRootContainers, listRoutes, listS3Sources, listSandboxes, listScheduleRunJobs, listScheduleRuns, listScheduleServices, listSecrets, listServiceHealthStatuses, listServiceProjects, listServices, listServiceSchedules, listSkills, listSourceBackups, listSourceFiles, listSourceMaps, listSources, listStaticBundles, listSyncedRepositories, listTeamMembers, listTeamProjects, listTeams, listUsers, listWebhooks, login, logout, lookupDnsARecords, mintEnrollmentToken, mkdir, nodeHeartbeat, nodeMetricsGetRange, observabilityFullEvent, observabilityListEvents, oidcCallback, type Options, patchAdminGate, patchPreviewGatewaySettings, pauseDeployment, pauseSandbox, planRestore, postDnsAck, previewAlert, previewFunnelMetrics, previewHostnameMode, promoteClusterMember, promoteDeployment, provisionDomain, purgeProjectLogs, pushExternalImage, queryData, queryGenaiTraces, queryLogs, queryMetrics, queryTraces, queryTraceSummaries, readFile, reAnalyze, recordConsoleEvent, recordEventMetrics, recordFlagExposure, recordSpeedMetrics, refreshRouteTable, regenerateDsn, registerExternalImage, registerNode, reinstallGitlabWebhook, rejectPendingAction, reloadPlugins, removeClusterMember, removeManagedDomain, removeRole, removeTeamMember, renameConversation, renewDomain, requestPasswordReset, resetPassword, resizeSandbox, resolveAlarm, restartContainer, restartPreviewGateway, restartSandbox, restoreFlag, restoreUser, resumeDeployment, resumeSandbox, retryCluster, retryDelivery, retryPgUpgrade, retryRun, revealGlobalMcpConfig, revealMcpConfig, revealNotificationProviderConfig, revealServiceParameter, revenueCreateIntegration, revenueDeleteIntegration, revenueGlobalEvents, revenueImportInvoicesCsv, revenueImportSubscriptionsCsv, revenueListIntegrations, revenueListProviders, revenueMetricsCustomers, revenueMetricsGlobalMrr, revenueMetricsGlobalSummary, revenueMetricsMrr, revenueMetricsSummary, revenueRecentEvents, revenueRotateToken, revenueUpdateConfig, revenueUpdateSecret, revokeDsn, revokeEnrollmentToken, revokeJoinToken, revokeProjectAccess, rollbackPgUpgrade, rollbackToDeployment, rootfsGc, rootfsReport, rotateApiKey, rotateDeploymentToken, runBackupForSource, runConnectionHealthCheck, runExternalServiceBackup, runScheduleNow, sandboxCreatePreviewLink, saveAgentToken, saveAiProviderCredential, searchLogs, sendEmail, setDefaultS3Source, setFlagEnvironment, setPreviewPassword, setupDns, setupDnsChallenge, setupEmailTracking, setupMfa, sleepEnvironment, smokeTestAgent, sourceSandbox, startAnalysis, startContainer, startFix, startGitProviderOauth, startOidcLoginBySlug, startPgUpgrade, startRestore, startService, statPath, stopContainer, stopSandbox, stopService, streamContainerMetrics, streamEvents, streamRunEvents, syncRepositories, tailDeploymentJobLogs, tailLogs, teardownDeployment, teardownEnvironment, testNotificationProvider, testOidcProvider, testProvider, testProviderConnection, testProviderKeyById, testProviderKeyInline, testS3ConnectionPreview, testS3SourceConnection, trackClick, trackOpen, triggerAgent, triggerProjectPipeline, triggerScan, triggerServiceHealthCheck, triggerWeeklyDigest, unlinkServiceFromProject, updateAgent, updateAiProvider, updateAlert, updateAlertRule, updateApiKey, updateAutomaticDeploy, updateBackupSchedule, updateCloudflareProvider, updateConnectionToken, updateCustomDomain, updateDashboard, updateDeploymentToken, updateEmailProvider, updateEnvironmentSettings, updateEnvironmentSubdomain, updateEnvironmentVariable, updateErrorGroup, updateFlag, updateFunnel, updateGitProviderCredentials, updateGitSettings, updateGlobalMcp, updateGlobalSkill, updateIncidentStatus, updateIpAccessControl, updateManagedDomain, updateMcp, updateNotificationEmailProvider, updateNotificationProvider, updateOidcProvider, updatePreferences, updateProject, updateProjectDeploymentConfig, updateProjectSecret, updateProjectSettings, updateProvider, updateProviderKey, updateRoute, updateS3Source, updateSelf, updateService, updateServiceResources, updateSessionDuration, updateSettings, updateSkill, updateSlackProvider, updateSpeedMetrics, updateTeam, updateTeamMemberRole, updateUser, updateWebhook, updateWebhookProvider, upgradePreviewGateway, upgradeService, uploadGlobalSkill, uploadReleaseFile, uploadSkill, uploadSourceFile, uploadSourceMap, uploadStaticBundle, upsertSecret, validateConnection, validateEmail, verifyAndEnableMfa, verifyDomain, verifyEmail, verifyManagedDomain, verifyMfaChallenge, verifyStepUp, wakeEnvironment, webhookTrigger, workflowDryRun, writeFile, writeFiles } from './sdk.gen'; +export type { AcknowledgeAlarmData, AcknowledgeAlarmErrors, AcknowledgeAlarmResponses, AcmeOrderResponse, ActivateAiProviderData, ActivateAiProviderErrors, ActivateAiProviderResponse, ActivateAiProviderResponses, ActivateApiKeyData, ActivateApiKeyErrors, ActivateApiKeyResponse, ActivateApiKeyResponses, ActivateConnectionData, ActivateConnectionErrors, ActivateConnectionResponses, ActivateProviderData, ActivateProviderErrors, ActivateProviderResponse, ActivateProviderResponses, ActiveVisitor, ActiveVisitorsQuery, ActiveVisitorsResponse, ActivityDay, ActivityEvent, ActivityGraphQuery, ActivityGraphResponse, AddClusterMemberData, AddClusterMemberErrors, AddClusterMemberRequest, AddClusterMemberResponse, AddClusterMemberResponses, AddContextData, AddContextErrors, AddContextRequest, AddContextResponses, AddEnvironmentDomainData, AddEnvironmentDomainErrors, AddEnvironmentDomainRequest, AddEnvironmentDomainResponse, AddEnvironmentDomainResponses, AddEventsData, AddEventsError, AddEventsErrors, AddEventsRequest, AddEventsResponse, AddEventsResponse2, AddEventsResponses, AddManagedDomainApiRequest, AddManagedDomainData, AddManagedDomainErrors, AddManagedDomainResponse, AddManagedDomainResponses, AddSessionReplayEventsData, AddSessionReplayEventsError, AddSessionReplayEventsErrors, AddSessionReplayEventsResponse, AddSessionReplayEventsResponses, AddTeamMemberData, AddTeamMemberErrors, AddTeamMemberResponse, AddTeamMemberResponses, AdminDrainNodeData, AdminDrainNodeErrors, AdminDrainNodeResponse, AdminDrainNodeResponses, AdminDrainStatusData, AdminDrainStatusErrors, AdminDrainStatusResponse, AdminDrainStatusResponses, AdminGateResponse, AdminGateSource, AdminGetNodeData, AdminGetNodeErrors, AdminGetNodeResponse, AdminGetNodeResponses, AdminListNodeContainersData, AdminListNodeContainersErrors, AdminListNodeContainersResponse, AdminListNodeContainersResponses, AdminListNodesData, AdminListNodesErrors, AdminListNodesResponse, AdminListNodesResponses, AdminRemoveNodeData, AdminRemoveNodeErrors, AdminRemoveNodeResponse, AdminRemoveNodeResponses, AdminUndrainNodeData, AdminUndrainNodeErrors, AdminUndrainNodeResponse, AdminUndrainNodeResponses, AgentConfigResponse, AgentRunLogResponse, AgentRunResponse, AgentRunWithLogsResponse, AgentSandboxSettings, AgentSandboxSettingsMasked, AggregatedBucketItem, AggregatedBucketsQuery, AggregatedBucketsResponse, AggregationLevel, AggregationTemporality, AiAgentBreakdownResponse, AiAgentBreakdownRow, AiAgentDescriptor, AiAgentPageRow, AiAgentPagesResponse, AiAgentTimelineResponse, AiAgentTimelineRow, AiChatLimitsSettings, AiConfigSettings, AiPageBreakdownResponse, AiPageBreakdownRow, AiStatusBreakdownResponse, AiStatusBreakdownRow, AlarmListResponse, AlarmResponse, AlarmSummaryResponse, AlertRuleResponse, AllocEntry, AnalyticsSessionEventsResponse, AnnotatedSpan, AnomalyAlgorithm, AnomalyParams, AnomalyPreviewPointResponse, AnomalyPreviewRequest, AnomalyPreviewResponse, ApiKeyListResponse, ApiKeyResponse, ApplyHostnameModeData, ApplyHostnameModeErrors, ApplyHostnameModeRequest, ApplyHostnameModeResponse, ApplyHostnameModeResponses, AppSettings, AppSettingsResponse, ArchiveConversationData, ArchiveConversationErrors, ArchiveConversationResponse, ArchiveConversationResponses, ArchiveFlagData, ArchiveFlagErrors, ArchiveFlagResponse, ArchiveFlagResponse2, ArchiveFlagResponses, ArchiveMode, AssignRoleData, AssignRoleErrors, AssignRoleRequest, AssignRoleResponses, AttachScheduleServicesData, AttachScheduleServicesError, AttachScheduleServicesErrors, AttachScheduleServicesRequest, AttachScheduleServicesResponse, AttachScheduleServicesResponse2, AttachScheduleServicesResponses, AuditLogIpInfo, AuditLogResponse, AuditLogUserInfo, AuthFlavorDto, AuthResponse, AuthStatusResponse, AuthTokenResponse, AutofixerRunResponse, AutofixerRunWithLogsResponse, AutofixRunConfig, AutoWatchParams, AvailableContainerInfo, AvailablePermissions, BackupAlertListResponse, BackupAlertResponse, BackupResponse, BackupScheduleResponse, BitbucketAuthInput, BlobCopyData, BlobCopyError, BlobCopyErrors, BlobCopyResponse, BlobCopyResponses, BlobDeleteData, BlobDeleteError, BlobDeleteErrors, BlobDeleteResponse, BlobDeleteResponses, BlobDisableData, BlobDisableErrors, BlobDisableResponse, BlobDisableResponses, BlobDownloadData, BlobDownloadError, BlobDownloadErrors, BlobDownloadResponses, BlobEnableData, BlobEnableErrors, BlobEnableResponse, BlobEnableResponses, BlobHeadData, BlobHeadError, BlobHeadErrors, BlobHeadResponses, BlobListData, BlobListError, BlobListErrors, BlobListResponse, BlobListResponses, BlobPutData, BlobPutError, BlobPutErrors, BlobPutResponse, BlobPutResponses, BlobResponse, BlobStatusData, BlobStatusErrors, BlobStatusResponse, BlobStatusResponse2, BlobStatusResponses, BlobUpdateData, BlobUpdateErrors, BlobUpdateResponse, BlobUpdateResponses, BranchInfo, BranchListResponse, BrowserCount, BrowsersQuery, BuildConfiguration, BuildLimitsSettings, CancelBackupData, CancelBackupError, CancelBackupErrors, CancelBackupResponse, CancelBackupResponse2, CancelBackupResponses, CancelData, CancelDeploymentData, CancelDeploymentErrors, CancelDeploymentResponse, CancelDeploymentResponses, CancelDomainOrderData, CancelDomainOrderErrors, CancelDomainOrderResponse, CancelDomainOrderResponses, CancelErrors, CancelPgUpgradeData, CancelPgUpgradeErrors, CancelPgUpgradeResponse, CancelPgUpgradeResponses, CancelResponses, CancelRunData, CancelRunErrors, CancelRunResponse, CancelRunResponses, CancelScheduleRunData, CancelScheduleRunError, CancelScheduleRunErrors, CancelScheduleRunResponse, CancelScheduleRunResponses, CertStatusResponse, ChallengeConfig, ChallengeError, ChallengeValidationStatus, ChangePasswordRequest, ChangePasswordSelfData, ChangePasswordSelfErrors, ChangePasswordSelfResponse, ChangePasswordSelfResponses, ChangeProjectSourceData, ChangeProjectSourceErrors, ChangeProjectSourceRequest, ChangeProjectSourceResponse, ChangeProjectSourceResponses, ChatCompletionChoice, ChatCompletionRequest, ChatCompletionResponse, ChatCompletionsData, ChatCompletionsError, ChatCompletionsErrors, ChatCompletionsResponse, ChatCompletionsResponses, ChatMessage, ChatReadinessResponse, CheckAnalyticsHasEventsData, CheckAnalyticsHasEventsErrors, CheckAnalyticsHasEventsResponse, CheckAnalyticsHasEventsResponses, CheckCommitExistsData, CheckCommitExistsErrors, CheckCommitExistsResponse, CheckCommitExistsResponses, CheckDomainStatusData, CheckDomainStatusErrors, CheckDomainStatusResponse, CheckDomainStatusResponses, CheckExplorerSupportData, CheckExplorerSupportErrors, CheckExplorerSupportResponse, CheckExplorerSupportResponses, CheckIpBlockedData, CheckIpBlockedError, CheckIpBlockedErrors, CheckIpBlockedResponses, CheckProviderDeletionSafetyData, CheckProviderDeletionSafetyErrors, CheckProviderDeletionSafetyResponse, CheckProviderDeletionSafetyResponses, ChildBackupEntryResponse, ChildBackupListResponse, ChunkUploadOptionsData, ChunkUploadOptionsResponse, ChunkUploadOptionsResponses, CleanupExpiredBackupsData, CleanupExpiredBackupsError, CleanupExpiredBackupsErrors, CleanupExpiredBackupsRequest, CleanupExpiredBackupsResponse, CleanupExpiredBackupsResponses, ClearPreviewPasswordData, ClearPreviewPasswordErrors, ClearPreviewPasswordResponse, ClearPreviewPasswordResponses, CliDeviceApproveData, CliDeviceApproveErrors, CliDeviceApproveRequest, CliDeviceApproveResponse, CliDeviceApproveResponse2, CliDeviceApproveResponses, CliDeviceDenyData, CliDeviceDenyErrors, CliDeviceDenyResponse, CliDeviceDenyResponses, CliDeviceLookupData, CliDeviceLookupErrors, CliDeviceLookupResponse, CliDeviceLookupResponse2, CliDeviceLookupResponses, CliDevicePollData, CliDevicePollErrors, CliDevicePollRequest, CliDevicePollResponse, CliDevicePollResponse2, CliDevicePollResponses, CliDeviceStartData, CliDeviceStartErrors, CliDeviceStartRequest, CliDeviceStartResponse, CliDeviceStartResponse2, CliDeviceStartResponses, ClientOptions, CliLoginRequest, CliLogoutData, CliLogoutErrors, CliLogoutResponse, CliLogoutResponses, CloudflareConfig, CloudProvider, ClusterCapacity, ClusterDnsSettings, ClusterHealthReportResponse, ClusterMemberHealthResponse, ClusterMemberRequest, CmdBody, CmdData, CmdErrors, CmdInner, CmdKillBody, CmdKillData, CmdKillErrors, CmdKillResponse, CmdKillResponses, CmdLogsData, CmdLogsErrors, CmdLogsResponses, CmdResponse, CmdResponse2, CmdResponses, CommitExistsResponse, CommitInfo, CommitListResponse, Comparator, ComposePublicPort, ConfirmPendingActionData, ConfirmPendingActionErrors, ConfirmPendingActionResponse, ConfirmPendingActionResponses, ConnectionListQuery, ConnectionListResponse, ConnectionResponse, ConnectionTestResult, ConsoleEventPayload, ContainerActionResponse, ContainerDetailResponse, ContainerEnvironmentVariableValueResponse, ContainerInfoResponse, ContainerInventoryItem, ContainerListResponse, ContainerLogSettings, ContainerLogsQuery, ContainerMetricHistoryPoint, ContainerMetricsGetHistoryData, ContainerMetricsGetHistoryErrors, ContainerMetricsGetHistoryResponse, ContainerMetricsGetHistoryResponses, ContainerMetricsHistoryQuery, ContainerMetricsResponse, ContainerResponse, ContainerRuntimeInfo, ContainerStatsSample, ContentPart, ContextLine, ContextLogsRequest, ContextLogsResponse, ConversationDetailResponse, ConversationResponse, ConversationsQueryParams, ConversationSummary, CopyBlobRequest, CostAnalysis, CreateAgentData, CreateAgentErrors, CreateAgentResponse, CreateAgentResponses, CreateAlertData, CreateAlertError, CreateAlertErrors, CreateAlertResponse, CreateAlertResponses, CreateAlertRuleData, CreateAlertRuleErrors, CreateAlertRuleRequest, CreateAlertRuleResponse, CreateAlertRuleResponses, CreateApiKeyData, CreateApiKeyErrors, CreateApiKeyRequest, CreateApiKeyResponse, CreateApiKeyResponse2, CreateApiKeyResponses, CreateBackupScheduleData, CreateBackupScheduleError, CreateBackupScheduleErrors, CreateBackupScheduleRequest, CreateBackupScheduleResponse, CreateBackupScheduleResponses, CreateBitbucketProviderData, CreateBitbucketProviderErrors, CreateBitbucketProviderResponse, CreateBitbucketProviderResponses, CreateBitbucketRequest, CreateCloudflareProviderData, CreateCloudflareProviderErrors, CreateCloudflareProviderRequest, CreateCloudflareProviderResponse, CreateCloudflareProviderResponses, CreateConversationData, CreateConversationErrors, CreateConversationRequest, CreateConversationResponse, CreateConversationResponses, CreateCustomDomainData, CreateCustomDomainErrors, CreateCustomDomainResponse, CreateCustomDomainResponses, CreateDashboardData, CreateDashboardError, CreateDashboardErrors, CreateDashboardRequest, CreateDashboardResponse, CreateDashboardResponses, CreateDeploymentTokenData, CreateDeploymentTokenErrors, CreateDeploymentTokenRequest, CreateDeploymentTokenResponse, CreateDeploymentTokenResponse2, CreateDeploymentTokenResponses, CreateDnsProviderData, CreateDnsProviderErrors, CreateDnsProviderRequest, CreateDnsProviderResponse, CreateDnsProviderResponses, CreateDomainData, CreateDomainErrors, CreateDomainRequest, CreateDomainResponse, CreateDomainResponses, CreatedResource, CreateDsnData, CreateDsnErrors, CreateDsnRequest, CreateDsnResponse, CreateDsnResponses, CreateEmailDomainData, CreateEmailDomainErrors, CreateEmailDomainRequest, CreateEmailDomainResponse, CreateEmailDomainResponses, CreateEmailProviderData, CreateEmailProviderErrors, CreateEmailProviderRequest, CreateEmailProviderResponse, CreateEmailProviderResponses, CreateEnvironmentData, CreateEnvironmentErrors, CreateEnvironmentRequest, CreateEnvironmentResponse, CreateEnvironmentResponses, CreateEnvironmentVariableData, CreateEnvironmentVariableErrors, CreateEnvironmentVariableRequest, CreateEnvironmentVariableResponse, CreateEnvironmentVariableResponses, CreateExternalServiceRequest, CreateFlagData, CreateFlagErrors, CreateFlagRequest, CreateFlagResponse, CreateFlagResponses, CreateFunnelData, CreateFunnelErrors, CreateFunnelRequest, CreateFunnelResponse, CreateFunnelResponse2, CreateFunnelResponses, CreateFunnelStep, CreateGenericProviderData, CreateGenericProviderErrors, CreateGenericProviderResponse, CreateGenericProviderResponses, CreateGenericRequest, CreateGiteaPatProviderData, CreateGiteaPatProviderErrors, CreateGiteaPatProviderResponse, CreateGiteaPatProviderResponses, CreateGiteaPatRequest, CreateGithubPatProviderData, CreateGithubPatProviderErrors, CreateGithubPatProviderResponse, CreateGithubPatProviderResponses, CreateGitHubPatRequest, CreateGitlabOauthProviderData, CreateGitlabOauthProviderErrors, CreateGitlabOauthProviderResponse, CreateGitlabOauthProviderResponses, CreateGitLabOAuthRequest, CreateGitlabPatProviderData, CreateGitlabPatProviderErrors, CreateGitlabPatProviderResponse, CreateGitlabPatProviderResponses, CreateGitLabPatRequest, CreateGitProviderData, CreateGitProviderErrors, CreateGitProviderResponse, CreateGitProviderResponses, CreateGlobalMcpData, CreateGlobalMcpErrors, CreateGlobalMcpResponse, CreateGlobalMcpResponses, CreateGlobalSkillData, CreateGlobalSkillErrors, CreateGlobalSkillResponse, CreateGlobalSkillResponses, CreateIncidentData, CreateIncidentErrors, CreateIncidentRequest, CreateIncidentResponse, CreateIncidentResponses, CreateIntegrationBody, CreateIpAccessControlData, CreateIpAccessControlError, CreateIpAccessControlErrors, CreateIpAccessControlRequest, CreateIpAccessControlResponse, CreateIpAccessControlResponses, CreateMcpData, CreateMcpErrors, CreateMcpRequest, CreateMcpResponse, CreateMcpResponses, CreateMetricAlertRequest, CreateMonitorData, CreateMonitorErrors, CreateMonitorRequest, CreateMonitorResponse, CreateMonitorResponses, CreateNotificationEmailProviderData, CreateNotificationEmailProviderErrors, CreateNotificationEmailProviderRequest, CreateNotificationEmailProviderResponse, CreateNotificationEmailProviderResponses, CreateNotificationProviderData, CreateNotificationProviderErrors, CreateNotificationProviderResponse, CreateNotificationProviderResponses, CreateOidcProviderData, CreateOidcProviderErrors, CreateOidcProviderRequest, CreateOidcProviderResponse, CreateOidcProviderResponses, CreateOidcRoleMappingData, CreateOidcRoleMappingRequest, CreateOidcRoleMappingResponse, CreateOidcRoleMappingResponses, CreateOrRecreateOrderData, CreateOrRecreateOrderErrors, CreateOrRecreateOrderResponse, CreateOrRecreateOrderResponses, CreatePlanData, CreatePlanErrors, CreatePlanRequest, CreatePlanResponse, CreatePlanResponse2, CreatePlanResponses, CreatePrData, CreatePrErrors, CreateProjectAccessRequest, CreateProjectData, CreateProjectErrors, CreateProjectFromTemplateData, CreateProjectFromTemplateErrors, CreateProjectFromTemplateRequest, CreateProjectFromTemplateResponse, CreateProjectFromTemplateResponse2, CreateProjectFromTemplateResponses, CreateProjectReleaseData, CreateProjectReleaseErrors, CreateProjectReleaseResponse, CreateProjectReleaseResponses, CreateProjectRequest, CreateProjectResponse, CreateProjectResponses, CreateProjectSecretData, CreateProjectSecretErrors, CreateProjectSecretRequest, CreateProjectSecretResponse, CreateProjectSecretResponses, CreateProviderKeyData, CreateProviderKeyError, CreateProviderKeyErrors, CreateProviderKeyRequest, CreateProviderKeyResponse, CreateProviderKeyResponses, CreateProviderRequest, CreatePrResponse, CreatePrResponse2, CreatePrResponses, CreateReleaseData, CreateReleaseErrors, CreateReleaseResponse, CreateReleaseResponses, CreateRouteData, CreateRouteErrors, CreateRouteRequest, CreateRouteResponse, CreateRouteResponses, CreateS3SourceData, CreateS3SourceError, CreateS3SourceErrors, CreateS3SourceRequest, CreateS3SourceResponse, CreateS3SourceResponses, CreateSandboxBody, CreateSandboxData, CreateSandboxErrors, CreateSandboxResponse, CreateSandboxResponses, CreateServiceData, CreateServiceErrors, CreateServiceResponse, CreateServiceResponses, CreateSkillData, CreateSkillErrors, CreateSkillRequest, CreateSkillResponse, CreateSkillResponses, CreateSlackProviderData, CreateSlackProviderErrors, CreateSlackProviderRequest, CreateSlackProviderResponse, CreateSlackProviderResponses, CreateTeamData, CreateTeamErrors, CreateTeamMemberRequest, CreateTeamRequest, CreateTeamResponse, CreateTeamResponses, CreateUserData, CreateUserErrors, CreateUserRequest, CreateUserResponse, CreateUserResponses, CreateWebhookData, CreateWebhookErrors, CreateWebhookProviderData, CreateWebhookProviderErrors, CreateWebhookProviderRequest, CreateWebhookProviderResponse, CreateWebhookProviderResponses, CreateWebhookRequestBody, CreateWebhookResponse, CreateWebhookResponses, CronExecutionInfo, CronInfo, CrossProjectSiblingRef, CrossProjectTraceResponse, CurrentStatusResponse, CustomDomainRequest, CustomDomainResponse, CustomerMovementResponse, DashboardLayout, DashboardProjectsAnalyticsQuery, DashboardProjectsAnalyticsResponse, DashboardSection, DashboardTile, DatabaseMetricsResponse, DatabaseMetricsRow, DataImplication, DataImplicationSeverity, DeactivateApiKeyData, DeactivateApiKeyErrors, DeactivateApiKeyResponse, DeactivateApiKeyResponses, DeactivateConnectionData, DeactivateConnectionErrors, DeactivateConnectionResponses, DeactivateProviderData, DeactivateProviderErrors, DeactivateProviderResponses, DeleteAgentData, DeleteAgentErrors, DeleteAgentResponse, DeleteAgentResponses, DeleteAlertData, DeleteAlertError, DeleteAlertErrors, DeleteAlertResponse, DeleteAlertResponses, DeleteAlertRuleData, DeleteAlertRuleErrors, DeleteAlertRuleResponse, DeleteAlertRuleResponses, DeleteApiKeyData, DeleteApiKeyErrors, DeleteApiKeyResponse, DeleteApiKeyResponses, DeleteBackupData, DeleteBackupError, DeleteBackupErrors, DeleteBackupResponse, DeleteBackupResponses, DeleteBackupScheduleData, DeleteBackupScheduleError, DeleteBackupScheduleErrors, DeleteBackupScheduleResponse, DeleteBackupScheduleResponses, DeleteBlobRequest, DeleteBlobResponse, DeleteConnectionData, DeleteConnectionErrors, DeleteConnectionResponse, DeleteConnectionResponses, DeleteCustomDomainData, DeleteCustomDomainErrors, DeleteCustomDomainResponse, DeleteCustomDomainResponses, DeleteDashboardData, DeleteDashboardError, DeleteDashboardErrors, DeleteDashboardResponse, DeleteDashboardResponses, DeleteDeploymentTokenData, DeleteDeploymentTokenErrors, DeleteDeploymentTokenResponse, DeleteDeploymentTokenResponses, DeleteDnsProviderData, DeleteDnsProviderErrors, DeleteDnsProviderResponse, DeleteDnsProviderResponses, DeleteDomainData, DeleteDomainErrors, DeleteDomainResponse, DeleteDomainResponses, DeleteEmailDomainData, DeleteEmailDomainErrors, DeleteEmailDomainResponse, DeleteEmailDomainResponses, DeleteEmailProviderData, DeleteEmailProviderErrors, DeleteEmailProviderResponse, DeleteEmailProviderResponses, DeleteEnvironmentData, DeleteEnvironmentDomainData, DeleteEnvironmentDomainErrors, DeleteEnvironmentDomainResponse, DeleteEnvironmentDomainResponses, DeleteEnvironmentErrors, DeleteEnvironmentResponse, DeleteEnvironmentResponses, DeleteEnvironmentVariableData, DeleteEnvironmentVariableErrors, DeleteEnvironmentVariableResponse, DeleteEnvironmentVariableResponses, DeleteExternalImageData, DeleteExternalImageErrors, DeleteExternalImageResponse, DeleteExternalImageResponses, DeleteFunnelData, DeleteFunnelErrors, DeleteFunnelResponses, DeleteGitProviderData, DeleteGitProviderErrors, DeleteGitProviderResponse, DeleteGitProviderResponses, DeleteGlobalMcpData, DeleteGlobalMcpErrors, DeleteGlobalMcpResponse, DeleteGlobalMcpResponses, DeleteGlobalSkillData, DeleteGlobalSkillErrors, DeleteGlobalSkillResponse, DeleteGlobalSkillResponses, DeleteIpAccessControlData, DeleteIpAccessControlError, DeleteIpAccessControlErrors, DeleteIpAccessControlResponse, DeleteIpAccessControlResponses, DeleteMcpData, DeleteMcpErrors, DeleteMcpResponse, DeleteMcpResponses, DeleteMonitorData, DeleteMonitorErrors, DeleteMonitorResponse, DeleteMonitorResponses, DeleteNotificationProviderData, DeleteNotificationProviderErrors, DeleteNotificationProviderResponse, DeleteNotificationProviderResponses, DeleteOidcProviderData, DeleteOidcProviderResponse, DeleteOidcProviderResponses, DeleteOidcRoleMappingData, DeleteOidcRoleMappingResponse, DeleteOidcRoleMappingResponses, DeletePreferencesData, DeletePreferencesErrors, DeletePreferencesResponse, DeletePreferencesResponses, DeleteProjectData, DeleteProjectErrors, DeleteProjectResponse, DeleteProjectResponses, DeleteProjectSecretData, DeleteProjectSecretErrors, DeleteProjectSecretResponse, DeleteProjectSecretResponses, DeleteProviderKeyData, DeleteProviderKeyError, DeleteProviderKeyErrors, DeleteProviderKeyResponse, DeleteProviderKeyResponses, DeleteProviderSafelyData, DeleteProviderSafelyErrors, DeleteProviderSafelyResponse, DeleteProviderSafelyResponses, DeleteReleaseSourceFilesData, DeleteReleaseSourceFilesErrors, DeleteReleaseSourceFilesResponse, DeleteReleaseSourceFilesResponses, DeleteReleaseSourceMapsData, DeleteReleaseSourceMapsErrors, DeleteReleaseSourceMapsResponse, DeleteReleaseSourceMapsResponses, DeleteResponse, DeleteRouteData, DeleteRouteErrors, DeleteRouteResponse, DeleteRouteResponses, DeleteS3SourceData, DeleteS3SourceError, DeleteS3SourceErrors, DeleteS3SourceResponse, DeleteS3SourceResponses, DeleteScanData, DeleteScanError, DeleteScanErrors, DeleteScanResponse, DeleteScanResponses, DeleteSecretData, DeleteSecretErrors, DeleteSecretResponse, DeleteSecretResponses, DeleteServiceData, DeleteServiceErrors, DeleteServiceResponse, DeleteServiceResponses, DeleteSessionReplayData, DeleteSessionReplayError, DeleteSessionReplayErrors, DeleteSessionReplayResponses, DeleteSkillData, DeleteSkillErrors, DeleteSkillResponse, DeleteSkillResponses, DeleteSourceMapData, DeleteSourceMapErrors, DeleteSourceMapResponse, DeleteSourceMapResponses, DeleteStaticBundleData, DeleteStaticBundleErrors, DeleteStaticBundleResponse, DeleteStaticBundleResponses, DeleteTeamData, DeleteTeamErrors, DeleteTeamResponse, DeleteTeamResponses, DeleteUserData, DeleteUserErrors, DeleteUserResponse, DeleteUserResponses, DeleteWebhookData, DeleteWebhookErrors, DeleteWebhookResponse, DeleteWebhookResponses, DelRequest, DelResponse, DeployFromImageData, DeployFromImageErrors, DeployFromImageRequest, DeployFromImageResponse, DeployFromImageResponses, DeployFromImageUploadData, DeployFromImageUploadErrors, DeployFromImageUploadQuery, DeployFromImageUploadResponse, DeployFromImageUploadResponses, DeployFromStaticData, DeployFromStaticErrors, DeployFromStaticRequest, DeployFromStaticResponse, DeployFromStaticResponses, DeployFromUploadedSourceData, DeployFromUploadedSourceErrors, DeployFromUploadedSourceResponse, DeployFromUploadedSourceResponses, DeploymentConfig, DeploymentConfigSnapshot, DeploymentConfiguration, DeploymentContainerLogContentResponse, DeploymentContainerLogResponse, DeploymentContainerLogsListResponse, DeploymentEnvironmentResponse, DeploymentJobResponse, DeploymentJobsResponse, DeploymentListResponse, DeploymentMetadata, DeploymentMetricsGetLatestData, DeploymentMetricsGetLatestErrors, DeploymentMetricsGetLatestResponse, DeploymentMetricsGetLatestResponses, DeploymentMetricsGetRangeData, DeploymentMetricsGetRangeErrors, DeploymentMetricsGetRangeResponse, DeploymentMetricsGetRangeResponses, DeploymentMetricsToggleData, DeploymentMetricsToggleErrors, DeploymentMetricsToggleResponses, DeploymentResponse, DeploymentStateResponse, DeploymentStrategy, DeploymentTokenListResponse, DeploymentTokenResponse, DestroySandboxData, DestroySandboxErrors, DestroySandboxResponse, DestroySandboxResponses, DetachScheduleServiceData, DetachScheduleServiceError, DetachScheduleServiceErrors, DetachScheduleServiceResponse, DetachScheduleServiceResponses, DetectionConfig, DetectPublicPresetsData, DetectPublicPresetsErrors, DetectPublicPresetsResponse, DetectPublicPresetsResponses, DeviceCount, DigestSections, Direction, DisableBackupScheduleData, DisableBackupScheduleErrors, DisableBackupScheduleResponse, DisableBackupScheduleResponses, DisableBlobResponse, DisableKvResponse, DisableMfaData, DisableMfaErrors, DisableMfaRequest, DisableMfaResponse, DisableMfaResponses, DiscoverRequest, DiscoverResponse, DiscoverWorkloadsData, DiscoverWorkloadsErrors, DiscoverWorkloadsResponse, DiscoverWorkloadsResponses, DiskInfo, DiskSpaceAlert, DiskSpaceAlertSettings, DiskSpaceCheckResult, DnsAckRequest, DnsAckResponse, DnsChallengeRecordResult, DnsChangesResponse, DnsCompletionResponse, DnsLookupError, DnsLookupRequest, DnsLookupResponse, DnsProviderCredentials, DnsProviderResponse, DnsProviderSettings, DnsProviderSettingsMasked, DnsProviderType, DnsRecord, DnsRecordChange, DnsRecordContent, DnsRecordResponse, DnsRecordSetupResult, DnsRecordStatusResponse, DnsZone, DockerComposePresetConfig, DockerfilePresetConfig, DockerfileVariant, DockerRegistrySettings, DockerRegistrySettingsMasked, DomainAction, DomainChallengeResponse, DomainData, DomainEnvironmentResponse, DomainError, DomainErrors, DomainPlan, DomainResponse, DomainResponse2, DomainResponses, DownloadGlobalSkillArchiveData, DownloadGlobalSkillArchiveErrors, DownloadGlobalSkillArchiveResponse, DownloadGlobalSkillArchiveResponses, DownloadObjectData, DownloadObjectErrors, DownloadObjectResponse, DownloadObjectResponses, DownloadSkillArchiveData, DownloadSkillArchiveErrors, DownloadSkillArchiveResponse, DownloadSkillArchiveResponses, DrainNodeResponse, DrainStatusResponse, DropArchiveUpload, DropInspectionResponse, DropOffPoint, DropPresetCandidate, EmailConfig, EmailDomainResponse, EmailDomainWithDnsResponse, EmailProviderResponse, EmailProviderTypeRoute, EmailRequest, EmailResponse, EmailStatsResponse, EmailStatusData, EmailStatusErrors, EmailStatusResponse, EmailStatusResponse2, EmailStatusResponses, EmailTrackingResponse, EmailTrackingSetupResponse, EmailTrackingStatusResponse, EmbeddingData, EmbeddingInput, EmbeddingRequest, EmbeddingResponse, EmbeddingsData, EmbeddingsError, EmbeddingsErrors, EmbeddingsResponse, EmbeddingsResponses, EmbeddingUsage, EnableBackupScheduleData, EnableBackupScheduleErrors, EnableBackupScheduleResponse, EnableBackupScheduleResponses, EnableBlobRequest, EnableBlobResponse, EnableKvRequest, EnableKvResponse, EnablePgStatStatementsResponse, EndpointDto, EnqueuedJob, EnrichVisitorData, EnrichVisitorErrors, EnrichVisitorRequest, EnrichVisitorResponse, EnrichVisitorResponse2, EnrichVisitorResponses, EnrollmentTokenInfo, EnrollmentTokenListResponse, EntityInfoResponse, EntityResponse, EnvironmentConfiguration, EnvironmentDomainResponse, EnvironmentInfo, EnvironmentResponse, EnvironmentVariable, EnvironmentVariableInfo, EnvironmentVariableResponse, EnvironmentVariableValueResponse, EnvVarInput, EnvVarIntegrationInfo, EnvVarResponse, EnvVarTemplateResponse, ErrorDashboardStatsQuery, ErrorDashboardStatsResponse, ErrorEventResponse, ErrorGroupResponse, ErrorGroupStatsResponse, ErrorResponse, ErrorRow, ErrorTimeSeriesDataResponse, ErrorTimeSeriesQuery, EventActivityBucket, EventBreakdown, EventBrowserStats, EventCount, EventCountryStats, EventDetailQuery, EventDetailResponse, EventEntriesQuery, EventEntriesResponse, EventEntryInfo, EventKind, EventMetricsPayload, EventReferrerStats, EventsCountQuery, EventsResponse, EventTimeline, EventTimelineQuery, EventType, EventTypeBreakdown, EventTypeBreakdownQuery, EventTypeResponse, EventTypesResponse, EventVisitorInfo, EventVisitorsQuery, EventVisitorsResponse, ExecBody, ExecData, ExecDetachedData, ExecDetachedErrors, ExecDetachedResponse, ExecDetachedResponse2, ExecDetachedResponses, ExecErrors, ExecResponse, ExecResponse2, ExecResponses, ExecuteDeploymentOperationData, ExecuteDeploymentOperationErrors, ExecuteDeploymentOperationResponse, ExecuteDeploymentOperationResponses, ExecuteImportData, ExecuteImportErrors, ExecuteImportRequest, ExecuteImportResponse, ExecuteImportResponse2, ExecuteImportResponses, ExecuteOperationRequest, ExpireRequest, ExpireResponse, ExplorerSupportResponse, ExtendTimeoutBody, ExtendTimeoutData, ExtendTimeoutErrors, ExtendTimeoutResponse, ExtendTimeoutResponses, ExternalImageResponse, ExternalServiceBackupResponse, ExternalServiceDetails, ExternalServiceEnablePgStatStatementsData, ExternalServiceEnablePgStatStatementsErrors, ExternalServiceEnablePgStatStatementsResponse, ExternalServiceEnablePgStatStatementsResponses, ExternalServiceInfo, ExternalServiceMetricsByDatabaseData, ExternalServiceMetricsByDatabaseErrors, ExternalServiceMetricsByDatabaseResponse, ExternalServiceMetricsByDatabaseResponses, ExternalServiceMetricsCreateAlertRuleData, ExternalServiceMetricsCreateAlertRuleErrors, ExternalServiceMetricsCreateAlertRuleResponse, ExternalServiceMetricsCreateAlertRuleResponses, ExternalServiceMetricsDeleteAlertRuleData, ExternalServiceMetricsDeleteAlertRuleErrors, ExternalServiceMetricsDeleteAlertRuleResponse, ExternalServiceMetricsDeleteAlertRuleResponses, ExternalServiceMetricsGetAlertRulesData, ExternalServiceMetricsGetAlertRulesErrors, ExternalServiceMetricsGetAlertRulesResponse, ExternalServiceMetricsGetAlertRulesResponses, ExternalServiceMetricsGetLatestData, ExternalServiceMetricsGetLatestErrors, ExternalServiceMetricsGetLatestResponse, ExternalServiceMetricsGetLatestResponses, ExternalServiceMetricsGetRangeData, ExternalServiceMetricsGetRangeErrors, ExternalServiceMetricsGetRangeResponse, ExternalServiceMetricsGetRangeResponses, ExternalServiceMetricsStatusData, ExternalServiceMetricsStatusErrors, ExternalServiceMetricsStatusResponse, ExternalServiceMetricsStatusResponses, ExternalServiceMetricsToggleData, ExternalServiceMetricsToggleErrors, ExternalServiceMetricsToggleResponses, ExternalServiceMetricsUpdateAlertRuleData, ExternalServiceMetricsUpdateAlertRuleErrors, ExternalServiceMetricsUpdateAlertRuleResponse, ExternalServiceMetricsUpdateAlertRuleResponses, ExternalServiceResetPgStatStatementsData, ExternalServiceResetPgStatStatementsErrors, ExternalServiceResetPgStatStatementsResponse, ExternalServiceResetPgStatStatementsResponses, ExternalServiceSummary, FieldResponse, FinalizeOrderData, FinalizeOrderErrors, FinalizeOrderResponse, FinalizeOrderResponses, FinalizeProjectReleaseData, FinalizeProjectReleaseErrors, FinalizeProjectReleaseResponse, FinalizeProjectReleaseResponses, FindConversationData, FindConversationErrors, FindConversationResponse, FindConversationResponses, FiringSeriesEntry, FlagEnvironmentResponse, FlagListResponse, FlagResponse, FlagSnapshot, FlagSnapshotResponse, FlagValueType, ForecastAlgorithm, ForecastParams, FullError, FullEvent, FullRequest, FunnelMetricsResponse, FunnelResponse, GatewayStatus, GenAiEvent, GenAiSpanDetail, GenAiTraceDetailResponse, GenAiTraceSummariesResponse, GenAiTraceSummary, GeneralStatsQuery, GeneralStatsResponse, GenerateDockerfileRequest, GenerateDockerfileResponse, GenerateJoinTokenData, GenerateJoinTokenErrors, GenerateJoinTokenResponse, GenerateJoinTokenResponse2, GenerateJoinTokenResponses, GeneratePresetDockerfileData, GeneratePresetDockerfileErrors, GeneratePresetDockerfileResponse, GeneratePresetDockerfileResponses, GeoLocationResponse, GeoRestrictionsConfig, GetAccessInfoData, GetAccessInfoErrors, GetAccessInfoResponse, GetAccessInfoResponses, GetActiveVisitorsData, GetActiveVisitorsErrors, GetActiveVisitorsResponse, GetActiveVisitorsResponses, GetActivityGraphData, GetActivityGraphErrors, GetActivityGraphResponse, GetActivityGraphResponses, GetAdminGateData, GetAdminGateErrors, GetAdminGateResponse, GetAdminGateResponses, GetAgentData, GetAgentErrors, GetAgentResponse, GetAgentResponses, GetAggregatedBucketsData, GetAggregatedBucketsErrors, GetAggregatedBucketsResponse, GetAggregatedBucketsResponses, GetAiAgentBreakdownData, GetAiAgentBreakdownError, GetAiAgentBreakdownErrors, GetAiAgentBreakdownResponse, GetAiAgentBreakdownResponses, GetAiAgentPagesData, GetAiAgentPagesError, GetAiAgentPagesErrors, GetAiAgentPagesResponse, GetAiAgentPagesResponses, GetAiAgentTimelineData, GetAiAgentTimelineError, GetAiAgentTimelineErrors, GetAiAgentTimelineResponse, GetAiAgentTimelineResponses, GetAiPageBreakdownData, GetAiPageBreakdownError, GetAiPageBreakdownErrors, GetAiPageBreakdownResponse, GetAiPageBreakdownResponses, GetAiStatusBreakdownData, GetAiStatusBreakdownError, GetAiStatusBreakdownErrors, GetAiStatusBreakdownResponse, GetAiStatusBreakdownResponses, GetAlertData, GetAlertError, GetAlertErrors, GetAlertResponse, GetAlertResponses, GetAlertRuleData, GetAlertRuleErrors, GetAlertRuleResponse, GetAlertRuleResponses, GetAllRepositoriesByNameData, GetAllRepositoriesByNameErrors, GetAllRepositoriesByNameResponse, GetAllRepositoriesByNameResponses, GetAnalyticsActiveVisitorsData, GetAnalyticsActiveVisitorsErrors, GetAnalyticsActiveVisitorsResponse, GetAnalyticsActiveVisitorsResponses, GetAnalyticsEventsCountData, GetAnalyticsEventsCountErrors, GetAnalyticsEventsCountResponse, GetAnalyticsEventsCountResponses, GetAnalyticsSessionEventsData, GetAnalyticsSessionEventsErrors, GetAnalyticsSessionEventsResponse, GetAnalyticsSessionEventsResponses, GetAnalyticsVisitorSessionsData, GetAnalyticsVisitorSessionsErrors, GetAnalyticsVisitorSessionsResponse, GetAnalyticsVisitorSessionsResponses, GetApiKeyData, GetApiKeyErrors, GetApiKeyPermissionsData, GetApiKeyPermissionsErrors, GetApiKeyPermissionsResponse, GetApiKeyPermissionsResponses, GetApiKeyResponse, GetApiKeyResponses, GetAuditLogData, GetAuditLogErrors, GetAuditLogResponse, GetAuditLogResponses, GetBackupData, GetBackupError, GetBackupErrors, GetBackupResponse, GetBackupResponses, GetBackupScheduleData, GetBackupScheduleErrors, GetBackupScheduleResponse, GetBackupScheduleResponses, GetBranchesByRepositoryIdData, GetBranchesByRepositoryIdErrors, GetBranchesByRepositoryIdResponse, GetBranchesByRepositoryIdResponses, GetBucketedIncidentsData, GetBucketedIncidentsErrors, GetBucketedIncidentsResponse, GetBucketedIncidentsResponses, GetBucketedStatusData, GetBucketedStatusErrors, GetBucketedStatusResponse, GetBucketedStatusResponses, GetChallengeTokenData, GetChallengeTokenErrors, GetChallengeTokenResponse, GetChallengeTokenResponses, GetChatReadinessData, GetChatReadinessErrors, GetChatReadinessResponse, GetChatReadinessResponses, GetCliStatusData, GetCliStatusErrors, GetCliStatusResponses, GetClusterHealthData, GetClusterHealthErrors, GetClusterHealthResponse, GetClusterHealthResponses, GetClusterMemberData, GetClusterMemberErrors, GetClusterMemberResponse, GetClusterMemberResponses, GetCmdData, GetCmdErrors, GetCmdResponse, GetCmdResponses, GetContainerDetailData, GetContainerDetailErrors, GetContainerDetailResponse, GetContainerDetailResponses, GetContainerEnvironmentVariableData, GetContainerEnvironmentVariableErrors, GetContainerEnvironmentVariableResponse, GetContainerEnvironmentVariableResponses, GetContainerInfoData, GetContainerInfoErrors, GetContainerInfoResponse, GetContainerInfoResponses, GetContainerLogsByIdData, GetContainerLogsByIdErrors, GetContainerLogsData, GetContainerLogsErrors, GetContainerMetricsData, GetContainerMetricsErrors, GetContainerMetricsResponse, GetContainerMetricsResponses, GetConversationData, GetConversationDetailData, GetConversationDetailError, GetConversationDetailErrors, GetConversationDetailResponse, GetConversationDetailResponses, GetConversationErrors, GetConversationResponse, GetConversationResponses, GetConversationsData, GetConversationsError, GetConversationsErrors, GetConversationsResponse, GetConversationsResponses, GetCronByIdData, GetCronByIdErrors, GetCronByIdResponse, GetCronByIdResponses, GetCronExecutionsData, GetCronExecutionsErrors, GetCronExecutionsResponse, GetCronExecutionsResponses, GetCrossProjectTraceSiblingsData, GetCrossProjectTraceSiblingsError, GetCrossProjectTraceSiblingsErrors, GetCrossProjectTraceSiblingsResponse, GetCrossProjectTraceSiblingsResponses, GetCurrentMonitorStatusData, GetCurrentMonitorStatusErrors, GetCurrentMonitorStatusResponse, GetCurrentMonitorStatusResponses, GetCurrentUserData, GetCurrentUserErrors, GetCurrentUserResponse, GetCurrentUserResponses, GetCustomDomainData, GetCustomDomainErrors, GetCustomDomainResponse, GetCustomDomainResponses, GetDashboardData, GetDashboardError, GetDashboardErrors, GetDashboardProjectsAnalyticsData, GetDashboardProjectsAnalyticsErrors, GetDashboardProjectsAnalyticsResponse, GetDashboardProjectsAnalyticsResponses, GetDashboardResponse, GetDashboardResponses, GetDeliveryData, GetDeliveryErrors, GetDeliveryResponse, GetDeliveryResponses, GetDeploymentContainerLogContentData, GetDeploymentContainerLogContentErrors, GetDeploymentContainerLogContentResponse, GetDeploymentContainerLogContentResponses, GetDeploymentData, GetDeploymentErrors, GetDeploymentJobLogsData, GetDeploymentJobLogsErrors, GetDeploymentJobLogsResponse, GetDeploymentJobLogsResponses, GetDeploymentJobsData, GetDeploymentJobsErrors, GetDeploymentJobsResponse, GetDeploymentJobsResponses, GetDeploymentOperationsData, GetDeploymentOperationsErrors, GetDeploymentOperationsResponse, GetDeploymentOperationsResponses, GetDeploymentOperationStatusData, GetDeploymentOperationStatusErrors, GetDeploymentOperationStatusResponse, GetDeploymentOperationStatusResponses, GetDeploymentResponse, GetDeploymentResponses, GetDeploymentsParams, GetDeploymentTokenData, GetDeploymentTokenErrors, GetDeploymentTokenResponse, GetDeploymentTokenResponses, GetDiskStatusData, GetDiskStatusErrors, GetDiskStatusResponse, GetDiskStatusResponses, GetDnsChangesData, GetDnsChangesErrors, GetDnsChangesResponse, GetDnsChangesResponses, GetDnsProviderData, GetDnsProviderErrors, GetDnsProviderResponse, GetDnsProviderResponses, GetDomainByHostData, GetDomainByHostErrors, GetDomainByHostResponse, GetDomainByHostResponses, GetDomainByIdData, GetDomainByIdErrors, GetDomainByIdResponse, GetDomainByIdResponses, GetDomainByNameData, GetDomainByNameErrors, GetDomainByNameResponse, GetDomainByNameResponses, GetDomainData, GetDomainDnsRecordsData, GetDomainDnsRecordsErrors, GetDomainDnsRecordsResponse, GetDomainDnsRecordsResponses, GetDomainErrors, GetDomainOrderData, GetDomainOrderErrors, GetDomainOrderResponse, GetDomainOrderResponses, GetDomainResponse, GetDomainResponses, GetEmailData, GetEmailErrors, GetEmailEventsData, GetEmailEventsErrors, GetEmailEventsResponse, GetEmailEventsResponses, GetEmailLinksData, GetEmailLinksErrors, GetEmailLinksResponse, GetEmailLinksResponses, GetEmailProviderData, GetEmailProviderErrors, GetEmailProviderResponse, GetEmailProviderResponses, GetEmailResponse, GetEmailResponses, GetEmailStatsData, GetEmailStatsErrors, GetEmailStatsResponse, GetEmailStatsResponses, GetEmailTrackingData, GetEmailTrackingErrors, GetEmailTrackingResponse, GetEmailTrackingResponses, GetEmailTrackingStatusData, GetEmailTrackingStatusErrors, GetEmailTrackingStatusResponse, GetEmailTrackingStatusResponses, GetEntityInfoData, GetEntityInfoErrors, GetEntityInfoResponse, GetEntityInfoResponses, GetEnvironmentCronsData, GetEnvironmentCronsErrors, GetEnvironmentCronsResponse, GetEnvironmentCronsResponses, GetEnvironmentData, GetEnvironmentDomainsData, GetEnvironmentDomainsErrors, GetEnvironmentDomainsResponse, GetEnvironmentDomainsResponses, GetEnvironmentErrors, GetEnvironmentResponse, GetEnvironmentResponses, GetEnvironmentsData, GetEnvironmentsErrors, GetEnvironmentsResponse, GetEnvironmentsResponses, GetEnvironmentVariablesData, GetEnvironmentVariablesErrors, GetEnvironmentVariablesQuery, GetEnvironmentVariablesResponse, GetEnvironmentVariablesResponses, GetEnvironmentVariableValueData, GetEnvironmentVariableValueErrors, GetEnvironmentVariableValueResponse, GetEnvironmentVariableValueResponses, GetErrorDashboardStatsData, GetErrorDashboardStatsErrors, GetErrorDashboardStatsResponse, GetErrorDashboardStatsResponses, GetErrorEventData, GetErrorEventErrors, GetErrorEventResponse, GetErrorEventResponses, GetErrorGroupData, GetErrorGroupErrors, GetErrorGroupResponse, GetErrorGroupResponses, GetErrorStatsData, GetErrorStatsErrors, GetErrorStatsResponse, GetErrorStatsResponses, GetErrorTimeSeriesData, GetErrorTimeSeriesErrors, GetErrorTimeSeriesResponse, GetErrorTimeSeriesResponses, GetEventDetailData, GetEventDetailErrors, GetEventDetailResponse, GetEventDetailResponses, GetEventEntriesData, GetEventEntriesErrors, GetEventEntriesResponse, GetEventEntriesResponses, GetEventsCountData, GetEventsCountErrors, GetEventsCountResponse, GetEventsCountResponses, GetEventsTimelineData, GetEventsTimelineErrors, GetEventsTimelineResponse, GetEventsTimelineResponses, GetEventTypeBreakdownData, GetEventTypeBreakdownErrors, GetEventTypeBreakdownResponse, GetEventTypeBreakdownResponses, GetEventVisitorsData, GetEventVisitorsErrors, GetEventVisitorsResponse, GetEventVisitorsResponses, GetExternalImageData, GetExternalImageErrors, GetExternalImageResponse, GetExternalImageResponses, GetFileData, GetFileErrors, GetFileResponse, GetFileResponses, GetFlagData, GetFlagErrors, GetFlagResponse, GetFlagResponses, GetFlagSnapshotData, GetFlagSnapshotErrors, GetFlagSnapshotResponse, GetFlagSnapshotResponses, GetFunnelMetricsData, GetFunnelMetricsErrors, GetFunnelMetricsQuery, GetFunnelMetricsResponse, GetFunnelMetricsResponses, GetGenaiTraceData, GetGenaiTraceError, GetGenaiTraceErrors, GetGenaiTraceResponse, GetGenaiTraceResponses, GetGeneralStatsData, GetGeneralStatsErrors, GetGeneralStatsResponse, GetGeneralStatsResponses, GetGitProviderData, GetGitProviderErrors, GetGitProviderResponse, GetGitProviderResponses, GetGlobalEventsData, GetGlobalEventsErrors, GetGlobalEventsResponse, GetGlobalEventsResponses, GetGlobalEventStatsData, GetGlobalEventStatsErrors, GetGlobalEventStatsResponse, GetGlobalEventStatsResponses, GetGlobalMcpData, GetGlobalMcpErrors, GetGlobalMcpResponse, GetGlobalMcpResponses, GetGlobalSandboxStatusData, GetGlobalSandboxStatusErrors, GetGlobalSandboxStatusResponse, GetGlobalSandboxStatusResponses, GetGlobalSkillData, GetGlobalSkillErrors, GetGlobalSkillResponse, GetGlobalSkillResponses, GetGroupedPageMetricsData, GetGroupedPageMetricsError, GetGroupedPageMetricsErrors, GetGroupedPageMetricsResponse, GetGroupedPageMetricsResponses, GetHealthData, GetHealthError, GetHealthErrors, GetHealthResponse, GetHealthResponses, GetHourlyVisitsData, GetHourlyVisitsErrors, GetHourlyVisitsResponse, GetHourlyVisitsResponses, GetHttpChallengeDebugData, GetHttpChallengeDebugErrors, GetHttpChallengeDebugResponse, GetHttpChallengeDebugResponses, GetImportStatusData, GetImportStatusErrors, GetImportStatusResponse, GetImportStatusResponses, GetIncidentData, GetIncidentErrors, GetIncidentResponse, GetIncidentResponses, GetIncidentUpdatesData, GetIncidentUpdatesErrors, GetIncidentUpdatesResponse, GetIncidentUpdatesResponses, GetIpAccessControlData, GetIpAccessControlError, GetIpAccessControlErrors, GetIpAccessControlResponse, GetIpAccessControlResponses, GetIpGeolocationData, GetIpGeolocationError, GetIpGeolocationErrors, GetIpGeolocationResponse, GetIpGeolocationResponses, GetJoinTokenStatusData, GetJoinTokenStatusErrors, GetJoinTokenStatusResponse, GetJoinTokenStatusResponses, GetLastDeploymentData, GetLastDeploymentErrors, GetLastDeploymentResponse, GetLastDeploymentResponses, GetLatestScanData, GetLatestScanError, GetLatestScanErrors, GetLatestScanResponse, GetLatestScanResponses, GetLatestScansPerEnvironmentData, GetLatestScansPerEnvironmentError, GetLatestScansPerEnvironmentErrors, GetLatestScansPerEnvironmentResponse, GetLatestScansPerEnvironmentResponses, GetLiveVisitorsListData, GetLiveVisitorsListErrors, GetLiveVisitorsListResponse, GetLiveVisitorsListResponses, GetLogContextData, GetLogContextError, GetLogContextErrors, GetLogContextResponse, GetLogContextResponses, GetMcpData, GetMcpErrors, GetMcpResponse, GetMcpResponses, GetMetricsOverTimeData, GetMetricsOverTimeError, GetMetricsOverTimeErrors, GetMetricsOverTimeResponse, GetMetricsOverTimeResponses, GetMonitorData, GetMonitorErrors, GetMonitorResponse, GetMonitorResponses, GetNotificationProviderData, GetNotificationProviderErrors, GetNotificationProviderResponse, GetNotificationProviderResponses, GetOnDemandCertStatusData, GetOnDemandCertStatusErrors, GetOnDemandCertStatusResponse, GetOnDemandCertStatusResponses, GetOrCreateDsnData, GetOrCreateDsnErrors, GetOrCreateDsnRequest, GetOrCreateDsnResponse, GetOrCreateDsnResponses, GetPageFlowData, GetPageFlowErrors, GetPageFlowResponse, GetPageFlowResponses, GetPageHourlySessionsData, GetPageHourlySessionsErrors, GetPageHourlySessionsResponse, GetPageHourlySessionsResponses, GetPagePathDetailData, GetPagePathDetailErrors, GetPagePathDetailResponse, GetPagePathDetailResponses, GetPagePathsData, GetPagePathsErrors, GetPagePathsResponse, GetPagePathsResponses, GetPagePathsSparklinesData, GetPagePathsSparklinesErrors, GetPagePathsSparklinesResponse, GetPagePathsSparklinesResponses, GetPagePathVisitorsData, GetPagePathVisitorsErrors, GetPagePathVisitorsResponse, GetPagePathVisitorsResponses, GetPendingActionData, GetPendingActionErrors, GetPendingActionResponse, GetPendingActionResponses, GetPerformanceMetricsData, GetPerformanceMetricsError, GetPerformanceMetricsErrors, GetPerformanceMetricsResponse, GetPerformanceMetricsResponses, GetPgUpgradeData, GetPgUpgradeErrors, GetPgUpgradeLogsData, GetPgUpgradeLogsErrors, GetPgUpgradeLogsResponse, GetPgUpgradeLogsResponses, GetPgUpgradeResponse, GetPgUpgradeResponses, GetPipelineStatsData, GetPipelineStatsError, GetPipelineStatsErrors, GetPipelineStatsResponse, GetPipelineStatsResponses, GetPlatformInfoData, GetPlatformInfoErrors, GetPlatformInfoResponse, GetPlatformInfoResponses, GetPostgresWalHealthData, GetPostgresWalHealthErrors, GetPostgresWalHealthResponse, GetPostgresWalHealthResponses, GetPreferencesData, GetPreferencesErrors, GetPreferencesResponse, GetPreferencesResponses, GetPreviewGatewayLogsData, GetPreviewGatewayLogsResponse, GetPreviewGatewayLogsResponses, GetPreviewGatewaySettingsData, GetPreviewGatewaySettingsResponse, GetPreviewGatewaySettingsResponses, GetPreviewGatewayStatusData, GetPreviewGatewayStatusResponse, GetPreviewGatewayStatusResponses, GetPricingData, GetPricingError, GetPricingErrors, GetPricingResponse, GetPricingResponses, GetPrivateIpData, GetPrivateIpErrors, GetPrivateIpResponses, GetProjectAlarmsSummaryData, GetProjectAlarmsSummaryErrors, GetProjectAlarmsSummaryResponse, GetProjectAlarmsSummaryResponses, GetProjectBySlugData, GetProjectBySlugErrors, GetProjectBySlugResponse, GetProjectBySlugResponses, GetProjectData, GetProjectDeploymentsData, GetProjectDeploymentsErrors, GetProjectDeploymentsResponse, GetProjectDeploymentsResponses, GetProjectErrors, GetProjectResponse, GetProjectResponses, GetProjectsData, GetProjectSecretsQuery, GetProjectsErrors, GetProjectServiceEnvironmentVariablesData, GetProjectServiceEnvironmentVariablesErrors, GetProjectServiceEnvironmentVariablesResponse, GetProjectServiceEnvironmentVariablesResponses, GetProjectSessionReplaysData, GetProjectSessionReplaysError, GetProjectSessionReplaysErrors, GetProjectSessionReplaysQuery, GetProjectSessionReplaysResponse, GetProjectSessionReplaysResponse2, GetProjectSessionReplaysResponses, GetProjectsHealthData, GetProjectsHealthError, GetProjectsHealthErrors, GetProjectsHealthResponse, GetProjectsHealthResponses, GetProjectsMonitorHealthData, GetProjectsMonitorHealthErrors, GetProjectsMonitorHealthResponse, GetProjectsMonitorHealthResponses, GetProjectsResponse, GetProjectsResponses, GetProjectStatisticsData, GetProjectStatisticsErrors, GetProjectStatisticsResponse, GetProjectStatisticsResponses, GetProjectTemplateData, GetProjectTemplateErrors, GetProjectTemplateResponse, GetProjectTemplateResponses, GetPropertyBreakdownData, GetPropertyBreakdownErrors, GetPropertyBreakdownResponse, GetPropertyBreakdownResponses, GetPropertyTimelineData, GetPropertyTimelineErrors, GetPropertyTimelineResponse, GetPropertyTimelineResponses, GetProviderConnectionsData, GetProviderConnectionsErrors, GetProviderConnectionsResponse, GetProviderConnectionsResponses, GetProviderMetadataData, GetProviderMetadataErrors, GetProviderMetadataResponse, GetProviderMetadataResponses, GetProvidersMetadataData, GetProvidersMetadataErrors, GetProvidersMetadataResponse, GetProvidersMetadataResponses, GetProxyLogByIdData, GetProxyLogByIdError, GetProxyLogByIdErrors, GetProxyLogByIdResponse, GetProxyLogByIdResponses, GetProxyLogByRequestIdData, GetProxyLogByRequestIdError, GetProxyLogByRequestIdErrors, GetProxyLogByRequestIdResponse, GetProxyLogByRequestIdResponses, GetProxyLogsData, GetProxyLogsError, GetProxyLogsErrors, GetProxyLogsResponse, GetProxyLogsResponses, GetPublicBranchesData, GetPublicBranchesErrors, GetPublicBranchesResponse, GetPublicBranchesResponses, GetPublicIpData, GetPublicIpErrors, GetPublicIpResponses, GetPublicRepositoryData, GetPublicRepositoryErrors, GetPublicRepositoryResponse, GetPublicRepositoryResponses, GetQuotaData, GetQuotaError, GetQuotaErrors, GetQuotaResponse, GetQuotaResponses, GetRecentActivityData, GetRecentActivityErrors, GetRecentActivityResponse, GetRecentActivityResponses, GetRemoteExternalImageData, GetRemoteExternalImageErrors, GetRemoteExternalImageResponse, GetRemoteExternalImageResponses, GetRepositoryBranchesData, GetRepositoryBranchesErrors, GetRepositoryBranchesResponse, GetRepositoryBranchesResponses, GetRepositoryByIdData, GetRepositoryByIdErrors, GetRepositoryByIdResponse, GetRepositoryByIdResponses, GetRepositoryByNameData, GetRepositoryByNameErrors, GetRepositoryByNameResponse, GetRepositoryByNameResponses, GetRepositoryPresetByNameData, GetRepositoryPresetByNameErrors, GetRepositoryPresetByNameResponse, GetRepositoryPresetByNameResponses, GetRepositoryPresetLiveData, GetRepositoryPresetLiveErrors, GetRepositoryPresetLiveResponse, GetRepositoryPresetLiveResponses, GetRepositoryTagsData, GetRepositoryTagsErrors, GetRepositoryTagsResponse, GetRepositoryTagsResponses, GetRequest, GetResolvedEnvironmentVariablesData, GetResolvedEnvironmentVariablesErrors, GetResolvedEnvironmentVariablesResponse, GetResolvedEnvironmentVariablesResponses, GetResolvedEnvironmentVariableValueData, GetResolvedEnvironmentVariableValueErrors, GetResolvedEnvironmentVariableValueResponse, GetResolvedEnvironmentVariableValueResponses, GetResponse, GetRestoreCapabilitiesData, GetRestoreCapabilitiesError, GetRestoreCapabilitiesErrors, GetRestoreCapabilitiesResponse, GetRestoreCapabilitiesResponses, GetRestoreRunData, GetRestoreRunError, GetRestoreRunErrors, GetRestoreRunResponse, GetRestoreRunResponses, GetRouteData, GetRouteErrors, GetRouteResponse, GetRouteResponses, GetRunData, GetRunErrors, GetRunResponse, GetRunResponses, GetRunWithLogsData, GetRunWithLogsErrors, GetRunWithLogsResponse, GetRunWithLogsResponses, GetS3CredentialsData, GetS3CredentialsErrors, GetS3CredentialsResponse, GetS3CredentialsResponses, GetS3SourceData, GetS3SourceError, GetS3SourceErrors, GetS3SourceResponse, GetS3SourceResponses, GetSandboxData, GetSandboxErrors, GetSandboxResponse, GetSandboxResponses, GetSandboxStatusData, GetSandboxStatusErrors, GetSandboxStatusResponse, GetSandboxStatusResponses, GetScanByDeploymentData, GetScanByDeploymentError, GetScanByDeploymentErrors, GetScanByDeploymentResponse, GetScanByDeploymentResponses, GetScanData, GetScanError, GetScanErrors, GetScanResponse, GetScanResponses, GetScanVulnerabilitiesData, GetScanVulnerabilitiesError, GetScanVulnerabilitiesErrors, GetScanVulnerabilitiesResponse, GetScanVulnerabilitiesResponses, GetServiceBySlugData, GetServiceBySlugErrors, GetServiceBySlugResponse, GetServiceBySlugResponses, GetServiceData, GetServiceEnvironmentVariableData, GetServiceEnvironmentVariableErrors, GetServiceEnvironmentVariableResponse, GetServiceEnvironmentVariableResponses, GetServiceEnvironmentVariablesData, GetServiceEnvironmentVariablesErrors, GetServiceEnvironmentVariablesResponse, GetServiceEnvironmentVariablesResponses, GetServiceErrors, GetServiceHealthStatusData, GetServiceHealthStatusErrors, GetServiceHealthStatusResponse, GetServiceHealthStatusResponses, GetServicePreviewEnvironmentVariableNamesData, GetServicePreviewEnvironmentVariableNamesErrors, GetServicePreviewEnvironmentVariableNamesResponse, GetServicePreviewEnvironmentVariableNamesResponses, GetServicePreviewEnvironmentVariablesMaskedData, GetServicePreviewEnvironmentVariablesMaskedErrors, GetServicePreviewEnvironmentVariablesMaskedResponse, GetServicePreviewEnvironmentVariablesMaskedResponses, GetServiceResponse, GetServiceResponses, GetServiceRuntimeData, GetServiceRuntimeErrors, GetServiceRuntimeResponse, GetServiceRuntimeResponses, GetServiceStatsData, GetServiceStatsErrors, GetServiceStatsResponse, GetServiceStatsResponses, GetServiceTypeParametersData, GetServiceTypeParametersErrors, GetServiceTypeParametersResponses, GetServiceTypesData, GetServiceTypesErrors, GetServiceTypesResponse, GetServiceTypesResponses, GetSessionDetailsData, GetSessionDetailsErrors, GetSessionDetailsResponse, GetSessionDetailsResponses, GetSessionEventsData, GetSessionEventsErrors, GetSessionEventsResponse, GetSessionEventsResponses, GetSessionLogsData, GetSessionLogsErrors, GetSessionLogsResponse, GetSessionLogsResponses, GetSessionReplayData, GetSessionReplayError, GetSessionReplayErrors, GetSessionReplayEventsData, GetSessionReplayEventsError, GetSessionReplayEventsErrors, GetSessionReplayEventsResponse, GetSessionReplayEventsResponses, GetSessionReplayResponse, GetSessionReplayResponse2, GetSessionReplayResponses, GetSettingsData, GetSettingsErrors, GetSettingsResponse, GetSettingsResponses, GetSkillData, GetSkillErrors, GetSkillResponse, GetSkillResponses, GetSlowQueriesData, GetSlowQueriesErrors, GetSlowQueriesResponse, GetSlowQueriesResponses, GetStaticBundleData, GetStaticBundleErrors, GetStaticBundleResponse, GetStaticBundleResponses, GetStatusOverviewData, GetStatusOverviewErrors, GetStatusOverviewResponse, GetStatusOverviewResponses, GetTagsByRepositoryIdData, GetTagsByRepositoryIdErrors, GetTagsByRepositoryIdResponse, GetTagsByRepositoryIdResponses, GetTeamData, GetTeamErrors, GetTeamResponse, GetTeamResponses, GetTimeBucketStatsData, GetTimeBucketStatsError, GetTimeBucketStatsErrors, GetTimeBucketStatsResponse, GetTimeBucketStatsResponses, GetTodayStatsData, GetTodayStatsError, GetTodayStatsErrors, GetTodayStatsResponse, GetTodayStatsResponses, GetTraceData, GetTraceError, GetTraceErrors, GetTraceResponse, GetTraceResponses, GetUnifiedTraceData, GetUnifiedTraceError, GetUnifiedTraceErrors, GetUnifiedTraceResponse, GetUnifiedTraceResponses, GetUniqueCountsData, GetUniqueCountsErrors, GetUniqueCountsResponse, GetUniqueCountsResponses, GetUniqueEventsData, GetUniqueEventsErrors, GetUniqueEventsQuery, GetUniqueEventsResponse, GetUniqueEventsResponses, GetUpdateStatusData, GetUpdateStatusErrors, GetUpdateStatusResponse, GetUpdateStatusResponses, GetUptimeHistoryData, GetUptimeHistoryErrors, GetUptimeHistoryResponse, GetUptimeHistoryResponses, GetUsageByProviderData, GetUsageByProviderError, GetUsageByProviderErrors, GetUsageByProviderResponse, GetUsageByProviderResponses, GetUsageRecentData, GetUsageRecentError, GetUsageRecentErrors, GetUsageRecentResponse, GetUsageRecentResponses, GetUsageSummaryData, GetUsageSummaryError, GetUsageSummaryErrors, GetUsageSummaryResponse, GetUsageSummaryResponses, GetUsageTimeseriesData, GetUsageTimeseriesError, GetUsageTimeseriesErrors, GetUsageTimeseriesResponse, GetUsageTimeseriesResponses, GetUsageTopModelsData, GetUsageTopModelsError, GetUsageTopModelsErrors, GetUsageTopModelsResponse, GetUsageTopModelsResponses, GetVisitorByGuidData, GetVisitorByGuidErrors, GetVisitorByGuidResponse, GetVisitorByGuidResponses, GetVisitorByIdData, GetVisitorByIdErrors, GetVisitorByIdResponse, GetVisitorByIdResponses, GetVisitorDetailsData, GetVisitorDetailsErrors, GetVisitorDetailsResponse, GetVisitorDetailsResponses, GetVisitorFacetsData, GetVisitorFacetsErrors, GetVisitorFacetsResponse, GetVisitorFacetsResponses, GetVisitorInfoData, GetVisitorInfoErrors, GetVisitorInfoResponse, GetVisitorInfoResponses, GetVisitorJourneyData, GetVisitorJourneyErrors, GetVisitorJourneyResponse, GetVisitorJourneyResponses, GetVisitorsData, GetVisitorsErrors, GetVisitorSessionsData, GetVisitorSessionsError, GetVisitorSessionsErrors, GetVisitorSessionsQuery, GetVisitorSessionsResponse, GetVisitorSessionsResponse2, GetVisitorSessionsResponses, GetVisitorsResponse, GetVisitorsResponses, GetVisitorStatsData, GetVisitorStatsErrors, GetVisitorStatsResponse, GetVisitorStatsResponses, GetWebhookData, GetWebhookErrors, GetWebhookResponse, GetWebhookResponses, GitPushEvent, GitRefResponse, GitSourcePlan, GlobalConversationResponse, GlobalEventStatsResponse, GlobalMrrResponse, GlobalRecentEventResponse, GlobalRevenueSummaryResponse, GrantProjectAccessData, GrantProjectAccessErrors, GrantProjectAccessResponse, GrantProjectAccessResponses, GroupedPageMetric, GroupedPageMetricsQuery, GroupedPageMetricsResponse, HandleGitProviderOauthCallbackData, HandleGitProviderOauthCallbackErrors, HasAnalyticsEventsData, HasAnalyticsEventsErrors, HasAnalyticsEventsResponse, HasAnalyticsEventsResponse2, HasAnalyticsEventsResponses, HasErrorGroupsData, HasErrorGroupsErrors, HasErrorGroupsResponse, HasErrorGroupsResponse2, HasErrorGroupsResponses, HasEventsQuery, HasEventsResponse, HasMetricsQuery, HasMetricsResponse, HasPerformanceMetricsData, HasPerformanceMetricsError, HasPerformanceMetricsErrors, HasPerformanceMetricsResponse, HasPerformanceMetricsResponses, HealthCheckConfiguration, HealthCheckEntryResponse, HealthResponse, HealthStatus, HealthSummary, HeartbeatApiRequest, HeartbeatResponse, HierarchyLevel, HistogramSummary, HostnameChange, HostnamePreviewResponse, HourlyPageSessions, HourlyVisitsQuery, HttpChallengeDebugResponse, ImportCredentials, ImportExecutionStatus, ImportExternalServiceData, ImportExternalServiceErrors, ImportExternalServiceRequest, ImportExternalServiceResponse, ImportExternalServiceResponses, ImportOutcomeResponse, ImportPlan, ImportRowErrorResponse, ImportSelector, ImportSource, ImportSourceCapabilities, ImportSourceInfo, ImportStatusResponse, IncidentBucket, IncidentBucketedResponse, IncidentResponse, IncidentUpdateResponse, IncrRequest, IncrResponse, IngestLogsByPathData, IngestLogsByPathError, IngestLogsByPathErrors, IngestLogsByPathResponses, IngestLogsData, IngestLogsError, IngestLogsErrors, IngestLogsResponses, IngestMetricsByPathData, IngestMetricsByPathError, IngestMetricsByPathErrors, IngestMetricsByPathResponses, IngestMetricsData, IngestMetricsError, IngestMetricsErrors, IngestMetricsResponses, IngestSentryEnvelopeData, IngestSentryEnvelopeErrors, IngestSentryEnvelopeResponses, IngestSentryEventData, IngestSentryEventErrors, IngestSentryEventResponse, IngestSentryEventResponses, IngestTracesByPathData, IngestTracesByPathError, IngestTracesByPathErrors, IngestTracesByPathResponses, IngestTracesData, IngestTracesError, IngestTracesErrors, IngestTracesResponses, InitAuthResponse, InitSessionReplayData, InitSessionReplayError, InitSessionReplayErrors, InitSessionReplayResponse, InitSessionReplayResponses, Insight, InsightSeverity, InsightsResponse, InsightStatus, InspectDropArchiveData, InspectDropArchiveErrors, InspectDropArchiveResponse, InspectDropArchiveResponses, IntegrationResponse, IpAccessControlQuery, IpAccessControlResponse, JobLogsData, JobLogsErrors, JobLogsResponses, JobStatusData, JobStatusErrors, JobStatusResponse, JobStatusResponse2, JobStatusResponses, JobSummaryResponse, JoinTokenStatusResponse, JourneyEvent, JourneySession, KeysRequest, KeysResponse, KillJobBody, KillJobData, KillJobErrors, KillJobResponse, KillJobResponses, KnownAiAgentsResponse, KvDelData, KvDelErrors, KvDelResponse, KvDelResponses, KvDisableData, KvDisableErrors, KvDisableResponse, KvDisableResponses, KvEnableData, KvEnableErrors, KvEnableResponse, KvEnableResponses, KvExpireData, KvExpireErrors, KvExpireResponse, KvExpireResponses, KvGetData, KvGetErrors, KvGetResponse, KvGetResponses, KvIncrData, KvIncrErrors, KvIncrResponse, KvIncrResponses, KvKeysData, KvKeysErrors, KvKeysResponse, KvKeysResponses, KvSetData, KvSetErrors, KvSetResponse, KvSetResponses, KvStatusData, KvStatusErrors, KvStatusResponse, KvStatusResponse2, KvStatusResponses, KvTtlData, KvTtlErrors, KvTtlResponse, KvTtlResponses, KvUpdateData, KvUpdateErrors, KvUpdateResponse, KvUpdateResponses, LatestRunForSourceData, LatestRunForSourceErrors, LatestRunForSourceResponse, LatestRunForSourceResponses, LemonSqueezyConfig, LetsEncryptSettings, LineContext, LinkCustomDomainToCertificateData, LinkCustomDomainToCertificateErrors, LinkCustomDomainToCertificateResponse, LinkCustomDomainToCertificateResponses, LinkServiceRequest, LinkServiceToProjectData, LinkServiceToProjectErrors, LinkServiceToProjectResponse, LinkServiceToProjectResponses, ListAgentRunsData, ListAgentRunsErrors, ListAgentRunsResponse, ListAgentRunsResponses, ListAgentsData, ListAgentsErrors, ListAgentsResponse, ListAgentsResponse2, ListAgentsResponses, ListAiProvidersData, ListAiProvidersErrors, ListAiProvidersResponse, ListAiProvidersResponses, ListAlertRulesData, ListAlertRulesErrors, ListAlertRulesResponse, ListAlertRulesResponses, ListAlertsData, ListAlertsError, ListAlertsErrors, ListAlertsResponse, ListAlertsResponses, ListAllConversationsData, ListAllConversationsErrors, ListAllConversationsResponse, ListAllConversationsResponses, ListAllRunsData, ListAllRunsErrors, ListAllRunsResponse, ListAllRunsResponses, ListApiKeysData, ListApiKeysErrors, ListApiKeysQuery, ListApiKeysResponse, ListApiKeysResponses, ListAuditLogsData, ListAuditLogsErrors, ListAuditLogsQuery, ListAuditLogsResponse, ListAuditLogsResponses, ListAvailableContainersData, ListAvailableContainersErrors, ListAvailableContainersResponse, ListAvailableContainersResponses, ListBackupAlertsData, ListBackupAlertsError, ListBackupAlertsErrors, ListBackupAlertsResponse, ListBackupAlertsResponses, ListBackupChildrenData, ListBackupChildrenError, ListBackupChildrenErrors, ListBackupChildrenResponse, ListBackupChildrenResponses, ListBackupSchedulesData, ListBackupSchedulesError, ListBackupSchedulesErrors, ListBackupSchedulesResponse, ListBackupSchedulesResponses, ListBackupsForScheduleData, ListBackupsForScheduleErrors, ListBackupsForScheduleResponse, ListBackupsForScheduleResponses, ListBlobsQuery, ListBlobsResponse, ListCommitsByRepositoryIdData, ListCommitsByRepositoryIdErrors, ListCommitsByRepositoryIdResponse, ListCommitsByRepositoryIdResponses, ListConnectionsData, ListConnectionsErrors, ListConnectionsResponse, ListConnectionsResponses, ListContainersAtPathData, ListContainersAtPathErrors, ListContainersAtPathResponse, ListContainersAtPathResponses, ListContainersData, ListContainersErrors, ListContainersResponse, ListContainersResponses, ListConversationsData, ListConversationsErrors, ListConversationsResponse, ListConversationsResponses, ListCustomDomainsForProjectData, ListCustomDomainsForProjectErrors, ListCustomDomainsForProjectResponse, ListCustomDomainsForProjectResponses, ListCustomDomainsResponse, ListDashboardsData, ListDashboardsError, ListDashboardsErrors, ListDashboardsResponse, ListDashboardsResponses, ListDeliveriesData, ListDeliveriesErrors, ListDeliveriesResponse, ListDeliveriesResponses, ListDeploymentContainerLogsData, ListDeploymentContainerLogsErrors, ListDeploymentContainerLogsResponse, ListDeploymentContainerLogsResponses, ListDeploymentTokensData, ListDeploymentTokensErrors, ListDeploymentTokensQuery, ListDeploymentTokensResponse, ListDeploymentTokensResponses, ListDnsProvidersData, ListDnsProvidersErrors, ListDnsProvidersResponse, ListDnsProvidersResponses, ListDomainsData, ListDomainsErrors, ListDomainsResponse, ListDomainsResponse2, ListDomainsResponses, ListDsnsData, ListDsnsErrors, ListDsnsResponse, ListDsnsResponses, ListEmailDomainsData, ListEmailDomainsErrors, ListEmailDomainsResponse, ListEmailDomainsResponses, ListEmailProvidersData, ListEmailProvidersErrors, ListEmailProvidersResponse, ListEmailProvidersResponses, ListEmailsData, ListEmailsErrors, ListEmailsResponse, ListEmailsResponses, ListEnrollmentTokensData, ListEnrollmentTokensErrors, ListEnrollmentTokensResponse, ListEnrollmentTokensResponses, ListEntitiesData, ListEntitiesErrors, ListEntitiesQuery, ListEntitiesResponse, ListEntitiesResponses, ListErrorEventsData, ListErrorEventsErrors, ListErrorEventsQuery, ListErrorEventsResponse, ListErrorEventsResponses, ListErrorGroupsData, ListErrorGroupsErrors, ListErrorGroupsQuery, ListErrorGroupsResponse, ListErrorGroupsResponses, ListEventsData, ListEventsResponse, ListEventsResponses, ListEventTypesData, ListEventTypesResponse, ListEventTypesResponses, ListExternalImagesData, ListExternalImagesErrors, ListExternalImagesResponse, ListExternalImagesResponses, ListExternalPluginsData, ListExternalPluginsErrors, ListExternalPluginsResponse, ListExternalPluginsResponses, ListExternalServiceBackupsData, ListExternalServiceBackupsError, ListExternalServiceBackupsErrors, ListExternalServiceBackupsResponse, ListExternalServiceBackupsResponses, ListFlagsData, ListFlagsErrors, ListFlagsResponse, ListFlagsResponses, ListFunnelsData, ListFunnelsErrors, ListFunnelsResponse, ListFunnelsResponses, ListGitProvidersData, ListGitProvidersErrors, ListGitProvidersResponse, ListGitProvidersResponses, ListGlobalMcpsData, ListGlobalMcpsErrors, ListGlobalMcpsResponse, ListGlobalMcpsResponses, ListGlobalSkillsData, ListGlobalSkillsErrors, ListGlobalSkillsResponse, ListGlobalSkillsResponses, ListIncidentsData, ListIncidentsErrors, ListIncidentsResponses, ListInsightsData, ListInsightsError, ListInsightsErrors, ListInsightsResponse, ListInsightsResponses, ListIpAccessControlData, ListIpAccessControlError, ListIpAccessControlErrors, ListIpAccessControlResponse, ListIpAccessControlResponses, ListJobsData, ListJobsErrors, ListJobsResponse, ListJobsResponse2, ListJobsResponses, ListKnownAiAgentsData, ListKnownAiAgentsError, ListKnownAiAgentsErrors, ListKnownAiAgentsResponse, ListKnownAiAgentsResponses, ListManagedDomainsData, ListManagedDomainsErrors, ListManagedDomainsResponse, ListManagedDomainsResponses, ListMcpsData, ListMcpsErrors, ListMcpsResponse, ListMcpsResponse2, ListMcpsResponses, ListMetricLabelKeysData, ListMetricLabelKeysError, ListMetricLabelKeysErrors, ListMetricLabelKeysResponse, ListMetricLabelKeysResponses, ListMetricLabelValuesData, ListMetricLabelValuesError, ListMetricLabelValuesErrors, ListMetricLabelValuesResponse, ListMetricLabelValuesResponses, ListMetricNamesData, ListMetricNamesError, ListMetricNamesErrors, ListMetricNamesResponse, ListMetricNamesResponses, ListModelsData, ListModelsError, ListModelsErrors, ListModelsResponse, ListModelsResponses, ListMonitorsData, ListMonitorsErrors, ListMonitorsResponse, ListMonitorsResponses, ListNotificationProvidersData, ListNotificationProvidersErrors, ListNotificationProvidersResponse, ListNotificationProvidersResponses, ListOidcProvidersData, ListOidcProvidersResponse, ListOidcProvidersResponses, ListOidcProviderUsersData, ListOidcProviderUsersErrors, ListOidcProviderUsersResponse, ListOidcProviderUsersResponses, ListOidcRoleMappingsData, ListOidcRoleMappingsResponse, ListOidcRoleMappingsResponses, ListOnDemandCertsData, ListOnDemandCertsErrors, ListOnDemandCertsResponse, ListOnDemandCertsResponse2, ListOnDemandCertsResponses, ListOrdersData, ListOrdersErrors, ListOrdersResponse, ListOrdersResponse2, ListOrdersResponses, ListPeersData, ListPeersErrors, ListPeersResponse, ListPeersResponses, ListPendingActionsData, ListPendingActionsErrors, ListPendingActionsResponse, ListPendingActionsResponses, ListPgUpgradesData, ListPgUpgradesErrors, ListPgUpgradesResponse, ListPgUpgradesResponses, ListPresetsData, ListPresetsErrors, ListPresetsResponse, ListPresetsResponse2, ListPresetsResponses, ListProjectAccessData, ListProjectAccessErrors, ListProjectAccessResponse, ListProjectAccessResponses, ListProjectAlarmsData, ListProjectAlarmsErrors, ListProjectAlarmsResponse, ListProjectAlarmsResponses, ListProjectScansData, ListProjectScansError, ListProjectScansErrors, ListProjectScansResponse, ListProjectScansResponses, ListProjectSecretsData, ListProjectSecretsErrors, ListProjectSecretsResponse, ListProjectSecretsResponses, ListProjectServicesData, ListProjectServicesErrors, ListProjectServicesResponse, ListProjectServicesResponses, ListProjectTemplatesData, ListProjectTemplatesErrors, ListProjectTemplatesResponse, ListProjectTemplatesResponses, ListProjectTemplateTagsData, ListProjectTemplateTagsErrors, ListProjectTemplateTagsResponse, ListProjectTemplateTagsResponses, ListProviderKeysData, ListProviderKeysError, ListProviderKeysErrors, ListProviderKeysResponse, ListProviderKeysResponses, ListProviderZonesData, ListProviderZonesErrors, ListProviderZonesResponse, ListProviderZonesResponses, ListPublicProvidersData, ListPublicProvidersResponse, ListPublicProvidersResponses, ListReleaseFilesData, ListReleaseFilesErrors, ListReleaseFilesResponse, ListReleaseFilesResponses, ListReleasesData, ListReleasesErrors, ListReleasesResponse, ListReleasesResponses, ListRemoteExternalImagesData, ListRemoteExternalImagesErrors, ListRemoteExternalImagesResponse, ListRemoteExternalImagesResponses, ListRepositoriesByConnectionData, ListRepositoriesByConnectionErrors, ListRepositoriesByConnectionResponse, ListRepositoriesByConnectionResponses, ListRepositoriesByProviderData, ListRepositoriesByProviderErrors, ListRepositoriesByProviderResponse, ListRepositoriesByProviderResponses, ListRestoreRunsForServiceData, ListRestoreRunsForServiceResponse, ListRestoreRunsForServiceResponses, ListRootContainersData, ListRootContainersErrors, ListRootContainersResponse, ListRootContainersResponses, ListRoutesData, ListRoutesErrors, ListRoutesResponse, ListRoutesResponses, ListRunsResponse, ListS3SourcesData, ListS3SourcesError, ListS3SourcesErrors, ListS3SourcesResponse, ListS3SourcesResponses, ListSandboxesData, ListSandboxesResponse, ListSandboxesResponse2, ListSandboxesResponses, ListScansQuery, ListScheduleRunJobsData, ListScheduleRunJobsError, ListScheduleRunJobsErrors, ListScheduleRunJobsResponse, ListScheduleRunJobsResponses, ListScheduleRunsData, ListScheduleRunsError, ListScheduleRunsErrors, ListScheduleRunsResponse, ListScheduleRunsResponses, ListScheduleServicesData, ListScheduleServicesError, ListScheduleServicesErrors, ListScheduleServicesResponse, ListScheduleServicesResponses, ListSecretsData, ListSecretsErrors, ListSecretsResponse, ListSecretsResponse2, ListSecretsResponses, ListServiceHealthStatusesData, ListServiceHealthStatusesErrors, ListServiceHealthStatusesResponse, ListServiceHealthStatusesResponses, ListServiceProjectsData, ListServiceProjectsErrors, ListServiceProjectsResponse, ListServiceProjectsResponses, ListServiceSchedulesData, ListServiceSchedulesError, ListServiceSchedulesErrors, ListServiceSchedulesResponse, ListServiceSchedulesResponses, ListServicesData, ListServicesErrors, ListServicesResponse, ListServicesResponses, ListSkillsData, ListSkillsErrors, ListSkillsResponse, ListSkillsResponse2, ListSkillsResponses, ListSourceBackupsData, ListSourceBackupsError, ListSourceBackupsErrors, ListSourceBackupsResponse, ListSourceBackupsResponses, ListSourceFilesData, ListSourceFilesErrors, ListSourceFilesResponse, ListSourceFilesResponses, ListSourceMapsData, ListSourceMapsErrors, ListSourceMapsResponse, ListSourceMapsResponses, ListSourcesData, ListSourcesErrors, ListSourcesResponse, ListSourcesResponses, ListStaticBundlesData, ListStaticBundlesErrors, ListStaticBundlesResponse, ListStaticBundlesResponses, ListSyncedRepositoriesData, ListSyncedRepositoriesErrors, ListSyncedRepositoriesResponse, ListSyncedRepositoriesResponses, ListTagsResponse, ListTeamMembersData, ListTeamMembersErrors, ListTeamMembersResponse, ListTeamMembersResponses, ListTeamProjectsData, ListTeamProjectsErrors, ListTeamProjectsResponse, ListTeamProjectsResponses, ListTeamsData, ListTeamsErrors, ListTeamsResponse, ListTeamsResponses, ListTemplatesQuery, ListTemplatesResponse, ListUsersData, ListUsersErrors, ListUsersResponse, ListUsersResponses, ListVulnerabilitiesQuery, ListWebhooksData, ListWebhooksErrors, ListWebhooksResponse, ListWebhooksResponses, LiveVisitorInfo, LiveVisitorsListResponse, LocationCount, LocationGranularity, LocationInfo, LoginData, LoginErrors, LoginRequest, LoginResponse, LoginResponses, LogLevel, LogoutData, LogoutErrors, LogoutResponses, LogRecord, LogSearchLine, LogSeverity, LogSource, LogsQuery, LogsResponse, LogStream, LookupDnsARecordsData, LookupDnsARecordsError, LookupDnsARecordsErrors, LookupDnsARecordsResponse, LookupDnsARecordsResponses, ManagedDomainResponse, ManualAction, ManualActionTiming, McpDefinitionResponse, MessageContent, MessagePart, MessageResponse, MeteredMode, MetricAggregation, MetricBucket, MetricDataPoint, MetricsOverTimeResponse, MetricsQuery, MetricsRangeQuery, MetricsStatusResponse, MetricsStoreKind, MetricsSummaryResponse, MetricType, MfaRequiredResponse, MfaSetupResponse, MfaVerificationRequest, MigrationStep, MigrationSummary, MintEnrollmentTokenData, MintEnrollmentTokenErrors, MintEnrollmentTokenRequest, MintEnrollmentTokenResponse, MintEnrollmentTokenResponse2, MintEnrollmentTokenResponses, MiscResult, MkdirBody, MkdirData, MkdirErrors, MkdirResponse, MkdirResponses, ModelInfo, ModelListResponse, ModelPricing, ModelUsage, MonitoringSettings, MonitoringSettingsMasked, MonitorResponse, MonitorStatus, MrrBucketResponse, MultiNodeSettings, MultiNodeSettingsMasked, MxResult, NavEntry, NavSection, NetworkConfiguration, NetworkMode, NixpacksPresetConfig, NixpacksProvider, NodeContainerListResponse, NodeContainerResponse, NodeCostInfo, NodeHeartbeatData, NodeHeartbeatErrors, NodeHeartbeatResponse, NodeHeartbeatResponses, NodeInfoResponse, NodeListResponse, NodeMetricsGetRangeData, NodeMetricsGetRangeErrors, NodeMetricsGetRangeResponse, NodeMetricsGetRangeResponses, NotificationPreferencesResponse, NotificationProviderResponse, ObservabilityCompressionSettings, ObservabilityEvent, ObservabilityFullEventData, ObservabilityFullEventError, ObservabilityFullEventErrors, ObservabilityFullEventResponse, ObservabilityFullEventResponses, ObservabilityListEventsData, ObservabilityListEventsError, ObservabilityListEventsErrors, ObservabilityListEventsResponse, ObservabilityListEventsResponses, ObservabilityRetentionSettings, OidcCallbackData, OidcProviderResponse, OidcProvidersListResponse, OidcProviderSummary, OidcProviderUserResponse, OidcRoleMappingResponse, OidcTestConnectionResponse, OnDemandCertAttemptResponse, OnDemandCertRow, OnDemandTlsSettings, OpenAiError, OpenAiErrorResponse, OperatingSystemCount, OperationResultResponse, OperationResultsResponse, OtelDashboardResponse, OtelDashboardsResponse, OtelMetricAlertRuleResponse, OtelMetricAlertsResponse, OtelMetricLabelKeysResponse, OtelMetricLabelValuesResponse, OtelMetricNamesResponse, OtelMetricsResponse, OutlierAlgorithm, OutlierParams, OverprovisioningAssessment, OverprovisioningVerdict, PageActivityBucket, PageCountryStats, PageFlowEntry, PageFlowQuery, PageFlowResponse, PageHourlySessionsQuery, PageHourlySessionsResponse, PagePathDetailQuery, PagePathDetailResponse, PagePathInfo, PagePathSparkline, PagePathSparklinePoint, PagePathsQuery, PagePathsResponse, PagePathsSparklineQuery, PagePathsSparklineResponse, PagePathVisitorsQuery, PagePathVisitorsResponse, PageReferrerStats, PagesComparisonResponse, PageSessionComparison, PageSessionStats, PageSessionStatsQuery, PageTransition, PageVisit, PageVisitorSession, PaginatedEmailsResponse, PaginatedEntitiesResponse, PaginatedErrorEventsResponse, PaginatedErrorGroupsResponse, PaginatedEventsResponse, PaginatedExternalImagesResponse, PaginatedProjectList, PaginatedStaticBundlesResponse, Pagination, PaginationMeta, PaginationParams, PasswordProtectionConfig, PatchAdminGateData, PatchAdminGateErrors, PatchAdminGateResponse, PatchAdminGateResponses, PatchPreviewGatewaySettingsData, PatchPreviewGatewaySettingsResponse, PatchPreviewGatewaySettingsResponses, PatchSettingsRequest, PathVisitors, PathVisitorsAnalyticsQuery, PathVisitorsResponse, PauseDeploymentData, PauseDeploymentErrors, PauseDeploymentResponse, PauseDeploymentResponses, PauseSandboxData, PauseSandboxErrors, PauseSandboxResponse, PauseSandboxResponses, PeerEntry, PeerListResponse, PendingActionResponse, PerformanceMetricsQuery, PerformanceMetricsResponse, PermissionInfo, PgUpgradeLogResponse, PgUpgradeResponse, PipelineStats, PipelineStatsResponse, PlanComplexity, PlanMetadata, PlanRestoreData, PlanRestoreError, PlanRestoreErrors, PlanRestoreResponse, PlanRestoreResponses, PlanSourceBackup, PlanTarget, PlatformInfo, PluginManifest, PortMapping, PostDnsAckData, PostDnsAckErrors, PostDnsAckResponse, PostDnsAckResponses, PostgresWalHealth, PresetConfigSchema, PresetInfo, PresetResponse, PreviewAlertData, PreviewAlertError, PreviewAlertErrors, PreviewAlertResponse, PreviewAlertResponses, PreviewFunnelMetricsData, PreviewFunnelMetricsErrors, PreviewFunnelMetricsResponse, PreviewFunnelMetricsResponses, PreviewGatewaySettings, PreviewGatewaySettingsMasked, PreviewGatewaySettingsResponse, PreviewHostnameModeData, PreviewHostnameModeErrors, PreviewHostnameModeResponse, PreviewHostnameModeResponses, PreviewShareLinkBody, PreviewShareLinkResponse, PricingResponse, ProblemDetails, ProjectAccessResponse, ProjectConfiguration, ProjectDashboardAnalytics, ProjectDsnResponse, ProjectHealthSummary, ProjectInfo, ProjectMonitorHealth, ProjectPresetResponse, ProjectQuery, ProjectRef, ProjectResponse, ProjectSecretEnvironmentInfo, ProjectSecretResponse, ProjectServiceInfo, ProjectsHealthResponse, ProjectsMonitorHealthResponse, ProjectStatisticsResponse, ProjectStatsBreakdown, ProjectType, ProjectUsageInfoResponse, PromoteClusterMemberData, PromoteClusterMemberErrors, PromoteClusterMemberResponses, PromoteDeploymentData, PromoteDeploymentErrors, PromoteDeploymentRequest, PromoteDeploymentResponse, PromoteDeploymentResponses, PropertyBreakdownItem, PropertyBreakdownQuery, PropertyBreakdownResponse, PropertyColumn, PropertyTimelineItem, PropertyTimelineQuery, PropertyTimelineResponse, Protocol, ProviderCatalogDto, ProviderCatalogResponse, ProviderConfig, ProviderConfigMasked, ProviderDeletionCheckResponse, ProviderDescriptor, ProviderKeyResponse, ProviderMetadata, ProviderResponse, ProviderUsage, ProvisionDomainData, ProvisionDomainErrors, ProvisionDomainResponse, ProvisionDomainResponses, ProvisionResponse, ProxyLogResponse, ProxyLogsPaginatedResponse, PublicHostnameStrategy, PublicPresetResponse, PublicRepositoryInfo, PurgeLogsRequest, PurgeProjectLogsData, PurgeProjectLogsError, PurgeProjectLogsErrors, PurgeProjectLogsResponses, PushedExternalImageResponse, PushExternalImageData, PushExternalImageErrors, PushExternalImageResponse, PushExternalImageResponses, PushImageRequest, QueryDataData, QueryDataErrors, QueryDataRequest, QueryDataResponse, QueryDataResponse2, QueryDataResponses, QueryGenaiTracesData, QueryGenaiTracesError, QueryGenaiTracesErrors, QueryGenaiTracesResponse, QueryGenaiTracesResponses, QueryLogsData, QueryLogsError, QueryLogsErrors, QueryLogsResponse, QueryLogsResponses, QueryMetricsData, QueryMetricsError, QueryMetricsErrors, QueryMetricsResponse, QueryMetricsResponses, QueryTracesData, QueryTracesError, QueryTracesErrors, QueryTracesResponse, QueryTracesResponses, QueryTraceSummariesData, QueryTraceSummariesError, QueryTraceSummariesErrors, QueryTraceSummariesResponse, QueryTraceSummariesResponses, QuotaResponse, RateLimitConfig, RateLimitSettings, ReachabilityStatus, ReadFileData, ReadFileErrors, ReadFileResponse, ReadFileResponse2, ReadFileResponses, ReAnalyzeData, ReAnalyzeErrors, ReAnalyzeResponses, RecentActivityQuery, RecentActivityResponse, RecentEventResponse, RecentQueryParams, RecordConsoleEventData, RecordConsoleEventErrors, RecordConsoleEventResponses, RecordEventMetricsData, RecordEventMetricsErrors, RecordEventMetricsResponse, RecordEventMetricsResponses, RecordExposureRequest, RecordExposureResponse, RecordFlagExposureData, RecordFlagExposureErrors, RecordFlagExposureResponse, RecordFlagExposureResponses, RecordListResponse, RecordSpeedMetricsData, RecordSpeedMetricsError, RecordSpeedMetricsErrors, RecordSpeedMetricsResponse, RecordSpeedMetricsResponses, RecoveryTarget, ReferrerCount, ReferrersAnalyticsQuery, RefreshRouteTableData, RefreshRouteTableErrors, RefreshRouteTableResponse, RefreshRouteTableResponses, RegenerateDsnData, RegenerateDsnErrors, RegenerateDsnRequest, RegenerateDsnResponse, RegenerateDsnResponses, RegisterExternalImageData, RegisterExternalImageErrors, RegisterExternalImageResponse, RegisterExternalImageResponses, RegisterImageRequest, RegisterNodeApiRequest, RegisterNodeData, RegisterNodeErrors, RegisterNodeResponse, RegisterNodeResponse2, RegisterNodeResponses, RegisterRequest, ReinstallGitlabWebhookData, ReinstallGitlabWebhookErrors, ReinstallGitlabWebhookResponse, ReinstallGitlabWebhookResponses, ReinstallWebhookResponse, RejectPendingActionData, RejectPendingActionErrors, RejectPendingActionResponse, RejectPendingActionResponses, ReleaseListResponse, ReloadPluginsData, ReloadPluginsErrors, ReloadPluginsResponse, ReloadPluginsResponses, ReloadResponse, RemoteDeploymentResponse, RemoveClusterMemberData, RemoveClusterMemberErrors, RemoveClusterMemberResponse, RemoveClusterMemberResponses, RemoveManagedDomainData, RemoveManagedDomainErrors, RemoveManagedDomainResponse, RemoveManagedDomainResponses, RemoveNodeResponse, RemoveRoleData, RemoveRoleErrors, RemoveRoleResponse, RemoveRoleResponses, RemoveTeamMemberData, RemoveTeamMemberErrors, RemoveTeamMemberResponse, RemoveTeamMemberResponses, RenameConversationData, RenameConversationErrors, RenameConversationRequest, RenameConversationResponse, RenameConversationResponses, RenewDomainData, RenewDomainErrors, RenewDomainResponse, RenewDomainResponses, RepositoryListQuery, RepositoryListResponse, RepositoryPresetResponse, RepositoryResponse, RepositorySyncStartedResponse, RequestPasswordResetData, RequestPasswordResetErrors, RequestPasswordResetResponse, RequestPasswordResetResponses, RequestRow, ResetPasswordData, ResetPasswordErrors, ResetPasswordRequest, ResetPasswordResponse, ResetPasswordResponses, ResetPgStatStatementsRequest, ResetPgStatStatementsResponse, ResizeSandboxBody, ResizeSandboxData, ResizeSandboxErrors, ResizeSandboxResponse, ResizeSandboxResponses, ResolveAlarmData, ResolveAlarmErrors, ResolveAlarmResponses, ResolvedEnvVarResponse, ResolvedEnvVarSource, ResourceCounts, ResourceFootprint, ResourceInfo, ResourceLimitApplyResult, ResourceLimits, ResourceLimitsResponse, ResourceLimitsUpdateResponse, ResourcesBody, RestartContainerData, RestartContainerErrors, RestartContainerResponse, RestartContainerResponses, RestartPreviewGatewayData, RestartPreviewGatewayResponse, RestartPreviewGatewayResponses, RestartSandboxData, RestartSandboxErrors, RestartSandboxResponse, RestartSandboxResponses, RestoreCapabilities, RestoreCapabilitiesResponse, RestoreFlagData, RestoreFlagErrors, RestoreFlagResponse, RestoreFlagResponses, RestorePlan, RestoreRequestMode, RestoreRunView, RestoreUserData, RestoreUserErrors, RestoreUserResponse, RestoreUserResponses, ResumeDeploymentData, ResumeDeploymentErrors, ResumeDeploymentResponse, ResumeDeploymentResponses, ResumeSandboxData, ResumeSandboxErrors, ResumeSandboxResponse, ResumeSandboxResponses, RetentionCleanupFailure, RetentionCleanupReport, RetryClusterData, RetryClusterErrors, RetryClusterRequest, RetryClusterResponse, RetryClusterResponses, RetryDeliveryData, RetryDeliveryErrors, RetryDeliveryResponse, RetryDeliveryResponses, RetryPgUpgradeData, RetryPgUpgradeErrors, RetryPgUpgradeResponse, RetryPgUpgradeResponses, RetryRunData, RetryRunErrors, RetryRunResponse, RetryRunResponses, RevealGlobalMcpConfigData, RevealGlobalMcpConfigErrors, RevealGlobalMcpConfigResponse, RevealGlobalMcpConfigResponses, RevealMcpConfigData, RevealMcpConfigErrors, RevealMcpConfigResponse, RevealMcpConfigResponses, RevealNotificationProviderConfigData, RevealNotificationProviderConfigErrors, RevealNotificationProviderConfigResponse, RevealNotificationProviderConfigResponses, RevealServiceParameterData, RevealServiceParameterErrors, RevealServiceParameterResponse, RevealServiceParameterResponses, RevenueCreateIntegrationData, RevenueCreateIntegrationErrors, RevenueCreateIntegrationResponse, RevenueCreateIntegrationResponses, RevenueDeleteIntegrationData, RevenueDeleteIntegrationResponse, RevenueDeleteIntegrationResponses, RevenueGlobalEventsData, RevenueGlobalEventsResponse, RevenueGlobalEventsResponses, RevenueImportInvoicesCsvData, RevenueImportInvoicesCsvErrors, RevenueImportInvoicesCsvResponse, RevenueImportInvoicesCsvResponses, RevenueImportSubscriptionsCsvData, RevenueImportSubscriptionsCsvErrors, RevenueImportSubscriptionsCsvResponse, RevenueImportSubscriptionsCsvResponses, RevenueListIntegrationsData, RevenueListIntegrationsResponse, RevenueListIntegrationsResponses, RevenueListProvidersData, RevenueListProvidersResponse, RevenueListProvidersResponses, RevenueMetricsCustomersData, RevenueMetricsCustomersResponse, RevenueMetricsCustomersResponses, RevenueMetricsGlobalMrrData, RevenueMetricsGlobalMrrResponse, RevenueMetricsGlobalMrrResponses, RevenueMetricsGlobalSummaryData, RevenueMetricsGlobalSummaryResponse, RevenueMetricsGlobalSummaryResponses, RevenueMetricsMrrData, RevenueMetricsMrrResponse, RevenueMetricsMrrResponses, RevenueMetricsSummaryData, RevenueMetricsSummaryResponse, RevenueMetricsSummaryResponses, RevenueRecentEventsData, RevenueRecentEventsResponse, RevenueRecentEventsResponses, RevenueRotateTokenData, RevenueRotateTokenResponse, RevenueRotateTokenResponses, RevenueRow, RevenueUpdateConfigData, RevenueUpdateConfigErrors, RevenueUpdateConfigResponse, RevenueUpdateConfigResponses, RevenueUpdateSecretData, RevenueUpdateSecretErrors, RevenueUpdateSecretResponse, RevenueUpdateSecretResponses, RevokeDsnData, RevokeDsnErrors, RevokeDsnResponse, RevokeDsnResponses, RevokeEnrollmentTokenData, RevokeEnrollmentTokenErrors, RevokeEnrollmentTokenResponse, RevokeEnrollmentTokenResponses, RevokeJoinTokenData, RevokeJoinTokenErrors, RevokeJoinTokenResponse, RevokeJoinTokenResponses, RevokeProjectAccessData, RevokeProjectAccessErrors, RevokeProjectAccessResponse, RevokeProjectAccessResponses, RiskLevel, RoleInfo, RollbackPgUpgradeData, RollbackPgUpgradeErrors, RollbackPgUpgradeResponse, RollbackPgUpgradeResponses, RollbackToDeploymentData, RollbackToDeploymentErrors, RollbackToDeploymentResponse, RollbackToDeploymentResponses, RootfsCacheEntry, RootfsGcData, RootfsGcReport, RootfsGcResponses, RootfsReport, RootfsReportData, RootfsReportResponses, RootfsVmEntry, RotateApiKeyData, RotateApiKeyErrors, RotateApiKeyResponse, RotateApiKeyResponses, RotateDeploymentTokenData, RotateDeploymentTokenErrors, RotateDeploymentTokenResponse, RotateDeploymentTokenResponses, RouteRefreshResponse, RouteResponse, RouteRole, RouteUser, RouteUserWithRoles, RunBackupForSourceData, RunBackupForSourceError, RunBackupForSourceErrors, RunBackupForSourceResponse, RunBackupForSourceResponses, RunBackupRequest, RunConnectionHealthCheckData, RunConnectionHealthCheckErrors, RunConnectionHealthCheckResponse, RunConnectionHealthCheckResponses, RunExternalServiceBackupData, RunExternalServiceBackupError, RunExternalServiceBackupErrors, RunExternalServiceBackupRequest, RunExternalServiceBackupResponse, RunExternalServiceBackupResponses, RunScheduleNowData, RunScheduleNowError, RunScheduleNowErrors, RunScheduleNowResponse, RunScheduleNowResponses, S3ConnectionTestResponse, S3CredentialsResponse, S3SourceResponse, S3SourceResponseWritable, SandboxCreatePreviewLinkData, SandboxCreatePreviewLinkErrors, SandboxCreatePreviewLinkResponse, SandboxCreatePreviewLinkResponses, SandboxDomainResponse, SandboxEvent, SandboxEventsResponse, SandboxInner, SandboxResponse, SandboxRoute, SandboxStatusResponse, SaveAgentTokenData, SaveAgentTokenErrors, SaveAgentTokenRequest, SaveAgentTokenResponse, SaveAgentTokenResponse2, SaveAgentTokenResponses, SaveAiProviderCredentialData, SaveAiProviderCredentialErrors, SaveAiProviderCredentialResponse, SaveAiProviderCredentialResponses, SaveCredentialRequest, SaveCredentialResponse, ScalewayCredentialsRequest, ScanResponse, ScheduleRunEntry, ScheduleRunJobEntry, ScheduleRunListResponse, ScheduleRunResponse, ScheduleRunSummary, ScheduleRunSummaryList, ScreenshotSettings, SearchLogsData, SearchLogsError, SearchLogsErrors, SearchLogsRequest, SearchLogsResponse, SearchLogsResponse2, SearchLogsResponses, SearchMode, Seasonality, SecretResponse, SecurityConfig, SecurityHeadersConfig, SecurityHeadersSettings, SendEmailData, SendEmailErrors, SendEmailRequestBody, SendEmailResponse, SendEmailResponseBody, SendEmailResponses, SendMessageRequest, SensitiveConfigValueResponse, SensitiveMcpConfigValueResponse, SensitiveValueResponse, SentryChunkUploadResponse, SentryCreateReleaseRequest, SentryEventRequest, SentryEventResponse, SentryReleaseFileResponse, SentryReleaseProjectRef, SentryReleaseResponse, SeriesStateEntry, ServiceAccessInfo, ServiceAction, ServiceAlertRuleResponse, ServiceBackupEntryResponse, ServiceBackupListResponse, ServiceCreateAlertRuleRequest, ServiceHealthResponse, ServiceHealthStatusBatchResponse, ServiceHealthStatusEntryResponse, ServiceMemberInfo, ServiceParameter, ServicePlan, ServiceResourceLimits, ServiceRuntimeReport, ServiceStatsReport, ServiceTypeInfo, ServiceTypeRoute, ServiceUpdateAlertRuleRequest, SesCredentialsRequest, SessionDetails, SessionDetailsQuery, SessionEvent, SessionEventDto, SessionEventsQuery, SessionEventsResponse, SessionLogsQuery, SessionLogsResponse, SessionReplayEventsRequest, SessionReplayInfoDto, SessionReplayInitRequest, SessionReplayInitResponse, SessionReplayWithEventsDto, SessionReplayWithVisitorDto, SessionRequestLog, SessionSummary, SetDefaultS3SourceData, SetDefaultS3SourceError, SetDefaultS3SourceErrors, SetDefaultS3SourceResponse, SetDefaultS3SourceResponses, SetFlagEnvironmentData, SetFlagEnvironmentErrors, SetFlagEnvironmentRequest, SetFlagEnvironmentResponse, SetFlagEnvironmentResponses, SetPreviewPasswordBody, SetPreviewPasswordData, SetPreviewPasswordErrors, SetPreviewPasswordResponse, SetPreviewPasswordResponse2, SetPreviewPasswordResponses, SetRequest, SetResponse, SettingsUpdateResponse, SetupDnsChallengeData, SetupDnsChallengeErrors, SetupDnsChallengeRequest, SetupDnsChallengeResponse, SetupDnsChallengeResponse2, SetupDnsChallengeResponses, SetupDnsData, SetupDnsErrors, SetupDnsRequest, SetupDnsResponse, SetupDnsResponse2, SetupDnsResponses, SetupEmailTrackingData, SetupEmailTrackingErrors, SetupEmailTrackingResponse, SetupEmailTrackingResponses, SetupMfaData, SetupMfaErrors, SetupMfaResponse, SetupMfaResponses, SiblingRef, SkillDefinitionResponse, SlackConfig, SleepEnvironmentData, SleepEnvironmentErrors, SleepEnvironmentResponse, SleepEnvironmentResponses, SlowQueriesResponse, SlowQueryRow, SmartFilter, SmokeTestAgentData, SmokeTestAgentErrors, SmokeTestAgentResponse, SmokeTestAgentResponses, SmokeTestResponse, SmtpCredentialsRequest, SmtpEncryptionRoute, SmtpResult, SourceArchiveUpload, SourceBackupEntry, SourceBackupIndexResponse, SourceBody, SourceFileListResponse, SourceFileResponse, SourceMapListResponse, SourceMapResponse, SourceSandboxData, SourceSandboxErrors, SourceSandboxResponse, SourceSandboxResponses, SourceType, SpanEvent, SpanKind, SpanRecord, SpanRow, SpanStatusCode, SpeedMetricsPayload, SpeedSegmentFilters, StaleSlot, StartAnalysisData, StartAnalysisErrors, StartAnalysisRequest, StartAnalysisResponse, StartAnalysisResponses, StartContainerData, StartContainerErrors, StartContainerResponse, StartContainerResponses, StartFixData, StartFixErrors, StartFixResponses, StartGitProviderOauthData, StartGitProviderOauthErrors, StartOidcLoginBySlugData, StartOidcLoginBySlugErrors, StartPgUpgradeData, StartPgUpgradeErrors, StartPgUpgradeRequest, StartPgUpgradeResponse, StartPgUpgradeResponses, StartRestoreData, StartRestoreError, StartRestoreErrors, StartRestoreRequest, StartRestoreResponse, StartRestoreResponses, StartServiceData, StartServiceErrors, StartServiceResponse, StartServiceResponses, StaticBundleResponse, StaticParams, StaticPresetConfig, StatPathData, StatPathErrors, StatPathResponse, StatPathResponses, StatResponse, StatsFilters, StatusBucket, StatusBucketedResponse, StatusCodeCount, StatusCodesQuery, StatusPageOverview, StepConversionResponse, StepResourceType, StepResult, StepUpResponse, StopContainerData, StopContainerErrors, StopContainerResponse, StopContainerResponses, StopSandboxData, StopSandboxErrors, StopSandboxResponse, StopSandboxResponses, StopSequence, StopServiceData, StopServiceErrors, StopServiceResponse, StopServiceResponses, StorageQuota, StreamContainerMetricsData, StreamContainerMetricsErrors, StreamContainerMetricsResponses, StreamEventsData, StreamEventsErrors, StreamEventsResponses, StreamRunEventsData, StreamRunEventsErrors, StreamRunEventsResponses, StripeConfig, SyncedRepositoryListQuery, SyncRepositoriesData, SyncRepositoriesErrors, SyncRepositoriesResponse, SyncRepositoriesResponses, SyntaxResult, TagInfo, TagListResponse, TailDeploymentJobLogsData, TailDeploymentJobLogsErrors, TailLogsData, TailLogsError, TailLogsErrors, TailLogsRequest, TailLogsResponses, TargetRecommendation, TeamListResponse, TeamMemberResponse, TeamResponse, TeamRole, TeardownDeploymentData, TeardownDeploymentErrors, TeardownDeploymentResponse, TeardownDeploymentResponses, TeardownEnvironmentData, TeardownEnvironmentErrors, TeardownEnvironmentResponse, TeardownEnvironmentResponses, TemplateResponse, TestEmailRequest, TestEmailResponse, TestNotificationProviderData, TestNotificationProviderErrors, TestNotificationProviderResponse, TestNotificationProviderResponses, TestOidcProviderData, TestOidcProviderResponse, TestOidcProviderResponses, TestProviderConnectionData, TestProviderConnectionErrors, TestProviderConnectionResponse, TestProviderConnectionResponses, TestProviderData, TestProviderErrors, TestProviderKeyByIdData, TestProviderKeyByIdError, TestProviderKeyByIdErrors, TestProviderKeyByIdResponse, TestProviderKeyByIdResponses, TestProviderKeyInlineData, TestProviderKeyInlineError, TestProviderKeyInlineErrors, TestProviderKeyInlineResponse, TestProviderKeyInlineResponses, TestProviderKeyRequest, TestProviderKeyResponse, TestProviderResponse, TestProviderResponse2, TestProviderResponses, TestS3ConnectionPreviewData, TestS3ConnectionPreviewError, TestS3ConnectionPreviewErrors, TestS3ConnectionPreviewResponse, TestS3ConnectionPreviewResponses, TestS3SourceConnectionData, TestS3SourceConnectionError, TestS3SourceConnectionErrors, TestS3SourceConnectionResponse, TestS3SourceConnectionResponses, TimeBucketStats, TimeBucketStatsResponse, TimeseriesBucket, TimeseriesQueryParams, TlsMode, TodayStatsResponse, ToggleDeploymentMetricsRequest, ToggleServiceMetricsRequest, TokenRenewalRequest, ToolCallEvent, ToolInfo, ToolResultEvent, TopModelsQueryParams, TraceProjectRef, TracesResponse, TraceSummariesResponse, TraceSummary, TrackClickData, TrackClickErrors, TrackedLinkResponse, TrackingEventResponse, TrackOpenData, TrackOpenErrors, TrackOpenResponses, TriggerAgentData, TriggerAgentErrors, TriggerAgentRequest, TriggerAgentResponse, TriggerAgentResponses, TriggerDigestResponse, TriggerPipelinePayload, TriggerPipelineResponse, TriggerProjectPipelineData, TriggerProjectPipelineErrors, TriggerProjectPipelineResponse, TriggerProjectPipelineResponses, TriggerScanData, TriggerScanError, TriggerScanErrors, TriggerScanRequest, TriggerScanResponse, TriggerScanResponse2, TriggerScanResponses, TriggerServiceHealthCheckData, TriggerServiceHealthCheckErrors, TriggerServiceHealthCheckResponse, TriggerServiceHealthCheckResponses, TriggerWeeklyDigestData, TriggerWeeklyDigestErrors, TriggerWeeklyDigestResponse, TriggerWeeklyDigestResponses, TtlRequest, TtlResponse, TxtRecord, UiManifest, UiRoute, UndrainNodeResponse, UnifiedTrace, UniqueCountsQuery, UniqueCountsResponse, UnlinkServiceFromProjectData, UnlinkServiceFromProjectErrors, UnlinkServiceFromProjectResponse, UnlinkServiceFromProjectResponses, UnsupportedFeature, UpdateAdminGateRequest, UpdateAgentData, UpdateAgentErrors, UpdateAgentResponse, UpdateAgentResponses, UpdateAiProviderData, UpdateAiProviderErrors, UpdateAiProviderRequest, UpdateAiProviderResponse, UpdateAiProviderResponse2, UpdateAiProviderResponses, UpdateAlertData, UpdateAlertError, UpdateAlertErrors, UpdateAlertResponse, UpdateAlertResponses, UpdateAlertRuleData, UpdateAlertRuleErrors, UpdateAlertRuleRequest, UpdateAlertRuleResponse, UpdateAlertRuleResponses, UpdateApiKeyData, UpdateApiKeyErrors, UpdateApiKeyRequest, UpdateApiKeyResponse, UpdateApiKeyResponses, UpdateAutomaticDeployData, UpdateAutomaticDeployErrors, UpdateAutomaticDeployRequest, UpdateAutomaticDeployResponse, UpdateAutomaticDeployResponses, UpdateBackupScheduleData, UpdateBackupScheduleError, UpdateBackupScheduleErrors, UpdateBackupScheduleRequest, UpdateBackupScheduleResponse, UpdateBackupScheduleResponses, UpdateBlobRequest, UpdateBlobResponse, UpdateCloudflareProviderData, UpdateCloudflareProviderErrors, UpdateCloudflareProviderRequest, UpdateCloudflareProviderResponse, UpdateCloudflareProviderResponses, UpdateConfigBody, UpdateConnectionTokenData, UpdateConnectionTokenErrors, UpdateConnectionTokenResponse, UpdateConnectionTokenResponses, UpdateCustomDomainData, UpdateCustomDomainErrors, UpdateCustomDomainRequest, UpdateCustomDomainResponse, UpdateCustomDomainResponses, UpdateDashboardData, UpdateDashboardError, UpdateDashboardErrors, UpdateDashboardRequest, UpdateDashboardResponse, UpdateDashboardResponses, UpdateDeploymentConfigRequest, UpdateDeploymentTokenData, UpdateDeploymentTokenErrors, UpdateDeploymentTokenRequest, UpdateDeploymentTokenResponse, UpdateDeploymentTokenResponses, UpdateDnsProviderRequest, UpdateEmailProviderData, UpdateEmailProviderErrors, UpdateEmailProviderRequest, UpdateEmailProviderResponse, UpdateEmailProviderResponses, UpdateEnvironmentSettingsData, UpdateEnvironmentSettingsErrors, UpdateEnvironmentSettingsRequest, UpdateEnvironmentSettingsResponse, UpdateEnvironmentSettingsResponses, UpdateEnvironmentSubdomainData, UpdateEnvironmentSubdomainErrors, UpdateEnvironmentSubdomainRequest, UpdateEnvironmentSubdomainResponse, UpdateEnvironmentSubdomainResponses, UpdateEnvironmentVariableData, UpdateEnvironmentVariableErrors, UpdateEnvironmentVariableRequest, UpdateEnvironmentVariableResponse, UpdateEnvironmentVariableResponses, UpdateErrorGroupData, UpdateErrorGroupErrors, UpdateErrorGroupRequest, UpdateErrorGroupResponses, UpdateExternalServiceRequest, UpdateFlagData, UpdateFlagErrors, UpdateFlagRequest, UpdateFlagResponse, UpdateFlagResponses, UpdateFunnelData, UpdateFunnelErrors, UpdateFunnelResponses, UpdateGitProviderCredentialsData, UpdateGitProviderCredentialsErrors, UpdateGitProviderCredentialsResponse, UpdateGitProviderCredentialsResponses, UpdateGitSettingsData, UpdateGitSettingsErrors, UpdateGitSettingsRequest, UpdateGitSettingsResponse, UpdateGitSettingsResponses, UpdateGlobalMcpData, UpdateGlobalMcpErrors, UpdateGlobalMcpResponse, UpdateGlobalMcpResponses, UpdateGlobalSkillData, UpdateGlobalSkillErrors, UpdateGlobalSkillResponse, UpdateGlobalSkillResponses, UpdateIncidentStatusData, UpdateIncidentStatusErrors, UpdateIncidentStatusRequest, UpdateIncidentStatusResponse, UpdateIncidentStatusResponses, UpdateIpAccessControlData, UpdateIpAccessControlError, UpdateIpAccessControlErrors, UpdateIpAccessControlRequest, UpdateIpAccessControlResponse, UpdateIpAccessControlResponses, UpdateKvRequest, UpdateKvResponse, UpdateManagedDomainApiRequest, UpdateManagedDomainData, UpdateManagedDomainErrors, UpdateManagedDomainResponse, UpdateManagedDomainResponses, UpdateMcpData, UpdateMcpErrors, UpdateMcpRequest, UpdateMcpResponse, UpdateMcpResponses, UpdateMemberRoleRequest, UpdateMetricAlertRequest, UpdateNotificationEmailProviderData, UpdateNotificationEmailProviderErrors, UpdateNotificationEmailProviderRequest, UpdateNotificationEmailProviderResponse, UpdateNotificationEmailProviderResponses, UpdateNotificationProviderData, UpdateNotificationProviderErrors, UpdateNotificationProviderResponse, UpdateNotificationProviderResponses, UpdateOidcProviderData, UpdateOidcProviderRequest, UpdateOidcProviderResponse, UpdateOidcProviderResponses, UpdatePreferencesData, UpdatePreferencesErrors, UpdatePreferencesRequest, UpdatePreferencesResponse, UpdatePreferencesResponses, UpdateProjectData, UpdateProjectDeploymentConfigData, UpdateProjectDeploymentConfigErrors, UpdateProjectDeploymentConfigResponse, UpdateProjectDeploymentConfigResponses, UpdateProjectErrors, UpdateProjectResponse, UpdateProjectResponses, UpdateProjectSecretData, UpdateProjectSecretErrors, UpdateProjectSecretRequest, UpdateProjectSecretResponse, UpdateProjectSecretResponses, UpdateProjectSettingsData, UpdateProjectSettingsErrors, UpdateProjectSettingsRequest, UpdateProjectSettingsResponse, UpdateProjectSettingsResponses, UpdateProviderCredentialsRequest, UpdateProviderData, UpdateProviderErrors, UpdateProviderKeyData, UpdateProviderKeyError, UpdateProviderKeyErrors, UpdateProviderKeyRequest, UpdateProviderKeyResponse, UpdateProviderKeyResponses, UpdateProviderRequest, UpdateProviderResponse, UpdateProviderResponses, UpdateRouteData, UpdateRouteErrors, UpdateRouteRequest, UpdateRouteResponse, UpdateRouteResponses, UpdateS3SourceData, UpdateS3SourceError, UpdateS3SourceErrors, UpdateS3SourceRequest, UpdateS3SourceResponse, UpdateS3SourceResponses, UpdateSecretBody, UpdateSelfData, UpdateSelfErrors, UpdateSelfRequest, UpdateSelfResponse, UpdateSelfResponses, UpdateServiceData, UpdateServiceErrors, UpdateServiceResourcesData, UpdateServiceResourcesErrors, UpdateServiceResourcesResponse, UpdateServiceResourcesResponses, UpdateServiceResponse, UpdateServiceResponses, UpdateSessionDurationData, UpdateSessionDurationError, UpdateSessionDurationErrors, UpdateSessionDurationRequest, UpdateSessionDurationResponse, UpdateSessionDurationResponse2, UpdateSessionDurationResponses, UpdateSettingsData, UpdateSettingsErrors, UpdateSettingsResponse, UpdateSettingsResponses, UpdateSkillData, UpdateSkillErrors, UpdateSkillRequest, UpdateSkillResponse, UpdateSkillResponses, UpdateSlackProviderData, UpdateSlackProviderErrors, UpdateSlackProviderRequest, UpdateSlackProviderResponse, UpdateSlackProviderResponses, UpdateSpeedMetricsData, UpdateSpeedMetricsError, UpdateSpeedMetricsErrors, UpdateSpeedMetricsPayload, UpdateSpeedMetricsResponse, UpdateSpeedMetricsResponses, UpdateStatusResponse, UpdateTeamData, UpdateTeamErrors, UpdateTeamMemberRoleData, UpdateTeamMemberRoleErrors, UpdateTeamMemberRoleResponse, UpdateTeamMemberRoleResponses, UpdateTeamRequest, UpdateTeamResponse, UpdateTeamResponses, UpdateTokenRequest, UpdateTokenResponse, UpdateUserData, UpdateUserErrors, UpdateUserRequest, UpdateUserResponse, UpdateUserResponses, UpdateWebhookData, UpdateWebhookErrors, UpdateWebhookProviderData, UpdateWebhookProviderErrors, UpdateWebhookProviderRequest, UpdateWebhookProviderResponse, UpdateWebhookProviderResponses, UpdateWebhookRequestBody, UpdateWebhookResponse, UpdateWebhookResponses, UpgradeExternalServiceRequest, UpgradePreviewGatewayData, UpgradePreviewGatewayResponse, UpgradePreviewGatewayResponses, UpgradeRequest, UpgradeServiceData, UpgradeServiceErrors, UpgradeServiceResponse, UpgradeServiceResponses, UploadGlobalSkillData, UploadGlobalSkillErrors, UploadGlobalSkillResponse, UploadGlobalSkillResponses, UploadReleaseFileData, UploadReleaseFileErrors, UploadReleaseFileResponse, UploadReleaseFileResponses, UploadSkillData, UploadSkillErrors, UploadSkillResponse, UploadSkillResponses, UploadSourceFileData, UploadSourceFileErrors, UploadSourceFileResponse, UploadSourceFileResponses, UploadSourceMapData, UploadSourceMapErrors, UploadSourceMapResponse, UploadSourceMapResponses, UploadStaticBundleData, UploadStaticBundleErrors, UploadStaticBundleResponse, UploadStaticBundleResponses, UpsertAgentRequest, UpsertSecretData, UpsertSecretErrors, UpsertSecretRequest, UpsertSecretResponse, UpsertSecretResponses, UptimeDataPoint, UptimeHistoryResponse, UsageFilter, UsageInfo, UsageLogEntry, UsageLogPage, UsageQueryParams, UsageSource, UsageSummary, UserResponse, ValidateConnectionData, ValidateConnectionErrors, ValidateConnectionResponse, ValidateConnectionResponses, ValidateEmailData, ValidateEmailErrors, ValidateEmailRequest, ValidateEmailResponse, ValidateEmailResponse2, ValidateEmailResponses, ValidationLevel, ValidationReport, ValidationResponse, ValidationResult, ValidationStatus, ValidationSummary, VerifyAndEnableMfaData, VerifyAndEnableMfaErrors, VerifyAndEnableMfaResponse, VerifyAndEnableMfaResponses, VerifyDomainData, VerifyDomainErrors, VerifyDomainResponse, VerifyDomainResponses, VerifyEmailData, VerifyEmailErrors, VerifyEmailResponse, VerifyEmailResponses, VerifyManagedDomainData, VerifyManagedDomainErrors, VerifyManagedDomainResponse, VerifyManagedDomainResponses, VerifyMfaChallengeData, VerifyMfaChallengeErrors, VerifyMfaChallengeResponse, VerifyMfaChallengeResponses, VerifyMfaRequest, VerifyStepUpData, VerifyStepUpErrors, VerifyStepUpRequest, VerifyStepUpResponse, VerifyStepUpResponses, ViewItem, ViewsOverTime, ViewsOverTimeQuery, VisitorDetails, VisitorFacets, VisitorFacetsQuery, VisitorFacetValue, VisitorInfo, VisitorJourneyQuery, VisitorJourneyResponse, VisitorLocationsQuery, VisitorRecord, VisitorSegmentFilters, VisitorSessionsQuery, VisitorSessionsResponse, VisitorsListQuery, VisitorsResponse, VisitorStats, VisitorWithGeolocation, VolumeMount, VolumeType, VulnerabilityResponse, WakeEnvironmentData, WakeEnvironmentErrors, WakeEnvironmentResponse, WakeEnvironmentResponses, WalWarning, WalWarningSeverity, WebhookConfig, WebhookDeliveryResponse, WebhookResponse, WebhookTriggerData, WebhookTriggerErrors, WebhookTriggerRequest, WebhookTriggerResponse, WebhookTriggerResponse2, WebhookTriggerResponses, WorkflowDryRunData, WorkflowDryRunErrors, WorkflowDryRunRequest, WorkflowDryRunResponse, WorkflowDryRunResponses, WorkloadDescriptor, WorkloadId, WorkloadStatus, WorkloadType, WriteFileBody, WriteFileData, WriteFileErrors, WriteFileResponse, WriteFileResponses, WriteFilesBody, WriteFilesData, WriteFilesErrors, WriteFilesResponse, WriteFilesResponse2, WriteFilesResponses, ZoneListResponse } from './types.gen'; diff --git a/web/src/api/client/sdk.gen.ts b/web/src/api/client/sdk.gen.ts index d459072f5..c075a1e2e 100644 --- a/web/src/api/client/sdk.gen.ts +++ b/web/src/api/client/sdk.gen.ts @@ -2,7 +2,7 @@ import { type Client, type ClientMeta, formDataBodySerializer, type Options as Options2, type RequestResult, type ServerSentEventsResult, type TDataShape } from './client'; import { client } from './client.gen'; -import type { AcknowledgeAlarmData, AcknowledgeAlarmErrors, AcknowledgeAlarmResponses, ActivateAiProviderData, ActivateAiProviderErrors, ActivateAiProviderResponses, ActivateApiKeyData, ActivateApiKeyErrors, ActivateApiKeyResponses, ActivateConnectionData, ActivateConnectionErrors, ActivateConnectionResponses, ActivateProviderData, ActivateProviderErrors, ActivateProviderResponses, AddClusterMemberData, AddClusterMemberErrors, AddClusterMemberResponses, AddContextData, AddContextErrors, AddContextResponses, AddEnvironmentDomainData, AddEnvironmentDomainErrors, AddEnvironmentDomainResponses, AddEventsData, AddEventsErrors, AddEventsResponses, AddManagedDomainData, AddManagedDomainErrors, AddManagedDomainResponses, AddSessionReplayEventsData, AddSessionReplayEventsErrors, AddSessionReplayEventsResponses, AddTeamMemberData, AddTeamMemberErrors, AddTeamMemberResponses, AdminDrainNodeData, AdminDrainNodeErrors, AdminDrainNodeResponses, AdminDrainStatusData, AdminDrainStatusErrors, AdminDrainStatusResponses, AdminGetNodeData, AdminGetNodeErrors, AdminGetNodeResponses, AdminListNodeContainersData, AdminListNodeContainersErrors, AdminListNodeContainersResponses, AdminListNodesData, AdminListNodesErrors, AdminListNodesResponses, AdminRemoveNodeData, AdminRemoveNodeErrors, AdminRemoveNodeResponses, AdminUndrainNodeData, AdminUndrainNodeErrors, AdminUndrainNodeResponses, ApplyHostnameModeData, ApplyHostnameModeErrors, ApplyHostnameModeResponses, ArchiveConversationData, ArchiveConversationErrors, ArchiveConversationResponses, ArchiveFlagData, ArchiveFlagErrors, ArchiveFlagResponses, AssignRoleData, AssignRoleErrors, AssignRoleResponses, AttachScheduleServicesData, AttachScheduleServicesErrors, AttachScheduleServicesResponses, BlobCopyData, BlobCopyErrors, BlobCopyResponses, BlobDeleteData, BlobDeleteErrors, BlobDeleteResponses, BlobDisableData, BlobDisableErrors, BlobDisableResponses, BlobDownloadData, BlobDownloadErrors, BlobDownloadResponses, BlobEnableData, BlobEnableErrors, BlobEnableResponses, BlobHeadData, BlobHeadErrors, BlobHeadResponses, BlobListData, BlobListErrors, BlobListResponses, BlobPutData, BlobPutErrors, BlobPutResponses, BlobStatusData, BlobStatusErrors, BlobStatusResponses, BlobUpdateData, BlobUpdateErrors, BlobUpdateResponses, CancelBackupData, CancelBackupErrors, CancelBackupResponses, CancelData, CancelDeploymentData, CancelDeploymentErrors, CancelDeploymentResponses, CancelDomainOrderData, CancelDomainOrderErrors, CancelDomainOrderResponses, CancelErrors, CancelPgUpgradeData, CancelPgUpgradeErrors, CancelPgUpgradeResponses, CancelResponses, CancelRunData, CancelRunErrors, CancelRunResponses, CancelScheduleRunData, CancelScheduleRunErrors, CancelScheduleRunResponses, ChangePasswordSelfData, ChangePasswordSelfErrors, ChangePasswordSelfResponses, ChangeProjectSourceData, ChangeProjectSourceErrors, ChangeProjectSourceResponses, ChatCompletionsData, ChatCompletionsErrors, ChatCompletionsResponses, CheckAnalyticsHasEventsData, CheckAnalyticsHasEventsErrors, CheckAnalyticsHasEventsResponses, CheckCommitExistsData, CheckCommitExistsErrors, CheckCommitExistsResponses, CheckDomainStatusData, CheckDomainStatusErrors, CheckDomainStatusResponses, CheckExplorerSupportData, CheckExplorerSupportErrors, CheckExplorerSupportResponses, CheckIpBlockedData, CheckIpBlockedErrors, CheckIpBlockedResponses, CheckProviderDeletionSafetyData, CheckProviderDeletionSafetyErrors, CheckProviderDeletionSafetyResponses, ChunkUploadOptionsData, ChunkUploadOptionsResponses, CleanupExpiredBackupsData, CleanupExpiredBackupsErrors, CleanupExpiredBackupsResponses, ClearPreviewPasswordData, ClearPreviewPasswordErrors, ClearPreviewPasswordResponses, CliDeviceApproveData, CliDeviceApproveErrors, CliDeviceApproveResponses, CliDeviceDenyData, CliDeviceDenyErrors, CliDeviceDenyResponses, CliDeviceLookupData, CliDeviceLookupErrors, CliDeviceLookupResponses, CliDevicePollData, CliDevicePollErrors, CliDevicePollResponses, CliDeviceStartData, CliDeviceStartErrors, CliDeviceStartResponses, CliLogoutData, CliLogoutErrors, CliLogoutResponses, CmdData, CmdErrors, CmdKillData, CmdKillErrors, CmdKillResponses, CmdLogsData, CmdLogsErrors, CmdLogsResponses, CmdResponses, ConfirmPendingActionData, ConfirmPendingActionErrors, ConfirmPendingActionResponses, ContainerMetricsGetHistoryData, ContainerMetricsGetHistoryErrors, ContainerMetricsGetHistoryResponses, CreateAgentData, CreateAgentErrors, CreateAgentResponses, CreateAlertData, CreateAlertErrors, CreateAlertResponses, CreateAlertRuleData, CreateAlertRuleErrors, CreateAlertRuleResponses, CreateApiKeyData, CreateApiKeyErrors, CreateApiKeyResponses, CreateBackupScheduleData, CreateBackupScheduleErrors, CreateBackupScheduleResponses, CreateBitbucketProviderData, CreateBitbucketProviderErrors, CreateBitbucketProviderResponses, CreateCloudflareProviderData, CreateCloudflareProviderErrors, CreateCloudflareProviderResponses, CreateConversationData, CreateConversationErrors, CreateConversationResponses, CreateCustomDomainData, CreateCustomDomainErrors, CreateCustomDomainResponses, CreateDashboardData, CreateDashboardErrors, CreateDashboardResponses, CreateDeploymentTokenData, CreateDeploymentTokenErrors, CreateDeploymentTokenResponses, CreateDnsProviderData, CreateDnsProviderErrors, CreateDnsProviderResponses, CreateDomainData, CreateDomainErrors, CreateDomainResponses, CreateDsnData, CreateDsnErrors, CreateDsnResponses, CreateEmailDomainData, CreateEmailDomainErrors, CreateEmailDomainResponses, CreateEmailProviderData, CreateEmailProviderErrors, CreateEmailProviderResponses, CreateEnvironmentData, CreateEnvironmentErrors, CreateEnvironmentResponses, CreateEnvironmentVariableData, CreateEnvironmentVariableErrors, CreateEnvironmentVariableResponses, CreateFlagData, CreateFlagErrors, CreateFlagResponses, CreateFunnelData, CreateFunnelErrors, CreateFunnelResponses, CreateGenericProviderData, CreateGenericProviderErrors, CreateGenericProviderResponses, CreateGiteaPatProviderData, CreateGiteaPatProviderErrors, CreateGiteaPatProviderResponses, CreateGithubPatProviderData, CreateGithubPatProviderErrors, CreateGithubPatProviderResponses, CreateGitlabOauthProviderData, CreateGitlabOauthProviderErrors, CreateGitlabOauthProviderResponses, CreateGitlabPatProviderData, CreateGitlabPatProviderErrors, CreateGitlabPatProviderResponses, CreateGitProviderData, CreateGitProviderErrors, CreateGitProviderResponses, CreateGlobalMcpData, CreateGlobalMcpErrors, CreateGlobalMcpResponses, CreateGlobalSkillData, CreateGlobalSkillErrors, CreateGlobalSkillResponses, CreateIncidentData, CreateIncidentErrors, CreateIncidentResponses, CreateIpAccessControlData, CreateIpAccessControlErrors, CreateIpAccessControlResponses, CreateMcpData, CreateMcpErrors, CreateMcpResponses, CreateMonitorData, CreateMonitorErrors, CreateMonitorResponses, CreateNotificationEmailProviderData, CreateNotificationEmailProviderErrors, CreateNotificationEmailProviderResponses, CreateNotificationProviderData, CreateNotificationProviderErrors, CreateNotificationProviderResponses, CreateOidcProviderData, CreateOidcProviderErrors, CreateOidcProviderResponses, CreateOidcRoleMappingData, CreateOidcRoleMappingResponses, CreateOrRecreateOrderData, CreateOrRecreateOrderErrors, CreateOrRecreateOrderResponses, CreatePlanData, CreatePlanErrors, CreatePlanResponses, CreatePrData, CreatePrErrors, CreateProjectData, CreateProjectErrors, CreateProjectFromTemplateData, CreateProjectFromTemplateErrors, CreateProjectFromTemplateResponses, CreateProjectReleaseData, CreateProjectReleaseErrors, CreateProjectReleaseResponses, CreateProjectResponses, CreateProjectSecretData, CreateProjectSecretErrors, CreateProjectSecretResponses, CreateProviderKeyData, CreateProviderKeyErrors, CreateProviderKeyResponses, CreatePrResponses, CreateReleaseData, CreateReleaseErrors, CreateReleaseResponses, CreateRouteData, CreateRouteErrors, CreateRouteResponses, CreateS3SourceData, CreateS3SourceErrors, CreateS3SourceResponses, CreateSandboxData, CreateSandboxErrors, CreateSandboxResponses, CreateServiceData, CreateServiceErrors, CreateServiceResponses, CreateSkillData, CreateSkillErrors, CreateSkillResponses, CreateSlackProviderData, CreateSlackProviderErrors, CreateSlackProviderResponses, CreateTeamData, CreateTeamErrors, CreateTeamResponses, CreateUserData, CreateUserErrors, CreateUserResponses, CreateWebhookData, CreateWebhookErrors, CreateWebhookProviderData, CreateWebhookProviderErrors, CreateWebhookProviderResponses, CreateWebhookResponses, DeactivateApiKeyData, DeactivateApiKeyErrors, DeactivateApiKeyResponses, DeactivateConnectionData, DeactivateConnectionErrors, DeactivateConnectionResponses, DeactivateProviderData, DeactivateProviderErrors, DeactivateProviderResponses, DeleteAgentData, DeleteAgentErrors, DeleteAgentResponses, DeleteAlertData, DeleteAlertErrors, DeleteAlertResponses, DeleteAlertRuleData, DeleteAlertRuleErrors, DeleteAlertRuleResponses, DeleteApiKeyData, DeleteApiKeyErrors, DeleteApiKeyResponses, DeleteBackupData, DeleteBackupErrors, DeleteBackupResponses, DeleteBackupScheduleData, DeleteBackupScheduleErrors, DeleteBackupScheduleResponses, DeleteConnectionData, DeleteConnectionErrors, DeleteConnectionResponses, DeleteCustomDomainData, DeleteCustomDomainErrors, DeleteCustomDomainResponses, DeleteDashboardData, DeleteDashboardErrors, DeleteDashboardResponses, DeleteDeploymentTokenData, DeleteDeploymentTokenErrors, DeleteDeploymentTokenResponses, DeleteDnsProviderData, DeleteDnsProviderErrors, DeleteDnsProviderResponses, DeleteDomainData, DeleteDomainErrors, DeleteDomainResponses, DeleteEmailDomainData, DeleteEmailDomainErrors, DeleteEmailDomainResponses, DeleteEmailProviderData, DeleteEmailProviderErrors, DeleteEmailProviderResponses, DeleteEnvironmentData, DeleteEnvironmentDomainData, DeleteEnvironmentDomainErrors, DeleteEnvironmentDomainResponses, DeleteEnvironmentErrors, DeleteEnvironmentResponses, DeleteEnvironmentVariableData, DeleteEnvironmentVariableErrors, DeleteEnvironmentVariableResponses, DeleteExternalImageData, DeleteExternalImageErrors, DeleteExternalImageResponses, DeleteFunnelData, DeleteFunnelErrors, DeleteFunnelResponses, DeleteGitProviderData, DeleteGitProviderErrors, DeleteGitProviderResponses, DeleteGlobalMcpData, DeleteGlobalMcpErrors, DeleteGlobalMcpResponses, DeleteGlobalSkillData, DeleteGlobalSkillErrors, DeleteGlobalSkillResponses, DeleteIpAccessControlData, DeleteIpAccessControlErrors, DeleteIpAccessControlResponses, DeleteMcpData, DeleteMcpErrors, DeleteMcpResponses, DeleteMonitorData, DeleteMonitorErrors, DeleteMonitorResponses, DeleteNotificationProviderData, DeleteNotificationProviderErrors, DeleteNotificationProviderResponses, DeleteOidcProviderData, DeleteOidcProviderResponses, DeleteOidcRoleMappingData, DeleteOidcRoleMappingResponses, DeletePreferencesData, DeletePreferencesErrors, DeletePreferencesResponses, DeleteProjectData, DeleteProjectErrors, DeleteProjectResponses, DeleteProjectSecretData, DeleteProjectSecretErrors, DeleteProjectSecretResponses, DeleteProviderKeyData, DeleteProviderKeyErrors, DeleteProviderKeyResponses, DeleteProviderSafelyData, DeleteProviderSafelyErrors, DeleteProviderSafelyResponses, DeleteReleaseSourceFilesData, DeleteReleaseSourceFilesErrors, DeleteReleaseSourceFilesResponses, DeleteReleaseSourceMapsData, DeleteReleaseSourceMapsErrors, DeleteReleaseSourceMapsResponses, DeleteRouteData, DeleteRouteErrors, DeleteRouteResponses, DeleteS3SourceData, DeleteS3SourceErrors, DeleteS3SourceResponses, DeleteScanData, DeleteScanErrors, DeleteScanResponses, DeleteSecretData, DeleteSecretErrors, DeleteSecretResponses, DeleteServiceData, DeleteServiceErrors, DeleteServiceResponses, DeleteSessionReplayData, DeleteSessionReplayErrors, DeleteSessionReplayResponses, DeleteSkillData, DeleteSkillErrors, DeleteSkillResponses, DeleteSourceMapData, DeleteSourceMapErrors, DeleteSourceMapResponses, DeleteStaticBundleData, DeleteStaticBundleErrors, DeleteStaticBundleResponses, DeleteTeamData, DeleteTeamErrors, DeleteTeamResponses, DeleteUserData, DeleteUserErrors, DeleteUserResponses, DeleteWebhookData, DeleteWebhookErrors, DeleteWebhookResponses, DeployFromImageData, DeployFromImageErrors, DeployFromImageResponses, DeployFromImageUploadData, DeployFromImageUploadErrors, DeployFromImageUploadResponses, DeployFromStaticData, DeployFromStaticErrors, DeployFromStaticResponses, DeploymentMetricsGetLatestData, DeploymentMetricsGetLatestErrors, DeploymentMetricsGetLatestResponses, DeploymentMetricsGetRangeData, DeploymentMetricsGetRangeErrors, DeploymentMetricsGetRangeResponses, DeploymentMetricsToggleData, DeploymentMetricsToggleErrors, DeploymentMetricsToggleResponses, DestroySandboxData, DestroySandboxErrors, DestroySandboxResponses, DetachScheduleServiceData, DetachScheduleServiceErrors, DetachScheduleServiceResponses, DetectPublicPresetsData, DetectPublicPresetsErrors, DetectPublicPresetsResponses, DisableBackupScheduleData, DisableBackupScheduleErrors, DisableBackupScheduleResponses, DisableMfaData, DisableMfaErrors, DisableMfaResponses, DiscoverWorkloadsData, DiscoverWorkloadsErrors, DiscoverWorkloadsResponses, DomainData, DomainErrors, DomainResponses, DownloadGlobalSkillArchiveData, DownloadGlobalSkillArchiveErrors, DownloadGlobalSkillArchiveResponses, DownloadObjectData, DownloadObjectErrors, DownloadObjectResponses, DownloadSkillArchiveData, DownloadSkillArchiveErrors, DownloadSkillArchiveResponses, EmailStatusData, EmailStatusErrors, EmailStatusResponses, EmbeddingsData, EmbeddingsErrors, EmbeddingsResponses, EnableBackupScheduleData, EnableBackupScheduleErrors, EnableBackupScheduleResponses, EnrichVisitorData, EnrichVisitorErrors, EnrichVisitorResponses, ExecData, ExecDetachedData, ExecDetachedErrors, ExecDetachedResponses, ExecErrors, ExecResponses, ExecuteDeploymentOperationData, ExecuteDeploymentOperationErrors, ExecuteDeploymentOperationResponses, ExecuteImportData, ExecuteImportErrors, ExecuteImportResponses, ExtendTimeoutData, ExtendTimeoutErrors, ExtendTimeoutResponses, ExternalServiceEnablePgStatStatementsData, ExternalServiceEnablePgStatStatementsErrors, ExternalServiceEnablePgStatStatementsResponses, ExternalServiceMetricsByDatabaseData, ExternalServiceMetricsByDatabaseErrors, ExternalServiceMetricsByDatabaseResponses, ExternalServiceMetricsCreateAlertRuleData, ExternalServiceMetricsCreateAlertRuleErrors, ExternalServiceMetricsCreateAlertRuleResponses, ExternalServiceMetricsDeleteAlertRuleData, ExternalServiceMetricsDeleteAlertRuleErrors, ExternalServiceMetricsDeleteAlertRuleResponses, ExternalServiceMetricsGetAlertRulesData, ExternalServiceMetricsGetAlertRulesErrors, ExternalServiceMetricsGetAlertRulesResponses, ExternalServiceMetricsGetLatestData, ExternalServiceMetricsGetLatestErrors, ExternalServiceMetricsGetLatestResponses, ExternalServiceMetricsGetRangeData, ExternalServiceMetricsGetRangeErrors, ExternalServiceMetricsGetRangeResponses, ExternalServiceMetricsStatusData, ExternalServiceMetricsStatusErrors, ExternalServiceMetricsStatusResponses, ExternalServiceMetricsToggleData, ExternalServiceMetricsToggleErrors, ExternalServiceMetricsToggleResponses, ExternalServiceMetricsUpdateAlertRuleData, ExternalServiceMetricsUpdateAlertRuleErrors, ExternalServiceMetricsUpdateAlertRuleResponses, ExternalServiceResetPgStatStatementsData, ExternalServiceResetPgStatStatementsErrors, ExternalServiceResetPgStatStatementsResponses, FinalizeOrderData, FinalizeOrderErrors, FinalizeOrderResponses, FinalizeProjectReleaseData, FinalizeProjectReleaseErrors, FinalizeProjectReleaseResponses, FindConversationData, FindConversationErrors, FindConversationResponses, GenerateJoinTokenData, GenerateJoinTokenErrors, GenerateJoinTokenResponses, GeneratePresetDockerfileData, GeneratePresetDockerfileErrors, GeneratePresetDockerfileResponses, GetAccessInfoData, GetAccessInfoErrors, GetAccessInfoResponses, GetActiveVisitorsData, GetActiveVisitorsErrors, GetActiveVisitorsResponses, GetActivityGraphData, GetActivityGraphErrors, GetActivityGraphResponses, GetAdminGateData, GetAdminGateErrors, GetAdminGateResponses, GetAgentData, GetAgentErrors, GetAgentResponses, GetAggregatedBucketsData, GetAggregatedBucketsErrors, GetAggregatedBucketsResponses, GetAiAgentBreakdownData, GetAiAgentBreakdownErrors, GetAiAgentBreakdownResponses, GetAiAgentPagesData, GetAiAgentPagesErrors, GetAiAgentPagesResponses, GetAiAgentTimelineData, GetAiAgentTimelineErrors, GetAiAgentTimelineResponses, GetAiPageBreakdownData, GetAiPageBreakdownErrors, GetAiPageBreakdownResponses, GetAiStatusBreakdownData, GetAiStatusBreakdownErrors, GetAiStatusBreakdownResponses, GetAlertData, GetAlertErrors, GetAlertResponses, GetAlertRuleData, GetAlertRuleErrors, GetAlertRuleResponses, GetAllRepositoriesByNameData, GetAllRepositoriesByNameErrors, GetAllRepositoriesByNameResponses, GetAnalyticsActiveVisitorsData, GetAnalyticsActiveVisitorsErrors, GetAnalyticsActiveVisitorsResponses, GetAnalyticsEventsCountData, GetAnalyticsEventsCountErrors, GetAnalyticsEventsCountResponses, GetAnalyticsSessionEventsData, GetAnalyticsSessionEventsErrors, GetAnalyticsSessionEventsResponses, GetAnalyticsVisitorSessionsData, GetAnalyticsVisitorSessionsErrors, GetAnalyticsVisitorSessionsResponses, GetApiKeyData, GetApiKeyErrors, GetApiKeyPermissionsData, GetApiKeyPermissionsErrors, GetApiKeyPermissionsResponses, GetApiKeyResponses, GetAuditLogData, GetAuditLogErrors, GetAuditLogResponses, GetBackupData, GetBackupErrors, GetBackupResponses, GetBackupScheduleData, GetBackupScheduleErrors, GetBackupScheduleResponses, GetBranchesByRepositoryIdData, GetBranchesByRepositoryIdErrors, GetBranchesByRepositoryIdResponses, GetBucketedIncidentsData, GetBucketedIncidentsErrors, GetBucketedIncidentsResponses, GetBucketedStatusData, GetBucketedStatusErrors, GetBucketedStatusResponses, GetChallengeTokenData, GetChallengeTokenErrors, GetChallengeTokenResponses, GetChatReadinessData, GetChatReadinessErrors, GetChatReadinessResponses, GetCliStatusData, GetCliStatusErrors, GetCliStatusResponses, GetClusterHealthData, GetClusterHealthErrors, GetClusterHealthResponses, GetClusterMemberData, GetClusterMemberErrors, GetClusterMemberResponses, GetCmdData, GetCmdErrors, GetCmdResponses, GetContainerDetailData, GetContainerDetailErrors, GetContainerDetailResponses, GetContainerEnvironmentVariableData, GetContainerEnvironmentVariableErrors, GetContainerEnvironmentVariableResponses, GetContainerInfoData, GetContainerInfoErrors, GetContainerInfoResponses, GetContainerLogsByIdData, GetContainerLogsByIdErrors, GetContainerLogsData, GetContainerLogsErrors, GetContainerMetricsData, GetContainerMetricsErrors, GetContainerMetricsResponses, GetConversationData, GetConversationDetailData, GetConversationDetailErrors, GetConversationDetailResponses, GetConversationErrors, GetConversationResponses, GetConversationsData, GetConversationsErrors, GetConversationsResponses, GetCronByIdData, GetCronByIdErrors, GetCronByIdResponses, GetCronExecutionsData, GetCronExecutionsErrors, GetCronExecutionsResponses, GetCrossProjectTraceSiblingsData, GetCrossProjectTraceSiblingsErrors, GetCrossProjectTraceSiblingsResponses, GetCurrentMonitorStatusData, GetCurrentMonitorStatusErrors, GetCurrentMonitorStatusResponses, GetCurrentUserData, GetCurrentUserErrors, GetCurrentUserResponses, GetCustomDomainData, GetCustomDomainErrors, GetCustomDomainResponses, GetDashboardData, GetDashboardErrors, GetDashboardProjectsAnalyticsData, GetDashboardProjectsAnalyticsErrors, GetDashboardProjectsAnalyticsResponses, GetDashboardResponses, GetDeliveryData, GetDeliveryErrors, GetDeliveryResponses, GetDeploymentContainerLogContentData, GetDeploymentContainerLogContentErrors, GetDeploymentContainerLogContentResponses, GetDeploymentData, GetDeploymentErrors, GetDeploymentJobLogsData, GetDeploymentJobLogsErrors, GetDeploymentJobLogsResponses, GetDeploymentJobsData, GetDeploymentJobsErrors, GetDeploymentJobsResponses, GetDeploymentOperationsData, GetDeploymentOperationsErrors, GetDeploymentOperationsResponses, GetDeploymentOperationStatusData, GetDeploymentOperationStatusErrors, GetDeploymentOperationStatusResponses, GetDeploymentResponses, GetDeploymentTokenData, GetDeploymentTokenErrors, GetDeploymentTokenResponses, GetDiskStatusData, GetDiskStatusErrors, GetDiskStatusResponses, GetDnsChangesData, GetDnsChangesErrors, GetDnsChangesResponses, GetDnsProviderData, GetDnsProviderErrors, GetDnsProviderResponses, GetDomainByHostData, GetDomainByHostErrors, GetDomainByHostResponses, GetDomainByIdData, GetDomainByIdErrors, GetDomainByIdResponses, GetDomainByNameData, GetDomainByNameErrors, GetDomainByNameResponses, GetDomainData, GetDomainDnsRecordsData, GetDomainDnsRecordsErrors, GetDomainDnsRecordsResponses, GetDomainErrors, GetDomainOrderData, GetDomainOrderErrors, GetDomainOrderResponses, GetDomainResponses, GetEmailData, GetEmailErrors, GetEmailEventsData, GetEmailEventsErrors, GetEmailEventsResponses, GetEmailLinksData, GetEmailLinksErrors, GetEmailLinksResponses, GetEmailProviderData, GetEmailProviderErrors, GetEmailProviderResponses, GetEmailResponses, GetEmailStatsData, GetEmailStatsErrors, GetEmailStatsResponses, GetEmailTrackingData, GetEmailTrackingErrors, GetEmailTrackingResponses, GetEmailTrackingStatusData, GetEmailTrackingStatusErrors, GetEmailTrackingStatusResponses, GetEntityInfoData, GetEntityInfoErrors, GetEntityInfoResponses, GetEnvironmentCronsData, GetEnvironmentCronsErrors, GetEnvironmentCronsResponses, GetEnvironmentData, GetEnvironmentDomainsData, GetEnvironmentDomainsErrors, GetEnvironmentDomainsResponses, GetEnvironmentErrors, GetEnvironmentResponses, GetEnvironmentsData, GetEnvironmentsErrors, GetEnvironmentsResponses, GetEnvironmentVariablesData, GetEnvironmentVariablesErrors, GetEnvironmentVariablesResponses, GetEnvironmentVariableValueData, GetEnvironmentVariableValueErrors, GetEnvironmentVariableValueResponses, GetErrorDashboardStatsData, GetErrorDashboardStatsErrors, GetErrorDashboardStatsResponses, GetErrorEventData, GetErrorEventErrors, GetErrorEventResponses, GetErrorGroupData, GetErrorGroupErrors, GetErrorGroupResponses, GetErrorStatsData, GetErrorStatsErrors, GetErrorStatsResponses, GetErrorTimeSeriesData, GetErrorTimeSeriesErrors, GetErrorTimeSeriesResponses, GetEventDetailData, GetEventDetailErrors, GetEventDetailResponses, GetEventEntriesData, GetEventEntriesErrors, GetEventEntriesResponses, GetEventsCountData, GetEventsCountErrors, GetEventsCountResponses, GetEventsTimelineData, GetEventsTimelineErrors, GetEventsTimelineResponses, GetEventTypeBreakdownData, GetEventTypeBreakdownErrors, GetEventTypeBreakdownResponses, GetEventVisitorsData, GetEventVisitorsErrors, GetEventVisitorsResponses, GetExternalImageData, GetExternalImageErrors, GetExternalImageResponses, GetFileData, GetFileErrors, GetFileResponses, GetFlagData, GetFlagErrors, GetFlagResponses, GetFlagSnapshotData, GetFlagSnapshotErrors, GetFlagSnapshotResponses, GetFunnelMetricsData, GetFunnelMetricsErrors, GetFunnelMetricsResponses, GetGenaiTraceData, GetGenaiTraceErrors, GetGenaiTraceResponses, GetGeneralStatsData, GetGeneralStatsErrors, GetGeneralStatsResponses, GetGitProviderData, GetGitProviderErrors, GetGitProviderResponses, GetGlobalEventsData, GetGlobalEventsErrors, GetGlobalEventsResponses, GetGlobalEventStatsData, GetGlobalEventStatsErrors, GetGlobalEventStatsResponses, GetGlobalMcpData, GetGlobalMcpErrors, GetGlobalMcpResponses, GetGlobalSandboxStatusData, GetGlobalSandboxStatusErrors, GetGlobalSandboxStatusResponses, GetGlobalSkillData, GetGlobalSkillErrors, GetGlobalSkillResponses, GetGroupedPageMetricsData, GetGroupedPageMetricsErrors, GetGroupedPageMetricsResponses, GetHealthData, GetHealthErrors, GetHealthResponses, GetHourlyVisitsData, GetHourlyVisitsErrors, GetHourlyVisitsResponses, GetHttpChallengeDebugData, GetHttpChallengeDebugErrors, GetHttpChallengeDebugResponses, GetImportStatusData, GetImportStatusErrors, GetImportStatusResponses, GetIncidentData, GetIncidentErrors, GetIncidentResponses, GetIncidentUpdatesData, GetIncidentUpdatesErrors, GetIncidentUpdatesResponses, GetIpAccessControlData, GetIpAccessControlErrors, GetIpAccessControlResponses, GetIpGeolocationData, GetIpGeolocationErrors, GetIpGeolocationResponses, GetJoinTokenStatusData, GetJoinTokenStatusErrors, GetJoinTokenStatusResponses, GetLastDeploymentData, GetLastDeploymentErrors, GetLastDeploymentResponses, GetLatestScanData, GetLatestScanErrors, GetLatestScanResponses, GetLatestScansPerEnvironmentData, GetLatestScansPerEnvironmentErrors, GetLatestScansPerEnvironmentResponses, GetLiveVisitorsListData, GetLiveVisitorsListErrors, GetLiveVisitorsListResponses, GetLogContextData, GetLogContextErrors, GetLogContextResponses, GetMcpData, GetMcpErrors, GetMcpResponses, GetMetricsOverTimeData, GetMetricsOverTimeErrors, GetMetricsOverTimeResponses, GetMonitorData, GetMonitorErrors, GetMonitorResponses, GetNotificationProviderData, GetNotificationProviderErrors, GetNotificationProviderResponses, GetOnDemandCertStatusData, GetOnDemandCertStatusErrors, GetOnDemandCertStatusResponses, GetOrCreateDsnData, GetOrCreateDsnErrors, GetOrCreateDsnResponses, GetPageFlowData, GetPageFlowErrors, GetPageFlowResponses, GetPageHourlySessionsData, GetPageHourlySessionsErrors, GetPageHourlySessionsResponses, GetPagePathDetailData, GetPagePathDetailErrors, GetPagePathDetailResponses, GetPagePathsData, GetPagePathsErrors, GetPagePathsResponses, GetPagePathsSparklinesData, GetPagePathsSparklinesErrors, GetPagePathsSparklinesResponses, GetPagePathVisitorsData, GetPagePathVisitorsErrors, GetPagePathVisitorsResponses, GetPendingActionData, GetPendingActionErrors, GetPendingActionResponses, GetPerformanceMetricsData, GetPerformanceMetricsErrors, GetPerformanceMetricsResponses, GetPgUpgradeData, GetPgUpgradeErrors, GetPgUpgradeLogsData, GetPgUpgradeLogsErrors, GetPgUpgradeLogsResponses, GetPgUpgradeResponses, GetPipelineStatsData, GetPipelineStatsErrors, GetPipelineStatsResponses, GetPlatformInfoData, GetPlatformInfoErrors, GetPlatformInfoResponses, GetPostgresWalHealthData, GetPostgresWalHealthErrors, GetPostgresWalHealthResponses, GetPreferencesData, GetPreferencesErrors, GetPreferencesResponses, GetPreviewGatewayLogsData, GetPreviewGatewayLogsResponses, GetPreviewGatewaySettingsData, GetPreviewGatewaySettingsResponses, GetPreviewGatewayStatusData, GetPreviewGatewayStatusResponses, GetPricingData, GetPricingErrors, GetPricingResponses, GetPrivateIpData, GetPrivateIpErrors, GetPrivateIpResponses, GetProjectAlarmsSummaryData, GetProjectAlarmsSummaryErrors, GetProjectAlarmsSummaryResponses, GetProjectBySlugData, GetProjectBySlugErrors, GetProjectBySlugResponses, GetProjectData, GetProjectDeploymentsData, GetProjectDeploymentsErrors, GetProjectDeploymentsResponses, GetProjectErrors, GetProjectResponses, GetProjectsData, GetProjectsErrors, GetProjectServiceEnvironmentVariablesData, GetProjectServiceEnvironmentVariablesErrors, GetProjectServiceEnvironmentVariablesResponses, GetProjectSessionReplaysData, GetProjectSessionReplaysErrors, GetProjectSessionReplaysResponses, GetProjectsHealthData, GetProjectsHealthErrors, GetProjectsHealthResponses, GetProjectsMonitorHealthData, GetProjectsMonitorHealthErrors, GetProjectsMonitorHealthResponses, GetProjectsResponses, GetProjectStatisticsData, GetProjectStatisticsErrors, GetProjectStatisticsResponses, GetProjectTemplateData, GetProjectTemplateErrors, GetProjectTemplateResponses, GetPropertyBreakdownData, GetPropertyBreakdownErrors, GetPropertyBreakdownResponses, GetPropertyTimelineData, GetPropertyTimelineErrors, GetPropertyTimelineResponses, GetProviderConnectionsData, GetProviderConnectionsErrors, GetProviderConnectionsResponses, GetProviderMetadataData, GetProviderMetadataErrors, GetProviderMetadataResponses, GetProvidersMetadataData, GetProvidersMetadataErrors, GetProvidersMetadataResponses, GetProxyLogByIdData, GetProxyLogByIdErrors, GetProxyLogByIdResponses, GetProxyLogByRequestIdData, GetProxyLogByRequestIdErrors, GetProxyLogByRequestIdResponses, GetProxyLogsData, GetProxyLogsErrors, GetProxyLogsResponses, GetPublicBranchesData, GetPublicBranchesErrors, GetPublicBranchesResponses, GetPublicIpData, GetPublicIpErrors, GetPublicIpResponses, GetPublicRepositoryData, GetPublicRepositoryErrors, GetPublicRepositoryResponses, GetQuotaData, GetQuotaErrors, GetQuotaResponses, GetRecentActivityData, GetRecentActivityErrors, GetRecentActivityResponses, GetRemoteExternalImageData, GetRemoteExternalImageErrors, GetRemoteExternalImageResponses, GetRepositoryBranchesData, GetRepositoryBranchesErrors, GetRepositoryBranchesResponses, GetRepositoryByIdData, GetRepositoryByIdErrors, GetRepositoryByIdResponses, GetRepositoryByNameData, GetRepositoryByNameErrors, GetRepositoryByNameResponses, GetRepositoryPresetByNameData, GetRepositoryPresetByNameErrors, GetRepositoryPresetByNameResponses, GetRepositoryPresetLiveData, GetRepositoryPresetLiveErrors, GetRepositoryPresetLiveResponses, GetRepositoryTagsData, GetRepositoryTagsErrors, GetRepositoryTagsResponses, GetResolvedEnvironmentVariablesData, GetResolvedEnvironmentVariablesErrors, GetResolvedEnvironmentVariablesResponses, GetResolvedEnvironmentVariableValueData, GetResolvedEnvironmentVariableValueErrors, GetResolvedEnvironmentVariableValueResponses, GetRestoreCapabilitiesData, GetRestoreCapabilitiesErrors, GetRestoreCapabilitiesResponses, GetRestoreRunData, GetRestoreRunErrors, GetRestoreRunResponses, GetRouteData, GetRouteErrors, GetRouteResponses, GetRunData, GetRunErrors, GetRunResponses, GetRunWithLogsData, GetRunWithLogsErrors, GetRunWithLogsResponses, GetS3CredentialsData, GetS3CredentialsErrors, GetS3CredentialsResponses, GetS3SourceData, GetS3SourceErrors, GetS3SourceResponses, GetSandboxData, GetSandboxErrors, GetSandboxResponses, GetSandboxStatusData, GetSandboxStatusErrors, GetSandboxStatusResponses, GetScanByDeploymentData, GetScanByDeploymentErrors, GetScanByDeploymentResponses, GetScanData, GetScanErrors, GetScanResponses, GetScanVulnerabilitiesData, GetScanVulnerabilitiesErrors, GetScanVulnerabilitiesResponses, GetServiceBySlugData, GetServiceBySlugErrors, GetServiceBySlugResponses, GetServiceData, GetServiceEnvironmentVariableData, GetServiceEnvironmentVariableErrors, GetServiceEnvironmentVariableResponses, GetServiceEnvironmentVariablesData, GetServiceEnvironmentVariablesErrors, GetServiceEnvironmentVariablesResponses, GetServiceErrors, GetServiceHealthStatusData, GetServiceHealthStatusErrors, GetServiceHealthStatusResponses, GetServicePreviewEnvironmentVariableNamesData, GetServicePreviewEnvironmentVariableNamesErrors, GetServicePreviewEnvironmentVariableNamesResponses, GetServicePreviewEnvironmentVariablesMaskedData, GetServicePreviewEnvironmentVariablesMaskedErrors, GetServicePreviewEnvironmentVariablesMaskedResponses, GetServiceResponses, GetServiceRuntimeData, GetServiceRuntimeErrors, GetServiceRuntimeResponses, GetServiceStatsData, GetServiceStatsErrors, GetServiceStatsResponses, GetServiceTypeParametersData, GetServiceTypeParametersErrors, GetServiceTypeParametersResponses, GetServiceTypesData, GetServiceTypesErrors, GetServiceTypesResponses, GetSessionDetailsData, GetSessionDetailsErrors, GetSessionDetailsResponses, GetSessionEventsData, GetSessionEventsErrors, GetSessionEventsResponses, GetSessionLogsData, GetSessionLogsErrors, GetSessionLogsResponses, GetSessionReplayData, GetSessionReplayErrors, GetSessionReplayEventsData, GetSessionReplayEventsErrors, GetSessionReplayEventsResponses, GetSessionReplayResponses, GetSettingsData, GetSettingsErrors, GetSettingsResponses, GetSkillData, GetSkillErrors, GetSkillResponses, GetSlowQueriesData, GetSlowQueriesErrors, GetSlowQueriesResponses, GetStaticBundleData, GetStaticBundleErrors, GetStaticBundleResponses, GetStatusOverviewData, GetStatusOverviewErrors, GetStatusOverviewResponses, GetTagsByRepositoryIdData, GetTagsByRepositoryIdErrors, GetTagsByRepositoryIdResponses, GetTeamData, GetTeamErrors, GetTeamResponses, GetTimeBucketStatsData, GetTimeBucketStatsErrors, GetTimeBucketStatsResponses, GetTodayStatsData, GetTodayStatsErrors, GetTodayStatsResponses, GetTraceData, GetTraceErrors, GetTraceResponses, GetUnifiedTraceData, GetUnifiedTraceErrors, GetUnifiedTraceResponses, GetUniqueCountsData, GetUniqueCountsErrors, GetUniqueCountsResponses, GetUniqueEventsData, GetUniqueEventsErrors, GetUniqueEventsResponses, GetUpdateStatusData, GetUpdateStatusErrors, GetUpdateStatusResponses, GetUptimeHistoryData, GetUptimeHistoryErrors, GetUptimeHistoryResponses, GetUsageByProviderData, GetUsageByProviderErrors, GetUsageByProviderResponses, GetUsageRecentData, GetUsageRecentErrors, GetUsageRecentResponses, GetUsageSummaryData, GetUsageSummaryErrors, GetUsageSummaryResponses, GetUsageTimeseriesData, GetUsageTimeseriesErrors, GetUsageTimeseriesResponses, GetUsageTopModelsData, GetUsageTopModelsErrors, GetUsageTopModelsResponses, GetVisitorByGuidData, GetVisitorByGuidErrors, GetVisitorByGuidResponses, GetVisitorByIdData, GetVisitorByIdErrors, GetVisitorByIdResponses, GetVisitorDetailsData, GetVisitorDetailsErrors, GetVisitorDetailsResponses, GetVisitorFacetsData, GetVisitorFacetsErrors, GetVisitorFacetsResponses, GetVisitorInfoData, GetVisitorInfoErrors, GetVisitorInfoResponses, GetVisitorJourneyData, GetVisitorJourneyErrors, GetVisitorJourneyResponses, GetVisitorsData, GetVisitorsErrors, GetVisitorSessionsData, GetVisitorSessionsErrors, GetVisitorSessionsResponses, GetVisitorsResponses, GetVisitorStatsData, GetVisitorStatsErrors, GetVisitorStatsResponses, GetWebhookData, GetWebhookErrors, GetWebhookResponses, GrantProjectAccessData, GrantProjectAccessErrors, GrantProjectAccessResponses, HandleGitProviderOauthCallbackData, HandleGitProviderOauthCallbackErrors, HasAnalyticsEventsData, HasAnalyticsEventsErrors, HasAnalyticsEventsResponses, HasErrorGroupsData, HasErrorGroupsErrors, HasErrorGroupsResponses, HasPerformanceMetricsData, HasPerformanceMetricsErrors, HasPerformanceMetricsResponses, ImportExternalServiceData, ImportExternalServiceErrors, ImportExternalServiceResponses, IngestLogsByPathData, IngestLogsByPathErrors, IngestLogsByPathResponses, IngestLogsData, IngestLogsErrors, IngestLogsResponses, IngestMetricsByPathData, IngestMetricsByPathErrors, IngestMetricsByPathResponses, IngestMetricsData, IngestMetricsErrors, IngestMetricsResponses, IngestSentryEnvelopeData, IngestSentryEnvelopeErrors, IngestSentryEnvelopeResponses, IngestSentryEventData, IngestSentryEventErrors, IngestSentryEventResponses, IngestTracesByPathData, IngestTracesByPathErrors, IngestTracesByPathResponses, IngestTracesData, IngestTracesErrors, IngestTracesResponses, InitSessionReplayData, InitSessionReplayErrors, InitSessionReplayResponses, JobLogsData, JobLogsErrors, JobLogsResponses, JobStatusData, JobStatusErrors, JobStatusResponses, KillJobData, KillJobErrors, KillJobResponses, KvDelData, KvDelErrors, KvDelResponses, KvDisableData, KvDisableErrors, KvDisableResponses, KvEnableData, KvEnableErrors, KvEnableResponses, KvExpireData, KvExpireErrors, KvExpireResponses, KvGetData, KvGetErrors, KvGetResponses, KvIncrData, KvIncrErrors, KvIncrResponses, KvKeysData, KvKeysErrors, KvKeysResponses, KvSetData, KvSetErrors, KvSetResponses, KvStatusData, KvStatusErrors, KvStatusResponses, KvTtlData, KvTtlErrors, KvTtlResponses, KvUpdateData, KvUpdateErrors, KvUpdateResponses, LatestRunForSourceData, LatestRunForSourceErrors, LatestRunForSourceResponses, LinkCustomDomainToCertificateData, LinkCustomDomainToCertificateErrors, LinkCustomDomainToCertificateResponses, LinkServiceToProjectData, LinkServiceToProjectErrors, LinkServiceToProjectResponses, ListAgentRunsData, ListAgentRunsErrors, ListAgentRunsResponses, ListAgentsData, ListAgentsErrors, ListAgentsResponses, ListAiProvidersData, ListAiProvidersErrors, ListAiProvidersResponses, ListAlertRulesData, ListAlertRulesErrors, ListAlertRulesResponses, ListAlertsData, ListAlertsErrors, ListAlertsResponses, ListAllConversationsData, ListAllConversationsErrors, ListAllConversationsResponses, ListAllRunsData, ListAllRunsErrors, ListAllRunsResponses, ListApiKeysData, ListApiKeysErrors, ListApiKeysResponses, ListAuditLogsData, ListAuditLogsErrors, ListAuditLogsResponses, ListAvailableContainersData, ListAvailableContainersErrors, ListAvailableContainersResponses, ListBackupAlertsData, ListBackupAlertsErrors, ListBackupAlertsResponses, ListBackupChildrenData, ListBackupChildrenErrors, ListBackupChildrenResponses, ListBackupSchedulesData, ListBackupSchedulesErrors, ListBackupSchedulesResponses, ListBackupsForScheduleData, ListBackupsForScheduleErrors, ListBackupsForScheduleResponses, ListCommitsByRepositoryIdData, ListCommitsByRepositoryIdErrors, ListCommitsByRepositoryIdResponses, ListConnectionsData, ListConnectionsErrors, ListConnectionsResponses, ListContainersAtPathData, ListContainersAtPathErrors, ListContainersAtPathResponses, ListContainersData, ListContainersErrors, ListContainersResponses, ListConversationsData, ListConversationsErrors, ListConversationsResponses, ListCustomDomainsForProjectData, ListCustomDomainsForProjectErrors, ListCustomDomainsForProjectResponses, ListDashboardsData, ListDashboardsErrors, ListDashboardsResponses, ListDeliveriesData, ListDeliveriesErrors, ListDeliveriesResponses, ListDeploymentContainerLogsData, ListDeploymentContainerLogsErrors, ListDeploymentContainerLogsResponses, ListDeploymentTokensData, ListDeploymentTokensErrors, ListDeploymentTokensResponses, ListDnsProvidersData, ListDnsProvidersErrors, ListDnsProvidersResponses, ListDomainsData, ListDomainsErrors, ListDomainsResponses, ListDsnsData, ListDsnsErrors, ListDsnsResponses, ListEmailDomainsData, ListEmailDomainsErrors, ListEmailDomainsResponses, ListEmailProvidersData, ListEmailProvidersErrors, ListEmailProvidersResponses, ListEmailsData, ListEmailsErrors, ListEmailsResponses, ListEnrollmentTokensData, ListEnrollmentTokensErrors, ListEnrollmentTokensResponses, ListEntitiesData, ListEntitiesErrors, ListEntitiesResponses, ListErrorEventsData, ListErrorEventsErrors, ListErrorEventsResponses, ListErrorGroupsData, ListErrorGroupsErrors, ListErrorGroupsResponses, ListEventsData, ListEventsResponses, ListEventTypesData, ListEventTypesResponses, ListExternalImagesData, ListExternalImagesErrors, ListExternalImagesResponses, ListExternalPluginsData, ListExternalPluginsErrors, ListExternalPluginsResponses, ListExternalServiceBackupsData, ListExternalServiceBackupsErrors, ListExternalServiceBackupsResponses, ListFlagsData, ListFlagsErrors, ListFlagsResponses, ListFunnelsData, ListFunnelsErrors, ListFunnelsResponses, ListGitProvidersData, ListGitProvidersErrors, ListGitProvidersResponses, ListGlobalMcpsData, ListGlobalMcpsErrors, ListGlobalMcpsResponses, ListGlobalSkillsData, ListGlobalSkillsErrors, ListGlobalSkillsResponses, ListIncidentsData, ListIncidentsErrors, ListIncidentsResponses, ListInsightsData, ListInsightsErrors, ListInsightsResponses, ListIpAccessControlData, ListIpAccessControlErrors, ListIpAccessControlResponses, ListJobsData, ListJobsErrors, ListJobsResponses, ListKnownAiAgentsData, ListKnownAiAgentsErrors, ListKnownAiAgentsResponses, ListManagedDomainsData, ListManagedDomainsErrors, ListManagedDomainsResponses, ListMcpsData, ListMcpsErrors, ListMcpsResponses, ListMetricLabelKeysData, ListMetricLabelKeysErrors, ListMetricLabelKeysResponses, ListMetricLabelValuesData, ListMetricLabelValuesErrors, ListMetricLabelValuesResponses, ListMetricNamesData, ListMetricNamesErrors, ListMetricNamesResponses, ListModelsData, ListModelsErrors, ListModelsResponses, ListMonitorsData, ListMonitorsErrors, ListMonitorsResponses, ListNotificationProvidersData, ListNotificationProvidersErrors, ListNotificationProvidersResponses, ListOidcProvidersData, ListOidcProvidersResponses, ListOidcProviderUsersData, ListOidcProviderUsersErrors, ListOidcProviderUsersResponses, ListOidcRoleMappingsData, ListOidcRoleMappingsResponses, ListOnDemandCertsData, ListOnDemandCertsErrors, ListOnDemandCertsResponses, ListOrdersData, ListOrdersErrors, ListOrdersResponses, ListPeersData, ListPeersErrors, ListPeersResponses, ListPendingActionsData, ListPendingActionsErrors, ListPendingActionsResponses, ListPgUpgradesData, ListPgUpgradesErrors, ListPgUpgradesResponses, ListPresetsData, ListPresetsErrors, ListPresetsResponses, ListProjectAccessData, ListProjectAccessErrors, ListProjectAccessResponses, ListProjectAlarmsData, ListProjectAlarmsErrors, ListProjectAlarmsResponses, ListProjectScansData, ListProjectScansErrors, ListProjectScansResponses, ListProjectSecretsData, ListProjectSecretsErrors, ListProjectSecretsResponses, ListProjectServicesData, ListProjectServicesErrors, ListProjectServicesResponses, ListProjectTemplatesData, ListProjectTemplatesErrors, ListProjectTemplatesResponses, ListProjectTemplateTagsData, ListProjectTemplateTagsErrors, ListProjectTemplateTagsResponses, ListProviderKeysData, ListProviderKeysErrors, ListProviderKeysResponses, ListProviderZonesData, ListProviderZonesErrors, ListProviderZonesResponses, ListPublicProvidersData, ListPublicProvidersResponses, ListReleaseFilesData, ListReleaseFilesErrors, ListReleaseFilesResponses, ListReleasesData, ListReleasesErrors, ListReleasesResponses, ListRemoteExternalImagesData, ListRemoteExternalImagesErrors, ListRemoteExternalImagesResponses, ListRepositoriesByConnectionData, ListRepositoriesByConnectionErrors, ListRepositoriesByConnectionResponses, ListRepositoriesByProviderData, ListRepositoriesByProviderErrors, ListRepositoriesByProviderResponses, ListRestoreRunsForServiceData, ListRestoreRunsForServiceResponses, ListRootContainersData, ListRootContainersErrors, ListRootContainersResponses, ListRoutesData, ListRoutesErrors, ListRoutesResponses, ListS3SourcesData, ListS3SourcesErrors, ListS3SourcesResponses, ListSandboxesData, ListSandboxesResponses, ListScheduleRunJobsData, ListScheduleRunJobsErrors, ListScheduleRunJobsResponses, ListScheduleRunsData, ListScheduleRunsErrors, ListScheduleRunsResponses, ListScheduleServicesData, ListScheduleServicesErrors, ListScheduleServicesResponses, ListSecretsData, ListSecretsErrors, ListSecretsResponses, ListServiceHealthStatusesData, ListServiceHealthStatusesErrors, ListServiceHealthStatusesResponses, ListServiceProjectsData, ListServiceProjectsErrors, ListServiceProjectsResponses, ListServiceSchedulesData, ListServiceSchedulesErrors, ListServiceSchedulesResponses, ListServicesData, ListServicesErrors, ListServicesResponses, ListSkillsData, ListSkillsErrors, ListSkillsResponses, ListSourceBackupsData, ListSourceBackupsErrors, ListSourceBackupsResponses, ListSourceFilesData, ListSourceFilesErrors, ListSourceFilesResponses, ListSourceMapsData, ListSourceMapsErrors, ListSourceMapsResponses, ListSourcesData, ListSourcesErrors, ListSourcesResponses, ListStaticBundlesData, ListStaticBundlesErrors, ListStaticBundlesResponses, ListSyncedRepositoriesData, ListSyncedRepositoriesErrors, ListSyncedRepositoriesResponses, ListTeamMembersData, ListTeamMembersErrors, ListTeamMembersResponses, ListTeamProjectsData, ListTeamProjectsErrors, ListTeamProjectsResponses, ListTeamsData, ListTeamsErrors, ListTeamsResponses, ListUsersData, ListUsersErrors, ListUsersResponses, ListWebhooksData, ListWebhooksErrors, ListWebhooksResponses, LoginData, LoginErrors, LoginResponses, LogoutData, LogoutErrors, LogoutResponses, LookupDnsARecordsData, LookupDnsARecordsErrors, LookupDnsARecordsResponses, MintEnrollmentTokenData, MintEnrollmentTokenErrors, MintEnrollmentTokenResponses, MkdirData, MkdirErrors, MkdirResponses, NodeHeartbeatData, NodeHeartbeatErrors, NodeHeartbeatResponses, NodeMetricsGetRangeData, NodeMetricsGetRangeErrors, NodeMetricsGetRangeResponses, ObservabilityFullEventData, ObservabilityFullEventErrors, ObservabilityFullEventResponses, ObservabilityListEventsData, ObservabilityListEventsErrors, ObservabilityListEventsResponses, OidcCallbackData, PatchAdminGateData, PatchAdminGateErrors, PatchAdminGateResponses, PatchPreviewGatewaySettingsData, PatchPreviewGatewaySettingsResponses, PauseDeploymentData, PauseDeploymentErrors, PauseDeploymentResponses, PauseSandboxData, PauseSandboxErrors, PauseSandboxResponses, PlanRestoreData, PlanRestoreErrors, PlanRestoreResponses, PostDnsAckData, PostDnsAckErrors, PostDnsAckResponses, PreviewAlertData, PreviewAlertErrors, PreviewAlertResponses, PreviewFunnelMetricsData, PreviewFunnelMetricsErrors, PreviewFunnelMetricsResponses, PreviewHostnameModeData, PreviewHostnameModeErrors, PreviewHostnameModeResponses, PromoteClusterMemberData, PromoteClusterMemberErrors, PromoteClusterMemberResponses, PromoteDeploymentData, PromoteDeploymentErrors, PromoteDeploymentResponses, ProvisionDomainData, ProvisionDomainErrors, ProvisionDomainResponses, PurgeProjectLogsData, PurgeProjectLogsErrors, PurgeProjectLogsResponses, PushExternalImageData, PushExternalImageErrors, PushExternalImageResponses, QueryDataData, QueryDataErrors, QueryDataResponses, QueryGenaiTracesData, QueryGenaiTracesErrors, QueryGenaiTracesResponses, QueryLogsData, QueryLogsErrors, QueryLogsResponses, QueryMetricsData, QueryMetricsErrors, QueryMetricsResponses, QueryTracesData, QueryTracesErrors, QueryTracesResponses, QueryTraceSummariesData, QueryTraceSummariesErrors, QueryTraceSummariesResponses, ReadFileData, ReadFileErrors, ReadFileResponses, ReAnalyzeData, ReAnalyzeErrors, ReAnalyzeResponses, RecordConsoleEventData, RecordConsoleEventErrors, RecordConsoleEventResponses, RecordEventMetricsData, RecordEventMetricsErrors, RecordEventMetricsResponses, RecordFlagExposureData, RecordFlagExposureErrors, RecordFlagExposureResponses, RecordSpeedMetricsData, RecordSpeedMetricsErrors, RecordSpeedMetricsResponses, RefreshRouteTableData, RefreshRouteTableErrors, RefreshRouteTableResponses, RegenerateDsnData, RegenerateDsnErrors, RegenerateDsnResponses, RegisterExternalImageData, RegisterExternalImageErrors, RegisterExternalImageResponses, RegisterNodeData, RegisterNodeErrors, RegisterNodeResponses, ReinstallGitlabWebhookData, ReinstallGitlabWebhookErrors, ReinstallGitlabWebhookResponses, RejectPendingActionData, RejectPendingActionErrors, RejectPendingActionResponses, ReloadPluginsData, ReloadPluginsErrors, ReloadPluginsResponses, RemoveClusterMemberData, RemoveClusterMemberErrors, RemoveClusterMemberResponses, RemoveManagedDomainData, RemoveManagedDomainErrors, RemoveManagedDomainResponses, RemoveRoleData, RemoveRoleErrors, RemoveRoleResponses, RemoveTeamMemberData, RemoveTeamMemberErrors, RemoveTeamMemberResponses, RenameConversationData, RenameConversationErrors, RenameConversationResponses, RenewDomainData, RenewDomainErrors, RenewDomainResponses, RequestPasswordResetData, RequestPasswordResetErrors, RequestPasswordResetResponses, ResetPasswordData, ResetPasswordErrors, ResetPasswordResponses, ResizeSandboxData, ResizeSandboxErrors, ResizeSandboxResponses, ResolveAlarmData, ResolveAlarmErrors, ResolveAlarmResponses, RestartContainerData, RestartContainerErrors, RestartContainerResponses, RestartPreviewGatewayData, RestartPreviewGatewayResponses, RestartSandboxData, RestartSandboxErrors, RestartSandboxResponses, RestoreFlagData, RestoreFlagErrors, RestoreFlagResponses, RestoreUserData, RestoreUserErrors, RestoreUserResponses, ResumeDeploymentData, ResumeDeploymentErrors, ResumeDeploymentResponses, ResumeSandboxData, ResumeSandboxErrors, ResumeSandboxResponses, RetryClusterData, RetryClusterErrors, RetryClusterResponses, RetryDeliveryData, RetryDeliveryErrors, RetryDeliveryResponses, RetryPgUpgradeData, RetryPgUpgradeErrors, RetryPgUpgradeResponses, RetryRunData, RetryRunErrors, RetryRunResponses, RevealGlobalMcpConfigData, RevealGlobalMcpConfigErrors, RevealGlobalMcpConfigResponses, RevealMcpConfigData, RevealMcpConfigErrors, RevealMcpConfigResponses, RevealNotificationProviderConfigData, RevealNotificationProviderConfigErrors, RevealNotificationProviderConfigResponses, RevealServiceParameterData, RevealServiceParameterErrors, RevealServiceParameterResponses, RevenueCreateIntegrationData, RevenueCreateIntegrationErrors, RevenueCreateIntegrationResponses, RevenueDeleteIntegrationData, RevenueDeleteIntegrationResponses, RevenueGlobalEventsData, RevenueGlobalEventsResponses, RevenueImportInvoicesCsvData, RevenueImportInvoicesCsvErrors, RevenueImportInvoicesCsvResponses, RevenueImportSubscriptionsCsvData, RevenueImportSubscriptionsCsvErrors, RevenueImportSubscriptionsCsvResponses, RevenueListIntegrationsData, RevenueListIntegrationsResponses, RevenueListProvidersData, RevenueListProvidersResponses, RevenueMetricsCustomersData, RevenueMetricsCustomersResponses, RevenueMetricsGlobalMrrData, RevenueMetricsGlobalMrrResponses, RevenueMetricsGlobalSummaryData, RevenueMetricsGlobalSummaryResponses, RevenueMetricsMrrData, RevenueMetricsMrrResponses, RevenueMetricsSummaryData, RevenueMetricsSummaryResponses, RevenueRecentEventsData, RevenueRecentEventsResponses, RevenueRotateTokenData, RevenueRotateTokenResponses, RevenueUpdateConfigData, RevenueUpdateConfigErrors, RevenueUpdateConfigResponses, RevenueUpdateSecretData, RevenueUpdateSecretErrors, RevenueUpdateSecretResponses, RevokeDsnData, RevokeDsnErrors, RevokeDsnResponses, RevokeEnrollmentTokenData, RevokeEnrollmentTokenErrors, RevokeEnrollmentTokenResponses, RevokeJoinTokenData, RevokeJoinTokenErrors, RevokeJoinTokenResponses, RevokeProjectAccessData, RevokeProjectAccessErrors, RevokeProjectAccessResponses, RollbackPgUpgradeData, RollbackPgUpgradeErrors, RollbackPgUpgradeResponses, RollbackToDeploymentData, RollbackToDeploymentErrors, RollbackToDeploymentResponses, RootfsGcData, RootfsGcResponses, RootfsReportData, RootfsReportResponses, RotateApiKeyData, RotateApiKeyErrors, RotateApiKeyResponses, RotateDeploymentTokenData, RotateDeploymentTokenErrors, RotateDeploymentTokenResponses, RunBackupForSourceData, RunBackupForSourceErrors, RunBackupForSourceResponses, RunConnectionHealthCheckData, RunConnectionHealthCheckErrors, RunConnectionHealthCheckResponses, RunExternalServiceBackupData, RunExternalServiceBackupErrors, RunExternalServiceBackupResponses, RunScheduleNowData, RunScheduleNowErrors, RunScheduleNowResponses, SandboxCreatePreviewLinkData, SandboxCreatePreviewLinkErrors, SandboxCreatePreviewLinkResponses, SaveAgentTokenData, SaveAgentTokenErrors, SaveAgentTokenResponses, SaveAiProviderCredentialData, SaveAiProviderCredentialErrors, SaveAiProviderCredentialResponses, SearchLogsData, SearchLogsErrors, SearchLogsResponses, SendEmailData, SendEmailErrors, SendEmailResponses, SetDefaultS3SourceData, SetDefaultS3SourceErrors, SetDefaultS3SourceResponses, SetFlagEnvironmentData, SetFlagEnvironmentErrors, SetFlagEnvironmentResponses, SetPreviewPasswordData, SetPreviewPasswordErrors, SetPreviewPasswordResponses, SetupDnsChallengeData, SetupDnsChallengeErrors, SetupDnsChallengeResponses, SetupDnsData, SetupDnsErrors, SetupDnsResponses, SetupEmailTrackingData, SetupEmailTrackingErrors, SetupEmailTrackingResponses, SetupMfaData, SetupMfaErrors, SetupMfaResponses, SleepEnvironmentData, SleepEnvironmentErrors, SleepEnvironmentResponses, SmokeTestAgentData, SmokeTestAgentErrors, SmokeTestAgentResponses, SourceSandboxData, SourceSandboxErrors, SourceSandboxResponses, StartAnalysisData, StartAnalysisErrors, StartAnalysisResponses, StartContainerData, StartContainerErrors, StartContainerResponses, StartFixData, StartFixErrors, StartFixResponses, StartGitProviderOauthData, StartGitProviderOauthErrors, StartOidcLoginBySlugData, StartOidcLoginBySlugErrors, StartPgUpgradeData, StartPgUpgradeErrors, StartPgUpgradeResponses, StartRestoreData, StartRestoreErrors, StartRestoreResponses, StartServiceData, StartServiceErrors, StartServiceResponses, StatPathData, StatPathErrors, StatPathResponses, StopContainerData, StopContainerErrors, StopContainerResponses, StopSandboxData, StopSandboxErrors, StopSandboxResponses, StopServiceData, StopServiceErrors, StopServiceResponses, StreamContainerMetricsData, StreamContainerMetricsErrors, StreamContainerMetricsResponses, StreamEventsData, StreamEventsErrors, StreamEventsResponses, StreamRunEventsData, StreamRunEventsErrors, StreamRunEventsResponses, SyncRepositoriesData, SyncRepositoriesErrors, SyncRepositoriesResponses, TailDeploymentJobLogsData, TailDeploymentJobLogsErrors, TailLogsData, TailLogsErrors, TailLogsResponses, TeardownDeploymentData, TeardownDeploymentErrors, TeardownDeploymentResponses, TeardownEnvironmentData, TeardownEnvironmentErrors, TeardownEnvironmentResponses, TestNotificationProviderData, TestNotificationProviderErrors, TestNotificationProviderResponses, TestOidcProviderData, TestOidcProviderResponses, TestProviderConnectionData, TestProviderConnectionErrors, TestProviderConnectionResponses, TestProviderData, TestProviderErrors, TestProviderKeyByIdData, TestProviderKeyByIdErrors, TestProviderKeyByIdResponses, TestProviderKeyInlineData, TestProviderKeyInlineErrors, TestProviderKeyInlineResponses, TestProviderResponses, TestS3ConnectionPreviewData, TestS3ConnectionPreviewErrors, TestS3ConnectionPreviewResponses, TestS3SourceConnectionData, TestS3SourceConnectionErrors, TestS3SourceConnectionResponses, TrackClickData, TrackClickErrors, TrackOpenData, TrackOpenErrors, TrackOpenResponses, TriggerAgentData, TriggerAgentErrors, TriggerAgentResponses, TriggerProjectPipelineData, TriggerProjectPipelineErrors, TriggerProjectPipelineResponses, TriggerScanData, TriggerScanErrors, TriggerScanResponses, TriggerServiceHealthCheckData, TriggerServiceHealthCheckErrors, TriggerServiceHealthCheckResponses, TriggerWeeklyDigestData, TriggerWeeklyDigestErrors, TriggerWeeklyDigestResponses, UnlinkServiceFromProjectData, UnlinkServiceFromProjectErrors, UnlinkServiceFromProjectResponses, UpdateAgentData, UpdateAgentErrors, UpdateAgentResponses, UpdateAiProviderData, UpdateAiProviderErrors, UpdateAiProviderResponses, UpdateAlertData, UpdateAlertErrors, UpdateAlertResponses, UpdateAlertRuleData, UpdateAlertRuleErrors, UpdateAlertRuleResponses, UpdateApiKeyData, UpdateApiKeyErrors, UpdateApiKeyResponses, UpdateAutomaticDeployData, UpdateAutomaticDeployErrors, UpdateAutomaticDeployResponses, UpdateBackupScheduleData, UpdateBackupScheduleErrors, UpdateBackupScheduleResponses, UpdateCloudflareProviderData, UpdateCloudflareProviderErrors, UpdateCloudflareProviderResponses, UpdateConnectionTokenData, UpdateConnectionTokenErrors, UpdateConnectionTokenResponses, UpdateCustomDomainData, UpdateCustomDomainErrors, UpdateCustomDomainResponses, UpdateDashboardData, UpdateDashboardErrors, UpdateDashboardResponses, UpdateDeploymentTokenData, UpdateDeploymentTokenErrors, UpdateDeploymentTokenResponses, UpdateEmailProviderData, UpdateEmailProviderErrors, UpdateEmailProviderResponses, UpdateEnvironmentSettingsData, UpdateEnvironmentSettingsErrors, UpdateEnvironmentSettingsResponses, UpdateEnvironmentSubdomainData, UpdateEnvironmentSubdomainErrors, UpdateEnvironmentSubdomainResponses, UpdateEnvironmentVariableData, UpdateEnvironmentVariableErrors, UpdateEnvironmentVariableResponses, UpdateErrorGroupData, UpdateErrorGroupErrors, UpdateErrorGroupResponses, UpdateFlagData, UpdateFlagErrors, UpdateFlagResponses, UpdateFunnelData, UpdateFunnelErrors, UpdateFunnelResponses, UpdateGitProviderCredentialsData, UpdateGitProviderCredentialsErrors, UpdateGitProviderCredentialsResponses, UpdateGitSettingsData, UpdateGitSettingsErrors, UpdateGitSettingsResponses, UpdateGlobalMcpData, UpdateGlobalMcpErrors, UpdateGlobalMcpResponses, UpdateGlobalSkillData, UpdateGlobalSkillErrors, UpdateGlobalSkillResponses, UpdateIncidentStatusData, UpdateIncidentStatusErrors, UpdateIncidentStatusResponses, UpdateIpAccessControlData, UpdateIpAccessControlErrors, UpdateIpAccessControlResponses, UpdateManagedDomainData, UpdateManagedDomainErrors, UpdateManagedDomainResponses, UpdateMcpData, UpdateMcpErrors, UpdateMcpResponses, UpdateNotificationEmailProviderData, UpdateNotificationEmailProviderErrors, UpdateNotificationEmailProviderResponses, UpdateNotificationProviderData, UpdateNotificationProviderErrors, UpdateNotificationProviderResponses, UpdateOidcProviderData, UpdateOidcProviderResponses, UpdatePreferencesData, UpdatePreferencesErrors, UpdatePreferencesResponses, UpdateProjectData, UpdateProjectDeploymentConfigData, UpdateProjectDeploymentConfigErrors, UpdateProjectDeploymentConfigResponses, UpdateProjectErrors, UpdateProjectResponses, UpdateProjectSecretData, UpdateProjectSecretErrors, UpdateProjectSecretResponses, UpdateProjectSettingsData, UpdateProjectSettingsErrors, UpdateProjectSettingsResponses, UpdateProviderData, UpdateProviderErrors, UpdateProviderKeyData, UpdateProviderKeyErrors, UpdateProviderKeyResponses, UpdateProviderResponses, UpdateRouteData, UpdateRouteErrors, UpdateRouteResponses, UpdateS3SourceData, UpdateS3SourceErrors, UpdateS3SourceResponses, UpdateSelfData, UpdateSelfErrors, UpdateSelfResponses, UpdateServiceData, UpdateServiceErrors, UpdateServiceResourcesData, UpdateServiceResourcesErrors, UpdateServiceResourcesResponses, UpdateServiceResponses, UpdateSessionDurationData, UpdateSessionDurationErrors, UpdateSessionDurationResponses, UpdateSettingsData, UpdateSettingsErrors, UpdateSettingsResponses, UpdateSkillData, UpdateSkillErrors, UpdateSkillResponses, UpdateSlackProviderData, UpdateSlackProviderErrors, UpdateSlackProviderResponses, UpdateSpeedMetricsData, UpdateSpeedMetricsErrors, UpdateSpeedMetricsResponses, UpdateTeamData, UpdateTeamErrors, UpdateTeamMemberRoleData, UpdateTeamMemberRoleErrors, UpdateTeamMemberRoleResponses, UpdateTeamResponses, UpdateUserData, UpdateUserErrors, UpdateUserResponses, UpdateWebhookData, UpdateWebhookErrors, UpdateWebhookProviderData, UpdateWebhookProviderErrors, UpdateWebhookProviderResponses, UpdateWebhookResponses, UpgradePreviewGatewayData, UpgradePreviewGatewayResponses, UpgradeServiceData, UpgradeServiceErrors, UpgradeServiceResponses, UploadGlobalSkillData, UploadGlobalSkillErrors, UploadGlobalSkillResponses, UploadReleaseFileData, UploadReleaseFileErrors, UploadReleaseFileResponses, UploadSkillData, UploadSkillErrors, UploadSkillResponses, UploadSourceFileData, UploadSourceFileErrors, UploadSourceFileResponses, UploadSourceMapData, UploadSourceMapErrors, UploadSourceMapResponses, UploadStaticBundleData, UploadStaticBundleErrors, UploadStaticBundleResponses, UpsertSecretData, UpsertSecretErrors, UpsertSecretResponses, ValidateConnectionData, ValidateConnectionErrors, ValidateConnectionResponses, ValidateEmailData, ValidateEmailErrors, ValidateEmailResponses, VerifyAndEnableMfaData, VerifyAndEnableMfaErrors, VerifyAndEnableMfaResponses, VerifyDomainData, VerifyDomainErrors, VerifyDomainResponses, VerifyEmailData, VerifyEmailErrors, VerifyEmailResponses, VerifyManagedDomainData, VerifyManagedDomainErrors, VerifyManagedDomainResponses, VerifyMfaChallengeData, VerifyMfaChallengeErrors, VerifyMfaChallengeResponses, VerifyStepUpData, VerifyStepUpErrors, VerifyStepUpResponses, WakeEnvironmentData, WakeEnvironmentErrors, WakeEnvironmentResponses, WebhookTriggerData, WebhookTriggerErrors, WebhookTriggerResponses, WorkflowDryRunData, WorkflowDryRunErrors, WorkflowDryRunResponses, WriteFileData, WriteFileErrors, WriteFileResponses, WriteFilesData, WriteFilesErrors, WriteFilesResponses } from './types.gen'; +import type { AcknowledgeAlarmData, AcknowledgeAlarmErrors, AcknowledgeAlarmResponses, ActivateAiProviderData, ActivateAiProviderErrors, ActivateAiProviderResponses, ActivateApiKeyData, ActivateApiKeyErrors, ActivateApiKeyResponses, ActivateConnectionData, ActivateConnectionErrors, ActivateConnectionResponses, ActivateProviderData, ActivateProviderErrors, ActivateProviderResponses, AddClusterMemberData, AddClusterMemberErrors, AddClusterMemberResponses, AddContextData, AddContextErrors, AddContextResponses, AddEnvironmentDomainData, AddEnvironmentDomainErrors, AddEnvironmentDomainResponses, AddEventsData, AddEventsErrors, AddEventsResponses, AddManagedDomainData, AddManagedDomainErrors, AddManagedDomainResponses, AddSessionReplayEventsData, AddSessionReplayEventsErrors, AddSessionReplayEventsResponses, AddTeamMemberData, AddTeamMemberErrors, AddTeamMemberResponses, AdminDrainNodeData, AdminDrainNodeErrors, AdminDrainNodeResponses, AdminDrainStatusData, AdminDrainStatusErrors, AdminDrainStatusResponses, AdminGetNodeData, AdminGetNodeErrors, AdminGetNodeResponses, AdminListNodeContainersData, AdminListNodeContainersErrors, AdminListNodeContainersResponses, AdminListNodesData, AdminListNodesErrors, AdminListNodesResponses, AdminRemoveNodeData, AdminRemoveNodeErrors, AdminRemoveNodeResponses, AdminUndrainNodeData, AdminUndrainNodeErrors, AdminUndrainNodeResponses, ApplyHostnameModeData, ApplyHostnameModeErrors, ApplyHostnameModeResponses, ArchiveConversationData, ArchiveConversationErrors, ArchiveConversationResponses, ArchiveFlagData, ArchiveFlagErrors, ArchiveFlagResponses, AssignRoleData, AssignRoleErrors, AssignRoleResponses, AttachScheduleServicesData, AttachScheduleServicesErrors, AttachScheduleServicesResponses, BlobCopyData, BlobCopyErrors, BlobCopyResponses, BlobDeleteData, BlobDeleteErrors, BlobDeleteResponses, BlobDisableData, BlobDisableErrors, BlobDisableResponses, BlobDownloadData, BlobDownloadErrors, BlobDownloadResponses, BlobEnableData, BlobEnableErrors, BlobEnableResponses, BlobHeadData, BlobHeadErrors, BlobHeadResponses, BlobListData, BlobListErrors, BlobListResponses, BlobPutData, BlobPutErrors, BlobPutResponses, BlobStatusData, BlobStatusErrors, BlobStatusResponses, BlobUpdateData, BlobUpdateErrors, BlobUpdateResponses, CancelBackupData, CancelBackupErrors, CancelBackupResponses, CancelData, CancelDeploymentData, CancelDeploymentErrors, CancelDeploymentResponses, CancelDomainOrderData, CancelDomainOrderErrors, CancelDomainOrderResponses, CancelErrors, CancelPgUpgradeData, CancelPgUpgradeErrors, CancelPgUpgradeResponses, CancelResponses, CancelRunData, CancelRunErrors, CancelRunResponses, CancelScheduleRunData, CancelScheduleRunErrors, CancelScheduleRunResponses, ChangePasswordSelfData, ChangePasswordSelfErrors, ChangePasswordSelfResponses, ChangeProjectSourceData, ChangeProjectSourceErrors, ChangeProjectSourceResponses, ChatCompletionsData, ChatCompletionsErrors, ChatCompletionsResponses, CheckAnalyticsHasEventsData, CheckAnalyticsHasEventsErrors, CheckAnalyticsHasEventsResponses, CheckCommitExistsData, CheckCommitExistsErrors, CheckCommitExistsResponses, CheckDomainStatusData, CheckDomainStatusErrors, CheckDomainStatusResponses, CheckExplorerSupportData, CheckExplorerSupportErrors, CheckExplorerSupportResponses, CheckIpBlockedData, CheckIpBlockedErrors, CheckIpBlockedResponses, CheckProviderDeletionSafetyData, CheckProviderDeletionSafetyErrors, CheckProviderDeletionSafetyResponses, ChunkUploadOptionsData, ChunkUploadOptionsResponses, CleanupExpiredBackupsData, CleanupExpiredBackupsErrors, CleanupExpiredBackupsResponses, ClearPreviewPasswordData, ClearPreviewPasswordErrors, ClearPreviewPasswordResponses, CliDeviceApproveData, CliDeviceApproveErrors, CliDeviceApproveResponses, CliDeviceDenyData, CliDeviceDenyErrors, CliDeviceDenyResponses, CliDeviceLookupData, CliDeviceLookupErrors, CliDeviceLookupResponses, CliDevicePollData, CliDevicePollErrors, CliDevicePollResponses, CliDeviceStartData, CliDeviceStartErrors, CliDeviceStartResponses, CliLogoutData, CliLogoutErrors, CliLogoutResponses, CmdData, CmdErrors, CmdKillData, CmdKillErrors, CmdKillResponses, CmdLogsData, CmdLogsErrors, CmdLogsResponses, CmdResponses, ConfirmPendingActionData, ConfirmPendingActionErrors, ConfirmPendingActionResponses, ContainerMetricsGetHistoryData, ContainerMetricsGetHistoryErrors, ContainerMetricsGetHistoryResponses, CreateAgentData, CreateAgentErrors, CreateAgentResponses, CreateAlertData, CreateAlertErrors, CreateAlertResponses, CreateAlertRuleData, CreateAlertRuleErrors, CreateAlertRuleResponses, CreateApiKeyData, CreateApiKeyErrors, CreateApiKeyResponses, CreateBackupScheduleData, CreateBackupScheduleErrors, CreateBackupScheduleResponses, CreateBitbucketProviderData, CreateBitbucketProviderErrors, CreateBitbucketProviderResponses, CreateCloudflareProviderData, CreateCloudflareProviderErrors, CreateCloudflareProviderResponses, CreateConversationData, CreateConversationErrors, CreateConversationResponses, CreateCustomDomainData, CreateCustomDomainErrors, CreateCustomDomainResponses, CreateDashboardData, CreateDashboardErrors, CreateDashboardResponses, CreateDeploymentTokenData, CreateDeploymentTokenErrors, CreateDeploymentTokenResponses, CreateDnsProviderData, CreateDnsProviderErrors, CreateDnsProviderResponses, CreateDomainData, CreateDomainErrors, CreateDomainResponses, CreateDsnData, CreateDsnErrors, CreateDsnResponses, CreateEmailDomainData, CreateEmailDomainErrors, CreateEmailDomainResponses, CreateEmailProviderData, CreateEmailProviderErrors, CreateEmailProviderResponses, CreateEnvironmentData, CreateEnvironmentErrors, CreateEnvironmentResponses, CreateEnvironmentVariableData, CreateEnvironmentVariableErrors, CreateEnvironmentVariableResponses, CreateFlagData, CreateFlagErrors, CreateFlagResponses, CreateFunnelData, CreateFunnelErrors, CreateFunnelResponses, CreateGenericProviderData, CreateGenericProviderErrors, CreateGenericProviderResponses, CreateGiteaPatProviderData, CreateGiteaPatProviderErrors, CreateGiteaPatProviderResponses, CreateGithubPatProviderData, CreateGithubPatProviderErrors, CreateGithubPatProviderResponses, CreateGitlabOauthProviderData, CreateGitlabOauthProviderErrors, CreateGitlabOauthProviderResponses, CreateGitlabPatProviderData, CreateGitlabPatProviderErrors, CreateGitlabPatProviderResponses, CreateGitProviderData, CreateGitProviderErrors, CreateGitProviderResponses, CreateGlobalMcpData, CreateGlobalMcpErrors, CreateGlobalMcpResponses, CreateGlobalSkillData, CreateGlobalSkillErrors, CreateGlobalSkillResponses, CreateIncidentData, CreateIncidentErrors, CreateIncidentResponses, CreateIpAccessControlData, CreateIpAccessControlErrors, CreateIpAccessControlResponses, CreateMcpData, CreateMcpErrors, CreateMcpResponses, CreateMonitorData, CreateMonitorErrors, CreateMonitorResponses, CreateNotificationEmailProviderData, CreateNotificationEmailProviderErrors, CreateNotificationEmailProviderResponses, CreateNotificationProviderData, CreateNotificationProviderErrors, CreateNotificationProviderResponses, CreateOidcProviderData, CreateOidcProviderErrors, CreateOidcProviderResponses, CreateOidcRoleMappingData, CreateOidcRoleMappingResponses, CreateOrRecreateOrderData, CreateOrRecreateOrderErrors, CreateOrRecreateOrderResponses, CreatePlanData, CreatePlanErrors, CreatePlanResponses, CreatePrData, CreatePrErrors, CreateProjectData, CreateProjectErrors, CreateProjectFromTemplateData, CreateProjectFromTemplateErrors, CreateProjectFromTemplateResponses, CreateProjectReleaseData, CreateProjectReleaseErrors, CreateProjectReleaseResponses, CreateProjectResponses, CreateProjectSecretData, CreateProjectSecretErrors, CreateProjectSecretResponses, CreateProviderKeyData, CreateProviderKeyErrors, CreateProviderKeyResponses, CreatePrResponses, CreateReleaseData, CreateReleaseErrors, CreateReleaseResponses, CreateRouteData, CreateRouteErrors, CreateRouteResponses, CreateS3SourceData, CreateS3SourceErrors, CreateS3SourceResponses, CreateSandboxData, CreateSandboxErrors, CreateSandboxResponses, CreateServiceData, CreateServiceErrors, CreateServiceResponses, CreateSkillData, CreateSkillErrors, CreateSkillResponses, CreateSlackProviderData, CreateSlackProviderErrors, CreateSlackProviderResponses, CreateTeamData, CreateTeamErrors, CreateTeamResponses, CreateUserData, CreateUserErrors, CreateUserResponses, CreateWebhookData, CreateWebhookErrors, CreateWebhookProviderData, CreateWebhookProviderErrors, CreateWebhookProviderResponses, CreateWebhookResponses, DeactivateApiKeyData, DeactivateApiKeyErrors, DeactivateApiKeyResponses, DeactivateConnectionData, DeactivateConnectionErrors, DeactivateConnectionResponses, DeactivateProviderData, DeactivateProviderErrors, DeactivateProviderResponses, DeleteAgentData, DeleteAgentErrors, DeleteAgentResponses, DeleteAlertData, DeleteAlertErrors, DeleteAlertResponses, DeleteAlertRuleData, DeleteAlertRuleErrors, DeleteAlertRuleResponses, DeleteApiKeyData, DeleteApiKeyErrors, DeleteApiKeyResponses, DeleteBackupData, DeleteBackupErrors, DeleteBackupResponses, DeleteBackupScheduleData, DeleteBackupScheduleErrors, DeleteBackupScheduleResponses, DeleteConnectionData, DeleteConnectionErrors, DeleteConnectionResponses, DeleteCustomDomainData, DeleteCustomDomainErrors, DeleteCustomDomainResponses, DeleteDashboardData, DeleteDashboardErrors, DeleteDashboardResponses, DeleteDeploymentTokenData, DeleteDeploymentTokenErrors, DeleteDeploymentTokenResponses, DeleteDnsProviderData, DeleteDnsProviderErrors, DeleteDnsProviderResponses, DeleteDomainData, DeleteDomainErrors, DeleteDomainResponses, DeleteEmailDomainData, DeleteEmailDomainErrors, DeleteEmailDomainResponses, DeleteEmailProviderData, DeleteEmailProviderErrors, DeleteEmailProviderResponses, DeleteEnvironmentData, DeleteEnvironmentDomainData, DeleteEnvironmentDomainErrors, DeleteEnvironmentDomainResponses, DeleteEnvironmentErrors, DeleteEnvironmentResponses, DeleteEnvironmentVariableData, DeleteEnvironmentVariableErrors, DeleteEnvironmentVariableResponses, DeleteExternalImageData, DeleteExternalImageErrors, DeleteExternalImageResponses, DeleteFunnelData, DeleteFunnelErrors, DeleteFunnelResponses, DeleteGitProviderData, DeleteGitProviderErrors, DeleteGitProviderResponses, DeleteGlobalMcpData, DeleteGlobalMcpErrors, DeleteGlobalMcpResponses, DeleteGlobalSkillData, DeleteGlobalSkillErrors, DeleteGlobalSkillResponses, DeleteIpAccessControlData, DeleteIpAccessControlErrors, DeleteIpAccessControlResponses, DeleteMcpData, DeleteMcpErrors, DeleteMcpResponses, DeleteMonitorData, DeleteMonitorErrors, DeleteMonitorResponses, DeleteNotificationProviderData, DeleteNotificationProviderErrors, DeleteNotificationProviderResponses, DeleteOidcProviderData, DeleteOidcProviderResponses, DeleteOidcRoleMappingData, DeleteOidcRoleMappingResponses, DeletePreferencesData, DeletePreferencesErrors, DeletePreferencesResponses, DeleteProjectData, DeleteProjectErrors, DeleteProjectResponses, DeleteProjectSecretData, DeleteProjectSecretErrors, DeleteProjectSecretResponses, DeleteProviderKeyData, DeleteProviderKeyErrors, DeleteProviderKeyResponses, DeleteProviderSafelyData, DeleteProviderSafelyErrors, DeleteProviderSafelyResponses, DeleteReleaseSourceFilesData, DeleteReleaseSourceFilesErrors, DeleteReleaseSourceFilesResponses, DeleteReleaseSourceMapsData, DeleteReleaseSourceMapsErrors, DeleteReleaseSourceMapsResponses, DeleteRouteData, DeleteRouteErrors, DeleteRouteResponses, DeleteS3SourceData, DeleteS3SourceErrors, DeleteS3SourceResponses, DeleteScanData, DeleteScanErrors, DeleteScanResponses, DeleteSecretData, DeleteSecretErrors, DeleteSecretResponses, DeleteServiceData, DeleteServiceErrors, DeleteServiceResponses, DeleteSessionReplayData, DeleteSessionReplayErrors, DeleteSessionReplayResponses, DeleteSkillData, DeleteSkillErrors, DeleteSkillResponses, DeleteSourceMapData, DeleteSourceMapErrors, DeleteSourceMapResponses, DeleteStaticBundleData, DeleteStaticBundleErrors, DeleteStaticBundleResponses, DeleteTeamData, DeleteTeamErrors, DeleteTeamResponses, DeleteUserData, DeleteUserErrors, DeleteUserResponses, DeleteWebhookData, DeleteWebhookErrors, DeleteWebhookResponses, DeployFromImageData, DeployFromImageErrors, DeployFromImageResponses, DeployFromImageUploadData, DeployFromImageUploadErrors, DeployFromImageUploadResponses, DeployFromStaticData, DeployFromStaticErrors, DeployFromStaticResponses, DeployFromUploadedSourceData, DeployFromUploadedSourceErrors, DeployFromUploadedSourceResponses, DeploymentMetricsGetLatestData, DeploymentMetricsGetLatestErrors, DeploymentMetricsGetLatestResponses, DeploymentMetricsGetRangeData, DeploymentMetricsGetRangeErrors, DeploymentMetricsGetRangeResponses, DeploymentMetricsToggleData, DeploymentMetricsToggleErrors, DeploymentMetricsToggleResponses, DestroySandboxData, DestroySandboxErrors, DestroySandboxResponses, DetachScheduleServiceData, DetachScheduleServiceErrors, DetachScheduleServiceResponses, DetectPublicPresetsData, DetectPublicPresetsErrors, DetectPublicPresetsResponses, DisableBackupScheduleData, DisableBackupScheduleErrors, DisableBackupScheduleResponses, DisableMfaData, DisableMfaErrors, DisableMfaResponses, DiscoverWorkloadsData, DiscoverWorkloadsErrors, DiscoverWorkloadsResponses, DomainData, DomainErrors, DomainResponses, DownloadGlobalSkillArchiveData, DownloadGlobalSkillArchiveErrors, DownloadGlobalSkillArchiveResponses, DownloadObjectData, DownloadObjectErrors, DownloadObjectResponses, DownloadSkillArchiveData, DownloadSkillArchiveErrors, DownloadSkillArchiveResponses, EmailStatusData, EmailStatusErrors, EmailStatusResponses, EmbeddingsData, EmbeddingsErrors, EmbeddingsResponses, EnableBackupScheduleData, EnableBackupScheduleErrors, EnableBackupScheduleResponses, EnrichVisitorData, EnrichVisitorErrors, EnrichVisitorResponses, ExecData, ExecDetachedData, ExecDetachedErrors, ExecDetachedResponses, ExecErrors, ExecResponses, ExecuteDeploymentOperationData, ExecuteDeploymentOperationErrors, ExecuteDeploymentOperationResponses, ExecuteImportData, ExecuteImportErrors, ExecuteImportResponses, ExtendTimeoutData, ExtendTimeoutErrors, ExtendTimeoutResponses, ExternalServiceEnablePgStatStatementsData, ExternalServiceEnablePgStatStatementsErrors, ExternalServiceEnablePgStatStatementsResponses, ExternalServiceMetricsByDatabaseData, ExternalServiceMetricsByDatabaseErrors, ExternalServiceMetricsByDatabaseResponses, ExternalServiceMetricsCreateAlertRuleData, ExternalServiceMetricsCreateAlertRuleErrors, ExternalServiceMetricsCreateAlertRuleResponses, ExternalServiceMetricsDeleteAlertRuleData, ExternalServiceMetricsDeleteAlertRuleErrors, ExternalServiceMetricsDeleteAlertRuleResponses, ExternalServiceMetricsGetAlertRulesData, ExternalServiceMetricsGetAlertRulesErrors, ExternalServiceMetricsGetAlertRulesResponses, ExternalServiceMetricsGetLatestData, ExternalServiceMetricsGetLatestErrors, ExternalServiceMetricsGetLatestResponses, ExternalServiceMetricsGetRangeData, ExternalServiceMetricsGetRangeErrors, ExternalServiceMetricsGetRangeResponses, ExternalServiceMetricsStatusData, ExternalServiceMetricsStatusErrors, ExternalServiceMetricsStatusResponses, ExternalServiceMetricsToggleData, ExternalServiceMetricsToggleErrors, ExternalServiceMetricsToggleResponses, ExternalServiceMetricsUpdateAlertRuleData, ExternalServiceMetricsUpdateAlertRuleErrors, ExternalServiceMetricsUpdateAlertRuleResponses, ExternalServiceResetPgStatStatementsData, ExternalServiceResetPgStatStatementsErrors, ExternalServiceResetPgStatStatementsResponses, FinalizeOrderData, FinalizeOrderErrors, FinalizeOrderResponses, FinalizeProjectReleaseData, FinalizeProjectReleaseErrors, FinalizeProjectReleaseResponses, FindConversationData, FindConversationErrors, FindConversationResponses, GenerateJoinTokenData, GenerateJoinTokenErrors, GenerateJoinTokenResponses, GeneratePresetDockerfileData, GeneratePresetDockerfileErrors, GeneratePresetDockerfileResponses, GetAccessInfoData, GetAccessInfoErrors, GetAccessInfoResponses, GetActiveVisitorsData, GetActiveVisitorsErrors, GetActiveVisitorsResponses, GetActivityGraphData, GetActivityGraphErrors, GetActivityGraphResponses, GetAdminGateData, GetAdminGateErrors, GetAdminGateResponses, GetAgentData, GetAgentErrors, GetAgentResponses, GetAggregatedBucketsData, GetAggregatedBucketsErrors, GetAggregatedBucketsResponses, GetAiAgentBreakdownData, GetAiAgentBreakdownErrors, GetAiAgentBreakdownResponses, GetAiAgentPagesData, GetAiAgentPagesErrors, GetAiAgentPagesResponses, GetAiAgentTimelineData, GetAiAgentTimelineErrors, GetAiAgentTimelineResponses, GetAiPageBreakdownData, GetAiPageBreakdownErrors, GetAiPageBreakdownResponses, GetAiStatusBreakdownData, GetAiStatusBreakdownErrors, GetAiStatusBreakdownResponses, GetAlertData, GetAlertErrors, GetAlertResponses, GetAlertRuleData, GetAlertRuleErrors, GetAlertRuleResponses, GetAllRepositoriesByNameData, GetAllRepositoriesByNameErrors, GetAllRepositoriesByNameResponses, GetAnalyticsActiveVisitorsData, GetAnalyticsActiveVisitorsErrors, GetAnalyticsActiveVisitorsResponses, GetAnalyticsEventsCountData, GetAnalyticsEventsCountErrors, GetAnalyticsEventsCountResponses, GetAnalyticsSessionEventsData, GetAnalyticsSessionEventsErrors, GetAnalyticsSessionEventsResponses, GetAnalyticsVisitorSessionsData, GetAnalyticsVisitorSessionsErrors, GetAnalyticsVisitorSessionsResponses, GetApiKeyData, GetApiKeyErrors, GetApiKeyPermissionsData, GetApiKeyPermissionsErrors, GetApiKeyPermissionsResponses, GetApiKeyResponses, GetAuditLogData, GetAuditLogErrors, GetAuditLogResponses, GetBackupData, GetBackupErrors, GetBackupResponses, GetBackupScheduleData, GetBackupScheduleErrors, GetBackupScheduleResponses, GetBranchesByRepositoryIdData, GetBranchesByRepositoryIdErrors, GetBranchesByRepositoryIdResponses, GetBucketedIncidentsData, GetBucketedIncidentsErrors, GetBucketedIncidentsResponses, GetBucketedStatusData, GetBucketedStatusErrors, GetBucketedStatusResponses, GetChallengeTokenData, GetChallengeTokenErrors, GetChallengeTokenResponses, GetChatReadinessData, GetChatReadinessErrors, GetChatReadinessResponses, GetCliStatusData, GetCliStatusErrors, GetCliStatusResponses, GetClusterHealthData, GetClusterHealthErrors, GetClusterHealthResponses, GetClusterMemberData, GetClusterMemberErrors, GetClusterMemberResponses, GetCmdData, GetCmdErrors, GetCmdResponses, GetContainerDetailData, GetContainerDetailErrors, GetContainerDetailResponses, GetContainerEnvironmentVariableData, GetContainerEnvironmentVariableErrors, GetContainerEnvironmentVariableResponses, GetContainerInfoData, GetContainerInfoErrors, GetContainerInfoResponses, GetContainerLogsByIdData, GetContainerLogsByIdErrors, GetContainerLogsData, GetContainerLogsErrors, GetContainerMetricsData, GetContainerMetricsErrors, GetContainerMetricsResponses, GetConversationData, GetConversationDetailData, GetConversationDetailErrors, GetConversationDetailResponses, GetConversationErrors, GetConversationResponses, GetConversationsData, GetConversationsErrors, GetConversationsResponses, GetCronByIdData, GetCronByIdErrors, GetCronByIdResponses, GetCronExecutionsData, GetCronExecutionsErrors, GetCronExecutionsResponses, GetCrossProjectTraceSiblingsData, GetCrossProjectTraceSiblingsErrors, GetCrossProjectTraceSiblingsResponses, GetCurrentMonitorStatusData, GetCurrentMonitorStatusErrors, GetCurrentMonitorStatusResponses, GetCurrentUserData, GetCurrentUserErrors, GetCurrentUserResponses, GetCustomDomainData, GetCustomDomainErrors, GetCustomDomainResponses, GetDashboardData, GetDashboardErrors, GetDashboardProjectsAnalyticsData, GetDashboardProjectsAnalyticsErrors, GetDashboardProjectsAnalyticsResponses, GetDashboardResponses, GetDeliveryData, GetDeliveryErrors, GetDeliveryResponses, GetDeploymentContainerLogContentData, GetDeploymentContainerLogContentErrors, GetDeploymentContainerLogContentResponses, GetDeploymentData, GetDeploymentErrors, GetDeploymentJobLogsData, GetDeploymentJobLogsErrors, GetDeploymentJobLogsResponses, GetDeploymentJobsData, GetDeploymentJobsErrors, GetDeploymentJobsResponses, GetDeploymentOperationsData, GetDeploymentOperationsErrors, GetDeploymentOperationsResponses, GetDeploymentOperationStatusData, GetDeploymentOperationStatusErrors, GetDeploymentOperationStatusResponses, GetDeploymentResponses, GetDeploymentTokenData, GetDeploymentTokenErrors, GetDeploymentTokenResponses, GetDiskStatusData, GetDiskStatusErrors, GetDiskStatusResponses, GetDnsChangesData, GetDnsChangesErrors, GetDnsChangesResponses, GetDnsProviderData, GetDnsProviderErrors, GetDnsProviderResponses, GetDomainByHostData, GetDomainByHostErrors, GetDomainByHostResponses, GetDomainByIdData, GetDomainByIdErrors, GetDomainByIdResponses, GetDomainByNameData, GetDomainByNameErrors, GetDomainByNameResponses, GetDomainData, GetDomainDnsRecordsData, GetDomainDnsRecordsErrors, GetDomainDnsRecordsResponses, GetDomainErrors, GetDomainOrderData, GetDomainOrderErrors, GetDomainOrderResponses, GetDomainResponses, GetEmailData, GetEmailErrors, GetEmailEventsData, GetEmailEventsErrors, GetEmailEventsResponses, GetEmailLinksData, GetEmailLinksErrors, GetEmailLinksResponses, GetEmailProviderData, GetEmailProviderErrors, GetEmailProviderResponses, GetEmailResponses, GetEmailStatsData, GetEmailStatsErrors, GetEmailStatsResponses, GetEmailTrackingData, GetEmailTrackingErrors, GetEmailTrackingResponses, GetEmailTrackingStatusData, GetEmailTrackingStatusErrors, GetEmailTrackingStatusResponses, GetEntityInfoData, GetEntityInfoErrors, GetEntityInfoResponses, GetEnvironmentCronsData, GetEnvironmentCronsErrors, GetEnvironmentCronsResponses, GetEnvironmentData, GetEnvironmentDomainsData, GetEnvironmentDomainsErrors, GetEnvironmentDomainsResponses, GetEnvironmentErrors, GetEnvironmentResponses, GetEnvironmentsData, GetEnvironmentsErrors, GetEnvironmentsResponses, GetEnvironmentVariablesData, GetEnvironmentVariablesErrors, GetEnvironmentVariablesResponses, GetEnvironmentVariableValueData, GetEnvironmentVariableValueErrors, GetEnvironmentVariableValueResponses, GetErrorDashboardStatsData, GetErrorDashboardStatsErrors, GetErrorDashboardStatsResponses, GetErrorEventData, GetErrorEventErrors, GetErrorEventResponses, GetErrorGroupData, GetErrorGroupErrors, GetErrorGroupResponses, GetErrorStatsData, GetErrorStatsErrors, GetErrorStatsResponses, GetErrorTimeSeriesData, GetErrorTimeSeriesErrors, GetErrorTimeSeriesResponses, GetEventDetailData, GetEventDetailErrors, GetEventDetailResponses, GetEventEntriesData, GetEventEntriesErrors, GetEventEntriesResponses, GetEventsCountData, GetEventsCountErrors, GetEventsCountResponses, GetEventsTimelineData, GetEventsTimelineErrors, GetEventsTimelineResponses, GetEventTypeBreakdownData, GetEventTypeBreakdownErrors, GetEventTypeBreakdownResponses, GetEventVisitorsData, GetEventVisitorsErrors, GetEventVisitorsResponses, GetExternalImageData, GetExternalImageErrors, GetExternalImageResponses, GetFileData, GetFileErrors, GetFileResponses, GetFlagData, GetFlagErrors, GetFlagResponses, GetFlagSnapshotData, GetFlagSnapshotErrors, GetFlagSnapshotResponses, GetFunnelMetricsData, GetFunnelMetricsErrors, GetFunnelMetricsResponses, GetGenaiTraceData, GetGenaiTraceErrors, GetGenaiTraceResponses, GetGeneralStatsData, GetGeneralStatsErrors, GetGeneralStatsResponses, GetGitProviderData, GetGitProviderErrors, GetGitProviderResponses, GetGlobalEventsData, GetGlobalEventsErrors, GetGlobalEventsResponses, GetGlobalEventStatsData, GetGlobalEventStatsErrors, GetGlobalEventStatsResponses, GetGlobalMcpData, GetGlobalMcpErrors, GetGlobalMcpResponses, GetGlobalSandboxStatusData, GetGlobalSandboxStatusErrors, GetGlobalSandboxStatusResponses, GetGlobalSkillData, GetGlobalSkillErrors, GetGlobalSkillResponses, GetGroupedPageMetricsData, GetGroupedPageMetricsErrors, GetGroupedPageMetricsResponses, GetHealthData, GetHealthErrors, GetHealthResponses, GetHourlyVisitsData, GetHourlyVisitsErrors, GetHourlyVisitsResponses, GetHttpChallengeDebugData, GetHttpChallengeDebugErrors, GetHttpChallengeDebugResponses, GetImportStatusData, GetImportStatusErrors, GetImportStatusResponses, GetIncidentData, GetIncidentErrors, GetIncidentResponses, GetIncidentUpdatesData, GetIncidentUpdatesErrors, GetIncidentUpdatesResponses, GetIpAccessControlData, GetIpAccessControlErrors, GetIpAccessControlResponses, GetIpGeolocationData, GetIpGeolocationErrors, GetIpGeolocationResponses, GetJoinTokenStatusData, GetJoinTokenStatusErrors, GetJoinTokenStatusResponses, GetLastDeploymentData, GetLastDeploymentErrors, GetLastDeploymentResponses, GetLatestScanData, GetLatestScanErrors, GetLatestScanResponses, GetLatestScansPerEnvironmentData, GetLatestScansPerEnvironmentErrors, GetLatestScansPerEnvironmentResponses, GetLiveVisitorsListData, GetLiveVisitorsListErrors, GetLiveVisitorsListResponses, GetLogContextData, GetLogContextErrors, GetLogContextResponses, GetMcpData, GetMcpErrors, GetMcpResponses, GetMetricsOverTimeData, GetMetricsOverTimeErrors, GetMetricsOverTimeResponses, GetMonitorData, GetMonitorErrors, GetMonitorResponses, GetNotificationProviderData, GetNotificationProviderErrors, GetNotificationProviderResponses, GetOnDemandCertStatusData, GetOnDemandCertStatusErrors, GetOnDemandCertStatusResponses, GetOrCreateDsnData, GetOrCreateDsnErrors, GetOrCreateDsnResponses, GetPageFlowData, GetPageFlowErrors, GetPageFlowResponses, GetPageHourlySessionsData, GetPageHourlySessionsErrors, GetPageHourlySessionsResponses, GetPagePathDetailData, GetPagePathDetailErrors, GetPagePathDetailResponses, GetPagePathsData, GetPagePathsErrors, GetPagePathsResponses, GetPagePathsSparklinesData, GetPagePathsSparklinesErrors, GetPagePathsSparklinesResponses, GetPagePathVisitorsData, GetPagePathVisitorsErrors, GetPagePathVisitorsResponses, GetPendingActionData, GetPendingActionErrors, GetPendingActionResponses, GetPerformanceMetricsData, GetPerformanceMetricsErrors, GetPerformanceMetricsResponses, GetPgUpgradeData, GetPgUpgradeErrors, GetPgUpgradeLogsData, GetPgUpgradeLogsErrors, GetPgUpgradeLogsResponses, GetPgUpgradeResponses, GetPipelineStatsData, GetPipelineStatsErrors, GetPipelineStatsResponses, GetPlatformInfoData, GetPlatformInfoErrors, GetPlatformInfoResponses, GetPostgresWalHealthData, GetPostgresWalHealthErrors, GetPostgresWalHealthResponses, GetPreferencesData, GetPreferencesErrors, GetPreferencesResponses, GetPreviewGatewayLogsData, GetPreviewGatewayLogsResponses, GetPreviewGatewaySettingsData, GetPreviewGatewaySettingsResponses, GetPreviewGatewayStatusData, GetPreviewGatewayStatusResponses, GetPricingData, GetPricingErrors, GetPricingResponses, GetPrivateIpData, GetPrivateIpErrors, GetPrivateIpResponses, GetProjectAlarmsSummaryData, GetProjectAlarmsSummaryErrors, GetProjectAlarmsSummaryResponses, GetProjectBySlugData, GetProjectBySlugErrors, GetProjectBySlugResponses, GetProjectData, GetProjectDeploymentsData, GetProjectDeploymentsErrors, GetProjectDeploymentsResponses, GetProjectErrors, GetProjectResponses, GetProjectsData, GetProjectsErrors, GetProjectServiceEnvironmentVariablesData, GetProjectServiceEnvironmentVariablesErrors, GetProjectServiceEnvironmentVariablesResponses, GetProjectSessionReplaysData, GetProjectSessionReplaysErrors, GetProjectSessionReplaysResponses, GetProjectsHealthData, GetProjectsHealthErrors, GetProjectsHealthResponses, GetProjectsMonitorHealthData, GetProjectsMonitorHealthErrors, GetProjectsMonitorHealthResponses, GetProjectsResponses, GetProjectStatisticsData, GetProjectStatisticsErrors, GetProjectStatisticsResponses, GetProjectTemplateData, GetProjectTemplateErrors, GetProjectTemplateResponses, GetPropertyBreakdownData, GetPropertyBreakdownErrors, GetPropertyBreakdownResponses, GetPropertyTimelineData, GetPropertyTimelineErrors, GetPropertyTimelineResponses, GetProviderConnectionsData, GetProviderConnectionsErrors, GetProviderConnectionsResponses, GetProviderMetadataData, GetProviderMetadataErrors, GetProviderMetadataResponses, GetProvidersMetadataData, GetProvidersMetadataErrors, GetProvidersMetadataResponses, GetProxyLogByIdData, GetProxyLogByIdErrors, GetProxyLogByIdResponses, GetProxyLogByRequestIdData, GetProxyLogByRequestIdErrors, GetProxyLogByRequestIdResponses, GetProxyLogsData, GetProxyLogsErrors, GetProxyLogsResponses, GetPublicBranchesData, GetPublicBranchesErrors, GetPublicBranchesResponses, GetPublicIpData, GetPublicIpErrors, GetPublicIpResponses, GetPublicRepositoryData, GetPublicRepositoryErrors, GetPublicRepositoryResponses, GetQuotaData, GetQuotaErrors, GetQuotaResponses, GetRecentActivityData, GetRecentActivityErrors, GetRecentActivityResponses, GetRemoteExternalImageData, GetRemoteExternalImageErrors, GetRemoteExternalImageResponses, GetRepositoryBranchesData, GetRepositoryBranchesErrors, GetRepositoryBranchesResponses, GetRepositoryByIdData, GetRepositoryByIdErrors, GetRepositoryByIdResponses, GetRepositoryByNameData, GetRepositoryByNameErrors, GetRepositoryByNameResponses, GetRepositoryPresetByNameData, GetRepositoryPresetByNameErrors, GetRepositoryPresetByNameResponses, GetRepositoryPresetLiveData, GetRepositoryPresetLiveErrors, GetRepositoryPresetLiveResponses, GetRepositoryTagsData, GetRepositoryTagsErrors, GetRepositoryTagsResponses, GetResolvedEnvironmentVariablesData, GetResolvedEnvironmentVariablesErrors, GetResolvedEnvironmentVariablesResponses, GetResolvedEnvironmentVariableValueData, GetResolvedEnvironmentVariableValueErrors, GetResolvedEnvironmentVariableValueResponses, GetRestoreCapabilitiesData, GetRestoreCapabilitiesErrors, GetRestoreCapabilitiesResponses, GetRestoreRunData, GetRestoreRunErrors, GetRestoreRunResponses, GetRouteData, GetRouteErrors, GetRouteResponses, GetRunData, GetRunErrors, GetRunResponses, GetRunWithLogsData, GetRunWithLogsErrors, GetRunWithLogsResponses, GetS3CredentialsData, GetS3CredentialsErrors, GetS3CredentialsResponses, GetS3SourceData, GetS3SourceErrors, GetS3SourceResponses, GetSandboxData, GetSandboxErrors, GetSandboxResponses, GetSandboxStatusData, GetSandboxStatusErrors, GetSandboxStatusResponses, GetScanByDeploymentData, GetScanByDeploymentErrors, GetScanByDeploymentResponses, GetScanData, GetScanErrors, GetScanResponses, GetScanVulnerabilitiesData, GetScanVulnerabilitiesErrors, GetScanVulnerabilitiesResponses, GetServiceBySlugData, GetServiceBySlugErrors, GetServiceBySlugResponses, GetServiceData, GetServiceEnvironmentVariableData, GetServiceEnvironmentVariableErrors, GetServiceEnvironmentVariableResponses, GetServiceEnvironmentVariablesData, GetServiceEnvironmentVariablesErrors, GetServiceEnvironmentVariablesResponses, GetServiceErrors, GetServiceHealthStatusData, GetServiceHealthStatusErrors, GetServiceHealthStatusResponses, GetServicePreviewEnvironmentVariableNamesData, GetServicePreviewEnvironmentVariableNamesErrors, GetServicePreviewEnvironmentVariableNamesResponses, GetServicePreviewEnvironmentVariablesMaskedData, GetServicePreviewEnvironmentVariablesMaskedErrors, GetServicePreviewEnvironmentVariablesMaskedResponses, GetServiceResponses, GetServiceRuntimeData, GetServiceRuntimeErrors, GetServiceRuntimeResponses, GetServiceStatsData, GetServiceStatsErrors, GetServiceStatsResponses, GetServiceTypeParametersData, GetServiceTypeParametersErrors, GetServiceTypeParametersResponses, GetServiceTypesData, GetServiceTypesErrors, GetServiceTypesResponses, GetSessionDetailsData, GetSessionDetailsErrors, GetSessionDetailsResponses, GetSessionEventsData, GetSessionEventsErrors, GetSessionEventsResponses, GetSessionLogsData, GetSessionLogsErrors, GetSessionLogsResponses, GetSessionReplayData, GetSessionReplayErrors, GetSessionReplayEventsData, GetSessionReplayEventsErrors, GetSessionReplayEventsResponses, GetSessionReplayResponses, GetSettingsData, GetSettingsErrors, GetSettingsResponses, GetSkillData, GetSkillErrors, GetSkillResponses, GetSlowQueriesData, GetSlowQueriesErrors, GetSlowQueriesResponses, GetStaticBundleData, GetStaticBundleErrors, GetStaticBundleResponses, GetStatusOverviewData, GetStatusOverviewErrors, GetStatusOverviewResponses, GetTagsByRepositoryIdData, GetTagsByRepositoryIdErrors, GetTagsByRepositoryIdResponses, GetTeamData, GetTeamErrors, GetTeamResponses, GetTimeBucketStatsData, GetTimeBucketStatsErrors, GetTimeBucketStatsResponses, GetTodayStatsData, GetTodayStatsErrors, GetTodayStatsResponses, GetTraceData, GetTraceErrors, GetTraceResponses, GetUnifiedTraceData, GetUnifiedTraceErrors, GetUnifiedTraceResponses, GetUniqueCountsData, GetUniqueCountsErrors, GetUniqueCountsResponses, GetUniqueEventsData, GetUniqueEventsErrors, GetUniqueEventsResponses, GetUpdateStatusData, GetUpdateStatusErrors, GetUpdateStatusResponses, GetUptimeHistoryData, GetUptimeHistoryErrors, GetUptimeHistoryResponses, GetUsageByProviderData, GetUsageByProviderErrors, GetUsageByProviderResponses, GetUsageRecentData, GetUsageRecentErrors, GetUsageRecentResponses, GetUsageSummaryData, GetUsageSummaryErrors, GetUsageSummaryResponses, GetUsageTimeseriesData, GetUsageTimeseriesErrors, GetUsageTimeseriesResponses, GetUsageTopModelsData, GetUsageTopModelsErrors, GetUsageTopModelsResponses, GetVisitorByGuidData, GetVisitorByGuidErrors, GetVisitorByGuidResponses, GetVisitorByIdData, GetVisitorByIdErrors, GetVisitorByIdResponses, GetVisitorDetailsData, GetVisitorDetailsErrors, GetVisitorDetailsResponses, GetVisitorFacetsData, GetVisitorFacetsErrors, GetVisitorFacetsResponses, GetVisitorInfoData, GetVisitorInfoErrors, GetVisitorInfoResponses, GetVisitorJourneyData, GetVisitorJourneyErrors, GetVisitorJourneyResponses, GetVisitorsData, GetVisitorsErrors, GetVisitorSessionsData, GetVisitorSessionsErrors, GetVisitorSessionsResponses, GetVisitorsResponses, GetVisitorStatsData, GetVisitorStatsErrors, GetVisitorStatsResponses, GetWebhookData, GetWebhookErrors, GetWebhookResponses, GrantProjectAccessData, GrantProjectAccessErrors, GrantProjectAccessResponses, HandleGitProviderOauthCallbackData, HandleGitProviderOauthCallbackErrors, HasAnalyticsEventsData, HasAnalyticsEventsErrors, HasAnalyticsEventsResponses, HasErrorGroupsData, HasErrorGroupsErrors, HasErrorGroupsResponses, HasPerformanceMetricsData, HasPerformanceMetricsErrors, HasPerformanceMetricsResponses, ImportExternalServiceData, ImportExternalServiceErrors, ImportExternalServiceResponses, IngestLogsByPathData, IngestLogsByPathErrors, IngestLogsByPathResponses, IngestLogsData, IngestLogsErrors, IngestLogsResponses, IngestMetricsByPathData, IngestMetricsByPathErrors, IngestMetricsByPathResponses, IngestMetricsData, IngestMetricsErrors, IngestMetricsResponses, IngestSentryEnvelopeData, IngestSentryEnvelopeErrors, IngestSentryEnvelopeResponses, IngestSentryEventData, IngestSentryEventErrors, IngestSentryEventResponses, IngestTracesByPathData, IngestTracesByPathErrors, IngestTracesByPathResponses, IngestTracesData, IngestTracesErrors, IngestTracesResponses, InitSessionReplayData, InitSessionReplayErrors, InitSessionReplayResponses, InspectDropArchiveData, InspectDropArchiveErrors, InspectDropArchiveResponses, JobLogsData, JobLogsErrors, JobLogsResponses, JobStatusData, JobStatusErrors, JobStatusResponses, KillJobData, KillJobErrors, KillJobResponses, KvDelData, KvDelErrors, KvDelResponses, KvDisableData, KvDisableErrors, KvDisableResponses, KvEnableData, KvEnableErrors, KvEnableResponses, KvExpireData, KvExpireErrors, KvExpireResponses, KvGetData, KvGetErrors, KvGetResponses, KvIncrData, KvIncrErrors, KvIncrResponses, KvKeysData, KvKeysErrors, KvKeysResponses, KvSetData, KvSetErrors, KvSetResponses, KvStatusData, KvStatusErrors, KvStatusResponses, KvTtlData, KvTtlErrors, KvTtlResponses, KvUpdateData, KvUpdateErrors, KvUpdateResponses, LatestRunForSourceData, LatestRunForSourceErrors, LatestRunForSourceResponses, LinkCustomDomainToCertificateData, LinkCustomDomainToCertificateErrors, LinkCustomDomainToCertificateResponses, LinkServiceToProjectData, LinkServiceToProjectErrors, LinkServiceToProjectResponses, ListAgentRunsData, ListAgentRunsErrors, ListAgentRunsResponses, ListAgentsData, ListAgentsErrors, ListAgentsResponses, ListAiProvidersData, ListAiProvidersErrors, ListAiProvidersResponses, ListAlertRulesData, ListAlertRulesErrors, ListAlertRulesResponses, ListAlertsData, ListAlertsErrors, ListAlertsResponses, ListAllConversationsData, ListAllConversationsErrors, ListAllConversationsResponses, ListAllRunsData, ListAllRunsErrors, ListAllRunsResponses, ListApiKeysData, ListApiKeysErrors, ListApiKeysResponses, ListAuditLogsData, ListAuditLogsErrors, ListAuditLogsResponses, ListAvailableContainersData, ListAvailableContainersErrors, ListAvailableContainersResponses, ListBackupAlertsData, ListBackupAlertsErrors, ListBackupAlertsResponses, ListBackupChildrenData, ListBackupChildrenErrors, ListBackupChildrenResponses, ListBackupSchedulesData, ListBackupSchedulesErrors, ListBackupSchedulesResponses, ListBackupsForScheduleData, ListBackupsForScheduleErrors, ListBackupsForScheduleResponses, ListCommitsByRepositoryIdData, ListCommitsByRepositoryIdErrors, ListCommitsByRepositoryIdResponses, ListConnectionsData, ListConnectionsErrors, ListConnectionsResponses, ListContainersAtPathData, ListContainersAtPathErrors, ListContainersAtPathResponses, ListContainersData, ListContainersErrors, ListContainersResponses, ListConversationsData, ListConversationsErrors, ListConversationsResponses, ListCustomDomainsForProjectData, ListCustomDomainsForProjectErrors, ListCustomDomainsForProjectResponses, ListDashboardsData, ListDashboardsErrors, ListDashboardsResponses, ListDeliveriesData, ListDeliveriesErrors, ListDeliveriesResponses, ListDeploymentContainerLogsData, ListDeploymentContainerLogsErrors, ListDeploymentContainerLogsResponses, ListDeploymentTokensData, ListDeploymentTokensErrors, ListDeploymentTokensResponses, ListDnsProvidersData, ListDnsProvidersErrors, ListDnsProvidersResponses, ListDomainsData, ListDomainsErrors, ListDomainsResponses, ListDsnsData, ListDsnsErrors, ListDsnsResponses, ListEmailDomainsData, ListEmailDomainsErrors, ListEmailDomainsResponses, ListEmailProvidersData, ListEmailProvidersErrors, ListEmailProvidersResponses, ListEmailsData, ListEmailsErrors, ListEmailsResponses, ListEnrollmentTokensData, ListEnrollmentTokensErrors, ListEnrollmentTokensResponses, ListEntitiesData, ListEntitiesErrors, ListEntitiesResponses, ListErrorEventsData, ListErrorEventsErrors, ListErrorEventsResponses, ListErrorGroupsData, ListErrorGroupsErrors, ListErrorGroupsResponses, ListEventsData, ListEventsResponses, ListEventTypesData, ListEventTypesResponses, ListExternalImagesData, ListExternalImagesErrors, ListExternalImagesResponses, ListExternalPluginsData, ListExternalPluginsErrors, ListExternalPluginsResponses, ListExternalServiceBackupsData, ListExternalServiceBackupsErrors, ListExternalServiceBackupsResponses, ListFlagsData, ListFlagsErrors, ListFlagsResponses, ListFunnelsData, ListFunnelsErrors, ListFunnelsResponses, ListGitProvidersData, ListGitProvidersErrors, ListGitProvidersResponses, ListGlobalMcpsData, ListGlobalMcpsErrors, ListGlobalMcpsResponses, ListGlobalSkillsData, ListGlobalSkillsErrors, ListGlobalSkillsResponses, ListIncidentsData, ListIncidentsErrors, ListIncidentsResponses, ListInsightsData, ListInsightsErrors, ListInsightsResponses, ListIpAccessControlData, ListIpAccessControlErrors, ListIpAccessControlResponses, ListJobsData, ListJobsErrors, ListJobsResponses, ListKnownAiAgentsData, ListKnownAiAgentsErrors, ListKnownAiAgentsResponses, ListManagedDomainsData, ListManagedDomainsErrors, ListManagedDomainsResponses, ListMcpsData, ListMcpsErrors, ListMcpsResponses, ListMetricLabelKeysData, ListMetricLabelKeysErrors, ListMetricLabelKeysResponses, ListMetricLabelValuesData, ListMetricLabelValuesErrors, ListMetricLabelValuesResponses, ListMetricNamesData, ListMetricNamesErrors, ListMetricNamesResponses, ListModelsData, ListModelsErrors, ListModelsResponses, ListMonitorsData, ListMonitorsErrors, ListMonitorsResponses, ListNotificationProvidersData, ListNotificationProvidersErrors, ListNotificationProvidersResponses, ListOidcProvidersData, ListOidcProvidersResponses, ListOidcProviderUsersData, ListOidcProviderUsersErrors, ListOidcProviderUsersResponses, ListOidcRoleMappingsData, ListOidcRoleMappingsResponses, ListOnDemandCertsData, ListOnDemandCertsErrors, ListOnDemandCertsResponses, ListOrdersData, ListOrdersErrors, ListOrdersResponses, ListPeersData, ListPeersErrors, ListPeersResponses, ListPendingActionsData, ListPendingActionsErrors, ListPendingActionsResponses, ListPgUpgradesData, ListPgUpgradesErrors, ListPgUpgradesResponses, ListPresetsData, ListPresetsErrors, ListPresetsResponses, ListProjectAccessData, ListProjectAccessErrors, ListProjectAccessResponses, ListProjectAlarmsData, ListProjectAlarmsErrors, ListProjectAlarmsResponses, ListProjectScansData, ListProjectScansErrors, ListProjectScansResponses, ListProjectSecretsData, ListProjectSecretsErrors, ListProjectSecretsResponses, ListProjectServicesData, ListProjectServicesErrors, ListProjectServicesResponses, ListProjectTemplatesData, ListProjectTemplatesErrors, ListProjectTemplatesResponses, ListProjectTemplateTagsData, ListProjectTemplateTagsErrors, ListProjectTemplateTagsResponses, ListProviderKeysData, ListProviderKeysErrors, ListProviderKeysResponses, ListProviderZonesData, ListProviderZonesErrors, ListProviderZonesResponses, ListPublicProvidersData, ListPublicProvidersResponses, ListReleaseFilesData, ListReleaseFilesErrors, ListReleaseFilesResponses, ListReleasesData, ListReleasesErrors, ListReleasesResponses, ListRemoteExternalImagesData, ListRemoteExternalImagesErrors, ListRemoteExternalImagesResponses, ListRepositoriesByConnectionData, ListRepositoriesByConnectionErrors, ListRepositoriesByConnectionResponses, ListRepositoriesByProviderData, ListRepositoriesByProviderErrors, ListRepositoriesByProviderResponses, ListRestoreRunsForServiceData, ListRestoreRunsForServiceResponses, ListRootContainersData, ListRootContainersErrors, ListRootContainersResponses, ListRoutesData, ListRoutesErrors, ListRoutesResponses, ListS3SourcesData, ListS3SourcesErrors, ListS3SourcesResponses, ListSandboxesData, ListSandboxesResponses, ListScheduleRunJobsData, ListScheduleRunJobsErrors, ListScheduleRunJobsResponses, ListScheduleRunsData, ListScheduleRunsErrors, ListScheduleRunsResponses, ListScheduleServicesData, ListScheduleServicesErrors, ListScheduleServicesResponses, ListSecretsData, ListSecretsErrors, ListSecretsResponses, ListServiceHealthStatusesData, ListServiceHealthStatusesErrors, ListServiceHealthStatusesResponses, ListServiceProjectsData, ListServiceProjectsErrors, ListServiceProjectsResponses, ListServiceSchedulesData, ListServiceSchedulesErrors, ListServiceSchedulesResponses, ListServicesData, ListServicesErrors, ListServicesResponses, ListSkillsData, ListSkillsErrors, ListSkillsResponses, ListSourceBackupsData, ListSourceBackupsErrors, ListSourceBackupsResponses, ListSourceFilesData, ListSourceFilesErrors, ListSourceFilesResponses, ListSourceMapsData, ListSourceMapsErrors, ListSourceMapsResponses, ListSourcesData, ListSourcesErrors, ListSourcesResponses, ListStaticBundlesData, ListStaticBundlesErrors, ListStaticBundlesResponses, ListSyncedRepositoriesData, ListSyncedRepositoriesErrors, ListSyncedRepositoriesResponses, ListTeamMembersData, ListTeamMembersErrors, ListTeamMembersResponses, ListTeamProjectsData, ListTeamProjectsErrors, ListTeamProjectsResponses, ListTeamsData, ListTeamsErrors, ListTeamsResponses, ListUsersData, ListUsersErrors, ListUsersResponses, ListWebhooksData, ListWebhooksErrors, ListWebhooksResponses, LoginData, LoginErrors, LoginResponses, LogoutData, LogoutErrors, LogoutResponses, LookupDnsARecordsData, LookupDnsARecordsErrors, LookupDnsARecordsResponses, MintEnrollmentTokenData, MintEnrollmentTokenErrors, MintEnrollmentTokenResponses, MkdirData, MkdirErrors, MkdirResponses, NodeHeartbeatData, NodeHeartbeatErrors, NodeHeartbeatResponses, NodeMetricsGetRangeData, NodeMetricsGetRangeErrors, NodeMetricsGetRangeResponses, ObservabilityFullEventData, ObservabilityFullEventErrors, ObservabilityFullEventResponses, ObservabilityListEventsData, ObservabilityListEventsErrors, ObservabilityListEventsResponses, OidcCallbackData, PatchAdminGateData, PatchAdminGateErrors, PatchAdminGateResponses, PatchPreviewGatewaySettingsData, PatchPreviewGatewaySettingsResponses, PauseDeploymentData, PauseDeploymentErrors, PauseDeploymentResponses, PauseSandboxData, PauseSandboxErrors, PauseSandboxResponses, PlanRestoreData, PlanRestoreErrors, PlanRestoreResponses, PostDnsAckData, PostDnsAckErrors, PostDnsAckResponses, PreviewAlertData, PreviewAlertErrors, PreviewAlertResponses, PreviewFunnelMetricsData, PreviewFunnelMetricsErrors, PreviewFunnelMetricsResponses, PreviewHostnameModeData, PreviewHostnameModeErrors, PreviewHostnameModeResponses, PromoteClusterMemberData, PromoteClusterMemberErrors, PromoteClusterMemberResponses, PromoteDeploymentData, PromoteDeploymentErrors, PromoteDeploymentResponses, ProvisionDomainData, ProvisionDomainErrors, ProvisionDomainResponses, PurgeProjectLogsData, PurgeProjectLogsErrors, PurgeProjectLogsResponses, PushExternalImageData, PushExternalImageErrors, PushExternalImageResponses, QueryDataData, QueryDataErrors, QueryDataResponses, QueryGenaiTracesData, QueryGenaiTracesErrors, QueryGenaiTracesResponses, QueryLogsData, QueryLogsErrors, QueryLogsResponses, QueryMetricsData, QueryMetricsErrors, QueryMetricsResponses, QueryTracesData, QueryTracesErrors, QueryTracesResponses, QueryTraceSummariesData, QueryTraceSummariesErrors, QueryTraceSummariesResponses, ReadFileData, ReadFileErrors, ReadFileResponses, ReAnalyzeData, ReAnalyzeErrors, ReAnalyzeResponses, RecordConsoleEventData, RecordConsoleEventErrors, RecordConsoleEventResponses, RecordEventMetricsData, RecordEventMetricsErrors, RecordEventMetricsResponses, RecordFlagExposureData, RecordFlagExposureErrors, RecordFlagExposureResponses, RecordSpeedMetricsData, RecordSpeedMetricsErrors, RecordSpeedMetricsResponses, RefreshRouteTableData, RefreshRouteTableErrors, RefreshRouteTableResponses, RegenerateDsnData, RegenerateDsnErrors, RegenerateDsnResponses, RegisterExternalImageData, RegisterExternalImageErrors, RegisterExternalImageResponses, RegisterNodeData, RegisterNodeErrors, RegisterNodeResponses, ReinstallGitlabWebhookData, ReinstallGitlabWebhookErrors, ReinstallGitlabWebhookResponses, RejectPendingActionData, RejectPendingActionErrors, RejectPendingActionResponses, ReloadPluginsData, ReloadPluginsErrors, ReloadPluginsResponses, RemoveClusterMemberData, RemoveClusterMemberErrors, RemoveClusterMemberResponses, RemoveManagedDomainData, RemoveManagedDomainErrors, RemoveManagedDomainResponses, RemoveRoleData, RemoveRoleErrors, RemoveRoleResponses, RemoveTeamMemberData, RemoveTeamMemberErrors, RemoveTeamMemberResponses, RenameConversationData, RenameConversationErrors, RenameConversationResponses, RenewDomainData, RenewDomainErrors, RenewDomainResponses, RequestPasswordResetData, RequestPasswordResetErrors, RequestPasswordResetResponses, ResetPasswordData, ResetPasswordErrors, ResetPasswordResponses, ResizeSandboxData, ResizeSandboxErrors, ResizeSandboxResponses, ResolveAlarmData, ResolveAlarmErrors, ResolveAlarmResponses, RestartContainerData, RestartContainerErrors, RestartContainerResponses, RestartPreviewGatewayData, RestartPreviewGatewayResponses, RestartSandboxData, RestartSandboxErrors, RestartSandboxResponses, RestoreFlagData, RestoreFlagErrors, RestoreFlagResponses, RestoreUserData, RestoreUserErrors, RestoreUserResponses, ResumeDeploymentData, ResumeDeploymentErrors, ResumeDeploymentResponses, ResumeSandboxData, ResumeSandboxErrors, ResumeSandboxResponses, RetryClusterData, RetryClusterErrors, RetryClusterResponses, RetryDeliveryData, RetryDeliveryErrors, RetryDeliveryResponses, RetryPgUpgradeData, RetryPgUpgradeErrors, RetryPgUpgradeResponses, RetryRunData, RetryRunErrors, RetryRunResponses, RevealGlobalMcpConfigData, RevealGlobalMcpConfigErrors, RevealGlobalMcpConfigResponses, RevealMcpConfigData, RevealMcpConfigErrors, RevealMcpConfigResponses, RevealNotificationProviderConfigData, RevealNotificationProviderConfigErrors, RevealNotificationProviderConfigResponses, RevealServiceParameterData, RevealServiceParameterErrors, RevealServiceParameterResponses, RevenueCreateIntegrationData, RevenueCreateIntegrationErrors, RevenueCreateIntegrationResponses, RevenueDeleteIntegrationData, RevenueDeleteIntegrationResponses, RevenueGlobalEventsData, RevenueGlobalEventsResponses, RevenueImportInvoicesCsvData, RevenueImportInvoicesCsvErrors, RevenueImportInvoicesCsvResponses, RevenueImportSubscriptionsCsvData, RevenueImportSubscriptionsCsvErrors, RevenueImportSubscriptionsCsvResponses, RevenueListIntegrationsData, RevenueListIntegrationsResponses, RevenueListProvidersData, RevenueListProvidersResponses, RevenueMetricsCustomersData, RevenueMetricsCustomersResponses, RevenueMetricsGlobalMrrData, RevenueMetricsGlobalMrrResponses, RevenueMetricsGlobalSummaryData, RevenueMetricsGlobalSummaryResponses, RevenueMetricsMrrData, RevenueMetricsMrrResponses, RevenueMetricsSummaryData, RevenueMetricsSummaryResponses, RevenueRecentEventsData, RevenueRecentEventsResponses, RevenueRotateTokenData, RevenueRotateTokenResponses, RevenueUpdateConfigData, RevenueUpdateConfigErrors, RevenueUpdateConfigResponses, RevenueUpdateSecretData, RevenueUpdateSecretErrors, RevenueUpdateSecretResponses, RevokeDsnData, RevokeDsnErrors, RevokeDsnResponses, RevokeEnrollmentTokenData, RevokeEnrollmentTokenErrors, RevokeEnrollmentTokenResponses, RevokeJoinTokenData, RevokeJoinTokenErrors, RevokeJoinTokenResponses, RevokeProjectAccessData, RevokeProjectAccessErrors, RevokeProjectAccessResponses, RollbackPgUpgradeData, RollbackPgUpgradeErrors, RollbackPgUpgradeResponses, RollbackToDeploymentData, RollbackToDeploymentErrors, RollbackToDeploymentResponses, RootfsGcData, RootfsGcResponses, RootfsReportData, RootfsReportResponses, RotateApiKeyData, RotateApiKeyErrors, RotateApiKeyResponses, RotateDeploymentTokenData, RotateDeploymentTokenErrors, RotateDeploymentTokenResponses, RunBackupForSourceData, RunBackupForSourceErrors, RunBackupForSourceResponses, RunConnectionHealthCheckData, RunConnectionHealthCheckErrors, RunConnectionHealthCheckResponses, RunExternalServiceBackupData, RunExternalServiceBackupErrors, RunExternalServiceBackupResponses, RunScheduleNowData, RunScheduleNowErrors, RunScheduleNowResponses, SandboxCreatePreviewLinkData, SandboxCreatePreviewLinkErrors, SandboxCreatePreviewLinkResponses, SaveAgentTokenData, SaveAgentTokenErrors, SaveAgentTokenResponses, SaveAiProviderCredentialData, SaveAiProviderCredentialErrors, SaveAiProviderCredentialResponses, SearchLogsData, SearchLogsErrors, SearchLogsResponses, SendEmailData, SendEmailErrors, SendEmailResponses, SetDefaultS3SourceData, SetDefaultS3SourceErrors, SetDefaultS3SourceResponses, SetFlagEnvironmentData, SetFlagEnvironmentErrors, SetFlagEnvironmentResponses, SetPreviewPasswordData, SetPreviewPasswordErrors, SetPreviewPasswordResponses, SetupDnsChallengeData, SetupDnsChallengeErrors, SetupDnsChallengeResponses, SetupDnsData, SetupDnsErrors, SetupDnsResponses, SetupEmailTrackingData, SetupEmailTrackingErrors, SetupEmailTrackingResponses, SetupMfaData, SetupMfaErrors, SetupMfaResponses, SleepEnvironmentData, SleepEnvironmentErrors, SleepEnvironmentResponses, SmokeTestAgentData, SmokeTestAgentErrors, SmokeTestAgentResponses, SourceSandboxData, SourceSandboxErrors, SourceSandboxResponses, StartAnalysisData, StartAnalysisErrors, StartAnalysisResponses, StartContainerData, StartContainerErrors, StartContainerResponses, StartFixData, StartFixErrors, StartFixResponses, StartGitProviderOauthData, StartGitProviderOauthErrors, StartOidcLoginBySlugData, StartOidcLoginBySlugErrors, StartPgUpgradeData, StartPgUpgradeErrors, StartPgUpgradeResponses, StartRestoreData, StartRestoreErrors, StartRestoreResponses, StartServiceData, StartServiceErrors, StartServiceResponses, StatPathData, StatPathErrors, StatPathResponses, StopContainerData, StopContainerErrors, StopContainerResponses, StopSandboxData, StopSandboxErrors, StopSandboxResponses, StopServiceData, StopServiceErrors, StopServiceResponses, StreamContainerMetricsData, StreamContainerMetricsErrors, StreamContainerMetricsResponses, StreamEventsData, StreamEventsErrors, StreamEventsResponses, StreamRunEventsData, StreamRunEventsErrors, StreamRunEventsResponses, SyncRepositoriesData, SyncRepositoriesErrors, SyncRepositoriesResponses, TailDeploymentJobLogsData, TailDeploymentJobLogsErrors, TailLogsData, TailLogsErrors, TailLogsResponses, TeardownDeploymentData, TeardownDeploymentErrors, TeardownDeploymentResponses, TeardownEnvironmentData, TeardownEnvironmentErrors, TeardownEnvironmentResponses, TestNotificationProviderData, TestNotificationProviderErrors, TestNotificationProviderResponses, TestOidcProviderData, TestOidcProviderResponses, TestProviderConnectionData, TestProviderConnectionErrors, TestProviderConnectionResponses, TestProviderData, TestProviderErrors, TestProviderKeyByIdData, TestProviderKeyByIdErrors, TestProviderKeyByIdResponses, TestProviderKeyInlineData, TestProviderKeyInlineErrors, TestProviderKeyInlineResponses, TestProviderResponses, TestS3ConnectionPreviewData, TestS3ConnectionPreviewErrors, TestS3ConnectionPreviewResponses, TestS3SourceConnectionData, TestS3SourceConnectionErrors, TestS3SourceConnectionResponses, TrackClickData, TrackClickErrors, TrackOpenData, TrackOpenErrors, TrackOpenResponses, TriggerAgentData, TriggerAgentErrors, TriggerAgentResponses, TriggerProjectPipelineData, TriggerProjectPipelineErrors, TriggerProjectPipelineResponses, TriggerScanData, TriggerScanErrors, TriggerScanResponses, TriggerServiceHealthCheckData, TriggerServiceHealthCheckErrors, TriggerServiceHealthCheckResponses, TriggerWeeklyDigestData, TriggerWeeklyDigestErrors, TriggerWeeklyDigestResponses, UnlinkServiceFromProjectData, UnlinkServiceFromProjectErrors, UnlinkServiceFromProjectResponses, UpdateAgentData, UpdateAgentErrors, UpdateAgentResponses, UpdateAiProviderData, UpdateAiProviderErrors, UpdateAiProviderResponses, UpdateAlertData, UpdateAlertErrors, UpdateAlertResponses, UpdateAlertRuleData, UpdateAlertRuleErrors, UpdateAlertRuleResponses, UpdateApiKeyData, UpdateApiKeyErrors, UpdateApiKeyResponses, UpdateAutomaticDeployData, UpdateAutomaticDeployErrors, UpdateAutomaticDeployResponses, UpdateBackupScheduleData, UpdateBackupScheduleErrors, UpdateBackupScheduleResponses, UpdateCloudflareProviderData, UpdateCloudflareProviderErrors, UpdateCloudflareProviderResponses, UpdateConnectionTokenData, UpdateConnectionTokenErrors, UpdateConnectionTokenResponses, UpdateCustomDomainData, UpdateCustomDomainErrors, UpdateCustomDomainResponses, UpdateDashboardData, UpdateDashboardErrors, UpdateDashboardResponses, UpdateDeploymentTokenData, UpdateDeploymentTokenErrors, UpdateDeploymentTokenResponses, UpdateEmailProviderData, UpdateEmailProviderErrors, UpdateEmailProviderResponses, UpdateEnvironmentSettingsData, UpdateEnvironmentSettingsErrors, UpdateEnvironmentSettingsResponses, UpdateEnvironmentSubdomainData, UpdateEnvironmentSubdomainErrors, UpdateEnvironmentSubdomainResponses, UpdateEnvironmentVariableData, UpdateEnvironmentVariableErrors, UpdateEnvironmentVariableResponses, UpdateErrorGroupData, UpdateErrorGroupErrors, UpdateErrorGroupResponses, UpdateFlagData, UpdateFlagErrors, UpdateFlagResponses, UpdateFunnelData, UpdateFunnelErrors, UpdateFunnelResponses, UpdateGitProviderCredentialsData, UpdateGitProviderCredentialsErrors, UpdateGitProviderCredentialsResponses, UpdateGitSettingsData, UpdateGitSettingsErrors, UpdateGitSettingsResponses, UpdateGlobalMcpData, UpdateGlobalMcpErrors, UpdateGlobalMcpResponses, UpdateGlobalSkillData, UpdateGlobalSkillErrors, UpdateGlobalSkillResponses, UpdateIncidentStatusData, UpdateIncidentStatusErrors, UpdateIncidentStatusResponses, UpdateIpAccessControlData, UpdateIpAccessControlErrors, UpdateIpAccessControlResponses, UpdateManagedDomainData, UpdateManagedDomainErrors, UpdateManagedDomainResponses, UpdateMcpData, UpdateMcpErrors, UpdateMcpResponses, UpdateNotificationEmailProviderData, UpdateNotificationEmailProviderErrors, UpdateNotificationEmailProviderResponses, UpdateNotificationProviderData, UpdateNotificationProviderErrors, UpdateNotificationProviderResponses, UpdateOidcProviderData, UpdateOidcProviderResponses, UpdatePreferencesData, UpdatePreferencesErrors, UpdatePreferencesResponses, UpdateProjectData, UpdateProjectDeploymentConfigData, UpdateProjectDeploymentConfigErrors, UpdateProjectDeploymentConfigResponses, UpdateProjectErrors, UpdateProjectResponses, UpdateProjectSecretData, UpdateProjectSecretErrors, UpdateProjectSecretResponses, UpdateProjectSettingsData, UpdateProjectSettingsErrors, UpdateProjectSettingsResponses, UpdateProviderData, UpdateProviderErrors, UpdateProviderKeyData, UpdateProviderKeyErrors, UpdateProviderKeyResponses, UpdateProviderResponses, UpdateRouteData, UpdateRouteErrors, UpdateRouteResponses, UpdateS3SourceData, UpdateS3SourceErrors, UpdateS3SourceResponses, UpdateSelfData, UpdateSelfErrors, UpdateSelfResponses, UpdateServiceData, UpdateServiceErrors, UpdateServiceResourcesData, UpdateServiceResourcesErrors, UpdateServiceResourcesResponses, UpdateServiceResponses, UpdateSessionDurationData, UpdateSessionDurationErrors, UpdateSessionDurationResponses, UpdateSettingsData, UpdateSettingsErrors, UpdateSettingsResponses, UpdateSkillData, UpdateSkillErrors, UpdateSkillResponses, UpdateSlackProviderData, UpdateSlackProviderErrors, UpdateSlackProviderResponses, UpdateSpeedMetricsData, UpdateSpeedMetricsErrors, UpdateSpeedMetricsResponses, UpdateTeamData, UpdateTeamErrors, UpdateTeamMemberRoleData, UpdateTeamMemberRoleErrors, UpdateTeamMemberRoleResponses, UpdateTeamResponses, UpdateUserData, UpdateUserErrors, UpdateUserResponses, UpdateWebhookData, UpdateWebhookErrors, UpdateWebhookProviderData, UpdateWebhookProviderErrors, UpdateWebhookProviderResponses, UpdateWebhookResponses, UpgradePreviewGatewayData, UpgradePreviewGatewayResponses, UpgradeServiceData, UpgradeServiceErrors, UpgradeServiceResponses, UploadGlobalSkillData, UploadGlobalSkillErrors, UploadGlobalSkillResponses, UploadReleaseFileData, UploadReleaseFileErrors, UploadReleaseFileResponses, UploadSkillData, UploadSkillErrors, UploadSkillResponses, UploadSourceFileData, UploadSourceFileErrors, UploadSourceFileResponses, UploadSourceMapData, UploadSourceMapErrors, UploadSourceMapResponses, UploadStaticBundleData, UploadStaticBundleErrors, UploadStaticBundleResponses, UpsertSecretData, UpsertSecretErrors, UpsertSecretResponses, ValidateConnectionData, ValidateConnectionErrors, ValidateConnectionResponses, ValidateEmailData, ValidateEmailErrors, ValidateEmailResponses, VerifyAndEnableMfaData, VerifyAndEnableMfaErrors, VerifyAndEnableMfaResponses, VerifyDomainData, VerifyDomainErrors, VerifyDomainResponses, VerifyEmailData, VerifyEmailErrors, VerifyEmailResponses, VerifyManagedDomainData, VerifyManagedDomainErrors, VerifyManagedDomainResponses, VerifyMfaChallengeData, VerifyMfaChallengeErrors, VerifyMfaChallengeResponses, VerifyStepUpData, VerifyStepUpErrors, VerifyStepUpResponses, WakeEnvironmentData, WakeEnvironmentErrors, WakeEnvironmentResponses, WebhookTriggerData, WebhookTriggerErrors, WebhookTriggerResponses, WorkflowDryRunData, WorkflowDryRunErrors, WorkflowDryRunResponses, WriteFileData, WriteFileErrors, WriteFileResponses, WriteFilesData, WriteFilesErrors, WriteFilesResponses } from './types.gen'; export type Options = Options2 & { /** @@ -1748,6 +1748,20 @@ export const checkDomainStatus = (options: ...options }); +/** + * Inspect a source ZIP without creating a project or retaining the upload. + */ +export const inspectDropArchive = (options: Options): RequestResult => (options.client ?? client).post({ + ...formDataBodySerializer, + security: [{ scheme: 'bearer', type: 'http' }], + url: '/drop/inspect', + ...options, + headers: { + 'Content-Type': null, + ...options.headers + } +}); + /** * List all email domains */ @@ -5496,6 +5510,20 @@ export const deployFromImageUpload = (opti ...options }); +/** + * Upload source code and immediately start a preset-based deployment. + */ +export const deployFromUploadedSource = (options: Options): RequestResult => (options.client ?? client).post({ + ...formDataBodySerializer, + security: [{ scheme: 'bearer', type: 'http' }], + url: '/projects/{project_id}/environments/{environment_id}/deploy/source', + ...options, + headers: { + 'Content-Type': null, + ...options.headers + } +}); + /** * Deploy from an uploaded static bundle * diff --git a/web/src/api/client/types.gen.ts b/web/src/api/client/types.gen.ts index a826da8bf..2e5a9e062 100644 --- a/web/src/api/client/types.gen.ts +++ b/web/src/api/client/types.gen.ts @@ -5615,6 +5615,15 @@ export type DrainStatusResponse = { status: string; }; +export type DropArchiveUpload = { + file: Blob | File; +}; + +export type DropInspectionResponse = { + candidates: Array; + suggestedName: string; +}; + /** * Drop-off point: pages where visitors leave the site */ @@ -5637,6 +5646,15 @@ export type DropOffPoint = { total_views: number; }; +export type DropPresetCandidate = { + confidence: string; + directory: string; + isStatic: boolean; + label: string; + preset: string; + reason: string; +}; + export type EmailConfig = { accept_invalid_certs?: boolean; from_address: string; @@ -15572,6 +15590,10 @@ export type SmtpResult = { is_disabled: boolean; }; +export type SourceArchiveUpload = { + file: Blob | File; +}; + /** * Entry in the source backup index. Covers both DB-tracked backups * (have a row in `backups`) and S3-scan discoveries (raw S3 objects with @@ -15723,9 +15745,10 @@ export type SourceMapResponse = { * - `Git`: Source code from a Git repository (traditional flow) * - `DockerImage`: Pre-built Docker image from external registry * - `StaticFiles`: Pre-built static files uploaded as a bundle + * - `UploadedSource`: Source archive uploaded without a Git repository * - `Manual`: Flexible type that accepts any deployment method */ -export type SourceType = 'git' | 'docker_image' | 'static_files' | 'manual'; +export type SourceType = 'git' | 'docker_image' | 'static_files' | 'uploaded_source' | 'manual'; /** * A span event (log-like annotation on a span). @@ -25434,6 +25457,29 @@ export type CheckDomainStatusResponses = { export type CheckDomainStatusResponse = CheckDomainStatusResponses[keyof CheckDomainStatusResponses]; +export type InspectDropArchiveData = { + body: DropArchiveUpload; + path?: never; + query?: never; + url: '/drop/inspect'; +}; + +export type InspectDropArchiveErrors = { + /** + * Invalid or unsupported archive + */ + 400: unknown; +}; + +export type InspectDropArchiveResponses = { + /** + * Detected deployable project roots + */ + 200: DropInspectionResponse; +}; + +export type InspectDropArchiveResponse = InspectDropArchiveResponses[keyof InspectDropArchiveResponses]; + export type ListEmailDomainsData = { body?: never; path?: never; @@ -40019,6 +40065,36 @@ export type DeployFromImageUploadResponses = { export type DeployFromImageUploadResponse = DeployFromImageUploadResponses[keyof DeployFromImageUploadResponses]; +export type DeployFromUploadedSourceData = { + body: SourceArchiveUpload; + path: { + project_id: number; + environment_id: number; + }; + query?: never; + url: '/projects/{project_id}/environments/{environment_id}/deploy/source'; +}; + +export type DeployFromUploadedSourceErrors = { + /** + * Invalid source archive + */ + 400: unknown; + /** + * Project or environment not found + */ + 404: unknown; +}; + +export type DeployFromUploadedSourceResponses = { + /** + * Source deployment started + */ + 202: RemoteDeploymentResponse; +}; + +export type DeployFromUploadedSourceResponse = DeployFromUploadedSourceResponses[keyof DeployFromUploadedSourceResponses]; + export type DeployFromStaticData = { body: DeployFromStaticRequest; path: { diff --git a/web/src/components/command/CommandPalette.tsx b/web/src/components/command/CommandPalette.tsx index 190454281..f547b8d42 100644 --- a/web/src/components/command/CommandPalette.tsx +++ b/web/src/components/command/CommandPalette.tsx @@ -122,6 +122,12 @@ const mainNavItems: NavigationItem[] = [ icon: FolderPlus, keywords: ['new', 'create', 'add', 'project', 'app'], }, + { + title: 'Drop Project Files', + url: '/drop', + icon: Upload, + keywords: ['drop', 'upload', 'zip', 'folder', 'deploy', 'no git'], + }, { title: 'Import Project', url: '/projects/import-wizard', diff --git a/web/src/components/dashboard/DropButton.tsx b/web/src/components/dashboard/DropButton.tsx new file mode 100644 index 000000000..f7c341e27 --- /dev/null +++ b/web/src/components/dashboard/DropButton.tsx @@ -0,0 +1,41 @@ +import { Button } from '@/components/ui/button' +import { UploadCloud } from 'lucide-react' +import { Link, useLocation } from 'react-router' + +/** + * Global top-bar entry point to `/drop` — deploy by dropping a folder or ZIP, + * no Git remote and no CLI. + * + * Drop is reachable from the Projects header, the empty-state onboarding, the + * New Project shell and the command palette, but all four of those live inside + * the project-creation flow. This button is the one surface that follows you + * across the whole console, so "I have a folder on my desk, ship it" is always + * one click away rather than something you have to navigate back to Projects + * to find. + * + * `UploadCloud` is deliberate, not decorative: every other Drop surface already + * uses it, so the icon alone identifies the feature once you've seen it once. + * A different glyph here would fragment that association. + * + * Unconditional by design — Drop needs no operator configuration, so there is + * no "not set up" state to gate on. + */ +export function DropButton() { + const { pathname } = useLocation() + const isActive = pathname === '/drop' + + return ( + + ) +} diff --git a/web/src/components/dashboard/FirstProjectOnboarding.tsx b/web/src/components/dashboard/FirstProjectOnboarding.tsx index 146329ec7..95bac78fe 100644 --- a/web/src/components/dashboard/FirstProjectOnboarding.tsx +++ b/web/src/components/dashboard/FirstProjectOnboarding.tsx @@ -12,6 +12,7 @@ import { Play, ScrollText, Terminal, + UploadCloud, } from 'lucide-react' import { Button } from '@/components/ui/button' import { CopyButton } from '@/components/ui/copy-button' @@ -49,7 +50,8 @@ const SHOWCASE: ReadonlyArray<{ { icon: BarChart3, name: 'Analytics', - blurb: 'Visitors, pages, funnels, and a live globe — no third-party scripts.', + blurb: + 'Visitors, pages, funnels, and a live globe — no third-party scripts.', href: 'https://temps.sh/docs/analytics', }, { @@ -156,7 +158,7 @@ export function FirstProjectOnboarding({ - {/* Deploy your own — Git / CLI. */} + {/* Deploy your own — Git, CLI, or browser upload. */}
- {/* Two peer paths — Git and CLI. Migrating from another platform has + {/* Three peer paths. Migrating from another platform has its own entry point in the page header above, so it isn't repeated here as a third card. */} -
+
{/* Path A — Deploy from Git */}
@@ -224,6 +226,27 @@ export function FirstProjectOnboarding({ ))}
+ +
+
+
+ +
+
+

Drop project files

+

+ Upload a folder or ZIP; Temps detects and builds it +

+
+
+

+ Create and deploy a project directly from your browser without a + repository or local CLI setup. +

+ +
diff --git a/web/src/components/dashboard/Header.tsx b/web/src/components/dashboard/Header.tsx index d5e7b935b..2281ec216 100644 --- a/web/src/components/dashboard/Header.tsx +++ b/web/src/components/dashboard/Header.tsx @@ -4,6 +4,7 @@ import { } from '@/api/client/@tanstack/react-query.gen' import { AiAssistantButton } from '@/components/ai/AiAssistantButton' import { BackupAlertsButton } from '@/components/dashboard/BackupAlertsButton' +import { DropButton } from '@/components/dashboard/DropButton' import { useBreadcrumbs } from '@/contexts/BreadcrumbContext' import { useConsoleExtensions } from '@temps-sdk/console-kit' import { useQuery } from '@tanstack/react-query' @@ -222,7 +223,9 @@ export function Header() { {/* The "+" quick-actions menu and the theme toggle used to live here. Every entry it held is now in the command palette (⌘K), and appearance moved into the account menu — so the header keeps only - what you reach for mid-task: the assistant and alerts. */} + what you reach for mid-task: dropping files, the assistant, and + alerts. */} + diff --git a/web/src/components/drop/DropZone.tsx b/web/src/components/drop/DropZone.tsx new file mode 100644 index 000000000..223e774fa --- /dev/null +++ b/web/src/components/drop/DropZone.tsx @@ -0,0 +1,169 @@ +import { Button } from '@/components/ui/button' +import { htmlRootCandidates, isDropArchive, type DropFile } from '@/lib/drop-archive' +import { filesFromDrop, filesFromInput } from '@/lib/drop-files' +import { cn } from '@/lib/utils' +import { + FileArchive, + FileCode2, + FolderOpen, + PackageOpen, + UploadCloud, + X, +} from 'lucide-react' +import { useEffect, useId, useRef, useState } from 'react' + +interface DropZoneProps { + files: DropFile[] + /** Called with the new selection, or `[]` when the user clears it. */ + onSelect: (files: DropFile[]) => void + onError: (message: string) => void + disabled?: boolean +} + +/** + * The drag-and-drop surface shared by `/drop` (new project) and + * `/projects/:slug/drop` (deploy into an existing project). Both accept the + * same three shapes — a project folder, a single HTML file, or a `.zip` — + * because a user who learned the gesture on one page should not discover the + * other silently accepts less. + * + * `webkitdirectory` is set imperatively: React does not recognise it as a JSX + * prop, and hardcoding it would break the "choose a single file" input. + */ +export function DropZone({ + files, + onSelect, + onError, + disabled = false, +}: DropZoneProps) { + const folderInputRef = useRef(null) + const fileInputRef = useRef(null) + const [isDragging, setIsDragging] = useState(false) + const inputId = useId() + + useEffect(() => { + folderInputRef.current?.setAttribute('webkitdirectory', '') + }, []) + + const htmlPages = htmlRootCandidates(files) + const isArchive = files.length === 1 && isDropArchive(files[0].file.name) + const totalBytes = files.reduce((sum, item) => sum + item.file.size, 0) + + return ( +
{ + event.preventDefault() + if (!disabled) setIsDragging(true) + }} + onDragOver={(event) => event.preventDefault()} + onDragLeave={(event) => { + if (!event.currentTarget.contains(event.relatedTarget as Node)) { + setIsDragging(false) + } + }} + onDrop={async (event) => { + event.preventDefault() + setIsDragging(false) + if (disabled) return + try { + onSelect(await filesFromDrop(event)) + } catch (caught) { + onError( + caught instanceof Error + ? caught.message + : 'Those files could not be read' + ) + } + }} + > +
+
+ {files.length === 0 ? ( + <> +
+ +
+

+ Drag your project here +

+

+ A project folder, one HTML file, or a .zip archive. Folders are + packaged locally before upload. +

+
+ + +
+ + ) : ( + <> + +
+ {isArchive ? ( + + ) : ( + + )} +
+

+ {files.length === 1 + ? files[0].file.name + : `${files.length} files ready`} +

+

+ {(totalBytes / 1024).toLocaleString(undefined, { + maximumFractionDigits: 1, + })}{' '} + KB + {!isArchive && + ` · ${htmlPages.length} HTML page${htmlPages.length === 1 ? '' : 's'}`} +

+ + )} +
+ + onSelect(filesFromInput(event.target.files))} + /> + onSelect(filesFromInput(event.target.files))} + /> +
+ ) +} diff --git a/web/src/components/project/NewProjectShell.tsx b/web/src/components/project/NewProjectShell.tsx index 3806c92c9..8f04f59c4 100644 --- a/web/src/components/project/NewProjectShell.tsx +++ b/web/src/components/project/NewProjectShell.tsx @@ -13,6 +13,7 @@ import { Container, FolderGit2, CheckCircle2, + UploadCloud, } from 'lucide-react' import Github from '@/icons/Github' import Gitlab from '@/icons/Gitlab' @@ -70,8 +71,7 @@ export function NewProjectShell({ normalizedProviderTypes.size === 1 ? [...normalizedProviderTypes][0] : undefined - const browsePill = (soleProviderType && - PROVIDER_PILLS[soleProviderType]) || { + const browsePill = (soleProviderType && PROVIDER_PILLS[soleProviderType]) || { icon: FolderGit2, title: 'Repositories', } @@ -147,6 +147,13 @@ export function NewProjectShell({ ) })} + + + Drop files + {children} diff --git a/web/src/components/project/ProjectDeployments.tsx b/web/src/components/project/ProjectDeployments.tsx index 0d77b0574..76466418e 100644 --- a/web/src/components/project/ProjectDeployments.tsx +++ b/web/src/components/project/ProjectDeployments.tsx @@ -42,7 +42,16 @@ import { toast } from 'sonner' import { Button } from '@/components/ui/button' import { Input } from '@/components/ui/input' import { Label } from '@/components/ui/label' -import { ArrowUpRight, ChevronLeft, ChevronRight, Loader2, PlusIcon, RefreshCw, Upload } from 'lucide-react' +import { + ArrowUpRight, + ChevronLeft, + ChevronRight, + Loader2, + PlusIcon, + RefreshCw, + Upload, + UploadCloud, +} from 'lucide-react' import { EmptyPlaceholder } from '@/components/ui/empty-placeholder' const ITEMS_PER_PAGE = 10 @@ -52,7 +61,9 @@ export function ProjectDeployments({ project }: { project: ProjectResponse }) { const [selectedDeployment, setSelectedDeployment] = useState( null ) - const [promoteDeploymentId, setPromoteDeploymentId] = useState(null) + const [promoteDeploymentId, setPromoteDeploymentId] = useState( + null + ) const [promoteTargetEnv, setPromoteTargetEnv] = useState('') // Static-files deploy: upload a bundle, then deploy it to an environment. const [staticDialogOpen, setStaticDialogOpen] = useState(false) @@ -402,7 +413,7 @@ export function ProjectDeployments({ project }: { project: ProjectResponse }) { const fd = new FormData() fd.append('file', staticFile) const uploadRes = await fetch( - `/api/projects/${project.id}/static-bundles`, + `/api/projects/${project.id}/upload/static`, { method: 'POST', credentials: 'include', body: fd } ) if (!uploadRes.ok) { @@ -542,8 +553,8 @@ export function ProjectDeployments({ project }: { project: ProjectResponse }) { Deploy static files - Upload a .zip or .tar.gz of your built static site and deploy it to an - environment. + Upload a .zip or .tar.gz of your built static site and deploy it to + an environment.
@@ -558,7 +569,8 @@ export function ProjectDeployments({ project }: { project: ProjectResponse }) { /> {staticFile && (

- {staticFile.name} ({(staticFile.size / 1024 / 1024).toFixed(1)} MB) + {staticFile.name} ({(staticFile.size / 1024 / 1024).toFixed(1)}{' '} + MB)

)}
@@ -596,7 +608,9 @@ export function ProjectDeployments({ project }: { project: ProjectResponse }) { onClick={handleDeployStatic} disabled={!staticFile || !staticEnv || staticUploading} > - {staticUploading && } + {staticUploading && ( + + )} {staticUploading ? 'Deploying...' : 'Upload & deploy'} @@ -658,6 +672,13 @@ export function ProjectDeployments({ project }: { project: ProjectResponse }) { Deploy static files + ) : project.source_type === 'uploaded_source' ? ( + ) : project.source_type === 'docker_image' ? ( {project.source_type === 'static_files' ? ( @@ -750,6 +775,13 @@ export function ProjectDeployments({ project }: { project: ProjectResponse }) { Deploy static files + ) : project.source_type === 'uploaded_source' ? ( + ) : project.source_type === 'docker_image' ? ( ) : ( - )} @@ -801,7 +839,9 @@ export function ProjectDeployments({ project }: { project: ProjectResponse }) {

- Showing {(currentPage - 1) * ITEMS_PER_PAGE + 1}–{Math.min(currentPage * ITEMS_PER_PAGE, deploymentsData.total)} of {deploymentsData.total} + Showing {(currentPage - 1) * ITEMS_PER_PAGE + 1}– + {Math.min(currentPage * ITEMS_PER_PAGE, deploymentsData.total)} of{' '} + {deploymentsData.total} {currentPage} / {totalPages} @@ -853,7 +893,7 @@ export function ProjectDeployments({ project }: { project: ProjectResponse }) { } defaultType={(() => { const deployment = deploymentsData?.deployments.find( - (d) => d.id === selectedDeployment, + (d) => d.id === selectedDeployment ) if (!deployment) return 'branch' // Default to branch for new deployments if (deployment?.tag) return 'tag' @@ -892,7 +932,10 @@ export function ProjectDeployments({ project }: { project: ProjectResponse }) {

- diff --git a/web/src/lib/drop-archive.test.ts b/web/src/lib/drop-archive.test.ts new file mode 100644 index 000000000..b35d6ad4a --- /dev/null +++ b/web/src/lib/drop-archive.test.ts @@ -0,0 +1,93 @@ +import { describe, expect, test } from 'bun:test' +import { + formatDetectedProjectLabel, + htmlRootCandidates, + normalizeDropFiles, + prepareDrop, + type DropFile, +} from './drop-archive' + +function dropped(path: string, contents = path): DropFile { + const parts = path.split('/') + return { file: new File([contents], parts[parts.length - 1]), path } +} + +describe('drop archive preparation', () => { + test('hides the internal dot path for root project candidates', () => { + expect(formatDetectedProjectLabel('Static Site', '.')).toBe('Static Site') + expect(formatDetectedProjectLabel('Vite', 'apps/web')).toBe( + 'Vite · apps/web' + ) + }) + + test('removes the selected folder name but preserves its tree', () => { + const files = normalizeDropFiles([ + dropped('portfolio/index.html'), + dropped('portfolio/assets/site.css'), + ]) + + expect(files.map(({ path }) => path)).toEqual([ + 'index.html', + 'assets/site.css', + ]) + }) + + test('ignores operating-system metadata', () => { + const files = normalizeDropFiles([ + dropped('site/index.html'), + dropped('site/.DS_Store'), + dropped('site/__MACOSX/._index.html'), + ]) + + expect(files.map(({ path }) => path)).toEqual(['index.html']) + }) + + test('excludes secrets, git metadata, and dependency trees', () => { + const files = normalizeDropFiles([ + dropped('site/index.html'), + dropped('site/.env', 'TOKEN=secret'), + dropped('site/.env.local', 'TOKEN=secret'), + dropped('site/server.pem', 'secret'), + dropped('site/.git/config'), + dropped('site/node_modules/pkg/index.js'), + ]) + + expect(files.map(({ path }) => path)).toEqual(['index.html']) + }) + + test('finds root page choices when index.html is absent', () => { + expect( + htmlRootCandidates([ + dropped('site/about.html'), + dropped('site/docs/start.html'), + ]) + ).toEqual(['about.html', 'docs/start.html']) + }) + + test('packages a single HTML file as a valid zip with an index redirect', async () => { + const prepared = await prepareDrop([ + dropped('landing.html', '

Hello

'), + ]) + const bytes = new Uint8Array(await prepared.file.arrayBuffer()) + const archiveText = new TextDecoder().decode(bytes) + + expect(new DataView(bytes.buffer).getUint32(0, true)).toBe(0x04034b50) + expect(archiveText).toContain('landing.html') + expect(archiveText).toContain('index.html') + expect(prepared.rootPage).toBe('landing.html') + }) + + test('passes an existing archive through without copying it', async () => { + const archive = new File(['zip'], 'site.zip', { type: 'application/zip' }) + const prepared = await prepareDrop([{ file: archive, path: archive.name }]) + + expect(prepared.file).toBe(archive) + expect(prepared.rootPage).toBeNull() + }) + + test('rejects traversal paths', () => { + expect(() => normalizeDropFiles([dropped('../index.html')])).toThrow( + 'Unsafe path' + ) + }) +}) diff --git a/web/src/lib/drop-archive.ts b/web/src/lib/drop-archive.ts new file mode 100644 index 000000000..a19eec62e --- /dev/null +++ b/web/src/lib/drop-archive.ts @@ -0,0 +1,247 @@ +export interface DropFile { + file: File + path: string +} + +export interface PreparedDrop { + file: File + fileCount: number + rootPage: string | null +} + +const ARCHIVE_PATTERN = /\.zip$/i +const IGNORED_PATH_PARTS = new Set([ + '.DS_Store', + 'Thumbs.db', + '__MACOSX', + '.git', + 'node_modules', +]) +const textEncoder = new TextEncoder() +const MAX_BROWSER_PACKAGE_BYTES = 100 * 1024 * 1024 + +export function isDropArchive(filename: string): boolean { + return ARCHIVE_PATTERN.test(filename) +} + +export function formatDetectedProjectLabel( + label: string, + directory: string +): string { + return !directory || directory === '.' ? label : `${label} · ${directory}` +} + +function cleanPath(path: string): string { + const parts = path + .replace(/\\/g, '/') + .split('/') + .filter((part) => part && part !== '.') + + if (parts.some((part) => part === '..')) { + throw new Error(`Unsafe path in dropped files: ${path}`) + } + + return parts.join('/') +} + +function shouldIgnore(path: string): boolean { + return path + .split('/') + .some( + (part) => + IGNORED_PATH_PARTS.has(part) || + part === '.env' || + part.startsWith('.env.') || + part.endsWith('.pem') || + part.endsWith('.key') || + part === 'credentials.json' + ) +} + +export function normalizeDropFiles(files: DropFile[]): DropFile[] { + const cleaned = files + .map(({ file, path }) => ({ file, path: cleanPath(path || file.name) })) + .filter(({ path }) => path && !shouldIgnore(path)) + + if (cleaned.length === 0) return [] + + const splitPaths = cleaned.map(({ path }) => path.split('/')) + const firstPart = splitPaths[0][0] + const hasSharedFolder = splitPaths.every( + (parts) => parts.length > 1 && parts[0] === firstPart + ) + + return hasSharedFolder + ? cleaned.map(({ file, path }) => ({ + file, + path: path.slice(firstPart.length + 1), + })) + : cleaned +} + +export function htmlRootCandidates(files: DropFile[]): string[] { + return normalizeDropFiles(files) + .map(({ path }) => path) + .filter((path) => path.toLowerCase().endsWith('.html')) + .sort((a, b) => a.localeCompare(b)) +} + +function writeU16(view: DataView, offset: number, value: number) { + view.setUint16(offset, value, true) +} + +function writeU32(view: DataView, offset: number, value: number) { + view.setUint32(offset, value >>> 0, true) +} + +function crc32(bytes: Uint8Array): number { + let crc = 0xffffffff + for (const byte of bytes) { + crc ^= byte + for (let bit = 0; bit < 8; bit += 1) { + crc = (crc >>> 1) ^ (0xedb88320 & -(crc & 1)) + } + } + return (crc ^ 0xffffffff) >>> 0 +} + +function dosTimestamp(date: Date): { date: number; time: number } { + const year = Math.max(1980, date.getFullYear()) + return { + date: ((year - 1980) << 9) | ((date.getMonth() + 1) << 5) | date.getDate(), + time: + (date.getHours() << 11) | + (date.getMinutes() << 5) | + Math.floor(date.getSeconds() / 2), + } +} + +async function createStoredZip( + entries: Array<{ path: string; contents: Blob }> +): Promise { + const localParts: BlobPart[] = [] + const centralParts: BlobPart[] = [] + let localOffset = 0 + let centralSize = 0 + const now = dosTimestamp(new Date()) + + for (const entry of entries) { + const name = textEncoder.encode(cleanPath(entry.path)) + const contents = new Uint8Array(await entry.contents.arrayBuffer()) + const checksum = crc32(contents) + + const localHeader = new ArrayBuffer(30) + const localView = new DataView(localHeader) + writeU32(localView, 0, 0x04034b50) + writeU16(localView, 4, 20) + writeU16(localView, 6, 0x0800) + writeU16(localView, 8, 0) + writeU16(localView, 10, now.time) + writeU16(localView, 12, now.date) + writeU32(localView, 14, checksum) + writeU32(localView, 18, contents.byteLength) + writeU32(localView, 22, contents.byteLength) + writeU16(localView, 26, name.byteLength) + writeU16(localView, 28, 0) + localParts.push(localHeader, name, contents) + + const centralHeader = new ArrayBuffer(46) + const centralView = new DataView(centralHeader) + writeU32(centralView, 0, 0x02014b50) + writeU16(centralView, 4, 20) + writeU16(centralView, 6, 20) + writeU16(centralView, 8, 0x0800) + writeU16(centralView, 10, 0) + writeU16(centralView, 12, now.time) + writeU16(centralView, 14, now.date) + writeU32(centralView, 16, checksum) + writeU32(centralView, 20, contents.byteLength) + writeU32(centralView, 24, contents.byteLength) + writeU16(centralView, 28, name.byteLength) + writeU16(centralView, 30, 0) + writeU16(centralView, 32, 0) + writeU16(centralView, 34, 0) + writeU16(centralView, 36, 0) + writeU32(centralView, 38, 0) + writeU32(centralView, 42, localOffset) + centralParts.push(centralHeader, name) + + localOffset += 30 + name.byteLength + contents.byteLength + centralSize += 46 + name.byteLength + } + + const end = new ArrayBuffer(22) + const endView = new DataView(end) + writeU32(endView, 0, 0x06054b50) + writeU16(endView, 4, 0) + writeU16(endView, 6, 0) + writeU16(endView, 8, entries.length) + writeU16(endView, 10, entries.length) + writeU32(endView, 12, centralSize) + writeU32(endView, 16, localOffset) + writeU16(endView, 20, 0) + + return new Blob([...localParts, ...centralParts, end], { + type: 'application/zip', + }) +} + +function redirectPage(target: string): Blob { + const escaped = target + .split('/') + .map((part) => encodeURIComponent(part)) + .join('/') + const href = `./${escaped}` + return new Blob( + [ + '', + ``, + `Redirecting…Open site`, + ], + { type: 'text/html' } + ) +} + +export async function prepareDrop( + rawFiles: DropFile[], + selectedRootPage?: string +): Promise { + if (rawFiles.length === 1 && isDropArchive(rawFiles[0].file.name)) { + if (rawFiles[0].file.size > 500 * 1024 * 1024) { + throw new Error('Drop exceeds the 500 MB upload limit') + } + return { file: rawFiles[0].file, fileCount: 1, rootPage: null } + } + + const files = normalizeDropFiles(rawFiles) + if (files.length === 0) throw new Error('The selected folder is empty') + + const totalBytes = files.reduce((sum, { file }) => sum + file.size, 0) + if (totalBytes > MAX_BROWSER_PACKAGE_BYTES) { + throw new Error( + 'Folders larger than 100 MB must be zipped before upload to limit browser memory use' + ) + } + + const paths = new Set(files.map(({ path }) => path.toLowerCase())) + let rootPage: string | null = null + const entries = files.map(({ file, path }) => ({ + path, + contents: file as Blob, + })) + + if (!paths.has('index.html')) { + const candidates = htmlRootCandidates(files) + rootPage = selectedRootPage || candidates[0] || null + if (rootPage) { + entries.push({ path: 'index.html', contents: redirectPage(rootPage) }) + } + } + + const archive = await createStoredZip(entries) + return { + file: new File([archive], 'temps-drop.zip', { type: 'application/zip' }), + fileCount: files.length, + rootPage, + } +} diff --git a/web/src/lib/drop-files.ts b/web/src/lib/drop-files.ts new file mode 100644 index 000000000..792756208 --- /dev/null +++ b/web/src/lib/drop-files.ts @@ -0,0 +1,131 @@ +import type { DropFile } from '@/lib/drop-archive' + +/** + * Browser plumbing for turning a drag-and-drop or file-picker gesture into a + * flat `DropFile[]`, shared by the standalone `/drop` page and the + * project-scoped `/projects/:slug/drop` page. + * + * Folder drops only work through the non-standard `webkitGetAsEntry` API — + * `dataTransfer.files` flattens a directory to nothing. Every browser Temps + * supports implements it, but it is not in the DOM lib types, so the minimal + * `Legacy*` shapes below describe just the parts we call. + */ + +interface LegacyFileSystemEntry { + isFile: boolean + isDirectory: boolean + name: string +} + +interface LegacyFileEntry extends LegacyFileSystemEntry { + file(success: (file: File) => void, error: (error: DOMException) => void): void +} + +interface LegacyDirectoryReader { + readEntries( + success: (entries: LegacyFileSystemEntry[]) => void, + error: (error: DOMException) => void + ): void +} + +interface LegacyDirectoryEntry extends LegacyFileSystemEntry { + createReader(): LegacyDirectoryReader +} + +/** + * `readEntries` returns at most ~100 entries per call and signals completion + * with an empty batch, so a large directory needs to be drained in a loop. + */ +async function readDirectoryEntries( + directory: LegacyDirectoryEntry +): Promise { + const reader = directory.createReader() + const entries: LegacyFileSystemEntry[] = [] + while (true) { + const batch = await new Promise((resolve, reject) => + reader.readEntries(resolve, reject) + ) + if (batch.length === 0) return entries + entries.push(...batch) + } +} + +async function readEntry( + entry: LegacyFileSystemEntry, + prefix = '' +): Promise { + const path = prefix ? `${prefix}/${entry.name}` : entry.name + if (entry.isFile) { + const file = await new Promise((resolve, reject) => + (entry as LegacyFileEntry).file(resolve, reject) + ) + return [{ file, path }] + } + if (!entry.isDirectory) return [] + + const children = await readDirectoryEntries(entry as LegacyDirectoryEntry) + const nested = await Promise.all(children.map((child) => readEntry(child, path))) + return nested.flat() +} + +/** Read a drop event into `DropFile[]`, recursing into dropped directories. */ +export async function filesFromDrop( + event: React.DragEvent +): Promise { + const items = Array.from(event.dataTransfer.items) + const entryItems = items + .map((item) => { + const getEntry = ( + item as DataTransferItem & { + webkitGetAsEntry?: () => LegacyFileSystemEntry | null + } + ).webkitGetAsEntry + return getEntry?.call(item) ?? null + }) + .filter((entry): entry is LegacyFileSystemEntry => entry !== null) + + if (entryItems.length > 0) { + return (await Promise.all(entryItems.map((entry) => readEntry(entry)))).flat() + } + + return Array.from(event.dataTransfer.files).map((file) => ({ + file, + path: file.webkitRelativePath || file.name, + })) +} + +/** Read an `` selection into `DropFile[]`. */ +export function filesFromInput(selected: FileList | null): DropFile[] { + if (!selected) return [] + return Array.from(selected).map((file) => ({ + file, + path: file.webkitRelativePath || file.name, + })) +} + +/** Best-effort project name from the dropped folder or archive name. */ +export function inferredProjectName(files: DropFile[]): string { + const firstPath = files[0]?.path.replace(/\\/g, '/') || '' + const parts = firstPath.split('/').filter(Boolean) + const source = parts.length > 1 ? parts[0] : parts[0] || '' + return source + .replace(/\.(tar\.gz|tgz|zip|tar|html?)$/i, '') + .replace(/[_-]+/g, ' ') + .trim() +} + +/** + * Unwrap whatever the API client threw into something worth showing a user. + * Problem Details put the useful sentence in `detail`, not `message`. + */ +export function dropErrorMessage( + error: unknown, + fallback = 'The drop could not be deployed' +): string { + if (error instanceof Error) return error.message + if (error && typeof error === 'object') { + const problem = error as { detail?: string; message?: string } + return problem.detail || problem.message || fallback + } + return fallback +} diff --git a/web/src/lib/drop-project-name.test.ts b/web/src/lib/drop-project-name.test.ts new file mode 100644 index 000000000..675d85a06 --- /dev/null +++ b/web/src/lib/drop-project-name.test.ts @@ -0,0 +1,29 @@ +import { describe, expect, test } from 'bun:test' +import { + ensureDropProjectName, + normalizeDropProjectName, +} from './drop-project-name' + +describe('Drop project names', () => { + test('slugifies spaces, punctuation, casing, and accents', () => { + expect(normalizeDropProjectName('My Café Site!')).toBe('my-cafe-site') + }) + + test('truncates names to the project DNS-label budget', () => { + const result = normalizeDropProjectName(`${'very-long-'.repeat(8)}site`) + expect(result.length).toBeLessThanOrEqual(40) + expect(result.endsWith('-')).toBe(false) + }) + + test('generates a stable-shaped fallback when no usable name exists', () => { + expect(ensureDropProjectName('🔥🔥', () => 'a1b2c3d4')).toBe( + 'drop-a1b2c3d4' + ) + }) + + test('does not add randomness to a usable name', () => { + expect(ensureDropProjectName('Release Candidate', () => 'unused')).toBe( + 'release-candidate' + ) + }) +}) diff --git a/web/src/lib/drop-project-name.ts b/web/src/lib/drop-project-name.ts new file mode 100644 index 000000000..5daa52051 --- /dev/null +++ b/web/src/lib/drop-project-name.ts @@ -0,0 +1,28 @@ +import { customAlphabet } from 'nanoid' +import slugify from 'slugify' + +const randomDropId = customAlphabet('abcdefghijklmnopqrstuvwxyz0123456789', 8) +const MAX_PROJECT_NAME_LENGTH = 40 + +/** + * Convert user- or filename-derived text to the same DNS-safe shape used by + * project URLs. An empty result is intentionally preserved so callers can + * distinguish "still editing" from "needs a generated name". + */ +export function normalizeDropProjectName(value: string): string { + return slugify(value, { + lower: true, + strict: true, + trim: true, + }) + .slice(0, MAX_PROJECT_NAME_LENGTH) + .replace(/-+$/g, '') +} + +/** Return a valid project slug, generating one when the source has no name. */ +export function ensureDropProjectName( + value: string, + createId: () => string = randomDropId +): string { + return normalizeDropProjectName(value) || `drop-${createId()}` +} diff --git a/web/src/pages/Drop.tsx b/web/src/pages/Drop.tsx new file mode 100644 index 000000000..dacc86442 --- /dev/null +++ b/web/src/pages/Drop.tsx @@ -0,0 +1,492 @@ +import { + createProject, + deleteProject, + deployFromUploadedSource, + deployFromStatic, + getEnvironments, + inspectDropArchive, + type DropInspectionResponse, + type EnvironmentResponse, + type ProjectResponse, +} from '@/api/client' +import { DropZone } from '@/components/drop/DropZone' +import { PageContainer } from '@/components/layout/PageContainer' +import { Button } from '@/components/ui/button' +import { Input } from '@/components/ui/input' +import { Label } from '@/components/ui/label' +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from '@/components/ui/select' +import { useBreadcrumbs } from '@/contexts/BreadcrumbContext' +import { usePageTitle } from '@/hooks/usePageTitle' +import { + formatDetectedProjectLabel, + htmlRootCandidates, + isDropArchive, + prepareDrop, + type DropFile, +} from '@/lib/drop-archive' +import { dropErrorMessage, inferredProjectName } from '@/lib/drop-files' +import { ensureDropProjectName } from '@/lib/drop-project-name' +import { cn } from '@/lib/utils' +import { ArrowRight, Check, Loader2, RotateCcw, UploadCloud } from 'lucide-react' +import { useEffect, useMemo, useState } from 'react' +import { Link, useNavigate } from 'react-router' + +type DropStage = + | 'idle' + | 'packing' + | 'detecting' + | 'creating' + | 'uploading' + | 'deploying' + | 'done' + +function stageLabel(stage: DropStage): string { + switch (stage) { + case 'packing': + return 'Packing files locally' + case 'creating': + return 'Creating project' + case 'detecting': + return 'Detecting preset' + case 'uploading': + return 'Uploading project' + case 'deploying': + return 'Starting deployment' + case 'done': + return 'Deployment started' + default: + return 'Ready to deploy' + } +} + +export function Drop() { + const navigate = useNavigate() + const { setBreadcrumbs } = useBreadcrumbs() + const [files, setFiles] = useState([]) + const [projectName, setProjectName] = useState('') + const [nameWasEdited, setNameWasEdited] = useState(false) + const [rootPage, setRootPage] = useState('') + const [stage, setStage] = useState('idle') + const [error, setError] = useState(null) + const [project, setProject] = useState(null) + const [environment, setEnvironment] = useState( + null + ) + const [preparedArchive, setPreparedArchive] = useState(null) + const [inspection, setInspection] = useState( + null + ) + const [selectedCandidateIndex, setSelectedCandidateIndex] = useState('0') + + usePageTitle('Drop') + useEffect(() => { + setBreadcrumbs([ + { label: 'Projects', href: '/projects' }, + { label: 'Drop' }, + ]) + }, [setBreadcrumbs]) + + const normalizedCandidates = useMemo(() => htmlRootCandidates(files), [files]) + const hasRootIndex = normalizedCandidates.some( + (path) => path.toLowerCase() === 'index.html' + ) + const isArchive = files.length === 1 && isDropArchive(files[0].file.name) + const isBusy = !['idle', 'done'].includes(stage) + + const setSelection = (nextFiles: DropFile[]) => { + setFiles(nextFiles) + setError(null) + setProject(null) + setEnvironment(null) + setPreparedArchive(null) + setInspection(null) + setSelectedCandidateIndex('0') + setStage('idle') + const candidates = htmlRootCandidates(nextFiles) + const hasIndex = candidates.some( + (path) => path.toLowerCase() === 'index.html' + ) + setRootPage(hasIndex ? '' : candidates[0] || '') + if (!nameWasEdited) { + setProjectName(ensureDropProjectName(inferredProjectName(nextFiles))) + } + } + + const reset = () => { + setFiles([]) + setProjectName('') + setNameWasEdited(false) + setRootPage('') + setStage('idle') + setError(null) + setProject(null) + setEnvironment(null) + setPreparedArchive(null) + setInspection(null) + setSelectedCandidateIndex('0') + } + + const deploy = async () => { + if (files.length === 0 || isBusy) return + + let createdProject: ProjectResponse | null = null + let deploymentAccepted = false + const normalizedProjectName = ensureDropProjectName(projectName) + setProjectName(normalizedProjectName) + setError(null) + try { + let archive = preparedArchive + let detected = inspection + if (!archive || !detected) { + setStage('packing') + const prepared = await prepareDrop(files, rootPage || undefined) + archive = prepared.file + setPreparedArchive(archive) + + setStage('detecting') + const inspectResponse = await inspectDropArchive({ + throwOnError: true, + body: { file: archive }, + }) + detected = inspectResponse.data + if (!detected) throw new Error('Preset detection returned no result') + setInspection(detected) + setSelectedCandidateIndex('0') + if (!nameWasEdited) { + setProjectName(ensureDropProjectName(detected.suggestedName)) + } + setStage('idle') + return + } + + const candidate = detected.candidates[Number(selectedCandidateIndex)] + if (!candidate) throw new Error('Choose a detected project preset') + + setStage('creating') + const projectResult = await createProject({ + throwOnError: true, + body: { + name: normalizedProjectName, + directory: candidate.directory, + main_branch: 'main', + // Static-file projects do not build this preset, but project creation + // still validates the catalog slug. Match the existing manual-project + // flow and use a known built-in preset as metadata. + preset: candidate.preset, + source_type: candidate.isStatic ? 'static_files' : 'uploaded_source', + project_type: candidate.isStatic ? 'static' : 'server', + automatic_deploy: false, + storage_service_ids: [], + }, + }) + createdProject = projectResult.data + if (!createdProject) throw new Error('Temps created no project record') + + const environmentsResult = await getEnvironments({ + throwOnError: true, + path: { project_id: createdProject.id }, + }) + const environments = environmentsResult.data || [] + const targetEnvironment = + environments.find((item) => item.name.toLowerCase() === 'production') || + environments.find((item) => !item.is_preview) || + environments[0] + if (!targetEnvironment) + throw new Error('The project has no deployment environment') + + setStage('uploading') + const body = new FormData() + body.append('file', archive) + if (!candidate.isStatic) { + const sourceResponse = await deployFromUploadedSource({ + throwOnError: true, + path: { + project_id: createdProject.id, + environment_id: targetEnvironment.id, + }, + body: { file: archive }, + }) + const sourceDeployment = sourceResponse.data + if (!sourceDeployment) + throw new Error('Source deployment returned no result') + deploymentAccepted = true + navigate( + `/projects/${createdProject.slug}/deployments/${sourceDeployment.id}` + ) + return + } + const uploadResponse = await fetch( + `/api/projects/${createdProject.id}/upload/static`, + { method: 'POST', credentials: 'include', body } + ) + if (!uploadResponse.ok) { + const problem = (await uploadResponse.json().catch(() => null)) as { + detail?: string + } | null + throw new Error( + problem?.detail || `Upload failed (${uploadResponse.status})` + ) + } + const bundle = (await uploadResponse.json()) as { id: number } + + setStage('deploying') + await deployFromStatic({ + throwOnError: true, + path: { + project_id: createdProject.id, + environment_id: targetEnvironment.id, + }, + body: { static_bundle_id: bundle.id }, + }) + deploymentAccepted = true + setProject(createdProject) + setEnvironment(targetEnvironment) + setStage('done') + } catch (caught) { + let message = dropErrorMessage(caught) + if (createdProject && !deploymentAccepted) { + try { + await deleteProject({ + throwOnError: true, + path: { id: createdProject.id }, + }) + message += ' The incomplete project was removed.' + } catch (cleanupError) { + message += ` Cleanup also failed: ${dropErrorMessage(cleanupError)}` + } + } + setError(message) + setStage('idle') + } + } + + if (stage === 'done' && project && environment) { + return ( + +
+
+
+
+ +
+

+ Drop accepted +

+

+ {project.name} is on its way live. +

+

+ Temps accepted the bundle and started the deployment. The project + page has the live build log and final status. +

+
+ + + +
+
+
+ + ) + } + + return ( + +
+
+

+ Repository optional +

+

+ Drop files. Get a deployment. +

+

+ Ship a static site or application without Git or a CLI. Temps + detects the preset, creates a project, and starts the right build + pipeline in one pass. +

+
+
+ 01 Select + 02 Name + 03 Deploy +
+
+ +
+ + + +
+ +
+ ) +} diff --git a/web/src/pages/ProjectDetail.tsx b/web/src/pages/ProjectDetail.tsx index 37f250f54..53640afe4 100644 --- a/web/src/pages/ProjectDetail.tsx +++ b/web/src/pages/ProjectDetail.tsx @@ -8,6 +8,7 @@ import { import NotFound from '@/components/global/NotFound' import { ProjectAnalytics } from '@/components/project/ProjectAnalytics' import { ProjectDeployments } from '@/components/project/ProjectDeployments' +import { ProjectDrop } from '@/pages/ProjectDrop' import { ProjectDetailHeader } from '@/components/project/ProjectDetailHeader' import { ProjectOverview } from '@/components/project/ProjectOverview' import { ProjectRevenue } from '@/components/project/ProjectRevenue' @@ -354,6 +355,7 @@ export function ProjectDetail() { path="deployments/:deploymentId" element={} /> + } /> } diff --git a/web/src/pages/ProjectDrop.tsx b/web/src/pages/ProjectDrop.tsx new file mode 100644 index 000000000..487412f7c --- /dev/null +++ b/web/src/pages/ProjectDrop.tsx @@ -0,0 +1,380 @@ +import { + deployFromStatic, + deployFromUploadedSource, + getEnvironments, + inspectDropArchive, + updateProjectSettings, + type DropInspectionResponse, + type EnvironmentResponse, + type ProjectResponse, +} from '@/api/client' +import { DropZone } from '@/components/drop/DropZone' +import { Button } from '@/components/ui/button' +import { Label } from '@/components/ui/label' +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from '@/components/ui/select' +import { usePageTitle } from '@/hooks/usePageTitle' +import { + formatDetectedProjectLabel, + htmlRootCandidates, + isDropArchive, + prepareDrop, + type DropFile, +} from '@/lib/drop-archive' +import { dropErrorMessage } from '@/lib/drop-files' +import { cn } from '@/lib/utils' +import { Loader2, UploadCloud } from 'lucide-react' +import { useEffect, useMemo, useState } from 'react' +import { useNavigate } from 'react-router' + +type Stage = 'idle' | 'packing' | 'detecting' | 'saving' | 'uploading' | 'deploying' + +function stageLabel(stage: Stage, detected: boolean): string { + switch (stage) { + case 'packing': + return 'Packing files locally' + case 'detecting': + return 'Detecting preset' + case 'saving': + return 'Updating build configuration' + case 'uploading': + return 'Uploading source' + case 'deploying': + return 'Starting deployment' + default: + return detected ? 'Deploy' : 'Detect preset' + } +} + +/** + * Deploy a new source archive into an **existing** project — the same gesture + * as `/drop`, but targeting a project that already exists instead of creating + * one. + * + * This replaced a plain `` dialog that accepted only a + * `.zip` and did no detection. That was a worse experience than the front-door + * `/drop` page for the exact users most likely to repeat the action, so both + * paths now share `DropZone` and the same detect-then-deploy flow: folder, + * single HTML file, or ZIP. + * + * **What this page may change about the project:** the build `directory` and + * `preset` only, and only when the user picks a candidate that differs from + * what the project already has. Port, resource limits, environment variables, + * domains and every other setting are deliberately left alone — re-uploading + * source is not an invitation to silently re-provision the service. + */ +export function ProjectDrop({ project }: { project: ProjectResponse }) { + const navigate = useNavigate() + const [files, setFiles] = useState([]) + const [rootPage, setRootPage] = useState('') + const [stage, setStage] = useState('idle') + const [error, setError] = useState(null) + const [preparedArchive, setPreparedArchive] = useState(null) + const [inspection, setInspection] = useState( + null + ) + const [candidateIndex, setCandidateIndex] = useState('0') + const [environments, setEnvironments] = useState([]) + const [environmentId, setEnvironmentId] = useState('') + + usePageTitle(`Upload source · ${project.name}`) + + const isBusy = stage !== 'idle' + const htmlPages = useMemo(() => htmlRootCandidates(files), [files]) + const hasRootIndex = htmlPages.some((p) => p.toLowerCase() === 'index.html') + const isArchive = files.length === 1 && isDropArchive(files[0].file.name) + const candidate = inspection?.candidates[Number(candidateIndex)] + + // Environments are needed before the first deploy; production is the sane + // default so the common case is zero clicks. + useEffect(() => { + let cancelled = false + getEnvironments({ path: { project_id: project.id } }) + .then((result) => { + if (cancelled) return + const list = result.data || [] + setEnvironments(list) + const preferred = + list.find((e) => e.name.toLowerCase() === 'production') || + list.find((e) => !e.is_preview) || + list[0] + if (preferred) setEnvironmentId(String(preferred.id)) + }) + .catch((caught) => { + if (!cancelled) setError(dropErrorMessage(caught)) + }) + return () => { + cancelled = true + } + }, [project.id]) + + // Once detection returns, prefer the candidate matching the project's current + // build directory — a repeat upload of the same app should not silently + // switch which directory gets built. + useEffect(() => { + if (!inspection) return + const current = (project.directory || '.').replace(/^\.\/+/, '') || '.' + const match = inspection.candidates.findIndex( + (c) => (c.directory || '.') === current + ) + setCandidateIndex(String(match >= 0 ? match : 0)) + }, [inspection, project.directory]) + + const select = (next: DropFile[]) => { + setFiles(next) + setError(null) + setPreparedArchive(null) + setInspection(null) + setCandidateIndex('0') + setStage('idle') + const candidates = htmlRootCandidates(next) + const hasIndex = candidates.some((p) => p.toLowerCase() === 'index.html') + setRootPage(hasIndex ? '' : candidates[0] || '') + } + + const run = async () => { + if (files.length === 0 || isBusy || !environmentId) return + setError(null) + try { + // First press packs + detects and stops, so the user can confirm the + // detected directory before anything is written. + if (!preparedArchive || !inspection) { + setStage('packing') + const prepared = await prepareDrop(files, rootPage || undefined) + setPreparedArchive(prepared.file) + + setStage('detecting') + const response = await inspectDropArchive({ + throwOnError: true, + body: { file: prepared.file }, + }) + if (!response.data) throw new Error('Preset detection returned no result') + setInspection(response.data) + setStage('idle') + return + } + + if (!candidate) throw new Error('Choose a detected project') + + // Only persist directory/preset, and only when they actually changed. + const currentDirectory = (project.directory || '.').replace(/^\.\/+/, '') || '.' + const nextDirectory = candidate.directory || '.' + if (nextDirectory !== currentDirectory || candidate.preset !== project.preset) { + setStage('saving') + await updateProjectSettings({ + throwOnError: true, + path: { project_id: project.id }, + body: { directory: nextDirectory, preset: candidate.preset }, + }) + } + + const targetEnvironment = Number(environmentId) + + if (candidate.isStatic) { + setStage('uploading') + const body = new FormData() + body.append('file', preparedArchive) + const uploadResponse = await fetch( + `/api/projects/${project.id}/upload/static`, + { method: 'POST', credentials: 'include', body } + ) + if (!uploadResponse.ok) { + const problem = (await uploadResponse.json().catch(() => null)) as { + detail?: string + } | null + throw new Error( + problem?.detail || `Upload failed (${uploadResponse.status})` + ) + } + const bundle = (await uploadResponse.json()) as { id: number } + + setStage('deploying') + await deployFromStatic({ + throwOnError: true, + path: { project_id: project.id, environment_id: targetEnvironment }, + body: { static_bundle_id: bundle.id }, + }) + navigate(`/projects/${project.slug}/deployments?autoRefresh=true`) + return + } + + setStage('uploading') + const response = await deployFromUploadedSource({ + throwOnError: true, + path: { project_id: project.id, environment_id: targetEnvironment }, + body: { file: preparedArchive }, + }) + const deployment = response.data + if (!deployment) throw new Error('Source deployment returned no result') + navigate(`/projects/${project.slug}/deployments/${deployment.id}`) + } catch (caught) { + setError(dropErrorMessage(caught)) + setStage('idle') + } + } + + return ( +
+
+

+ Repository optional +

+ {/* h2, not h1 — the project shell already renders the page's h1. */} +

+ Upload new source +

+

+ Drop a folder or ZIP to build and deploy a new version of{' '} + {project.name}. + Only the build directory and preset can change here — ports, resources + and environment variables stay as configured. +

+
+ +
+ + + +
+
+ ) +} diff --git a/web/src/pages/Projects.tsx b/web/src/pages/Projects.tsx index 57e1b4a7e..12badb1a8 100644 --- a/web/src/pages/Projects.tsx +++ b/web/src/pages/Projects.tsx @@ -27,6 +27,7 @@ import { Minus, TrendingDown, TrendingUp, + UploadCloud, Users, } from 'lucide-react' import { Link, useNavigate } from 'react-router' @@ -310,6 +311,12 @@ export function Projects() { actions={ <> + }