Platform

Deploy a catalog app

Installs an app from the curated catalog on the target agent. Returns immediately with status: pending; poll GET /platform/deployments/{id} until it reaches running (typically 30 s – 3 min depending on the app).

You can install the same app multiple times on one agent — the platform assigns each instance its own host port automatically, so they coexist without conflict. (Fixed-protocol apps like RustDesk are the exception — one per server.)

Network mode (declared on the catalog manifest, not passed in the request — every catalog app picks one). Drives whether the response carries a domain (HTTP path) or a connection_info: {ip, ports, public_key} block (raw TCP/UDP path) for reachability:

  • http (default) — app speaks HTTP. Behind Caddy + Let's Encrypt at an imprezaapps.com subdomain (or a customer domain). The domain handling rules below apply.
  • host_ports — app speaks raw TCP/UDP (RustDesk: 21115/tcp, 21116/tcp + 21116/udp, 21117/tcp, 21118/tcp, 21119/tcp). No Caddy, no cert, no domain. Response carries connection_info with the reachable ip, the ports list (with manifest labels), and — for apps that emit one on the boot log — a public_key the server auto-captures (RustDesk does this). Clients connect to <ip>:<port> with the app's own encryption. The domain field in the body is ignored.
  • hybrid — raw protocol ports AND an HTTP admin UI behind Caddy on a subdomain. Response carries BOTH domain (admin UI) and connection_info (raw ports).

Port-conflict guard: fixed protocol ports can only be bound once per host, so a second host_ports/hybrid deploy on the same agent that reuses a port returns 409 CONFLICT.

Domain handling — match the clientarea behavior across all callers (API, CLI, MCP). Applies to http + hybrid modes; host_ports ignores the domain field entirely:

  • Leave domain empty → server auto-generates <app-slug>-<6hex>.imprezaapps.com, creates the Cloudflare A record at the agent's public IP, and uses it as the deployment hostname. Most common path for new customers.
  • Pass domain ending in .imprezaapps.com → server ensures a Cloudflare A record exists for that exact name (idempotent — reuses if already there).
  • Pass a domain you own → passthrough; you handle DNS (point an A record at the agent's public IP before deploy so Let's Encrypt can issue). Cold standby exception: with standby: true, no hostname is generated. Omit domain, onion and vars.domain; only the reviewed Memos 0.31.0 recipe is accepted.
post/platform/deployments

Request

  • Base URL: https://api.imprezahost.com/v1
  • URL: https://api.imprezahost.com/v1/platform/deployments
  • Auth: API key in header X-API-Key and API key in header X-API-Secret

Request body

standbyboolean

Create a cold standby without a public route. Requires the failover_enabled gate. Only the reviewed Memos 0.31.0 catalog version is supported. Omit domain, onion, and vars.domain. A standby receives no auto-generated hostname and no Tor service. Private onion, customer domains, database bindings and unreviewed recipes are unsupported. Creation does not pair, copy data or switch traffic; use the failover standby workflow.

app_namestring required

Name of the catalog app (e.g. vaultwarden).

agent_idstring required
app_versionstring

Specific version. Defaults to latest_version from the catalog.

domainstring

Public hostname the app will respond on (FQDN, no scheme). Optional — leave empty to get an auto-generated <slug>-<6hex>.imprezaapps.com subdomain. When set to a *.imprezaapps.com name, the server ensures the Cloudflare record exists. For customer-owned apex domains, point the A record at the agent IP before calling so Let's Encrypt can issue.

Uniqueness: *.imprezaapps.com is a shared namespace — first-come-first-served across all accounts. Picking a name already claimed by any live deployment (yours or someone else's) returns 400 INVALID_REQUEST with a neutral "already in use" message (no enumeration on other accounts). Names are released when the deploy fully uninstalls.

onionboolean

Also publish a Tor v3 hidden service alongside the clearnet URL.

varsobject

App-specific variables. The exact keys depend on the manifest — call GET /platform/apps/{name} to see declared vars with their required / default / generate settings.

Example request

{
  "app_name": "vaultwarden",
  "agent_id": "agt_4bcbffef132a2089",
  "app_version": "1.32.0",
  "domain": "vault.example.com",
  "vars": {
    "signups_allowed": "true"
  }
}

Response

Deployment enqueued

Changes

No recorded changes to this operation across all 1 revision of this API.