Skip to content

POST /api/vms

Updated

Create a classic Linux VM. Use a stable vm_id when calling this from automation so a retry does not create a second VM.

PropertyValue
Scopereadwrite
Request bodyJSON
Success201 Created or 202 Accepted when image provisioning continues in the background

Endpoint

POST ${baseUrl}/api/vms
readwrite

Create a classic Linux VM from a registry or cached cloud 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/vms" \
  --header "Authorization: Bearer ${VIRT_AGENT_API_KEY}" \
  --header "Content-Type: application/json" \
  --data @- <<'JSON'
{
"vm_id": "${id}",
"vcpus": 2,
"memory_mb": 2048,
"firmware_path": "/usr/share/virtainer/CLOUDHV.fd",
"image": {
  "image_id": "replace-with-image-id",
  "content_sha256": "replace-with-registry-sha256",
  "fetch_url": "replace-with-registry-download-url",
  "distro": "debian",
  "version": "13"
},
"disk": {
  "mode": "copy",
  "size_gib": 20
},
"cloud_init": {
  "user": "root",
  "ssh_authorized_keys": [
    "ssh-ed25519 AAAA..."
  ],
  "console_autologin": false
},
"auto_boot": true
}
JSON

Use GET /api/registry/images or GET /api/registry/images/{id} to populate the image fields.

