TypeScript SDK
Reference for fastvm. Auto-generated from the OpenAPI spec.
Install
npm install fastvmImport
import { FastvmClient } from 'fastvm'; const client = new FastvmClient(); // reads FASTVM_API_KEY / FASTVM_BASE_URL
Top-level helpers
client.*
client.uploadhelper
client.upload( vmId: string, localPath: string, remotePath: string, opts?: { fetchTimeoutSec?: number; execTimeoutSec?: number }, ): Promise<void>
Description
Copy a local file or directory into the VM. Uses vms.files.presign
and vms.files.fetch under the hood. Directories are tarred on the
fly before upload and extracted VM-side after fetch.
Streams end-to-end with no intermediate copy to /tmp on the client,
so multi-GB transfers are bounded by VM disk, not RAM. Directory
mode needs the tar binary on the client's PATH (standard on
macOS and Linux; available on modern Windows via bsdtar).
Parameters
| Param | Type | Default | Description |
|---|---|---|---|
| vmId | string | required | Target VM id. |
| localPath | string | required | Local file or directory path. |
| remotePath | string | required | Destination path inside the VM. |
| opts.fetchTimeoutSec | number | 600 | Timeout on the VM-side /files/fetch call. |
| opts.execTimeoutSec | number | 600 | Timeout on VM-side tar extraction. |
Returns
Promise<void>Example
await client.upload(vm.id, './config.toml', '/etc/app.toml'); await client.upload(vm.id, './src', '/root/src');
client.downloadhelper
client.download( vmId: string, remotePath: string, localPath: string, opts?: { fetchTimeoutSec?: number; execTimeoutSec?: number }, ): Promise<void>
Description
Copy a file or directory from the VM to the client. Uses
vms.files.presign plus a VM-side exec to classify the path and
stream its contents out. Directories are tarred VM-side and
un-tarred on the client, rooted at ./ so upload and download are
symmetric.
Streams end-to-end with no intermediate copy. Missing paths raise
FileNotFoundError (Python) or FileTransferError with
code: 'ENOENT' (TypeScript).
Parameters
| Param | Type | Default | Description |
|---|---|---|---|
| vmId | string | required | Target VM id. |
| remotePath | string | required | Source path inside the VM. |
| localPath | string | required | Destination path on the client. |
| opts.fetchTimeoutSec | number | 600 | Timeout on VM-side /files/fetch. |
| opts.execTimeoutSec | number | 600 | Timeout on VM-side exec. |
Returns
Promise<void>Example
await client.download(vm.id, '/root/out.log', './out.log'); await client.download(vm.id, '/var/log', './log-backup');
client.waitForVmReadyhelper
client.waitForVmReady( vmId: string, opts?: { pollIntervalMs?: number; timeoutMs?: number }, ): Promise<VM>
Description
Poll GET /v1/vms/{id} until the VM reaches status == "running" or
a terminal failure status. Same polling logic as vms.launch; use
this when you already have a VM id from vms.list() or another flow.
Parameters
| Param | Type | Default | Description |
|---|---|---|---|
| vmId | string | required | Target VM id. |
| opts.pollIntervalMs | number | 2000 | Milliseconds between polls. |
| opts.timeoutMs | number | 300000 | Total wait deadline in ms. |
Returns
Promise<>Example
let vm = await client.vms.retrieve(someId); vm = await client.waitForVmReady(vm.id, { timeoutMs: });
VMs
client.vms.*
client.vms.list
GET/v1/vmsclient.vms.list( status: VMStatus, ): APIPromise<VM[]>
Description
List VMs
Parameters
| Param | Type | Default | Description |
|---|---|---|---|
| status | VMStatus | — | Restrict to VMs with this status. Accepts any value of VMStatus; unknown values return an empty list. |
Returns
[]client.vms.launchoverride
POST/v1/vmsclient.vms.launch( params: VmLaunchParams, options?: RequestOptions, launchOpts?: { wait?: boolean; pollIntervalMs?: number; timeoutMs?: number }, ): APIPromise<VM>
Description
Launch a VM and (by default) block until it reaches status == "running".
POST /v1/vms returns 201 for immediately-running VMs and 202 for queued
VMs; the override handles both paths transparently by polling
GET /v1/vms/{id}.
Pass wait=false (TS) / wait=False (Python) to skip polling and
return the raw 201/202 body. Pass snapshot_id / snapshotId to
restore from a snapshot instead of cold-booting.
Terminal failure statuses (error, stopped, deleting) raise
VMLaunchError. Polling-deadline exceeded raises VMNotReadyError.
Parameters
| Param | Type | Default | Description |
|---|---|---|---|
| params | VmLaunchParams | required | Generated launch params (machineType, snapshotId, name, metadata, firewall). |
| options | RequestOptions | undefined | undefined | Generated per-request options (headers, signal, timeout, etc.). |
| launchOpts.wait | boolean | true | Block until RUNNING. Set false for raw 201/202 behavior. |
| launchOpts.pollIntervalMs | number | 2000 | Milliseconds between polls (±10% jitter applied). |
| launchOpts.timeoutMs | number | 300000 | Total polling deadline in ms. Throws VMNotReadyError on exceed. |
Returns
APIPromise<>Example
import { FastvmClient } from 'fastvm'; const client = new FastvmClient(); const vm = await client.vms.launch({ machineType: 'c1m2', name: 'dev' }); console.log(vm.id, vm.status); // "running" // Restore from snapshot const fromSnap = await client.vms.launch({ snapshotId: 'snp_...' }); // Skip polling — returns the raw 201/202 body const queued = await client.vms.launch( { machineType: 'c1m2' }, undefined, { wait: false }, );
client.vms.retrieve
GET/v1/vms/{id}client.vms.retrieve( id: string, ): APIPromise<VM>
Description
Get a VM
Parameters
| Param | Type | Default | Description |
|---|---|---|---|
| id | string | required | VM ID (UUID). |
Returns
client.vms.update
PATCH/v1/vms/{id}client.vms.update( id: string, name: string, metadata: Metadata, ttl: unknown, ): APIPromise<VM>
Description
Update a VM
Parameters
| Param | Type | Default | Description |
|---|---|---|---|
| id | string | required | VM ID (UUID). |
| name | string | — | |
| metadata | Metadata | — | |
| ttl | unknown | — |
Returns
client.vms.delete
DELETE/v1/vms/{id}client.vms.delete( id: string, ): APIPromise<DeleteResponse>
Description
Delete a VM
Parameters
| Param | Type | Default | Description |
|---|---|---|---|
| id | string | required | VM ID (UUID). |
Returns
client.vms.pause
POST/v1/vms/{id}/pauseclient.vms.pause( id: string, ): APIPromise<VM>
Description
Pause a VM
Parameters
| Param | Type | Default | Description |
|---|---|---|---|
| id | string | required | VM ID (UUID). |
Returns
client.vms.resume
POST/v1/vms/{id}/resumeclient.vms.resume( id: string, ): APIPromise<VM>
Description
Resume a paused VM
Parameters
| Param | Type | Default | Description |
|---|---|---|---|
| id | string | required | VM ID (UUID). |
Returns
client.vms.refreshTtl
POST/v1/vms/{id}/ttl/refreshclient.vms.refreshTtl( id: string, ): APIPromise<VM>
Description
Reset the VM's TTL cycle
Parameters
| Param | Type | Default | Description |
|---|---|---|---|
| id | string | required | VM ID (UUID). |
Returns
client.vms.setFirewall
PUT/v1/vms/{id}/firewallclient.vms.setFirewall( id: string, ingress: IngressPolicy, egress: EgressPolicy, dns: DNSPolicy, ): APIPromise<VM>
Description
Replace firewall policy
Parameters
| Param | Type | Default | Description |
|---|---|---|---|
| id | string | required | VM ID (UUID). |
| ingress | IngressPolicy | — | |
| egress | EgressPolicy | — | |
| dns | DNSPolicy | — |
Returns
client.vms.patchFirewall
PATCH/v1/vms/{id}/firewallclient.vms.patchFirewall( id: string, ingress: IngressPolicy, egress: EgressPolicy, dns: DNSPolicy, ): APIPromise<VM>
Description
Patch firewall policy
Parameters
| Param | Type | Default | Description |
|---|---|---|---|
| id | string | required | VM ID (UUID). |
| ingress | IngressPolicy | — | |
| egress | EgressPolicy | — | |
| dns | DNSPolicy | — |
Returns
client.vms.consoleToken
POST/v1/vms/{id}/console-tokenclient.vms.consoleToken( id: string, ): APIPromise<ConsoleTokenResponse>
Description
Mint a console token
Parameters
| Param | Type | Default | Description |
|---|---|---|---|
| id | string | required | VM ID (UUID). |
Returns
client.vms.runrefresh
POST/v1/vms/{id}/execclient.vms.run( id: string, params: VmRunParams, options?: RequestOptions, ): APIPromise<ExecVMResponse>
Description
Execute a command inside a VM. Same generated method as upstream. TypeScript doesn't silently iterate strings into characters, so no shell-string auto-wrap helper is needed. Pass an argv array directly.
Parameters
| Param | Type | Default | Description |
|---|---|---|---|
| id | string | required | Target VM id. |
| params | VmRunParams | required | Request body (command: string[], timeoutSec?: number). |
| options | RequestOptions | undefined | undefined | Generated per-request options. |
Returns
APIPromise<>Example
const result = await client.vms.run(vm.id, { command: ['python3', 'main.py', '--flag'], }); console.log(result.exitCode, result.stdout);
client.vms.streamhelper
client.vms.stream( id: string, body: VmRunParams, opts?: StreamOptions, ): AsyncIterable<ExecEvent>
Description
Stream exec output as typed events via Accept: application/x-ndjson.
Same endpoint as vms.run (POST /v1/vms/{id}/exec), but the server
emits a newline-delimited stream of ExecEvent objects instead of a
single buffered JSON response. Events are:
"o"— stdout chunk (decoded bytes indata)"e"— stderr chunk (decoded bytes indata)"x"— terminal exit event (exit_code,timed_out,duration_ms)
There is no 4 MiB per-stream cap on output. The HTTP connection stays
open until the command exits or timeout_sec fires server-side. Use
this for long-running processes (builds, test runners, live logs) where
you need incremental output without buffering the entire result.
Shell strings (Python only) are auto-wrapped into ["sh", "-c", ...]
exactly like vms.run.
Parameters
| Param | Type | Default | Description |
|---|---|---|---|
| id | string | required | Target VM id. |
| body | VmRunParams | required | Request body (command: string[], timeoutSec?: number, stdin?: string). |
| opts.timeoutMs | number | undefined (no client-side timeout) | Client-side HTTP abort deadline in milliseconds. |
Returns
AsyncIterable<>Example
import { FastvmClient, type ExecEvent } from 'fastvm'; const client = new FastvmClient(); for await (const event of client.vms.stream(vm.id, { command: ['make', '-j8'] })) { if (event.type === 'o') process.stdout.write(event.data); else if (event.type === 'e') process.stderr.write(event.data); else if (event.type === 'x') console.log(`exit ${event.exitCode} in ${event.durationMs}ms`); }
VMs.Services
client.vms.services.*
client.vms.services.list
GET/v1/vms/{id}/servicesclient.vms.services.list( id: string, ): APIPromise<Service[]>
Description
List service registrations
Parameters
| Param | Type | Default | Description |
|---|---|---|---|
| id | string | required | VM ID (UUID). |
Returns
[]client.vms.services.register
POST/v1/vms/{id}/servicesclient.vms.services.register( id: string, name: string, port: number, h2c: boolean, ): APIPromise<Service>
Description
Register a service on a VM
Parameters
| Param | Type | Default | Description |
|---|---|---|---|
| id | string | required | VM ID (UUID). |
| name | string | required | |
| port | number | required | |
| h2c | boolean | false | Optional. When true, the proxy uses HTTP/2 cleartext to the backend (required for gRPC). Defaults to false (HTTP/1.1). |
Returns
client.vms.services.update
PUT/v1/vms/{id}/services/{serviceName}client.vms.services.update( id: string, serviceName: string, port: number, h2c: boolean, ): APIPromise<Service>
Description
Register or update a service on a VM
Parameters
| Param | Type | Default | Description |
|---|---|---|---|
| id | string | required | VM ID (UUID). |
| serviceName | string | required | Service registration name. 1–29 chars, lowercase letters and digits with optional single internal hyphens (no leading, trailing, or consecutive hyphens). Embedded in the public URL as the leftmost label. |
| port | number | required | New TCP port. Same value as the existing entry is a no-op. |
| h2c | boolean | false | Optional. When true, the proxy uses HTTP/2 cleartext to the backend. Same value as the existing entry is a no-op; a different value updates the registered transport. |
Returns
client.vms.services.delete
DELETE/v1/vms/{id}/services/{serviceName}client.vms.services.delete( id: string, serviceName: string, )
Description
Deregister a service from a VM
Parameters
| Param | Type | Default | Description |
|---|---|---|---|
| id | string | required | VM ID (UUID). |
| serviceName | string | required | Service registration name. 1–29 chars, lowercase letters and digits with optional single internal hyphens (no leading, trailing, or consecutive hyphens). Embedded in the public URL as the leftmost label. |
VMs.Ssh_keys
client.vms.ssh_keys.*
client.vms.ssh_keys.list
GET/v1/vms/{id}/ssh-keysclient.vms.ssh_keys.list( id: string, ): APIPromise<SshKeyListResponse>
Description
List authorized SSH keys for a VM
Parameters
| Param | Type | Default | Description |
|---|---|---|---|
| id | string | required | VM ID (UUID). |
Returns
client.vms.ssh_keys.add
POST/v1/vms/{id}/ssh-keysclient.vms.ssh_keys.add( id: string, name: string, publicKey: string, ): APIPromise<SshKey>
Description
Register an SSH public key
Parameters
| Param | Type | Default | Description |
|---|---|---|---|
| id | string | required | VM ID (UUID). |
| name | string | — | Optional human label. |
| publicKey | string | required | OpenSSH-format public key (ssh-ed25519 AAA...). Comments are stripped. Newlines are rejected. |
Returns
Example
import { readFileSync } from "node:fs"; await client.vms.sshKeys.add(vm.id, { publicKey: readFileSync(`${process.env.HOME}/.ssh/id_ed25519.pub`, "utf8"), name: "laptop", }); // then: ssh root@<vm.publicIpv6>
client.vms.ssh_keys.delete
DELETE/v1/vms/{id}/ssh-keys/{fingerprint}client.vms.ssh_keys.delete( id: string, fingerprint: string, ): APIPromise<DeleteResponse>
Description
Remove an authorized SSH key
Parameters
| Param | Type | Default | Description |
|---|---|---|---|
| id | string | required | VM ID (UUID). |
| fingerprint | string | required | OpenSSH SHA256 fingerprint of the key to delete (e.g. SHA256:abc...). The base64 hash includes + and / and the prefix has :, so callers MUST URL-encode the value into the path segment. SDKs do this automatically. |
Returns
VMs.Files
client.vms.files.*
client.vms.files.presign
POST/v1/vms/{id}/files/presignclient.vms.files.presign( id: string, path: string, ): APIPromise<FilePresignResponse>
Description
Mint signed URLs for uploading a file to a VM
Parameters
| Param | Type | Default | Description |
|---|---|---|---|
| id | string | required | VM ID (UUID). |
| path | string | required | Absolute destination path inside the guest filesystem (where the file will land after fetchFileToVm). Used only to scope the staging object key; any value server-side is accepted here. |
Returns
Example
// High-level helpers — handle presign + PUT/GET + fetch + (for dirs) tar // for both file and directory transfers automatically. await client.upload(vm.id, './local/file.txt', '/root/file.txt'); await client.upload(vm.id, './local-dir', '/root/remote-dir'); await client.download(vm.id, '/root/out.log', './out.log'); await client.download(vm.id, '/var/log', './log-backup'); // Raw call if you need manual control over the signed-URL flow: const presign = await client.vms.files.presign(vm.id, { path: '/root/file.txt' });
client.vms.files.fetch
POST/v1/vms/{id}/files/fetchclient.vms.files.fetch( id: string, url: string, path: string, timeoutSec: number, ): APIPromise<ExecVMResponse>
Description
Fetch a file into a VM from a presigned URL
Parameters
| Param | Type | Default | Description |
|---|---|---|---|
| id | string | required | VM ID (UUID). |
| url | string | required | Must be the downloadUrl previously returned by POST /v1/vms/{id}/files/presign (URLs from other sources are rejected). |
| path | string | required | Absolute destination path inside the guest filesystem. |
| timeoutSec | number | — | Per-fetch timeout in seconds. |
Returns
Example
// You usually don't call this directly — client.upload() composes // presign + PUT + fetch in a single call. Use it when piping an // already-hosted URL (still from /files/presign) into the VM. await client.vms.files.fetch(vm.id, { url: presign.downloadUrl, path: '/root/file.txt', });
Snapshots
client.snapshots.*
client.snapshots.list
GET/v1/snapshotsclient.snapshots.list(): APIPromise<Snapshot[]>
Description
List snapshots
Returns
[]client.snapshots.create
POST/v1/snapshotsclient.snapshots.create( vmId: string, name: string, ): APIPromise<Snapshot>
Description
Create a snapshot from a VM
Parameters
| Param | Type | Default | Description |
|---|---|---|---|
| vmId | string | required | |
| name | string | — | Snapshot name (trimmed + whitespace-collapsed, max 64 runes; longer values are truncated server-side). Auto-generated as snapshot-<8-char-vmId-prefix> if empty. |
Returns
client.snapshots.retrieve
GET/v1/snapshots/{id}client.snapshots.retrieve( id: string, ): APIPromise<Snapshot>
Description
Get a snapshot
Parameters
| Param | Type | Default | Description |
|---|---|---|---|
| id | string | required | Snapshot ID (UUID). |
Returns
client.snapshots.update
PATCH/v1/snapshots/{id}client.snapshots.update( id: string, name: string, ): APIPromise<Snapshot>
Description
Rename a snapshot
Parameters
| Param | Type | Default | Description |
|---|---|---|---|
| id | string | required | Snapshot ID (UUID). |
| name | string | — |
Returns
client.snapshots.delete
DELETE/v1/snapshots/{id}client.snapshots.delete( id: string, ): APIPromise<DeleteResponse>
Description
Delete a snapshot
Parameters
| Param | Type | Default | Description |
|---|---|---|---|
| id | string | required | Snapshot ID (UUID). |
Returns
Builds
client.builds.*
client.builds.create
POST/v1/buildsclient.builds.create( name: string, imageRef: string, dockerfileContent: string, machineType: MachineType, diskGiB: number, contextDownloadUrl: string, ): APIPromise<BuildResponse>
Description
Build a snapshot from an image ref or Dockerfile
Parameters
| Param | Type | Default | Description |
|---|---|---|---|
| name | string | — | Optional human-readable name for the resulting snapshot. If omitted, the build ID is used. |
| imageRef | string | — | Docker image reference (e.g. python:3.13-slim, ghcr.io/user/repo:tag). Used directly on the no-Dockerfile path, and as a fallback FROM source otherwise. |
| dockerfileContent | string | — | Raw Dockerfile content to feed to buildah bud inside the build VM. Multi-stage, SHELL, RUN --mount, and every standard Dockerfile feature is supported (handled natively by buildah). Container-runtime metadata (CMD, ENTRYPOINT, EXPOSE, LABEL, HEALTHCHECK) is consumed by buildah but does not surface on the resulting FastVM snapshot — when the snapshot boots, systemd takes over, not the container's CMD. |
| machineType | MachineType | — | |
| diskGiB | number | — | Disk size for the build VM. Defaults to 10 GiB if omitted. |
| contextDownloadUrl | string | — | Presigned GET URL for a tar.gz of the build context. The worker downloads and extracts this into /tmp/buildctx before invoking buildah, so COPY instructions resolve against the user's files. Obtain via POST /v1/build-contexts/presign. |
Returns
Example
// Raw call (returns 202 immediately; poll for completion). const build = await client.builds.create({ imageRef: 'python:3.13-slim', dockerfileContent: 'FROM python:3.13-slim\nRUN pip install flask\n', });
client.builds.retrieve
GET/v1/builds/{id}client.builds.retrieve( id: string, ): APIPromise<BuildResponse>
Description
Get build status
Parameters
| Param | Type | Default | Description |
|---|---|---|---|
| id | string | required | Build ID (UUID). |
Returns
Build_contexts
client.build_contexts.*
client.build_contexts.presign
POST/v1/build-contexts/presignclient.build_contexts.presign(): APIPromise<FilePresignResponse>
Description
Mint signed URLs for uploading a build context tarball
Returns
Quotas
client.quotas.*
client.quotas.retrieve
GET/v1/org/quotasclient.quotas.retrieve(): APIPromise<OrgQuotaUsage>
Description
Get org quotas and usage
Returns
Types
Shared schemas referenced in parameters and return values.
DeleteResponse
object| Field | Type | Description |
|---|---|---|
| id | string | |
| deleted | boolean |
VMStatus
primitiveprovisioning, running, stopped, pausing, paused, resuming, deleting, error. Terminal failure statuses are error and stopped; transitional values (provisioning, pausing, resuming, deleting) indicate the VM is in flight. Additional values may be introduced in future server versions; clients should treat unknown values as "in transition" rather than as hard errors.SnapshotStatus
primitivecreating, ready, error. Additional values may be introduced in future server versions.MachineType
primitivec1m2, c2m4). Controls CPU and memory allocation. Must be supplied on launch unless restoring from a snapshot.VM
object| Field | Type | Description |
|---|---|---|
| id | string | |
| name | string | |
| orgId | string | |
| machineName | string | |
| sourceName | string | Source snapshot or image name (empty on fresh boot). |
| firewall | FirewallPolicy | |
| effectiveFirewall | unknown | Read-only composed view: firewall (the user policy) unioned with per-service auto-rules from this VM's registered services. Each auto-rule has source CIDR ::/0 and a description of the form auto: proxy service <name>. The same policy is what the worker firewall actually enforces. Set firewall to mutate; this field is computed per-response from firewall and the current service registry, never persisted. |
| metadata | Metadata | |
| envVars | EnvVars | |
| publicIpv6 | string | |
| cpu | number | |
| memoryMiB | number | |
| diskGiB | number | |
| status | VMStatus | |
| createdAt | string | |
| deletedAt | unknown | |
| ttl | unknown | Optional auto-action timer. Null when no TTL is configured. See TTL for semantics. |
| expiresAtMs | number | Absolute timestamp in ms when the TTL fires. Set only while the VM is running (the countdown freezes on pause). |
| ttlRemainingMs | number | Remaining cycle budget in ms. Set only while the VM is paused; restored to expiresAtMs on resume. |
| pausedAt | unknown | When the VM became paused; null otherwise. |
Snapshot
object| Field | Type | Description |
|---|---|---|
| id | string | |
| name | string | |
| orgId | string | |
| vmId | string | |
| firewall | FirewallPolicy | |
| metadata | Metadata | |
| envVars | EnvVars | |
| services | SnapshotService[] | Captured service registrations from the source VM at snapshot time. |
| status | SnapshotStatus | |
| createdAt | string |
PolicyAction
enumallowdenyIngressRuleKind
enumcidr is supported — inbound packets don't carry a domain the worker could match on without TLS interception.cidrEgressRuleKind
enumcidr: match by destination IP/CIDR + port/proto. - fqdn: match by destination domain (resolved through the in-process DNS resolver) + port/proto. Resolved IPs land in a per-rule dynamic nft set; the chain emits one rule per fqdn rule keyed on (set, proto, port). Port/proto enforcement on fqdn rules is honest — the prior kind: domain shape with a shared allow-set silently ignored them. Fqdn values accept an optional leading *. wildcard (e.g. *.example.com). Bare wildcards and non-leading wildcards are rejected. Wildcards match one-or-more labels left of the suffix and do not match the apex (matches DNS wildcard semantics).cidrfqdnDNSMode
enumdns.domains. - allow: allowlist — only listed domains can resolve; any other query returns NXDOMAIN. - deny: blocklist — listed domains return NXDOMAIN; all other queries resolve through the upstream resolver. Default is deny with an empty list, which means "resolve everything" — the safe default that preserves existing behavior when callers omit the dns block.allowdenyIngressRule
object| Field | Type | Description |
|---|---|---|
| action | PolicyAction | |
| kind | IngressRuleKind | |
| value | string | CIDR (e.g. ::/0, 10.0.0.0/8). IPv4 and IPv6 CIDRs are both accepted in the schema; L3 enforcement coverage per family is a worker-side concern. |
| protocol | "tcp" | "udp" | "any" | |
| ports | string | Single port (443), inclusive range (8080-8090), or any. When protocol is any, ports MUST be any. |
| description | string |
IngressPolicy
object| Field | Type | Description |
|---|---|---|
| default | PolicyAction | |
| rules | IngressRule[] |
EgressRule
object| Field | Type | Description |
|---|---|---|
| action | PolicyAction | |
| kind | EgressRuleKind | |
| value | string | For kind: cidr, an IPv4 or IPv6 CIDR. For kind: fqdn, a domain name with optional leading *. wildcard. Must be reachable through the dns gate — a fqdn value blocked by dns.mode/dns.domains is rejected at PUT time as a dead rule. |
| protocol | "tcp" | "udp" | "any" | |
| ports | string | Single port (443), inclusive range (8080-8090), or any. When protocol is any, ports MUST be any. |
| description | string |
EgressPolicy
object| Field | Type | Description |
|---|---|---|
| default | PolicyAction | |
| rules | EgressRule[] |
DNSPolicy
objectmode to deny when missing, domains to [], and blockBypass to false (see normalizeDNSPolicy in scheduler/internal/httpapi/firewall.go).| Field | Type | Description |
|---|---|---|
| mode | DNSMode | |
| domains | string[] | |
| blockBypass | boolean | When true, the worker denies DoT (TCP 853) and the known public DoH endpoint IPs at the nft layer so guests cannot sidestep the in-process resolver. Default false — turning this on breaks workloads that legitimately reach 1.1.1.1 / 8.8.8.8 / etc. on TCP/443 for non-DoH reasons (e.g. services whose data plane lives on a Cloudflare anycast IP). Operators who enable DNS allowlist mode typically also flip this on explicitly. |
FirewallPolicy
objectfirewall: null on VM create is also valid.| Field | Type | Description |
|---|---|---|
| ingress | IngressPolicy | |
| egress | EgressPolicy | |
| dns | DNSPolicy |
SnapshotService
objectPOST /v1/vms (snapshot-restore branch) so the new VM gets the same service registrations the source VM had at snapshot time.| Field | Type | Description |
|---|---|---|
| name | string | |
| port | number | |
| h2c | boolean |
BuildResponse
objectPOST /v1/builds (initial pending state) and GET /v1/builds/{id} (current state on each poll).| Field | Type | Description |
|---|---|---|
| id | string | Build ID (UUID). Use this to poll status. |
| name | string | |
| status | string | Current state. Known values: pending (accepted, not yet started), running (worker is executing), completed (snapshot is ready), failed (build did not produce a snapshot). Additional values may be introduced in future server versions; clients should treat unknown values as "in progress" rather than as hard errors. |
| snapshotId | string | Set when status is completed. Fetch the corresponding Snapshot record via GET /v1/snapshots/{id}. |
| imageRef | string | |
| progress | string | Human-readable phase string while the build runs (e.g. creating build VM, buildah pull, buildah bud, applying image, settling VM, creating snapshot). Not present after a terminal status. |
| error | string | Set when status is failed. Diagnostic from the worker (truncated to ~4 KiB). |
| createdAt | string |
Metadata
objectEnvVars
object[A-Za-z_][A-Za-z0-9_]*); values may not contain newline, carriage return, or null bytes. Total JSON encoding ≤65536 bytes.ExecEvent
objectPOST /v1/vms/{id}/exec under Accept: application/x-ndjson. Short field names (t, d, c, to, ms) keep per-chunk overhead small since high-output commands can produce thousands of events per exec.| Field | Type | Description |
|---|---|---|
| t | "o" | "e" | "x" | Event type: o = stdout chunk, e = stderr chunk, x = terminal exit event. |
| d | string | For o/e: base64-encoded raw bytes of the chunk. For x: optional diagnostic string (e.g. spawn failure) when non-empty. |
| c | number | Exit code. Present on x events only. |
| to | boolean | True if the command was killed by the timeout. x events only. |
| ms | number | Guest-reported duration in milliseconds. x events only. |
ExecVMResponse
objectPOST /v1/vms/{id}/exec under Accept: application/json. The server collects the streamed events and returns this aggregate once the command exits. Per-stream output is capped at 4 MiB; overflow bytes are dropped and signalled via stdoutTruncated / stderrTruncated. Streaming clients (Accept: application/x-ndjson) receive every byte without a cap.| Field | Type | Description |
|---|---|---|
| exitCode | number | |
| stdout | string | |
| stderr | string | |
| timedOut | boolean | |
| stdoutTruncated | boolean | True if the collector dropped stdout bytes past the 4 MiB cap. |
| stderrTruncated | boolean | True if the collector dropped stderr bytes past the 4 MiB cap. |
| durationMs | number |
FilePresignResponse
objectuploadUrl, and either side GETs them back via downloadUrl. URLs expire after expiresInSec seconds and the staging object is auto-deleted after about a day.| Field | Type | Description |
|---|---|---|
| uploadUrl | string | Presigned PUT URL for the staging object. Accepts Content-Type: application/octet-stream. Used by the client on upload, or by the VM (via an exec'd curl -T -) on download. |
| downloadUrl | string | Presigned GET URL for the same staging object. Used by the VM (via POST /v1/vms/{id}/files/fetch) on upload, or by the client (via httpx.stream / curl) on download. |
| expiresInSec | number | Lifetime of both URLs in seconds. |
| maxUploadBytes | number | Upper bound on upload size (equals the VM's disk size in bytes). |
ConsoleTokenResponse
object| Field | Type | Description |
|---|---|---|
| token | string | |
| expiresInSec | number | |
| websocketPath | string | Relative WebSocket path; combine with your API host as wss://<host><websocketPath>?session=<token>. |
SshKey
object| Field | Type | Description |
|---|---|---|
| name | string | Optional human label. |
| publicKey | string | OpenSSH-format public key, of the form <type> <base64-blob> — the optional comment is stripped server-side. Supported types: ssh-ed25519, ssh-rsa, ecdsa-sha2-nistp{256,384,521}, plus FIDO2 hardware-backed variants (sk-...@openssh.com). |
| fingerprint | string | OpenSSH SHA256 fingerprint, e.g. SHA256:abc.... This is the identifier — matches what ssh-keygen -lf prints and what your ssh client shows on first connect; pass it back as the {fingerprint} path segment to deleteSshKey. |
| createdAt | string |
SshKeyListResponse
object| Field | Type | Description |
|---|---|---|
| keys | SshKey[] |
OrgQuotaValues
object| Field | Type | Description |
|---|---|---|
| vcpu | number | |
| memoryMiB | number | |
| diskGiB | number | |
| snapshotCount | number |
OrgQuotaUsage
object| Field | Type | Description |
|---|---|---|
| orgId | string | |
| limits | OrgQuotaValues | |
| usage | OrgQuotaValues |
Service
object| Field | Type | Description |
|---|---|---|
| name | string | Service name (1–29 chars). Embedded in the public URL as <name>--<vmIdHexNoHyphens>.proxy.<stack-domain>. |
| port | number | TCP port the service listens on inside the VM. Privileged ports (<1024) are rejected. |
| h2c | boolean | When true, the proxy speaks HTTP/2 cleartext (h2c) to the backend. Required for gRPC and h2c-only apps. When false (default), the proxy uses HTTP/1.1 — covers HTTP/1.1 apps, Server-Sent Events, and WebSocket pass-through. |
HealthResponse
object| Field | Type | Description |
|---|---|---|
| status | string |