openapi: 3.0.3
info:
title: Volcano Hosting API
description: |-
Public API for Volcano Hosting clients, SDKs, and CLI tooling (Port 8000).
This specification intentionally excludes first-party/internal APIs. See api/openapi-internal.yaml for non-public internal and Builder operations.
version: 3.0.0
contact:
name: Volcano Hosting
email: support@volcano.dev
servers:
- url: https://api.volcano.dev
description: Production API server
- url: http://localhost:8000
description: Development API server (use VOLCANO_API_URL env var)
tags:
- name: Projects
description: Project management operations
- name: Logs
description: Project-scoped log search and activity APIs
- name: Functions
description: Function deployment and management
- name: Durable Functions
description: |-
Long-running functions that checkpoint their progress and resume from the
last completed step, and the executions started against them. Separate
from Functions because a durable function is started asynchronously: what
a start returns is an execution to poll and stop, not a result. Durable
work is metered on its own allowances: executions, and the operations each
execution performs while it runs.
- name: Frontends
description: Frontend deployment and management. Supports Next.js 15.x and 16.x with Node.js 22.x or 24.x inferred from package.json engines.node when the selected Node.js family satisfies the installed Next.js package engines.node constraint.
- name: Tokens
description: Service keys for function invocation and database admin access
- name: Variables
description: Environment variable management
- name: Databases
description: Serverless PostgreSQL database provisioning and management
- name: Database Branches
description: Short-lived forks of a database for development and testing
- name: Database Queries
description: REST API for querying databases (SELECT, INSERT, UPDATE, DELETE)
- name: Authentication
description: End-user authentication (signup, signin, profile)
- name: Auth Admin
description: Auth user management (platform admin only)
- name: Auth Configuration
description: Authentication settings and anon keys
- name: Anon Keys
description: Project-specific public keys for frontend auth
- name: Service Keys
description: Project-specific secret keys for admin operations (bypass RLS - backend only!)
- name: OAuth Configuration
description: OAuth provider configuration (Google, GitHub, Microsoft, Apple)
- name: OAuth Authentication
description: OAuth login flows and provider management for end users
- name: Git Connections
description: Platform-user git provider connections for deployment source integrations
- name: Project Imports
description: Read-only project source discovery and import readiness checks
- name: Storage Buckets
description: Storage bucket management (platform admin)
- name: Storage Policies
description: Storage access policy management (platform admin)
- name: Storage Admin
description: Storage statistics and cross-bucket object listing (platform admin)
- name: Storage Objects
description: File upload, download, and management (SDK-facing)
- name: Locks
description: Project-scoped leases for backend coordination (service-role keys only)
- name: Realtime
description: WebSocket realtime configuration and monitoring
- name: System
description: System health and monitoring endpoints
- name: CLI Authentication
description: |
Browser-based CLI login flow for automatic token provisioning.
The CLI creates a session, opens a browser for user authentication,
and polls for completion. Session completion is handled by volcano.dev
via the Management API.
paths:
/user/imports/connect:
post:
tags:
- Project Imports
summary: Start a project import provider connection
description: |
Starts a first-party dashboard user's provider connection flow. The
response sets a short-lived HttpOnly browser-binding cookie for the
public provider callback.
operationId: startImportConnect
security:
- UserToken: []
- AuthUserAccessToken: []
parameters:
- name: provider
in: query
required: false
description: Import provider to connect. Defaults to Vercel.
schema:
$ref: '#/components/schemas/ImportProvider'
- name: redirect
in: query
required: false
description: Validated application URL used after the provider callback.
schema:
type: string
format: uri
pattern: ^https://[^/?#]+(?:[/?][^#]*)?$|^http://(?:localhost|127\.0\.0\.1|\[::1\])(?::[0-9]+)?(?:[/?][^#]*)?$
responses:
'200':
description: Provider authorization URL
content:
application/json:
schema:
$ref: '#/components/schemas/ImportConnectStartResponse'
'400':
description: Unsupported provider or invalid redirect
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Not authenticated
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Failed to start the connection
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'503':
description: Import provider integration is not configured
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/imports/{provider}/callback:
get:
tags:
- Project Imports
summary: Complete a project import provider connection
description: |
Public provider callback protected by signed state and the browser-binding
cookie created by startImportConnect.
operationId: completeImportConnect
security: []
parameters:
- name: provider
in: path
required: true
schema:
$ref: '#/components/schemas/ImportProvider'
- name: state
in: query
required: true
description: Signed connect state generated by startImportConnect.
schema:
type: string
- name: code
in: query
required: false
description: Provider authorization code.
schema:
type: string
- name: error
in: query
required: false
description: Provider error category.
schema:
type: string
- name: teamId
in: query
required: false
description: Vercel team selected during installation.
schema:
type: string
- name: configurationId
in: query
required: false
description: Vercel Integration configuration identifier.
schema:
type: string
- name: next
in: query
required: false
description: Provider completion URL validated by the provider adapter.
schema:
type: string
- name: source
in: query
required: false
description: Vercel installation source indicator.
schema:
type: string
responses:
'303':
description: Redirect to the provider completion URL, signed application redirect, or Volcano import page
headers:
Location:
description: Validated redirect target
schema:
type: string
'400':
description: Invalid callback request, state, or browser binding
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'429':
description: Too many callback attempts
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Failed to complete the connection
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'503':
description: Import provider integration is not configured
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/user/imports/connections:
get:
tags:
- Project Imports
summary: List project import provider connections
operationId: listImportConnections
security:
- UserToken: []
- AuthUserAccessToken: []
responses:
'200':
description: Stored import provider connections
content:
application/json:
schema:
$ref: '#/components/schemas/ImportConnectionsResponse'
'401':
description: Not authenticated
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Failed to list connections
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/user/imports/connections/{connectionId}:
delete:
tags:
- Project Imports
summary: Delete a project import provider connection
operationId: deleteImportConnection
security:
- UserToken: []
- AuthUserAccessToken: []
parameters:
- name: connectionId
in: path
required: true
description: Connection ID to delete.
schema:
type: string
format: uuid
responses:
'204':
description: Connection deleted
'400':
description: Malformed connection ID
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Not authenticated
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Connection not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'409':
description: Connection changed while it was being deleted
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Failed to delete the connection
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'503':
description: Import provider integration is not configured
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/imports/{provider}/sources:
get:
tags:
- Project Imports
summary: List project sources available from a provider connection
description: Lists provider projects without changing provider or Volcano resources.
operationId: listImportSources
security:
- UserToken: []
- AuthUserAccessToken: []
parameters:
- name: provider
in: path
required: true
schema:
$ref: '#/components/schemas/ImportProvider'
- name: connection_id
in: query
required: true
description: Owned provider connection used for discovery.
schema:
type: string
format: uuid
responses:
'200':
description: Provider sources available to import
content:
application/json:
schema:
$ref: '#/components/schemas/ImportSourcesResponse'
'400':
description: Invalid provider or connection ID
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Not authenticated
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'403':
description: The provider connection lacks a required Integration scope
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Connection or provider source not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'409':
description: The provider connection must be reconnected
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'429':
description: Provider rate limit exceeded
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Failed to list provider sources
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'503':
description: Provider unavailable or integration not configured
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/imports/{provider}/preflight:
post:
tags:
- Project Imports
summary: Check whether a provider project is ready to import
description: Produces a deterministic read-only readiness report for a proposed new Volcano project.
operationId: preflightProjectImport
security:
- UserToken: []
- AuthUserAccessToken: []
parameters:
- name: provider
in: path
required: true
schema:
$ref: '#/components/schemas/ImportProvider'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/ProjectImportPreflightRequest'
responses:
'200':
description: Import readiness report
content:
application/json:
schema:
$ref: '#/components/schemas/ProjectImportReport'
'400':
description: Invalid provider, source, project name, or target
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Not authenticated
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'403':
description: The provider connection lacks a required Integration scope
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Connection or provider source not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'409':
description: The provider connection must be reconnected
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'429':
description: Provider rate limit exceeded
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Failed to produce an import readiness report
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'503':
description: Provider unavailable or integration not configured
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/imports/{provider}/runs:
post:
tags:
- Project Imports
summary: Start a Vercel project import
description: Creates a Volcano project from an importable production preflight report. Retrying the same request with the same Idempotency-Key returns the existing run.
operationId: startProjectImport
security:
- UserToken: []
- AuthUserAccessToken: []
parameters:
- name: provider
in: path
required: true
schema:
$ref: '#/components/schemas/ImportProvider'
- name: Idempotency-Key
in: header
required: true
schema:
type: string
minLength: 1
maxLength: 255
pattern: ^[!-~]+$
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/ProjectImportStartRequest'
responses:
'202':
description: Import run accepted
headers:
Location:
required: true
schema:
type: string
content:
application/json:
schema:
$ref: '#/components/schemas/ProjectImportRun'
'400':
description: Invalid request or idempotency key
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Not authenticated
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'403':
description: Provider permission or project admission denied
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Connection or provider source not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'409':
description: Preflight is stale, idempotency key was reused, or destination conflicts
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'422':
description: Source is not importable
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'429':
description: Provider rate limit exceeded
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Failed to start the import
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'503':
description: Provider unavailable or integration not configured
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/imports/{provider}/runs/{runId}:
get:
tags:
- Project Imports
summary: Get a project import run
operationId: getProjectImportRun
security:
- UserToken: []
- AuthUserAccessToken: []
parameters:
- name: provider
in: path
required: true
schema:
$ref: '#/components/schemas/ImportProvider'
- name: runId
in: path
required: true
schema:
type: string
format: uuid
responses:
'200':
description: Import run status
content:
application/json:
schema:
$ref: '#/components/schemas/ProjectImportRun'
'400':
description: Invalid import run ID
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Not authenticated
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Import run not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Failed to get the import run
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/user/git/connect:
post:
tags:
- Git Connections
summary: Start a git provider connection
description: |
Starts a first-party dashboard user's git provider connection flow and
returns the provider authorization URL. The response also sets a
short-lived HttpOnly callback binding cookie tied to the authenticated
user through the signed provider state.
operationId: startGitConnect
security:
- UserToken: []
- AuthUserAccessToken: []
parameters:
- name: provider
in: query
required: false
description: Git provider to connect. Defaults to github.
schema:
type: string
enum:
- github
default: github
- name: redirect
in: query
required: false
description: URL to redirect the browser to after the provider callback completes.
schema:
type: string
responses:
'200':
description: Provider authorization URL
content:
application/json:
schema:
$ref: '#/components/schemas/GitConnectStartResponse'
'400':
description: Unsupported provider or invalid redirect
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Not authenticated
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Failed to start the connection
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'503':
description: Git provider integration is not configured
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/user/git/connections:
get:
tags:
- Git Connections
summary: List git provider connections
operationId: listGitConnections
security:
- UserToken: []
- AuthUserAccessToken: []
responses:
'200':
description: Stored git provider connections
content:
application/json:
schema:
$ref: '#/components/schemas/GitConnectionsResponse'
'401':
description: Not authenticated
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Failed to list connections
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'503':
description: Git provider integration is not configured
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/user/git/connections/{connectionId}:
delete:
tags:
- Git Connections
summary: Delete a git provider connection
operationId: deleteGitConnection
security:
- UserToken: []
- AuthUserAccessToken: []
parameters:
- name: connectionId
in: path
required: true
description: Connection ID to delete
schema:
type: string
format: uuid
responses:
'204':
description: Connection deleted
'400':
description: Malformed connection ID
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Not authenticated
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Connection not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Failed to delete connection
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'503':
description: Git provider integration is not configured
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/user/git/connections/{connectionId}/installations:
get:
tags:
- Git Connections
summary: List GitHub App installations accessible to a connection
description: |
Live proxy to GitHub: lists the platform GitHub App installations the
connection's stored user token can access. Nothing is persisted by
this call.
operationId: listGitInstallations
security:
- UserToken: []
- AuthUserAccessToken: []
parameters:
- name: connectionId
in: path
required: true
description: Connection ID to browse installations for.
schema:
type: string
format: uuid
responses:
'200':
description: Installations accessible to the connection
content:
application/json:
schema:
$ref: '#/components/schemas/GitInstallationsResponse'
'400':
description: Malformed connection ID
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Not authenticated
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Connection not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Failed to list installations
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'503':
description: Git provider integration is not configured
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/user/git/connections/{connectionId}/installations/{installationId}/repositories:
get:
tags:
- Git Connections
summary: List repos accessible to a connection through an installation
description: |
Live proxy to GitHub: lists the repos the connection's stored user
token can access through installationId. Nothing is persisted by this
call.
operationId: listGitInstallationRepositories
security:
- UserToken: []
- AuthUserAccessToken: []
parameters:
- name: connectionId
in: path
required: true
description: Connection ID to browse repositories for.
schema:
type: string
format: uuid
- name: installationId
in: path
required: true
description: GitHub App installation ID.
schema:
type: integer
format: int64
responses:
'200':
description: Repositories accessible through the installation
content:
application/json:
schema:
$ref: '#/components/schemas/GitRepositoriesResponse'
'400':
description: Malformed connection or installation ID
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Not authenticated
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Connection not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Failed to list repositories
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'503':
description: Git provider integration is not configured
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/github/callback:
get:
tags:
- Git Connections
summary: Complete a GitHub App connection callback
description: |
Public GitHub App callback. The signed state and callback binding cookie
bind the provider authorization to the browser that started the flow.
operationId: gitConnectCallback
security: []
parameters:
- name: code
in: query
required: false
description: GitHub user authorization code.
schema:
type: string
- name: state
in: query
required: true
description: Signed connect state generated by startGitConnect.
schema:
type: string
- name: error
in: query
required: false
description: Provider error returned by GitHub.
schema:
type: string
responses:
'303':
description: Redirect back to the app after a successful or failed connect attempt
headers:
Location:
description: Redirect target
schema:
type: string
'400':
description: Invalid callback request or state
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'429':
description: Too many callback attempts from this client
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Failed to complete the connection
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'503':
description: Git provider integration is not configured
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/projects:
get:
tags:
- Projects
summary: List all projects for authenticated user
description: |
Returns projects that are not deleting or deleted, newest first.
Supports two mutually exclusive pagination modes. Offset mode uses
`page` and `limit`. Cursor mode uses `cursor` or `ending_before` with
`limit`, returns `next_cursor`/`prev_cursor`, and supports a bounded
`offset` past the cursor anchor. Supplying `limit` without `page`
selects cursor mode. `search` applies a case-insensitive project-name
filter in either mode. `include` optionally expands each returned
project with its Git connection and/or aggregate health summary using
`git_connection` and `health`. Sending `page` with `cursor` or `ending_before`,
or sending both cursor directions, returns 400.
operationId: listProjects
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/Page'
- $ref: '#/components/parameters/Limit'
- $ref: '#/components/parameters/Cursor'
- $ref: '#/components/parameters/EndingBefore'
- $ref: '#/components/parameters/Offset'
- $ref: '#/components/parameters/Search'
- name: include
in: query
required: false
description: Optional comma-separated project metadata expansions.
style: form
explode: false
schema:
type: array
uniqueItems: true
items:
type: string
enum:
- git_connection
- health
responses:
'200':
description: Successful response
content:
application/json:
schema:
$ref: '#/components/schemas/PaginatedProjects'
'400':
description: Invalid or conflicting pagination parameters
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
post:
tags:
- Projects
summary: Create a new project
description: |
Creates a project for the authenticated user.
Each user can create up to 1,000 projects. Requests over this cap return 403.
operationId: createProject
security:
- UserToken: []
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CreateProjectRequest'
responses:
'201':
description: Project created
content:
application/json:
schema:
$ref: '#/components/schemas/Project'
'400':
description: Bad request
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'403':
description: Project limit exceeded for the user
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/projects/{id}:
get:
tags:
- Projects
summary: Get project by ID
operationId: getProject
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
responses:
'200':
description: Successful response
content:
application/json:
schema:
$ref: '#/components/schemas/Project'
'404':
description: Project not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
patch:
tags:
- Projects
summary: Update project metadata and region policy
operationId: updateProject
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/UpdateProjectRequest'
responses:
'200':
description: Project updated
content:
application/json:
schema:
$ref: '#/components/schemas/Project'
'400':
description: |
Bad request (no region selected, an unknown region, or — for a
project holding durable functions — a region that does not offer
durable execution)
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'403':
description: Forbidden (for example, selecting subset regions on non-SUPERAGENT plan)
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Project not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'409':
description: Conflict (project name already exists or a resource deployment blocks a region change)
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
delete:
tags:
- Projects
summary: Delete a project
description: |
Starts asynchronous project deletion. The project remains available from
`GET /projects/{id}` with `status: deleting` until cleanup finishes, but is
removed from project lists as soon as deletion starts. After cleanup it
returns 404.
operationId: deleteProject
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
responses:
'202':
description: Project deletion started
'404':
description: Project not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/projects/{id}/health:
get:
tags:
- Projects
summary: Get project health
description: |
Returns a fast control-plane health snapshot for the project and its
deployed resources. The endpoint does not run live provider probes.
A successful request returns 200 even when the project status is
`unhealthy`; transport and authorization failures use HTTP errors.
operationId: getProjectHealth
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
responses:
'200':
description: Project health snapshot retrieved
content:
application/json:
schema:
$ref: '#/components/schemas/ProjectHealthResponse'
'401':
description: Unauthorized - invalid or missing token
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'403':
description: Access denied
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Project not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Internal server error
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/projects/{id}/metrics/query:
post:
tags:
- Projects
summary: Query project runtime metrics
description: |
Evaluates a batch of named, curated runtime metric queries over one
trailing time range. Query IDs correlate each request with its result;
raw backend query languages are intentionally not exposed.
operationId: queryProjectMetrics
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/ProjectMetricsQueryRequest'
responses:
'200':
description: Project runtime metric queries evaluated
content:
application/json:
schema:
$ref: '#/components/schemas/ProjectMetricsQueryResponse'
'400':
description: Invalid metric query
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Unauthorized - invalid or missing token
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'403':
description: Access denied
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Project not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Internal server error
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'503':
description: Runtime metrics backend unavailable
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/projects/{id}/logo:
get:
tags:
- Projects
summary: Get the project logo image
description: |
Returns the raw logo image stored in the project's storage folder. This
endpoint is unauthenticated so the asset can be rendered directly in an
`
` tag; project IDs are unguessable UUIDs and logos are
non-sensitive branding. The `Project.logo_url` field exposes a versioned
path to this endpoint.
operationId: getProjectLogo
security: []
parameters:
- $ref: '#/components/parameters/ProjectId'
responses:
'200':
description: Logo image
content:
image/png:
schema:
type: string
format: binary
image/jpeg:
schema:
type: string
format: binary
image/gif:
schema:
type: string
format: binary
image/webp:
schema:
type: string
format: binary
image/svg+xml:
schema:
type: string
format: binary
'404':
description: Project or logo not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
post:
tags:
- Projects
summary: Upload or replace the project logo
description: |
Uploads an image as the project's logo, storing it in the project's
storage folder. Accepts PNG, JPEG, GIF, WebP, or SVG up to 2 MB. Replaces any
existing logo. Returns the updated project, whose `logo_url` reflects
the new logo.
operationId: uploadProjectLogo
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
requestBody:
required: true
content:
multipart/form-data:
schema:
type: object
required:
- logo
properties:
logo:
type: string
format: binary
description: Logo image (PNG, JPEG, GIF, WebP, or SVG; max 2 MB)
responses:
'200':
description: Logo uploaded
content:
application/json:
schema:
$ref: '#/components/schemas/Project'
'400':
description: Bad request (missing file, unsupported type, or too large)
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'403':
description: Access denied
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Project not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'409':
description: Project is being deleted
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'503':
description: Logo storage is not configured
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
delete:
tags:
- Projects
summary: Remove the project logo
description: |
Deletes the project logo from the project's storage folder and clears its
record. Returns the updated project with no `logo_url`.
operationId: deleteProjectLogo
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
responses:
'200':
description: Logo removed
content:
application/json:
schema:
$ref: '#/components/schemas/Project'
'403':
description: Access denied
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Project not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'409':
description: Project is being deleted
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'503':
description: Logo storage is not configured
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/projects/{id}/usage:
get:
tags:
- Projects
summary: Get usage metrics for a project
description: |
Returns project usage totals for the current usage month plus
recent hourly and daily time series for each tracked metric.
operationId: getProjectUsage
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
responses:
'200':
description: Usage metrics retrieved
content:
application/json:
schema:
$ref: '#/components/schemas/ProjectUsageResponse'
'403':
description: Access denied
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Project not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/projects/{id}/shared-variables:
put:
tags:
- Projects
summary: Replace shared variable names
description: |
Atomically replaces the complete shared function-variable list without
changing values. Names must already exist. Validates final affected
function environments before membership or propagation side effects.
An empty list clears membership. Omitted names remain stored as non-shared variables.
operationId: replaceSharedVariables
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
requestBody:
required: true
content:
application/json:
schema:
type: object
additionalProperties: false
required:
- shared_variables
not:
required:
- expected_shared_variables
- expected_shared_variables_digest
properties:
shared_variables:
type: array
uniqueItems: true
items:
type: string
maxLength: 256
pattern: ^[a-zA-Z_][a-zA-Z0-9_]*$
expected_shared_variables:
type: array
uniqueItems: true
description: When present, replace only if the current complete shared list matches this list.
items:
type: string
maxLength: 256
pattern: ^[a-zA-Z_][a-zA-Z0-9_]*$
expected_shared_variables_digest:
type: string
minLength: 64
maxLength: 64
pattern: ^[a-f0-9]{64}$
description: SHA-256 of the sorted unique current shared names joined by a newline. Use instead of expected_shared_variables for a compact conditional replacement.
responses:
'204':
description: Shared list replaced and affected function synchronization started.
'400':
description: Invalid names or final function environment.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Unauthorized
'404':
description: Project not found
'409':
description: Shared list changed since it was read.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'413':
description: Request body exceeds 4,194,304 bytes
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Persistence or synchronization failed
'503':
description: Shared variable membership writes are disabled during rollout
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/projects/{id}/config:
get:
tags:
- Projects
summary: Export project configuration
description: |
Exports the project's current user-facing configuration as a
declarative manifest. Returns JSON by default. Request the canonical
volcano-config.yaml rendering with `Accept: application/yaml` or
`?format=yaml`; the YAML is returned verbatim as the raw response body
(`Content-Type: application/yaml`) and is meant to be saved as-is.
Variable values and write-only secrets (SMTP password, OAuth client secrets, TLS material)
are omitted from the export; shared_variables contains names only; the YAML rendering adds a header comment
describing how to set them via CLI environment interpolation.
operationId: getProjectConfig
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
- name: format
in: query
required: false
description: Response format override. Takes precedence over the Accept header.
schema:
type: string
enum:
- json
- yaml
responses:
'200':
description: |
Current project configuration. JSON by default; when YAML is
requested the body is the canonical volcano-config.yaml document
served verbatim with `Content-Type: application/yaml`.
content:
application/json:
schema:
$ref: '#/components/schemas/ProjectConfig'
application/yaml:
schema:
type: string
format: binary
description: |
Canonical volcano-config.yaml document returned verbatim,
ready to be saved as-is. The response body is limited to
4,194,304 bytes, matching the configuration apply limit.
'401':
description: Unauthorized - invalid or missing token
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Project not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'413':
description: Canonical YAML export exceeds 4,194,304 bytes
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
put:
tags:
- Projects
summary: Apply project configuration
description: |
Validates and applies a declarative configuration manifest to the
project, reconciling each declared section and returning a per-resource
report. Omitted sections are untouched. Declared collection keys
(`variables`, `buckets[].policies`, `auth.providers.oauth`,
`auth.email.templates`, `functions[].schedulers`) are fully synced:
resources absent from the manifest are deleted. Functions, frontends,
databases, and buckets are never created or deleted; manifest entries
for resources that do not exist are skipped and reported in `skipped`,
and existing resources missing from a declared section are reported in
`missing`. Validation failures (including plan-gate violations) return
422 and nothing is applied. Set `dry_run=true` to get the projected
report without applying changes. Applies are serialized per project;
a concurrent apply returns 409.
operationId: applyProjectConfig
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
- name: dry_run
in: query
required: false
description: Validate and report projected actions without applying changes.
schema:
type: boolean
default: false
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/ProjectConfig'
responses:
'200':
description: |
Apply report. Individual entries may still carry `action: error`
for apply-phase failures (summary.errors > 0); already-applied
changes are not rolled back.
content:
application/json:
schema:
$ref: '#/components/schemas/ProjectConfigApplyResult'
'400':
description: Malformed request body
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Unauthorized - invalid or missing token
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Project not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'409':
description: Another apply is in progress for this project
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'422':
description: Manifest validation failed; nothing was applied
content:
application/json:
schema:
$ref: '#/components/schemas/ProjectConfigValidationErrorResponse'
'503':
description: Shared variable membership writes are disabled during rollout
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/projects/{id}/source-export:
get:
tags:
- Projects
- Git Connections
summary: Report the project's source-of-truth state
operationId: getProjectSourceExport
description: |
Volcano stores the source of the functions and frontend it runs for a
project. This reports whether that source has been written to the
connected repository, and whether the repository has taken over as the
project's source of truth.
`mode` is `platform`, `git_exporting`, `git_pending`, or `git`. Export
enters `git_exporting` before reading stored source. GitHub's signed
push event confirms that the initial commit reached the production
branch. That push or a newer production push changes the mode to
`git_pending` when it starts a deployment. `exported_at` records that
transition.
A successful Git run completes the transition when it matches the
recorded repository, production branch, and root directory and actually
dispatches every recorded resource. Ordinary production-branch pushes
deploy without changing a platform-managed project's source ownership.
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
responses:
'200':
description: The project's source-of-truth state
content:
application/json:
schema:
$ref: '#/components/schemas/ProjectSourceExportState'
'401':
description: Unauthorized - invalid or missing token
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'403':
description: Forbidden - project not owned by the caller
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Project not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Internal server error
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'501':
description: Source export is not available in this deployment mode
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
post:
tags:
- Projects
- Git Connections
summary: Initialize an empty repository with a project's stored source
operationId: exportProjectSource
description: |
Creates the first commit in the connected repository and pushes it
directly to the configured production branch. The push enters the
ordinary Git auto-deploy flow. Direct source writes remain frozen until
that deployment succeeds and the repository becomes the source of truth.
The caller confirms the production branch shown before export. Starting
export pins that branch: later GitHub default-branch changes do not
repoint the project. If the configured branch changed after the caller
read it, the request fails without exporting so the caller can show and
confirm the new value.
The response lists what the export could not carry: resources with no
successful deployment to take source from (`skipped`), and things no
export can hand back (`omitted`) — migrations, which Volcano stores no
copy of, and credential-shaped files, which are left for their owner to
add.
Requires a connected repository with no commits or branches, and runs
once. Volcano never creates the repository. If GitHub did not confirm
the push, retrying creates the same commit and adopts it when it already
reached the repository.
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/ExportProjectSourceRequest'
responses:
'201':
description: The initial production-branch commit that was pushed
content:
application/json:
schema:
$ref: '#/components/schemas/ProjectSourceExport'
'400':
description: Malformed request body
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Unauthorized - invalid or missing token
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'403':
description: Forbidden - project not owned by the caller
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Project not found, or it has no repository connected
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'409':
description: |
The source has already been exported, the repository has already
taken over as the source of truth, the confirmed production branch
is stale, a function or frontend deployment is still in progress,
or the project has no stored source to export
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'422':
description: |
The repository refused the branch, or its contents cannot be laid
out as a repository — a stored file that only ever carries
credentials, or a layout Git auto-deploy would not read back
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'429':
description: GitHub rate limited the request
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Internal server error
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'501':
description: Source export is not available in this deployment mode
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'503':
description: GitHub integration is not configured
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
delete:
tags:
- Projects
- Git Connections
summary: Cancel an incomplete source export
operationId: cancelProjectSourceExport
description: |
Restores platform source writes while the project is in
`git_exporting` or `git_pending`. If Volcano reserved or deployed the
root commit, export remains consumed and cannot be run again. The
connected repository and any commit already pushed to it are unchanged.
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
responses:
'204':
description: The incomplete source transition was canceled
'401':
description: Unauthorized - invalid or missing token
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'403':
description: Forbidden - project not owned by the caller
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Project not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'409':
description: No incomplete transition exists, or Git already took ownership
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Internal server error
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'501':
description: Source export is not available in this deployment mode
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/projects/{id}/git-connection/production-branch:
put:
tags:
- Projects
- Git Connections
summary: Set the branch a project deploys from
description: |
Changes only the production branch, leaving the repository binding
alone. PUT /projects/{id}/git-connection can also set it, but that is a
full rebind: it needs connection_id, installation_id and a repository
selector resent, and re-resolves the repository against GitHub for a
field that does not depend on it.
The branch does not have to exist. It is validated as a Git branch name
and nothing more, so a project can be pointed at a branch that is about
to be pushed — the case a repository created empty depends on.
Setting the branch here marks it as the project's own choice, so a later
default-branch rename on GitHub no longer moves it. Projects that never
set one keep following the repository's default branch.
operationId: setProjectGitProductionBranch
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/SetProjectGitProductionBranchRequest'
responses:
'200':
description: The project's repo connection, with the new branch
content:
application/json:
schema:
$ref: '#/components/schemas/ProjectGitConnection'
'400':
description: |
Malformed request body, or a production_branch that is not a valid
Git branch name
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Unauthorized - invalid or missing token
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'403':
description: Project not owned by the caller
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: |
Project not found, or it has no repository connected. The branch is
part of the connection, so there is nothing to set it on until one
exists.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'409':
description: A Git source transition is pending
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Failed to set the production branch
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/projects/{id}/git-connection:
get:
tags:
- Projects
- Git Connections
summary: Get a project's repo connection
operationId: getProjectGitConnection
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
responses:
'200':
description: The project's current repo connection
content:
application/json:
schema:
$ref: '#/components/schemas/ProjectGitConnection'
'401':
description: Unauthorized - invalid or missing token
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'403':
description: Project not owned by the caller
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Project not found, or has no repo connection
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Failed to get project git connection
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
put:
tags:
- Projects
- Git Connections
summary: Connect or update a project's repo connection
description: |
Full replace, following Vercel's model: many projects may point at the
same repo, so this only binds the project — it never creates or
deletes git-provider state. Used for both the initial connect and
later edits (repo change, root directory, production branch).
Resolves the repository_id or repo_full_name selector against the repos
accessible through installation_id via connection_id's stored GitHub
user token, then persists repository metadata only from that validated
GitHub response.
operationId: connectProjectGit
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/ConnectProjectGitRequest'
responses:
'200':
description: The project's repo connection
content:
application/json:
schema:
$ref: '#/components/schemas/ProjectGitConnection'
'400':
description: |
Malformed request body, no repository selector, selectors that
identify different repositories, a production_branch that is not a
valid Git branch name, no production_branch on a repository with no
default branch to follow (name one to connect a repository that has
no commits yet), or a production_branch other than the new
repository's default in a request that also changes repository.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Unauthorized - invalid or missing token
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'403':
description: |
Project not owned by the caller, or the selected repository is not
accessible through installation_id
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Project or connection not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'409':
description: |
A Git source transition is pending or complete, so the recorded
repository and root cannot be changed
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Failed to connect project git
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'503':
description: Git provider integration is not configured
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
delete:
tags:
- Projects
- Git Connections
summary: Disconnect a project's repo connection
operationId: disconnectProjectGit
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
responses:
'204':
description: Connection removed
'401':
description: Unauthorized - invalid or missing token
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'403':
description: Project not owned by the caller
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Project not found, or has no repo connection
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'409':
description: |
A Git source transition is pending or complete, so the recorded
repository cannot be disconnected
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Failed to disconnect project git
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/projects/{id}/git-deploy-settings:
get:
tags:
- Projects
- Git Connections
summary: Get a project's Git auto-deploy settings
operationId: getProjectGitDeploySettings
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
responses:
'200':
description: The project's current Git auto-deploy settings
content:
application/json:
schema:
$ref: '#/components/schemas/ProjectGitDeploySettings'
'401':
description: Unauthorized - invalid or missing token
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'403':
description: Project not owned by the caller
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Project not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Failed to get project git deploy settings
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
put:
tags:
- Projects
- Git Connections
summary: Update a project's Git auto-deploy settings
description: |
Full replace of the project's Git auto-deploy settings: what a push to
the connected repo's production branch deploys.
Connecting a repository sets auto_deploy_enabled and deploy_functions
to true for a project that has never called this endpoint, so a push
deploys without any further setup. Once these settings have been saved
here they are the project's own: connecting, rebinding, disconnecting
and reconnecting all leave them untouched, including when they were
saved before any repository was connected. Frontend settings are off
until set here; the frontend need not exist when they are saved, since
frontend_name is resolved at deploy time.
operationId: updateProjectGitDeploySettings
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/UpdateProjectGitDeploySettingsRequest'
responses:
'200':
description: The project's updated Git auto-deploy settings
content:
application/json:
schema:
$ref: '#/components/schemas/ProjectGitDeploySettings'
'400':
description: Malformed request body, or frontend_app_root without frontend_name
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Unauthorized - invalid or missing token
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'403':
description: Project not owned by the caller
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Project not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'409':
description: |
A Git source transition is pending, or this change would remove
deploy coverage after Git has taken over
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Failed to update project git deploy settings
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/projects/{id}/databases/{databaseName}/queries:
get:
tags:
- Databases
summary: Get database queries
description: |
Returns the database's current top queries from pg_stat_statements
ranked by total execution time.
**SUPERAGENT plan required.** This endpoint is only available to projects owned
by users on the SUPERAGENT billing plan.
operationId: getProjectDatabaseQueries
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
- $ref: '#/components/parameters/DatabaseName'
- name: limit
in: query
description: Maximum number of queries to return.
schema:
type: integer
minimum: 1
maximum: 100
default: 10
responses:
'200':
description: Database query performance retrieved
content:
application/json:
schema:
$ref: '#/components/schemas/DatabaseQueryPerformanceResponse'
'400':
description: Bad request - invalid query parameters
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Unauthorized - invalid or missing token
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'403':
description: Access denied
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Project or database not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Internal server error
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/deployments:
get:
tags:
- Projects
summary: List deployments across a user's projects
description: |
Lists Function and Frontend deployment attempts across every project the
user owns, newest first. Pass `project_id` to narrow the feed to a single
project.
Scope is project **ownership** (`projects.user_id`). `owner_id` names
whose deployments to return, not who started them — the actor is
`initiated_by_user_id`, which this endpoint does not filter on.
With a user token the scope is always the authenticated user: `owner_id`
may be omitted, or set to that same user, but naming anyone else is
refused with 403. Service callers on the management API must pass it,
since they have no authenticated user.
The owner is not checked for existence: an id with no projects returns an
empty page rather than `404`. Unlike `/users/{id}/usage`, this endpoint is
polled to detect an event, so a caller needs `404` to keep meaning "this
route is not served here" — which is how a consumer notices it is running
against an older release. A mistyped owner therefore reads as "nothing
deployed"; callers that need to tell those apart should verify the user
through `GET /users/{id}` first.
Ordering is selectable. The default is the feed order — most recent
attempt first. `completed_at.asc` orders by completion, oldest first, and
considers only attempts that finished; combined with `limit=1` and a
`status` filter it answers "when did this user first succeed" in one
bounded query.
Both pagination modes are supported, selected exactly as
`/projects/{id}/deployments` selects them: `cursor`/`ending_before` (or a
`limit` with no `page`) uses keyset pagination; otherwise `page`/`limit`
offset pagination. `page` with a cursor, and `cursor` with
`ending_before`, are rejected.
A cursor is bound to every filter *and* to `order`, so changing any of
them mid-pagination rejects the cursor rather than silently skipping or
repeating rows. The keyset position is `(created_at, id)` for
`created_at.desc` and `(completed_at, id)` for `completed_at.asc`.
operationId: listDeployments
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/Page'
- $ref: '#/components/parameters/Limit'
- $ref: '#/components/parameters/Cursor'
- $ref: '#/components/parameters/EndingBefore'
- $ref: '#/components/parameters/Offset'
- $ref: '#/components/parameters/DeploymentOwnerId'
- name: project_id
in: query
required: false
description: Restrict the feed to a single project owned by the user.
schema:
type: string
format: uuid
- name: created_after
in: query
required: false
description: Restrict results to attempts created at or after this timestamp.
schema:
type: string
format: date-time
- $ref: '#/components/parameters/DeploymentResourceType'
- $ref: '#/components/parameters/DeploymentStatus'
- $ref: '#/components/parameters/DeploymentOperation'
- $ref: '#/components/parameters/DeploymentOrder'
responses:
'200':
description: Successful response
content:
application/json:
schema:
$ref: '#/components/schemas/PaginatedProjectDeployments'
'400':
description: Bad request - invalid filter or pagination
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Unauthorized - invalid or missing token
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'403':
description: Forbidden - owner_id names a different user
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Internal server error
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/projects/{id}/deployments:
get:
tags:
- Projects
summary: List deployments in a project
description: |
Lists Function and Frontend deployment attempts across the project,
ordered most-recent first. Each item includes a normalized resource
reference so clients can render both resource types without extra
fetches.
operationId: listProjectDeployments
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
- $ref: '#/components/parameters/Page'
- $ref: '#/components/parameters/Limit'
- $ref: '#/components/parameters/Cursor'
- $ref: '#/components/parameters/EndingBefore'
- $ref: '#/components/parameters/Offset'
- $ref: '#/components/parameters/Search'
- name: created_after
in: query
required: false
description: Restrict results to attempts created at or after this timestamp.
schema:
type: string
format: date-time
- name: resource_type
in: query
required: false
description: |
Restrict the feed to a single resource type. Omit to return both
Function and Frontend deployments.
schema:
type: string
enum:
- function
- frontend
responses:
'200':
description: Successful response
content:
application/json:
schema:
$ref: '#/components/schemas/PaginatedProjectDeployments'
'400':
description: Bad request - invalid identifier
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Unauthorized - invalid or missing token
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'403':
description: Forbidden - project ownership required
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Internal server error
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/projects/{id}/deployments/summary:
get:
tags:
- Projects
summary: Summarize deployments in a project
description: |
Summarizes deployment attempts for one comparable resource pipeline.
Success rate uses conclusive outcomes only: active and deleted attempts
are successful; failed and degraded attempts are failures; in-progress
and superseded attempts are excluded. Median build duration includes
completed, non-superseded attempts with recorded build work,
including failed builds.
operationId: summarizeProjectDeployments
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
- name: search
in: query
required: false
description: Restrict the summary to resource names containing this value.
schema:
type: string
- name: resource_type
in: query
required: true
description: Restrict the summary to one comparable deployment pipeline.
schema:
type: string
enum:
- function
- frontend
- name: created_after
in: query
required: false
description: Restrict results to attempts created at or after this timestamp.
schema:
type: string
format: date-time
responses:
'200':
description: Successful response
content:
application/json:
schema:
$ref: '#/components/schemas/ProjectDeploymentSummary'
'400':
description: Bad request - invalid identifier or filter
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Unauthorized - invalid or missing token
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'403':
description: Forbidden - project ownership required
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Internal server error
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/projects/{id}/domains:
get:
tags:
- Frontends
summary: List all custom domains in a project
description: |
Project-scoped custom-domain list. Returns every active custom
domain across every frontend in the project (excludes soft-deleted
rows). Each item inlines the linked frontend's id and name so the
UI does not need a second fetch to render the "Linked to" column.
operationId: listProjectCustomDomains
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
- $ref: '#/components/parameters/Page'
- $ref: '#/components/parameters/Limit'
- $ref: '#/components/parameters/Cursor'
- $ref: '#/components/parameters/EndingBefore'
- $ref: '#/components/parameters/Offset'
- $ref: '#/components/parameters/Search'
responses:
'200':
description: Successful response
content:
application/json:
schema:
$ref: '#/components/schemas/PaginatedProjectCustomDomains'
'400':
description: Bad request - invalid identifier
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Unauthorized - invalid or missing token
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'403':
description: Forbidden - project ownership required
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Internal server error
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/projects/{id}/functions:
get:
tags:
- Functions
summary: List all functions in a project
description: |
Supports two mutually exclusive pagination modes. Offset mode uses `page`
and `limit` and returns `next` (URL). Cursor mode uses `cursor` and
`limit`, supports `search` (case-insensitive name match), and returns
`next_cursor`/`prev_cursor`. Sending both `page` and `cursor` (or `page`
and `search`) returns 400.
operationId: listFunctions
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
- $ref: '#/components/parameters/Page'
- $ref: '#/components/parameters/Limit'
- $ref: '#/components/parameters/Cursor'
- $ref: '#/components/parameters/EndingBefore'
- $ref: '#/components/parameters/Offset'
- $ref: '#/components/parameters/Search'
responses:
'200':
description: Successful response
content:
application/json:
schema:
$ref: '#/components/schemas/PaginatedFunctions'
'404':
description: Project not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
post:
tags:
- Functions
summary: Create or update function code
description: |
Upload a serverless function source bundle. Direct API clients may send the function code
as a ZIP or tar.gz archive via multipart/form-data. The API stores a normalized tar.gz
source archive.
Cloud deploys should include source files and dependency manifests/lockfiles, not installed
dependency directories. Volcano installs Node.js, Python, and Ruby dependencies during the
function compile build.
Source archive size is enforced by the API with `SOURCE_ARCHIVE_SIZE_LIMIT_MB`; the CLI
does not apply its own source archive size limit. After the final container image is
built, the publish build enforces `LAMBDA_TARGET_CONTAINER_SIZE_LIMIT_MB` before pushing.
Uploaded source archives cannot contain symlink entries. Safe symlinks created during
the cloud build are materialized before publish.
Volcano builds and deploys the function asynchronously after upload. A deployment that starts
immediately returns a Function resource with `status: provisioning`, then transitions to
`active` or `failed`. If another deployment is running, the response preserves the resource's
current status and exposes the queued deployment through `pending_deployment_id`.
Existing function traffic continues to use the last known-good runtime during an update. A failed
update keeps that runtime available and records the attempted deployment as failed.
Only one deployment runs for a given function. A newer request supersedes any queued request
and starts after the running deployment. Different functions and projects deploy concurrently.
If a function with the same name already exists in the project, this operation updates that
function's runtime, handler, and source bundle and returns `200 OK`.
Each project can contain up to 10,000 functions. Creating a new function over this cap returns 403.
operationId: createFunction
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
requestBody:
required: true
content:
multipart/form-data:
schema:
type: object
required:
- name
- code
- runtime
properties:
name:
type: string
description: DNS-safe function name (lowercase letters, numbers, hyphens; cannot start or end with hyphen)
maxLength: 63
pattern: ^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$
example: my-api-function
code:
type: string
format: binary
description: ZIP or tar.gz archive containing function source code plus dependency manifests/lockfiles. The API enforces SOURCE_ARCHIVE_SIZE_LIMIT_MB and stores a normalized tar.gz source archive.
runtime:
type: string
enum:
- nodejs22.x
- nodejs24.x
- python3.10
- python3.11
- python3.12
- python3.13
- python3.14
- ruby3.3
- ruby3.4
- ruby4.0
description: |
Runtime environment. Required.
- Node.js: nodejs22.x, nodejs24.x
- Python: python3.10, python3.11, python3.12, python3.13, python3.14
- Ruby: ruby3.3, ruby3.4, ruby4.0
example: nodejs24.x
handler:
type: string
description: |
The name of the function to invoke. Defaults to "handler" if not specified.
Your code must export/define a function with this name:
- Node.js: exports.handler (in index.js)
- Python: def handler() (in main.py)
- Ruby: def handler() (in main.rb)
default: handler
example: handler
is_public:
type: boolean
description: |
Whether the function can be reached through public invocation
ingress. Omit it to keep the function's current visibility; a
new function starts private.
invocation_mode:
$ref: '#/components/schemas/FunctionInvocationMode'
http_auth_mode:
$ref: '#/components/schemas/FunctionHTTPAuthMode'
openapi_spec:
type: string
description: JSON-encoded OpenAPI 3.0 or 3.1 metadata for an HTTP-mode function.
variable_scope:
type: string
enum:
- all
- scoped
description: |
Which project variables this function receives. `all` (the default) gives it only project variables marked `shared: true`; `scoped` gives it only the variables it selects. Omitting this leaves an existing function's scope unchanged.
variables:
type: string
description: |
JSON-encoded array of project variable names this function requires, on top of the ones detected in its source. A declared name the project does not define is rejected with 400; a detected name it does not define is ignored. Only used when `variable_scope` is `scoped`. Omitting this leaves an existing function's declared names unchanged.
responses:
'200':
description: Existing function updated; its deployment was started or queued
content:
application/json:
schema:
$ref: '#/components/schemas/Function'
'201':
description: Function created and deployment workflow started
content:
application/json:
schema:
$ref: '#/components/schemas/Function'
'400':
description: Bad request (invalid file, too large, etc.)
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'403':
description: Function limit exceeded for the project
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'409':
description: |
Function deletion is queued or running, or the name is already held
by a durable function — a function cannot change kind.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Internal server error (function deployment failed)
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/projects/{id}/functions/{functionId}:
get:
tags:
- Functions
summary: Get function by ID
operationId: getFunction
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
- $ref: '#/components/parameters/FunctionId'
responses:
'200':
description: Successful response
content:
application/json:
schema:
$ref: '#/components/schemas/Function'
'404':
description: Function not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
patch:
tags:
- Functions
summary: Update function settings
operationId: updateFunction
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
- $ref: '#/components/parameters/FunctionId'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/UpdateFunctionRequest'
examples:
makePublic:
summary: Make function public (anon keys can invoke)
value:
is_public: true
makePrivate:
summary: Make function private (default behavior)
value:
is_public: false
responses:
'200':
description: Function updated
content:
application/json:
schema:
$ref: '#/components/schemas/Function'
'400':
description: Bad request
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Function not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
delete:
tags:
- Functions
summary: Delete a function
description: |
Schedules asynchronous function deletion. If another deployment is running, the function
preserves its current status and exposes the queued deletion through `pending_deployment_id`.
Its status changes to `deleting` when cleanup starts. After cleanup, it returns 404 and no
longer appears in function lists.
operationId: deleteFunction
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
- $ref: '#/components/parameters/FunctionId'
responses:
'202':
description: Function deletion started or queued
'404':
description: Function not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/functions/{functionId}/invoke:
post:
tags:
- Functions
summary: Invoke a function
description: |
Invoke a serverless function.
**With Service Key** (admin/background operations):
- Use for background jobs, webhooks, cron, admin operations
- Function receives payload only (no user context)
- Database queries bypass RLS (admin access)
**With Auth User Token** (user-facing):
- Use for user-initiated actions
- Function receives payload + `__volcano_auth` context:
```javascript
{
user_id: "uuid",
email: "user@example.com",
project_id: "uuid",
role: "authenticated" or "anonymous"
}
```
- Database queries enforce RLS (user-scoped data)
**With Anon Key** (public function only):
- Requires anon key permission: `functions.invoke`
- Function must have `is_public: true`
- Function receives payload only (no `__volcano_auth`)
**Transport and CORS:**
- This operation is the authenticated direct RPC endpoint and always uses the
POST `{payload: ...}` contract, including for functions whose DNS ingress is
configured in HTTP mode.
- The geo-routed DNS ingress is the function's `invoke_url`. It is on a
different domain from this API, so it cannot be derived from the API host.
- RPC-mode DNS ingress accepts POST at `/`. HTTP-mode DNS ingress accepts GET,
HEAD, POST, PUT, PATCH, and DELETE at `/` and nested paths.
- Direct and RPC-mode CORS preflight advertises `POST, OPTIONS`. HTTP-mode DNS
preflight advertises `GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS`.
- `http_auth_mode: none` applies only to public HTTP-mode DNS ingress; this
direct operation always requires a Volcano credential.
**Durable functions are not invocable here.** A durable function's id
answers 404, whatever its visibility, because a synchronous call would
run it with no execution record, no idempotency and no concurrency
accounting. Start one with
`POST /durable-functions/{functionId}/executions`.
operationId: invokeFunction
security:
- AnonKey: []
- ServiceRoleKey: []
- AuthUserAccessToken: []
parameters:
- $ref: '#/components/parameters/FunctionId'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/FunctionInvocationRequest'
examples:
serviceCall:
summary: Admin/background operation (service key)
value:
payload:
action: process_batch
items:
- 1
- 2
- 3
userCall:
summary: User-initiated call (auth token)
value:
payload:
action: get_profile
anonCall:
summary: Public function call (anon key)
value:
payload:
action: ping_public_endpoint
responses:
'200':
description: Function response (passthrough from function runtime)
headers:
X-Volcano-Version:
description: Volcano API/runtime version that served this invocation (`` in production, `-` in non-production)
schema:
type: string
X-Volcano-Region:
description: Region the function ran in (for example `us-east-1`)
schema:
type: string
content:
application/json:
schema:
$ref: '#/components/schemas/FunctionInvocationResponse'
'400':
description: Bad request - invalid payload or function in failed state
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Unauthorized - invalid or missing token
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'403':
description: Forbidden - CORS blocked, missing `functions.invoke`, or private function with anon key
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Function not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'429':
description: |
Rate limit exceeded (per-function or project-wide limit), or the
owning platform user's billing-cycle bandwidth allowance (aggregate ingress +
egress) was exceeded.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'503':
description: |
Function still provisioning or rate limiting service unavailable.
A freshly deployed (or updated) function may briefly report
`provisioning` and reject invocations until the background status
reconciler observes its deployment workflow completing and transitions
it to `active`. This is expected for a few seconds after deploy; clients
should retry.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
default:
description: Function response (passthrough; status code/body/headers come from the function)
headers:
X-Volcano-Version:
description: Volcano API/runtime version that served this invocation (`` in production, `-` in non-production)
schema:
type: string
X-Volcano-Region:
description: Region the function ran in (for example `us-east-1`)
schema:
type: string
content:
application/json:
schema:
$ref: '#/components/schemas/FunctionInvocationResponse'
/durable-functions/{functionId}/executions:
post:
tags:
- Durable Functions
summary: Start a durable execution from an application
description: |
Starts an execution of a durable function using an application
credential, and returns its handle.
This is the durable counterpart of `POST /functions/{functionId}/invoke`,
and it is the endpoint an application calls. Like that one, it is not
project-scoped: an anon key, a service key and an auth user token each
carry their own project. The project-scoped collection under
`/projects/{id}/durable-functions/...` remains the owner's management
surface.
**With a service key or an auth user token:** any durable function in
the project.
**With an anon key:** requires the `functions.invoke` permission, and
the function must have `is_public: true`.
Starting is all this endpoint does. Reading a result or stopping an
execution requires the project owner's token, because an anon key is
shared by everyone who loads the page and an execution is addressed by
id alone.
Send `X-Volcano-Execution-Name` to make the start idempotent: repeating
a start with the same name returns the existing execution instead of
beginning a second one.
Each execution counts once against the project's durable execution
allowance, however many times the start is retried under the same
execution name, and the number in flight at once is capped by the plan.
The operations the execution performs are counted against the durable
operations allowance when it finishes.
operationId: startDurableExecutionFromApplication
security:
- AnonKey: []
- ServiceRoleKey: []
- AuthUserAccessToken: []
parameters:
- $ref: '#/components/parameters/DurableFunctionId'
- name: X-Volcano-Execution-Name
in: header
required: false
description: |
Idempotency key for this execution. Generated when omitted. A repeat
under a name that already names a running execution returns that
execution and is not charged again.
Letters, digits, `-`, `_` and `.`, up to 255 characters. Anything
else is rejected with `400`.
schema:
type: string
maxLength: 255
pattern: ^[A-Za-z0-9._-]+$
requestBody:
required: false
content:
application/json:
schema:
description: Input passed to the function, up to 256 KiB.
responses:
'202':
description: Execution accepted and started
content:
application/json:
schema:
$ref: '#/components/schemas/DurableExecution'
'400':
description: Payload is not valid JSON, or the execution name is invalid
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: |
Missing or invalid credential. Also returned for a platform user
token, which is not an application credential; project owners start
executions through the project-scoped collection.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'403':
description: |
The anon key lacks `functions.invoke`, the function is not public,
or the request's origin is refused by the project's CORS policy.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: |
Durable function not found. Also returned for a standard function's
id and for a durable function in another project, so the response
cannot be used to tell those apart.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'409':
description: |
Function is not deployed yet, or has no deployed region. Also
returned when two starts under the same execution name raced and
both released it, which is retryable as it stands.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'413':
description: Payload is larger than 256 KiB
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'429':
description: |
The project has too many executions in flight for its plan, the
function invocation rate limit was exceeded, the project is over
its bandwidth cap, or the account is out of one of its
billing-cycle durable allowances: executions, operations, or
compute. Operations and compute are counted once an execution
finishes, so a refusal on either never interrupts an execution
already running — it declines the next start.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'503':
description: |
Durable execution is not available in this environment, or the
usage limit service could not be reached to charge the start. The
first is returned by a deployment that has no durable execution
engine, such as a local one, and is not retryable there; the second
is transient.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/functions/resolve:
get:
tags:
- Functions
summary: Resolve function name for invocation
description: |
Resolves a DNS-safe function name to its function ID and invocation URL within the caller's project.
SDKs use this endpoint internally to invoke by function name while routing by function ID.
Invoke the returned `invoke_url` as-is. It does not share a domain with the API, so a host
built from the API URL will not reach the function. When the deployment serves no public
invocation domain, as in local development, `invoke_url` is omitted and callers invoke
through `POST /functions/{functionId}/invoke`.
**With Service Key**:
- Allowed
**With Auth User Token**:
- Allowed
**With Anon Key**:
- Requires anon key permission: `functions.invoke`
- Function must have `is_public: true`
operationId: resolveFunctionForInvocation
security:
- AnonKey: []
- ServiceRoleKey: []
- AuthUserAccessToken: []
parameters:
- name: name
in: query
required: true
schema:
type: string
maxLength: 63
pattern: ^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$
description: DNS-safe function name (lowercase letters, numbers, hyphens; cannot start or end with hyphen)
example: my-function
responses:
'200':
description: Function resolved successfully
content:
application/json:
schema:
$ref: '#/components/schemas/ResolveFunctionResponse'
'400':
description: Bad request - missing or invalid function name
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Unauthorized - invalid or missing token
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'403':
description: Forbidden - CORS blocked or missing `functions.invoke` permission for anon key
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: |
Function not found (or private function with anon key). A durable
function is never resolvable here: it is started through
`POST /durable-functions/{functionId}/executions`, not invoked.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/projects/{id}/logs/activity:
post:
tags:
- Logs
summary: Get project log activity
description: |
Retrieve bucketed log counts for one resource type in the project. Set
`resource.type` to `function`, `frontend`, or `database`. Add
`resource.ids` to filter to one or more resources, and add
`resource.deployments.ids` to count deployment logs instead of runtime
logs for functions and frontends. Deployment logs are not supported for
databases. Database logs are a SUPERAGENT-plan feature; `resource.type=database`
from a HOBBY-plan project owner returns 403. The activity window is limited
to the plan's retention window (HOBBY: 1 day, SUPERAGENT: 30 days); older start
times are clamped to that window.
operationId: getProjectLogActivity
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/LogActivityRequest'
responses:
'200':
description: Successful response
content:
application/json:
schema:
$ref: '#/components/schemas/LogActivityResponse'
'400':
description: Bad request - invalid query parameter
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Unauthorized - invalid or missing token
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'403':
description: Forbidden - project ownership required
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Project or resource not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/projects/{id}/logs/search:
post:
tags:
- Logs
summary: Search project logs
description: |
Search or filter logs for one resource type in the project. Set
`resource.type` to `function`, `frontend`, or `database`. Add
`resource.ids` to filter to one or more resources, and add
`resource.deployments.ids` to read deployment logs instead of runtime
logs for functions and frontends. Deployment logs are not supported for
databases. Database logs are a SUPERAGENT-plan feature; requests for
`resource.type=database` from a HOBBY-plan project owner return 403.
Log history (runtime and deployment) is limited to the plan's retention
window (HOBBY: 1 day, SUPERAGENT: 30 days); older time ranges are clamped to that
window.
operationId: searchProjectLogs
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/LogSearchRequest'
responses:
'200':
description: Successful response
content:
application/json:
schema:
$ref: '#/components/schemas/LogSearchResponse'
'400':
description: Bad request - invalid query parameter
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Unauthorized - invalid or missing token
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'403':
description: Forbidden - project ownership required
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Project or resource not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/projects/{id}/logs/stream:
post:
tags:
- Logs
summary: Stream project logs
description: |
Live-tail project logs as Server-Sent Events. The request body uses the
resource selector plus `q`, `start_time`, and `limit`,
including runtime logs and function/frontend deployment logs selected
with `resource.deployments`. Deployment logs are not supported for
databases. Database logs are a SUPERAGENT-plan feature; `resource.type=database`
from a HOBBY-plan project owner returns 403. The `q` field uses the same
syntax as search and activity requests. Do not send `cursor` or
`end_time`; use `/logs/search` for range backfills.
Explicit historical `start_time` values are limited to the plan's
retention window (HOBBY: 1 day, SUPERAGENT: 30 days). Resume with
`Last-Event-ID` or the `last_event_id` query parameter. The cursor is
bound to the request body: the resource selector and every filter must
match the original request when reconnecting, otherwise the request is
rejected with `400`.
This is a live tail, not a gap-free backfill. On connect or reconnect the
server delivers at most `limit` of the most recent matching events from
the cursor position and then follows new events; events older than that
window are not replayed. Use `/logs/search` to backfill a time range.
operationId: streamProjectLogs
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
- name: Last-Event-ID
in: header
required: false
schema:
type: string
description: Opaque stream cursor from the most recent SSE `id` field.
- name: last_event_id
in: query
required: false
schema:
type: string
description: Opaque stream cursor fallback when setting `Last-Event-ID` is not practical.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/LogStreamRequest'
responses:
'200':
description: Server-Sent Events stream. `log` events contain a JSON `LogSearchEvent`; `warning` events contain a JSON object with an `error` field.
content:
text/event-stream:
schema:
type: string
examples:
log:
summary: Log event
value: |
: connected
id: STREAM_CURSOR
event: log
data: {"id":"LOG_EVENT_ID","timestamp":"2024-01-01T12:00:00Z","level":"info","message":"User logged in","resource":{"type":"function","id":"550e8400-e29b-41d4-a716-446655440000","name":"login"},"region":"us-east-1"}
'400':
description: Bad request - invalid selector, stream cursor, or unsupported stream field
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Unauthorized - invalid or missing token
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'403':
description: Forbidden - project ownership required
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Project or resource not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Internal server error - log streaming setup failed
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/projects/{id}/functions/batch:
post:
tags:
- Functions
summary: Deploy multiple functions in one request
description: |
Upload multiple function source archives in one multipart request. Each archive should contain source files
plus dependency manifests/lockfiles, not installed dependency directories. ZIP and tar.gz uploads are
accepted and normalized to tar.gz before storage. The API enforces `SOURCE_ARCHIVE_SIZE_LIMIT_MB`
for each uploaded and normalized source archive. The server records a shared
deployment batch ID for the resulting function deployments. Each function deployment runs its own
compile/publish workflow concurrently, and each publish build enforces `LAMBDA_TARGET_CONTAINER_SIZE_LIMIT_MB`
for the final container image.
One batch request can include up to 100 functions. Submit multiple batch requests for larger projects.
If one function fails before its workflow starts, already-started function deployments are left
running and the failed function is reported in the `failed` array. Failed new functions are deleted;
failed updates are rolled back to their previous metadata/status where possible.
operationId: createFunctionsBatch
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
requestBody:
required: true
content:
multipart/form-data:
schema:
type: object
properties:
functions:
type: string
description: |
JSON array of functions with `name`, `runtime`, optional `handler`, and `file_field`. Each `file_field` must name a multipart file field containing that function's ZIP or tar.gz source bundle.
Each entry may also declare `variable_scope` (`all` or `scoped`) and `variables` (an array of project variable names). Omitting them leaves the function's stored declaration unchanged. Volcano detects direct environment references in the uploaded source code and keeps them separate from the declared names: detected names are not written back to the declaration and do not appear in a config export. A scoped function receives its declared names plus the detected ones the project defines; a detected name the project does not define is ignored, since such a reference is often optional. Detection reads code only, so a name appearing solely in a comment or in an unrelated string is not a reference. Declare a name when the function reads it through a computed key, or when it must not deploy without the variable. The request is rejected with 400 before anything is deployed if a scoped function declares a variable the project does not define, or if the resulting environment exceeds 4096 bytes.
code_0:
type: string
format: binary
description: Function ZIP or tar.gz archive referenced by the first manifest entry's `file_field`; additional code_N file fields may be included. Each archive is subject to SOURCE_ARCHIVE_SIZE_LIMIT_MB.
required:
- functions
responses:
'202':
description: Batch deployment accepted
content:
application/json:
schema:
$ref: '#/components/schemas/BatchFunctionDeployResponse'
'207':
description: Batch deployment partially accepted; successful functions started deployment and failed functions were compensated where possible
content:
application/json:
schema:
$ref: '#/components/schemas/BatchFunctionDeployResponse'
'400':
description: Bad request
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'403':
description: Function limit exceeded for the project
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'409':
description: |
A name in the batch is held by a function of the other kind — a
function cannot change kind — or the project's source is managed by
Git, where deploys come from a push to the production branch.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/projects/{id}/schedulers:
get:
tags:
- Functions
summary: List every function scheduler in a project
description: |
Project-scoped counterpart to `/projects/{id}/functions/{functionId}/schedulers`.
Returns schedulers across all functions in the project, ordered by
creation time descending, with standard page/limit pagination so
clients don't have to fan out one request per function.
operationId: listProjectSchedulers
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
- $ref: '#/components/parameters/Page'
- $ref: '#/components/parameters/Limit'
- $ref: '#/components/parameters/Cursor'
- $ref: '#/components/parameters/EndingBefore'
- $ref: '#/components/parameters/Offset'
- $ref: '#/components/parameters/Search'
responses:
'200':
description: Project schedulers
content:
application/json:
schema:
$ref: '#/components/schemas/FunctionSchedulerListResponse'
/projects/{id}/functions/{functionId}/schedulers:
get:
tags:
- Functions
summary: List schedulers for a function
operationId: listFunctionSchedulers
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
- $ref: '#/components/parameters/FunctionId'
responses:
'200':
description: Function schedulers
content:
application/json:
schema:
$ref: '#/components/schemas/FunctionSchedulerListResponse'
'404':
description: Function not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
post:
tags:
- Functions
summary: Create a scheduler for a function
description: Creates regional scheduled invocation jobs. Requested regions must be a subset of the function's deployed regions.
operationId: createFunctionScheduler
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
- $ref: '#/components/parameters/FunctionId'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CreateFunctionSchedulerRequest'
responses:
'201':
description: Scheduler created
content:
application/json:
schema:
$ref: '#/components/schemas/FunctionScheduler'
'400':
description: |
Invalid schedule, geofenced region, a scheduler of this name
already exists on the function, or the function is not active.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'403':
description: |
Schedulers are not available on this plan, or the project already
holds as many as the plan allows. The cap counts standard and
durable function schedulers together.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Function not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/projects/{id}/functions/{functionId}/schedulers/{schedulerId}:
get:
tags:
- Functions
summary: Get a function scheduler
operationId: getFunctionScheduler
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
- $ref: '#/components/parameters/FunctionId'
- $ref: '#/components/parameters/SchedulerId'
responses:
'200':
description: Function scheduler
content:
application/json:
schema:
$ref: '#/components/schemas/FunctionScheduler'
'404':
description: Function or scheduler not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
patch:
tags:
- Functions
summary: Update a function scheduler
operationId: updateFunctionScheduler
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
- $ref: '#/components/parameters/FunctionId'
- $ref: '#/components/parameters/SchedulerId'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/UpdateFunctionSchedulerRequest'
responses:
'200':
description: Scheduler updated
content:
application/json:
schema:
$ref: '#/components/schemas/FunctionScheduler'
'400':
description: |
Invalid schedule, geofenced region, or a scheduler of this name
already exists on the function.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Function or scheduler not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
delete:
tags:
- Functions
summary: Delete a function scheduler
operationId: deleteFunctionScheduler
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
- $ref: '#/components/parameters/FunctionId'
- $ref: '#/components/parameters/SchedulerId'
responses:
'204':
description: Scheduler deleted
'404':
description: Function or scheduler not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/projects/{id}/functions/{functionId}/deployments:
get:
tags:
- Functions
summary: List function deployments
operationId: listFunctionDeployments
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
- $ref: '#/components/parameters/FunctionId'
- $ref: '#/components/parameters/Page'
- $ref: '#/components/parameters/Limit'
responses:
'200':
description: Successful response
content:
application/json:
schema:
$ref: '#/components/schemas/PaginatedFunctionDeployments'
'404':
description: Function not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/projects/{id}/durable-functions:
get:
tags:
- Durable Functions
summary: List all durable functions in a project
description: |
Standard functions never appear here, and durable functions never appear
under `/projects/{id}/functions`. The two are separate collections.
operationId: listDurableFunctions
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
- $ref: '#/components/parameters/Page'
- $ref: '#/components/parameters/Limit'
- $ref: '#/components/parameters/Search'
responses:
'200':
description: Successful response
content:
application/json:
schema:
$ref: '#/components/schemas/PaginatedDurableFunctions'
'400':
description: Bad request - invalid pagination parameters
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Project not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
post:
tags:
- Durable Functions
summary: Create or update a durable function
description: |
Upload a durable function source bundle. Creates the function on the
first call for a name and redeploys it on every call after that, the
same create-or-update contract `POST /projects/{id}/functions` has.
Volcano builds and deploys asynchronously. A deployment that starts
immediately returns `status: provisioning`, then transitions to `active`
or `failed`; a deployment that has to wait for a running one is exposed
through `pending_deployment_id`. Existing executions keep running
against the runtime they started on.
The `durable` configuration is derived from the project's plan rather
than supplied here, and is fixed once the function exists. A name
already held by a standard function is rejected with 409: a function
cannot change kind.
operationId: createDurableFunction
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
requestBody:
required: true
content:
multipart/form-data:
schema:
type: object
required:
- name
- code
- runtime
properties:
name:
type: string
description: DNS-safe function name (lowercase letters, numbers, hyphens; cannot start or end with hyphen)
maxLength: 63
pattern: ^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$
example: order-pipeline
code:
type: string
format: binary
description: ZIP or tar.gz archive containing function source code plus dependency manifests/lockfiles.
runtime:
type: string
enum:
- nodejs22.x
- nodejs24.x
- python3.13
- python3.14
description: |
Runtime environment. Required. Durable execution needs the
durable authoring API, which ships for these runtimes only;
any other runtime is rejected with 400 and the response
names the ones that work. Note that a durable Python
function needs a newer runtime than a standard one defaults
to. `GET /functions/runtimes` reports `durable_capable` per
runtime.
example: nodejs24.x
handler:
type: string
description: The name of the function to invoke. Defaults to "handler" if not specified.
default: handler
example: handler
is_public:
type: boolean
description: |
Whether anon keys with `functions.invoke` may start an
execution. Redeploying is the only way to change it, since
the collection has no update endpoint; omit it to keep the
current visibility, and a new function starts private.
The standard collection's synchronous invocation fields —
`invocation_mode`, `http_auth_mode`, `openapi_spec` —
configure a request path no durable route serves, and are
rejected with 400 rather than ignored.
variable_scope:
type: string
enum:
- all
- scoped
description: |
Which project variables this function receives. `all` (the default) gives it every project variable; `scoped` gives it only the variables it selects. Omitting this leaves an existing function's scope unchanged.
variables:
type: string
description: |
JSON-encoded array of project variable names this function requires, on top of the ones detected in its source. A declared name the project does not define is rejected with 400; a detected name it does not define is ignored. Only used when `variable_scope` is `scoped`. Omitting this leaves an existing function's declared names unchanged.
responses:
'200':
description: Existing durable function updated; its deployment was started or queued
content:
application/json:
schema:
$ref: '#/components/schemas/DurableFunction'
'201':
description: Durable function created and deployment workflow started
content:
application/json:
schema:
$ref: '#/components/schemas/DurableFunction'
'400':
description: |
Bad request (invalid archive, unsupported runtime, invalid name, or a
project region that does not offer durable execution — a durable
function deploys to every region of its project)
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'403':
description: Durable function limit exceeded for the project
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'409':
description: Name is held by a standard function, or a deletion is queued or running
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Internal server error (function deployment failed)
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'503':
description: |
Durable deploys are paused platform-wide. The same request succeeds
once they are re-enabled; executions already running are unaffected.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/projects/{id}/durable-functions/{functionId}:
get:
tags:
- Durable Functions
summary: Get durable function by ID or name
operationId: getDurableFunction
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
- $ref: '#/components/parameters/DurableFunctionId'
responses:
'200':
description: Successful response
content:
application/json:
schema:
$ref: '#/components/schemas/DurableFunction'
'404':
description: Durable function not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
delete:
tags:
- Durable Functions
summary: Delete a durable function
description: |
Accepted for asynchronous teardown; the work continues after the
response. The function's executions go with it: history stops being
readable whatever `retention_days` had left, and the executions still
running stop counting against the project's concurrency cap. Stop an
execution first if you need it to end before the function does.
operationId: deleteDurableFunction
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
- $ref: '#/components/parameters/DurableFunctionId'
responses:
'202':
description: Deletion accepted and teardown started
'404':
description: |
Durable function not found. Also returned for an id that names a
durable function in another project, so the response cannot be used
to tell the two apart.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/projects/{id}/durable-functions/{functionId}/deployments:
get:
tags:
- Durable Functions
summary: List durable function deployments
operationId: listDurableFunctionDeployments
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
- $ref: '#/components/parameters/DurableFunctionId'
- $ref: '#/components/parameters/Page'
- $ref: '#/components/parameters/Limit'
responses:
'200':
description: Successful response
content:
application/json:
schema:
$ref: '#/components/schemas/PaginatedFunctionDeployments'
'404':
description: Durable function not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/projects/{id}/durable-functions/{functionId}/schedulers:
get:
tags:
- Durable Functions
summary: List schedulers for a durable function
description: |
The durable collection's counterpart to
`/projects/{id}/functions/{functionId}/schedulers`. A standard
function's id is not accepted here, and a durable function's id is not
accepted there.
operationId: listDurableFunctionSchedulers
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
- $ref: '#/components/parameters/DurableFunctionId'
responses:
'200':
description: Durable function schedulers
content:
application/json:
schema:
$ref: '#/components/schemas/FunctionSchedulerListResponse'
'404':
description: Durable function not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
post:
tags:
- Durable Functions
summary: Create a scheduler for a durable function
description: |
Each tick starts an execution rather than invoking the function, under
an execution name derived from the run, so a retried tick resolves to
the execution it already started. Requested regions must be a subset of
the function's deployed regions.
A tick draws on the same durable allowances and concurrency cap a
manual start does, and a tick that would exceed the cap fails that run.
operationId: createDurableFunctionScheduler
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
- $ref: '#/components/parameters/DurableFunctionId'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CreateFunctionSchedulerRequest'
responses:
'201':
description: Scheduler created
content:
application/json:
schema:
$ref: '#/components/schemas/FunctionScheduler'
'400':
description: |
Invalid schedule, geofenced region, a scheduler of this name
already exists on the function, or the function is not active.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'403':
description: |
Schedulers are not available on this plan, or the project already
holds as many as the plan allows. The cap counts standard and
durable function schedulers together.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Durable function not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/projects/{id}/durable-functions/{functionId}/schedulers/{schedulerId}:
get:
tags:
- Durable Functions
summary: Get a durable function scheduler
operationId: getDurableFunctionScheduler
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
- $ref: '#/components/parameters/DurableFunctionId'
- $ref: '#/components/parameters/SchedulerId'
responses:
'200':
description: Durable function scheduler
content:
application/json:
schema:
$ref: '#/components/schemas/FunctionScheduler'
'404':
description: Durable function or scheduler not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
patch:
tags:
- Durable Functions
summary: Update a durable function scheduler
operationId: updateDurableFunctionScheduler
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
- $ref: '#/components/parameters/DurableFunctionId'
- $ref: '#/components/parameters/SchedulerId'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/UpdateFunctionSchedulerRequest'
responses:
'200':
description: Scheduler updated
content:
application/json:
schema:
$ref: '#/components/schemas/FunctionScheduler'
'400':
description: |
Invalid schedule, geofenced region, or a scheduler of this name
already exists on the function.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Durable function or scheduler not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
delete:
tags:
- Durable Functions
summary: Delete a durable function scheduler
operationId: deleteDurableFunctionScheduler
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
- $ref: '#/components/parameters/DurableFunctionId'
- $ref: '#/components/parameters/SchedulerId'
responses:
'204':
description: Scheduler deleted
'404':
description: Durable function or scheduler not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/projects/{id}/durable-functions/{functionId}/executions:
post:
tags:
- Durable Functions
summary: Start a durable execution
description: |
Starts an execution and returns its handle. Never returns a result: an
execution can outlive any request a client could hold open, so the
result is read back from
`GET /projects/{id}/durable-functions/{functionId}/executions/{executionId}`.
The request body is the execution's input and must be valid JSON if
present. An empty body starts the execution with no input.
Send `X-Volcano-Execution-Name` to make the start idempotent: repeating a
start with the same name returns the existing execution instead of
beginning a second one.
Each execution counts against the project's durable execution
allowance, the operations it performs count against the durable
operations allowance when it finishes, and the number of executions in
flight at once is capped by the plan.
operationId: startDurableExecution
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
- $ref: '#/components/parameters/DurableFunctionId'
- name: X-Volcano-Execution-Name
in: header
required: false
description: |
Idempotency key for this execution. Generated when omitted. A repeat
under a name that already names a running execution returns that
execution and is not charged again.
Letters, digits, `-`, `_` and `.`, up to 255 characters. Anything
else is rejected with `400`.
schema:
type: string
maxLength: 255
pattern: ^[A-Za-z0-9._-]+$
requestBody:
required: false
content:
application/json:
schema:
description: Input passed to the function, up to 256 KiB.
responses:
'202':
description: Execution accepted and started
content:
application/json:
schema:
$ref: '#/components/schemas/DurableExecution'
'400':
description: Payload is not valid JSON, or the execution name is invalid
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Durable function not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'409':
description: |
Function is not deployed yet, or has no deployed region. Also
returned when two starts under the same execution name raced and
both released it, which is retryable as it stands.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'413':
description: Payload exceeds the maximum execution input size
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'429':
description: |
Too many executions already in flight for this project, or the
account is out of one of its billing-cycle durable allowances:
executions, operations, or compute. An owner-started execution is
metered exactly like an application-started one.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'503':
description: |
Durable execution is not available in this environment, or the
usage limit service could not be reached to charge the start. The
first is returned by a deployment that has no durable execution
engine, such as a local one, and is not retryable there; the second
is transient.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
get:
tags:
- Durable Functions
summary: List a durable function's executions
description: |
Returns the platform's last observed status for each execution; listing
does not poll each one. Fetch a single execution for its live state.
operationId: listDurableExecutions
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
- $ref: '#/components/parameters/DurableFunctionId'
- $ref: '#/components/parameters/Page'
- $ref: '#/components/parameters/Limit'
- name: status
in: query
required: false
description: Return only executions in this status.
schema:
$ref: '#/components/schemas/DurableExecutionStatus'
responses:
'200':
description: Successful response
content:
application/json:
schema:
$ref: '#/components/schemas/PaginatedDurableExecutions'
'400':
description: Unsupported status filter
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Durable function not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/projects/{id}/durable-functions/{functionId}/executions/{executionId}:
get:
tags:
- Durable Functions
summary: Get a durable execution
description: |
Returns the execution's current state, including its `result` once it has
succeeded. Poll this to wait for an execution to finish.
operationId: getDurableExecution
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
- $ref: '#/components/parameters/DurableFunctionId'
- $ref: '#/components/parameters/DurableExecutionId'
responses:
'200':
description: Successful response
content:
application/json:
schema:
$ref: '#/components/schemas/DurableExecution'
'404':
description: Durable function or execution not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'503':
description: |
Durable execution is not available in this environment. Returned by
a deployment that has no durable execution engine, such as a local
one; the request is not retryable there.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/projects/{id}/durable-functions/{functionId}/executions/{executionId}/stop:
post:
tags:
- Durable Functions
summary: Stop a durable execution
description: |
Cancels a running execution. Its completed steps are not undone.
The call is accepted rather than awaited: cancellation happens behind
it, so the response reports the execution as it was read back and may
still say `running`. Do not branch on that status — the execution
settles into `stopped` shortly after, and polling
`GET /projects/{id}/durable-functions/{functionId}/executions/{executionId}`
is how you see it get there.
Stopping an execution that already finished is not an error: the
response carries the state it settled in.
operationId: stopDurableExecution
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
- $ref: '#/components/parameters/DurableFunctionId'
- $ref: '#/components/parameters/DurableExecutionId'
responses:
'200':
description: |
Stop accepted. The body is the execution as it was read back, which
may still report `running`.
content:
application/json:
schema:
$ref: '#/components/schemas/DurableExecution'
'404':
description: Durable function or execution not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'409':
description: Execution has not started yet
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'503':
description: |
Durable execution is not available in this environment. Returned by
a deployment that has no durable execution engine, such as a local
one; the request is not retryable there.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/projects/{id}/frontends:
get:
tags:
- Frontends
summary: List all frontends in a project
description: |
Supports two mutually exclusive pagination modes. Offset mode uses `page`
and `limit` and returns `next` (URL). Cursor mode uses `cursor` and
`limit`, supports `search` (case-insensitive name match), and returns
`next_cursor`. Sending both `page` and `cursor` (or `page` and `search`)
returns 400.
operationId: listFrontends
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
- $ref: '#/components/parameters/Page'
- $ref: '#/components/parameters/Limit'
- $ref: '#/components/parameters/Cursor'
- $ref: '#/components/parameters/EndingBefore'
- $ref: '#/components/parameters/Offset'
- $ref: '#/components/parameters/Search'
responses:
'200':
description: Successful response
content:
application/json:
schema:
$ref: '#/components/schemas/PaginatedFrontends'
'400':
description: Bad request - invalid project identifier
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Unauthorized - invalid or missing token
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'403':
description: Forbidden - project ownership required
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Project not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Internal server error
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
post:
tags:
- Frontends
summary: Create a new frontend deployment
description: |
Creates and deploys a frontend for the project.
If a frontend with the same name already exists in the project, this operation updates that
frontend using the uploaded archive and starts a new deployment. A deployment that starts
immediately returns `status: provisioning`, then transitions to `active`, `degraded`, or
`failed`. If another deployment is running, the response preserves the frontend's current status
and exposes the queued deployment through `pending_deployment_id`.
Existing frontend traffic continues to use an available runtime while the new deployment builds
and provisions. Each deployment publishes its own static assets before the runtimes switch to its
build, and the live build's assets keep serving until the new deployment is live, so a page loaded
mid-deployment resolves its assets whichever build served it. A failed redeploy puts the runtimes
back on the build they were running, leaves the frontend `active` on the previous deployment, and
records the attempted deployment as failed. `degraded` means the runtime remains available but
edge synchronization requires recovery; Volcano retries the edge step without rebuilding. Only one deployment may run for a
given frontend, while independent frontends and projects can deploy concurrently.
For monorepos, provide `app_root` as a relative path from the uploaded archive root
to the Next.js app that should be built. Omit it for single-app archives.
Supported frontend environments are Next.js 15.x and 16.x with Node.js
22.x or 24.x. The Node.js runtime is inferred from
`package.json` `engines.node`; if omitted, Volcano uses Node.js 22.x.
The selected Node.js family must also satisfy the installed Next.js package's
`engines.node` constraint. Volcano tests Next 15.5.25 (`^18.18.0 || ^19.8.0 || >=20.0.0`) and Next 16.3.5 (`>=20.9.0`).
Source archive size is enforced by the API with `SOURCE_ARCHIVE_SIZE_LIMIT_MB`; the CLI
does not apply its own source archive size limit. After the final container images are
built, the publish build enforces `LAMBDA_TARGET_CONTAINER_SIZE_LIMIT_MB` before pushing.
This operation is limited by plan-based frontend deployment quotas (`FREE_FRONTEND_DEPLOYMENTS`, `PRO_FRONTEND_DEPLOYMENTS`).
Each project can contain up to 10,000 frontends regardless of plan.
operationId: createFrontend
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
requestBody:
required: true
content:
multipart/form-data:
schema:
type: object
required:
- name
- archive
properties:
name:
type: string
maxLength: 63
pattern: ^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$
description: DNS-safe frontend name
framework:
type: string
enum:
- nextjs
default: nextjs
description: Next.js frontend. Supported Next.js majors are 15.x and 16.x.
app_root:
type: string
maxLength: 1024
description: Optional relative POSIX path from the uploaded archive root to the Next.js app to build, for example `apps/web`.
example: apps/web
archive:
type: string
format: binary
description: ZIP or tar.gz archive of the frontend project directory or monorepo workspace root. The API enforces SOURCE_ARCHIVE_SIZE_LIMIT_MB and stores a normalized tar.gz archive.
responses:
'200':
description: Existing frontend updated; its deployment was started or queued
content:
application/json:
schema:
$ref: '#/components/schemas/Frontend'
'201':
description: Frontend created and deployment workflow started
content:
application/json:
schema:
$ref: '#/components/schemas/Frontend'
'400':
description: Bad request
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Unauthorized - invalid or missing token
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'403':
description: Frontend deployment limit exceeded for the current plan or project hard cap
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Project not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'409':
description: Conflict - frontend deletion is queued or running
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Internal server error
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'503':
description: Service unavailable - frontend workflow or archive limit configuration missing
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/projects/{id}/frontends/{frontendId}:
get:
tags:
- Frontends
summary: Get frontend details
operationId: getFrontend
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
- $ref: '#/components/parameters/FrontendId'
responses:
'200':
description: Successful response
content:
application/json:
schema:
$ref: '#/components/schemas/Frontend'
'400':
description: Bad request - invalid identifier
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Unauthorized - invalid or missing token
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'403':
description: Forbidden - project ownership required
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Frontend not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Internal server error
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
delete:
tags:
- Frontends
summary: Delete a frontend
description: |
Schedules asynchronous frontend deletion. If another deployment is running, the frontend
preserves its current status and exposes the queued deletion through `pending_deployment_id`.
Its status changes to `deleting` when cleanup starts. After cleanup, it returns 404 and no
longer appears in frontend lists.
operationId: deleteFrontend
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
- $ref: '#/components/parameters/FrontendId'
responses:
'202':
description: Frontend deletion started or queued
'400':
description: Bad request - invalid identifier
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Unauthorized - invalid or missing token
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'403':
description: Forbidden - project ownership required
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Frontend not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Internal server error
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'503':
description: Service unavailable - frontend workflow configuration missing
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/projects/{id}/frontends/{frontendId}/redeploy:
post:
tags:
- Frontends
summary: Redeploy frontend using latest uploaded artifact
description: |
Starts a new frontend workflow using the latest stored artifact. A deployment that starts
immediately returns `status: provisioning`, then transitions to `active`, `degraded`, or
`failed`. An overlapping deployment preserves the frontend's current status, is exposed through
`pending_deployment_id`, and supersedes any older queued deployment. The previous runtime and its
published static assets remain available during provisioning, and a failed redeploy restores the
regional runtimes to that build and keeps it serving while the attempted deployment is recorded as
failed.
operationId: redeployFrontend
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
- $ref: '#/components/parameters/FrontendId'
responses:
'200':
description: Frontend redeploy started or queued
content:
application/json:
schema:
$ref: '#/components/schemas/Frontend'
'400':
description: Bad request - invalid identifier
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Unauthorized - invalid or missing token
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'403':
description: Forbidden - project ownership required
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Frontend not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'409':
description: Conflict - frontend deletion is queued or running
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Internal server error
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'503':
description: Service unavailable - frontend workflow configuration missing
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/projects/{id}/frontends/{frontendId}/domain:
get:
tags:
- Frontends
summary: Get frontend custom domain status
operationId: getFrontendCustomDomain
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
- $ref: '#/components/parameters/FrontendId'
responses:
'200':
description: |
Frontend custom domain status, or null when the frontend has no
custom domain configured (the common empty state).
content:
application/json:
schema:
nullable: true
allOf:
- $ref: '#/components/schemas/FrontendCustomDomainResponse'
'400':
description: Bad request - invalid identifier
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Unauthorized - invalid or missing token
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'403':
description: Forbidden - project ownership required
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Frontend not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Internal server error
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
post:
tags:
- Frontends
summary: Configure frontend custom domain (SUPERAGENT)
description: |
Configures one custom domain for a frontend.
The default Volcano-generated frontend URL remains active.
Wildcard Volcano frontend TLS remains valid and isolated from custom-domain certificate changes.
Managed TLS returns the DNS records currently required for setup. Volcano may require a tenant-specific TXT ownership challenge before returning the certificate authority's validation record. After ownership verification succeeds, Volcano permanently assigns the hostname to the account, including after the domain is deleted. A required but unverified ownership reservation expires after 72 hours.
An unverified reservation does not block an account that proves ownership. When another account holds one, a managed TLS request gets `409` with `code: ownership_verification_required` and the caller's own `required_record`; after publishing it, the same request takes over the reservation. A BYOC request with a publicly trusted certificate and key for the hostname also takes it over; other BYOC requests get a `409` without `code`. Hostnames claimed through ownership verification and BYOC domains are never taken over.
operationId: createFrontendCustomDomain
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
- $ref: '#/components/parameters/FrontendId'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CreateFrontendCustomDomainRequest'
responses:
'200':
description: Custom domain already configured with same hostname
content:
application/json:
schema:
$ref: '#/components/schemas/FrontendCustomDomainResponse'
'201':
description: Custom domain provisioning started
content:
application/json:
schema:
$ref: '#/components/schemas/FrontendCustomDomainResponse'
'400':
description: Bad request - invalid domain
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Unauthorized - invalid or missing token
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'403':
description: Forbidden - custom domains require SUPERAGENT plan
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Frontend not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'409':
description: Conflict - custom domain already in use, reserved by another account until ownership is proven, still detaching, or frontend already has a custom domain
content:
application/json:
schema:
$ref: '#/components/schemas/FrontendCustomDomainConflictError'
'500':
description: Internal server error
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'503':
description: Service unavailable - custom domain provisioning is temporarily unavailable
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
delete:
tags:
- Frontends
summary: Delete frontend custom domain
operationId: deleteFrontendCustomDomain
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
- $ref: '#/components/parameters/FrontendId'
responses:
'204':
description: Custom domain detach scheduled
'400':
description: Bad request - invalid identifier
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Unauthorized - invalid or missing token
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'403':
description: Forbidden - project ownership required
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Frontend or custom domain not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Internal server error
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/projects/{id}/frontends/{frontendId}/deployments:
get:
tags:
- Frontends
summary: List frontend deployments
operationId: listFrontendDeployments
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
- $ref: '#/components/parameters/FrontendId'
- $ref: '#/components/parameters/Page'
- $ref: '#/components/parameters/Limit'
responses:
'200':
description: Successful response
content:
application/json:
schema:
$ref: '#/components/schemas/PaginatedFrontendDeployments'
'400':
description: Bad request - invalid identifier
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Unauthorized - invalid or missing token
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'403':
description: Forbidden - project ownership required
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Frontend not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Internal server error
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/projects/{id}/frontends/{frontendId}/usage:
get:
tags:
- Frontends
summary: Per-day request and error counts for a single frontend
description: |
Returns a zero-filled daily series of request counts and 5xx
error counts for one frontend, oldest first. Each entry is one
UTC day; missing days (no traffic recorded) come back as
`requests: 0, errors: 0` so the response always has exactly
`days` entries.
Backs the Monitoring section on the Frontend detail page in
volcano-web. `days` defaults to 30 and is capped at 90 to keep
the (frontend_id, day) index scan bounded.
operationId: getFrontendUsageHistory
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
- $ref: '#/components/parameters/FrontendId'
- name: days
in: query
description: Number of trailing days to return (1–90, default 30).
required: false
schema:
type: integer
minimum: 1
maximum: 90
default: 30
responses:
'200':
description: Successful response
content:
application/json:
schema:
$ref: '#/components/schemas/FrontendUsageHistoryResponse'
'400':
description: Bad request - invalid identifier
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Unauthorized - invalid or missing token
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'403':
description: Forbidden - project ownership required
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Frontend not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Internal server error
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/projects/{id}/variables:
get:
tags:
- Variables
summary: List all variables for a project
description: |
Returns project-level environment variables used by deployed functions and frontends.
operationId: listVariables
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
- $ref: '#/components/parameters/Page'
- $ref: '#/components/parameters/Limit'
- $ref: '#/components/parameters/Cursor'
- $ref: '#/components/parameters/EndingBefore'
- $ref: '#/components/parameters/Offset'
- $ref: '#/components/parameters/Search'
responses:
'200':
description: Successful response
content:
application/json:
schema:
$ref: '#/components/schemas/PaginatedVariables'
'404':
description: Project not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
post:
tags:
- Variables
summary: Create or update a variable
description: |
Creates a project-level environment variable and triggers asynchronous propagation
to deployed functions and frontends in the project's configured regions.
operationId: createVariable
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CreateVariableRequest'
responses:
'201':
description: Variable created
content:
application/json:
schema:
$ref: '#/components/schemas/Variable'
'400':
description: Bad request
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'503':
description: Private variable membership writes are disabled during rollout
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/projects/{id}/databases:
get:
tags:
- Databases
summary: List all databases for a project
description: |
Supports two mutually exclusive pagination modes. Offset mode uses `page`
and `limit`. Cursor mode uses `cursor` and `limit`, supports `search`
(case-insensitive name match), and returns `next_cursor`/`prev_cursor`.
The optional `status` filter applies in both modes and is bound to the
cursor. Sending both `page` and `cursor` (or `page` and `search`) returns 400.
operationId: listDatabases
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
- $ref: '#/components/parameters/Page'
- $ref: '#/components/parameters/Limit'
- $ref: '#/components/parameters/Cursor'
- $ref: '#/components/parameters/EndingBefore'
- $ref: '#/components/parameters/Offset'
- $ref: '#/components/parameters/Search'
- name: status
in: query
required: false
schema:
type: string
enum:
- provisioning
- active
- restoring
- failed
- deleting
description: Return only the databases in this status.
responses:
'200':
description: Successful response
content:
application/json:
schema:
$ref: '#/components/schemas/PaginatedDatabases'
post:
tags:
- Databases
summary: Create a new serverless PostgreSQL database
description: |
Creates a serverless PostgreSQL database in the project.
Each project can hold 1 database on Hobby and up to 10,000 on Superagent.
Requests over the plan's cap return 403.
operationId: createDatabase
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CreateDatabaseRequest'
responses:
'201':
description: Database created (provisioning)
content:
application/json:
schema:
$ref: '#/components/schemas/Database'
'403':
description: Database limit exceeded for the project
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/projects/{id}/databases/{databaseName}:
get:
tags:
- Databases
summary: Get database details
operationId: getDatabase
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
- $ref: '#/components/parameters/DatabaseName'
responses:
'200':
description: Successful response
content:
application/json:
schema:
$ref: '#/components/schemas/Database'
delete:
tags:
- Databases
summary: Delete a database
description: |
Deletes a database and the instance backing it. When the instance is
removed synchronously the database row is deleted and the response is
`204`. If the instance cannot be deleted right away, the database row
is retained (status `deleting`) and its teardown is handed to the
background reconciler, which retries the deletion and removes the row
once the instance is gone; in that case the response is `202`. The database row is
never dropped while its instance still exists, so an instance is
never orphaned without a record to retry from.
operationId: deleteDatabase
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
- $ref: '#/components/parameters/DatabaseName'
responses:
'202':
description: |
Deletion accepted and in progress. The backing instance could not be
removed synchronously, so the database is marked `deleting` and torn
down asynchronously by the reconciler.
content:
application/json:
schema:
type: object
properties:
status:
type: string
example: deleting
message:
type: string
example: database deletion in progress
'204':
description: Database deleted (backing instance removed synchronously)
'404':
description: Project or database not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'409':
description: |
A restore is running on the database. Deleting it while a worker is
replacing its data would race that worker, so wait for the restore
to finish.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'503':
description: |
Volcano could not check whether a restore is running, and will not
delete a database that might be mid-restore. Retry.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/projects/{id}/databases/{databaseName}/branches:
get:
tags:
- Database Branches
summary: List a database's branches
description: |
Returns every branch of the database, including those still provisioning
and those that failed, since each still holds a name.
Connection strings are omitted. Fetch a single branch to get its
connection string.
operationId: listDatabaseBranches
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
- $ref: '#/components/parameters/DatabaseName'
responses:
'200':
description: Successful response
content:
application/json:
schema:
$ref: '#/components/schemas/DatabaseBranchList'
'404':
description: Project or database not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'503':
description: Branching is temporarily unavailable
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
post:
tags:
- Database Branches
summary: Create a branch of a database
description: |
Forks the database into a new branch. The branch starts as an exact copy
of the parent's data and diverges from there.
Provisioning is asynchronous: the response is `202` with the branch in
`provisioning` and no connection string. Poll the branch until it reports
`active`, at which point it carries its own connection string.
Retrying a create with a name that already exists returns `409` rather
than a second branch, so a retried request cannot silently consume two
slots of the branch allowance.
operationId: createDatabaseBranch
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
- $ref: '#/components/parameters/DatabaseName'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CreateDatabaseBranchRequest'
responses:
'202':
description: Branch accepted and provisioning
content:
application/json:
schema:
$ref: '#/components/schemas/DatabaseBranch'
'400':
description: Invalid branch name or lifetime
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'403':
description: |
The database has reached its branch allowance, or the owner's plan
does not include branching.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Project or database not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'409':
description: |
A branch of that name already exists on this database, or the
database cannot be branched right now because it is still
provisioning, being restored, failed, or being deleted.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'503':
description: Branching is temporarily unavailable
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/projects/{id}/databases/{databaseName}/branches/{branchName}:
get:
tags:
- Database Branches
summary: Get a branch
description: |
Returns the branch, including its connection string once it is `active`.
Poll this after creating a branch to learn when it is connectable.
operationId: getDatabaseBranch
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
- $ref: '#/components/parameters/DatabaseName'
- $ref: '#/components/parameters/BranchName'
responses:
'200':
description: Successful response
content:
application/json:
schema:
$ref: '#/components/schemas/DatabaseBranch'
'404':
description: Project, database, or branch not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'503':
description: Branching is temporarily unavailable
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
patch:
tags:
- Database Branches
summary: Extend a branch's lifetime
description: |
Replaces the branch's lifetime and restarts the countdown from now, so a
branch you are still working on is not swept mid-session. The new
duration is remembered, so a later reset re-arms the same lifetime.
operationId: updateDatabaseBranch
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
- $ref: '#/components/parameters/DatabaseName'
- $ref: '#/components/parameters/BranchName'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/UpdateDatabaseBranchRequest'
responses:
'200':
description: Lifetime updated
content:
application/json:
schema:
$ref: '#/components/schemas/DatabaseBranch'
'400':
description: Requested lifetime is outside the allowed range
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Project, database, or branch not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'409':
description: The branch is being deleted
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'503':
description: Branching is temporarily unavailable
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
delete:
tags:
- Database Branches
summary: Delete a branch
description: |
Marks the branch for teardown and returns immediately. The branch stops
accepting connections at once; its fork and its row are removed by a
background job, so a provider outage cannot leave the call hanging or the
branch half-deleted.
Deleting a branch that is still provisioning is allowed and stops the
build, and repeating the call while teardown is in progress is accepted
again. Once the branch is gone the call returns `404`.
operationId: deleteDatabaseBranch
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
- $ref: '#/components/parameters/DatabaseName'
- $ref: '#/components/parameters/BranchName'
responses:
'202':
description: Deletion accepted and in progress
content:
application/json:
schema:
type: object
properties:
status:
type: string
example: deleting
message:
type: string
example: branch deletion in progress
required:
- status
- message
'404':
description: Project, database, or branch not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'503':
description: Branching is temporarily unavailable
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/projects/{id}/databases/{databaseName}/branches/{branchName}/reset:
post:
tags:
- Database Branches
summary: Reset a branch to its parent's current state
description: |
Discards everything written on the branch and re-forks it from the
parent as it is now.
Returns immediately with the branch in `provisioning`. The rewind runs in
the background; poll the branch until it reports `active` before
connecting again.
The branch keeps its name and its connection string, so anything holding
that string keeps working once it is active again, and its lifetime is
re-armed to the duration it was created with. The branch does not serve
connections for the duration of the reset.
operationId: resetDatabaseBranch
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
- $ref: '#/components/parameters/DatabaseName'
- $ref: '#/components/parameters/BranchName'
responses:
'202':
description: Branch reset accepted; the branch is provisioning
content:
application/json:
schema:
$ref: '#/components/schemas/DatabaseBranch'
'404':
description: Project, database, or branch not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'409':
description: |
The branch is not active, a reset is already in progress, the parent
database is being restored, or the parent was restored within the
last 24 hours — a reset re-forks from the parent, and the provider
holds a child's reset shut for that long afterwards.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'503':
description: Branching is temporarily unavailable
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/projects/{id}/databases/{databaseName}/branches/{branchName}/reset-password:
post:
tags:
- Database Branches
summary: Rotate a branch's password
description: |
Issues a new password for the branch and invalidates the previous
connection string. Existing connections are not interrupted; new ones
must use the returned string. Proxies pick the rotation up within a few
seconds, so the previous password can still open new connections until
then.
The parent database's credentials are untouched.
operationId: resetDatabaseBranchPassword
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
- $ref: '#/components/parameters/DatabaseName'
- $ref: '#/components/parameters/BranchName'
responses:
'200':
description: Password rotated
content:
application/json:
schema:
$ref: '#/components/schemas/DatabaseBranch'
'404':
description: Project, database, or branch not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'409':
description: The branch is not active
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'503':
description: Branching is temporarily unavailable
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/projects/{id}/databases/{databaseName}/backups:
get:
tags:
- Database Backups
summary: List a database's backups
description: |
Returns every backup of the database, newest first, together with the
window a point-in-time restore may target.
Both backups you took and backups the schedule produced are listed;
`source` tells them apart. Only manual backups count against the plan's
backup allowance.
operationId: listDatabaseBackups
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
- $ref: '#/components/parameters/DatabaseName'
responses:
'200':
description: Successful response
content:
application/json:
schema:
$ref: '#/components/schemas/DatabaseBackupList'
'403':
description: Backups are SUPERAGENT-only and the owner's plan does not include them
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Project or database not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'409':
description: |
The database has no storage project yet, so there is nothing to
list. A database reports this while it is still provisioning.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'503':
description: Backups are temporarily unavailable
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
post:
tags:
- Database Backups
summary: Back up a database
description: |
Captures the database as it is now. The backup is available immediately;
its `size_bytes` appears once the storage provider has costed it.
Backups are rate-limited to one per minute per database, and capped by
the owner's plan.
operationId: createDatabaseBackup
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
- $ref: '#/components/parameters/DatabaseName'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CreateDatabaseBackupRequest'
responses:
'201':
description: Backup created
content:
application/json:
schema:
$ref: '#/components/schemas/DatabaseBackup'
'400':
description: Invalid backup name
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'403':
description: |
The database has reached its backup allowance, or the owner's plan
does not include backups, which are SUPERAGENT-only.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Project or database not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'409':
description: |
A backup of that name already exists, the database is not active, a
restore is running on it, or a backup was taken too recently.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'503':
description: Backups are temporarily unavailable
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/projects/{id}/databases/{databaseName}/backups/{backupName}:
get:
tags:
- Database Backups
summary: Get a backup
description: Returns one backup of the database.
operationId: getDatabaseBackup
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
- $ref: '#/components/parameters/DatabaseName'
- $ref: '#/components/parameters/BackupName'
responses:
'200':
description: Successful response
content:
application/json:
schema:
$ref: '#/components/schemas/DatabaseBackup'
'403':
description: Backups are SUPERAGENT-only and the owner's plan does not include them
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Project, database, or backup not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'409':
description: |
The database has no storage project yet, so it holds no backups. A
database reports this while it is still provisioning.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'503':
description: Backups are temporarily unavailable
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
delete:
tags:
- Database Backups
summary: Delete a backup
description: |
Deletes the backup and frees its storage. Scheduled backups can be
deleted too. A backup that is already gone reports `404`, so a name
that never existed and a name that no longer does read the same.
Refused with `409` while the database is being restored.
operationId: deleteDatabaseBackup
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
- $ref: '#/components/parameters/DatabaseName'
- $ref: '#/components/parameters/BackupName'
responses:
'200':
description: Backup deleted
content:
application/json:
schema:
type: object
properties:
status:
type: string
example: deleted
message:
type: string
example: backup deleted
required:
- status
- message
'403':
description: Backups are SUPERAGENT-only and the owner's plan does not include them
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Project, database, or backup not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'409':
description: |
The database is being restored. A restore is pinned to a backup it
may not have restored yet, so deleting one is refused until the
restore finishes.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'503':
description: Backups are temporarily unavailable
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/projects/{id}/databases/{databaseName}/backup-schedule:
get:
tags:
- Database Backups
summary: Get the automated backup schedule
description: |
Returns the database's backup schedule. An empty list means no scheduled
backups.
operationId: getDatabaseBackupSchedule
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
- $ref: '#/components/parameters/DatabaseName'
responses:
'200':
description: Successful response
content:
application/json:
schema:
$ref: '#/components/schemas/DatabaseBackupSchedule'
'403':
description: Backups are SUPERAGENT-only and the owner's plan does not include them
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Project or database not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'409':
description: |
The database has no storage project yet, so it has no schedule. A
database reports this while it is still provisioning.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'503':
description: Backups are temporarily unavailable
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
put:
tags:
- Database Backups
summary: Replace the automated backup schedule
description: |
Replaces the schedule wholesale. Send an empty `entries` list to stop
scheduled backups.
Scheduled backups do not count against the plan's backup allowance, but
their retention is clamped to the plan's.
operationId: updateDatabaseBackupSchedule
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
- $ref: '#/components/parameters/DatabaseName'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/DatabaseBackupSchedule'
responses:
'200':
description: Schedule replaced
content:
application/json:
schema:
$ref: '#/components/schemas/DatabaseBackupSchedule'
'400':
description: |
The schedule names a recurrence that cannot fire: a weekly or
monthly one with no `day`, or a `day` outside its frequency's range
(1-7 for weekly, 1-28 for monthly). The response says which.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'403':
description: Backups are SUPERAGENT-only and the owner's plan does not include them
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Project or database not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'409':
description: |
The database is not active, or a restore is running on it — a restore
moves the data to a new branch, and the provider keeps the schedule
per branch.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'503':
description: Backups are temporarily unavailable
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/projects/{id}/databases/{databaseName}/restores:
get:
tags:
- Database Backups
summary: List a database's restores
description: |
Returns the database's restore history, newest first, capped at the 50
most recent. There is no pagination: a database that has been restored
more than 50 times keeps the older records but does not return them.
operationId: listDatabaseRestores
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
- $ref: '#/components/parameters/DatabaseName'
responses:
'200':
description: Successful response
content:
application/json:
schema:
$ref: '#/components/schemas/DatabaseRestoreList'
'403':
description: Backups are SUPERAGENT-only and the owner's plan does not include them
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Project or database not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'503':
description: Backups are temporarily unavailable
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
post:
tags:
- Database Backups
summary: Restore a database
description: |
Replaces the database's data, either with a named backup or with its
state at a point in time. This is destructive: everything written after
that point is discarded.
Asynchronous: the response is `202` with the restore `pending` and the
database `restoring`. The database does not accept connections until the
restore reports `completed`; its connection string is unchanged
throughout, so nothing holding it needs updating.
Restores are in place. There is no way to restore into a second
database, and a database's branches are never restored — they keep
serving their own data, but resetting a branch from its parent is
refused by the storage provider for up to 24 hours afterwards.
operationId: createDatabaseRestore
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
- $ref: '#/components/parameters/DatabaseName'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CreateDatabaseRestoreRequest'
responses:
'202':
description: Restore accepted and in progress
content:
application/json:
schema:
$ref: '#/components/schemas/DatabaseRestore'
'400':
description: |
Neither or both restore targets were named, or the requested time is
outside the available window.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'403':
description: |
The owner's plan does not include backups or point-in-time restore.
Both are SUPERAGENT-only.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Project, database, or backup not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'409':
description: |
A restore is already in progress, the database is not active,
another database operation is still running, or the database is
holding as many pre-restore branches as it may.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'503':
description: Backups are temporarily unavailable
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/projects/{id}/databases/{databaseName}/restores/{restoreId}:
get:
tags:
- Database Backups
summary: Get a restore
description: |
Returns the restore. Poll this after starting one; the database is
connectable again once it reports `completed`.
operationId: getDatabaseRestore
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
- $ref: '#/components/parameters/DatabaseName'
- $ref: '#/components/parameters/RestoreId'
responses:
'200':
description: Successful response
content:
application/json:
schema:
$ref: '#/components/schemas/DatabaseRestore'
'403':
description: Backups are SUPERAGENT-only and the owner's plan does not include them
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Project, database, or restore not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'503':
description: Backups are temporarily unavailable
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/projects/{id}/databases/{databaseName}/reset-password:
post:
tags:
- Databases
summary: Reset database password
description: |
Rotates the Volcano-managed PostgreSQL password used by clients when connecting
through pgproxy. This does not rotate or expose the internal owner password.
The returned password and connection string are the only client credentials that
will authenticate through pgproxy after reset.
Existing connections are not interrupted; new ones must use the returned
string. Proxies pick the rotation up within a few seconds, so the previous
password can still open new connections until then.
operationId: resetDatabasePassword
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
- $ref: '#/components/parameters/DatabaseName'
responses:
'200':
description: Password reset successful
content:
application/json:
schema:
type: object
properties:
message:
type: string
role_name:
type: string
description: Volcano-managed per-database client login (also the pgproxy routing username)
example: volcano_client_11111111-1111-1111-1111-111111111111
new_password:
type: string
description: New Volcano-managed client password. Always starts with `vpg_`.
connection_string:
type: string
description: Updated pgproxy connection string using Volcano-managed credentials.
'400':
description: Database is not active
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Database not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'409':
description: |
A restore is running on the database. A restore replaces the
credentials as it finishes, so wait for it and rotate afterwards.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'503':
description: |
Volcano could not check whether a restore is running, and will not
rotate a credential a restore might be about to replace. Retry.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/projects/{id}/databases/{databaseName}/type:
patch:
tags:
- Databases
summary: Update database size
description: |
Change the size tier of a database. This may briefly interrupt active connections.
**Available sizes:**
- `volcano-db-xs`: Up to ~1GB RAM - Development, small apps
- `volcano-db-s`: Up to ~4GB RAM - Production-ready, light traffic
- `volcano-db-m`: Up to ~8GB RAM - Medium traffic applications
- `volcano-db-l`: Up to ~16GB RAM - High traffic, larger datasets
- `volcano-db-xl`: Up to ~32GB RAM - Heavy workloads
- `volcano-db-2xl`: Up to ~64GB RAM - Enterprise-scale
operationId: updateDatabaseType
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
- $ref: '#/components/parameters/DatabaseName'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/UpdateDatabaseTypeRequest'
responses:
'200':
description: Database type updated
content:
application/json:
schema:
$ref: '#/components/schemas/Database'
'400':
description: Invalid database type
'404':
description: Database not found
'409':
description: |
The database is not active — being provisioned, deleted, or
restored. Compute can only be changed while it is active.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'503':
description: |
Volcano could not check whether a restore is running, and will not
reconfigure compute a restore might be moving. Retry.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/projects/{id}/databases/{databaseName}/stats:
get:
tags:
- Databases
summary: Get database consumption metrics
description: |
Retrieve consumption metrics including storage, compute time, and data transfer.
Metrics are aggregated at the project level. Defaults to last 24 hours.
**Note:** Advanced metrics require an upgraded plan.
operationId: getDatabaseStats
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
- $ref: '#/components/parameters/DatabaseName'
- name: from
in: query
required: false
schema:
type: string
format: date-time
description: Start time in RFC3339 format (e.g., "2024-01-01T00:00:00Z"). Defaults to 24 hours ago.
- name: to
in: query
required: false
schema:
type: string
format: date-time
description: End time in RFC3339 format (e.g., "2024-01-02T00:00:00Z"). Defaults to now.
- name: granularity
in: query
required: false
schema:
type: string
enum:
- hourly
- daily
- monthly
default: hourly
description: Level of detail for metrics aggregation
responses:
'200':
description: Successful response
content:
application/json:
schema:
$ref: '#/components/schemas/DatabaseStats'
'400':
description: Invalid parameters
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Database not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'503':
description: Database metrics not available or requires upgraded plan
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/databases/{databaseName}/query/ping:
post:
tags:
- Database Queries
summary: Database connectivity probe (REST API)
description: |
Connectivity probe that runs a fixed `SELECT 1` through pgproxy, using the
same authentication, status/bandwidth gating, and metering as the other
`/query/*` endpoints.
Unlike those endpoints, ping takes **no request body** and performs **no
table-name validation**, so it works on any database — including a freshly
provisioned, empty one. It is a real committed round-trip through pgproxy,
so a `200` means the database is reachable and queryable. Used by the
dashboard's database connection test.
operationId: queryDatabasePing
security:
- AuthUserAccessToken: []
parameters:
- $ref: '#/components/parameters/DatabaseName'
responses:
'200':
description: Database is reachable
content:
application/json:
schema:
$ref: '#/components/schemas/DatabaseQueryResult'
example:
data:
- '?column?': 1
count: 1
'401':
description: Not authenticated
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'403':
description: Access denied
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Database not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'429':
$ref: '#/components/responses/DatabaseQueryCapExceeded'
/databases/{databaseName}/query/select:
post:
tags:
- Database Queries
summary: Query database with SELECT (REST API)
description: |
Query your database using a simple REST API - no SQL required!
**Authentication:** Requires auth user access token (from signup/signin)
**Row-Level Security:** Automatically enforced - you see only data you have access to
**Use Cases:**
- Query from browser/mobile apps
- Simple data retrieval
- Filtered searches with sorting and pagination
**Note:** For complex queries (JOINs, CTEs), use functions with direct SQL
operationId: queryDatabaseSelect
security:
- AuthUserAccessToken: []
parameters:
- $ref: '#/components/parameters/DatabaseName'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/DatabaseSelectRequest'
responses:
'200':
description: Query successful
content:
application/json:
schema:
$ref: '#/components/schemas/DatabaseQueryResult'
example:
data:
- id: uuid-123
title: My Post
content: Post content
status: published
views: 150
created_at: '2026-01-13T10:00:00Z'
count: 1
'400':
description: Invalid query
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Not authenticated
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'403':
description: Access denied
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Database not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'429':
$ref: '#/components/responses/DatabaseQueryCapExceeded'
/databases/{databaseName}/query/insert:
post:
tags:
- Database Queries
summary: Insert data into database (REST API)
description: |
Insert new rows into your database using REST API.
**Authentication:** Requires auth user access token
**Auto-set user_id:** If your table has a trigger using `auth.uid()`,
user_id will be automatically set to the authenticated user
**Security:** Row-Level Security policies are enforced
operationId: queryDatabaseInsert
security:
- AuthUserAccessToken: []
parameters:
- $ref: '#/components/parameters/DatabaseName'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/DatabaseInsertRequest'
responses:
'200':
description: Insert successful
content:
application/json:
schema:
$ref: '#/components/schemas/DatabaseQueryResult'
example:
data:
- id: uuid-123
title: My New Post
content: This is the content
status: draft
user_id: user-uuid
created_at: '2026-01-13T10:00:00Z'
count: 1
'400':
description: Invalid request
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Not authenticated
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'403':
description: Access denied
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Database not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'429':
$ref: '#/components/responses/DatabaseQueryCapExceeded'
/databases/{databaseName}/query/update:
post:
tags:
- Database Queries
summary: Update data in database (REST API)
description: |
Update existing rows in your database using REST API.
**Security:** Row-Level Security ensures you can only update data you have access to
**Safety:** Requires at least one filter to prevent accidental mass updates. A
request with no `filters` is rejected with `400` (mirrors delete). This matters
for service-key queries, which run with full access and bypass RLS.
**Note:** If RLS blocks the update, an empty result is returned (not an error)
operationId: queryDatabaseUpdate
security:
- AuthUserAccessToken: []
parameters:
- $ref: '#/components/parameters/DatabaseName'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/DatabaseUpdateRequest'
responses:
'200':
description: Update successful
content:
application/json:
schema:
$ref: '#/components/schemas/DatabaseQueryResult'
example:
data:
- id: post-uuid
title: Updated Title
status: published
updated_at: '2026-01-13T10:05:00Z'
count: 1
'400':
description: Invalid request
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Not authenticated
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'403':
description: Access denied
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Database not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'429':
$ref: '#/components/responses/DatabaseQueryCapExceeded'
/databases/{databaseName}/query/delete:
post:
tags:
- Database Queries
summary: Delete data from database (REST API)
description: |
Delete rows from your database using REST API.
**Safety:** Requires at least one filter to prevent accidental mass deletions
**Security:** Row-Level Security ensures you can only delete data you have access to
**Note:** If RLS blocks the delete, an empty result is returned (not an error)
operationId: queryDatabaseDelete
security:
- AuthUserAccessToken: []
parameters:
- $ref: '#/components/parameters/DatabaseName'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/DatabaseDeleteRequest'
responses:
'200':
description: Delete successful
content:
application/json:
schema:
$ref: '#/components/schemas/DatabaseQueryResult'
example:
data:
- id: post-uuid
title: Deleted Post
count: 1
'400':
description: Invalid request or missing filters
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Not authenticated
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'403':
description: Access denied
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Database not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'429':
$ref: '#/components/responses/DatabaseQueryCapExceeded'
/databases/{databaseName}/branches/{branchName}/query/ping:
post:
tags:
- Database Queries
summary: Database connectivity probe (REST API)
description: |
Connectivity probe that runs a fixed `SELECT 1` through pgproxy, using the
same authentication, status/bandwidth gating, and metering as the other
`/query/*` endpoints.
Unlike those endpoints, ping takes **no request body** and performs **no
table-name validation**, so it works on any database — including a freshly
provisioned, empty one. It is a real committed round-trip through pgproxy,
so a `200` means the database is reachable and queryable. Used by the
dashboard's database connection test.
**Branch-targeted.** Runs against the named branch instead of the parent
database, using the branch's own credentials. The branch must be `active`
and unexpired. Nothing about this request can reach the parent's data.
operationId: queryDatabaseBranchPing
security:
- AuthUserAccessToken: []
parameters:
- $ref: '#/components/parameters/DatabaseName'
- $ref: '#/components/parameters/BranchName'
responses:
'200':
description: Database is reachable
content:
application/json:
schema:
$ref: '#/components/schemas/DatabaseQueryResult'
example:
data:
- '?column?': 1
count: 1
'401':
description: Not authenticated
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'403':
description: Access denied
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Database or branch not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'429':
$ref: '#/components/responses/DatabaseQueryCapExceeded'
'503':
$ref: '#/components/responses/DatabaseBranchQueryUnavailable'
/databases/{databaseName}/branches/{branchName}/query/select:
post:
tags:
- Database Queries
summary: Query database with SELECT (REST API)
description: |
Query your database using a simple REST API - no SQL required!
**Authentication:** Requires auth user access token (from signup/signin)
**Row-Level Security:** Automatically enforced - you see only data you have access to
**Use Cases:**
- Query from browser/mobile apps
- Simple data retrieval
- Filtered searches with sorting and pagination
**Note:** For complex queries (JOINs, CTEs), use Lambda functions with direct SQL
**Branch-targeted.** Runs against the named branch instead of the parent
database, using the branch's own credentials. The branch must be `active`
and unexpired. Nothing about this request can reach the parent's data.
operationId: queryDatabaseBranchSelect
security:
- AuthUserAccessToken: []
parameters:
- $ref: '#/components/parameters/DatabaseName'
- $ref: '#/components/parameters/BranchName'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/DatabaseSelectRequest'
responses:
'200':
description: Query successful
content:
application/json:
schema:
$ref: '#/components/schemas/DatabaseQueryResult'
example:
data:
- id: uuid-123
title: My Post
content: Post content
status: published
views: 150
created_at: '2026-01-13T10:00:00Z'
count: 1
'400':
description: Invalid query
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Not authenticated
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'403':
description: Access denied
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Database or branch not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'429':
$ref: '#/components/responses/DatabaseQueryCapExceeded'
'503':
$ref: '#/components/responses/DatabaseBranchQueryUnavailable'
/databases/{databaseName}/branches/{branchName}/query/insert:
post:
tags:
- Database Queries
summary: Insert data into database (REST API)
description: |
Insert new rows into your database using REST API.
**Authentication:** Requires auth user access token
**Auto-set user_id:** If your table has a trigger using `auth.uid()`,
user_id will be automatically set to the authenticated user
**Security:** Row-Level Security policies are enforced
**Branch-targeted.** Runs against the named branch instead of the parent
database, using the branch's own credentials. The branch must be `active`
and unexpired. Nothing about this request can reach the parent's data.
operationId: queryDatabaseBranchInsert
security:
- AuthUserAccessToken: []
parameters:
- $ref: '#/components/parameters/DatabaseName'
- $ref: '#/components/parameters/BranchName'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/DatabaseInsertRequest'
responses:
'200':
description: Insert successful
content:
application/json:
schema:
$ref: '#/components/schemas/DatabaseQueryResult'
example:
data:
- id: uuid-123
title: My New Post
content: This is the content
status: draft
user_id: user-uuid
created_at: '2026-01-13T10:00:00Z'
count: 1
'400':
description: Invalid request
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Not authenticated
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'403':
description: Access denied
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Database or branch not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'429':
$ref: '#/components/responses/DatabaseQueryCapExceeded'
'503':
$ref: '#/components/responses/DatabaseBranchQueryUnavailable'
/databases/{databaseName}/branches/{branchName}/query/update:
post:
tags:
- Database Queries
summary: Update data in database (REST API)
description: |
Update existing rows in your database using REST API.
**Security:** Row-Level Security ensures you can only update data you have access to
**Safety:** Requires at least one filter to prevent accidental mass updates. A
request with no `filters` is rejected with `400` (mirrors delete). This matters
for service-key queries, which run with full access and bypass RLS.
**Note:** If RLS blocks the update, an empty result is returned (not an error)
**Branch-targeted.** Runs against the named branch instead of the parent
database, using the branch's own credentials. The branch must be `active`
and unexpired. Nothing about this request can reach the parent's data.
operationId: queryDatabaseBranchUpdate
security:
- AuthUserAccessToken: []
parameters:
- $ref: '#/components/parameters/DatabaseName'
- $ref: '#/components/parameters/BranchName'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/DatabaseUpdateRequest'
responses:
'200':
description: Update successful
content:
application/json:
schema:
$ref: '#/components/schemas/DatabaseQueryResult'
example:
data:
- id: post-uuid
title: Updated Title
status: published
updated_at: '2026-01-13T10:05:00Z'
count: 1
'400':
description: Invalid request
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Not authenticated
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'403':
description: Access denied
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Database or branch not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'429':
$ref: '#/components/responses/DatabaseQueryCapExceeded'
'503':
$ref: '#/components/responses/DatabaseBranchQueryUnavailable'
/databases/{databaseName}/branches/{branchName}/query/delete:
post:
tags:
- Database Queries
summary: Delete data from database (REST API)
description: |
Delete rows from your database using REST API.
**Safety:** Requires at least one filter to prevent accidental mass deletions
**Security:** Row-Level Security ensures you can only delete data you have access to
**Note:** If RLS blocks the delete, an empty result is returned (not an error)
**Branch-targeted.** Runs against the named branch instead of the parent
database, using the branch's own credentials. The branch must be `active`
and unexpired. Nothing about this request can reach the parent's data.
operationId: queryDatabaseBranchDelete
security:
- AuthUserAccessToken: []
parameters:
- $ref: '#/components/parameters/DatabaseName'
- $ref: '#/components/parameters/BranchName'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/DatabaseDeleteRequest'
responses:
'200':
description: Delete successful
content:
application/json:
schema:
$ref: '#/components/schemas/DatabaseQueryResult'
example:
data:
- id: post-uuid
title: Deleted Post
count: 1
'400':
description: Invalid request or missing filters
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Not authenticated
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'403':
description: Access denied
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Database or branch not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'429':
$ref: '#/components/responses/DatabaseQueryCapExceeded'
'503':
$ref: '#/components/responses/DatabaseBranchQueryUnavailable'
/databases/regions:
get:
tags:
- Databases
summary: List platform-supported regions for database provisioning
operationId: listDatabaseRegions
description: |
Returns the regions enabled for database provisioning in this platform environment.
These are the same regions offered for function deployment, and the only values
the `region` field of a database accepts.
This is a public endpoint that doesn't require authentication.
responses:
'200':
description: List of platform-supported regions
content:
application/json:
schema:
type: array
items:
type: object
properties:
id:
type: string
example: aws-us-east-1
description: Region identifier for API usage
name:
type: string
example: US East (N. Virginia)
description: Human-readable region location
/databases/postgres-versions:
get:
tags:
- Databases
summary: List available PostgreSQL versions
operationId: listPostgresVersions
description: |
Returns a list of supported PostgreSQL major versions for database provisioning.
This is a public endpoint that doesn't require authentication.
responses:
'200':
description: List of available PostgreSQL versions
content:
application/json:
schema:
type: array
items:
type: object
properties:
version:
type: string
example: '16'
description: PostgreSQL major version number
name:
type: string
example: PostgreSQL 16
description: Human-readable version name
default:
type: boolean
description: Whether this is the default version (recommended)
deprecated:
type: boolean
description: Whether this version is deprecated (approaching EOL)
/functions/runtimes:
get:
tags:
- Functions
summary: List supported function runtimes
operationId: listFunctionRuntimes
security: []
description: |
Returns the public function runtime catalog used by CLI clients to select supported runtimes,
language defaults, and local source packaging metadata for deployments.
This is a public endpoint that doesn't require authentication.
responses:
'200':
description: Supported function runtimes
content:
application/json:
schema:
$ref: '#/components/schemas/FunctionRuntimesResponse'
/functions/regions:
get:
tags:
- Functions
summary: List available regions for function deployment
operationId: listFunctionRegions
security: []
description: |
Returns the configured regions where functions can be deployed, each annotated
with a human-readable label and country flag emoji for use in UI pickers.
This is a public endpoint that doesn't require authentication.
responses:
'200':
description: Available function deployment regions
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/FunctionRegion'
/projects/{id}/variables/{name}:
get:
tags:
- Variables
summary: Get variable by name
description: |
Returns a project-level environment variable used by deployed functions and frontends.
operationId: getVariable
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
- $ref: '#/components/parameters/VariableName'
responses:
'200':
description: Successful response
content:
application/json:
schema:
$ref: '#/components/schemas/Variable'
'404':
description: Variable not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
put:
tags:
- Variables
summary: Update a variable
description: |
Updates a project-level environment variable and triggers asynchronous propagation
to deployed functions and frontends in the project's configured regions.
operationId: updateVariable
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
- $ref: '#/components/parameters/VariableName'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/UpdateVariableRequest'
responses:
'200':
description: Variable updated
content:
application/json:
schema:
$ref: '#/components/schemas/Variable'
'404':
description: Variable not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'503':
description: Private variable membership writes are disabled during rollout
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
delete:
tags:
- Variables
summary: Delete a variable
description: |
Deletes a project-level environment variable and triggers asynchronous propagation
of the removal to deployed functions and frontends in the project's configured regions.
operationId: deleteVariable
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
- $ref: '#/components/parameters/VariableName'
responses:
'204':
description: Variable deleted
'404':
description: Variable not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/auth/password-policy:
get:
tags:
- Authentication
summary: Get the effective password policy
description: |
Returns the backend-enforced password bounds and compromised-password
screening status for the project identified by the anon key. A valid
anon key is required, but no route-specific auth permission is needed.
operationId: authGetPasswordPolicy
security:
- AnonKey: []
responses:
'200':
description: Effective password policy
content:
application/json:
schema:
$ref: '#/components/schemas/AuthPasswordPolicy'
'401':
description: Invalid, missing, or revoked anon key
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Project or auth configuration not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/auth/signup:
post:
tags:
- Authentication
summary: Sign up a new auth user
description: |
Create a new end-user account. The project is determined from the anon key.
Requires project-specific anon key in Authorization header.
**Session-less**: signup never issues a session. On success it returns a
uniform acknowledgement (`AuthSignupResponse`) with no tokens; the client
obtains a session with a subsequent `POST /auth/signin`. If email confirmation
is enabled for the project, a confirmation email is sent and
`confirmation_required` is `true`.
**Anti-enumeration**: a signup for an already-registered email returns the
exact same `201` response as a fresh signup — it never returns `409` — so the
response cannot be used to discover which emails are registered.
operationId: authSignup
security:
- AnonKey: []
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- email
- password
properties:
email:
type: string
format: email
password:
type: string
description: |
Password validated after NFC normalization against the
policy returned by GET /auth/password-policy.
user_metadata:
type: object
additionalProperties: true
responses:
'201':
description: |
Signup acknowledged (session-less). Returned identically for a new
account and for an already-registered email (anti-enumeration).
content:
application/json:
schema:
$ref: '#/components/schemas/AuthSignupResponse'
'400':
description: Invalid input (bad email/password format)
'401':
description: |
Unauthorized - Invalid, tampered, revoked, or wrong-project anon key
'403':
description: |
Forbidden - Signups disabled, anon key lacks signup permission, or the
email domain is not in `allowed_email_domains`. The internal
`anonymous.volcano.internal` domain is reserved for anonymous
accounts and is refused whatever the project allows.
'429':
description: Rate limit exceeded
'503':
description: Compromised-password screening is temporarily unavailable
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/auth/signin:
post:
tags:
- Authentication
summary: Sign in an auth user
description: |
Authenticate with email and password. Requires an anon key.
Set `session_mode` to `cookie` to request HttpOnly refresh-token
storage. Cookie mode is honored only for an exact, credentialed CORS
origin on the same schemeful site as this API. Otherwise the response
retains the refresh token in its body. A frontend on its default
Volcano URL is cross-site with this API and so always gets the body
token.
operationId: authSignin
security:
- AnonKey: []
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- email
- password
properties:
email:
type: string
password:
type: string
session_mode:
type: string
enum:
- cookie
responses:
'200':
description: Signin successful
content:
application/json:
schema:
$ref: '#/components/schemas/AuthTokenResponse'
'400':
description: Invalid input (missing email/password)
'401':
description: |
Unauthorized - Invalid credentials, invalid/tampered/revoked anon key,
or account banned/deleted
'403':
description: |
Forbidden - Anon key lacks signin permission, or the email domain is
not in `allowed_email_domains` while `allowed_email_domains_mode` is
`signup_and_signin`. The domain is taken from the account's canonical
email (its primary identity), which is not necessarily the address in
the request.
'429':
description: Rate limit exceeded
/auth/refresh:
post:
tags:
- Authentication
summary: Refresh access token
description: |
Get a new access token using a refresh token. Requires an anon key.
Send `refresh_token` in the body for the default flow. An eligible
cookie-mode browser request may instead send `session_mode: cookie`
with an empty token or omit the request body; the API reads and resets
the project's HttpOnly cookie and omits `refresh_token` from the
response.
operationId: authRefresh
security:
- AnonKey: []
requestBody:
required: false
content:
application/json:
schema:
type: object
properties:
refresh_token:
type: string
session_mode:
type: string
enum:
- cookie
responses:
'200':
description: Token refreshed
content:
application/json:
schema:
$ref: '#/components/schemas/AuthTokenResponse'
'401':
description: Invalid or expired refresh token
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'403':
description: |
The account's email domain is not in `allowed_email_domains` while
`allowed_email_domains_mode` is `signup_and_signin`, so the session
cannot be extended
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'429':
description: Rate limit exceeded
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/auth/logout:
post:
tags:
- Authentication
summary: Logout (revoke refresh token)
description: |
Invalidate a refresh token. Requires an anon key.
Send `refresh_token` for the default flow. An eligible cookie-mode
browser request may instead send `session_mode: cookie` with an empty
token; logout remains idempotent when the cookie is missing or expired.
operationId: authLogout
security:
- AnonKey: []
requestBody:
required: false
content:
application/json:
schema:
type: object
properties:
refresh_token:
type: string
session_mode:
type: string
enum:
- cookie
responses:
'204':
description: Logged out successfully
/auth/forgot-password:
post:
tags:
- Authentication
summary: Request password reset
description: |
Generates recovery token and stores it (email sending pending).
Returns generic message to prevent email enumeration.
Project is identified via the anon key.
operationId: authForgotPassword
security:
- AnonKey: []
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- email
properties:
email:
type: string
format: email
responses:
'200':
description: Generic success message (doesn't reveal if email exists)
content:
application/json:
schema:
type: object
properties:
message:
type: string
example: If the email exists, a password reset link has been sent
'403':
description: Password reset is disabled for this project
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'429':
description: Rate limit exceeded (10 requests per hour per IP)
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/auth/reset-password:
post:
tags:
- Authentication
summary: Reset password with recovery token
description: |
Reset password using recovery token from forgot-password.
Revokes all existing sessions for security.
operationId: authResetPassword
security:
- AnonKey: []
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- token
- new_password
properties:
token:
type: string
description: Recovery token from forgot-password
new_password:
type: string
description: |
Password validated after NFC normalization against the
policy returned by GET /auth/password-policy.
responses:
'200':
description: Password reset successful
content:
application/json:
schema:
type: object
properties:
message:
type: string
'400':
description: Password doesn't meet requirements
'401':
description: Invalid or expired token
'503':
description: Compromised-password screening is temporarily unavailable
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/auth/confirm:
post:
tags:
- Authentication
summary: Confirm email address
description: |
Confirm email address using token sent via email.
Required if require_email_confirmation is enabled.
operationId: authConfirmEmail
security:
- AnonKey: []
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- token
properties:
token:
type: string
description: Confirmation token from email
responses:
'200':
description: Email confirmed or already confirmed
content:
application/json:
schema:
type: object
properties:
message:
type: string
enum:
- Email confirmed successfully
- Email already confirmed
examples:
confirmed:
summary: Fresh confirmation
value:
message: Email confirmed successfully
alreadyConfirmed:
summary: Token belongs to already-confirmed user
value:
message: Email already confirmed
'400':
description: Missing confirmation token in request body
'401':
description: Invalid or expired token
/auth/resend-confirmation:
post:
tags:
- Authentication
summary: Resend confirmation email
description: |
Resend email confirmation link.
Returns generic message to prevent email enumeration.
No email is sent when the account does not exist or is already confirmed.
If the account exists and is unconfirmed, a new token is generated and
any previous confirmation token is invalidated.
operationId: authResendConfirmation
security:
- AnonKey: []
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- email
properties:
email:
type: string
format: email
responses:
'200':
description: Generic success message
content:
application/json:
schema:
type: object
properties:
message:
type: string
'429':
description: Rate limit exceeded
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/auth/signup-anonymous:
post:
tags:
- Authentication
summary: Create anonymous user
description: |
Create guest user without email/password.
User metadata (like display_name) can be included and will appear in realtime presence events.
Requires enable_anonymous_signins to be true.
operationId: authSignupAnonymous
security:
- AnonKey: []
requestBody:
description: Optional user metadata
content:
application/json:
schema:
type: object
properties:
user_metadata:
type: object
additionalProperties: true
description: Custom user metadata (e.g., display_name, avatar_url)
example:
display_name: Alice
avatar_url: https://example.com/alice.jpg
responses:
'201':
description: Anonymous user created
content:
application/json:
schema:
$ref: '#/components/schemas/AuthTokenResponse'
'403':
description: Anonymous signins disabled
/auth/user/convert-anonymous:
post:
tags:
- Authentication
summary: Convert anonymous user to authenticated
description: |
Add email and password to anonymous user.
Requires auth user access token.
If require_email_confirmation is enabled for the project, the converted
user remains unconfirmed until /auth/confirm succeeds. When email
sending is enabled, a confirmation email is sent during conversion.
operationId: authConvertAnonymous
security:
- AuthUserAccessToken: []
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- email
- password
properties:
email:
type: string
format: email
password:
type: string
description: |
Password validated after NFC normalization against the
policy returned by GET /auth/password-policy.
user_metadata:
type: object
additionalProperties: true
responses:
'200':
description: User converted successfully
content:
application/json:
schema:
type: object
properties:
user:
$ref: '#/components/schemas/AuthUser'
'400':
description: Not an anonymous user
'403':
description: |
The chosen email domain is not in `allowed_email_domains`
'409':
description: Email already in use
'503':
description: Compromised-password screening is temporarily unavailable
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/auth/user/change-email:
post:
tags:
- Authentication
summary: Request email change
description: |
Request to change user's email address.
Sends confirmation token to new email address.
operationId: authRequestEmailChange
security:
- AuthUserAccessToken: []
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- new_email
properties:
new_email:
type: string
format: email
responses:
'200':
description: Confirmation email sent
content:
application/json:
schema:
type: object
properties:
message:
type: string
new_email:
type: string
'400':
description: Invalid email format or same as current email
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Not authenticated
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'403':
description: |
The requested email domain is not in `allowed_email_domains`
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'409':
description: Email already in use
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'429':
description: Rate limit exceeded (10 requests per hour per IP)
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/auth/user/confirm-email-change:
post:
tags:
- Authentication
summary: Confirm email change
description: Confirm email change with token sent to new address
operationId: authConfirmEmailChange
security:
- AuthUserAccessToken: []
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- email_change_token
properties:
email_change_token:
type: string
responses:
'200':
description: Email changed successfully
content:
application/json:
schema:
type: object
properties:
message:
type: string
user:
$ref: '#/components/schemas/AuthUser'
'400':
description: Invalid or expired token, or no pending email change
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Not authenticated
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'403':
description: |
The pending email domain is no longer in `allowed_email_domains`.
Re-checked here because the allowlist can narrow between the request
and the confirmation.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'409':
description: Email is now in use by another user
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/auth/user/cancel-email-change:
delete:
tags:
- Authentication
summary: Cancel pending email change
operationId: authCancelEmailChange
security:
- AuthUserAccessToken: []
responses:
'200':
description: Email change cancelled
content:
application/json:
schema:
type: object
properties:
message:
type: string
'401':
description: Not authenticated
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/auth/user/sessions:
get:
tags:
- Authentication
summary: Get current user's sessions
description: |
Returns paginated sessions for the currently authenticated user.
Each session includes device info, IP addresses, and activity timestamps.
The current session is marked with `is_current: true`.
**Ordering and pagination.** Without `sort`, results are ordered by most
recent activity and paged with `page`/`limit`, returning the
`sessions`/`total`/`page`/`limit`/`total_pages` body below. This is the
legacy default and is preserved for existing clients.
Send `sort=created_at` to opt into the standard list contract: results are
ordered by session start (newest first) and may be paged either with
`page`/`limit` or by cursor with `cursor`/`ending_before` plus a bounded
`offset` past the cursor anchor. Cursor responses use the shared
`data` envelope with `next_cursor`/`prev_cursor`.
Unlike other list endpoints, sending `limit` without `page` does **not**
select cursor mode here; `sort=created_at` is the only opt-in. Cursor
pagination is rejected with 400 for the activity order, because
`last_activity_at` changes whenever a session refreshes its token: a row
that crosses the cursor anchor between two requests would be skipped and
never shown. The `status=expired` filter is also offset-only because a
session can expire above the cursor anchor during a walk. Sending that
filter in cursor mode, `page` with `cursor` or `ending_before`, or both
cursor directions returns 400.
operationId: authGetMySessions
security:
- AuthUserAccessToken: []
parameters:
- name: page
in: query
description: Page number (1-indexed)
schema:
type: integer
minimum: 1
default: 1
- name: limit
in: query
description: Number of sessions per page (max 100)
schema:
type: integer
minimum: 1
maximum: 100
default: 20
- name: sort
in: query
description: |
Sort key. `last_activity` (default) orders by most recent activity and
supports offset pagination only. `created_at` orders by session start
and supports both offset and cursor pagination.
schema:
type: string
enum:
- last_activity
- created_at
default: last_activity
- name: status
in: query
description: |
Filter by whether the session can still be refreshed. Omit for every
stored session, including expired ones. `expired` is not supported
with cursor pagination.
schema:
type: string
enum:
- active
- expired
- name: cursor
in: query
description: |
Opaque keyset cursor from a previous response's `next_cursor`. Requires
`sort=created_at`; mutually exclusive with `page` and `ending_before`.
schema:
type: string
- name: ending_before
in: query
description: |
Opaque keyset cursor from a previous response's `prev_cursor`, paging
backward. Requires `sort=created_at`; mutually exclusive with `page`
and `cursor`.
schema:
type: string
- name: offset
in: query
description: |
Bounded number of rows to skip past the cursor anchor (the hybrid
jump, maximum 100000). Ignored unless `cursor` or `ending_before` is
supplied.
schema:
type: integer
minimum: 0
maximum: 100000
responses:
'200':
description: Paginated list of user sessions
content:
application/json:
schema:
type: object
properties:
sessions:
type: array
items:
$ref: '#/components/schemas/AuthSession'
total:
type: integer
description: Total number of sessions
page:
type: integer
description: Current page number
limit:
type: integer
description: Number of sessions per page
total_pages:
type: integer
description: Total number of pages
data:
type: array
description: Sessions for this page (cursor pagination only)
items:
$ref: '#/components/schemas/AuthSession'
has_more:
type: boolean
description: Whether a further page exists (cursor pagination only)
next_cursor:
type: string
description: Opaque cursor for the next page (cursor pagination only)
prev_cursor:
type: string
description: Opaque cursor for the previous page (cursor pagination only). Send as `ending_before`.
'400':
description: Invalid or conflicting pagination parameters
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Not authenticated
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
delete:
tags:
- Authentication
summary: Sign out from all other devices
description: |
Deletes all sessions except the current one.
Use this to log out from all other devices while keeping the current session active.
operationId: authDeleteAllMySessions
security:
- AuthUserAccessToken: []
responses:
'204':
description: All other sessions deleted
'401':
description: Not authenticated
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/auth/user/sessions/{sessionId}:
delete:
tags:
- Authentication
summary: Sign out from specific device
description: |
Deletes a specific session, logging out that device.
You can get session IDs from the list sessions endpoint.
operationId: authDeleteMySession
security:
- AuthUserAccessToken: []
parameters:
- name: sessionId
in: path
required: true
description: The session ID to delete
schema:
type: string
format: uuid
responses:
'204':
description: Session deleted
'401':
description: Not authenticated
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Session not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/auth/user:
get:
tags:
- Authentication
summary: Get current user profile
description: Returns authenticated user's profile. Requires access token.
operationId: authGetUser
security:
- AuthUserAccessToken: []
responses:
'200':
description: User profile
content:
application/json:
schema:
type: object
properties:
user:
$ref: '#/components/schemas/AuthUser'
'401':
description: Not authenticated - access token missing or invalid
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
put:
tags:
- Authentication
summary: Update user profile
description: Update password or metadata. Requires access token.
operationId: authUpdateUser
security:
- AuthUserAccessToken: []
requestBody:
content:
application/json:
schema:
type: object
properties:
password:
type: string
description: |
Password validated after NFC normalization against the
policy returned by GET /auth/password-policy.
user_metadata:
type: object
additionalProperties: true
description: |
Metadata keys to merge into the current user metadata.
Omitted keys remain unchanged; set a key to null to remove it.
Merging is shallow; nested objects replace the stored value for that top-level key.
responses:
'200':
description: Profile updated
content:
application/json:
schema:
type: object
properties:
user:
$ref: '#/components/schemas/AuthUser'
'400':
description: Bad request - invalid password or metadata format
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Not authenticated - access token missing or invalid
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'503':
description: Compromised-password screening is temporarily unavailable
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/auth/user/identities:
get:
tags:
- Authentication
summary: List the current user's identities
description: |
Returns every real email identity the account owns. An account can own
multiple identities (for example a password identity plus one or more
OAuth identities on different emails). Anonymous accounts have no real
identity and return an empty list.
operationId: authListIdentities
security:
- AuthUserAccessToken: []
responses:
'200':
description: List of identities
content:
application/json:
schema:
$ref: '#/components/schemas/AuthIdentitiesResponse'
'401':
description: Not authenticated
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/auth/user/identities/{identityId}:
delete:
tags:
- Authentication
summary: Unlink an identity from the current user
description: |
Removes a non-primary identity and its attached sign-in methods. Refused
when the identity is the account's primary, its only identity, or when
removing it would leave the account with no way to sign in.
operationId: authUnlinkIdentity
security:
- AuthUserAccessToken: []
parameters:
- name: identityId
in: path
required: true
description: The identity ID to unlink
schema:
type: string
format: uuid
responses:
'204':
description: Identity unlinked
'400':
description: Identity cannot be unlinked (primary, last, or would remove last sign-in method), or the identity id is malformed
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Not authenticated
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Identity not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/auth/user/methods:
get:
tags:
- Authentication
summary: List the current user's sign-in methods
description: |
Returns a flat list of every sign-in method the account owns (password,
each OAuth provider, and any active anonymous method), with the primary
method flagged. Password stubs and converted anonymous methods are excluded.
operationId: authListMethods
security:
- AuthUserAccessToken: []
responses:
'200':
description: List of sign-in methods
content:
application/json:
schema:
$ref: '#/components/schemas/AuthMethodsResponse'
'401':
description: Not authenticated
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/auth/user/methods/{methodId}/promote:
post:
tags:
- Authentication
summary: Set a method as the account's primary
description: |
Promotes the given method to the account's primary sign-in method. The
account's canonical email is re-derived from the promoted method's identity.
Refused for password stubs and converted anonymous methods, and for an
identity whose domain is outside the project's `allowed_email_domains`.
operationId: authPromoteMethod
security:
- AuthUserAccessToken: []
parameters:
- name: methodId
in: path
required: true
description: The method ID to promote
schema:
type: string
format: uuid
responses:
'200':
description: The promoted method
content:
application/json:
schema:
$ref: '#/components/schemas/AuthMethodSummary'
'400':
description: This method cannot be set as primary (password stub, converted anonymous method, or unverified email), or the method id is malformed
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Not authenticated
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'403':
description: The promoted identity's email domain is not in the project's allowed_email_domains
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Method not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/projects/{id}/auth/insights:
get:
tags:
- Auth Admin
summary: Get auth user insights
description: |
Returns current auth-user totals, rolling 30-day active users, and
zero-filled signup and successful sign-in counts for an inclusive UTC
date range. Weeks start on Monday. Sign-in counts and active-user
activity begin when collection is deployed. Historical signup counts
are backfilled from users present at deployment. Token refreshes affect
active users but not the sign-in series.
operationId: getAuthInsights
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
- name: from
in: query
description: Inclusive UTC start date. Defaults to 29 days before `to`.
schema:
type: string
format: date
- name: to
in: query
description: Inclusive UTC end date. Defaults to today.
schema:
type: string
format: date
- name: interval
in: query
description: Chart bucket size. Defaults to `day`.
schema:
$ref: '#/components/schemas/AuthInsightsInterval'
responses:
'200':
description: Auth insights retrieved
content:
application/json:
schema:
$ref: '#/components/schemas/AuthInsightsResponse'
example:
project_id: 4f165080-a931-4e03-b3bd-41c45c3f0058
observed_at: '2026-07-20T18:00:00Z'
window:
from: '2026-06-21'
to: '2026-07-20'
interval: day
summary:
total_users: 1234
active_users_30d: 418
series:
- bucket_start: '2026-07-20'
signups: 12
signins: 97
is_partial: true
'400':
description: Invalid date range or interval
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Unauthorized - invalid or missing token
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'403':
description: Access denied
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Project not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Internal server error
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/projects/{id}/auth/users:
get:
tags:
- Auth Admin
summary: List all auth users (admin)
description: List auth users in project. Requires platform token.
operationId: listAuthUsers
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
- $ref: '#/components/parameters/Page'
- $ref: '#/components/parameters/Limit'
- $ref: '#/components/parameters/Cursor'
- $ref: '#/components/parameters/EndingBefore'
- $ref: '#/components/parameters/Offset'
- $ref: '#/components/parameters/Search'
- name: status
in: query
required: false
description: Filter by effective status. `banned` returns only currently-banned users; an expired temporary ban lists as `active`.
schema:
type: string
enum:
- active
- banned
responses:
'200':
description: Successful response
content:
application/json:
schema:
$ref: '#/components/schemas/PaginatedAuthUsers'
'400':
description: Invalid status or pagination parameters
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/projects/{id}/auth/users/{userId}:
get:
tags:
- Auth Admin
summary: Get specific auth user (admin)
operationId: getAuthUser
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
- name: userId
in: path
required: true
schema:
type: string
format: uuid
responses:
'200':
description: Auth user details
content:
application/json:
schema:
$ref: '#/components/schemas/AuthUser'
delete:
tags:
- Auth Admin
summary: Delete auth user (admin)
description: Soft-deletes user and revokes all sessions
operationId: deleteAuthUser
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
- name: userId
in: path
required: true
schema:
type: string
format: uuid
responses:
'204':
description: User deleted
/projects/{id}/auth/users/{userId}/sessions:
get:
tags:
- Auth Admin
summary: List user sessions
description: |
List paginated sessions for a specific auth user.
Returns session details including device info, IP address, and activity timestamps.
Ordering and pagination match `GET /auth/user/sessions`: the default is
activity order with `page`/`limit` and the legacy `sessions` body, and
`sort=created_at` opts into the standard cursor/offset hybrid with the
shared `data` envelope. Cursor pagination is only available for
`sort=created_at`, because the activity timestamp changes under paging.
The `status=expired` filter is offset-only because sessions can expire
above a cursor anchor during a walk.
operationId: listUserSessions
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
- name: userId
in: path
required: true
schema:
type: string
format: uuid
- name: page
in: query
description: Page number (1-indexed)
schema:
type: integer
minimum: 1
default: 1
- name: limit
in: query
description: Number of sessions per page (max 100)
schema:
type: integer
minimum: 1
maximum: 100
default: 20
- name: sort
in: query
description: |
Sort key. `last_activity` (default) orders by most recent activity and
supports offset pagination only. `created_at` orders by session start
and supports both offset and cursor pagination.
schema:
type: string
enum:
- last_activity
- created_at
default: last_activity
- name: status
in: query
description: |
Filter by whether the session can still be refreshed. Omit for every
stored session, including expired ones. `expired` is not supported
with cursor pagination.
schema:
type: string
enum:
- active
- expired
- name: cursor
in: query
description: |
Opaque keyset cursor from a previous response's `next_cursor`. Requires
`sort=created_at`; mutually exclusive with `page` and `ending_before`.
schema:
type: string
- name: ending_before
in: query
description: |
Opaque keyset cursor from a previous response's `prev_cursor`, paging
backward. Requires `sort=created_at`; mutually exclusive with `page`
and `cursor`.
schema:
type: string
- name: offset
in: query
description: |
Bounded number of rows to skip past the cursor anchor (the hybrid
jump, maximum 100000). Ignored unless `cursor` or `ending_before` is
supplied.
schema:
type: integer
minimum: 0
maximum: 100000
responses:
'200':
description: Paginated list of user sessions
content:
application/json:
schema:
type: object
properties:
sessions:
type: array
items:
$ref: '#/components/schemas/AuthSession'
total:
type: integer
description: Total number of sessions
page:
type: integer
description: Current page number
limit:
type: integer
description: Number of sessions per page
total_pages:
type: integer
description: Total number of pages
data:
type: array
description: Sessions for this page (cursor pagination only)
items:
$ref: '#/components/schemas/AuthSession'
has_more:
type: boolean
description: Whether a further page exists (cursor pagination only)
next_cursor:
type: string
description: Opaque cursor for the next page (cursor pagination only)
prev_cursor:
type: string
description: Opaque cursor for the previous page (cursor pagination only). Send as `ending_before`.
'400':
description: Invalid or conflicting pagination parameters
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: User not found
delete:
tags:
- Auth Admin
summary: Delete all user sessions
description: |
Revokes all sessions for a user, forcing them to re-authenticate on all devices.
Use this to log out a user from everywhere.
operationId: deleteAllUserSessions
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
- name: userId
in: path
required: true
schema:
type: string
format: uuid
responses:
'204':
description: All sessions deleted
'404':
description: User not found
/projects/{id}/auth/users/{userId}/sessions/{sessionId}:
delete:
tags:
- Auth Admin
summary: Delete specific session
description: |
Revokes a specific session for a user.
Use this to log out a user from a single device.
operationId: deleteUserSession
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
- name: userId
in: path
required: true
schema:
type: string
format: uuid
- name: sessionId
in: path
required: true
schema:
type: string
format: uuid
responses:
'204':
description: Session deleted
'404':
description: Session or user not found
/projects/{id}/auth/users/{userId}/ban:
post:
tags:
- Auth Admin
summary: Ban a user
description: |
Bans a user temporarily or permanently. Banned users cannot sign in
and all their active sessions are immediately revoked.
- Omit `banned_until` for a permanent ban
- Provide `banned_until` ISO timestamp for a temporary ban
operationId: banAuthUser
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
- name: userId
in: path
required: true
schema:
type: string
format: uuid
requestBody:
content:
application/json:
schema:
type: object
properties:
banned_until:
type: string
format: date-time
description: When the ban expires (omit for permanent ban)
example: '2026-12-31T23:59:59Z'
responses:
'200':
description: User banned successfully
content:
application/json:
schema:
$ref: '#/components/schemas/BanUserResponse'
'404':
description: User not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/projects/{id}/auth/users/{userId}/unban:
post:
tags:
- Auth Admin
summary: Unban a user
description: |
Removes a ban from a user, restoring their ability to sign in.
The user's status is set back to 'active'.
operationId: unbanAuthUser
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
- name: userId
in: path
required: true
schema:
type: string
format: uuid
responses:
'200':
description: User unbanned successfully
content:
application/json:
schema:
$ref: '#/components/schemas/UnbanUserResponse'
'404':
description: User not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/projects/{id}/email-templates:
get:
tags:
- Auth Configuration
summary: List email templates
description: Returns all custom email templates for this project.
operationId: listEmailTemplates
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
responses:
'200':
description: Email templates list
content:
application/json:
schema:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/EmailTemplate'
post:
tags:
- Auth Configuration
summary: Create email template
description: |
Creates a custom email template for the project. Custom email templates
are a SUPERAGENT-plan feature: requests from a HOBBY-plan project owner are
rejected with 403, and HOBBY projects always send the built-in default
templates regardless of any previously saved custom rows.
Every project is created with one template per type, so customizing one
is usually a PUT; creating a type the project already has returns 409.
Valid template types: welcome, confirmation, password_reset, password_changed
operationId: createEmailTemplate
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CreateEmailTemplateRequest'
responses:
'201':
description: Template created
content:
application/json:
schema:
$ref: '#/components/schemas/EmailTemplate'
'400':
description: Invalid template type
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'403':
description: Custom email templates require the SUPERAGENT plan
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'409':
description: The project already has a template of this type
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/projects/{id}/email-templates/{type}:
get:
tags:
- Auth Configuration
summary: Get email template
operationId: getEmailTemplate
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
- name: type
in: path
required: true
schema:
type: string
enum:
- welcome
- confirmation
- password_reset
- password_changed
responses:
'200':
description: Email template
content:
application/json:
schema:
$ref: '#/components/schemas/EmailTemplate'
'404':
description: Template not found
put:
tags:
- Auth Configuration
summary: Update email template
description: |
Updates a custom email template. Custom email templates are a SUPERAGENT-plan
feature: requests from a HOBBY-plan project owner are rejected with 403
(including after a SUPERAGENT→HOBBY downgrade), so a HOBBY project cannot modify
templates and always sends the built-in defaults.
operationId: updateEmailTemplate
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
- name: type
in: path
required: true
schema:
type: string
enum:
- welcome
- confirmation
- password_reset
- password_changed
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/UpdateEmailTemplateRequest'
responses:
'200':
description: Template updated
content:
application/json:
schema:
$ref: '#/components/schemas/EmailTemplate'
'403':
description: Custom email templates require the SUPERAGENT plan
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Template not found
delete:
tags:
- Auth Configuration
summary: Delete email template
description: |
Deletes a custom template, reverting to the default. Custom email
templates are a SUPERAGENT-plan feature: requests from a HOBBY-plan project owner
are rejected with 403.
operationId: deleteEmailTemplate
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
- name: type
in: path
required: true
schema:
type: string
enum:
- welcome
- confirmation
- password_reset
- password_changed
responses:
'204':
description: Template deleted
'403':
description: Custom email templates require the SUPERAGENT plan
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Template not found
/email-templates/defaults:
get:
tags:
- Auth Configuration
summary: Get default email templates
description: Returns the default email templates used when no custom template is configured.
operationId: getDefaultEmailTemplates
responses:
'200':
description: Default templates
content:
application/json:
schema:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/EmailTemplate'
/email-templates/defaults/{type}:
get:
tags:
- Auth Configuration
summary: Get default email template by type
operationId: getDefaultEmailTemplate
parameters:
- name: type
in: path
required: true
schema:
type: string
enum:
- welcome
- confirmation
- password_reset
- password_changed
responses:
'200':
description: Default template
content:
application/json:
schema:
$ref: '#/components/schemas/EmailTemplate'
'404':
description: Template type not found
/projects/{id}/auth/config:
get:
tags:
- Auth Configuration
summary: Get auth configuration
operationId: getAuthConfig
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
responses:
'200':
description: Auth configuration
content:
application/json:
schema:
$ref: '#/components/schemas/AuthConfig'
put:
tags:
- Auth Configuration
summary: Update auth configuration
description: |
Updates the project's auth configuration. Only the fields present in
the body are changed.
operationId: updateAuthConfig
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/UpdateAuthConfigRequest'
responses:
'200':
description: Configuration updated
content:
application/json:
schema:
$ref: '#/components/schemas/AuthConfig'
'403':
description: |
The update would turn on, widen, or otherwise edit the email domain
allowlist (`allowed_email_domains`, `allowed_email_domains_mode`)
for a project that is not on the SUPERAGENT plan. A HOBBY project keeps
whatever allowlist it already has — parked, enforcing nothing until
it upgrades — and may still remove it, so a downgrade never leaves a
project locked out of its own signups.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/projects/{id}/auth/config/test-email:
post:
tags:
- Auth Configuration
summary: Send a test email using the project's saved SMTP config
description: |
Sends a diagnostic email to `to_email` using the project's
persisted `auth_config` SMTP credentials. If `html_body` or
`text_body` is supplied, the override path is taken: those
values (plus optional `subject`) are rendered through
html/text templates against the project's `Data` and
used as the body — used by the template editor's "Send Test"
affordance to preview an unsaved template. With both bodies
omitted, a hardcoded diagnostic message is sent and any
`subject` field is ignored. Sending `subject` alone (no
bodies) is rejected with 400 to avoid a silently-dropped
subject or a blank message. Also rejects with 400 if
`email_enabled=false` or `smtp_host` is empty.
operationId: testEmailConfig
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/TestEmailRequest'
responses:
'200':
description: Test email sent
content:
application/json:
schema:
$ref: '#/components/schemas/TestEmailResponse'
'400':
description: Invalid request or email delivery not configured
'401':
description: Unauthorized
'403':
description: Forbidden
'404':
description: Project not found
'502':
description: Template render failure or SMTP delivery failed
/projects/{id}/auth/hosted-pages/{pageType}:
get:
tags:
- Auth Configuration
summary: Get hosted auth page
description: |
Returns the saved HTML/CSS for the page type, or `page: null` when the
project has not customized it yet. Always returns `defaults` (the theme
shell to seed an editor with, which is valid input to the update endpoint)
and `runtime` (the script the rendered page runs, plus a preview harness).
operationId: getAuthHostedPage
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
- name: pageType
in: path
required: true
schema:
$ref: '#/components/schemas/HostedAuthPageType'
responses:
'200':
description: Hosted page loaded
content:
application/json:
schema:
$ref: '#/components/schemas/AuthHostedPageResponse'
put:
tags:
- Auth Configuration
summary: Update hosted auth page
description: |
Saves the current HTML/CSS for this page type.
Security validation rejects script tags, javascript: URLs, inline event handlers, iframe/object/embed/meta/link tags in HTML,
and closing style/head tags in CSS.
operationId: updateAuthHostedPage
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
- name: pageType
in: path
required: true
schema:
$ref: '#/components/schemas/HostedAuthPageType'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/UpdateAuthHostedPageRequest'
responses:
'200':
description: Hosted page updated
content:
application/json:
schema:
$ref: '#/components/schemas/AuthHostedPageResponse'
'400':
description: Invalid input or unsafe markup
'401':
description: Unauthorized
'403':
description: Forbidden
'404':
description: Project not found
/projects/{id}/auth/pages/appearance:
get:
tags:
- Auth Configuration
summary: Get managed auth page appearance
operationId: getAuthPageAppearance
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
responses:
'200':
description: Saved appearance and effective plan state
content:
application/json:
schema:
$ref: '#/components/schemas/AuthPageAppearanceResponse'
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'403':
description: Access denied
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Project not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Appearance could not be read
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/projects/{id}/auth/pages/theme:
put:
tags:
- Auth Configuration
summary: Save the managed auth page theme
operationId: updateAuthPageTheme
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/UpdateAuthPageThemeRequest'
responses:
'200':
description: Theme saved
content:
application/json:
schema:
$ref: '#/components/schemas/UpdateAuthPageThemeRequest'
'400':
description: Invalid or unreadable theme
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'403':
description: Plan does not permit customisation
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Project not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Theme could not be saved
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
delete:
tags:
- Auth Configuration
summary: Clear the managed auth page theme
operationId: deleteAuthPageTheme
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
responses:
'204':
description: Theme cleared
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'403':
description: Plan does not permit customisation
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Project not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Theme could not be cleared
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/projects/{id}/auth/pages/{pageType}/layout:
parameters:
- $ref: '#/components/parameters/ProjectId'
- name: pageType
in: path
required: true
schema:
$ref: '#/components/schemas/HostedAuthPageType'
put:
tags:
- Auth Configuration
summary: Save one managed auth page layout
operationId: updateAuthPageLayout
security:
- UserToken: []
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/UpdateAuthPageLayoutRequest'
responses:
'200':
description: Layout saved
content:
application/json:
schema:
$ref: '#/components/schemas/UpdateAuthPageLayoutRequest'
'400':
description: Invalid page type or layout
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'403':
description: Plan does not permit customisation
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Project not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Layout could not be saved
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
delete:
tags:
- Auth Configuration
summary: Clear one managed auth page layout
operationId: deleteAuthPageLayout
security:
- UserToken: []
responses:
'204':
description: Layout cleared
'400':
description: Invalid page type
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'403':
description: Plan does not permit customisation
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Project not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Layout could not be cleared
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/projects/{id}/auth/pages/{pageType}/preview:
get:
tags:
- Auth Configuration
summary: Render a short-lived managed auth page preview
description: |
Public HTML endpoint for a preview URL returned by the POST operation.
The signed ticket contains the unsaved appearance, expires shortly, and
runs the production page runtime against mocked authentication responses.
operationId: renderAuthPagePreview
security: []
parameters:
- $ref: '#/components/parameters/ProjectId'
- name: pageType
in: path
required: true
schema:
$ref: '#/components/schemas/HostedAuthPageType'
- name: ticket
in: query
required: true
schema:
type: string
minLength: 1
maxLength: 4096
description: Short-lived signed preview ticket returned by the POST operation.
responses:
'200':
description: Rendered preview document
content:
text/html:
schema:
type: string
'404':
description: Ticket is invalid or expired, its path does not match, or managed authentication is disabled
content:
text/plain:
schema:
type: string
'500':
description: Preview could not be rendered
content:
text/plain:
schema:
type: string
post:
tags:
- Auth Configuration
summary: Preview an unsaved managed auth page appearance
operationId: previewAuthPage
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
- name: pageType
in: path
required: true
schema:
$ref: '#/components/schemas/HostedAuthPageType'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/PreviewAuthPageRequest'
responses:
'200':
description: Short-lived URL for the rendered preview document
content:
application/json:
schema:
$ref: '#/components/schemas/PreviewAuthPageResponse'
'400':
description: Invalid page type or draft
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'403':
description: Access denied
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Project not found or managed authentication is disabled
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Preview could not be rendered
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/projects/{id}/auth/hosted/{pageType}:
get:
tags:
- Auth Configuration
summary: Render a managed auth page
description: |
Public HTML endpoint for signup, forgot-password, device approval,
verify-email, and reset-password pages. Login uses the path without a
page type.
Requires `Accept: text/html`.
Returns 404 when managed hosted pages are disabled for the project.
security: []
operationId: renderManagedAuthPage
parameters:
- $ref: '#/components/parameters/ProjectId'
- name: pageType
in: path
required: true
schema:
$ref: '#/components/schemas/HostedRenderablePageType'
responses:
'200':
description: Hosted auth page HTML
content:
text/html:
schema:
type: string
'400':
description: Invalid project id or unsupported Accept header
'404':
description: Managed pages disabled or page type not found
/projects/{id}/auth/hosted:
get:
tags:
- Auth Configuration
summary: Render default managed auth page
description: |
Public HTML endpoint for the managed login page.
Requires `Accept: text/html`.
security: []
operationId: renderDefaultManagedAuthPage
parameters:
- $ref: '#/components/parameters/ProjectId'
- name: action
in: query
required: false
schema:
type: string
enum:
- login
- signup
- forgot-password
- device
description: |
Optional deep-link action for the unified hosted page. Ignored when a
custom login page is configured. `action=device` renders the device
authorization approval UI inline (no redirect to any external app);
it signs the user in and calls `POST /auth/device/verify`.
- name: user_code
in: query
required: false
schema:
type: string
description: Device user code (from `POST /auth/device/authorize`) used with `action=device`.
- name: anon_key
in: query
required: false
schema:
type: string
description: Project anon key used by built-in managed auth flows (required for login/signup/device actions).
- name: state
in: query
required: false
schema:
type: string
description: |
Opaque one-time nonce generated by the client SDK before redirecting
here. On successful login/signup it is echoed back in the post-auth
redirect fragment as `state`, so the SDK can bind the returned session
to the flow it initiated (login-CSRF / session-fixation defense). The
SDK rejects a returned session whose `state` does not match.
responses:
'200':
description: Hosted auth page HTML
content:
text/html:
schema:
type: string
'400':
description: Invalid project id or unsupported Accept header
'404':
description: Managed pages disabled
/projects/{id}/auth/hosted/login/options:
get:
tags:
- Auth Configuration
summary: Get hosted login runtime options
description: |
Returns runtime options for the built-in managed login flow.
Requires `anon_key` query parameter.
Rate limited per project and client IP. Excess requests return `429` and `Retry-After`.
security: []
operationId: getHostedLoginOptions
parameters:
- $ref: '#/components/parameters/ProjectId'
- name: anon_key
in: query
required: true
schema:
type: string
responses:
'200':
description: Hosted login options returned
content:
application/json:
schema:
$ref: '#/components/schemas/HostedLoginOptionsResponse'
'401':
description: Invalid or missing anon key
'404':
description: Managed pages disabled
'429':
description: Rate limit exceeded
/projects/{id}/auth/hosted/login/check-email:
post:
tags:
- Auth Configuration
summary: Check whether email exists for hosted login flow
description: |
Used by the built-in managed login page to branch UI between signin and signup.
Requires anon key in Authorization header.
Rate limited per project and client IP. Excess requests return `429` and `Retry-After`.
security: []
operationId: hostedLoginCheckEmail
parameters:
- $ref: '#/components/parameters/ProjectId'
- name: Authorization
in: header
required: true
schema:
type: string
description: Bearer anon key (`Bearer `)
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/HostedLoginEmailCheckRequest'
responses:
'200':
description: Email existence evaluated
content:
application/json:
schema:
$ref: '#/components/schemas/HostedLoginEmailCheckResponse'
'401':
description: Invalid or missing anon key
'429':
description: Rate limit exceeded
/projects/{id}/auth/methods:
get:
tags:
- Auth Configuration
summary: Get all authentication methods
description: |
Returns all configured authentication methods for this project,
including email/password, anonymous, device authorization, and OAuth providers.
operationId: getAuthMethods
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
responses:
'200':
description: Authentication methods configuration
content:
application/json:
schema:
type: object
properties:
email_password:
type: object
properties:
enabled:
type: boolean
method:
type: string
name:
type: string
anonymous:
type: object
properties:
enabled:
type: boolean
method:
type: string
name:
type: string
oauth_providers:
type: array
items:
type: object
properties:
enabled:
type: boolean
method:
type: string
provider:
type: string
name:
type: string
redirect_url:
type: string
scopes:
type: array
items:
type: string
available_methods:
type: array
items:
type: string
example:
- email_password
- oauth_google
- oauth_github
put:
tags:
- Auth Configuration
summary: Configure authentication methods (unified)
description: |
Configure all authentication methods in a single request.
At least one method must remain enabled.
operationId: configureAuthMethods
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
requestBody:
content:
application/json:
schema:
type: object
properties:
enable_email_password:
type: boolean
enable_anonymous:
type: boolean
oauth_providers:
type: array
items:
type: object
properties:
provider:
type: string
enabled:
type: boolean
responses:
'200':
description: Methods configured
'400':
description: At least one method must be enabled
/projects/{id}/oauth/configs:
get:
tags:
- OAuth Configuration
summary: List OAuth configurations
description: List all OAuth provider configurations for this project
operationId: listOAuthConfigs
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
responses:
'200':
description: List of OAuth configurations
content:
application/json:
schema:
type: object
properties:
configs:
type: array
items:
$ref: '#/components/schemas/OAuthConfig'
post:
tags:
- OAuth Configuration
summary: Create OAuth configuration
description: Configure OAuth provider (Google, GitHub, Microsoft, Apple, Device)
operationId: createOAuthConfig
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CreateOAuthConfigRequest'
responses:
'201':
description: OAuth config created
content:
application/json:
schema:
$ref: '#/components/schemas/OAuthConfig'
'409':
description: Provider already configured
/projects/{id}/oauth/configs/{provider}:
get:
tags:
- OAuth Configuration
summary: Get OAuth configuration
operationId: getOAuthConfig
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
- name: provider
in: path
required: true
schema:
type: string
enum:
- google
- github
- microsoft
- apple
- device
- name: client_id
in: query
required: false
schema:
type: string
description: Required when `provider=device` to select a specific device client.
responses:
'200':
description: OAuth configuration
content:
application/json:
schema:
$ref: '#/components/schemas/OAuthConfig'
put:
tags:
- OAuth Configuration
summary: Update OAuth configuration
operationId: updateOAuthConfig
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
- name: provider
in: path
required: true
schema:
type: string
enum:
- google
- github
- microsoft
- apple
- device
- name: client_id
in: query
required: false
schema:
type: string
description: Required when `provider=device` to select a specific device client.
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/UpdateOAuthConfigRequest'
responses:
'200':
description: OAuth config updated
content:
application/json:
schema:
$ref: '#/components/schemas/OAuthConfig'
delete:
tags:
- OAuth Configuration
summary: Delete OAuth configuration
operationId: deleteOAuthConfig
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
- name: provider
in: path
required: true
schema:
type: string
enum:
- google
- github
- microsoft
- apple
- device
- name: client_id
in: query
required: false
schema:
type: string
description: Required when `provider=device` to select a specific device client.
responses:
'204':
description: OAuth config deleted
/projects/{id}/oauth/providers:
get:
tags:
- OAuth Configuration
summary: List available OAuth providers
description: Get list of supported OAuth providers and their default scopes
operationId: listAvailableOAuthProviders
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
responses:
'200':
description: Available providers
content:
application/json:
schema:
type: object
properties:
providers:
type: array
items:
type: object
properties:
id:
type: string
name:
type: string
default_scopes:
type: array
items:
type: string
/auth/oauth/{provider}/authorize:
get:
tags:
- OAuth Authentication
summary: Start OAuth authorization
description: |
Redirects user to OAuth provider for authorization.
Handles CSRF protection with state parameter.
Project is identified via the anon_key query parameter.
operationId: authOAuthAuthorize
parameters:
- name: provider
in: path
required: true
schema:
type: string
enum:
- google
- github
- microsoft
- apple
- name: anon_key
in: query
required: true
schema:
type: string
description: Project anon key (required - identifies the project)
- name: redirect_url
in: query
schema:
type: string
description: |
URL to redirect to after the OAuth flow (optional). Must exactly
match an entry in the project's `allowed_redirect_urls`, including
its query string, or be the project's own managed hosted-auth page
URL.
- name: client_state
in: query
schema:
type: string
maxLength: 255
description: |
Optional application nonce. It is stored with the server-generated
provider state and echoed to redirect_url as `state`.
- name: response_mode
in: query
schema:
type: string
enum:
- code
description: |
Set to `code` to receive a short-lived authorization code at
redirect_url, then use POST /auth/oauth/exchange to obtain the
session. `redirect_url` is required in this mode. When omitted, the
established session-fragment response is retained for compatibility
with existing clients.
responses:
'307':
description: Redirect to OAuth provider
'400':
description: |
OAuth provider is disabled for this project, or `redirect_url` is
not registered in `allowed_redirect_urls`
'404':
description: OAuth provider not configured
/auth/oauth/{provider}/callback:
get:
tags:
- OAuth Authentication
summary: OAuth callback handler
description: |
Handles OAuth provider callback with authorization code.
Exchanges code for tokens and creates/signs in user.
operationId: authOAuthCallback
parameters:
- name: provider
in: path
required: true
schema:
type: string
enum:
- google
- github
- microsoft
- apple
- name: code
in: query
required: true
schema:
type: string
- name: state
in: query
required: true
schema:
type: string
- name: error
in: query
schema:
type: string
responses:
'200':
description: Existing user signed in (when redirect_url was omitted)
content:
application/json:
schema:
$ref: '#/components/schemas/AuthTokenResponse'
'201':
description: New user created and signed in (when redirect_url was omitted)
content:
application/json:
schema:
$ref: '#/components/schemas/AuthTokenResponse'
'303':
description: |
Redirect to the exact registered redirect_url. Flows that requested
response_mode=code receive a short-lived, single-use `code` and
optional application `state`; compatibility flows receive the
established session fragment.
'400':
description: |
Missing/invalid code or state, the state parameter expired, or the
flow's stored redirect_url is no longer registered in
allowed_redirect_urls (re-checked at callback time)
'403':
description: |
The provider's email domain is not in `allowed_email_domains`. Creating
an account is refused under `signup` and `signup_and_signin`; signing in
an already-linked account is refused under `signup_and_signin`.
'409':
description: Email already exists (requires linking)
/auth/oauth/exchange:
post:
tags:
- OAuth Authentication
summary: Exchange OAuth authorization code
description: |
Atomically consumes a short-lived callback code and returns the user's
session. The request must use the same project anon key and exact
redirect_url that initiated the flow.
operationId: authOAuthExchange
security:
- AnonKey: []
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- code
- redirect_url
properties:
code:
type: string
redirect_url:
type: string
format: uri
responses:
'200':
description: Authorization code consumed and session created
content:
application/json:
schema:
$ref: '#/components/schemas/AuthTokenResponse'
'400':
description: Invalid, expired, consumed, or redirect-mismatched code
'401':
description: Missing or invalid project anon key
'403':
description: |
Email confirmation is now required, or the account's email domain is not
in `allowed_email_domains` while `allowed_email_domains_mode` is
`signup_and_signin`. Both are re-checked here because the code outlives
the callback that issued it.
'429':
description: Too many exchange attempts from this client
/auth/device/authorize:
post:
tags:
- OAuth Authentication
summary: Start RFC8628 device authorization
description: |
Starts OAuth 2.0 Device Authorization Grant (RFC 8628).
Returns `device_code` for the CLI and `user_code` for browser verification.
By default the returned `verification_uri` / `verification_uri_complete`
point at the project's managed device-approval page served by this API
(`/projects/{projectId}/auth/hosted?action=device&user_code=...&anon_key=...`),
which requires managed auth enabled and a default anon key for the
project.
Projects can override this by setting `device_verification_url` on the
auth config (`PATCH /auth/config`). When set, that URL is returned as-is
with the `user_code` appended (no `action=device` hint and no embedded
anon key — the page brings its own), so a CLI's `login` command surfaces
the project's own RFC 8628 approval page. With a custom URL, device login
does **not** require managed auth to be enabled; the custom page's origin
must be in the project's auth CORS allowlist to call
`POST /auth/device/verify`. Either way the verification page must
authenticate the end user and call `POST /auth/device/verify` with the
`user_code`. See the device-auth guide for both approaches.
operationId: authDeviceAuthorize
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- client_id
properties:
client_id:
type: string
description: Enabled `device` OAuth client ID for the target project
responses:
'200':
description: Device authorization started
content:
application/json:
schema:
$ref: '#/components/schemas/DeviceAuthorizationResponse'
'400':
description: Invalid request or unauthorized client
content:
application/json:
schema:
$ref: '#/components/schemas/OAuthErrorResponse'
/auth/device/token:
post:
tags:
- OAuth Authentication
summary: Poll device token endpoint
description: |
RFC8628 token polling endpoint.
Returns OAuth errors such as `authorization_pending`, `slow_down`, `access_denied`, and `expired_token`.
operationId: authDeviceToken
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- grant_type
- device_code
- client_id
properties:
grant_type:
type: string
enum:
- urn:ietf:params:oauth:grant-type:device_code
device_code:
type: string
client_id:
type: string
responses:
'200':
description: Device flow completed, auth-user session minted
content:
application/json:
schema:
$ref: '#/components/schemas/AuthTokenResponse'
'400':
description: Polling state/error response
content:
application/json:
schema:
$ref: '#/components/schemas/OAuthErrorResponse'
'403':
description: |
`access_denied` - the approving account's email domain is not in
`allowed_email_domains` while `allowed_email_domains_mode` is
`signup_and_signin`. Re-checked here because approval and redemption
are separate requests.
content:
application/json:
schema:
$ref: '#/components/schemas/OAuthErrorResponse'
/auth/device/verify:
post:
tags:
- OAuth Authentication
summary: Approve or deny a device code
description: |
Browser-side endpoint for authenticated auth-users to approve (`approve`) or deny (`deny`) a `user_code`.
Called by the verification page after the end user signs in. The grant is
scoped to the project the auth-user token belongs to: approving a
`user_code` issued for a different project returns `403`. This endpoint
does not require managed auth to be enabled, so a custom verification page
(hosted anywhere) can drive approval — it just needs an authenticated
project auth-user access token and, for cross-origin browser calls, the
page origin allowed in the project's auth CORS settings.
operationId: authDeviceVerify
security:
- AuthUserAccessToken: []
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- user_code
properties:
user_code:
type: string
action:
type: string
enum:
- approve
- deny
default: approve
responses:
'200':
description: Verification action accepted
content:
application/json:
schema:
type: object
properties:
success:
type: boolean
status:
type: string
'401':
description: Not authenticated
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/auth/platform/exchange:
post:
tags:
- OAuth Authentication
summary: Exchange auth-user device session for platform token
description: |
Exchanges a verified auth-user device-flow session into a platform token for CLI usage.
The target platform user is derived from authenticated auth-user mapping; client cannot select another user.
operationId: authPlatformExchange
security:
- AuthUserAccessToken: []
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- client_id
properties:
client_id:
type: string
responses:
'200':
description: Platform token minted
content:
application/json:
schema:
$ref: '#/components/schemas/PlatformExchangeResponse'
'403':
description: |
Exchange not allowed for this session/client/project, or the
account's email domain is not in `allowed_email_domains` while
`allowed_email_domains_mode` is `signup_and_signin`. The domain is
re-checked here because the minted platform token outlives the
session it is exchanged from.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/auth/oauth/providers:
get:
tags:
- OAuth Authentication
summary: List user's linked providers
description: Get list of OAuth providers linked to current user
operationId: authListOAuthProviders
security:
- AuthUserAccessToken: []
responses:
'200':
description: Linked providers
content:
application/json:
schema:
type: object
properties:
providers:
type: array
items:
type: object
properties:
provider:
type: string
linked_at:
type: string
format: date-time
updated_at:
type: string
format: date-time
'401':
description: Not authenticated
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/auth/oauth/{provider}/link:
post:
tags:
- OAuth Authentication
summary: Link OAuth provider to current user
description: |
Generates authorization URL to link OAuth provider to existing account.
User must be authenticated.
operationId: authLinkOAuthProvider
security:
- AuthUserAccessToken: []
parameters:
- name: provider
in: path
required: true
schema:
type: string
enum:
- google
- github
- microsoft
- apple
- name: redirect_url
in: query
schema:
type: string
description: |
URL to redirect to after linking completes (optional). Same
allowed_redirect_urls requirement as GET /auth/oauth/{provider}/authorize.
- name: client_state
in: query
schema:
type: string
maxLength: 255
description: |
Optional application nonce echoed to redirect_url as `state`.
- name: response_mode
in: query
schema:
type: string
enum:
- code
description: |
Set to `code` to receive a short-lived authorization code at
redirect_url. `redirect_url` is required in this mode. When
omitted, the established session-fragment response is retained for
compatibility with existing clients.
responses:
'200':
description: Authorization URL generated
content:
application/json:
schema:
type: object
properties:
authorization_url:
type: string
'400':
description: redirect_url is not registered in allowed_redirect_urls
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Not authenticated
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: OAuth provider not configured
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'409':
description: Provider already linked
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/auth/oauth/{provider}/unlink:
delete:
tags:
- OAuth Authentication
summary: Unlink OAuth provider
description: |
Remove OAuth provider from user's account.
Cannot unlink if it's the only authentication method.
operationId: authUnlinkOAuthProvider
security:
- AuthUserAccessToken: []
parameters:
- name: provider
in: path
required: true
schema:
type: string
enum:
- google
- github
- microsoft
- apple
responses:
'204':
description: Provider unlinked
'400':
description: Cannot unlink last authentication method
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Not authenticated
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Provider not linked
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/auth/oauth/{provider}/refresh-token:
post:
tags:
- OAuth Authentication
summary: Refresh OAuth provider token
description: |
Refresh the access token for an OAuth provider using its refresh token.
Allows calling provider APIs on user's behalf (e.g., Google Drive, GitHub repos).
operationId: refreshOAuthProviderToken
security:
- AuthUserAccessToken: []
parameters:
- name: provider
in: path
required: true
schema:
type: string
enum:
- google
- github
- microsoft
- apple
responses:
'200':
description: Token refreshed successfully
content:
application/json:
schema:
type: object
properties:
message:
type: string
provider:
type: string
expires_in:
type: integer
'400':
description: No refresh token available or refresh failed
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Not authenticated
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Provider not linked
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/auth/oauth/{provider}/token:
get:
tags:
- OAuth Authentication
summary: Get current provider access token
description: |
Get valid access token for OAuth provider.
Automatically refreshes if expired.
operationId: getOAuthProviderToken
security:
- AuthUserAccessToken: []
parameters:
- name: provider
in: path
required: true
schema:
type: string
enum:
- google
- github
- microsoft
- apple
responses:
'200':
description: Current access token
content:
application/json:
schema:
type: object
properties:
message:
type: string
provider:
type: string
expires_in:
type: integer
'401':
description: Not authenticated
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Provider not linked
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/auth/oauth/{provider}/call-api:
post:
tags:
- OAuth Authentication
summary: Call OAuth provider API
description: |
Make an authenticated request to an OAuth provider's API on behalf of the user.
The user's stored access token is automatically used and refreshed if needed.
The request is always sent to the provider's fixed API base URL joined with
the caller-supplied `endpoint`. `endpoint` must be a relative path beginning
with `/` (optionally with a query string); it cannot change the target host.
Absolute URLs, protocol-relative `//host` values, or userinfo (`@host`) are
rejected with `400` so the request can never be redirected to another host.
Examples of `endpoint`:
- Google userinfo: `/oauth2/v1/userinfo`
- GitHub repositories: `/user/repos`
- Microsoft Graph profile: `/me`
The response wraps the provider's raw JSON value with request metadata.
An empty provider body is represented as `data: null`; the envelope
preserves the provider's HTTP status in `status_code`, including errors.
Provider response bodies are limited to 8 MiB after decompression.
Transport failures, invalid JSON (including invalid UTF-8), and oversized
bodies return `502`. Provider redirects to another origin are blocked and
return `400`.
operationId: callOAuthProviderAPI
security:
- AuthUserAccessToken: []
parameters:
- name: provider
in: path
required: true
schema:
type: string
enum:
- google
- github
- microsoft
- apple
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- endpoint
properties:
endpoint:
type: string
description: |
Relative path on the provider's API, beginning with `/`. It is
joined with the provider's fixed base URL; it must not contain a
scheme, host, userinfo, or a leading `//`.
example: /user/repos
method:
type: string
enum:
- GET
- POST
default: GET
description: HTTP method to use
body:
type: object
additionalProperties: true
description: Request body for POST requests
responses:
'200':
description: Provider API response
content:
application/json:
schema:
type: object
description: OAuth provider API response envelope
required:
- provider
- endpoint
- status_code
- data
properties:
provider:
type: string
enum:
- google
- github
- microsoft
- apple
endpoint:
type: string
status_code:
type: integer
minimum: 100
maximum: 599
data:
description: Raw provider JSON value, or null when the provider returns no body
nullable: true
'400':
description: |
Invalid request (for example: missing `endpoint`, an `endpoint` that is
not a relative path, or an unsupported HTTP method), or a provider
redirect to another origin.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Not authenticated
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: OAuth provider configuration not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Failed to create the provider API request
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'502':
description: Provider transport failure, invalid JSON, or response body larger than 8 MiB
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/projects/{id}/anon-keys:
get:
tags:
- Anon Keys
summary: List anon keys
description: |
Supports two mutually exclusive pagination modes. Offset mode uses `page`
and `limit` and is the default when neither `cursor` nor `search` is
supplied (first page, default `limit`). Cursor mode uses `cursor` and
`limit`, supports `search` (case-insensitive name match), and returns
`next_cursor`. Sending both `page` and `cursor` (or `page` and `search`)
returns 400.
operationId: listAnonKeys
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
- $ref: '#/components/parameters/Page'
- $ref: '#/components/parameters/Limit'
- $ref: '#/components/parameters/Cursor'
- $ref: '#/components/parameters/EndingBefore'
- $ref: '#/components/parameters/Offset'
- $ref: '#/components/parameters/Search'
responses:
'200':
description: List of anon keys
content:
application/json:
schema:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/AnonKey'
total:
type: integer
description: Total number of items matching the query (so the UI can render numbered pages).
has_more:
type: boolean
description: Whether a next page exists.
next_cursor:
type: string
description: Opaque cursor for the next page (cursor pagination only)
prev_cursor:
type: string
description: Opaque cursor for the previous page (cursor pagination only). Send as `ending_before`.
post:
tags:
- Anon Keys
summary: Create anon key
operationId: createAnonKey
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- name
properties:
name:
type: string
description: |
Key name for identification.
Can only contain letters, numbers, underscores, and hyphens.
pattern: ^[A-Za-z0-9_-]+$
minLength: 1
maxLength: 255
example: frontend-app
permissions:
type: array
items:
type: string
enum:
- auth.signup
- auth.signin
- auth.refresh
- auth.logout
- auth.password_reset
- auth.confirm_email
- auth.resend_confirmation
- storage.upload
- storage.download
- storage.list
- storage.delete
- realtime.connect
- realtime.subscribe
- realtime.publish
- functions.invoke
description: |
Optional list of permissions for this key.
If not provided, defaults to auth-only permissions: auth.signup, auth.signin, auth.refresh, auth.logout, auth.password_reset, auth.confirm_email, auth.resend_confirmation.
Storage, realtime, and functions permissions must be explicitly added if needed.
example:
- auth.signup
- auth.signin
- auth.refresh
- auth.logout
responses:
'201':
description: Anon key created
content:
application/json:
schema:
$ref: '#/components/schemas/AnonKey'
/projects/{id}/anon-keys/{keyId}:
get:
tags:
- Anon Keys
summary: Get anon key
description: Get details of a specific anon key
operationId: getAnonKey
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
- name: keyId
in: path
required: true
schema:
type: string
format: uuid
responses:
'200':
description: Anon key details
content:
application/json:
schema:
$ref: '#/components/schemas/AnonKey'
'404':
description: Key not found
delete:
tags:
- Anon Keys
summary: Revoke anon key
description: Revokes key - it will immediately stop working
operationId: revokeAnonKey
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
- name: keyId
in: path
required: true
schema:
type: string
format: uuid
responses:
'204':
description: Key revoked
'401':
description: Unauthorized
'403':
description: Forbidden
'404':
description: Key not found
'409':
description: Cannot delete the project's default anon key
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Internal server error
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/projects/{id}/anon-keys/{keyId}/regenerate:
post:
tags:
- Anon Keys
summary: Regenerate anon key
description: Generate new JWT value for existing key
operationId: regenerateAnonKey
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
- name: keyId
in: path
required: true
schema:
type: string
format: uuid
responses:
'200':
description: Key regenerated
content:
application/json:
schema:
$ref: '#/components/schemas/AnonKey'
/projects/{id}/anon-keys/{keyId}/set-default:
post:
tags:
- Anon Keys
summary: Set default anon key
description: Promotes the given key to the project's configured default. At most one key per project can be default.
operationId: setDefaultAnonKey
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
- name: keyId
in: path
required: true
schema:
type: string
format: uuid
responses:
'200':
description: Key set as default
content:
application/json:
schema:
$ref: '#/components/schemas/AnonKey'
'401':
description: Unauthorized
'403':
description: Forbidden
'404':
description: Anon key not found
'500':
description: Internal server error
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/projects/{id}/service-keys:
get:
tags:
- Service Keys
summary: List service keys (paginated)
description: |
List all service role keys for a project with pagination.
**WARNING:** Service keys bypass RLS - for backend/admin use only!
operationId: listServiceKeys
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
- $ref: '#/components/parameters/Page'
- $ref: '#/components/parameters/Limit'
- $ref: '#/components/parameters/Cursor'
- $ref: '#/components/parameters/EndingBefore'
- $ref: '#/components/parameters/Offset'
- $ref: '#/components/parameters/Search'
responses:
'200':
description: Paginated list of service keys
content:
application/json:
schema:
$ref: '#/components/schemas/PaginatedServiceKeys'
post:
tags:
- Service Keys
summary: Create service key
description: |
Create a new service role key for admin operations.
**WARNING:** Service keys bypass all RLS policies!
Store securely and NEVER expose in frontend code.
operationId: createServiceKey
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- name
properties:
name:
type: string
description: |
Descriptive name for the key (e.g., "admin-dashboard", "background-jobs").
Can only contain letters, numbers, underscores, and hyphens.
pattern: ^[A-Za-z0-9_-]+$
minLength: 1
maxLength: 255
example: admin-dashboard
permissions:
type: array
items:
type: string
description: |
Optional least-privilege scope for the key. When omitted, empty, or
containing only blank strings, the key is granted full access (["*"])
for backward compatibility. Provide an explicit list (e.g.
["functions.invoke", "locks.manage"]) to restrict the key; "*"
grants everything. Scope enforcement applies to function invocation,
storage object operations, and project locks.
example:
- functions.invoke
- locks.manage
responses:
'201':
description: Service key created - save the key_value immediately!
content:
application/json:
schema:
$ref: '#/components/schemas/ServiceKey'
'409':
description: Key with this name already exists
/projects/{id}/service-keys/{keyId}:
get:
tags:
- Service Keys
summary: Get service key
description: Get details of a specific service key
operationId: getServiceKey
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
- name: keyId
in: path
required: true
schema:
type: string
format: uuid
responses:
'200':
description: Service key details
content:
application/json:
schema:
$ref: '#/components/schemas/ServiceKey'
'404':
description: Key not found
delete:
tags:
- Service Keys
summary: Delete service key
description: |
Permanently delete a service key.
Any services using this key will immediately lose access.
operationId: deleteServiceKey
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
- name: keyId
in: path
required: true
schema:
type: string
format: uuid
responses:
'204':
description: Key deleted
/projects/{id}/service-keys/{keyId}/regenerate:
post:
tags:
- Service Keys
summary: Regenerate service key
description: |
Generate new JWT value for existing key.
The old key is immediately invalidated.
Update your backend services with the new key before regenerating in production.
operationId: regenerateServiceKey
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
- name: keyId
in: path
required: true
schema:
type: string
format: uuid
responses:
'200':
description: Key regenerated - save the new key_value immediately!
content:
application/json:
schema:
$ref: '#/components/schemas/ServiceKey'
/projects/{id}/storage/buckets:
get:
tags:
- Storage Buckets
summary: List all storage buckets in a project
description: |
With no pagination params, returns the full bucket list as a bare array
(legacy). Supplying `cursor`, `ending_before`, `search`, or `limit`
switches to keyset (cursor) pagination and returns a paginated envelope
with `next_cursor`/`prev_cursor` and a filtered `total`.
operationId: listStorageBuckets
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
- $ref: '#/components/parameters/Limit'
- $ref: '#/components/parameters/Cursor'
- $ref: '#/components/parameters/EndingBefore'
- $ref: '#/components/parameters/Offset'
- $ref: '#/components/parameters/Search'
responses:
'200':
description: |
Either the full bucket list (bare array, legacy) or a paginated
envelope when cursor pagination is requested.
content:
application/json:
schema:
oneOf:
- type: array
items:
$ref: '#/components/schemas/StorageBucket'
- $ref: '#/components/schemas/PaginatedStorageBuckets'
post:
tags:
- Storage Buckets
summary: Create a new storage bucket
operationId: createStorageBucket
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CreateStorageBucketRequest'
responses:
'201':
description: Bucket created
content:
application/json:
schema:
$ref: '#/components/schemas/StorageBucket'
'409':
description: Bucket already exists
/projects/{id}/storage/buckets/{bucketName}:
get:
tags:
- Storage Buckets
summary: Get storage bucket by name
operationId: getStorageBucket
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
- $ref: '#/components/parameters/BucketName'
responses:
'200':
description: Bucket details
content:
application/json:
schema:
$ref: '#/components/schemas/StorageBucket'
'404':
description: Bucket not found
patch:
tags:
- Storage Buckets
summary: Update storage bucket settings
operationId: updateStorageBucket
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
- $ref: '#/components/parameters/BucketName'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/UpdateStorageBucketRequest'
responses:
'200':
description: Bucket updated
content:
application/json:
schema:
$ref: '#/components/schemas/StorageBucket'
delete:
tags:
- Storage Buckets
summary: Delete storage bucket and all objects
operationId: deleteStorageBucket
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
- $ref: '#/components/parameters/BucketName'
responses:
'200':
description: Bucket deleted
/projects/{id}/storage/buckets/{bucketName}/policies:
get:
tags:
- Storage Policies
summary: List storage policies for a bucket
operationId: listStoragePolicies
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
- $ref: '#/components/parameters/BucketName'
responses:
'200':
description: List of policies
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/StoragePolicy'
post:
tags:
- Storage Policies
summary: Create a storage policy
operationId: createStoragePolicy
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
- $ref: '#/components/parameters/BucketName'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CreateStoragePolicyRequest'
responses:
'201':
description: Policy created
content:
application/json:
schema:
$ref: '#/components/schemas/StoragePolicy'
/projects/{id}/storage/buckets/{bucketName}/policies/{policyId}:
delete:
tags:
- Storage Policies
summary: Delete a storage policy
operationId: deleteStoragePolicy
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
- $ref: '#/components/parameters/BucketName'
- name: policyId
in: path
required: true
schema:
type: string
format: uuid
responses:
'200':
description: Policy deleted
/projects/{id}/storage/objects:
get:
tags:
- Storage Admin
summary: List all storage objects in a project
description: |
Returns a paginated list of all storage objects across all buckets in the project.
Supports filtering by owner and pagination.
operationId: listStorageObjectsAdmin
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
- name: owner_id
in: query
description: Filter by owner user ID
schema:
type: string
format: uuid
- name: page
in: query
description: Page number (1-based)
schema:
type: integer
default: 1
minimum: 1
- name: limit
in: query
description: Items per page
schema:
type: integer
default: 50
minimum: 1
maximum: 100
- $ref: '#/components/parameters/Cursor'
- $ref: '#/components/parameters/EndingBefore'
- $ref: '#/components/parameters/Offset'
- $ref: '#/components/parameters/Search'
responses:
'200':
description: Paginated list of storage objects
content:
application/json:
schema:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/StorageObjectWithBucket'
page:
type: integer
limit:
type: integer
total:
type: integer
has_more:
type: boolean
next_cursor:
type: string
description: Opaque cursor for the next page (cursor pagination only)
prev_cursor:
type: string
description: Opaque cursor for the previous page (cursor pagination only). Send as `ending_before`.
/projects/{id}/storage/stats:
get:
tags:
- Storage Admin
summary: Get storage statistics for a project
description: Returns aggregate storage statistics including bucket count, object count, and total size.
operationId: getStorageStats
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
responses:
'200':
description: Storage statistics
content:
application/json:
schema:
$ref: '#/components/schemas/StorageStats'
/projects/{id}/realtime/config:
get:
tags:
- Realtime
summary: Get realtime configuration for a project
description: Returns the realtime configuration including enabled features and limits.
operationId: getRealtimeConfig
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
responses:
'200':
description: Realtime configuration
content:
application/json:
schema:
$ref: '#/components/schemas/RealtimeConfig'
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Project not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
put:
tags:
- Realtime
summary: Update realtime configuration for a project
description: Updates realtime settings including feature toggles and limits.
operationId: updateRealtimeConfig
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/UpdateRealtimeConfigRequest'
responses:
'200':
description: Updated realtime configuration
content:
application/json:
schema:
$ref: '#/components/schemas/RealtimeConfig'
'400':
description: Invalid configuration values
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/projects/{id}/realtime/stats:
get:
tags:
- Realtime
summary: Get realtime statistics for a project
description: Returns realtime usage statistics including connection counts and subscribed tables.
operationId: getRealtimeStats
security:
- UserToken: []
parameters:
- $ref: '#/components/parameters/ProjectId'
responses:
'200':
description: Realtime statistics
content:
application/json:
schema:
$ref: '#/components/schemas/RealtimeStats'
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/storage/{bucketName}:
get:
tags:
- Storage Objects
summary: List objects in a bucket
operationId: listStorageObjects
security:
- AnonKey: []
- ServiceRoleKey: []
- AuthUserAccessToken: []
parameters:
- $ref: '#/components/parameters/BucketName'
- name: prefix
in: query
description: Filter objects by path prefix
schema:
type: string
- name: limit
in: query
description: Maximum objects to return
schema:
type: integer
default: 50
maximum: 1000
- name: cursor
in: query
description: Pagination cursor
schema:
type: string
responses:
'200':
description: List of objects
content:
application/json:
schema:
$ref: '#/components/schemas/StorageListResponse'
'403':
description: Access denied by storage policy
'429':
$ref: '#/components/responses/BandwidthCapExceeded'
/locks/{key}/lease:
post:
tags:
- Locks
summary: Acquire a project lock
description: |
Acquires a project-scoped lease using the project embedded in the service-role key.
The caller must hold the `locks.manage` permission. Repeating the request with the
same lock token is idempotent and resets that lease to the requested TTL. A different
live owner receives `409 lock_held`; a caller whose own lease already lapsed receives
`409 lock_ownership_lost`.
operationId: acquireProjectLock
security:
- ServiceRoleKey: []
parameters:
- $ref: '#/components/parameters/LockKey'
- $ref: '#/components/parameters/LockToken'
- $ref: '#/components/parameters/LockRequestId'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/ProjectLockLeaseRequest'
responses:
'201':
description: Lease acquired
content:
application/json:
schema:
$ref: '#/components/schemas/ProjectLockLease'
'400':
description: Invalid lock key, token, or TTL
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Missing or invalid credentials
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'403':
description: A non-service credential was supplied or the service key lacks `locks.manage`
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'409':
description: |
The lock is held by another live lease (`lock_held`), or the caller's own lease
lapsed and is not yet reclaimable (`lock_ownership_lost`).
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'429':
description: Project lock request limit exceeded
headers:
Retry-After:
description: Seconds until the current fixed-minute window ends.
schema:
type: integer
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'503':
description: Lock service unavailable
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
patch:
tags:
- Locks
summary: Renew a project lock
description: |
Renews a lease owned by the supplied lock token. The request must arrive
more than one second before `expires_at`; this safety margin prevents
clock skew between regional API instances from resurrecting an expired
lease.
operationId: renewProjectLock
security:
- ServiceRoleKey: []
parameters:
- $ref: '#/components/parameters/LockKey'
- $ref: '#/components/parameters/LockToken'
- $ref: '#/components/parameters/LockRequestId'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/ProjectLockLeaseRequest'
responses:
'200':
description: Lease renewed
content:
application/json:
schema:
$ref: '#/components/schemas/ProjectLockLease'
'400':
description: Invalid lock key, token, or TTL
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Missing or invalid credentials
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'403':
description: A non-service credential was supplied or the service key lacks `locks.manage`
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'409':
description: The lease expired or is owned by another token
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'429':
description: Project lock request limit exceeded
headers:
Retry-After:
description: Seconds until the current fixed-minute window ends.
schema:
type: integer
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'503':
description: Lock service unavailable
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
delete:
tags:
- Locks
summary: Release a project lock
description: Releases a lease only when the supplied lock token still owns it.
operationId: releaseProjectLock
security:
- ServiceRoleKey: []
parameters:
- $ref: '#/components/parameters/LockKey'
- $ref: '#/components/parameters/LockToken'
- $ref: '#/components/parameters/LockRequestId'
responses:
'204':
description: Lease released
'400':
description: Invalid lock key or token
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Missing or invalid credentials
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'403':
description: A non-service credential was supplied or the service key lacks `locks.manage`
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'409':
description: The lease is owned by another token
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'429':
description: Project lock request limit exceeded
headers:
Retry-After:
description: Seconds until the current fixed-minute window ends.
schema:
type: integer
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'503':
description: Lock service unavailable
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/locks/{key}:
get:
tags:
- Locks
summary: Read a project lock
description: |
Reports whether the lock is currently held, when its lease expires, and the
holder's fencing token. `held` follows takeover eligibility rather than raw
expiry, so `held: false` means an acquire would succeed now. No lock token is
required, making this usable for monitoring and recovery.
operationId: getProjectLock
security:
- ServiceRoleKey: []
parameters:
- $ref: '#/components/parameters/LockKey'
- $ref: '#/components/parameters/LockRequestId'
responses:
'200':
description: Current lock state
content:
application/json:
schema:
$ref: '#/components/schemas/ProjectLockState'
'400':
description: Invalid lock key
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Missing or invalid credentials
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'403':
description: A non-service credential was supplied or the service key lacks `locks.manage`
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'429':
description: Project lock request limit exceeded
headers:
Retry-After:
description: Seconds until the current fixed-minute window ends.
schema:
type: integer
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'503':
description: Lock service unavailable
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
delete:
tags:
- Locks
summary: Force release a project lock
description: |
Drops the lease whatever token holds it, for recovering a lock whose holder
died without releasing. Use `DELETE /locks/{key}/lease` for normal release.
This breaks mutual exclusion by itself: the previous holder keeps working
until its own renewal fails. Guard the protected resource with the lease's
`fencing_token`, which the next acquisition raises, so a write from the
displaced holder can be rejected. Succeeds when the lock is already absent.
operationId: forceReleaseProjectLock
security:
- ServiceRoleKey: []
parameters:
- $ref: '#/components/parameters/LockKey'
- $ref: '#/components/parameters/LockRequestId'
responses:
'204':
description: Lock released
'400':
description: Invalid lock key
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Missing or invalid credentials
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'403':
description: A non-service credential was supplied or the service key lacks `locks.manage`
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'429':
description: Project lock request limit exceeded
headers:
Retry-After:
description: Seconds until the current fixed-minute window ends.
schema:
type: integer
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'503':
description: Lock service unavailable
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/storage/{bucketName}/move:
post:
tags:
- Storage Objects
summary: Move/rename an object
operationId: moveStorageObject
security:
- ServiceRoleKey: []
- AuthUserAccessToken: []
parameters:
- $ref: '#/components/parameters/BucketName'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/StorageMoveRequest'
responses:
'200':
description: Object moved
content:
application/json:
schema:
$ref: '#/components/schemas/StorageObject'
'403':
description: Access denied by storage policy
'429':
$ref: '#/components/responses/BandwidthCapExceeded'
/storage/{bucketName}/copy:
post:
tags:
- Storage Objects
summary: Copy an object
operationId: copyStorageObject
security:
- ServiceRoleKey: []
- AuthUserAccessToken: []
parameters:
- $ref: '#/components/parameters/BucketName'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/StorageCopyRequest'
responses:
'201':
description: Object copied
content:
application/json:
schema:
$ref: '#/components/schemas/StorageObject'
'403':
description: Access denied by storage policy
'429':
$ref: '#/components/responses/BandwidthCapExceeded'
/storage/{bucketName}/{path}:
post:
tags:
- Storage Objects
summary: Upload a file or create resumable session
description: |
Unified endpoint for file uploads. Behavior depends on Content-Type and headers:
**Simple Upload (multipart/form-data):**
Upload a complete file in a single request. Best for files under 100MB.
**Create Resumable Session (application/json):**
Create a session for chunked uploads. Best for large files or unreliable networks.
Requires: `Content-Type: application/json` with body `{"filename": "...", "content_type": "...", "total_size": ...}`
**Complete Resumable Session:**
Complete a session after all parts are uploaded.
Requires: `X-Upload-Session` header with session ID and `X-Upload-Complete: true` header.
**Resumable Session Ownership:**
A session created with a user access token remains bound to that user. A session
created with an anon key remains bound to that exact anon key. Reuse the same
identity or anon key for part uploads, status, completion, and abort requests;
an ownership mismatch returns `404`.
operationId: uploadStorageObject
security:
- AnonKey: []
- ServiceRoleKey: []
- AuthUserAccessToken: []
parameters:
- $ref: '#/components/parameters/BucketName'
- name: path
in: path
required: true
description: Object path within bucket
schema:
type: string
- name: X-Upload-Session
in: header
required: false
description: Upload session ID (for completing resumable uploads)
schema:
type: string
- name: X-Upload-Complete
in: header
required: false
description: Set to "true" to complete a resumable upload session
schema:
type: string
enum:
- 'true'
requestBody:
required: true
content:
multipart/form-data:
schema:
type: object
required:
- file
properties:
file:
type: string
format: binary
description: File to upload (simple upload)
application/json:
schema:
$ref: '#/components/schemas/CreateUploadSessionRequest'
responses:
'200':
description: Resumable upload completed (when X-Upload-Complete=true)
content:
application/json:
schema:
$ref: '#/components/schemas/CompleteUploadSessionResponse'
'201':
description: File uploaded or session created
content:
application/json:
schema:
oneOf:
- $ref: '#/components/schemas/StorageObject'
- $ref: '#/components/schemas/CreateUploadSessionResponse'
'400':
description: |
Bad request. This can occur when:
- MIME type is not in the bucket's allowed_mime_types list
- File exceeds the bucket's configured file_size_limit
- File exceeds the global maximum upload size (5GB)
- Invalid request body or missing required fields
'403':
description: Access denied by storage policy
'404':
description: Resumable upload session not found or not owned by this credential
'413':
description: |
File size exceeds plan-based limits. This occurs when:
- File exceeds the plan-based maximum file size (HOBBY or SUPERAGENT tier)
- Upload would exceed the project's total storage quota
'429':
$ref: '#/components/responses/BandwidthCapExceeded'
put:
tags:
- Storage Objects
summary: Upload a part of a resumable upload
description: |
Upload a single part of a resumable upload session.
**Requirements:**
- Part numbers start at 1
- All parts except the last must be at least 5MB
- Maximum part size is 25MB
- Parts can be uploaded in any order
- Re-uploading a part overwrites the previous upload
- Anonymous sessions must reuse the exact anon key that created the session
operationId: uploadPart
security:
- AnonKey: []
- ServiceRoleKey: []
- AuthUserAccessToken: []
parameters:
- $ref: '#/components/parameters/BucketName'
- name: path
in: path
required: true
description: Object path within bucket
schema:
type: string
- name: X-Upload-Session
in: header
required: true
description: Upload session ID
schema:
type: string
- name: X-Part-Number
in: header
required: true
description: Part number (1 to 10000)
schema:
type: integer
minimum: 1
maximum: 10000
requestBody:
required: true
content:
application/octet-stream:
schema:
type: string
format: binary
responses:
'200':
description: Part uploaded
content:
application/json:
schema:
$ref: '#/components/schemas/UploadSessionPart'
'400':
description: Invalid part number or part data
'403':
description: Access denied
'404':
description: Session not found or not owned by this credential
get:
tags:
- Storage Objects
summary: Download a file or get upload session status
description: |
Download a file, or get the status of a resumable upload session.
**File Download (default):**
Downloads the file at the specified path.
**Session Status (with X-Upload-Session header):**
Returns the status of a resumable upload session, including which parts have been uploaded.
Anonymous sessions must reuse the exact anon key that created the session.
operationId: downloadStorageObject
security:
- AnonKey: []
- ServiceRoleKey: []
- AuthUserAccessToken: []
parameters:
- $ref: '#/components/parameters/BucketName'
- name: path
in: path
required: true
description: Object path within bucket
schema:
type: string
- name: Range
in: header
required: false
description: |
HTTP Range header for partial downloads.
Format: bytes=start-end or bytes=start-
Examples: bytes=0-1023, bytes=1000-
schema:
type: string
pattern: ^bytes=\d+-\d*$
- name: X-Upload-Session
in: header
required: false
description: Upload session ID (to get session status instead of downloading)
schema:
type: string
responses:
'200':
description: File content or session status
headers:
Content-Type:
schema:
type: string
Content-Length:
schema:
type: integer
ETag:
schema:
type: string
content:
application/octet-stream:
schema:
type: string
format: binary
application/json:
schema:
$ref: '#/components/schemas/UploadSessionStatusResponse'
'206':
description: Partial content (range request)
'400':
description: Invalid Range header format
'403':
description: Access denied by storage policy
'404':
description: Object or session not found, or session not owned by this credential
'429':
$ref: '#/components/responses/BandwidthCapExceeded'
delete:
tags:
- Storage Objects
summary: Delete a file or abort upload session
description: |
Delete a file, or abort a resumable upload session.
**File Delete (default):**
Deletes the file at the specified path.
**Abort Session (with X-Upload-Session header):**
Aborts a resumable upload session and cleans up any uploaded parts.
Anonymous sessions must reuse the exact anon key that created the session.
operationId: deleteStorageObject
security:
- AnonKey: []
- ServiceRoleKey: []
- AuthUserAccessToken: []
parameters:
- $ref: '#/components/parameters/BucketName'
- name: path
in: path
required: true
description: Object path within bucket
schema:
type: string
- name: X-Upload-Session
in: header
required: false
description: Upload session ID (to abort session instead of deleting file)
schema:
type: string
responses:
'200':
description: Object deleted or session aborted
'403':
description: Access denied by storage policy
'404':
description: Object or session not found, or session not owned by this credential
'429':
$ref: '#/components/responses/BandwidthCapExceeded'
/storage/{bucketName}/{path}/visibility:
patch:
tags:
- Storage Objects
summary: Update file visibility (public/private)
description: |
Change whether a file is publicly accessible. Only the file owner or a service key can change visibility.
If the bucket defines UPDATE policies, the owner must also satisfy one of them.
- Public files can be downloaded with just an anon key (no user authentication required)
- Private files (default) require authentication and must pass policy checks
- All downloads go through the Volcano API - there is no direct access to the underlying store
operationId: updateStorageObjectVisibility
security:
- ServiceRoleKey: []
- AuthUserAccessToken: []
parameters:
- $ref: '#/components/parameters/BucketName'
- name: path
in: path
required: true
description: Object path within bucket
schema:
type: string
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/StorageVisibilityRequest'
responses:
'200':
description: Visibility updated
content:
application/json:
schema:
$ref: '#/components/schemas/StorageObject'
'403':
description: Not the file owner or denied by the bucket's UPDATE policies
'404':
description: Object not found
/public/{projectId}/{bucketName}/{path}:
get:
tags:
- Storage Objects
summary: Download a public file (no authentication required)
description: |
Download a file that has been marked as public. This endpoint requires NO authentication.
**Access Requirements:**
- The file must have `is_public: true` set via the visibility endpoint
- Private files will return 403 Forbidden
**Use Cases:**
- Shareable public URLs for profile pictures, public documents, etc.
- Embedding public files on external websites
- Direct linking without requiring SDK or authentication
**URL Format:**
```
GET /public/{projectId}/{bucketName}/{path}
```
**Example:**
```
https://api.volcano.dev/public/abc123/avatars/user-photo.jpg
```
**CORS:**
This endpoint allows all origins since the file is already public.
operationId: downloadPublicFile
parameters:
- name: projectId
in: path
required: true
description: Project ID
schema:
type: string
format: uuid
- $ref: '#/components/parameters/BucketName'
- name: path
in: path
required: true
description: Object path within bucket
schema:
type: string
responses:
'200':
description: File content
content:
'*/*':
schema:
type: string
format: binary
'206':
description: Partial content (range request)
'404':
description: Not found (file doesn't exist or is not public)
'429':
$ref: '#/components/responses/BandwidthCapExceeded'
/health:
get:
tags:
- System
summary: Health check endpoint
description: Returns server health status. Used for load balancer and monitoring checks.
operationId: healthCheck
responses:
'200':
description: Server is healthy
content:
text/plain:
schema:
type: string
example: OK
/sandboxes/presets:
get:
tags:
- Sandboxes
summary: List available sandbox presets
operationId: listSandboxPresets
security: []
responses:
'200':
description: List available sandbox presets
content:
application/json:
schema:
$ref: '#/components/schemas/SandboxPresetList'
default:
description: Request refused or unavailable. Errors include invalid input (400), unauthenticated (401), forbidden (403), not found (404), conflicting retry (409), capacity exhausted (429), and disabled or unavailable (503).
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/projects/{id}/sandboxes:
get:
tags:
- Sandboxes
summary: List sandbox templates
operationId: listSandboxes
security:
- UserToken: []
- ServiceRoleKey: []
parameters:
- name: id
in: path
required: true
schema:
type: string
format: uuid
- $ref: '#/components/parameters/Limit'
- $ref: '#/components/parameters/Cursor'
responses:
'200':
description: List sandbox templates
content:
application/json:
schema:
$ref: '#/components/schemas/SandboxTemplatePage'
default:
description: Request refused or unavailable. Errors include invalid input (400), unauthenticated (401), forbidden (403), not found (404), conflicting retry (409), capacity exhausted (429), and disabled or unavailable (503).
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
post:
tags:
- Sandboxes
summary: Create a sandbox template from a verified preset
operationId: createSandbox
security:
- UserToken: []
- ServiceRoleKey: []
parameters:
- name: id
in: path
required: true
schema:
type: string
format: uuid
- name: Idempotency-Key
in: header
required: true
schema:
type: string
format: uuid
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CreateSandboxTemplateRequest'
responses:
'201':
description: Create a sandbox template from a verified preset
content:
application/json:
schema:
$ref: '#/components/schemas/SandboxTemplate'
default:
description: Request refused or unavailable. Errors include invalid input (400), unauthenticated (401), forbidden (403), not found (404), conflicting retry (409), capacity exhausted (429), and disabled or unavailable (503).
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/projects/{id}/sandboxes/{sandboxId}:
get:
tags:
- Sandboxes
summary: Get a sandbox template
operationId: getSandbox
security:
- UserToken: []
- ServiceRoleKey: []
parameters:
- name: id
in: path
required: true
schema:
type: string
format: uuid
- name: sandboxId
in: path
required: true
schema:
type: string
format: uuid
responses:
'200':
description: Get a sandbox template
content:
application/json:
schema:
$ref: '#/components/schemas/SandboxTemplate'
default:
description: Request refused or unavailable. Errors include invalid input (400), unauthenticated (401), forbidden (403), not found (404), conflicting retry (409), capacity exhausted (429), and disabled or unavailable (503).
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
patch:
tags:
- Sandboxes
summary: Rename a sandbox template
operationId: updateSandbox
security:
- UserToken: []
- ServiceRoleKey: []
parameters:
- name: id
in: path
required: true
schema:
type: string
format: uuid
- name: sandboxId
in: path
required: true
schema:
type: string
format: uuid
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/UpdateSandboxTemplateRequest'
responses:
'200':
description: Rename a sandbox template
content:
application/json:
schema:
$ref: '#/components/schemas/SandboxTemplate'
default:
description: Request refused or unavailable. Errors include invalid input (400), unauthenticated (401), forbidden (403), not found (404), conflicting retry (409), capacity exhausted (429), and disabled or unavailable (503).
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
delete:
tags:
- Sandboxes
summary: Retire a template and terminate its sessions
operationId: deleteSandbox
security:
- UserToken: []
- ServiceRoleKey: []
parameters:
- name: id
in: path
required: true
schema:
type: string
format: uuid
- name: sandboxId
in: path
required: true
schema:
type: string
format: uuid
responses:
'202':
description: Retire a template and terminate its sessions
default:
description: Request refused or unavailable. Errors include invalid input (400), unauthenticated (401), forbidden (403), not found (404), conflicting retry (409), capacity exhausted (429), and disabled or unavailable (503).
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/projects/{id}/sandboxes/{sandboxId}/deployments:
get:
tags:
- Sandboxes
summary: List sandbox deployment history
operationId: listSandboxDeployments
security:
- UserToken: []
- ServiceRoleKey: []
parameters:
- name: id
in: path
required: true
schema:
type: string
format: uuid
- name: sandboxId
in: path
required: true
schema:
type: string
format: uuid
- $ref: '#/components/parameters/Limit'
- $ref: '#/components/parameters/Cursor'
responses:
'200':
description: List sandbox deployment history
content:
application/json:
schema:
$ref: '#/components/schemas/SandboxDeploymentPage'
default:
description: Request refused or unavailable. Errors include invalid input (400), unauthenticated (401), forbidden (403), not found (404), conflicting retry (409), capacity exhausted (429), and disabled or unavailable (503).
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/projects/{id}/sandbox-sessions:
get:
tags:
- Sandboxes
summary: List project sandbox sessions
operationId: listSandboxSessions
security:
- UserToken: []
- ServiceRoleKey: []
parameters:
- name: id
in: path
required: true
schema:
type: string
format: uuid
- $ref: '#/components/parameters/Limit'
- $ref: '#/components/parameters/Cursor'
responses:
'200':
description: List project sandbox sessions
content:
application/json:
schema:
$ref: '#/components/schemas/SandboxSessionPage'
default:
description: Request refused or unavailable. Errors include invalid input (400), unauthenticated (401), forbidden (403), not found (404), conflicting retry (409), capacity exhausted (429), and disabled or unavailable (503).
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
post:
tags:
- Sandboxes
summary: Start a sandbox session
operationId: createSandboxSession
security:
- UserToken: []
- ServiceRoleKey: []
parameters:
- name: id
in: path
required: true
schema:
type: string
format: uuid
- name: Idempotency-Key
in: header
required: true
schema:
type: string
format: uuid
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CreateSandboxSessionRequest'
responses:
'201':
description: Start a sandbox session
content:
application/json:
schema:
$ref: '#/components/schemas/SandboxSession'
default:
description: Request refused or unavailable. Errors include invalid input (400), unauthenticated (401), forbidden (403), not found (404), conflicting retry (409), capacity exhausted (429), and disabled or unavailable (503).
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/projects/{id}/sandbox-executions:
post:
tags:
- Sandboxes
summary: Execute once and return after confirmed termination
operationId: executeSandbox
security:
- UserToken: []
- ServiceRoleKey: []
parameters:
- name: id
in: path
required: true
schema:
type: string
format: uuid
- name: Idempotency-Key
in: header
required: true
schema:
type: string
format: uuid
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/SandboxExecutionRequest'
responses:
'200':
description: Execute once and return after confirmed termination
content:
application/json:
schema:
$ref: '#/components/schemas/SandboxExecutionResult'
default:
description: Request refused or unavailable. Errors include invalid input (400), unauthenticated (401), forbidden (403), not found (404), conflicting retry (409), capacity exhausted (429), and disabled or unavailable (503).
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/sandbox-sessions/{sessionId}:
get:
tags:
- Sandboxes
summary: Get a sandbox session
operationId: getSandboxSession
security:
- UserToken: []
- ServiceRoleKey: []
- AuthUserAccessToken: []
parameters:
- name: sessionId
in: path
required: true
schema:
type: string
format: uuid
responses:
'200':
description: Get a sandbox session
content:
application/json:
schema:
$ref: '#/components/schemas/SandboxSession'
default:
description: Request refused or unavailable. Errors include invalid input (400), unauthenticated (401), forbidden (403), not found (404), conflicting retry (409), capacity exhausted (429), and disabled or unavailable (503).
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
delete:
tags:
- Sandboxes
summary: Request sandbox termination
operationId: terminateSandboxSession
security:
- UserToken: []
- ServiceRoleKey: []
parameters:
- name: sessionId
in: path
required: true
schema:
type: string
format: uuid
responses:
'202':
description: Request sandbox termination
content:
application/json:
schema:
$ref: '#/components/schemas/SandboxSession'
default:
description: Request refused or unavailable. Errors include invalid input (400), unauthenticated (401), forbidden (403), not found (404), conflicting retry (409), capacity exhausted (429), and disabled or unavailable (503).
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/sandbox-sessions/{sessionId}/suspend:
post:
tags:
- Sandboxes
summary: Suspend a sandbox session
operationId: suspendSandboxSession
security:
- UserToken: []
- ServiceRoleKey: []
parameters:
- name: sessionId
in: path
required: true
schema:
type: string
format: uuid
responses:
'202':
description: Suspend a sandbox session
content:
application/json:
schema:
$ref: '#/components/schemas/SandboxSession'
default:
description: Request refused or unavailable. Errors include invalid input (400), unauthenticated (401), forbidden (403), not found (404), conflicting retry (409), capacity exhausted (429), and disabled or unavailable (503).
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/sandbox-sessions/{sessionId}/resume:
post:
tags:
- Sandboxes
summary: Resume a sandbox session
operationId: resumeSandboxSession
security:
- UserToken: []
- ServiceRoleKey: []
parameters:
- name: sessionId
in: path
required: true
schema:
type: string
format: uuid
responses:
'202':
description: Resume a sandbox session
content:
application/json:
schema:
$ref: '#/components/schemas/SandboxSession'
default:
description: Request refused or unavailable. Errors include invalid input (400), unauthenticated (401), forbidden (403), not found (404), conflicting retry (409), capacity exhausted (429), and disabled or unavailable (503).
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/sandbox-sessions/{sessionId}/exec:
post:
tags:
- Sandboxes
summary: Execute a command within a session
operationId: executeSandboxSession
security:
- UserToken: []
- ServiceRoleKey: []
- AuthUserAccessToken: []
parameters:
- name: sessionId
in: path
required: true
schema:
type: string
format: uuid
- name: Idempotency-Key
in: header
required: true
schema:
type: string
format: uuid
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/SandboxCommandRequest'
responses:
'200':
description: Execute a command within a session
content:
application/json:
schema:
$ref: '#/components/schemas/SandboxCommandResult'
default:
description: Request refused or unavailable. Errors include invalid input (400), unauthenticated (401), forbidden (403), not found (404), conflicting retry (409), capacity exhausted (429), and disabled or unavailable (503).
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/sandbox-sessions/{sessionId}/files/read:
post:
tags:
- Sandboxes
summary: Read a workspace file
operationId: readSandboxSessionFile
security:
- UserToken: []
- ServiceRoleKey: []
- AuthUserAccessToken: []
parameters:
- name: sessionId
in: path
required: true
schema:
type: string
format: uuid
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/SandboxFileReadRequest'
responses:
'200':
description: Read a workspace file
content:
application/json:
schema:
$ref: '#/components/schemas/SandboxFileResult'
default:
description: Request refused or unavailable. Errors include invalid input (400), unauthenticated (401), forbidden (403), not found (404), conflicting retry (409), capacity exhausted (429), and disabled or unavailable (503).
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/sandbox-sessions/{sessionId}/files/write:
post:
tags:
- Sandboxes
summary: Write a workspace file
operationId: writeSandboxSessionFile
security:
- UserToken: []
- ServiceRoleKey: []
- AuthUserAccessToken: []
parameters:
- name: sessionId
in: path
required: true
schema:
type: string
format: uuid
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/SandboxFileWriteRequest'
responses:
'204':
description: Write a workspace file
default:
description: Request refused or unavailable. Errors include invalid input (400), unauthenticated (401), forbidden (403), not found (404), conflicting retry (409), capacity exhausted (429), and disabled or unavailable (503).
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/sandbox-sessions/{sessionId}/grants/{subjectId}:
put:
tags:
- Sandboxes
summary: Authorize an authenticated project user for this session
operationId: grantSandboxSession
security:
- UserToken: []
- ServiceRoleKey: []
parameters:
- name: sessionId
in: path
required: true
schema:
type: string
format: uuid
- name: subjectId
in: path
required: true
schema:
type: string
format: uuid
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/SandboxSubjectGrantRequest'
responses:
'204':
description: Authorize an authenticated project user for this session
default:
description: Request refused or unavailable. Errors include invalid input (400), unauthenticated (401), forbidden (403), not found (404), conflicting retry (409), capacity exhausted (429), and disabled or unavailable (503).
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
delete:
tags:
- Sandboxes
summary: Revoke a project user session grant
operationId: revokeSandboxSession
security:
- UserToken: []
- ServiceRoleKey: []
parameters:
- name: sessionId
in: path
required: true
schema:
type: string
format: uuid
- name: subjectId
in: path
required: true
schema:
type: string
format: uuid
responses:
'204':
description: Revoke a project user session grant
default:
description: Request refused or unavailable. Errors include invalid input (400), unauthenticated (401), forbidden (403), not found (404), conflicting retry (409), capacity exhausted (429), and disabled or unavailable (503).
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/sandbox-sessions/{sessionId}/access:
post:
tags:
- Sandboxes
summary: Issue a short-lived port-scoped access credential
operationId: createSandboxSessionAccess
security:
- UserToken: []
- ServiceRoleKey: []
- AuthUserAccessToken: []
parameters:
- name: sessionId
in: path
required: true
schema:
type: string
format: uuid
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/SandboxAccessRequest'
responses:
'200':
description: Issue a short-lived port-scoped access credential
content:
application/json:
schema:
$ref: '#/components/schemas/SandboxAccess'
default:
description: Request refused or unavailable. Errors include invalid input (400), unauthenticated (401), forbidden (403), not found (404), conflicting retry (409), capacity exhausted (429), and disabled or unavailable (503).
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
components:
securitySchemes:
AnonKey:
type: http
scheme: bearer
bearerFormat: JWT
description: |
Project-specific public key for frontend authentication.
Required for signup, signin, refresh, and logout endpoints.
Get from Project Settings → Authentication → Anon Keys.
Safe to expose in frontend code (scoped to project, limited permissions).
AuthUserAccessToken:
type: http
scheme: bearer
bearerFormat: JWT
description: |
Auth user access token obtained from signup/signin.
Used for authenticated function invocation and user profile access.
Functions invoked with access tokens receive user context in event.__volcano_auth.
Expires after configured lifetime (default: 1 hour).
ServiceRoleKey:
type: http
scheme: bearer
bearerFormat: JWT
description: |
Service role key for admin operations.
**WARNING:** Bypasses Row-Level Security - backend use only!
Create via POST /projects/{id}/service-keys.
Used for function invocation with full database access.
UserToken:
type: http
scheme: bearer
bearerFormat: JWT
description: |
Platform user token from the Management API.
Required for project management operations.
Obtain via POST /tokens in Management API (port 8001).
parameters:
BackupName:
name: backupName
in: path
required: true
schema:
type: string
minLength: 1
maxLength: 128
description: |
Backup name, unique within the database, exactly as returned by the list
endpoint.
Deliberately looser than the names you can create: a backup made by a
schedule is named for you, so reading or deleting one accepts any name a
backup can have.
BranchName:
name: branchName
in: path
required: true
schema:
type: string
pattern: ^[a-z0-9_]+$
maxLength: 64
description: Branch name (unique within the parent database, lowercase letters, numbers, and underscores only)
BucketName:
name: bucketName
in: path
required: true
schema:
type: string
pattern: ^[a-zA-Z0-9_-]+$
minLength: 1
maxLength: 64
description: Storage bucket name
Cursor:
name: cursor
in: query
required: false
schema:
type: string
description: |
Opaque keyset pagination cursor from a previous response's `next_cursor`
— pages forward. Mutually exclusive with `page` and `ending_before`;
combining them returns 400. When supplied, the request's `search` and
`limit` must match the values bound to the cursor or the request returns 400.
EndingBefore:
name: ending_before
in: query
required: false
schema:
type: string
description: |
Opaque keyset pagination cursor from a previous response's `prev_cursor`
— pages backward (the page immediately preceding this cursor). Mutually
exclusive with `page` and `cursor`; combining them returns 400. `search`
and `limit` must match the values bound to the cursor or the request
returns 400.
DatabaseName:
name: databaseName
in: path
required: true
schema:
type: string
pattern: ^[a-z0-9_]+$
maxLength: 64
description: Database name (unique within project, lowercase letters, numbers, and underscores only)
DeploymentId:
name: deploymentId
in: path
required: true
schema:
type: string
format: uuid
description: Frontend deployment ID
FrontendId:
name: frontendId
in: path
required: true
schema:
type: string
format: uuid
description: Frontend ID
FunctionId:
name: functionId
in: path
required: true
schema:
type: string
format: uuid
description: Function ID
DurableFunctionId:
name: functionId
in: path
required: true
schema:
type: string
description: Durable function ID, or its name within the project
DurableExecutionId:
name: executionId
in: path
required: true
schema:
type: string
format: uuid
description: Durable execution ID
Limit:
name: limit
in: query
required: false
schema:
type: integer
minimum: 1
maximum: 100
default: 10
description: Number of items per page (max 100)
LockKey:
name: key
in: path
required: true
description: Project-local lock name.
schema:
type: string
minLength: 1
maxLength: 128
pattern: ^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$
LockToken:
name: X-Volcano-Lock-Token
in: header
required: true
description: Opaque UUID generated once by the caller and retained for the lease lifetime.
schema:
type: string
format: uuid
LockRequestId:
name: X-Volcano-Request-Id
in: header
required: true
description: |
UUID correlating this request across client and server logs. Repeat safety comes from
the lock token, so a retry under a reused request ID still counts against the quota.
schema:
type: string
format: uuid
DeploymentOperation:
name: operation
in: query
required: false
description: Restrict a deployment feed to one kind of operation.
schema:
type: string
enum:
- deploy
- redeploy
- update
- delete
DeploymentOwnerId:
name: owner_id
in: query
required: false
description: |
The user who owns the projects whose deployments to return
(`projects.user_id`). This is ownership, not the actor that started the
deployment — see `initiated_by_user_id` for that. Not a UUID: platform
user ids are opaque strings.
schema:
type: string
maxLength: 255
DeploymentOrder:
name: order
in: query
required: false
description: |
Sort key and direction. `created_at.desc` (default) is the feed order.
`completed_at.asc` orders finished attempts by completion, oldest first,
and excludes attempts that never completed.
schema:
type: string
enum:
- created_at.desc
- completed_at.asc
default: created_at.desc
DeploymentResourceType:
name: resource_type
in: query
required: false
description: |
Restrict a deployment feed to a single resource type. Omit to return
both Function and Frontend deployments.
schema:
type: string
enum:
- function
- frontend
DeploymentStatus:
name: status
in: query
required: false
description: Restrict a deployment feed to attempts in one status.
schema:
type: string
enum:
- queued
- provisioning
- active
- degraded
- failed
- superseded
- deleting
- deleted
Offset:
name: offset
in: query
required: false
schema:
type: integer
minimum: 0
default: 0
description: |
Bounded row offset past the keyset anchor named by `cursor` (forward) or
`ending_before` (backward) — the hybrid jump. Seek to the anchor, then
skip this many rows within. Used for numbered jump-to-page: from the
current page, seek to its next/prev cursor and offset the remaining
pages. Only honored on the cursor pagination path; ignored otherwise.
Page:
name: page
in: query
required: false
schema:
type: integer
minimum: 1
description: |
Page number (1-indexed) for offset pagination. Declares no schema
default so the request validator does not inject one: handlers that omit
`page` see it unset (nil) and default to 1 in code, while cursor-first
endpoints (e.g. the project deployments feed) can detect its absence to
stay in keyset/search mode. Supplying `page` selects offset pagination.
ProjectId:
name: id
in: path
required: true
schema:
type: string
format: uuid
description: Project ID
Search:
name: search
in: query
required: false
schema:
type: string
maxLength: 256
description: |
Case-insensitive substring match on the resource `name`. See the
endpoint description for supported pagination modes.
RestoreId:
name: restoreId
in: path
required: true
schema:
type: string
format: uuid
description: Database restore ID
SchedulerId:
name: schedulerId
in: path
required: true
schema:
type: string
format: uuid
description: Function scheduler ID
VariableName:
name: name
in: path
required: true
schema:
type: string
minLength: 1
maxLength: 256
pattern: ^[a-zA-Z_][a-zA-Z0-9_]*$
description: Variable name
responses:
BandwidthCapExceeded:
description: |
The platform user exceeded their billing-cycle bandwidth allowance (aggregate
ingress + egress across owned projects). Enforcement is eventual:
requests are rejected until the allowance increases or the next
anniversary cycle begins.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
DatabaseQueryCapExceeded:
description: |
The query was rejected by a billing-cycle allowance: either the owning
platform user's bandwidth allowance (aggregate ingress + egress across
owned projects) or their database-request allowance. Enforcement is
eventual: queries are rejected until the allowance increases or the
next anniversary cycle begins. The error message identifies the resource.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
DatabaseBranchQueryUnavailable:
description: |
The branch exists but cannot serve queries: it is still provisioning,
being reset, expired, or its parent is being restored. Distinct from
`404` so a caller waiting on a branch can tell it apart from a typo.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
schemas:
SandboxPreset:
type: object
additionalProperties: false
properties:
id:
type: string
runtime:
type: string
version:
type: string
memory_mb:
type: integer
enum:
- 1024
- 2048
regions:
type: array
items:
type: string
required:
- id
- runtime
- version
- memory_mb
- regions
SandboxTemplate:
type: object
additionalProperties: false
properties:
id:
type: string
format: uuid
project_id:
type: string
format: uuid
name:
type: string
pattern: ^[a-z][a-z0-9-]{0,62}$
preset:
type: string
memory_mb:
type: integer
status:
type: string
enum:
- ready
- unavailable
- deleting
created_at:
type: string
format: date-time
required:
- id
- project_id
- name
- status
- created_at
CreateSandboxTemplateRequest:
type: object
additionalProperties: false
properties:
name:
type: string
pattern: ^[a-z][a-z0-9-]{0,62}$
preset:
type: string
description: Preset ID from the available Sandbox preset catalog.
memory_mb:
type: integer
enum:
- 1024
- 2048
default: 1024
required:
- name
- preset
UpdateSandboxTemplateRequest:
type: object
additionalProperties: false
properties:
name:
type: string
pattern: ^[a-z][a-z0-9-]{0,62}$
required:
- name
SandboxSession:
type: object
additionalProperties: false
properties:
id:
type: string
format: uuid
project_id:
type: string
format: uuid
sandbox_id:
type: string
format: uuid
state:
type: string
enum:
- starting
- running
- suspending
- suspended
- resuming
- terminating
- terminated
- unknown
desired_state:
type: string
enum:
- running
- suspended
- terminated
region:
type: string
memory_mb:
type: integer
created_at:
type: string
format: date-time
started_at:
type: string
format: date-time
expires_at:
type: string
format: date-time
required:
- id
- project_id
- sandbox_id
- state
- desired_state
- region
- memory_mb
- created_at
- expires_at
CreateSandboxSessionRequest:
type: object
additionalProperties: false
properties:
preset:
type: string
description: Preset ID from the available Sandbox preset catalog.
sandbox_id:
type: string
format: uuid
memory_mb:
type: integer
enum:
- 1024
- 2048
region:
type: string
pattern: ^(aws-)?[a-z]{2}(-[a-z]+)+-[0-9]+$
description: Region such as `us-east-1`. Region IDs issued by earlier versions of the API are still accepted.
max_duration_seconds:
type: integer
minimum: 30
maximum: 28800
default: 3600
idle_timeout_seconds:
type: integer
minimum: 0
maximum: 28800
default: 0
required:
- region
oneOf:
- required:
- preset
not:
required:
- sandbox_id
- required:
- sandbox_id
not:
required:
- preset
SandboxCommandRequest:
type: object
additionalProperties: false
properties:
command:
type: string
minLength: 1
maxLength: 65536
timeout_seconds:
type: integer
minimum: 1
maximum: 3600
default: 60
environment:
type: object
additionalProperties:
type: string
maxProperties: 64
required:
- command
SandboxExecutionRequest:
type: object
additionalProperties: false
properties:
preset:
type: string
description: Preset ID from the available Sandbox preset catalog.
sandbox_id:
type: string
format: uuid
memory_mb:
type: integer
enum:
- 1024
- 2048
region:
type: string
pattern: ^(aws-)?[a-z]{2}(-[a-z]+)+-[0-9]+$
description: Region such as `us-east-1`. Region IDs issued by earlier versions of the API are still accepted.
command:
type: string
minLength: 1
maxLength: 65536
timeout_seconds:
type: integer
minimum: 1
maximum: 60
default: 60
environment:
type: object
additionalProperties:
type: string
maxProperties: 64
required:
- region
- command
oneOf:
- required:
- preset
not:
required:
- sandbox_id
- required:
- sandbox_id
not:
required:
- preset
SandboxCommandResult:
type: object
additionalProperties: false
properties:
stdout:
type: string
stderr:
type: string
exit_code:
type: integer
stdout_truncated:
type: boolean
stderr_truncated:
type: boolean
timed_out:
type: boolean
required:
- stdout
- stderr
- exit_code
- stdout_truncated
- stderr_truncated
- timed_out
SandboxExecutionResult:
type: object
additionalProperties: false
properties:
stdout:
type: string
stderr:
type: string
exit_code:
type: integer
stdout_truncated:
type: boolean
stderr_truncated:
type: boolean
timed_out:
type: boolean
session_id:
type: string
format: uuid
region:
type: string
duration_ms:
type: integer
format: int64
minimum: 0
required:
- stdout
- stderr
- exit_code
- stdout_truncated
- stderr_truncated
- timed_out
- session_id
- region
- duration_ms
SandboxFileWriteRequest:
type: object
additionalProperties: false
properties:
path:
type: string
minLength: 1
maxLength: 4096
data:
type: string
format: byte
maxLength: 11184812
required:
- path
- data
SandboxFileReadRequest:
type: object
additionalProperties: false
properties:
path:
type: string
minLength: 1
maxLength: 4096
required:
- path
SandboxFileResult:
type: object
additionalProperties: false
properties:
data:
type: string
format: byte
required:
- data
SandboxSubjectGrantRequest:
type: object
additionalProperties: false
properties:
expires_at:
type: string
format: date-time
required:
- expires_at
SandboxAccessRequest:
type: object
additionalProperties: false
properties:
port:
type: integer
minimum: 1
maximum: 65532
expires_in_seconds:
type: integer
minimum: 1
maximum: 300
default: 300
required:
- port
SandboxAccess:
type: object
additionalProperties: false
properties:
url:
type: string
format: uri
token:
type: string
expires_at:
type: string
format: date-time
required:
- url
- token
- expires_at
SandboxDeployment:
type: object
additionalProperties: false
properties:
id:
type: string
format: uuid
status:
type: string
created_at:
type: string
format: date-time
updated_at:
type: string
format: date-time
required:
- id
- status
- created_at
- updated_at
SandboxPagination:
type: object
additionalProperties: false
properties:
limit:
type: integer
has_more:
type: boolean
next_cursor:
type: string
required:
- limit
- has_more
SandboxTemplatePage:
type: object
additionalProperties: false
properties:
data:
type: array
items:
$ref: '#/components/schemas/SandboxTemplate'
pagination:
$ref: '#/components/schemas/SandboxPagination'
required:
- data
- pagination
SandboxSessionPage:
type: object
additionalProperties: false
properties:
data:
type: array
items:
$ref: '#/components/schemas/SandboxSession'
pagination:
$ref: '#/components/schemas/SandboxPagination'
required:
- data
- pagination
SandboxDeploymentPage:
type: object
additionalProperties: false
properties:
data:
type: array
items:
$ref: '#/components/schemas/SandboxDeployment'
pagination:
$ref: '#/components/schemas/SandboxPagination'
required:
- data
- pagination
SandboxPresetList:
type: object
additionalProperties: false
properties:
data:
type: array
items:
$ref: '#/components/schemas/SandboxPreset'
required:
- data
SandboxCapacity:
type: object
additionalProperties: false
properties:
region:
type: string
allocated_memory_mb:
type: integer
format: int64
minimum: 0
required:
- region
- allocated_memory_mb
SandboxCapacityList:
type: object
additionalProperties: false
properties:
data:
type: array
items:
$ref: '#/components/schemas/SandboxCapacity'
required:
- data
PublishSandboxPresetRequest:
type: object
additionalProperties: false
properties:
id:
type: string
format: uuid
preset:
type: string
enum:
- python3.12
- node22
memory_mb:
type: integer
enum:
- 1024
- 2048
deployment_id:
type: string
format: uuid
required:
- id
- preset
- memory_mb
- deployment_id
AnonKey:
type: object
properties:
id:
type: string
format: uuid
project_id:
type: string
format: uuid
name:
type: string
key_value:
type: string
description: JWT token - use this in frontend Authorization header
permissions:
type: array
items:
type: string
description: |
Permissions granted to this anon key.
Auth permissions: auth.signup, auth.signin, auth.refresh, auth.logout, auth.password_reset, auth.confirm_email, auth.resend_confirmation
Storage permissions: storage.upload, storage.download, storage.list, storage.delete
Realtime permissions: realtime.connect, realtime.subscribe, realtime.publish
Functions permissions: functions.invoke
example:
- auth.signup
- auth.signin
- auth.refresh
- auth.logout
is_default:
type: boolean
description: Whether this is the project's configured default anon key. Only one key per project can be default.
created_at:
type: string
format: date-time
required:
- id
- name
- key_value
AuthConfig:
type: object
properties:
project_id:
type: string
format: uuid
access_token_lifetime:
type: integer
description: Access token lifetime in seconds
default: 3600
refresh_token_lifetime:
type: integer
description: Refresh token lifetime in seconds
default: 2592000
inactivity_timeout:
type: integer
description: Force re-login after inactivity (seconds, 0=never)
default: 0
max_session_duration:
type: integer
description: Force re-login after duration (seconds, 0=never)
default: 0
min_password_length:
type: integer
minimum: 15
maximum: 128
default: 15
description: Configured minimum password length in Unicode characters.
password_policy:
$ref: '#/components/schemas/AuthPasswordPolicy'
require_uppercase:
type: boolean
default: false
require_lowercase:
type: boolean
default: false
require_numbers:
type: boolean
default: false
require_special_chars:
type: boolean
default: false
enable_signup:
type: boolean
description: Master switch - allow new user signups via ANY provider
default: true
enable_email_password:
type: boolean
description: Enable email/password authentication as a provider
default: true
rate_limit_signup:
type: integer
description: Signups per hour per IP
default: 100
rate_limit_signin:
type: integer
description: Signins per hour per IP
default: 100
rate_limit_token_refresh:
type: integer
description: Refreshes per hour per IP
default: 1000
cors_enabled:
type: boolean
default: false
cors_allowed_origins:
type: array
items:
type: string
example:
- https://myapp.com
- http://localhost:3000
enable_anonymous_signins:
type: boolean
description: Allow creating users without email/password
default: false
allowed_email_domains:
type: array
description: |
Email domains allowed to create users in this project. Applies to
email/password signup, OAuth/SSO signup, anonymous conversion, and
email changes. Empty (the default) allows every domain.
Entries are stored normalized (lowercase, no `@` prefix) and match
the domain part exactly: `domain1.com` does not cover
`mail.domain1.com`. Signups from other domains are rejected with
403, and `allowed_email_domains_mode` decides whether sign-in is
covered as well.
The allowlist is a SUPERAGENT feature to configure and to enforce. A
downgrade parks it: the domains are still returned here and stop
being applied until the project is back on SUPERAGENT.
items:
type: string
example:
- domain1.com
- domain2.com
allowed_email_domains_mode:
type: string
description: |
How far `allowed_email_domains` reaches. `signup` only gates account
creation, so accounts that predate the list keep signing in.
`signup_and_signin` also refuses to issue a session to an account
whose domain is not listed. `disabled` keeps the list without
enforcing it.
enum:
- disabled
- signup
- signup_and_signin
default: signup
platform_token_ttl:
type: integer
description: TTL in seconds for platform tokens minted via `/auth/platform/exchange`
default: 2592000
allow_password_reset:
type: boolean
description: Enable forgot password flow
default: true
password_reset_timeout:
type: integer
description: Recovery token expiry in seconds
default: 3600
max_password_history:
type: integer
description: Number of previous passwords to remember (0=disabled)
default: 0
cors_allow_credentials:
type: boolean
description: Allow credentials in CORS requests
default: true
cors_max_age:
type: integer
description: CORS preflight cache duration (seconds)
default: 86400
require_email_confirmation:
type: boolean
description: Require users to confirm email before sign-in. Can only be true when email_enabled is true.
default: false
email_confirmation_timeout:
type: integer
description: Email confirmation token expiry in seconds.
default: 86400
auto_link_verified_oauth:
type: boolean
description: Link a verified OAuth identity to an existing confirmed account with the same email instead of returning a conflict. Requires require_email_confirmation to be true.
default: false
email_enabled:
type: boolean
description: Enable transactional email sending (confirmation, reset, change notifications). Must be true when require_email_confirmation is true.
default: false
email_from_address:
type: string
email_from_name:
type: string
smtp_host:
type: string
smtp_port:
type: integer
default: 587
smtp_username:
type: string
smtp_password_configured:
type: boolean
description: Whether an SMTP password is configured. The password itself is never returned.
default: false
smtp_use_tls:
type: boolean
default: true
email_confirmation_subject:
type: string
email_password_reset_subject:
type: string
email_password_changed_subject:
type: string
managed_auth_enabled:
type: boolean
description: Enables project-hosted managed auth pages.
default: false
post_auth_redirect_url:
type: string
description: Default redirect target after successful hosted auth.
allowed_redirect_urls:
type: array
description: Redirect allowlist used to validate post_auth_redirect_url and post_logout_redirect_url.
items:
type: string
post_logout_redirect_url:
type: string
description: Redirect target after logout from hosted pages.
device_verification_url:
type: string
description: |
Optional override for the device-authorization verification page.
When set, POST /auth/device/authorize returns this URL (with the
user_code) as verification_uri/verification_uri_complete instead of
the built-in managed device page. Lets a CLI surface the project's
own RFC 8628 approval page. Empty falls back to the managed page.
example: https://app.acme.com/device
required:
- password_policy
AuthInsightsInterval:
type: string
enum:
- day
- week
- month
AuthInsightsResponse:
type: object
additionalProperties: false
properties:
project_id:
type: string
format: uuid
observed_at:
type: string
format: date-time
window:
$ref: '#/components/schemas/AuthInsightsWindow'
summary:
$ref: '#/components/schemas/AuthInsightsSummary'
series:
type: array
items:
$ref: '#/components/schemas/AuthInsightsSeriesPoint'
required:
- project_id
- observed_at
- window
- summary
- series
AuthInsightsSeriesPoint:
type: object
additionalProperties: false
properties:
bucket_start:
type: string
format: date
signups:
type: integer
format: int64
minimum: 0
description: Accounts created during the bucket.
signins:
type: integer
format: int64
minimum: 0
description: Successful session creations during the bucket.
is_partial:
type: boolean
description: Whether the requested window or observation time clips this bucket.
required:
- bucket_start
- signups
- signins
- is_partial
AuthInsightsSummary:
type: object
additionalProperties: false
properties:
total_users:
type: integer
format: int64
minimum: 0
description: Current auth-user count, matching the auth-user list total.
active_users_30d:
type: integer
format: int64
minimum: 0
description: Users with a successful session creation or refresh in the trailing 30 days since activity collection was deployed.
required:
- total_users
- active_users_30d
AuthInsightsWindow:
type: object
additionalProperties: false
properties:
from:
type: string
format: date
to:
type: string
format: date
interval:
$ref: '#/components/schemas/AuthInsightsInterval'
required:
- from
- to
- interval
AuthHostedPage:
type: object
properties:
id:
type: string
format: uuid
project_id:
type: string
format: uuid
page_type:
$ref: '#/components/schemas/HostedAuthPageType'
html:
type: string
description: HTML content for this page type.
css:
type: string
description: CSS content for this page type.
created_at:
type: string
format: date-time
updated_at:
type: string
format: date-time
AuthPageAppearanceResponse:
type: object
required:
- theme
- layouts
- customisation_allowed
- parked
- defaults
- options
properties:
theme:
$ref: '#/components/schemas/AuthPageTheme'
layouts:
type: object
additionalProperties:
$ref: '#/components/schemas/AuthPageLayout'
customisation_allowed:
type: boolean
parked:
type: object
additionalProperties:
type: boolean
description: Per-page saved-but-not-live state.
defaults:
$ref: '#/components/schemas/AuthPageAppearanceDefaults'
options:
$ref: '#/components/schemas/AuthPageAppearanceOptions'
AuthPageDensity:
type: string
enum:
- compact
- comfortable
- spacious
AuthPageFont:
type: string
enum:
- system
- humanist
- geometric
- slab
- mono
AuthPageLayout:
type: string
enum:
- centered
- split-left
- split-right
AuthPageRadius:
type: string
enum:
- none
- small
- medium
- large
AuthPageScale:
type: string
enum:
- small
- default
- large
AuthPageTheme:
type: object
additionalProperties: false
required:
- version
- colors
- font
- scale
- density
- radius
properties:
version:
type: integer
enum:
- 1
colors:
$ref: '#/components/schemas/AuthPageThemeColors'
font:
$ref: '#/components/schemas/AuthPageFont'
scale:
$ref: '#/components/schemas/AuthPageScale'
density:
$ref: '#/components/schemas/AuthPageDensity'
radius:
$ref: '#/components/schemas/AuthPageRadius'
AuthHostedPageResponse:
type: object
required:
- page
- defaults
- runtime
properties:
page:
allOf:
- $ref: '#/components/schemas/AuthHostedPage'
nullable: true
description: The saved page, or null when the project has not customized this page type yet.
defaults:
$ref: '#/components/schemas/AuthHostedPageDefaults'
runtime:
$ref: '#/components/schemas/AuthHostedPageRuntime'
AuthIdentity:
type: object
description: |
A real email identity owned by the account. One account can own multiple
identities (for example a work email plus a personal email linked via OAuth).
properties:
id:
type: string
format: uuid
description: Unique identity identifier
email:
type: string
format: email
description: The email address this identity represents
email_verified:
type: boolean
description: Whether ownership of this email has been verified
is_primary:
type: boolean
description: Whether the account's primary sign-in method resolves to this identity
created_at:
type: string
format: date-time
required:
- id
- email
- email_verified
- is_primary
- created_at
AuthIdentitiesResponse:
type: object
properties:
identities:
type: array
items:
$ref: '#/components/schemas/AuthIdentity'
required:
- identities
AuthMethodSummary:
type: object
description: |
A single sign-in method the account owns (password, an OAuth provider, or an
active anonymous method). `is_primary` reflects the account's primary_method_id.
properties:
id:
type: string
format: uuid
description: Unique method identifier
type:
type: string
x-go-type: string
description: The kind of sign-in method
enum:
- password
- oauth
- anonymous
provider:
type: string
description: OAuth provider name; present only when type is oauth
example: google
identity_id:
type: string
description: |
The identity this method signs in to — a UUID for password/oauth methods,
empty for anonymous methods.
email:
type: string
description: The email of the method's identity (empty for anonymous)
is_primary:
type: boolean
description: Whether this is the account's primary sign-in method
last_used_at:
type: string
format: date-time
description: When this method was last used to sign in, if ever
created_at:
type: string
format: date-time
updated_at:
type: string
format: date-time
required:
- id
- type
- identity_id
- email
- is_primary
- created_at
- updated_at
AuthMethodsResponse:
type: object
properties:
methods:
type: array
items:
$ref: '#/components/schemas/AuthMethodSummary'
required:
- methods
AuthPasswordPolicy:
type: object
additionalProperties: false
description: Effective backend-enforced password policy.
properties:
effective_min_length:
type: integer
minimum: 15
maximum: 128
description: Effective minimum password length in Unicode characters.
min_configurable_length:
type: integer
minimum: 15
maximum: 15
description: Lowest minimum password length accepted by the auth configuration endpoint.
max_length:
type: integer
minimum: 128
maximum: 128
description: Maximum password length in Unicode characters.
require_uppercase:
type: boolean
description: Whether passwords must contain an ASCII uppercase letter (A-Z).
require_lowercase:
type: boolean
description: Whether passwords must contain an ASCII lowercase letter (a-z).
require_numbers:
type: boolean
description: Whether passwords must contain an ASCII digit (0-9).
require_special_chars:
type: boolean
description: Whether passwords must contain one of the backend-supported special characters.
compromised_passwords_rejected:
type: boolean
description: Whether common and known-compromised passwords are rejected by the backend.
required:
- effective_min_length
- min_configurable_length
- max_length
- require_uppercase
- require_lowercase
- require_numbers
- require_special_chars
- compromised_passwords_rejected
AuthSession:
type: object
description: An authentication session for a user
properties:
id:
type: string
format: uuid
description: Unique session identifier
user_id:
type: string
format: uuid
description: The user this session belongs to
provider:
type: string
description: Authentication provider used to create this session
enum:
- email
- google
- github
- microsoft
- apple
- anonymous
example: email
user_agent:
type: string
description: Browser/device user agent string
example: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)
ip_address:
type: string
description: IP address of the client when the session was created
example: 192.168.1.1
last_ip_address:
type: string
description: IP address of the most recent activity (token refresh)
example: 192.168.1.100
expires_at:
type: string
format: date-time
description: When this session expires
last_activity_at:
type: string
format: date-time
description: Last activity timestamp
session_started_at:
type: string
format: date-time
description: When the session was created
is_active:
type: boolean
description: Whether the session is currently active (not expired)
is_current:
type: boolean
description: Whether this is the session making the current request
created_at:
type: string
format: date-time
updated_at:
type: string
format: date-time
required:
- id
- user_id
- provider
- expires_at
- is_active
- is_current
AuthSignupResponse:
type: object
description: |
Uniform, session-less response returned by POST /auth/signup. It carries no
tokens and no user object, and is identical for a new account and for an
already-registered email (anti-enumeration). Clients obtain a session with a
subsequent POST /auth/signin.
properties:
confirmation_required:
type: boolean
description: |
Whether the project requires email confirmation. Reflects project config
only (identical for a new and an existing email), so it leaks nothing about
account existence.
message:
type: string
description: Human-readable acknowledgement.
required:
- confirmation_required
- message
AuthTokenResponse:
type: object
properties:
access_token:
type: string
description: JWT access token (expires after configured lifetime)
token_type:
type: string
example: bearer
expires_in:
type: integer
description: Access token lifetime in seconds
refresh_token:
type: string
x-go-type-skip-optional-pointer: true
description: |
Long-lived token for getting new access tokens. Omitted when the
request uses eligible HttpOnly cookie session storage.
user:
$ref: '#/components/schemas/AuthUser'
required:
- access_token
- token_type
- expires_in
- user
AuthUser:
type: object
properties:
id:
type: string
format: uuid
project_id:
type: string
format: uuid
email:
type: string
format: email
email_confirmed:
type: boolean
user_metadata:
type: object
additionalProperties: true
description: User-editable metadata
app_metadata:
type: object
additionalProperties: true
description: Application-controlled metadata (read-only for users)
avatar_url:
type: string
format: uri
description: User avatar URL (from OAuth provider or manually set)
status:
type: string
enum:
- active
- banned
- deleted
banned_until:
type: string
format: date-time
nullable: true
description: When temporary ban expires (null if not banned or permanent)
last_sign_in_at:
type: string
format: date-time
created_at:
type: string
format: date-time
updated_at:
type: string
format: date-time
required:
- id
- email
- status
BanUserResponse:
type: object
description: Response when banning a user
properties:
message:
type: string
example: User banned until 2026-12-31T23:59:59Z
user_id:
type: string
format: uuid
email:
type: string
format: email
status:
type: string
enum:
- banned
banned_until:
type: string
format: date-time
nullable: true
description: When the ban expires (null for permanent ban)
required:
- message
- user_id
- email
- status
BatchFunctionDeployFailure:
type: object
properties:
name:
type: string
function_id:
type: string
format: uuid
operation:
type: string
enum:
- deploy
- update
error:
type: string
required:
- name
- error
BatchFunctionDeployResponse:
type: object
properties:
batch_id:
type: string
format: uuid
data:
type: array
description: Functions whose deployment workflows were started successfully
items:
$ref: '#/components/schemas/Function'
failed:
type: array
description: Functions that failed before their workflow started. Successful functions are left running; failed new functions are deleted and failed updates are rolled back where possible.
items:
$ref: '#/components/schemas/BatchFunctionDeployFailure'
required:
- batch_id
- data
CompleteUploadSessionResponse:
type: object
description: Response when completing an upload
properties:
object:
$ref: '#/components/schemas/StorageObject'
CreateDatabaseBackupRequest:
type: object
properties:
name:
type: string
description: |
Backup name, unique within the database. Names beginning with
`volcano-` are reserved for the platform's own snapshots.
pattern: ^[a-z0-9][a-z0-9_-]{0,62}$
maxLength: 63
example: before_migration
required:
- name
CreateDatabaseBranchRequest:
type: object
properties:
name:
type: string
description: Branch name (must be unique within the parent database)
pattern: ^[a-z0-9_]+$
maxLength: 64
example: feature_checkout
ttl_seconds:
type: integer
format: int64
minimum: 3600
maximum: 2592000
description: |
How long the branch should live, between one hour and 30 days.
Defaults to 7 days when omitted.
example: 86400
required:
- name
CreateDatabaseRestoreRequest:
type: object
description: |
Names what to restore. Supply exactly one of `backup_name` or
`restore_to`.
properties:
backup_name:
type: string
minLength: 1
maxLength: 128
description: |
A backup of this database to restore, exactly as returned by the list
endpoint.
Deliberately looser than the names you can create, like the backup
path parameter: a backup made by a schedule is named for you, so
restoring one accepts any name a backup can have.
example: before_migration
restore_to:
type: string
format: date-time
description: |
A point in time to restore to, which must fall inside the
`restore_window` reported when listing backups.
example: '2026-01-15T09:30:00Z'
CreateDatabaseRequest:
type: object
description: |
Create a new PostgreSQL database. Volcano automatically sets up:
- Auth helpers (auth.uid(), auth.email(), auth.role())
- Database roles (anon for unauthenticated, authenticated for signed-in users)
- Secure multi-tenant isolation
- Ready for Row-Level Security
properties:
name:
type: string
description: Database name (must be unique within project)
pattern: ^[a-z0-9_]+$
maxLength: 64
example: my_database
region:
type: string
description: |
Region for database hosting. The accepted values are the regions this
environment runs in, so read them from `GET /databases/regions` rather
than hardcoding a list. A region the environment does not offer is
rejected with 400.
example: aws-us-east-1
pg_version:
type: string
description: PostgreSQL major version
example: '16'
enum:
- '15'
- '16'
database_type:
type: string
description: |
Compute size tier (optional, defaults to volcano-db-xs).
Determines autoscaling limits for the database.
enum:
- volcano-db-xs
- volcano-db-s
- volcano-db-m
- volcano-db-l
- volcano-db-xl
- volcano-db-2xl
default: volcano-db-xs
example: volcano-db-xs
required:
- name
- region
- pg_version
CreateEmailTemplateRequest:
type: object
properties:
template_type:
type: string
enum:
- welcome
- confirmation
- password_reset
- password_changed
description: Type of email template
subject:
type: string
description: Email subject line
example: Confirm your email
html_body:
type: string
description: |
HTML template body. Available placeholders:
- {{.Token}} - The confirmation/reset token
- {{.ProjectName}} - The project name
- {{.Email}} - User's email address
text_body:
type: string
description: Plain text template body (same placeholders as HTML)
required:
- template_type
- subject
- html_body
- text_body
CreateFrontendCustomDomainRequest:
type: object
additionalProperties: false
properties:
domain:
type: string
maxLength: 253
description: 'Fully-qualified domain name (hostname only, no scheme/path). Managed TLS (`tls.mode: managed`) accepts at most 219 characters; BYOC accepts 253.'
example: app.example.com
tls:
$ref: '#/components/schemas/FrontendCustomDomainTLSConfig'
required:
- domain
- tls
CreateFunctionSchedulerRequest:
type: object
required:
- name
- schedule
properties:
name:
type: string
maxLength: 200
enabled:
type: boolean
default: true
schedule:
$ref: '#/components/schemas/ScheduleRequest'
payload:
type: object
additionalProperties: true
regions:
type: array
description: Optional single explicit deployed region. If omitted, the scheduler chooses one deployed region and invokes according to the cron expression.
maxItems: 1
items:
type: string
CreateOAuthConfigRequest:
type: object
required:
- provider
properties:
provider:
type: string
enum:
- google
- github
- microsoft
- apple
- device
example: google
client_id:
type: string
example: 123456789.apps.googleusercontent.com
description: Required for non-device providers. Must not be provided for `provider=device`; server always auto-generates it.
client_secret:
type: string
example: GOCSPX-abc123def456
description: Required for non-device providers. Must not be provided for `provider=device`; server always auto-generates it.
redirect_url:
type: string
description: Required for non-device providers. Not used for `provider=device`.
format: uri
example: https://yourapp.com/auth/callback
scopes:
type: array
items:
type: string
example:
- openid
- email
- profile
description: Optional for non-device providers, uses provider defaults if omitted. Not used for `provider=device`.
CreateProjectRequest:
type: object
description: Request to create a new project
properties:
name:
type: string
description: |
Project name (must be unique).
Can only contain letters, numbers, underscores, and hyphens.
pattern: ^[A-Za-z0-9_-]+$
minLength: 1
maxLength: 255
example: my-awesome-app
all_regions:
type: boolean
description: |
Optional region policy.
- `true` (default): project functions deploy to all configured regions
- `false`: project deploys only to `selected_regions`
default: true
selected_regions:
type: array
items:
type: string
description: |
Optional region subset. Requires `all_regions=false`.
Region names must be a subset of platform `AWS_REGIONS`.
example:
- us-east-1
- us-west-2
required:
- name
CreateStorageBucketRequest:
type: object
properties:
name:
type: string
description: Bucket name (alphanumeric, dashes, underscores)
pattern: ^[a-zA-Z0-9_-]+$
minLength: 1
maxLength: 64
file_size_limit:
type: integer
format: int64
description: Maximum file size in bytes
allowed_mime_types:
type: array
items:
type: string
description: Allowed MIME types (e.g., ["image/png", "image/jpeg"])
required:
- name
CreateStoragePolicyRequest:
type: object
properties:
name:
type: string
description: Policy name
operation:
type: string
enum:
- SELECT
- INSERT
- UPDATE
- DELETE
description: Operation this policy applies to
definition:
type: string
description: Policy expression
required:
- name
- operation
- definition
CreateUploadSessionRequest:
type: object
description: Request to create a resumable upload session
properties:
object_path:
type: string
description: Target file path within the bucket
example: videos/large-file.mp4
content_type:
type: string
description: MIME type of the file
example: video/mp4
total_size:
type: integer
format: int64
description: Total file size in bytes (max 5TB)
minimum: 1
maximum: 5497558138880
example: 5368709120
part_size:
type: integer
format: int64
description: 'Part size in bytes (default: 25MB, min: 5MB, max: 25MB)'
minimum: 5242880
maximum: 26214400
example: 26214400
required:
- object_path
- content_type
- total_size
CreateUploadSessionResponse:
type: object
description: Response when creating an upload session
properties:
session_id:
type: string
description: Upload session ID
example: session-abc123
part_size:
type: integer
format: int64
description: Actual part size to use
example: 26214400
total_parts:
type: integer
description: Number of parts to upload
example: 52
expires_at:
type: string
format: date-time
description: When the session expires (7 days from creation)
example: '2024-01-22T10:30:00Z'
CreateVariableRequest:
type: object
properties:
shared:
type: boolean
description: Include this name in the project's shared function variables. Omission preserves existing membership; new variables default to true for legacy clients. Send false explicitly to create a non-shared variable.
name:
type: string
minLength: 1
maxLength: 256
pattern: ^[a-zA-Z_][a-zA-Z0-9_]*$
value:
type: string
required:
- name
- value
Database:
type: object
description: |
PostgreSQL database with automatic scalability and security features.
properties:
id:
type: string
format: uuid
project_id:
type: string
format: uuid
name:
type: string
description: Database name
pattern: ^[a-z0-9_]+$
maxLength: 64
status:
type: string
enum:
- provisioning
- active
- failed
- restoring
- deleting
description: |
Database status. `restoring` means a restore is replacing the
database's data: it does not accept connections, and the operations
that would race the restore are rejected until it finishes. Its
branches keep serving throughout.
provisioning_started_at:
type: string
format: date-time
description: Timestamp when the current provisioning phase started
connection_string:
type: string
description: |
Secure PostgreSQL connection URI for your database.
The database is identified by the globally-unique username
(`volcano_client_{database_id}`) already in this URI; the
`application_name` parameter only selects the access mode:
- `volcano_full_access` — Full admin access (DDL, migrations)
- `volcano_user_access:{user_id}` — User impersonation (RLS enforced)
- `volcano_user_access` — Anonymous access (anon role, RLS enforced)
region:
type: string
description: Region where the database is hosted
example: aws-us-east-1
pg_version:
type: string
description: PostgreSQL major version
example: '16'
database_type:
type: string
description: |
Database size tier that determines available RAM and scaling limits.
enum:
- volcano-db-xs
- volcano-db-s
- volcano-db-m
- volcano-db-l
- volcano-db-xl
- volcano-db-2xl
example: volcano-db-xs
storage_bytes:
type: integer
format: int64
minimum: 0
description: |
Latest observed storage for this database, in bytes: its own on-disk
size, plus what each branch has diverged from it, plus what its
backups cost to hold. This is the figure the storage allowance is
enforced against, and the stats endpoint breaks it down. A
point-in-time gauge recorded by a background pass, so it may be
absent until the database has been sampled, and it can trail the
stats endpoint's `current_storage_bytes`, which measures on request.
Summing the latest samples for every database in a project produces
the project's "Database Storage (Bytes)" usage gauge. Populated on
database list responses; single-database responses omit it.
last_invoked_at:
type: string
format: date-time
description: Most recent request timestamp for this database
created_at:
type: string
format: date-time
updated_at:
type: string
format: date-time
required:
- id
- project_id
- name
- status
- created_at
- updated_at
DatabaseBackup:
type: object
description: |
A point-in-time copy of a database, kept by the storage provider and
restorable in place.
Backups cover the database itself, not its branches. Restoring one
replaces the database's data and keeps its connection string.
properties:
name:
type: string
description: |
Backup name, unique within the database. Backups you create are
named by you; scheduled backups are named by the storage provider.
source:
type: string
enum:
- manual
- scheduled
description: |
Whether the backup was requested explicitly or produced by the
backup schedule. Only `manual` backups count against the plan's
backup allowance.
size_bytes:
type: integer
format: int64
minimum: 0
description: |
Storage the backup occupies. Absent until the provider has costed
it, which takes a few minutes after the backup is taken; absent is
not the same as empty.
expires_at:
type: string
format: date-time
description: |
When the backup is deleted automatically, from the plan's retention.
Absent means it is kept until deleted explicitly.
created_at:
type: string
format: date-time
description: The point in time the backup captures.
required:
- name
- source
- created_at
DatabaseBackupList:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/DatabaseBackup'
restore_window:
$ref: '#/components/schemas/DatabaseRestoreWindow'
required:
- data
DatabaseBackupSchedule:
type: object
description: |
The database's automated backup schedule. An empty list means no
scheduled backups; sending one clears the schedule.
properties:
entries:
type: array
items:
$ref: '#/components/schemas/DatabaseBackupScheduleEntry'
required:
- entries
DatabaseBackupScheduleEntry:
type: object
description: One recurrence of the automated backup schedule.
properties:
frequency:
type: string
enum:
- daily
- weekly
- monthly
hour:
type: integer
minimum: 0
maximum: 23
description: Hour of the day in UTC.
day:
type: integer
minimum: 1
maximum: 28
description: |
Day of the week (1-7, Monday to Sunday) for a weekly schedule, or day
of the month (1-28) for a monthly one. Required for both, ignored for
a daily schedule. Monthly stops at 28 so the schedule fires in every
month.
retention_seconds:
type: integer
format: int64
minimum: 3600
description: |
How long each backup from this recurrence is kept. Clamped to the
plan's retention, and defaulted to it when omitted.
required:
- frequency
- hour
DatabaseBranch:
type: object
description: |
A copy-on-write fork of a database, for development and testing.
A branch starts as an exact copy of its parent's data and diverges from
there. It has its own connection string and its own credential, so a
branch password cannot reach the parent.
Every branch expires. `expires_at` is a hard deadline: once it passes the
branch stops accepting connections and is deleted. Use `PATCH` to extend
a branch you are still working on.
properties:
id:
type: string
format: uuid
database_id:
type: string
format: uuid
description: The parent database this branch was forked from.
project_id:
type: string
format: uuid
name:
type: string
description: Branch name, unique within the parent database.
pattern: ^[a-z0-9_]+$
maxLength: 64
status:
type: string
enum:
- provisioning
- active
- failed
- deleting
description: |
Branch status. A new branch starts `provisioning` and is not
connectable until it reports `active`; poll this endpoint until it
does. `connection_string` is only present while `active`.
`provisioning` also covers a branch being rebuilt after a `reset`,
and a build that is between retries, so it is the status to keep
waiting on. `failed` is terminal: it means the platform gave up, and
the branch will not become `active` on its own.
connection_string:
type: string
description: |
PostgreSQL connection URI for this branch. Present only while the
branch is `active`.
The URI carries the branch's own globally-unique username and
password; `application_name` selects the access mode exactly as it
does for the parent database:
- `volcano_full_access` — Full admin access (DDL, migrations)
- `volcano_user_access:{user_id}` — User impersonation (RLS enforced)
- `volcano_user_access` — Anonymous access (anon role, RLS enforced)
ttl_seconds:
type: integer
format: int64
minimum: 1
description: |
The lifetime the branch was created with. Resetting a branch re-arms
this same duration, so a reset never shortens a branch's remaining
life.
expires_at:
type: string
format: date-time
description: |
When the branch stops serving connections and becomes eligible for
deletion. Enforced on the connection path, so it holds even if
reclamation is delayed.
storage_bytes:
type: integer
format: int64
minimum: 0
description: |
Bytes this branch has diverged from its parent, which is what a
branch actually costs. Shared pages are not counted twice. Counts
against the parent database's storage allowance. Absent until the
branch has been sampled.
last_invoked_at:
type: string
format: date-time
description: Most recent request timestamp for this branch
created_at:
type: string
format: date-time
updated_at:
type: string
format: date-time
required:
- id
- database_id
- project_id
- name
- status
- ttl_seconds
- expires_at
- created_at
- updated_at
DatabaseBranchList:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/DatabaseBranch'
required:
- data
DatabaseBranchStorage:
type: object
description: One branch's contribution to its parent database's storage.
properties:
id:
type: string
format: uuid
name:
type: string
description: Branch name
storage_bytes:
type: integer
format: int64
minimum: 0
description: |
Bytes this branch has diverged from its parent. Pages the branch
still shares with the parent are not counted, so this is what the
branch actually adds to the total rather than its apparent size.
required:
- id
- name
- storage_bytes
DatabaseSelectRequest:
type: object
properties:
table:
type: string
description: Table name to query
example: posts
select:
type: array
items:
type: string
description: Columns to select (omit for *)
example:
- id
- title
- content
- created_at
filters:
type: array
items:
$ref: '#/components/schemas/DatabaseQueryFilter'
description: WHERE conditions (combined with AND)
example:
- column: status
operator: eq
value: published
- column: views
operator: gt
value: 100
order:
type: array
items:
$ref: '#/components/schemas/DatabaseQueryOrder'
description: ORDER BY clauses
example:
- column: created_at
ascending: false
limit:
type: integer
minimum: 1
maximum: 1000
description: Maximum rows to return
example: 10
offset:
type: integer
minimum: 0
description: Number of rows to skip (for pagination)
example: 0
required:
- table
DatabaseInsertRequest:
type: object
properties:
table:
type: string
description: Table name
example: posts
values:
type: object
additionalProperties: true
description: Column values to insert
example:
title: My New Post
content: This is the content
status: draft
required:
- table
- values
DatabaseUpdateRequest:
type: object
properties:
table:
type: string
description: Table name
example: posts
values:
type: object
additionalProperties: true
description: Column values to update
example:
title: Updated Title
status: published
filters:
type: array
minItems: 1
items:
$ref: '#/components/schemas/DatabaseQueryFilter'
description: |
WHERE conditions for which rows to update. At least one filter is
required; a filterless update is rejected to avoid rewriting every
row.
example:
- column: id
operator: eq
value: post-uuid
required:
- table
- values
- filters
DatabaseDeleteRequest:
type: object
properties:
table:
type: string
description: Table name
example: posts
filters:
type: array
minItems: 1
items:
$ref: '#/components/schemas/DatabaseQueryFilter'
description: WHERE conditions (required for safety)
example:
- column: id
operator: eq
value: post-uuid
required:
- table
- filters
DatabaseQueryResult:
type: object
description: |
Rows returned by a data API request. RLS-filtered unless the request was
made with a service key.
properties:
data:
type: array
items:
type: object
additionalProperties: true
description: Result rows
count:
type: integer
description: Number of rows returned
DatabaseRestore:
type: object
description: |
A restore of a database, either from a named backup or to a point in
time. Restores run in the background and take longer than a request, so
the database is unavailable until this reports `completed`.
properties:
id:
type: string
format: uuid
database_id:
type: string
format: uuid
project_id:
type: string
format: uuid
kind:
type: string
enum:
- snapshot
- point_in_time
description: |
Whether the restore targets a named backup or an arbitrary point in
time. Both replace the database's data in place.
status:
type: string
enum:
- pending
- running
- completed
- failed
- exhausted
description: |
Restore status. `pending` and `running` both mean the restore is
still in flight and the database is not connectable; an attempt that
fails with tries left goes back to `pending`. `failed` and
`exhausted` both mean Volcano gave up: the database is left `failed`
if its data may already have been replaced, and `active` if the
restore never started — a backup that no longer exists at the
provider ends the restore without touching the database. A restore
cannot be cancelled once it starts.
backup_name:
type: string
description: |
The backup restored, kept even if that backup is later deleted.
Absent for a point-in-time restore.
restore_to:
type: string
format: date-time
description: The point in time restored to. Absent for a backup restore.
error:
type: string
description: Why the most recent attempt failed, when one has.
completed_at:
type: string
format: date-time
created_at:
type: string
format: date-time
updated_at:
type: string
format: date-time
required:
- id
- database_id
- project_id
- kind
- status
- created_at
- updated_at
DatabaseRestoreList:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/DatabaseRestore'
required:
- data
DatabaseRestoreWindow:
type: object
description: |
The span a point-in-time restore may target. Absent from the response
when the owner's plan does not include point-in-time restore, and while
the storage provider has no history window in place yet — briefly the
case after an upgrade, since the window is applied asynchronously. The
window is read from the provider rather than from the plan, so it never
advertises a point a restore could not actually reach.
properties:
earliest_restore_at:
type: string
format: date-time
description: |
The oldest point that can still be restored. Moves forward
continuously as history ages out, so treat it as a lower bound at
the moment it was read rather than a fixed value.
latest_restore_at:
type: string
format: date-time
description: The most recent point that can be restored, which is now.
DatabaseStats:
type: object
properties:
current_storage_bytes:
type: integer
format: int64
minimum: 0
description: |
On-disk size right now, in bytes: the database itself, plus every
branch's divergence from it, plus what its backups cost to hold. This
is the figure the storage allowance is enforced against. `branches`
and `backup_storage_bytes` break it down.
current_storage_mb:
type: number
format: double
minimum: 0
description: '`current_storage_bytes` expressed in megabytes.'
branches:
type: array
description: |
Per-branch contribution to `current_storage_bytes`. Empty when the
database has no branches. A branch that has not diverged from its
parent contributes nothing.
items:
$ref: '#/components/schemas/DatabaseBranchStorage'
backup_storage_bytes:
type: integer
format: int64
minimum: 0
description: |
What this database's backups contribute to `current_storage_bytes`.
A backup taken on request is charged as a full copy of the database
as it was at that moment, so two backups of a 2 GB database are 4 GB.
A backup schedule is charged its first snapshot in full and each
later one only for the storage it adds. Deleting a backup releases
its storage immediately.
Sampled from the provider rather than measured live, so it can lag a
change by a few minutes, and a backup taken seconds ago may not be
costed yet. Zero on a plan without backups.
storage_bytes:
type: integer
format: int64
description: Total storage used in bytes (data + WAL)
data_written_bytes:
type: integer
format: int64
description: Total data written in bytes
data_transfer_bytes:
type: integer
format: int64
description: Total data transferred in bytes
compute_time_seconds:
type: number
format: double
description: Total CPU seconds consumed
active_time_seconds:
type: number
format: double
description: Total active compute time in seconds
time_range:
type: string
description: Time range of the metrics (e.g., "2024-01-01T00:00:00Z to 2024-01-02T00:00:00Z")
granularity:
type: string
enum:
- hourly
- daily
- monthly
description: Granularity of the aggregated metrics
required:
- current_storage_bytes
- current_storage_mb
- backup_storage_bytes
- storage_bytes
- data_written_bytes
- data_transfer_bytes
- compute_time_seconds
- active_time_seconds
DatabaseQueryPerformanceResponse:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/DatabaseQueryPerformanceItem'
required:
- data
UpdateDatabaseBranchRequest:
type: object
description: Replace the branch's lifetime and restart its countdown from now.
properties:
ttl_seconds:
type: integer
format: int64
minimum: 3600
maximum: 2592000
description: The new lifetime, between one hour and 30 days.
example: 86400
required:
- ttl_seconds
DeviceAuthorizationResponse:
type: object
properties:
device_code:
type: string
user_code:
type: string
verification_uri:
type: string
description: |
Browser verification URL. Points at the project's managed device
approval page served by this API:
`/projects/{projectId}/auth/hosted?action=device&anon_key=...`.
Requires the project to have managed auth enabled and a default anon
key. A custom CLI may ignore this and direct users to its own
RFC 8628-compatible page instead (see the device-auth guide).
verification_uri_complete:
type: string
description: |
Same as `verification_uri` but with the `user_code` prefilled
(`&user_code=...`). This is the URL most device clients open.
expires_in:
type: integer
interval:
type: integer
required:
- device_code
- user_code
- verification_uri
- verification_uri_complete
- expires_in
- interval
EmailTemplate:
type: object
description: Custom email template
properties:
id:
type: string
format: uuid
project_id:
type: string
format: uuid
template_type:
type: string
enum:
- welcome
- confirmation
- password_reset
- password_changed
subject:
type: string
example: Confirm your email address
html_body:
type: string
description: HTML template with placeholders
text_body:
type: string
description: Plain text template with placeholders
created_at:
type: string
format: date-time
updated_at:
type: string
format: date-time
required:
- template_type
- subject
- html_body
- text_body
Error:
type: object
properties:
error:
type: string
code:
type: string
description: Stable machine-readable error code when a specific recovery path is available.
required:
- error
ImportProvider:
type: string
enum:
- vercel
default: vercel
x-enum-varnames:
- ImportProviderVercel
ImportConnectStartResponse:
type: object
properties:
authorization_url:
type: string
required:
- authorization_url
ImportConnection:
type: object
properties:
id:
type: string
format: uuid
provider:
$ref: '#/components/schemas/ImportProvider'
account_id:
type: string
account_name:
type: string
configuration_id:
type: string
granted_scopes:
type: array
items:
type: string
status:
type: string
expires_at:
type: string
format: date-time
nullable: true
last_authenticated_at:
type: string
format: date-time
created_at:
type: string
format: date-time
updated_at:
type: string
format: date-time
required:
- id
- provider
- account_id
- account_name
- configuration_id
- granted_scopes
- status
- last_authenticated_at
- created_at
- updated_at
ImportConnectionsResponse:
type: object
properties:
connections:
type: array
items:
$ref: '#/components/schemas/ImportConnection'
required:
- connections
ImportSource:
type: object
properties:
id:
type: string
name:
type: string
account_id:
type: string
framework:
type: string
required:
- id
- name
- account_id
- framework
ImportSourcesResponse:
type: object
properties:
sources:
type: array
items:
$ref: '#/components/schemas/ImportSource'
required:
- sources
ProjectImportTarget:
type: string
enum:
- production
x-enum-varnames:
- ProjectImportTargetProduction
ProjectImportDestinationMode:
type: string
enum:
- create
x-enum-varnames:
- ProjectImportDestinationCreate
ProjectImportDisposition:
type: string
enum:
- automatic
- manual
- deferred
- unsupported
x-enum-varnames:
- ProjectImportDispositionAutomatic
- ProjectImportDispositionManual
- ProjectImportDispositionDeferred
- ProjectImportDispositionUnsupported
ProjectImportImpact:
type: string
enum:
- none
- warning
- blocking
x-enum-varnames:
- ProjectImportImpactNone
- ProjectImportImpactWarning
- ProjectImportImpactBlocking
ProjectImportReadiness:
type: string
enum:
- importable
- needs_input
- blocked
x-enum-varnames:
- ProjectImportReadinessImportable
- ProjectImportReadinessNeedsInput
- ProjectImportReadinessBlocked
ProjectImportActionCode:
type: string
enum:
- project.create
- git.connect
- frontend.configure
- variable.set
x-enum-varnames:
- ProjectImportActionProjectCreate
- ProjectImportActionGitConnect
- ProjectImportActionFrontendConfigure
- ProjectImportActionVariableSet
ProjectImportResourceKind:
type: string
enum:
- project
- git_repository
- frontend
- variable
- domain
x-enum-varnames:
- ProjectImportResourceProject
- ProjectImportResourceGitRepository
- ProjectImportResourceFrontend
- ProjectImportResourceVariable
- ProjectImportResourceDomain
ProjectImportPreflightRequest:
type: object
properties:
connection_id:
type: string
format: uuid
source_id:
type: string
minLength: 1
project_name:
type: string
maxLength: 255
pattern: ^[A-Za-z0-9_-]+$
target:
$ref: '#/components/schemas/ProjectImportTarget'
confirm_environment_variable_read:
type: boolean
default: false
description: Set to true only after the user confirms an immediately preceding disclosure that the Vercel Integration grant permits reads and writes, while this preflight reads production variable values only. When false or omitted, preflight reads variable metadata only and reports readable values as manual input.
required:
- connection_id
- source_id
- project_name
- target
ProjectImportStartRequest:
type: object
properties:
connection_id:
type: string
format: uuid
source_id:
type: string
minLength: 1
maxLength: 255
project_name:
type: string
maxLength: 255
pattern: ^[A-Za-z0-9_-]+$
target:
$ref: '#/components/schemas/ProjectImportTarget'
confirm_environment_variable_read:
type: boolean
enum:
- true
preflight_fingerprint:
type: string
pattern: ^sha256:[0-9a-f]{64}$
required:
- connection_id
- source_id
- project_name
- target
- confirm_environment_variable_read
- preflight_fingerprint
ProjectImportRunStatus:
type: string
enum:
- pending
- running
- succeeded
- failed
- superseded
x-enum-varnames:
- ProjectImportRunStatusPending
- ProjectImportRunStatusRunning
- ProjectImportRunStatusSucceeded
- ProjectImportRunStatusFailed
- ProjectImportRunStatusSuperseded
ProjectImportRun:
type: object
properties:
id:
type: string
provider:
$ref: '#/components/schemas/ImportProvider'
source_id:
type: string
destination_project_name:
type: string
resource:
$ref: '#/components/schemas/ResourceReference'
deployment:
$ref: '#/components/schemas/DeploymentReference'
status:
$ref: '#/components/schemas/ProjectImportRunStatus'
error_code:
type: string
error_message:
type: string
created_at:
type: string
format: date-time
updated_at:
type: string
format: date-time
required:
- id
- provider
- source_id
- destination_project_name
- resource
- deployment
- status
- created_at
- updated_at
ProjectImportDestination:
type: object
properties:
mode:
$ref: '#/components/schemas/ProjectImportDestinationMode'
project_name:
type: string
target:
$ref: '#/components/schemas/ProjectImportTarget'
required:
- mode
- project_name
- target
ProjectImportResource:
type: object
properties:
kind:
$ref: '#/components/schemas/ProjectImportResourceKind'
name:
type: string
source_id:
type: string
minLength: 1
description: Stable provider identifier for a scoped source resource.
scope:
type: string
minLength: 1
description: URL-encoded source scope, including target, branch, and custom environment identifiers.
required:
- kind
- name
ProjectImportAction:
type: object
properties:
code:
$ref: '#/components/schemas/ProjectImportActionCode'
resource:
$ref: '#/components/schemas/ProjectImportResource'
disposition:
$ref: '#/components/schemas/ProjectImportDisposition'
required:
- code
- resource
- disposition
ProjectImportFinding:
type: object
properties:
code:
type: string
pattern: ^(vercel|volcano|import)\.[a-z0-9_]+$
resource:
$ref: '#/components/schemas/ProjectImportResource'
disposition:
$ref: '#/components/schemas/ProjectImportDisposition'
impact:
$ref: '#/components/schemas/ProjectImportImpact'
message:
type: string
remediation:
type: string
required:
- code
- resource
- disposition
- impact
- message
- remediation
ProjectImportSummary:
type: object
properties:
automatic:
type: integer
minimum: 0
manual:
type: integer
minimum: 0
deferred:
type: integer
minimum: 0
unsupported:
type: integer
minimum: 0
warnings:
type: integer
minimum: 0
blocking:
type: integer
minimum: 0
required:
- automatic
- manual
- deferred
- unsupported
- warnings
- blocking
ProjectImportReport:
type: object
properties:
schema_version:
type: string
provider:
$ref: '#/components/schemas/ImportProvider'
source:
$ref: '#/components/schemas/ImportSource'
destination:
$ref: '#/components/schemas/ProjectImportDestination'
actions:
type: array
items:
$ref: '#/components/schemas/ProjectImportAction'
findings:
type: array
items:
$ref: '#/components/schemas/ProjectImportFinding'
summary:
$ref: '#/components/schemas/ProjectImportSummary'
readiness:
$ref: '#/components/schemas/ProjectImportReadiness'
source_fingerprint:
type: string
capability_fingerprint:
type: string
fingerprint:
type: string
generated_at:
type: string
format: date-time
required:
- schema_version
- provider
- source
- destination
- actions
- findings
- summary
- readiness
- source_fingerprint
- capability_fingerprint
- fingerprint
- generated_at
GitConnection:
type: object
properties:
id:
type: string
format: uuid
provider:
type: string
provider_user_id:
type: string
provider_login:
type: string
status:
type: string
last_authenticated_at:
type: string
format: date-time
created_at:
type: string
format: date-time
updated_at:
type: string
format: date-time
required:
- id
- provider
- provider_user_id
- provider_login
- status
- last_authenticated_at
- created_at
- updated_at
GitConnectStartResponse:
type: object
properties:
authorization_url:
type: string
required:
- authorization_url
GitConnectionsResponse:
type: object
properties:
connections:
type: array
items:
$ref: '#/components/schemas/GitConnection'
required:
- connections
GitInstallation:
type: object
properties:
id:
type: integer
format: int64
account_login:
type: string
account_type:
type: string
repository_selection:
type: string
required:
- id
- account_login
- account_type
- repository_selection
GitInstallationsResponse:
type: object
properties:
installations:
type: array
items:
$ref: '#/components/schemas/GitInstallation'
required:
- installations
GitRepository:
type: object
properties:
id:
type: integer
format: int64
description: Stable GitHub repository id (repository.id), unchanged by renames.
full_name:
type: string
default_branch:
type: string
private:
type: boolean
is_empty:
type: boolean
description: Whether the repository has no commits and can receive an initial source export.
required:
- id
- full_name
- default_branch
- private
- is_empty
GitRepositoriesResponse:
type: object
properties:
repositories:
type: array
items:
$ref: '#/components/schemas/GitRepository'
required:
- repositories
ProjectGitConnection:
type: object
properties:
repo_installation_id:
type: integer
format: int64
repo_id:
type: integer
format: int64
description: Stable GitHub repository id (repository.id), the authoritative binding.
repo_full_name:
type: string
root_directory:
type: string
production_branch:
type: string
description: The branch a push must land on to deploy. Follows the repository's GitHub default branch unless the project set its own, which a default-branch rename on GitHub then leaves alone.
updated_at:
type: string
format: date-time
required:
- repo_installation_id
- repo_id
- repo_full_name
- root_directory
- production_branch
- updated_at
ProjectGitDeploySettings:
type: object
description: 'A project''s GitHub auto-deploy settings: what a push to the connected repo''s production branch deploys. All settings are default-off.'
properties:
auto_deploy_enabled:
type: boolean
description: Whether a production-branch push triggers a deployment.
deploy_functions:
type: boolean
description: Whether the repo's functions are deployed on push.
frontend_name:
type: string
description: Name of the frontend to build and deploy on push. Omitted when no frontend is deployed. Resolved at deploy time; need not exist yet.
frontend_app_root:
type: string
description: App root (subdirectory) the frontend builds from. Omitted for the repo root.
updated_at:
type: string
format: date-time
required:
- auto_deploy_enabled
- deploy_functions
- updated_at
UpdateProjectGitDeploySettingsRequest:
type: object
description: Full replace of a project's Git auto-deploy settings.
properties:
auto_deploy_enabled:
type: boolean
deploy_functions:
type: boolean
frontend_name:
type: string
description: Frontend to deploy on push. Omit or empty to deploy no frontend.
frontend_app_root:
type: string
description: App root the frontend builds from. Requires frontend_name; omit for the repo root.
required:
- auto_deploy_enabled
- deploy_functions
ProjectLockLeaseRequest:
type: object
additionalProperties: false
properties:
ttl_seconds:
type: integer
minimum: 5
maximum: 7776000
description: |
Lease duration in seconds, from 5 seconds through 90 days, measured
from when the request is served. Renew before it elapses. A renewal
sets the new expiry outright, so a shorter TTL shortens the lease.
Renewals cannot extend an acquisition beyond its absolute 90-day
deadline.
required:
- ttl_seconds
ProjectLockLease:
type: object
additionalProperties: false
properties:
expires_at:
type: string
format: date-time
description: Advisory lease expiry timestamp in UTC.
fencing_token:
type: integer
format: int64
description: |
Monotonically increasing token for this acquisition. It rises whenever the
lock changes hands and stays the same across renewals of one lease. Pass it
to the resource you are protecting and reject any write carrying a token
lower than the highest already seen; that is what stops a displaced holder
from writing after its lease lapsed.
required:
- expires_at
- fencing_token
ProjectLockState:
type: object
additionalProperties: false
properties:
held:
type: boolean
description: |
Whether the lock is unavailable right now. False means an acquire would
succeed. It remains true during the brief grace window after expiry.
expires_at:
type: string
format: date-time
description: Advisory lease expiry timestamp in UTC. Present only when held.
fencing_token:
type: integer
format: int64
description: Current holder's fencing token. Present only when held.
required:
- held
ProjectSourceExportState:
type: object
description: The project's source of truth and any pending Git transition.
properties:
mode:
type: string
enum:
- platform
- git_exporting
- git_pending
- git
transition_started_at:
type: string
format: date-time
nullable: true
description: When source export started, cleared if an incomplete transition is canceled.
exported_at:
type: string
format: date-time
nullable: true
description: When the initial export push entered deployment, or when a transition was canceled after its commit was reserved. Once set, the one-time export is consumed.
handed_over_at:
type: string
format: date-time
nullable: true
description: When a complete production-branch deployment first proved the repository could drive the project, null until then. Once set, the repository is the project's source of truth.
required:
- mode
- transition_started_at
- exported_at
- handed_over_at
ProjectSourceExport:
type: object
description: The initial production-branch commit, and everything export could not carry.
properties:
repo_full_name:
type: string
branch:
type: string
description: The production branch that was created.
commit_sha:
type: string
file_count:
type: integer
skipped:
type: array
description: Resources whose source could not be taken, with the reason. Most often a resource that has never deployed successfully.
items:
$ref: '#/components/schemas/ProjectSourceExportSkip'
omitted:
type: array
description: Things deliberately left out of the branch.
items:
$ref: '#/components/schemas/ProjectSourceExportOmission'
required:
- repo_full_name
- branch
- commit_sha
- file_count
- skipped
- omitted
ExportProjectSourceRequest:
type: object
additionalProperties: false
properties:
production_branch:
type: string
minLength: 1
description: The currently configured production branch the user confirmed for export.
required:
- production_branch
ProjectSourceExportSkip:
type: object
properties:
kind:
type: string
description: 'The kind of resource, "function" or "frontend". Deliberately not an enum: the generated constants would collide with an existing resource-type enum and rename its members.'
name:
type: string
reason:
type: string
required:
- kind
- name
- reason
ProjectSourceExportOmission:
type: object
properties:
kind:
type: string
description: 'What was left out: migrations Volcano stores no copy of, variable values, a credential-shaped file, installed dependencies, or an archive entry a repository cannot carry.'
resource:
type: string
description: The resource it came from, empty when project-wide.
path:
type: string
required:
- kind
- resource
- path
SetProjectGitProductionBranchRequest:
type: object
properties:
production_branch:
type: string
minLength: 1
maxLength: 255
description: The branch a push must land on to deploy. Validated as a Git branch name only — it does not have to exist yet.
required:
- production_branch
ConnectProjectGitRequest:
type: object
properties:
connection_id:
type: string
format: uuid
description: The caller's user_git_connections row (see /user/git/connections).
installation_id:
type: integer
format: int64
repository_id:
type: integer
format: int64
description: Stable GitHub repository id (repository.id), the preferred selector. Either repository_id or repo_full_name is required; when both are given they must identify the same live repository.
repo_full_name:
type: string
deprecated: true
description: Deprecated selector kept for a compatibility window; prefer repository_id. Either repository_id or repo_full_name is required.
root_directory:
type: string
description: Monorepo subdirectory the project builds from. Omit for the repo root.
production_branch:
type: string
maxLength: 255
description: 'The branch a push must land on to deploy, with three cases, because this is a full replace and a read-modify-write client sends back whatever it read. Omit it to follow the repository''s GitHub default branch, which also discards a branch set earlier. Send back the branch the project already deploys from, when that is the repository''s default, and nothing changes either way — a project pinned to that branch stays pinned. Sending the default branch when the project deploys from something else returns it to following the default, including on a rebind, where a pin describes a branch chosen for the repository being left. Any other branch becomes the project''s own choice, exempt from later default-branch renames. Validated as a Git branch name only: it does not have to exist yet, so a project can be pointed at a branch about to be pushed. Changing repository and naming a branch other than the new repository''s default in one request is refused with 400, because the branch named is almost always the previous repository''s, echoed back — connect first, then set the branch.'
required:
- connection_id
- installation_id
Frontend:
type: object
properties:
id:
type: string
format: uuid
project_id:
type: string
format: uuid
name:
type: string
maxLength: 63
pattern: ^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$
framework:
type: string
enum:
- nextjs
app_root:
type: string
maxLength: 1024
description: Optional relative POSIX path from the uploaded archive root to the Next.js app that is deployed.
status:
type: string
description: |
Frontend lifecycle status. `degraded` means the regional runtime remains
available but edge synchronization exhausted its immediate retries; Volcano
retries edge recovery without rebuilding the frontend, and stops once a new
deployment is queued or the retry budget runs out, leaving the frontend
`degraded` until the next redeploy. A redeploy that fails over a serving
frontend stays `active` on the previous deployment, so `failed` means no
deployment is serving.
enum:
- provisioning
- active
- degraded
- failed
- deleting
provisioning_started_at:
type: string
format: date-time
description: Timestamp when the current provisioning phase started
deployed_regions:
type: array
items:
type: string
current_deployment_id:
type: string
format: uuid
description: Identifier of the latest frontend deployment operation
pending_deployment_id:
type: string
format: uuid
description: Newest queued deployment that will run after the current operation
site_url:
type: string
custom_domain:
type: string
description: Active custom domain hostname when configured
custom_domain_status:
type: string
description: Current custom domain lifecycle status
enum:
- pending_verification
- provisioning
- active
- detaching
- failed
- deleted
last_invoked_at:
type: string
format: date-time
created_at:
type: string
format: date-time
updated_at:
type: string
format: date-time
required:
- id
- project_id
- name
- framework
- status
- deployed_regions
- created_at
- updated_at
FrontendCustomDomainTLSConfig:
type: object
description: 'TLS for a new custom domain. With `mode: managed`, Volcano issues and renews the certificate; omit every PEM field. With `mode: byoc`, send both `certificate_pem` and `private_key_pem`, plus an optional `certificate_chain_pem`.'
additionalProperties: false
not:
anyOf:
- allOf:
- properties:
mode:
enum:
- managed
required:
- mode
- anyOf:
- required:
- certificate_pem
- required:
- private_key_pem
- required:
- certificate_chain_pem
- allOf:
- properties:
mode:
enum:
- byoc
required:
- mode
- anyOf:
- not:
required:
- certificate_pem
- not:
required:
- private_key_pem
properties:
mode:
type: string
enum:
- managed
- byoc
default: byoc
description: managed for a Volcano-issued certificate; byoc to supply your own.
certificate_pem:
type: string
maxLength: 65536
description: PEM-encoded certificate. Required when mode is byoc; not allowed when mode is managed.
private_key_pem:
type: string
maxLength: 65536
description: PEM-encoded private key. Required when mode is byoc; not allowed when mode is managed.
certificate_chain_pem:
type: string
maxLength: 65536
description: Optional PEM-encoded certificate chain when mode is byoc; not allowed when mode is managed.
required:
- mode
FrontendCustomDomainResponse:
type: object
properties:
domain:
type: string
tls_mode:
type: string
enum:
- managed
- byoc
domain_status:
type: string
enum:
- pending_verification
- provisioning
- active
- detaching
- failed
- deleted
verification_status:
type: string
enum:
- pending
- verified
- failed
description: '`verified`: the domain is served by a validated certificate. `pending`: it is not served yet, is being re-validated after its certificate material was withdrawn, or Volcano is retrying after a failure. `failed`: a failure left the domain unserved, alongside `domain_status: failed`; managed domains report the cause in `failure_reason`.'
failure_reason:
type: string
description: Failure category, present only when managed TLS setup has failed. Current values are provider, certificate, ownership, and internal; ownership means another account has already claimed the hostname through ownership verification. Treat unrecognized values as internal.
verification_records:
type: array
items:
$ref: '#/components/schemas/FrontendDomainVerificationRecord'
required_routing_record:
allOf:
- $ref: '#/components/schemas/FrontendDomainRoutingRecord'
deprecated: true
description: Deprecated and no longer returned. Use routing_target_hostname as the DNS routing target.
routing_target_hostname:
type: string
description: DNS routing target hostname for this frontend. The DNS record type depends on whether the custom domain is a zone apex.
effective_urls:
type: array
items:
type: string
created_at:
type: string
format: date-time
updated_at:
type: string
format: date-time
required:
- domain
- tls_mode
- domain_status
- verification_status
- effective_urls
- created_at
- updated_at
FrontendDeployment:
type: object
properties:
id:
type: string
format: uuid
frontend_id:
type: string
format: uuid
project_id:
type: string
format: uuid
operation:
type: string
enum:
- deploy
- redeploy
- delete
status:
type: string
description: |
Deployment lifecycle status. A `degraded` redeploy remains available while
edge-only recovery is retried. A `failed` redeploy is recorded here while the
frontend keeps serving its previous deployment.
enum:
- queued
- provisioning
- active
- degraded
- failed
- superseded
- deleting
- deleted
deploy_source:
type: string
enum:
- git
- cli
- web
- api
- system
- unknown
description: What initiated this deployment.
initiated_by:
type: string
description: Platform user that triggered a request-initiated deployment; absent for git and system deployments.
artifact_bucket:
type: string
artifact_key:
type: string
artifact_version:
type: string
site_url:
type: string
cloudformation_stack_id:
type: string
cloudformation_stack_url:
type: string
codebuild_duration_seconds:
type: integer
format: int64
description: Total CodeBuild build duration recorded for this deployment, in seconds.
codebuild_build_count:
type: integer
description: Number of completed CodeBuild builds included in codebuild_duration_seconds.
codebuild_duration_recorded_at:
type: string
format: date-time
progress:
$ref: '#/components/schemas/DeploymentProgress'
error_message:
type: string
created_at:
type: string
format: date-time
updated_at:
type: string
format: date-time
required:
- id
- frontend_id
- project_id
- operation
- status
- deploy_source
- created_at
- updated_at
FrontendDomainRoutingRecord:
type: object
properties:
record_type:
type: string
enum:
- CNAME
name:
type: string
value:
type: string
required:
- record_type
- name
- value
FrontendDomainVerificationRecord:
type: object
description: The DNS records currently required for managed TLS. Volcano may require a tenant-specific TXT ownership record before returning a CNAME that authorizes certificate issuance and renewal. Clients must follow the records returned for the current lifecycle state instead of assuming a fixed sequence.
properties:
name:
type: string
type:
type: string
value:
type: string
required:
- name
- type
- value
FrontendCustomDomainConflictError:
description: 'Custom domain create conflict. With `code: ownership_verification_required`, another account holds an unverified managed TLS reservation for the hostname: publish `required_record` in DNS and send the same request again. The retry succeeds once Volcano can see the record. Other conflicts omit both fields.'
allOf:
- $ref: '#/components/schemas/Error'
- type: object
properties:
required_record:
$ref: '#/components/schemas/FrontendDomainVerificationRecord'
FrontendUsageDailyEntry:
type: object
description: One day of request and error counts for a single frontend.
properties:
day:
type: string
format: date
description: UTC date (YYYY-MM-DD) the counts cover.
requests:
type: integer
format: int64
description: Total requests served on this day.
errors:
type: integer
format: int64
description: 5xx responses served on this day.
page_views:
type: integer
format: int64
description: Navigable-document responses served on this day (text/html or Sec-Fetch-Dest=document) — strict subset of `requests`.
required:
- day
- requests
- errors
- page_views
FrontendUsageData:
type: object
description: Monthly frontend request totals grouped by frontend.
properties:
frontend_id:
type: string
format: uuid
description: Frontend ID
frontend_name:
type: string
description: Frontend name at the time usage was fetched
nullable: true
requests:
type: integer
format: int64
description: Total requests for this frontend in the current usage month
required:
- frontend_id
- requests
FrontendUsageHistoryResponse:
type: object
description: Zero-filled daily series of request + error counts for a single frontend, oldest first.
properties:
frontend_id:
type: string
format: uuid
days:
type: integer
description: Number of daily entries returned (always equal to the `days` query param after clamping).
daily:
type: array
items:
$ref: '#/components/schemas/FrontendUsageDailyEntry'
total_requests:
type: integer
format: int64
total_errors:
type: integer
format: int64
total_page_views:
type: integer
format: int64
required:
- frontend_id
- days
- daily
- total_requests
- total_errors
- total_page_views
Function:
type: object
properties:
id:
type: string
format: uuid
project_id:
type: string
format: uuid
name:
type: string
maxLength: 63
pattern: ^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$
status:
type: string
enum:
- provisioning
- active
- failed
- deleting
provisioning_started_at:
type: string
format: date-time
description: Timestamp when the current provisioning phase started
is_public:
type: boolean
description: |
Function visibility for anon-key invocation.
- `false` (default): only auth user tokens and service keys can invoke
- `true`: anon keys with `functions.invoke` can invoke
invocation_mode:
$ref: '#/components/schemas/FunctionInvocationMode'
http_auth_mode:
$ref: '#/components/schemas/FunctionHTTPAuthMode'
openapi_spec:
type: object
nullable: true
additionalProperties: true
description: Optional OpenAPI 3.0 or 3.1 document describing an HTTP-mode function.
has_openapi_spec:
type: boolean
description: Whether OpenAPI metadata is configured; list responses omit the document itself.
aws_function_arn:
type: string
invoke_url:
type: string
description: 'Canonical geo-routed HTTPS endpoint for invoking this function. Use it as-is: it does not share a domain with the API, so a host derived from the API URL will not reach the function. Omitted when the deployment serves no public invocation domain, as in local development, so a client testing for an empty string never matches.'
deployed_regions:
type: array
items:
type: string
description: Regions where this function is currently deployed
runtime:
type: string
handler:
type: string
current_deployment_id:
type: string
format: uuid
description: Identifier of the latest function deployment operation
pending_deployment_id:
type: string
format: uuid
description: Newest queued deployment that will run after the current operation
last_invoked_at:
type: string
format: date-time
description: Most recent successful invocation timestamp
created_at:
type: string
format: date-time
updated_at:
type: string
format: date-time
required:
- id
- project_id
- name
- status
- is_public
- invocation_mode
- http_auth_mode
- openapi_spec
- has_openapi_spec
- deployed_regions
- created_at
- updated_at
DurableFunction:
type: object
description: |
A durable function. Separate from `Function` because a durable function
is invoked only through its own execution endpoints, so it has no
invocation mode, HTTP auth mode, OpenAPI document or invoke URL, and it
carries a `durable` configuration that a standard function has no field
for.
properties:
id:
type: string
format: uuid
project_id:
type: string
format: uuid
name:
type: string
maxLength: 63
pattern: ^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$
status:
type: string
enum:
- provisioning
- active
- failed
- deleting
provisioning_started_at:
type: string
format: date-time
description: Timestamp when the current provisioning phase started
is_public:
type: boolean
description: |
Whether anon keys may start executions of this function through
`POST /durable-functions/{functionId}/executions`.
When `true`, an anon key holding `functions.invoke` can start an
execution. When `false` (the default) only service keys and auth
user tokens can. Reading and stopping an execution always require
the project owner's token, whatever this is set to.
Set it when the function is created. Durable functions have no
update endpoint, so changing visibility later means redeploying.
A public durable function is startable, never invocable: it is not
reachable through `POST /functions/{functionId}/invoke` or a
function URL, which answer `404` for either visibility.
durable:
$ref: '#/components/schemas/DurableFunctionConfig'
deployed_regions:
type: array
items:
type: string
description: Regions where this function is currently deployed
runtime:
type: string
handler:
type: string
current_deployment_id:
type: string
format: uuid
description: Identifier of the latest deployment operation
pending_deployment_id:
type: string
format: uuid
description: Newest queued deployment that will run after the current operation
last_invoked_at:
type: string
format: date-time
description: Most recent successful invocation timestamp
created_at:
type: string
format: date-time
updated_at:
type: string
format: date-time
required:
- id
- project_id
- name
- status
- is_public
- durable
- deployed_regions
- created_at
- updated_at
DurableFunctionConfig:
type: object
description: |
Execution limits the function was created with, derived from the
project's plan. Fixed for the life of the function: changing them means
creating a new one.
The memory the function runs at, and the timeout on one attempt within
an execution, also come from the plan but are not reported here: they
are applied to the deployed function rather than recorded on it. Both
are published per plan in the plans and limits guide.
properties:
execution_timeout_seconds:
type: integer
format: int64
description: |
How long a whole execution may run, including time suspended in a
wait. This is not a limit on one attempt: an execution outlives any
single attempt by checkpointing and resuming, and the per-attempt
timeout is the plan's own, smaller number.
retention_days:
type: integer
format: int64
description: |
How long a finished execution's result and history are retained, for
as long as the function exists. Deleting the function, or its
project, ends retention early and takes the history with it.
required:
- execution_timeout_seconds
- retention_days
DurableExecution:
type: object
properties:
id:
type: string
format: uuid
function_id:
type: string
format: uuid
name:
type: string
description: |
Idempotency key for the execution. Supplied by the client through
`X-Volcano-Execution-Name`, otherwise generated.
status:
$ref: '#/components/schemas/DurableExecutionStatus'
region:
type: string
description: |
Region the execution runs in. An execution is pinned to one region
for its whole life because its checkpoints live there.
result:
description: |
Whatever the function returned, verbatim. Absent while the execution
is still running, absent when the result was too large to return and
was checkpointed instead, and absent once the retention period has
lapsed.
result_expired:
type: boolean
description: |
`true` when the execution is terminal but its result is no longer
retained, which distinguishes a discarded result from an empty one.
Shortly after that the execution itself is dropped and reads answer
`404`.
A result that was checkpointed rather than returned leaves this
unset, so it reads like a function that returned nothing.
error:
$ref: '#/components/schemas/DurableExecutionError'
created_at:
type: string
format: date-time
completed_at:
type: string
format: date-time
description: Present once the execution has reached a terminal status.
required:
- id
- function_id
- name
- status
- region
- created_at
DurableExecutionStatus:
type: string
enum:
- pending
- running
- succeeded
- failed
- timed_out
- stopped
- unknown
description: |
Lifecycle state of an execution. `pending` covers the window between the
platform reserving the execution name and the function accepting the
start, and has no counterpart once the execution is under way.
`succeeded`, `failed`, `timed_out`, `stopped` and `unknown` are
terminal.
`unknown` means the execution's outcome cannot be established, so no
result or error can be given for it. Either it was under way and was
never seen to finish, or its start failed with a `500` without the
platform establishing whether the execution began — which is why a
name whose start returned an error can later read as `unknown` rather
than not being found. It is terminal because nothing can settle it
later, and it is rare — treat it as an outcome to retry rather than a
state to wait on. A retry under the same name picks this execution back
up instead of starting a second one, and needs a free concurrency slot
because an `unknown` execution has given its own up. `completed_at` on
an `unknown` execution is when the platform gave up, not when the work
ended.
DurableExecutionError:
type: object
description: Why a failed or timed-out execution ended.
properties:
type:
type: string
message:
type: string
FunctionInvocationMode:
type: string
enum:
- rpc
- http
description: |
Invocation contract. `rpc` preserves the existing POST `{payload: ...}` contract;
`http` forwards HTTP request semantics to the function runtime.
FunctionHTTPAuthMode:
type: string
enum:
- volcano
- none
description: |
Authentication applied by the HTTP ingress. `none` is valid only for public
HTTP-mode functions and is intended for externally signed webhooks.
FunctionDeployment:
type: object
properties:
id:
type: string
format: uuid
function_id:
type: string
format: uuid
project_id:
type: string
format: uuid
batch_id:
type: string
format: uuid
operation:
type: string
enum:
- deploy
- update
- delete
status:
type: string
enum:
- queued
- provisioning
- active
- failed
- superseded
- deleting
- deleted
deploy_source:
type: string
enum:
- git
- cli
- web
- api
- system
- unknown
description: What initiated this deployment.
initiated_by:
type: string
description: Platform user that triggered a request-initiated deployment; absent for git and system deployments.
artifact_bucket:
type: string
artifact_key:
type: string
artifact_version:
type: string
codebuild_duration_seconds:
type: integer
format: int64
description: Total CodeBuild build duration recorded for this deployment, in seconds.
codebuild_build_count:
type: integer
description: Number of completed CodeBuild builds included in codebuild_duration_seconds.
codebuild_duration_recorded_at:
type: string
format: date-time
progress:
$ref: '#/components/schemas/DeploymentProgress'
error_message:
type: string
completed_at:
type: string
format: date-time
created_at:
type: string
format: date-time
updated_at:
type: string
format: date-time
required:
- id
- function_id
- project_id
- operation
- status
- deploy_source
- created_at
- updated_at
FunctionInvocationRequest:
type: object
properties:
payload:
type: object
additionalProperties: true
description: |
Payload to send to the function.
If invoked with auth user token, Volcano automatically injects `__volcano_auth` context:
```javascript
{
...yourPayload,
__volcano_auth: {
user_id: "uuid",
email: "user@example.com",
project_id: "uuid",
role: "authenticated" | "anonymous"
}
}
```
FunctionInvocationResponse:
type: object
description: Raw function response body returned by the invoked function.
additionalProperties: true
LogActivityBucket:
type: object
description: Log-event counts for one activity time bucket.
properties:
start_time:
type: string
format: date-time
description: Bucket start time.
end_time:
type: string
format: date-time
description: Bucket end time.
counts:
type: object
description: Counts grouped by activity dimension.
properties:
levels:
type: object
additionalProperties:
type: integer
description: Counts by normalized log level.
regions:
type: object
additionalProperties:
type: integer
description: Counts by event region.
resource_ids:
type: object
additionalProperties:
type: integer
description: Counts by resource ID.
required:
- levels
- regions
- resource_ids
total:
type: integer
description: Total events in this bucket.
required:
- start_time
- end_time
- counts
- total
LogActivityRequest:
type: object
description: Activity request for bucketed log counts.
additionalProperties: false
properties:
resource:
$ref: '#/components/schemas/LogRequestResource'
q:
type: string
maxLength: 512
description: Optional activity query. Supports quoted text, implicit AND, AND/OR/NOT, parentheses, and fields such as `level`, `region`, `invocation.id`, `resource.id`, `resource.name`, `function`, `frontend`, `database`, and `body`.
start_time:
type: string
format: date-time
description: Start time.
end_time:
type: string
format: date-time
description: End time.
bucket_count:
type: integer
minimum: 1
maximum: 96
description: Number of activity buckets to return.
required:
- resource
LogActivityResponse:
type: object
description: Bucketed runtime log activity.
properties:
data:
type: array
items:
$ref: '#/components/schemas/LogActivityBucket'
total:
type: integer
description: Total events counted across all buckets.
required:
- data
- total
LogSearchRequest:
type: object
description: Search request for project logs.
additionalProperties: false
properties:
resource:
$ref: '#/components/schemas/LogRequestResource'
q:
type: string
maxLength: 512
description: Optional log query. Supports quoted text, implicit AND, AND/OR/NOT, parentheses, and fields such as `level`, `region`, `invocation.id`, `resource.id`, `resource.name`, `function`, `frontend`, `database`, and `body`.
start_time:
type: string
format: date-time
description: Start time.
end_time:
type: string
format: date-time
description: End time.
limit:
type: integer
minimum: 1
maximum: 1000
default: 100
description: Maximum number of records to return.
cursor:
type: string
description: Opaque pagination cursor from the previous response's `next_cursor`.
required:
- resource
LogStreamRequest:
type: object
description: Stream request for live project logs. Pagination cursors and fixed end times are not supported.
additionalProperties: false
properties:
resource:
$ref: '#/components/schemas/LogRequestResource'
q:
type: string
maxLength: 512
description: Optional log query using the same syntax as search and activity requests.
start_time:
type: string
format: date-time
description: Start time.
limit:
type: integer
minimum: 1
maximum: 1000
default: 100
description: Maximum number of records to deliver on connect or reconnect before following new events.
required:
- resource
LogSearchEvent:
allOf:
- $ref: '#/components/schemas/LogEvent'
- type: object
description: Runtime log event returned by project log search. Search results always include a stable event ID and owning resource.
properties:
id:
type: string
description: Opaque stable log event ID for pagination, deduplication, and display.
resource:
$ref: '#/components/schemas/LogResource'
required:
- id
- resource
LogSearchResponse:
type: object
description: Paginated project runtime log search response.
properties:
data:
type: array
items:
$ref: '#/components/schemas/LogSearchEvent'
description: Array of log events sorted by timestamp, newest first.
limit:
type: integer
description: Number of items requested per page.
has_more:
type: boolean
description: Whether there are more log events available.
next_cursor:
type: string
description: Opaque cursor for the next page. Send this value as `cursor` on the next request.
required:
- data
- limit
- has_more
FunctionRegion:
type: object
required:
- code
- label
- flag
properties:
code:
type: string
example: us-east-1
description: Region identifier accepted by function APIs.
label:
type: string
example: NA-East
description: Human-readable region label suitable for display in pickers.
flag:
type: string
example: 🇺🇸
description: Country flag emoji associated with the region's geography.
FunctionRuntimeOption:
type: object
required:
- name
- language
- default
- durable_capable
- deployment
properties:
name:
type: string
example: nodejs24.x
description: Runtime identifier accepted by function APIs.
language:
type: string
example: nodejs
description: Runtime language family used by the CLI to choose defaults from source files.
default:
type: boolean
description: Whether this runtime is the CLI default for its language.
durable_capable:
type: boolean
description: Whether a durable function can be authored on this runtime. Only runtimes with a durable authoring API report true, and a durable deploy naming any other runtime is rejected.
deployment:
$ref: '#/components/schemas/FunctionRuntimeDeployment'
FunctionRuntimesResponse:
type: object
required:
- runtimes
properties:
runtimes:
type: array
items:
$ref: '#/components/schemas/FunctionRuntimeOption'
FunctionScheduler:
type: object
properties:
id:
type: string
format: uuid
project_id:
type: string
format: uuid
function_id:
type: string
format: uuid
function_kind:
allOf:
- $ref: '#/components/schemas/FunctionKind'
description: |
Which collection the scheduled function belongs to. A project-wide
scheduler list mixes both kinds, and this is what says whether the
function is read back from `/projects/{id}/functions` or
`/projects/{id}/durable-functions` — and whether a tick invokes it
or starts a durable execution.
name:
type: string
enabled:
type: boolean
schedule_kind:
type: string
enum:
- cron
cron_expression:
type: string
payload:
type: object
additionalProperties: true
regions:
type: array
items:
type: string
regions_explicit:
type: boolean
next_run_at:
type: string
format: date-time
last_started_at:
type: string
format: date-time
last_completed_at:
type: string
format: date-time
last_error:
type: string
run_count:
type: integer
format: int64
description: Total number of times this scheduler has executed. 0 for a scheduler that has never run.
created_at:
type: string
format: date-time
updated_at:
type: string
format: date-time
FunctionSchedulerListResponse:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/FunctionScheduler'
page:
type: integer
limit:
type: integer
total:
type: integer
has_more:
type: boolean
next_cursor:
type: string
description: Opaque cursor for the next page (cursor pagination only; present if has_more is true)
prev_cursor:
type: string
description: Opaque cursor for the previous page (cursor pagination only; present when a previous page exists). Send as `ending_before`.
required:
- data
- page
- limit
- total
- has_more
HostedAuthPageType:
type: string
enum:
- login
- signup
- forgot-password
- device
- verify-email
- reset-password
HostedLoginEmailCheckRequest:
type: object
required:
- email
properties:
email:
type: string
format: email
HostedLoginEmailCheckResponse:
type: object
properties:
exists:
type: boolean
HostedLoginOptionsResponse:
type: object
properties:
require_email_confirmation:
type: boolean
email_password_enabled:
type: boolean
enable_signup:
type: boolean
post_auth_redirect_url:
type: string
oauth_providers:
type: array
items:
type: string
HostedRenderablePageType:
type: string
enum:
- signup
- forgot-password
- device
- verify-email
- reset-password
LogEvent:
type: object
description: Historical log event returned by log APIs.
properties:
id:
type: string
description: Opaque stable log event ID for pagination, deduplication, and display.
timestamp:
type: string
format: date-time
description: Event timestamp.
level:
$ref: '#/components/schemas/LiveLogLevel'
body:
description: Application log value. JSON arguments retain their JSON type. Strings containing a serialized JSON object or array are normalized to that object or array; all other strings remain strings.
nullable: true
oneOf:
- type: string
- type: object
additionalProperties: true
- type: array
items: {}
- type: number
format: double
- type: boolean
region:
type: string
description: Region where this log event originated.
resource:
$ref: '#/components/schemas/LogResource'
deployment:
$ref: '#/components/schemas/LogDeployment'
invocation_id:
type: string
description: Function invocation ID associated with this log event, when available.
required:
- timestamp
- body
LiveLogLevel:
type: string
enum:
- trace
- debug
- info
- warn
- error
- fatal
description: Canonical lowercase function runtime log level.
MetricUsageData:
type: object
description: Usage data for one metric across totals, daily, and hourly windows.
properties:
metric:
type: string
description: |
Metric name (for example, "Function & Frontend Invocations", "Frontend Requests",
"Durable Executions", "Durable Operations", "Durable Compute (MB-Seconds)",
"CodeBuild Build Seconds",
"Bandwidth Ingress (Bytes)", "Bandwidth Egress (Bytes)",
"Bandwidth Total (Bytes)", or "Database Storage (Bytes)"). Byte-based metrics are
reported in bytes. "Bandwidth Total (Bytes)" is derived (ingress + egress) and
is not billed separately. The three durable metrics are
counted separately from "Function & Frontend Invocations", which covers standard
invocations only. Operations and compute are counted when an execution finishes,
so they appear in the window the execution completed in rather than the one it
started in. "Durable Compute (MB-Seconds)" reports the memory the execution ran
at times the time it spent running, in megabyte-seconds; the allowance for it is
published in gigabyte-seconds, which is 1024 of these.
"Database Storage (Bytes)" is a current observed gauge,
not a cumulative counter. It is the sum of the latest samples exposed as
`storage_bytes` by the project's database list, so it includes what each
database's branches and backups hold, and it inherits that field's lag
behind a live measurement.
total:
type: integer
format: int64
description: Total usage for the current usage month
all_time:
type: integer
format: int64
description: Lifetime cumulative usage across every month for this metric
daily:
type: array
description: Last 30 days of daily usage points
items:
$ref: '#/components/schemas/UsageDataPoint'
hourly:
type: array
description: Last 24 hours of hourly usage points
items:
$ref: '#/components/schemas/UsageDataPoint'
required:
- metric
- total
- all_time
- daily
- hourly
OAuthConfig:
type: object
properties:
id:
type: string
format: uuid
provider:
type: string
enum:
- google
- github
- microsoft
- apple
- device
client_id:
type: string
example: 123456789.apps.googleusercontent.com
client_secret:
type: string
description: Masked in responses (shows only first/last 4 chars)
example: GOCS...****
enabled:
type: boolean
redirect_url:
type: string
format: uri
example: https://yourapp.com/auth/callback
scopes:
type: array
items:
type: string
example:
- openid
- email
- profile
created_at:
type: string
format: date-time
updated_at:
type: string
format: date-time
OAuthErrorResponse:
type: object
properties:
error:
type: string
error_description:
type: string
required:
- error
PaginatedAuthUsers:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/AuthUser'
page:
type: integer
description: Current page number (1-indexed)
limit:
type: integer
description: Number of items per page
total:
type: integer
description: Total number of items across all pages
has_more:
type: boolean
description: Whether there are more pages available
next:
type: string
description: URL path to next page (only present if has_more is true)
required:
- data
- page
- limit
- total
- has_more
PaginatedDatabases:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/Database'
page:
type: integer
description: Current page number (1-indexed)
limit:
type: integer
description: Number of items per page
total:
type: integer
description: Total number of items across all pages
has_more:
type: boolean
description: Whether there are more pages available
next:
type: string
description: URL path to next page (only present if has_more is true)
next_cursor:
type: string
description: Opaque cursor for the next page (cursor pagination only; present if has_more is true)
prev_cursor:
type: string
description: Opaque cursor for the previous page (cursor pagination only; present when a previous page exists). Send as `ending_before`.
required:
- data
- page
- limit
- total
- has_more
PaginatedFrontendDeployments:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/FrontendDeployment'
page:
type: integer
description: Current page number (1-indexed)
limit:
type: integer
description: Number of items per page
total:
type: integer
description: Total number of items across all pages
has_more:
type: boolean
description: Whether there are more pages available
next:
type: string
description: URL path to next page (only present if has_more is true)
required:
- data
- page
- limit
- total
- has_more
PaginatedFrontends:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/Frontend'
page:
type: integer
description: Current page number (1-indexed)
limit:
type: integer
description: Number of items per page
total:
type: integer
description: Total number of items across all pages
has_more:
type: boolean
description: Whether there are more pages available
next:
type: string
description: URL path to next page (offset pagination only; present if has_more is true)
next_cursor:
type: string
description: Opaque cursor for the next page (cursor pagination only; present if has_more is true)
prev_cursor:
type: string
description: Opaque cursor for the previous page (cursor pagination only; present when a previous page exists). Send as `ending_before`.
required:
- data
- page
- limit
- total
- has_more
PaginatedFunctionDeployments:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/FunctionDeployment'
page:
type: integer
description: Current page number (1-indexed)
limit:
type: integer
description: Number of items per page
total:
type: integer
description: Total number of items across all pages
has_more:
type: boolean
description: Whether there are more pages available
next:
type: string
description: URL path to next page (only present if has_more is true)
required:
- data
- page
- limit
- total
- has_more
PaginatedFunctions:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/Function'
page:
type: integer
description: Current page number (1-indexed)
limit:
type: integer
description: Number of items per page
total:
type: integer
description: Total number of items across all pages
has_more:
type: boolean
description: Whether there are more pages available
next:
type: string
description: URL path to next page (only present if has_more is true)
next_cursor:
type: string
description: Opaque cursor for the next page (cursor pagination only; present if has_more is true)
prev_cursor:
type: string
description: Opaque cursor for the previous page (cursor pagination only; present when a previous page exists). Send as `ending_before`.
required:
- data
- page
- limit
- total
- has_more
PaginatedDurableFunctions:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/DurableFunction'
page:
type: integer
description: Current page number (1-indexed)
limit:
type: integer
description: Number of items per page
total:
type: integer
description: Total number of items across all pages
has_more:
type: boolean
description: Whether there are more pages available
required:
- data
- page
- limit
- total
- has_more
PaginatedDurableExecutions:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/DurableExecution'
page:
type: integer
description: Current page number (1-indexed)
limit:
type: integer
description: Number of items per page
total:
type: integer
description: Total number of items across all pages
has_more:
type: boolean
description: Whether there are more pages available
required:
- data
- page
- limit
- total
- has_more
PaginatedProjectCustomDomains:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/ProjectFrontendCustomDomain'
page:
type: integer
description: Current page number (1-indexed)
limit:
type: integer
description: Number of items per page
total:
type: integer
description: Total number of items across all pages
has_more:
type: boolean
description: Whether there are more pages available
next:
type: string
description: URL path to next page (only present if has_more is true)
required:
- data
- page
- limit
- total
- has_more
PaginatedProjectDeployments:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/ProjectDeployment'
page:
type: integer
minimum: 1
description: |
Current page number (1-indexed). Offset pagination only — omitted in
cursor mode, where position comes from the cursor and there is no page
number to report. Required-and-1-indexed would otherwise force a `0`
onto every cursor response.
limit:
type: integer
description: Number of items per page
total:
type: integer
description: Total number of items across all pages
has_more:
type: boolean
description: Whether there are more pages available
next:
type: string
description: URL path to next page (offset pagination only; present if has_more is true)
next_cursor:
type: string
description: Opaque cursor for the next page (cursor pagination only; present if has_more is true)
prev_cursor:
type: string
description: Opaque cursor for the previous page (cursor pagination only; present when a previous page exists). Send as `ending_before`.
required:
- data
- limit
- total
- has_more
PaginatedProjects:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/Project'
page:
type: integer
description: Current page number (1-indexed)
limit:
type: integer
description: Number of items per page
total:
type: integer
description: Total number of items across all pages
has_more:
type: boolean
description: Whether there are more pages available
next:
type: string
description: URL path to next page (offset pagination only; present if has_more is true)
next_cursor:
type: string
description: Opaque cursor for the next page (cursor pagination only; present if has_more is true)
prev_cursor:
type: string
description: Opaque cursor for the previous page (cursor pagination only; present when a previous page exists). Send as `ending_before`.
status:
type: string
enum:
- provisioning
- active
- failed
description: Latest project variable propagation status.
current_sync_id:
type: string
format: uuid
description: Identifier of the latest variable propagation sync.
provisioning_started_at:
type: string
format: date-time
description: Timestamp when the current variable propagation phase started.
required:
- data
- page
- limit
- total
- has_more
PaginatedServiceKeys:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/ServiceKey'
page:
type: integer
description: Current page number (1-indexed)
limit:
type: integer
description: Number of items per page
total:
type: integer
description: Total number of items across all pages
has_more:
type: boolean
description: Whether there are more pages available
next:
type: string
description: URL path to next page (offset pagination only; present if has_more is true)
next_cursor:
type: string
description: Opaque cursor for the next page (cursor pagination only; present if has_more is true)
prev_cursor:
type: string
description: Opaque cursor for the previous page (cursor pagination only; present when a previous page exists). Send as `ending_before`.
required:
- data
- page
- limit
- total
- has_more
PaginatedStorageBuckets:
type: object
description: Cursor-paginated storage buckets (returned only when cursor pagination is requested).
properties:
data:
type: array
items:
$ref: '#/components/schemas/StorageBucket'
limit:
type: integer
description: Number of items per page
total:
type: integer
description: Total number of items matching the query
has_more:
type: boolean
description: Whether a next page exists
next_cursor:
type: string
description: Opaque cursor for the next page (present if has_more is true)
prev_cursor:
type: string
description: Opaque cursor for the previous page (present when a previous page exists). Send as `ending_before`.
required:
- data
- limit
- has_more
PaginatedVariables:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/Variable'
page:
type: integer
description: Current page number (1-indexed)
limit:
type: integer
description: Number of items per page
total:
type: integer
description: Total number of items across all pages
has_more:
type: boolean
description: Whether there are more pages available
next:
type: string
description: URL path to next page (only present if has_more is true)
next_cursor:
type: string
description: Opaque cursor for the next page (cursor pagination only; present if has_more is true)
prev_cursor:
type: string
description: Opaque cursor for the previous page (cursor pagination only; present when a previous page exists). Send as `ending_before`.
required:
- data
- page
- limit
- total
- has_more
PlatformExchangeResponse:
type: object
properties:
token:
type: string
user_id:
type: string
token_id:
type: string
format: uuid
expires_at:
type: string
format: date-time
required:
- token
- user_id
- token_id
- expires_at
Project:
type: object
properties:
id:
type: string
format: uuid
name:
type: string
status:
type: string
enum:
- active
- deleting
- failed
plan:
type: string
enum:
- HOBBY
- SUPERAGENT
description: Plan name applied to the project when available.
all_regions:
type: boolean
description: |
Region policy for function deployment.
- `true`: deploy functions to all configured platform regions
- `false`: deploy only to `selected_regions`
selected_regions:
type: array
items:
type: string
description: Effective region set for this project (normalized and deduplicated)
aws_application_name:
type: string
last_invoked_at:
type: string
format: date-time
description: Most recent activity timestamp across project resources
logo_url:
type: string
description: |
Relative API path that serves the project logo when one has been
uploaded. The path is versioned with a `?v=` cache-busting query
param that changes on each upload. Absent when the project has no
logo. The logo image is stored in the project's storage folder.
example: /projects/3fa85f64-5717-4562-b3fc-2c963f66afa6/logo?v=1718524800
git_connection:
allOf:
- $ref: '#/components/schemas/ProjectGitConnectionSummary'
description: Present for connected projects when `git_connection` is requested through the list endpoint's `include` parameter.
health:
allOf:
- $ref: '#/components/schemas/ProjectHealthSummary'
description: Present when `health` is requested through the list endpoint's `include` parameter.
created_at:
type: string
format: date-time
updated_at:
type: string
format: date-time
required:
- id
- name
- status
- all_regions
- selected_regions
- created_at
- updated_at
ProjectConfig:
type: object
additionalProperties: false
description: |
Declarative project configuration manifest (the JSON form of
volcano-config.yaml). Omitted sections are left untouched. Within
declared entries, omitted optional fields keep their current server
values (patch semantics). Declared collection keys are fully synced to
the manifest: `variables`, `buckets[].policies`, `auth.providers.oauth`,
`auth.email.templates`, and `functions[].schedulers` are reconciled to
exactly match, deleting resources absent from the manifest. Functions,
frontends, databases, and buckets are never created or deleted through
this manifest; entries referencing resources that do not exist are
skipped and reported.
properties:
version:
type: integer
enum:
- 1
description: Manifest schema version. Must be 1.
project:
$ref: '#/components/schemas/ProjectConfigProject'
databases:
type: array
items:
$ref: '#/components/schemas/ProjectConfigDatabase'
shared_variables:
type: array
uniqueItems: true
description: Replace the complete shared function-variable list with existing names, without changing variable values. Omission keeps membership unchanged; an empty list clears it.
items:
type: string
pattern: ^[a-zA-Z_][a-zA-Z0-9_]*$
variables:
type: array
description: Fully synced when declared - variables absent from this list are deleted.
items:
$ref: '#/components/schemas/ProjectConfigVariable'
buckets:
type: array
items:
$ref: '#/components/schemas/ProjectConfigBucket'
realtime:
$ref: '#/components/schemas/ProjectConfigRealtime'
auth:
$ref: '#/components/schemas/ProjectConfigAuth'
functions:
type: array
items:
$ref: '#/components/schemas/ProjectConfigFunction'
frontends:
type: array
items:
$ref: '#/components/schemas/ProjectConfigFrontend'
required:
- version
ProjectConfigApplyResult:
type: object
description: Per-resource report for a project config apply (or dry run).
properties:
dry_run:
type: boolean
description: True when the request was a dry run and no changes were made.
results:
type: array
items:
$ref: '#/components/schemas/ProjectConfigApplyResultEntry'
skipped:
type: array
description: |
Manifest entries referencing functions, frontends, databases, or
buckets that do not exist. Their configuration was not applied;
deploy/create the resource first, then re-apply.
items:
$ref: '#/components/schemas/ProjectConfigSkippedResource'
missing:
type: array
description: |
Existing functions, frontends, databases, or buckets that have no
entry in the corresponding declared manifest section.
items:
$ref: '#/components/schemas/ProjectConfigMissingResource'
summary:
$ref: '#/components/schemas/ProjectConfigApplySummary'
required:
- results
- skipped
- missing
- summary
ProjectConfigApplyResultEntry:
type: object
properties:
section:
type: string
description: Manifest section the entry belongs to (e.g. variables, buckets, auth.providers.oauth).
name:
type: string
description: Resource name or key within the section. Empty for singleton sections.
action:
type: string
enum:
- created
- updated
- deleted
- unchanged
- error
error:
type: string
description: Error detail when action is `error`.
notice:
type: string
description: Optional operational note (e.g. disabling realtime drops active connections).
required:
- section
- action
ProjectConfigApplySummary:
type: object
properties:
created:
type: integer
updated:
type: integer
deleted:
type: integer
unchanged:
type: integer
errors:
type: integer
skipped:
type: integer
missing:
type: integer
required:
- created
- updated
- deleted
- unchanged
- errors
- skipped
- missing
ProjectConfigAuth:
type: object
additionalProperties: false
description: Authentication settings, grouped like the dashboard auth-settings tabs.
properties:
tokens:
$ref: '#/components/schemas/ProjectConfigAuthTokens'
sessions:
$ref: '#/components/schemas/ProjectConfigAuthSessions'
signup:
$ref: '#/components/schemas/ProjectConfigAuthSignup'
rate_limits:
$ref: '#/components/schemas/ProjectConfigAuthRateLimits'
password:
$ref: '#/components/schemas/ProjectConfigAuthPassword'
password_reset:
$ref: '#/components/schemas/ProjectConfigAuthPasswordReset'
email_verification:
$ref: '#/components/schemas/ProjectConfigAuthEmailVerification'
cors:
$ref: '#/components/schemas/ProjectConfigAuthCORS'
providers:
$ref: '#/components/schemas/ProjectConfigAuthProviders'
email:
$ref: '#/components/schemas/ProjectConfigAuthEmail'
managed_pages:
$ref: '#/components/schemas/ProjectConfigAuthManagedPages'
ProjectConfigAuthCORS:
type: object
additionalProperties: false
properties:
enabled:
type: boolean
allowed_origins:
type: array
items:
type: string
allow_credentials:
type: boolean
max_age:
type: integer
ProjectConfigAuthEmail:
type: object
additionalProperties: false
properties:
enabled:
type: boolean
description: Enable transactional email sending
from:
$ref: '#/components/schemas/ProjectConfigAuthEmailFrom'
smtp:
$ref: '#/components/schemas/ProjectConfigAuthEmailSMTP'
templates:
$ref: '#/components/schemas/ProjectConfigEmailTemplates'
ProjectConfigAuthEmailFrom:
type: object
additionalProperties: false
properties:
address:
type: string
name:
type: string
ProjectConfigAuthEmailPasswordProvider:
type: object
additionalProperties: false
properties:
enabled:
type: boolean
ProjectConfigAuthEmailSMTP:
type: object
additionalProperties: false
properties:
host:
type: string
port:
type: integer
username:
type: string
password:
type: string
format: password
writeOnly: true
description: Write-only; omitted from config export.
use_tls:
type: boolean
ProjectConfigAuthEmailVerification:
type: object
additionalProperties: false
properties:
require_confirmation:
type: boolean
description: Require users to confirm email before sign-in. Requires email sending to be enabled.
confirmation_timeout:
type: integer
description: Email confirmation token expiry in seconds
ProjectConfigAuthManagedPages:
type: object
additionalProperties: false
properties:
enabled:
type: boolean
description: Enable or disable managed auth hosted pages
redirects:
$ref: '#/components/schemas/ProjectConfigAuthRedirects'
pages:
$ref: '#/components/schemas/ProjectConfigHostedPages'
appearance:
$ref: '#/components/schemas/ProjectConfigAuthPageAppearance'
ProjectConfigAuthPassword:
type: object
additionalProperties: false
properties:
min_length:
type: integer
minimum: 15
maximum: 128
require_uppercase:
type: boolean
require_lowercase:
type: boolean
require_numbers:
type: boolean
require_special_chars:
type: boolean
ProjectConfigAuthPasswordReset:
type: object
additionalProperties: false
properties:
allow:
type: boolean
timeout:
type: integer
description: Password reset token expiry in seconds
max_history:
type: integer
description: Number of previous passwords to disallow (0=disabled)
ProjectConfigAuthProviders:
type: object
additionalProperties: false
properties:
email_password:
$ref: '#/components/schemas/ProjectConfigAuthEmailPasswordProvider'
oauth:
type: array
description: Fully synced when declared - providers absent from this list are deleted.
items:
$ref: '#/components/schemas/ProjectConfigOAuthProvider'
ProjectConfigAuthRateLimits:
type: object
additionalProperties: false
description: Rate limits per hour.
properties:
signup:
type: integer
signin:
type: integer
token_refresh:
type: integer
password_reset:
type: integer
ProjectConfigAuthRedirects:
type: object
additionalProperties: false
properties:
allowed:
type: array
items:
type: string
description: Redirect allowlist. Every entry must be a valid http/https URL.
post_auth:
type: string
description: Must be included in `allowed` when set.
post_logout:
type: string
description: Must be included in `allowed` when set.
device_verification:
type: string
description: Optional custom device-authorization verification page URL.
ProjectConfigAuthSessions:
type: object
additionalProperties: false
properties:
inactivity_timeout:
type: integer
description: Force re-login after inactivity (seconds, 0=never)
max_session_duration:
type: integer
description: Force re-login after duration (seconds, 0=never)
ProjectConfigAuthSignup:
type: object
additionalProperties: false
properties:
enable_signup:
type: boolean
description: Master switch for signups across ALL providers
enable_anonymous_signins:
type: boolean
allowed_email_domains:
type: array
maxItems: 100
description: |
Email domains allowed to create users. Empty allows every domain.
Replaces the stored list; entries are normalized (lowercase, no `@`
prefix) and must be bare domains such as `domain1.com`. Matching is
exact, so subdomains need their own entry. At most 100 entries.
Restricting signups is a SUPERAGENT feature to configure and to enforce: a
HOBBY project can only declare the list it already has or remove the
restriction, and the list it keeps is parked until it upgrades.
items:
type: string
example:
- domain1.com
- domain2.com
allowed_email_domains_mode:
type: string
description: |
How far `allowed_email_domains` reaches. `signup` gates account
creation only. `signup_and_signin` also blocks sign-in for accounts
outside the list and signs out the ones it locks out. `disabled`
keeps the list without enforcing it.
enum:
- disabled
- signup
- signup_and_signin
ProjectConfigAuthTokens:
type: object
additionalProperties: false
description: Token lifetimes in seconds.
properties:
access_token_lifetime:
type: integer
refresh_token_lifetime:
type: integer
refresh_token_reuse_interval:
type: integer
platform_token_ttl:
type: integer
ProjectConfigBucket:
type: object
additionalProperties: false
description: |
Settings for an existing storage bucket. Buckets are never created or
deleted through the manifest. When `policies` is declared it is fully
synced (policies absent from the list are deleted; an empty list
deletes all); omitting `policies` leaves the bucket's policies
untouched.
properties:
name:
type: string
pattern: ^[a-zA-Z0-9_-]+$
minLength: 1
maxLength: 64
file_size_limit:
type: integer
format: int64
description: Maximum file size in bytes
allowed_mime_types:
type: array
items:
type: string
policies:
type: array
items:
$ref: '#/components/schemas/ProjectConfigBucketPolicy'
required:
- name
ProjectConfigBucketPolicy:
type: object
additionalProperties: false
properties:
name:
type: string
minLength: 1
operation:
type: string
enum:
- SELECT
- INSERT
- UPDATE
- DELETE
definition:
type: string
description: Policy expression
required:
- name
- operation
- definition
ProjectConfigCustomDomain:
type: object
additionalProperties: false
description: |
Custom domain with managed or BYOC TLS (SUPERAGENT plan). `tls` is required
when the domain is first created and optional afterwards. For an existing
domain, omitting `tls` or sending only `tls.mode` keeps the stored
certificate; new BYOC material for the same domain rotates the
certificate in place (zero downtime). Changing `tls.mode` for the same
hostname, or the hostname of a managed domain, requires deleting the
domain first. BYOC TLS material is write-only; exports render only
`tls.mode`.
properties:
domain:
type: string
maxLength: 253
description: 'Fully-qualified domain name (hostname only, no scheme/path). Managed TLS (`tls.mode: managed`) accepts at most 219 characters; BYOC accepts 253.'
tls:
$ref: '#/components/schemas/ProjectConfigFrontendCustomDomainTLSConfig'
required:
- domain
ProjectConfigDatabase:
type: object
additionalProperties: false
description: |
Assertion-only entry for an existing database. No database property is
mutable through the manifest; declared values are compared against the
deployed database and any mismatch fails validation. Databases are
never created or deleted here.
properties:
name:
type: string
minLength: 1
region:
type: string
description: Deployed region ID (e.g. aws-us-east-1). Asserted, never written.
pg_version:
type: string
enum:
- '15'
- '16'
description: PostgreSQL major version. Asserted, never written.
database_type:
type: string
enum:
- volcano-db-xs
- volcano-db-s
- volcano-db-m
- volcano-db-l
- volcano-db-xl
- volcano-db-2xl
description: |
Compute tier. Asserted, never written - tier changes are not
supported via the manifest; use the databases API/CLI/GUI instead.
required:
- name
- region
- pg_version
ProjectConfigEmailTemplate:
type: object
additionalProperties: false
properties:
subject:
type: string
html_body:
type: string
maxLength: 262144
description: HTML body. Max 256 KiB. SUPERAGENT plan required for custom bodies.
text_body:
type: string
maxLength: 262144
description: Plain-text body. Max 256 KiB. SUPERAGENT plan required for custom bodies.
ProjectConfigEmailTemplates:
type: object
additionalProperties: false
description: |
Email templates keyed by type. Fully synced when declared - template
types absent from a declared map revert to server defaults (custom
bodies deleted, subject overrides cleared). Custom template bodies
require the SUPERAGENT plan; subject-only changes are available on HOBBY.
properties:
confirmation:
$ref: '#/components/schemas/ProjectConfigEmailTemplate'
password_reset:
$ref: '#/components/schemas/ProjectConfigEmailTemplate'
password_changed:
$ref: '#/components/schemas/ProjectConfigEmailTemplate'
welcome:
$ref: '#/components/schemas/ProjectConfigEmailTemplate'
ProjectConfigFrontend:
type: object
additionalProperties: false
description: |
Configuration for an existing (deployed) frontend. Frontends are never
created or deleted through the manifest. A declared frontend entry
without `custom_domain` deletes an existing custom domain.
properties:
name:
type: string
minLength: 1
custom_domain:
$ref: '#/components/schemas/ProjectConfigCustomDomain'
required:
- name
ProjectConfigFunction:
type: object
additionalProperties: false
description: |
Configuration for an existing (deployed) function. Functions are never
created or deleted through the manifest. When `schedulers` is declared
it is fully synced (schedulers absent from the list are deleted);
omitting `schedulers` leaves the function's schedulers untouched. The
same applies to `variables`: declaring it replaces the function's
declared variable names, and omitting it leaves them untouched.
properties:
name:
type: string
minLength: 1
kind:
$ref: '#/components/schemas/FunctionKind'
public:
type: boolean
description: Function visibility for anon-key invocation
variable_scope:
type: string
enum:
- all
- scoped
description: |
Which project variables this function receives. `all` (the default)
gives it the project variables marked `shared: true`. `scoped` gives it only the variables
it selects: every name declared in `variables`, plus the names
Volcano detects in its source that the project defines.
variables:
type: array
items:
type: string
minLength: 1
maxLength: 256
description: |
Project variable names this function requires, on top of the ones
detected in its source. Declare a name here when the function reads
it through a computed key, which detection cannot see, or when the
function must not deploy without it: a declared name the project does
not define fails the apply, while a detected name it does not define
is ignored. Only used when `variable_scope` is `scoped`.
invocation_mode:
$ref: '#/components/schemas/FunctionInvocationMode'
http_auth_mode:
$ref: '#/components/schemas/FunctionHTTPAuthMode'
openapi_spec:
type: object
nullable: true
additionalProperties: true
x-go-type: nullable.Nullable[map[string]interface{}]
x-go-type-skip-optional-pointer: true
description: OpenAPI 3.0 or 3.1 metadata for an HTTP-mode function
schedulers:
type: array
items:
$ref: '#/components/schemas/ProjectConfigScheduler'
required:
- name
ProjectConfigHostedPage:
type: object
additionalProperties: false
properties:
html:
type: string
maxLength: 262144
description: Raw HTML markup for the page. Max 256 KiB.
css:
type: string
maxLength: 262144
description: Optional CSS injected at render time. Max 256 KiB.
required:
- html
ProjectConfigHostedPages:
type: object
additionalProperties: false
description: |
Hosted auth pages keyed by page type (SUPERAGENT plan). Upsert-only: omitted
pages are left untouched (there is no delete for hosted pages).
properties:
login:
$ref: '#/components/schemas/ProjectConfigHostedPage'
reset_password:
$ref: '#/components/schemas/ProjectConfigHostedPage'
signup:
$ref: '#/components/schemas/ProjectConfigHostedPage'
forgot_password:
$ref: '#/components/schemas/ProjectConfigHostedPage'
device:
$ref: '#/components/schemas/ProjectConfigHostedPage'
verify_email:
$ref: '#/components/schemas/ProjectConfigHostedPage'
PreviewAuthPageRequest:
type: object
additionalProperties: false
required:
- theme
- layout
properties:
theme:
$ref: '#/components/schemas/AuthPageTheme'
layout:
$ref: '#/components/schemas/AuthPageLayout'
action:
type: string
PreviewAuthPageResponse:
type: object
required:
- preview_url
- expires_at
properties:
preview_url:
type: string
format: uri
expires_at:
type: string
format: date-time
ProjectConfigMissingResource:
type: object
properties:
type:
type: string
enum:
- function
- frontend
- database
- bucket
name:
type: string
required:
- type
- name
ProjectConfigOAuthProvider:
type: object
additionalProperties: false
properties:
provider:
type: string
enum:
- google
- github
- microsoft
- apple
- device
enabled:
type: boolean
client_id:
type: string
description: |
Required for non-device providers. Server-generated for
`provider=device` (exported read-only, ignored on apply).
client_secret:
type: string
format: password
writeOnly: true
description: Write-only; omitted from config export. Not used for `provider=device`.
redirect_url:
type: string
description: Not used for `provider=device`.
scopes:
type: array
items:
type: string
required:
- provider
ProjectConfigProject:
type: object
additionalProperties: false
description: Project-level settings. `name` renames the project.
properties:
name:
type: string
pattern: ^[A-Za-z0-9_-]+$
minLength: 1
maxLength: 255
all_regions:
type: boolean
description: Region policy. `false` requires `selected_regions` (SUPERAGENT plan).
selected_regions:
type: array
items:
type: string
description: Region subset (bare region names). Requires `all_regions=false`.
ProjectConfigRealtime:
type: object
additionalProperties: false
properties:
enabled:
type: boolean
broadcast_enabled:
type: boolean
presence_enabled:
type: boolean
postgres_changes_enabled:
type: boolean
ProjectConfigScheduler:
type: object
additionalProperties: false
properties:
name:
type: string
minLength: 1
maxLength: 200
cron:
type: string
description: 5-field UTC cron expression
enabled:
type: boolean
payload:
type: object
additionalProperties: true
required:
- name
- cron
ProjectConfigSkippedResource:
type: object
properties:
type:
type: string
enum:
- function
- frontend
- database
- bucket
name:
type: string
reason:
type: string
required:
- type
- name
- reason
ProjectConfigValidationError:
type: object
properties:
section:
type: string
description: Manifest section the error refers to (e.g. databases, functions).
name:
type: string
description: Resource name or key within the section, when applicable.
message:
type: string
required:
- section
- message
ProjectConfigValidationErrorResponse:
type: object
description: Returned when manifest validation fails. Nothing was applied.
properties:
error:
type: string
errors:
type: array
items:
$ref: '#/components/schemas/ProjectConfigValidationError'
required:
- error
- errors
ProjectConfigVariable:
type: object
additionalProperties: false
properties:
shared:
type: boolean
description: Include this name in the project's shared function variables. Omission preserves existing membership; new variables default to true for legacy clients. Send false explicitly to create a non-shared variable.
name:
type: string
minLength: 1
value:
type: string
required:
- name
- value
ProjectHealthResource:
type: object
properties:
type:
type: string
enum:
- project
- function
- frontend
- database
id:
type: string
format: uuid
name:
type: string
kind:
allOf:
- $ref: '#/components/schemas/FunctionKind'
description: |
Which kind of function this check is about. Present only when `type`
is `function`, where both kinds share the name space and this is
what tells them apart.
required:
- type
- id
- name
ResourceReference:
type: object
description: Stable reference to a Volcano resource.
properties:
type:
type: string
enum:
- project
- function
- frontend
- database
id:
type: string
format: uuid
name:
type: string
required:
- type
- id
- name
DeploymentReference:
type: object
description: Stable reference to a Volcano deployment run.
properties:
id:
type: string
format: uuid
required:
- id
ProjectHealthScope:
type: object
properties:
resource:
$ref: '#/components/schemas/ProjectHealthResource'
required:
- resource
ProjectHealthResponse:
type: object
properties:
project_id:
type: string
format: uuid
status:
$ref: '#/components/schemas/ProjectHealthStatus'
observed_at:
type: string
format: date-time
fresh_through:
type: string
format: date-time
data_status:
$ref: '#/components/schemas/ProjectHealthDataStatus'
checks:
type: array
items:
$ref: '#/components/schemas/ProjectHealthCheck'
findings:
description: Top findings ordered by severity, then stable check ID.
type: array
maxItems: 5
items:
$ref: '#/components/schemas/ProjectHealthCheck'
required:
- project_id
- status
- observed_at
- fresh_through
- data_status
- checks
- findings
ProjectHealthStatus:
type: string
enum:
- healthy
- degraded
- critical
- unknown
ProjectHealthDataStatus:
type: string
enum:
- complete
- partial
- no_data
- stale
ProjectHealthCategory:
type: string
enum:
- lifecycle
- storage
ProjectHealthEvidence:
type: object
properties:
metric:
type: string
value:
type: number
format: double
unit:
type: string
sample_count:
type: integer
format: int64
minimum: 0
required:
- metric
- value
- unit
- sample_count
ProjectHealthCheck:
type: object
properties:
id:
type: string
category:
$ref: '#/components/schemas/ProjectHealthCategory'
status:
$ref: '#/components/schemas/ProjectHealthStatus'
reason_code:
type: string
scope:
$ref: '#/components/schemas/ProjectHealthScope'
evidence:
$ref: '#/components/schemas/ProjectHealthEvidence'
required:
- id
- category
- status
- reason_code
- scope
- evidence
ProjectMetricsDataStatus:
type: string
enum:
- complete
- partial
- no_data
ProjectMetricsDimensions:
type: object
additionalProperties: false
properties:
region:
type: string
resource_type:
type: string
enum:
- function
- frontend
ProjectMetricsGroupBy:
type: string
enum:
- region
- resource_type
ProjectMetricsMetric:
type: string
enum:
- request_count
- server_error_count
- availability
- p95_latency
ProjectMetricsQuery:
type: object
additionalProperties: false
properties:
id:
type: string
minLength: 1
maxLength: 64
pattern: ^[A-Za-z][A-Za-z0-9_-]*$
metric:
$ref: '#/components/schemas/ProjectMetricsMetric'
group_by:
$ref: '#/components/schemas/ProjectMetricsGroupBy'
required:
- id
- metric
ProjectMetricsQueryRequest:
type: object
additionalProperties: false
properties:
time_range:
$ref: '#/components/schemas/ProjectMetricsQueryTimeRange'
queries:
type: array
minItems: 1
maxItems: 10
items:
$ref: '#/components/schemas/ProjectMetricsQuery'
required:
- time_range
- queries
ProjectMetricsQueryResponse:
type: object
additionalProperties: false
properties:
observed_at:
type: string
format: date-time
fresh_through:
type: string
format: date-time
window:
$ref: '#/components/schemas/ProjectMetricsWindow'
results:
type: array
items:
$ref: '#/components/schemas/ProjectMetricsResult'
required:
- observed_at
- window
- results
ProjectMetricsQueryTimeRange:
type: object
additionalProperties: false
properties:
window:
type: string
enum:
- 30m
- 1h
- 24h
- 7d
required:
- window
ProjectMetricsResult:
type: object
additionalProperties: false
properties:
id:
type: string
metric:
$ref: '#/components/schemas/ProjectMetricsMetric'
unit:
$ref: '#/components/schemas/ProjectMetricsUnit'
data_status:
$ref: '#/components/schemas/ProjectMetricsDataStatus'
values:
type: array
items:
$ref: '#/components/schemas/ProjectMetricsValue'
required:
- id
- metric
- unit
- data_status
- values
ProjectMetricsUnit:
type: string
enum:
- count
- ratio
- seconds
ProjectMetricsValue:
type: object
additionalProperties: false
properties:
dimensions:
$ref: '#/components/schemas/ProjectMetricsDimensions'
value:
type: number
format: double
minimum: 0
required:
- dimensions
- value
ProjectMetricsWindow:
type: object
properties:
from:
type: string
format: date-time
to:
type: string
format: date-time
required:
- from
- to
ProjectFrontendCustomDomain:
allOf:
- $ref: '#/components/schemas/FrontendCustomDomainResponse'
- type: object
properties:
frontend:
type: object
description: |
The frontend this custom domain is attached to. Inlined to
avoid a second fetch from the project-scoped feed.
properties:
id:
type: string
format: uuid
name:
type: string
required:
- id
- name
required:
- frontend
ProjectDeployment:
type: object
description: A Function or Frontend deployment attempt in a project-scoped feed.
properties:
id:
type: string
format: uuid
project_id:
type: string
format: uuid
resource:
$ref: '#/components/schemas/ProjectDeploymentResource'
operation:
type: string
enum:
- deploy
- redeploy
- update
- delete
status:
type: string
enum:
- queued
- provisioning
- active
- degraded
- failed
- superseded
- deleting
- deleted
deploy_source:
type: string
enum:
- git
- cli
- web
- api
- system
- unknown
description: What initiated this deployment.
artifact_version:
type: string
error_message:
type: string
completed_at:
type: string
format: date-time
progress:
$ref: '#/components/schemas/DeploymentProgress'
created_at:
type: string
format: date-time
updated_at:
type: string
format: date-time
required:
- id
- project_id
- resource
- operation
- status
- deploy_source
- created_at
- updated_at
ProjectDeploymentResource:
type: object
description: The resource this deployment belongs to.
properties:
type:
type: string
enum:
- function
- frontend
id:
type: string
format: uuid
name:
type: string
kind:
allOf:
- $ref: '#/components/schemas/FunctionKind'
description: |
Which kind of function this deployment belongs to. Both kinds appear
in this feed under `type: function`, because a deployment means the
same thing for either, so this is what tells them apart. Absent when
`type` is `frontend`.
required:
- type
- id
- name
ProjectDeploymentSummary:
type: object
description: Aggregate deployment statistics for one resource pipeline.
properties:
deployment_count:
type: integer
description: All deployment attempts matching the filters.
successful_count:
type: integer
description: Attempts that reached active or deleted.
failed_count:
type: integer
description: Attempts that reached failed or degraded.
canceled_count:
type: integer
description: Superseded attempts, excluded from success rate and duration.
success_rate:
type: number
format: double
minimum: 0
maximum: 1
nullable: true
description: Successful attempts divided by successful plus failed attempts.
median_build_duration_seconds:
type: number
format: double
minimum: 0
nullable: true
description: Median CodeBuild duration across eligible completed attempts.
required:
- deployment_count
- successful_count
- failed_count
- canceled_count
- success_rate
- median_build_duration_seconds
ProjectUsageResponse:
type: object
description: Aggregated usage metrics for a project.
properties:
project_id:
type: string
format: uuid
description: Project ID
month:
type: string
description: Usage month in YYYY-MM format
example: 2026-02
metrics:
type: array
description: Usage metrics for the project
items:
$ref: '#/components/schemas/MetricUsageData'
frontends:
type: array
description: Per-frontend request totals for the current usage month
items:
$ref: '#/components/schemas/FrontendUsageData'
required:
- project_id
- month
- metrics
RealtimeConfig:
type: object
description: |
Realtime configuration for a project.
Note: Message size and channels per connection are plan-based (not configurable).
properties:
project_id:
type: string
format: uuid
description: Project ID
enabled:
type: boolean
description: Whether realtime is enabled for this project
default: false
broadcast_enabled:
type: boolean
description: Whether broadcast channels are enabled
default: true
presence_enabled:
type: boolean
description: Whether presence tracking is enabled
default: true
postgres_changes_enabled:
type: boolean
description: Whether Postgres change notifications are enabled
default: true
created_at:
type: string
format: date-time
description: When the configuration was created
updated_at:
type: string
format: date-time
description: When the configuration was last updated
RealtimePlanLimits:
type: object
description: Plan-based limits for realtime features
properties:
plan:
type: string
description: Public plan name (HOBBY or SUPERAGENT).
example: HOBBY
max_connections:
type: integer
description: Maximum concurrent connections allowed
example: 100
messages_per_month:
type: integer
description: Maximum messages per month
example: 1000000
message_size_kb:
type: integer
description: Maximum message size in KB
example: 32
channels_per_conn:
type: integer
description: Maximum channels per connection
example: 100
RealtimeStats:
type: object
description: Realtime usage statistics for a project
properties:
num_connections:
type: integer
description: Current number of active connections
peak_connections:
type: integer
description: Peak concurrent connections this usage period
last_invoked_at:
type: string
format: date-time
description: Most recent realtime activity timestamp across channels
limits:
$ref: '#/components/schemas/RealtimePlanLimits'
ResolveFunctionResponse:
type: object
properties:
name:
type: string
maxLength: 63
pattern: ^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$
description: DNS-safe function name
function_id:
type: string
format: uuid
description: Canonical function ID used for invocation routing
invoke_url:
type: string
description: 'Canonical HTTPS endpoint for invoking this function. Use it as-is: it does not share a domain with the API, so a host derived from the API URL will not reach the function. Omitted when the deployment serves no public invocation domain, as in local development; invoke through POST /functions/{functionId}/invoke instead.'
cache_ttl_seconds:
type: integer
minimum: 1
description: Suggested SDK cache TTL for this name-to-ID mapping
required:
- name
- function_id
- cache_ttl_seconds
ScheduleRequest:
type: object
required:
- cron_expression
properties:
kind:
type: string
enum:
- cron
default: cron
cron_expression:
type: string
description: Standard 5-field cron expression evaluated in UTC. Seconds fields, descriptors, and Quartz syntax are not supported.
example: '*/5 * * * *'
ServiceKey:
type: object
description: |
Service role key for admin operations.
**WARNING:** Bypasses all RLS - backend use only!
properties:
id:
type: string
format: uuid
project_id:
type: string
format: uuid
name:
type: string
description: Descriptive name for the key
key_value:
type: string
description: |
Full JWT token for Authorization header.
Returned on create, get, and list (decrypted from storage).
**Store securely - NEVER expose in frontend code!**
key_prefix:
type: string
description: First 12 characters of the key for display/identification
maxLength: 12
permissions:
type: array
items:
type: string
description: |
Operations this key may perform. ["*"] grants full admin access
(default for keys created without an explicit scope). Scoped keys
list specific permissions, e.g. ["functions.invoke", "locks.manage"].
example:
- '*'
created_at:
type: string
format: date-time
updated_at:
type: string
format: date-time
required:
- id
- name
- key_prefix
- permissions
StorageBucket:
type: object
description: |
A named container for files within a project.
Public access is controlled at the file level via is_public on StorageObject.
properties:
id:
type: string
format: uuid
project_id:
type: string
format: uuid
name:
type: string
description: Bucket name (unique within project)
pattern: ^[a-zA-Z0-9_-]+$
minLength: 1
maxLength: 64
file_size_limit:
type: integer
format: int64
nullable: true
description: Maximum file size in bytes (null for no limit)
allowed_mime_types:
type: array
nullable: true
items:
type: string
description: Allowed MIME types (null for all types)
last_invoked_at:
type: string
format: date-time
description: Most recent bucket operation timestamp
created_at:
type: string
format: date-time
updated_at:
type: string
format: date-time
required:
- id
- name
StorageCopyRequest:
type: object
properties:
from:
type: string
description: Source path
to:
type: string
description: Destination path
required:
- from
- to
StorageListResponse:
type: object
properties:
objects:
type: array
items:
$ref: '#/components/schemas/StorageObject'
next_cursor:
type: string
description: Cursor for next page (empty if no more results)
StorageMoveRequest:
type: object
properties:
from:
type: string
description: Source path
to:
type: string
description: Destination path
required:
- from
- to
StorageObject:
type: object
properties:
id:
type: string
format: uuid
bucket_id:
type: string
format: uuid
name:
type: string
description: Full path within bucket (e.g., "users/abc123/avatar.png")
owner_id:
type: string
format: uuid
nullable: true
description: Auth user who uploaded (null for anonymous/service)
is_public:
type: boolean
default: false
description: |
If true, the file can be downloaded with just an anon key (no user authentication).
Files are private by default. Only the owner or a service key can change visibility.
size:
type: integer
format: int64
description: File size in bytes
mime_type:
type: string
description: MIME type
etag:
type: string
description: Entity tag for cache validation
metadata:
type: object
additionalProperties: true
description: |
Custom user metadata (key-value pairs).
Limits: Maximum 50 keys, maximum 10KB total serialized size.
created_at:
type: string
format: date-time
updated_at:
type: string
format: date-time
public_url:
type: string
format: uri
description: |
Shareable public URL for this file (only set for public files with is_public=true).
This URL requires NO authentication and can be embedded in HTML, shared via email, etc.
The URL is properly URL-encoded by the server - use it as-is without additional encoding.
required:
- id
- bucket_id
- name
- is_public
- size
- mime_type
StorageObjectWithBucket:
type: object
description: Storage object with bucket name included (for admin listing across buckets)
properties:
id:
type: string
format: uuid
bucket_id:
type: string
format: uuid
bucket_name:
type: string
description: Name of the bucket containing this object
name:
type: string
description: Full path within bucket
owner_id:
type: string
format: uuid
nullable: true
description: Auth user who uploaded (null for anonymous/service)
is_public:
type: boolean
default: false
size:
type: integer
format: int64
description: File size in bytes
mime_type:
type: string
etag:
type: string
metadata:
type: object
additionalProperties: true
created_at:
type: string
format: date-time
updated_at:
type: string
format: date-time
public_url:
type: string
format: uri
description: |
Shareable public URL for this file (only set for public files with is_public=true).
This URL requires NO authentication and can be embedded in HTML, shared via email, etc.
required:
- id
- bucket_id
- bucket_name
- name
- is_public
- size
- mime_type
StoragePolicy:
type: object
properties:
id:
type: string
format: uuid
bucket_id:
type: string
format: uuid
name:
type: string
description: Policy name (unique within bucket)
operation:
type: string
enum:
- SELECT
- INSERT
- UPDATE
- DELETE
description: Operation this policy applies to
definition:
type: string
description: |
Policy expression evaluated at request time.
Examples:
- "true" - Allow all
- "auth.uid() = owner_id" - Owner only
- "auth.role() = 'authenticated'" - Authenticated users
- "(storage.foldername(name))[1] = auth.uid()::text" - User's folder
created_at:
type: string
format: date-time
updated_at:
type: string
format: date-time
required:
- id
- bucket_id
- name
- operation
- definition
StorageStats:
type: object
description: Aggregate storage statistics for a project
properties:
bucket_count:
type: integer
description: Number of storage buckets
object_count:
type: integer
description: Total number of stored files
total_size:
type: integer
format: int64
description: Total storage used in bytes
required:
- bucket_count
- object_count
- total_size
StorageVisibilityRequest:
type: object
properties:
is_public:
type: boolean
description: Whether the file should be publicly accessible
required:
- is_public
UnbanUserResponse:
type: object
description: Response when unbanning a user
properties:
message:
type: string
example: User unbanned successfully
user_id:
type: string
format: uuid
email:
type: string
format: email
status:
type: string
enum:
- active
required:
- message
- user_id
- email
- status
TestEmailRequest:
type: object
required:
- to_email
description: |
When `html_body` or `text_body` is provided the backend renders
those (plus optional `subject`) through html/text templates
against the standard `Data` (ProjectName, Name, SiteURL)
and sends the result — used by the template-editor "Send Test"
affordance to preview an unsaved template. When both bodies are
omitted a hardcoded diagnostic message is sent to verify SMTP
credentials and `subject` is ignored. Sending `subject` alone
(without a body) is rejected with 400.
properties:
to_email:
type: string
format: email
description: Recipient address for the diagnostic email.
subject:
type: string
description: |
Optional subject override, rendered as a text/template. Only
applied on the override path — requires `html_body` or
`text_body` to also be set, otherwise the request is
rejected with 400.
html_body:
type: string
maxLength: 262144
description: Optional HTML body override. Rendered as an html/template. Max 256 KiB.
text_body:
type: string
maxLength: 262144
description: Optional plain-text body override. Rendered as a text/template. Max 256 KiB.
TestEmailResponse:
type: object
required:
- success
properties:
success:
type: boolean
UpdateAuthConfigRequest:
type: object
description: 'All fields optional - only include fields you want to update. Validation rule: require_email_confirmation=true requires email_enabled=true.'
properties:
access_token_lifetime:
type: integer
refresh_token_lifetime:
type: integer
inactivity_timeout:
type: integer
max_session_duration:
type: integer
min_password_length:
type: integer
minimum: 15
maximum: 128
require_uppercase:
type: boolean
require_lowercase:
type: boolean
require_numbers:
type: boolean
require_special_chars:
type: boolean
enable_signup:
type: boolean
description: Master switch for signups across ALL providers
enable_email_password:
type: boolean
description: Enable/disable email/password provider
rate_limit_signup:
type: integer
rate_limit_signin:
type: integer
rate_limit_token_refresh:
type: integer
cors_allow_credentials:
type: boolean
cors_max_age:
type: integer
enable_anonymous_signins:
type: boolean
allowed_email_domains:
type: array
maxItems: 100
description: |
Replaces the email domain allowlist. Empty array removes the
restriction so any domain can sign up. Entries must be bare domains
such as `domain1.com` and are stored normalized (lowercase, no `@`
prefix); matching is exact, so subdomains need their own entry. At
most 100 entries.
Restricting signups is a SUPERAGENT feature to configure and to enforce: a
HOBBY project can only remove the restriction and gets 403 for any
other change, and the list it keeps is parked until it upgrades.
items:
type: string
example:
- domain1.com
- domain2.com
allowed_email_domains_mode:
type: string
description: |
How far `allowed_email_domains` reaches. `signup` gates account
creation only. `signup_and_signin` also blocks sign-in for accounts
outside the list; switching to it, or narrowing the list while in
it, deletes the sessions of every account it locks out. `disabled`
keeps the list without enforcing it.
enum:
- disabled
- signup
- signup_and_signin
allow_password_reset:
type: boolean
password_reset_timeout:
type: integer
max_password_history:
type: integer
require_email_confirmation:
type: boolean
description: Require users to confirm email before sign-in. Can only be true when email_enabled is true.
email_confirmation_timeout:
type: integer
description: Email confirmation token expiry in seconds.
auto_link_verified_oauth:
type: boolean
description: Link a verified OAuth identity to an existing confirmed account with the same email instead of returning a conflict. Requires require_email_confirmation to be true.
email_enabled:
type: boolean
description: Enable transactional email sending. Cannot be false while require_email_confirmation is true.
email_from_address:
type: string
email_from_name:
type: string
smtp_host:
type: string
smtp_port:
type: integer
smtp_username:
type: string
smtp_password:
type: string
format: password
writeOnly: true
minLength: 1
description: Replacement SMTP password. Omit this field to preserve the configured password. The value is encrypted at rest and never returned.
smtp_use_tls:
type: boolean
email_confirmation_subject:
type: string
email_password_reset_subject:
type: string
email_password_changed_subject:
type: string
managed_auth_enabled:
type: boolean
description: Enable or disable managed auth hosted pages for the project.
post_auth_redirect_url:
type: string
description: Must be included in allowed_redirect_urls when set.
allowed_redirect_urls:
type: array
items:
type: string
description: Redirect allowlist. Every entry must be a valid http/https URL.
post_logout_redirect_url:
type: string
description: Must be included in allowed_redirect_urls when set.
device_verification_url:
type: string
description: |
Optional custom device-authorization verification page. Must be a
valid http/https URL (not tied to allowed_redirect_urls). When set,
device-code logins return this URL (with user_code) instead of the
managed device page. Send an empty string to clear the override.
UpdateAuthHostedPageRequest:
type: object
required:
- html
properties:
html:
type: string
description: Raw HTML markup for the page. Max 256 KiB.
css:
type: string
description: Optional CSS injected at render time. Max 256 KiB.
UpdateAuthPageLayoutRequest:
type: object
additionalProperties: false
required:
- layout
properties:
layout:
$ref: '#/components/schemas/AuthPageLayout'
UpdateAuthPageThemeRequest:
type: object
additionalProperties: false
required:
- theme
properties:
theme:
$ref: '#/components/schemas/AuthPageTheme'
UpdateDatabaseTypeRequest:
type: object
description: Update database compute size tier
properties:
database_type:
type: string
description: New compute size tier
enum:
- volcano-db-xs
- volcano-db-s
- volcano-db-m
- volcano-db-l
- volcano-db-xl
- volcano-db-2xl
example: volcano-db-m
required:
- database_type
UpdateEmailTemplateRequest:
type: object
properties:
subject:
type: string
html_body:
type: string
text_body:
type: string
UpdateFunctionRequest:
type: object
additionalProperties: false
minProperties: 1
properties:
is_public:
type: boolean
description: |
Function visibility for anon-key invocation.
- `false` (default): private function
- `true`: public function (anon keys with `functions.invoke` can invoke)
invocation_mode:
$ref: '#/components/schemas/FunctionInvocationMode'
http_auth_mode:
$ref: '#/components/schemas/FunctionHTTPAuthMode'
openapi_spec:
type: object
nullable: true
additionalProperties: true
description: OpenAPI 3.0 or 3.1 metadata for HTTP mode. Send null to clear it.
UpdateFunctionSchedulerRequest:
type: object
properties:
name:
type: string
maxLength: 200
enabled:
type: boolean
schedule:
$ref: '#/components/schemas/ScheduleRequest'
payload:
type: object
additionalProperties: true
regions:
type: array
maxItems: 1
items:
type: string
UpdateOAuthConfigRequest:
type: object
properties:
client_id:
type: string
description: Supported for non-device providers. Not supported for `provider=device`.
client_secret:
type: string
description: Supported for non-device providers. Not supported for `provider=device`.
redirect_url:
type: string
format: uri
scopes:
type: array
items:
type: string
enabled:
type: boolean
UpdateProjectRequest:
type: object
description: Update mutable project fields (name and/or region policy)
properties:
name:
type: string
minLength: 1
maxLength: 255
example: my-awesome-app-renamed
all_regions:
type: boolean
description: |
If omitted and `selected_regions` is also omitted, existing region policy is preserved.
If `selected_regions` is provided without `all_regions`, it is treated as subset mode.
selected_regions:
type: array
items:
type: string
description: |
Region subset for project deployments.
Provide with `all_regions=false`.
example:
- us-east-1
UpdateRealtimeConfigRequest:
type: object
description: |
Request to update realtime configuration.
Limits (message size, channels per connection) are plan-based and cannot be configured.
properties:
enabled:
type: boolean
description: Whether realtime is enabled for this project
broadcast_enabled:
type: boolean
description: Whether broadcast channels are enabled
presence_enabled:
type: boolean
description: Whether presence tracking is enabled
postgres_changes_enabled:
type: boolean
description: Whether Postgres change notifications are enabled
UpdateStorageBucketRequest:
type: object
properties:
file_size_limit:
type: integer
format: int64
allowed_mime_types:
type: array
items:
type: string
UpdateVariableRequest:
type: object
properties:
shared:
type: boolean
description: Include this name in the project's shared function variables. Omission preserves existing membership; new variables default to true for legacy clients. Send false explicitly to create a non-shared variable.
value:
type: string
required:
- value
UploadSessionPart:
type: object
description: Information about an uploaded part
properties:
part_number:
type: integer
description: Part number (1-10000)
etag:
type: string
description: ETag of the uploaded part
size:
type: integer
format: int64
description: Size of the part in bytes
UploadSessionStatusResponse:
type: object
description: Status of an upload session
properties:
session_id:
type: string
description: Upload session ID
status:
type: string
enum:
- pending
- uploading
- completing
- completed
- aborted
description: Current status of the upload
path:
type: string
description: Target file path
content_type:
type: string
description: MIME type
total_size:
type: integer
format: int64
description: Total file size in bytes
part_size:
type: integer
format: int64
description: Size of each part (except last)
total_parts:
type: integer
description: Total number of parts
parts_uploaded:
type: integer
description: Number of parts uploaded
bytes_uploaded:
type: integer
format: int64
description: Total bytes uploaded so far
parts:
type: array
description: List of uploaded parts (for resume)
items:
$ref: '#/components/schemas/UploadSessionPart'
expires_at:
type: string
format: date-time
description: Session expiry time
created_at:
type: string
format: date-time
description: Session creation time
UsageDataPoint:
type: object
description: A single timestamped usage value.
properties:
timestamp:
type: string
format: date-time
description: UTC timestamp for the data point
value:
type: integer
format: int64
description: Usage value at the timestamp
required:
- timestamp
- value
Variable:
type: object
properties:
shared:
type: boolean
description: Include this name in the project's shared function variables. Omission preserves existing membership; new variables default to true for legacy clients. Send false explicitly to create a non-shared variable.
id:
type: string
format: uuid
project_id:
type: string
format: uuid
name:
type: string
maxLength: 256
value:
type: string
status:
type: string
enum:
- provisioning
- active
- failed
description: Latest project variable propagation status, when a sync has run.
current_sync_id:
type: string
format: uuid
description: Identifier of the latest variable propagation sync.
provisioning_started_at:
type: string
format: date-time
description: Timestamp when the current variable propagation phase started.
deploy_source:
type: string
enum:
- git
- cli
- web
- api
- system
- unknown
description: What initiated the latest variable propagation sync, when one has run.
created_at:
type: string
format: date-time
updated_at:
type: string
format: date-time
required:
- id
- project_id
- name
- value
- created_at
- updated_at
ProjectGitConnectionSummary:
type: object
properties:
repo_installation_id:
type: integer
format: int64
repo_id:
type: integer
format: int64
repo_full_name:
type: string
root_directory:
type: string
production_branch:
type: string
updated_at:
type: string
format: date-time
required:
- repo_installation_id
- repo_id
- repo_full_name
- root_directory
- production_branch
- updated_at
ProjectHealthSummary:
type: object
properties:
status:
$ref: '#/components/schemas/ProjectHealthStatus'
required:
- status
FunctionKind:
type: string
enum:
- standard
- durable
default: standard
description: |
Which kind of function this is. `standard` runs once per invocation.
`durable` checkpoints its progress and resumes from the last completed
step, and is invoked asynchronously through its own executions
collection. A function's kind is fixed when it is created and cannot be
changed afterwards. Omitting this field means `standard`.
AuthPageThemeColors:
type: object
additionalProperties: false
required:
- background
- surface
- text
- accent
- accent_text
properties:
background:
type: string
pattern: ^#[0-9a-fA-F]{6}$
surface:
type: string
pattern: ^#[0-9a-fA-F]{6}$
text:
type: string
pattern: ^#[0-9a-fA-F]{6}$
accent:
type: string
pattern: ^#[0-9a-fA-F]{6}$
accent_text:
type: string
pattern: ^#[0-9a-fA-F]{6}$
ProjectConfigAuthPageLayouts:
type: object
additionalProperties: false
properties:
login:
$ref: '#/components/schemas/AuthPageLayout'
signup:
$ref: '#/components/schemas/AuthPageLayout'
forgot_password:
$ref: '#/components/schemas/AuthPageLayout'
device:
$ref: '#/components/schemas/AuthPageLayout'
verify_email:
$ref: '#/components/schemas/AuthPageLayout'
reset_password:
$ref: '#/components/schemas/AuthPageLayout'
ProjectConfigAuthPageAppearance:
type: object
additionalProperties: false
properties:
theme:
$ref: '#/components/schemas/AuthPageTheme'
layouts:
$ref: '#/components/schemas/ProjectConfigAuthPageLayouts'
ManagedProjectConfigFrontendCustomDomainTLSConfig:
type: object
description: Volcano issues and renews the certificate. Certificate fields are not allowed.
additionalProperties: false
properties:
mode:
type: string
enum:
- managed
required:
- mode
BYOCProjectConfigFrontendCustomDomainTLSConfig:
type: object
description: 'Your own certificate. Send `certificate_pem` and `private_key_pem` together, with an optional `certificate_chain_pem`, to create the domain or rotate its certificate. For an existing BYOC domain, `mode: byoc` without certificate fields keeps the stored certificate; exports render only the mode.'
additionalProperties: false
not:
anyOf:
- required:
- certificate_pem
not:
required:
- private_key_pem
- required:
- private_key_pem
not:
required:
- certificate_pem
- required:
- certificate_chain_pem
not:
required:
- certificate_pem
- private_key_pem
properties:
mode:
type: string
enum:
- byoc
description: Optional; a TLS block without `mode` is BYOC.
certificate_pem:
type: string
maxLength: 65536
description: PEM-encoded certificate for create or rotation. Requires private_key_pem. Omitted from exports.
private_key_pem:
type: string
maxLength: 65536
description: PEM-encoded private key for create or rotation. Requires certificate_pem. Omitted from exports.
certificate_chain_pem:
type: string
maxLength: 65536
description: Optional PEM-encoded certificate chain. Requires certificate_pem and private_key_pem. Omitted from exports.
ProjectConfigFrontendCustomDomainTLSConfig:
description: TLS for the custom domain. `mode` defaults to `byoc` when omitted.
oneOf:
- $ref: '#/components/schemas/ManagedProjectConfigFrontendCustomDomainTLSConfig'
- $ref: '#/components/schemas/BYOCProjectConfigFrontendCustomDomainTLSConfig'
DatabaseQueryPerformanceDatabase:
type: object
properties:
id:
type: string
format: uuid
name:
type: string
required:
- id
- name
DatabaseQueryPerformanceItem:
type: object
properties:
query_id:
type: string
description: pg_stat_statements query identifier.
query:
type: string
maxLength: 8192
description: Normalized and obfuscated representative query text.
database:
$ref: '#/components/schemas/DatabaseQueryPerformanceDatabase'
role:
type: string
description: Database role used for the query.
calls:
type: integer
format: int64
total_exec_time_seconds:
type: number
format: double
description: Cumulative total execution time from pg_stat_statements in seconds.
max_exec_time_seconds:
type: number
format: double
mean_exec_time_seconds:
type: number
format: double
min_exec_time_seconds:
type: number
format: double
rows_processed:
type: integer
format: int64
required:
- query_id
- query
- database
- role
- calls
- total_exec_time_seconds
- max_exec_time_seconds
- mean_exec_time_seconds
- min_exec_time_seconds
- rows_processed
DeploymentPhase:
type: object
description: Timing and outcome for one normalized deployment pipeline phase.
properties:
name:
type: string
enum:
- queue
- checkout
- build
- image
- provisioning
- rollout
- verification
status:
type: string
enum:
- pending
- in_progress
- succeeded
- failed
- skipped
started_at:
type: string
format: date-time
completed_at:
type: string
format: date-time
duration_seconds:
type: integer
format: int64
minimum: 0
required:
- name
- status
DeploymentProgress:
type: object
description: Normalized live progress derived from the deployment workflow and build phases.
properties:
current_phase:
type: string
enum:
- queue
- checkout
- build
- image
- provisioning
- rollout
- verification
started_at:
type: string
format: date-time
completed_at:
type: string
format: date-time
elapsed_seconds:
type: integer
format: int64
minimum: 0
phases:
type: array
minItems: 7
maxItems: 7
items:
$ref: '#/components/schemas/DeploymentPhase'
updated_at:
type: string
format: date-time
required:
- started_at
- elapsed_seconds
- phases
- updated_at
LogDeploymentRequestSelector:
type: object
description: Deployment log selector for deployable resources.
additionalProperties: false
properties:
ids:
type: array
maxItems: 25
description: Optional deployment identifiers. Omit or send an empty array to include every deployment for the selected resources.
items:
type: string
format: uuid
LogFunctionRequestResource:
type: object
description: Edge Function log resource selector.
additionalProperties: false
properties:
type:
type: string
enum:
- function
description: Resource type to read logs for.
ids:
type: array
maxItems: 25
description: Optional function identifiers. Omit or send an empty array to include every function in the project.
items:
type: string
format: uuid
deployments:
$ref: '#/components/schemas/LogDeploymentRequestSelector'
required:
- type
LogFrontendRequestResource:
type: object
description: Frontend log resource selector.
additionalProperties: false
properties:
type:
type: string
enum:
- frontend
description: Resource type to read logs for.
ids:
type: array
maxItems: 25
description: Optional frontend identifiers. Omit or send an empty array to include every frontend in the project.
items:
type: string
format: uuid
deployments:
$ref: '#/components/schemas/LogDeploymentRequestSelector'
required:
- type
LogDatabaseRequestResource:
type: object
description: Database runtime log resource selector. Deployment logs are not supported for databases.
additionalProperties: false
properties:
type:
type: string
enum:
- database
description: Resource type to read logs for.
ids:
type: array
maxItems: 25
description: Optional database identifiers. Omit or send an empty array to include every database in the project.
items:
type: string
format: uuid
required:
- type
LogRequestResource:
description: Resource selectors for project log reads.
oneOf:
- $ref: '#/components/schemas/LogFunctionRequestResource'
- $ref: '#/components/schemas/LogFrontendRequestResource'
- $ref: '#/components/schemas/LogDatabaseRequestResource'
discriminator:
propertyName: type
mapping:
function: '#/components/schemas/LogFunctionRequestResource'
frontend: '#/components/schemas/LogFrontendRequestResource'
database: '#/components/schemas/LogDatabaseRequestResource'
LogResource:
type: object
description: Resource that owns a historical log event.
properties:
type:
type: string
enum:
- function
- frontend
- database
description: Resource type that owns the log event.
id:
type: string
format: uuid
description: Resource ID that owns the log event.
name:
type: string
description: Resource name associated with the log event, when available.
required:
- type
- id
LogDeployment:
type: object
description: Deployment context associated with a historical deployment log event.
properties:
id:
type: string
format: uuid
description: Deployment ID associated with the log event.
stage:
type: string
enum:
- compile
- publish
description: Deployment stage that produced the log event, when available.
required:
- id
DatabaseQueryFilter:
type: object
description: One WHERE condition. Conditions are combined with AND.
properties:
column:
type: string
example: status
operator:
type: string
enum:
- eq
- neq
- gt
- gte
- lt
- lte
- like
- ilike
- is
- in
example: eq
description: |
Filter operators:
- eq: equals (=)
- neq: not equals (<>)
- gt: greater than (>)
- gte: greater than or equal (>=)
- lt: less than (<)
- lte: less than or equal (<=)
- like: pattern match (LIKE)
- ilike: case-insensitive pattern match (ILIKE)
- is: IS NULL / IS NOT NULL
- in: IN array
value:
oneOf:
- type: string
nullable: true
- type: number
- type: boolean
- type: array
description: Array of values, for the `in` operator
items:
oneOf:
- type: string
- type: number
- type: boolean
example: published
required:
- column
- operator
- value
DatabaseQueryOrder:
type: object
description: One ORDER BY clause.
properties:
column:
type: string
example: created_at
ascending:
type: boolean
default: true
example: false
nulls_first:
type: boolean
default: false
required:
- column
FunctionRuntimeDeployment:
type: object
required:
- file_extensions
- entrypoint
- handler
- dependency_manifests
properties:
file_extensions:
type: array
description: Source file extensions the CLI can use to detect this runtime.
items:
type: string
example:
- .js
- .mjs
entrypoint:
type: string
description: Archive path the CLI should use for a single-file function source.
example: index.js
handler:
type: string
description: Handler symbol the CLI should submit when deploying this runtime.
example: handler
dependency_manifests:
type: array
description: Dependency manifest files the CLI should include for hosted builds.
items:
type: string
example:
- package.json
- package-lock.json
AuthHostedPageDefaults:
type: object
required:
- html
- css
description: |
The starting point for an unsaved page: the theme shell we render for the
built-in page plus its stylesheet. Valid input to the update endpoint —
it carries no script, meta, or link tags.
properties:
html:
type: string
description: Body shell markup containing the runtime render root.
css:
type: string
description: The built-in stylesheet, themed by the customer.
AuthHostedPageRuntime:
type: object
required:
- root_id
- script
- mock_prelude
description: |
The server-owned behavior of a hosted page. Clients compose previews from
this instead of reimplementing the page, so a preview cannot drift from
what is actually served.
properties:
root_id:
type: string
description: Element id the runtime script renders into. Markup carrying it opts into the theme-shell contract.
script:
type: string
description: The runtime script injected into the rendered page.
mock_prelude:
type: string
description: Preview harness that supplies request params and stubs the hosted-auth API. Never served on a real page.
AuthPageAppearanceDefaults:
type: object
required:
- theme
- layout
properties:
theme:
$ref: '#/components/schemas/AuthPageTheme'
layout:
$ref: '#/components/schemas/AuthPageLayout'
AuthPageAppearanceOptions:
type: object
required:
- pages
- fonts
- scales
- densities
- radii
- layouts
properties:
pages:
type: array
items:
$ref: '#/components/schemas/HostedAuthPageType'
fonts:
type: array
items:
$ref: '#/components/schemas/AuthPageFont'
scales:
type: array
items:
$ref: '#/components/schemas/AuthPageScale'
densities:
type: array
items:
$ref: '#/components/schemas/AuthPageDensity'
radii:
type: array
items:
$ref: '#/components/schemas/AuthPageRadius'
layouts:
type: array
items:
$ref: '#/components/schemas/AuthPageLayout'