Skip to main content
An app is org-level: it belongs to the organization, not to an agent, and outlives any session. Seventeen methods: fourteen on an app itself, plus installs.apply / installs.list for the declaration a project is applied from and artifacts.list for the catalog it is applied out of. API detail: Apps.

create

POST /v1/apps. AppCreate is { name, description?, type?, mcp? }type is "frontend_only" (default) or "fullstack"; mcp is the path of the MCP endpoint a fullstack app serves ("/mcp"), refused on frontend_only. Idempotent on the name.

list

GET /v1/apps, cursor-paginated.

get

GET /v1/apps/{id}. A fullstack app’s backend advances on read — poll here until status is terminal.

update

PATCH /v1/apps/{id}. AppPatch is { description?: string | null, mcp?: string | null }. Setting mcp mints the app’s VETTA_MCP_TOKEN secret and connects every agent that can access the app to its tools as <app>.<tool>; null removes both. See Tools from your apps.

delete

DELETE /v1/apps/{id}. Tears down the hosting project and, for fullstack, the app database. Irreversible.

deploy

POST /v1/apps/{id}/deployments. files maps paths to base64 contents; the build runs asynchronously.

deployments

GET /v1/apps/{id}/deployments. Non-terminal builds advance on read.

setSecret

POST /v1/apps/{id}/secrets. Write-only: the value never comes back on any read. Overwrites an existing name.

secrets

GET /v1/apps/{id}/secrets — names and timestamps only, never values.

deleteSecret

DELETE /v1/apps/{id}/secrets/{name}.

connectDomain

POST /v1/apps/{id}/domains. The domain must already exist at client.domains; connecting is pointing, never registering.

domains

GET /v1/apps/{id}/domains.

disconnectDomain

DELETE /v1/apps/{id}/domains/{domain} — by domain name.

query

POST /v1/apps/{id}/db/query. fullstack apps only; a frontend_only app answers feature_not_configured.

installs.apply

POST /v1/blueprints/installs. Records one applied declaration for a project — with what, by whom, and against which revision — and, when you name a published pair instead of sending one, performs the apply too. Sending a declaration records only, and that is the right shape for this client: you reconciled it yourself, which is the upsert-by-name every other method here performs, so report comes back null. Omitting the declaration and naming a published blueprint and template asks the server to reconcile the catalog’s bytes for you, as you, and report is what that run did — one line per resource, refusals included. expected_revision is expected_version copied: omit it for a deliberate unconditional apply, or send the revision you believe you are moving from and a mismatch is refused revision_conflict, whose message names the paths at which the stored declaration and yours disagree.

installs.list

GET /v1/blueprints/installs. Every install in the organization, most recently applied first.

artifacts.list

GET /v1/blueprints/artifacts. The published catalog, newest release first — every blueprint × template that can be run, carrying the setup questions to ask first, the crew and the apps it provisions, and the timers it runs. The catalog belongs to no organization: it is the same list for everybody, and nothing a customer writes reaches it. Applying one of these rows sends its blueprint and template in place of a declaration, which the catalog holds server-side.