ObjectFieldTypeRequiredDescription
HeaderAuthorizationbearer tokenyesBearer <api-key> from a readwrite key.
Bodyvm_idstringnoStable VM id. Omit to let the agent generate a UUID v4. Explicit ids must match ^[A-Za-z0-9][A-Za-z0-9_.-]{0,63}$.
vcpusintegeryesvCPU count. Must be at least 1.
memory_mbintegeryesMemory in MiB. Must be at least 64.
kernel_pathstringconditionallyAbsolute PVH kernel path on the Lite host. Exactly one of kernel_path or firmware_path is required.
firmware_pathstringconditionallyAbsolute firmware path on the Lite host. Exactly one of kernel_path or firmware_path is required.
diskobjectconditionallyAgent-owned root disk copy settings. Required unless image injects the base image into the disk copy path.
imageobjectnoRemote or registry image descriptor. When present, the agent downloads and verifies the image, then uses it as disk.base_path.
volumesarray of objectsnoExtra blank data volumes attached at create time. Omit or pass an empty array for no data volumes.
cmdlinestringnoKernel command line. Omit to use the host default.
netsarray of objectsnoNetwork interfaces, in order: index 0 becomes the guest’s eth0. If cloud_init is present and nets is omitted or empty, the handler attaches one interface on the default VM network. At most one interface may carry an IPv4 gateway, and at most one an IPv6 gateway.
platformobjectnoSMBIOS platform values.
cloud_initobjectnoNoCloud seed configuration rendered by the agent and attached to the VM. Its network block configures the first interface only; the rest take their guest address from their own ipv4.
nestedbooleannoWhether the guest may itself run KVM. Omit to follow the hypervisor default. Requesting true on a host without nested virtualization returns 400 rather than a VM that silently lacks it.
cpu_affinitystringnoHost logical CPUs to pin the vCPUs to, in cpuset notation such as “0-3” or “0,2,4-6”. Omit for no pinning.
cpu_topologyobjectnoGuest-visible CPU topology. Omit for the hypervisor default. Setting it removes this VM’s vCPU hot-add headroom, because the topology is fixed at boot.
pci_devicesarray of stringsnoHost PCI devices to pass through, as full BDF strings such as “0000:07:00.0”. Every device in the same IOMMU group must be listed together; GET /api/host/pci reports the grouping. Setting it removes this VM’s memory hot-add headroom, because passthrough pins guest memory.
disk_bps_totalintegernoRoot-disk throughput ceiling in bytes per second. Omit or 0 for unlimited.
disk_iops_totalintegernoRoot-disk ceiling in IO operations per second. Omit or 0 for unlimited.
auto_bootbooleannoDefault false. When true, the agent creates the VM and immediately boots it in the same request.
diskmodestringnoOnly copy is accepted. Omitted means copy.
base_pathstringconditionallyAbsolute host path to a trusted qcow2 base image. Required when image is not provided.
size_gibintegernoRoot disk size in GiB, 1..65535. Omit to keep the base virtual size or host default. The agent will not shrink below the base image size.
imageimage_idstringyesImage content id. Stored in the VM view as image.image_id.
content_sha256stringyesExpected SHA-256 digest of the downloaded image content.
fetch_urlstringyesURL the Lite host can fetch.
distrostringnoDisplay metadata, such as debian or fedora.
versionstringnoDisplay metadata, such as 13 or 42.
volumes[]size_gibintegeryesBlank data volume size in GiB. Must be at least 1. Volumes are attached in request order.
nets[]modestringnoOnly bridge is accepted. Omitted means bridge.
bridgestringnoHost bridge interface. Omit to use the resolved default bridge.
macstringnoGuest MAC address. Omit to let the agent generate one.
network_idstringnoHost network id from GET /api/networks. If provided, the agent resolves that network’s bridge.
vlan_tagintegerno802.1Q VLAN tag metadata.
ipv4objectnoStatic IPv4 metadata: address, optional gateway, optional dns_servers.
ipv6objectnoStatic IPv6 metadata: address, optional gateway, optional dns_servers.
mtuintegernoInterface MTU. Omit to use host defaults.
isolatedbooleannoPer-VM bridge port isolation override. Omit to inherit host policy.
spoof_guardbooleannoPer-VM MAC/IP anti-spoof override. Omit to inherit host policy.
rate_limit_mbpsintegernoSymmetric network rate limit in Mbps. Accepted range is 1..100000; omit for no limit.
allowed_ipsarray of stringsnoExtra source addresses or CIDRs anti-spoof lets through, beyond the interface’s own address. Use it for guest-side routing, NAT, VPN egress, or a floating VRRP address. It only extends a pinned address: on an interface with neither a static ipv4 nor a learned DHCP binding it stays inert.
nets[].ipv4 / nets[].ipv6addressstringyesCIDR address, for example 10.77.23.2/24 or 2001:db8::2/64.
gatewaystringnoGateway IP address without CIDR suffix.
dns_serversarray of stringsnoDNS server IP addresses.
cpu_topologysocketsintegeryesGuest-visible socket count.
coresintegeryesCores per socket.
threadsintegeryesThreads per core. sockets × cores × threads must equal vcpus exactly, or the request is rejected.
platformserial_numberstringnoSMBIOS serial number. Maximum 512 bytes; control characters, NUL, newline, and carriage return are rejected.
cloud_inithostnamestringnoGuest hostname. Omit to derive it from vm_id. Explicit values must be at most 63 bytes, use only letters, digits, and -, and cannot start or end with -.
userstringnoLogin user. Omit for root.
ssh_authorized_keysarray of stringsyes when using cloud-init loginPublic SSH keys written into the guest. Provide at least one key for automated access.
passwordstringnoOptional password for the cloud-init user. API-key VM views do not return this value.
networkobjectnoStatic guest network config rendered into NoCloud network-config. Omit for guest DHCP.
console_autologinbooleannoDefault false. When true, serial console login drops directly to a shell.
sudobooleannoDefault false. Grants sudo to non-root users.
instance_idstringnoAdvanced cloud-init instance identity. Omit unless preserving first-boot identity across rebuilds or migration.
raw_user_datanullnoReserved placeholder. Non-null values are rejected.
raw_network_confignullnoReserved placeholder. Non-null values are rejected.
cloud_init.networkipv4objectyesStatic IPv4 config for the guest.
ipv6objectnoStatic IPv6 config for the guest.
cloud_init.network.ipv4 / ipv6addressstringyesCIDR address.
gatewaystringnoGateway IP address without CIDR suffix.
dnsarray of stringsnoDNS server IP addresses. This cloud-init field is named dns, not dns_servers.
StatusBodyDescription
201 CreatedVmViewVM was created. If auto_boot is true, the returned view reflects the post-boot host state.
202 Acceptedprovision viewImage provisioning was accepted and continues in the background. Poll GET /api/vms/{id}.

Both success statuses return a classic VmView. With 201 Created, the view describes the created VM. With 202 Accepted, it is an in-progress view: state is created, display_state is downloading or creating, and fields whose resources do not exist yet can be empty or omitted.

Fields marked optional are omitted from the JSON object when they have no value. Fields marked nullable are always present and use null when they do not apply.

