Error
error (string, required) — Human-readable error message.
QuotaExceededError
Per-VM service quota exceeded. The `error` token is a stable
machine-readable code so SDKs can branch on it; `count` is the
configured cap at denial time.
error ("vm_service_quota_exceeded", required)count (integer, required)
DeleteResponse
id (string, required)deleted (boolean, required)
VMStatus
Lifecycle status. Known values: `provisioning`, `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
Snapshot lifecycle status. Known values: `creating`, `ready`, `error`.
Additional values may be introduced in future server versions.
TTL
Per-VM auto-action timer. The cycle ticks down while the VM is
`running` and freezes on pause. `seconds` is the original cycle
duration; refresh and PATCH-time updates reset to this value.
seconds (integer, required) — Cycle duration. Refresh resets to this value. Capped at 1 year
(31536000s); larger values are rejected with 400.
action ("pause" | "delete", required) — Action taken on expiry. `pause` re-arms the cycle for the
next running session; `delete` is terminal.
QuotaExceeded
429 body returned by `/v1/vms/{id}/resume` when the org's quota
for one of the listed dimensions would be exceeded.
error (string, required)dimension ("vcpu" | "memory_mib" | "disk_gib" | "snapshot_count", required)
MachineType
Machine size identifier (e.g. `c1m2`, `c2m4`). Controls CPU and
memory allocation. Must be supplied on launch unless restoring
from a snapshot.
VM
id (string, required)name (string, required)orgId (string, required)machineName (string)sourceName (string) — Source snapshot or image name (empty on fresh boot).firewall (FirewallPolicy)effectiveFirewall (any) — 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 (integer, required)memoryMiB (integer, required)diskGiB (integer, required)status (VMStatus, required)createdAt (string, required)deletedAt (string)ttl (any) — Optional auto-action timer. Null when no TTL is configured.
See `TTL` for semantics.
expiresAtMs (integer) — Absolute timestamp in ms when the TTL fires. Set only while
the VM is `running` (the countdown freezes on pause).
ttlRemainingMs (integer) — Remaining cycle budget in ms. Set only while the VM is
paused; restored to `expiresAtMs` on resume.
pausedAt (string) — When the VM became paused; null otherwise.volumes (VolumeAttachmentItem[]) — Currently-attached volumes on this VM.bucketMounts (BucketMount[]) — Currently-attached bucket-mounts on this VM.
Snapshot
id (string, required)name (string, required)orgId (string, required)vmId (string, required)firewall (FirewallPolicy)metadata (Metadata)envVars (EnvVars)services (SnapshotService[]) — Captured service registrations from the source VM at snapshot time.volumes (SnapshotVolumeAttachment[]) — Volume attachments captured at snapshot time.bucketMounts (SnapshotBucketMountAttachment[]) — BucketMount metadata captured at snapshot time (no credentials).status (SnapshotStatus, required)createdAt (string, required)
PolicyAction
Allow/deny verb. Used both as the per-direction default posture and
as each rule's action.
IngressRuleKind
Ingress rule kind. Only `cidr` is supported — inbound packets don't
carry a domain the worker could match on without TLS interception.
EgressRuleKind
Egress rule kind.
- `cidr`: 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).
DNSMode
Toggles the meaning of `dns.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.
IngressRule
action (PolicyAction, required)kind (IngressRuleKind, required)value (string, required) — 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", required)ports (string, required) — Single port (`443`), inclusive range (`8080-8090`), or `any`.
When `protocol` is `any`, `ports` MUST be `any`.
description (string)
IngressPolicy
default (PolicyAction, required)rules (IngressRule[])
EgressRule
action (PolicyAction, required)kind (EgressRuleKind, required)value (string, required) — 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", required)ports (string, required) — Single port (`443`), inclusive range (`8080-8090`), or `any`.
When `protocol` is `any`, `ports` MUST be `any`.
description (string)
EgressPolicy
default (PolicyAction, required)rules (EgressRule[])
DNSPolicy
DNS-layer filtering, independent of egress L4 rules. The resolver
applies the DNS gate BEFORE L4 enforcement; a domain blocked here
returns NXDOMAIN regardless of what egress.rules says about its
IPs. All fields are optional — the server defaults `mode` to
`deny` when missing, `domains` to `[]`, and `blockBypass` to
false (see `normalizeDNSPolicy` in
`scheduler/internal/httpapi/firewall.go`).
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
Top-level firewall policy with three independent axes. All
sub-blocks are optional — the server substitutes the safe
default (ingress deny / egress allow / dns mode=deny + empty)
for missing blocks. Sending `firewall: null` on VM create is
also valid.
ingress (IngressPolicy)egress (EgressPolicy)dns (DNSPolicy)
PatchFirewallRequest
Partial firewall update. Each block (`ingress`, `egress`, `dns`) is
optional; when present, the supplied object replaces that block
wholesale. To change a single rule, send the full block with the
desired rule list. An empty body (`{}`) is a no-op.
ingress (IngressPolicy)egress (EgressPolicy)dns (DNSPolicy)
SnapshotService
Captured (name, port, h2c) tuple for a single service
registration on a snapshotted VM. Carried across snapshot/
restore by `POST /v1/vms` (snapshot-restore branch) so the
new VM gets the same service registrations the source VM
had at snapshot time.
name (string, required)port (integer, required)h2c (boolean)
SnapshotRestoreWarnings
Reports best-effort failures during the snapshot-restore
service-replay step. Only present when restoring from a
snapshot AND the post-create bulk service registration failed.
The VM is created successfully and usable; the user can
manually re-register the listed services with one
`POST /v1/vms/{id}/services` per service.
Bulk service registration is atomic at Redis (one Lua call
either writes all-N entries or zero), so partial state
("5 of 8 registered") is impossible — the response is always
either a VM with all services registered or a VM with zero
services and the full list returned here.
servicesRegistrationFailed (boolean, required) — Always `true` when this object is present.unregisteredServices (SnapshotService[]) — Services from the snapshot that did not land on the new
VM. Caller can re-register each via
`POST /v1/vms/{id}/services`.
reason (string) — Operator-facing diagnostic for the failure.
VMCreateResponse
VM object as returned by `POST /v1/vms`. On snapshot restore,
an optional `snapshotRestoreWarnings` field may be present if
the captured services failed to re-register on the new VM.
Existing SDK callers that don't know about the field see the
unchanged VM wire shape (`omitempty` keeps the field absent on
cold boots and on warning-free restores).
CreateVMRequest
Boot behavior depends on which fields are set:
- `snapshotId` set → restore from snapshot (takes precedence over
`machineType` if both are sent).
- Otherwise → fresh boot. `machineType` selects the size; if
omitted or empty, defaults to `c1m2`.
name (string) — User-facing name (trimmed + whitespace-collapsed, max 64 runes
after normalization; longer values are truncated server-side).
Auto-generated as `vm-<8-char-id-prefix>` if empty.
machineType (MachineType)snapshotId (string) — Snapshot ID to restore from.diskGiB (integer) — Override the default disk size (GiB).firewall (FirewallPolicy)metadata (Metadata)envVars (EnvVars)ttl (TTL)volumes (VolumeAttachmentRequest[]) — Cold-boot inline volume attachments (managed Volume IDs).
On snapshot restore, this list authoritatively replaces the
captured list. Omit to use the captured list.
bucketMounts (CreateBucketMountRequest[]) — Cold-boot inline bucket-mounts. Same authoritative-replace
semantics on snapshot restore.
UpdateVMRequest
At least one of `name`, `metadata`, or `ttl` must be provided.
Sending `metadata: {}` clears all metadata; omitting it leaves
existing metadata unchanged. Sending `ttl: null` explicitly
clears the TTL; sending a `TTL` object replaces it; omitting
the field leaves the current TTL unchanged.
name (string)metadata (Metadata)ttl (any)
CreateSnapshotRequest
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.
UpdateSnapshotRequest
Rename a snapshot. `name` is optional; if omitted or empty, the
server regenerates the auto-name (`snapshot-<8-char-vmId-prefix>`).
CreateBuildRequest
At least one of `imageRef` or `dockerfileContent` must be set. If
only `imageRef` is provided, the build VM pulls that image and
rsyncs its rootfs over the VM's `/`. If `dockerfileContent` is
provided, the build VM writes it verbatim to
`/tmp/buildctx/Dockerfile` and runs `buildah bud`.
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 (integer) — 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`.
BuildResponse
Build state snapshot. Returned by `POST /v1/builds` (initial
`pending` state) and `GET /v1/builds/{id}` (current state on
each poll).
id (string, required) — Build ID (UUID). Use this to poll status.name (string)status (string, required) — 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, required)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, required)
Metadata
Free-form string→string map. Server-enforced limits: up to 256 keys,
key length 1–256 bytes, value length ≤4096 bytes, total JSON encoding
≤65536 bytes.
EnvVars
Environment variable string→string map injected into the VM at boot.
Keys must be 1–256 bytes and match shell-variable name
(`[A-Za-z_][A-Za-z0-9_]*`); values may not contain newline,
carriage return, or null bytes. Total JSON encoding ≤65536 bytes.
ExecVMRequest
command (string[], required) — Argv-style command. First element must be non-empty. For shell
strings, wrap as `["sh", "-c", "<string>"]`.
timeoutSec (integer) — Server-side execution timeout in seconds. Must be positive when
provided; omit to use the server default.
stdin (string) — Optional base64-encoded stdin blob, written to the child's stdin
before the process starts reading much and then closed. Streaming
stdin is not supported — pipe from a file inside the guest if you
need that shape.
ExecEvent
One event in the NDJSON exec stream returned by
`POST /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.
t ("o" | "e" | "x", required) — 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 (integer) — Exit code. Present on `x` events only.to (boolean) — True if the command was killed by the timeout. `x` events only.ms (integer) — Guest-reported duration in milliseconds. `x` events only.
ExecVMResponse
Buffered response shape for `POST /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.
exitCode (integer, required)stdout (string, required)stderr (string, required)timedOut (boolean, required)stdoutTruncated (boolean, required) — True if the collector dropped stdout bytes past the 4 MiB cap.stderrTruncated (boolean, required) — True if the collector dropped stderr bytes past the 4 MiB cap.durationMs (integer, required)
FilePresignRequest
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.
FilePresignResponse
Pair of signed URLs scoped to the same per-VM staging object.
Usable in either direction: either side (client or VM) PUTs bytes
to `uploadUrl`, and either side GETs them back via `downloadUrl`.
URLs expire after `expiresInSec` seconds and the staging object
is auto-deleted after about a day.
uploadUrl (string, required) — 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, required) — 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 (integer, required) — Lifetime of both URLs in seconds.maxUploadBytes (integer, required) — Upper bound on upload size (equals the VM's disk size in bytes).
FileFetchRequest
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 (integer) — Per-fetch timeout in seconds.
ConsoleTokenResponse
token (string, required)expiresInSec (integer, required)websocketPath (string, required) — Relative WebSocket path; combine with your API host as
`wss://<host><websocketPath>?session=<token>`.
SshKey
name (string) — Optional human label.publicKey (string, required) — 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, required) — 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, required)
SshKeyListResponse
keys (SshKey[], required)
AddSshKeyRequest
name (string) — Optional human label.publicKey (string, required) — OpenSSH-format public key (`ssh-ed25519 AAA...`). Comments are
stripped. Newlines are rejected.
OrgQuotaValues
vcpu (integer, required)memoryMiB (integer, required)diskGiB (integer, required)snapshotCount (integer, required)volumeCount (integer, required)volumeGiB (integer, required)
OrgQuotaUsage
orgId (string, required)limits (OrgQuotaValues, required)usage (OrgQuotaValues, required)
Service
name (string, required) — Service name (1–29 chars). Embedded in the public URL as
`<name>--<vmIdHexNoHyphens>.proxy.<stack-domain>`.
port (integer, required) — TCP port the service listens on inside the VM. Privileged
ports (<1024) are rejected.
h2c (boolean, required) — 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.
RegisterServiceRequest
name (string, required)port (integer, required)h2c (boolean) — Optional. When true, the proxy uses HTTP/2 cleartext to the
backend (required for gRPC). Defaults to false (HTTP/1.1).
UpdateServiceRequest
port (integer, required) — New TCP port. Same value as the existing entry is a no-op.h2c (boolean) — 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.
Volume
id (string, required)name (string, required)orgId (string, required)accessMode (string, required) — Access mode. Known values: `rw`, `ro`. Future server versions
may introduce additional values.
sizeGiB (integer, required)status (string, required) — Lifecycle status. Known values:
- `creating` — the substrate-create saga is in flight. Set
by the server briefly between the customer's `POST
/v1/volumes` and the worker substrate provisioning;
attach attempts are rejected with `VOL_NOT_READY` until
the saga commits. Clients polling immediately after
create may observe this state.
- `ready` — substrate is up; attachable.
- `deleting` — cleanup is in progress; not attachable.
Future server versions may introduce additional values.
pendingSizeGiB (integer) — When non-zero, a resize saga is in flight; `sizeGiB` is
still the pre-resize value and `pendingSizeGiB` is the
target. Set briefly between `PATCH /v1/volumes/{id}` and
the substrate resize commit. Clients polling immediately
after a resize may observe a non-zero value.
mountedCount (integer, required) — Number of currently-running VMs with this volume attached
(paused VMs are NOT counted).
usedGiB (integer) — Bytes used inside the volume (rounded down to GiB). Fetched
on-demand from the substrate; omitted when the substrate is
unreachable.
createdAt (string, required)
CreateVolumeRequest
name (string, required)sizeGiB (integer, required)accessMode ("rw" | "ro", required)
UpdateVolumeRequest
At least one of `name`, `sizeGiB`, or `accessMode` must be present.
`accessMode` requires `mountedCount == 0`. `sizeGiB` shrink requires
`usedGiB <= newSizeGiB`.
name (string)sizeGiB (integer)accessMode ("rw" | "ro")
VolumeAttachmentRequest
volumeId (string, required)mountPath (string, required) — Absolute path; must start with /mnt/ or /data/.readOnly (boolean)
VolumeAttachmentItem
volumeId (string, required)mountPath (string, required)readOnly (boolean)mountStatus (string, required) — Known values: `mounted`, `failed`, `pending`. `pending` appears
on attachments to paused VMs (mount happens on resume) and
briefly during in-flight hot-attach.
statusMessage (string)
VolumeAttachmentItemWithVm
DetachVolumeResponse
detached (boolean, required)warnings (DetachWarning[])
DetachWarning
type (string, required) — Known values: `ack_timeout`, `guest_unresponsive`.
message (string, required)
BucketMount
id (string, required)vmId (string, required)bucketUri (string, required) — `gs://...` or `s3://...`; future schemes may be added.
mountPath (string, required)readOnly (boolean)mountStatus (string, required) — Known values: `mounted`, `failed`, `pending`.
statusMessage (string)createdAt (string, required)
BucketMountCredentials
Customer-provided credentials. Never returned in API responses.
Discriminated union: the `type` property selects the per-provider
shape so SDKs surface typed per-type values.
GcpServiceAccountCredentials
type ("gcp-service-account-json", required)value (object, required)
AwsCredentials
type ("aws-credentials", required)value (object, required)
CreateBucketMountRequest
bucketUri (string, required) — Customer's GCS or S3 bucket URI. `gs://<bucket>[/prefix]`
or `s3://<bucket>[/prefix]`.
mountPath (string, required)readOnly (boolean)credentials (BucketMountCredentials, required)
UpdateBucketMountRequest
credentials (BucketMountCredentials, required)
AttachmentWarnings
skippedSnapshotVolumes (SnapshotVolumeSkip[])failedVolumeAttachments (FailedVolumeAttachment[])skippedSnapshotBucketMounts (SnapshotBucketMountSkip[])failedBucketMountAttachments (FailedBucketMountAttachment[])
SnapshotVolumeSkip
volumeId (string, required)mountPath (string, required)reason (string, required) — Known values: `deleted`, `deleting`, `cross_org`,
`vol_ro_ceiling_after_patch`.
FailedVolumeAttachment
volumeId (string, required)mountPath (string, required)statusMessage (string, required)
SnapshotBucketMountSkip
bucketUri (string, required)mountPath (string, required)reason (string, required) — Known values: `credentials_invalid`, `bucket_unreachable`,
`credentials_unavailable`.
FailedBucketMountAttachment
bucketUri (string, required)mountPath (string, required)statusMessage (string, required)
SnapshotVolumeAttachment
volumeId (string, required)mountPath (string, required)readOnly (boolean)
SnapshotBucketMountAttachment
bucketUri (string, required)mountPath (string, required)readOnly (boolean)