POST /api/appvm/vms
Updated
Create an AppVM from an image that has already been imported on the Lite host.
| Property | Value |
|---|---|
| Scope | readwrite |
| Request body | JSON |
| Success | 201 Created |
Endpoint
POST
${baseUrl}/api/appvm/vms Create an AppVM from an already imported OCI image.
Use your host URL and API key as shell variables:
baseUrl="https://agent.example.com"
VIRT_AGENT_API_KEY="<your-api-key>" cURL template
curl --request POST "${baseUrl}/api/appvm/vms" \
--header "Authorization: Bearer ${VIRT_AGENT_API_KEY}" \
--header "Content-Type: application/json" \
--data @- <<'JSON'
{
"vm_id": "${id}",
"image_id": "${imageId}",
"vcpus": 2,
"memory_mb": 2048,
"disk_gib": 12,
"auto_boot": true,
"restart_policy": "on-failure",
"env": [
"PORT=8080"
]
}
JSON Request
Section titled “Request”| Object | Field | Type | Required | Description |
|---|---|---|---|---|
| Header | Authorization | bearer token | yes | Bearer <api-key> from a readwrite key. |
| Body | vm_id | string | no | Stable VM id. Omit to let the agent generate one. |
image_id | string | yes | AppVM image id from GET /api/appvm/images response field images[].id. The image must be ready, not still importing. | |
vcpus | integer | yes | vCPU count. Must be at least 1. | |
memory_mb | integer | yes | Memory in MiB. Must be at least 64. | |
disk_gib | integer | yes | Root disk size in GiB. Must be at least 1. | |
network_id | string | no | Host network id from GET /api/networks. Omit to use the default VM network. | |
ip | string | conditionally | Static guest IPv4 address without prefix. Required with prefix and gateway; omit all three for DHCP. | |
prefix | integer | conditionally | IPv4 prefix length, 1..32. Required with ip and gateway; omit all three for DHCP. | |
gateway | string | conditionally | Static IPv4 gateway. Required with ip and prefix; omit all three for DHCP. | |
dns | array of strings | no | DNS server IPs for static mode. Must be empty or omitted in DHCP mode. | |
hostname | string | no | Guest hostname. Omit to derive an appvm-* hostname from the generated MAC address. Empty after trimming is treated as omitted. | |
auto_boot | boolean | no | Default true. When false, create the AppVM without booting it. | |
keepalive | boolean | no | Default false. When true, overrides the image entrypoint with a long-running keepalive shell. | |
env | array of strings | no | Operator-provided environment overrides in KEY=VALUE form. Values are visible in VM views. | |
secret_env | array of strings | no | Secret environment overrides in KEY=VALUE form. Values are sent to the guest but redacted from VM views. | |
restart_policy | enum | no | Default no. Accepted values: no, on-failure, always. | |
data_volumes | array of objects | no | Persistent ext4 data volumes mounted inside the AppVM rootfs. Maximum 8. | |
disk_bps_total | integer | no | Root disk bandwidth limit in bytes per second. Omit or pass 0 for no limit. | |
disk_iops_total | integer | no | Root disk IOPS limit. Omit or pass 0 for no limit. | |
| Static network group | ip + prefix + gateway omitted | shape | no | DHCP mode. The guest obtains address and DNS from the upstream lease. |
ip + prefix + gateway present | shape | yes for static mode | Static mode. The guest receives the exact IPv4 config over vsock. | |
| partial static fields | shape | invalid | Rejected with 400 BAD_REQUEST. | |
| env[] / secret_env[] | item form | string | yes for each item | Each item must be KEY=VALUE. |
| key | string | yes | Must match [A-Za-z_][A-Za-z0-9_]*. | |
| value | string | yes | Must not contain NUL, newline, or carriage return. | |
| count | limit | yes | Each list can contain at most 100 entries. | |
| size | limit | yes | Each entry can be at most 8192 bytes. | |
| redaction | behavior | yes | secret_env values are never returned in VM views; only keys are visible. | |
| data_volumes[] | size_gib | integer | yes | Volume size in GiB. Must be at least 1. |
mountpoint | string | yes | Absolute mount path inside the guest rootfs, for example /var/lib/data. Must not be /, contain empty segments, ., .., NUL, or control characters. Maximum 256 characters. Mountpoints must be unique. |
Response
Section titled “Response”| Status | Body | Description |
|---|---|---|
201 Created | object | AppVM was created. If auto_boot is omitted, the agent also attempted to boot it. |
| Field | Type | Description |
|---|---|---|
id | string | Created VM id. |
mode | string | Always appvm. |
image_id | string | Source AppVM image id. |
booted | boolean | Whether the request asked the agent to boot the VM. This is true when auto_boot is omitted. |
Use GET /api/appvm/vms/{id} after creation for the full VmView, including
network state, AppVM workload status, redacted environment view, health,
restart policy, data mounts, and discovered IP.
Examples
Section titled “Examples”Call example
Section titled “Call example”baseUrl="https://agent.example.com"VIRT_AGENT_API_KEY="<your-api-key>"
curl --request POST "${baseUrl}/api/appvm/vms" \ --header "Authorization: Bearer ${VIRT_AGENT_API_KEY}" \ --header "Content-Type: application/json" \ --data @- <<'JSON'{ "vm_id": "demo-api-appvm", "image_id": "nginx_latest", "vcpus": 2, "memory_mb": 2048, "disk_gib": 12, "auto_boot": true, "restart_policy": "on-failure", "env": [ "PORT=8080" ], "secret_env": [ "APP_SECRET=<redacted>" ], "data_volumes": [ { "size_gib": 10, "mountpoint": "/var/lib/app" } ]}JSONResponse example
Section titled “Response example”{ "id": "demo-api-appvm", "mode": "appvm", "image_id": "nginx_latest", "booted": true}Errors
Section titled “Errors”| Status | Code | Description |
|---|---|---|
400 | BAD_REQUEST | Validation failed, image id was not found, static network fields were incomplete, DNS was provided in DHCP mode, env values were invalid, or data volume mountpoints were invalid. |
401 | UNAUTHORIZED | API key is missing or invalid. |
403 | FORBIDDEN | Key is read-only or endpoint is outside the key allowlist. |
409 | ALREADY_EXISTS, CONFLICT, or capacity conflict | VM id already exists, AppVM image import is still in progress, or host admission rejected the requested resources. |
422 | none | JSON body could not be deserialized, for example a required field is missing or has the wrong type. This response is plain text, not the Virtainer JSON error envelope. |
500 | CH_ERROR, NETWORK_ERROR, STORAGE_ERROR, or INTERNAL | Host-side creation, disk, network, AppVM template, or boot work failed. |