VmView

FieldTypePresenceDescription
idstringalwaysVM id.
statestringalwaysStored lifecycle state: created, running, paused, stopped, or failed.
display_statestringalwaysUser-facing state. In addition to lifecycle states, classic VM provisioning can report booting, downloading, creating, or provision_failed.
vcpusintegeralwaysAssigned vCPU count.
memory_mbintegeralwaysAssigned memory in MiB.
kernel_pathstring or nullnullablePVH kernel path when direct kernel boot is used.
firmware_pathstring or nullnullableFirmware path when firmware boot is used.
disk_pathstringalwaysRoot disk path on the Lite host. An in-progress classic provision returns an empty string until the disk exists.
volumesarray of VmVolumealwaysAttached data volumes, in disk order. The item shape is documented below.
seed_diskSeedDiskoptionalThe host-generated cloud-init seed disk. Present only on a VM with cloud_init. It is not a data volume and cannot be detached, but it does occupy a guest device letter.
cmdlinestringalwaysKernel command line.
console_socket_pathstringalwaysHost serial-console socket path. An in-progress classic provision returns an empty string.
failure_reasonFailureReasonoptionalHuman-readable and machine-readable failure details.
pidintegeroptionalCloud Hypervisor process id when known.
netsarray of VmNetworkalwaysNetwork interfaces in order: index 0 is the guest's eth0. Empty array when the VM has no interface.
platformVmPlatformoptionalSMBIOS platform values.
diskVmDiskoptionalAgent-managed root disk metadata.
imageVmImageoptionalClassic VM source image identity.
cloud_initCloudInitViewoptionalClassic VM cloud-init view. API-key responses omit cloud_init.password.
io_limitDiskIoLimitoptionalRoot-disk throughput ceiling. Omitted when the disk is unthrottled.
nestedbooleanoptionalWhether the guest may itself run KVM. Omitted when never set explicitly, which means the hypervisor default applies.
cpu_affinityarray of integersoptionalHost logical CPUs the vCPUs are pinned to. Omitted when unpinned.
cpu_topologyCpuTopologyoptionalGuest-visible CPU topology. Omitted when the hypervisor default applies.
pci_devicesarray of stringsalwaysPassed-through host PCI devices, as full BDF strings such as 0000:07:00.0. Empty array when nothing is passed through.
balloon_mbintegeroptionalMemory reclaim target in MiB. Omitted when no memory is being reclaimed.
created_atRFC 3339 stringoptionalCreation timestamp.
discovered_ipv4stringoptionalObserved guest IPv4 address.
guest_panicked_atRFC 3339 stringoptionalWhen a guest kernel panic was observed over pvpanic. state stays running: the hypervisor is alive and the guest is not.
shutting_downbooleanoptionalPresent as true while ACPI shutdown is pending; omitted when false.
modestringalwaysAlways vm on this endpoint.

volumes[] (VmVolume)

FieldTypePresenceDescription
idstringalwaysStable per-VM volume id, such as data0.
pathstringalwaysVolume file path on the Lite host.
virtual_size_bytesintegeralwaysVirtual size visible to the guest, in bytes.
fmtstringalwaysVolume image format. Currently qcow2.
readonlybooleanalwaysWhether the volume is attached read-only.
ownedbooleanalwaysWhether the agent owns and manages the volume file. true means deleting the VM erases it.
volume_idstringoptionalId of the matching first-class volume, whose lifetime is independent of this VM. Omitted for a VM-owned disk.
devicestringalwaysGuest block device, such as /dev/vdc. Derived from disk order, so detaching an earlier disk shifts this one down a letter. Mount by UUID or label in the guest, never by device letter.
disk_bytesintegeroptionalBytes the volume file actually occupies, which is smaller than virtual_size_bytes for a sparse image. Only the single-VM read fills this in; list responses omit it rather than pay a stat per row.

seed_disk (SeedDisk)

FieldTypePresenceDescription
devicestringalwaysGuest block device holding the cloud-init seed. It sits directly after the root disk, so data volumes on a cloud-init VM start one letter later than on a VM without one.
size_bytesintegeralwaysSize the guest sees. Fixed, and small: the seed holds only the rendered cloud-init files.

io_limit (DiskIoLimit)

FieldTypePresenceDescription
bps_totalintegeroptionalCombined read and write ceiling in bytes per second. Omitted when unlimited.
iops_totalintegeroptionalCombined read and write ceiling in IO operations per second. Omitted when unlimited.

cpu_topology (CpuTopology)

FieldTypePresenceDescription
socketsintegeralwaysGuest-visible socket count.
coresintegeralwaysCores per socket.
threadsintegeralwaysThreads per core. sockets × cores × threads always equals vcpus.

failure_reason (FailureReason)

FieldTypePresenceDescription
detected_atRFC 3339 stringalwaysTime the failure was detected.
summarystringalwaysOne-line operator-readable explanation.
detailobjectalwaysTagged machine-readable detail. kind is one of socket_gone, socket_dead, ping_timeout, process_exit, process_signal, missing_pid, disk_missing, invalid_vm_id, boot_timeout, or provision_failed.
detail.kindstringalwaysFailure-detail discriminator.
detail.codeintegerconditionalProcess exit code when kind is process_exit.
detail.signumintegerconditionalSignal number when kind is process_signal.
detail.pathstringconditionalMissing disk path when kind is disk_missing.
detail.idstringconditionalInvalid VM id when kind is invalid_vm_id.
detail.secondsintegerconditionalTimeout duration when kind is boot_timeout.
causestringalwaysHigher-level cause: operator_shutdown, guest_shutdown, ch_crash, vmm_hang, disk_missing, boot_timeout, provision_failed, record_invalid, or unknown.

nets[] (VmNetwork)

FieldTypePresenceDescription
modestringalwaysNetwork mode. Currently bridge.
bridgestringalwaysHost bridge interface.
tap_namestringalwaysAgent-created tap interface.
macstringalwaysGuest MAC address.
network_idstringoptionalHost network id.
vlan_tagintegeroptional802.1Q VLAN tag.
ipv4VmNetworkIpConfigoptionalIPv4 assignment metadata.
ipv6VmNetworkIpConfigoptionalIPv6 assignment metadata.
mtuintegeroptionalInterface MTU.
isolatedbooleanoptionalPer-VM bridge port-isolation override.
spoof_guardbooleanoptionalPer-VM anti-spoof override.
rate_limit_mbpsintegeroptionalSymmetric network rate limit in Mbps.
allowed_ipsarray of stringsoptionalExtra source addresses or CIDRs anti-spoof lets through, beyond the interface's own address. Omitted when empty.
dhcp_snooped_ipv4stringoptionalGuest IPv4 learned from the upstream DHCP ACK. Authoritative, and the preferred source for discovered_ipv4. Only set on an interface with no static ipv4.
last_observed_ipv4stringoptionalLast IPv4 seen for this MAC in the host neighbor table. Guest-asserted, so it is a display fallback only, and it survives ARP expiry.

nets[].ipv4 / nets[].ipv6 (VmNetworkIpConfig)

FieldTypePresenceDescription
addressstringalwaysCIDR address.
gatewaystringoptionalGateway address without a CIDR suffix.
dns_serversarray of stringsoptionalDNS server addresses.

platform (VmPlatform)

FieldTypePresenceDescription
serial_numberstringoptionalSMBIOS serial number.

disk (VmDisk)

FieldTypePresenceDescription
modestringalwaysRoot disk mode. Currently copy.
base_pathstringalwaysCanonical source image path.
virtual_size_bytesintegeralwaysVirtual size visible to the guest, in bytes.
ownedbooleanalwaysWhether the agent owns and manages the root disk file.
image_fmtstringoptionalRoot disk image format. Currently qcow2.
qsd_pidintegeroptionalStorage process id.
qsd_start_timeintegeroptionalStorage process start time in boot-relative clock ticks.
qsd_blk_socketstringoptionalRoot-disk block socket path.
qsd_qmp_socketstringoptionalStorage control socket path.
runtimeVolumeRefoptionalBackend-independent runtime identity.

disk.runtime (VolumeRef)

FieldTypePresenceDescription
backendstringalwaysStorage backend. Currently qsd.
pidintegeralwaysStorage process id.
start_timeintegeralwaysStorage process start time in boot-relative clock ticks.
blk_socketstringalwaysRoot-disk block socket path.
qmp_socketstringalwaysStorage control socket path.

image (VmImage)

FieldTypePresenceDescription
image_idstringalwaysSource image id.
distrostringoptionalDistribution name.
versionstringoptionalDistribution version.

cloud_init (CloudInitView)

FieldTypePresenceDescription
hostnamestringalwaysGuest hostname.
userstringalwaysGuest account configured by cloud-init.
ssh_authorized_keysarray of stringsalwaysSSH public keys.
passwordstringoptionalGuest password. This field is always omitted from API-key responses.
networkCloudInitNetworkoptionalRendered static guest network input.
instance_idstringalwaysNoCloud instance identity.
console_autologinbooleanalwaysWhether serial-console auto-login is enabled.
sudobooleanalwaysWhether a non-root cloud-init user receives sudo access.

cloud_init.network (CloudInitNetwork)

FieldTypePresenceDescription
ipv4CloudInitIpConfigalwaysStatic IPv4 configuration.
ipv6CloudInitIpConfigoptionalStatic IPv6 configuration.

cloud_init.network.ipv4 / ipv6

FieldTypePresenceDescription
addressstringalwaysCIDR address.
gatewaystringoptionalGateway address without a CIDR suffix.
dnsarray of stringsoptionalDNS server addresses. This field is named dns, not dns_servers.

202 Accepted is used for asynchronous image provisioning. Treat the response as an in-progress VM view and poll by id until display_state leaves downloading or creating.

Terminal window
baseUrl="https://agent.example.com"
VIRT_AGENT_API_KEY="<your-api-key>"
curl --request POST "${baseUrl}/api/vms" \
--header "Authorization: Bearer ${VIRT_AGENT_API_KEY}" \
--header "Content-Type: application/json" \
--data @- <<'JSON'
{
"vm_id": "demo-api-vm",
"vcpus": 2,
"memory_mb": 2048,
"firmware_path": "/usr/share/virtainer/CLOUDHV.fd",
"image": {
"image_id": "debian-13-x86_64",
"content_sha256": "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
"fetch_url": "https://images.example.com/debian-13-x86_64.qcow2",
"distro": "debian",
"version": "13"
},
"disk": {
"mode": "copy",
"size_gib": 20
},
"nets": [
{
"network_id": "default"
}
],
"cloud_init": {
"user": "root",
"ssh_authorized_keys": [
"ssh-ed25519 <your-public-ssh-key> demo@example"
]
},
"auto_boot": true
}
JSON
{
"id": "demo-api-vm",
"state": "running",
"display_state": "booting",
"vcpus": 2,
"memory_mb": 2048,
"kernel_path": null,
"firmware_path": "/usr/share/virtainer/CLOUDHV.fd",
"disk_path": "/var/lib/virtainer/vms/demo-api-vm/root.qcow2",
"volumes": [],
"cmdline": "",
"console_socket_path": "/run/virtainer/demo-api-vm/console.sock",
"pid": 4242,
"nets": [
{
"mode": "bridge",
"bridge": "vmbr0",
"tap_name": "vtdemoapi0",
"mac": "02:00:00:12:34:56",
"network_id": "default"
}
],
"pci_devices": [],
"disk": {
"mode": "copy",
"base_path": "/var/lib/virtainer/images/debian-13-x86_64.qcow2",
"size_gib": 20
},
"image": {
"image_id": "debian-13-x86_64",
"distro": "debian",
"version": "13"
},
"cloud_init": {
"user": "root",
"ssh_authorized_keys": [
"ssh-ed25519 <your-public-ssh-key> demo@example"
],
"console_autologin": false,
"sudo": false
},
"created_at": "2026-07-03T10:00:00Z",
"mode": "vm"
}
StatusCodeDescription
400BAD_REQUESTValidation failed, such as invalid ids, missing disk base image, both boot methods present, unsupported disk mode, invalid hostname, or non-null reserved raw cloud-init fields.
401UNAUTHORIZEDAPI key is missing or invalid.
403FORBIDDENKey is read-only or endpoint is outside the key allowlist.
409ALREADY_EXISTS, INVALID_STATE, or capacity conflictVM id already exists, state changed during an operation, or host admission rejected the requested resources.
422noneJSON 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.
500CH_ERROR, NETWORK_ERROR, STORAGE_ERROR, or INTERNALHost-side creation, image, disk, network, or Cloud Hypervisor work failed.