Automation (REST API)
Everything you script against NexoVirt goes through the REST API under /api/v1. It is smaller and
friendlier than the raw Proxmox API: one token covers every connected host, and one call creates a
complete guest. This page walks through the typical workflow; the
interactive REST API reference lists every endpoint with a try-it panel.
1. Create an API token
Section titled “1. Create an API token”Open Settings → API tokens and fill in the Create token form:
| Field | What it does |
|---|---|
| Name | A label for the token, for example ci-bot or terraform. |
| Allowed IPs | One IP or CIDR per line (for example 203.0.113.5 or 198.51.100.0/24). Leave blank to allow any source. |
| Rate limit | Requests per minute. Leave blank (or 0) for no limit. |
| Connection scope | Comma-separated connection ids (the API’s host ids, one node or one cluster each) the token may access. Leave blank for all nodes. |
The token is shown once, right after you create it: copy it then. Only a hash is stored. The Tokens table shows each token’s allowed IPs, scope, rate, last use and status; Revoke disables a token immediately.
2. Authenticate
Section titled “2. Authenticate”Send the token as a bearer header on every request:
curl -s https://panel.example.com/api/v1/hosts \ -H "Authorization: Bearer $NEXOVIRT_TOKEN"The token check answers with a short {"error": "..."} body:
| Status | Meaning |
|---|---|
401 | Missing, unknown or revoked token. |
403 | The source IP is not in Allowed IPs, or the path names a host outside the token’s scope. |
429 | Rate limit exceeded. The Retry-After header says how many seconds until the next minute window. |
Host-less endpoints (GET /hosts, POST /guests, GET /placement/suggest) only ever see the hosts in
the token’s scope.
3. Read the response envelope
Section titled “3. Read the response envelope”Every endpoint answers with the same envelope:
{ "success": true, "data": { }, "error": null }On failure success is false, data is null and error holds a readable message (404 not found,
409 conflict, 422 validation, 502 Proxmox failure). List endpoints accept ?page= and ?perPage=
(default 50, at most 200) and add meta: { page, perPage, total }.
4. Discover what you can create with
Section titled “4. Discover what you can create with”Before creating a guest, look up the identifiers the create call takes. None of these return secrets.
| Endpoint | Returns |
|---|---|
GET /hosts/{id}/plans | Active plans (cores, memory, disk, traffic, runtime). |
GET /hosts/{id}/os-templates | QEMU OS templates, each with a ref like tpl:3. |
GET /hosts/{id}/ct-templates?node= | LXC templates: the managed library plus the node’s template files. |
GET /hosts/{id}/ip-zones | IP zones, each with a ref like zone:2. |
GET /hosts/{id}/next-vmid | The next free VMID. |
GET /hosts/{id}/storages, /networks, /nodes | Storage names, bridges and nodes. |
GET /users/{id}/ssh-keys | A user’s SSH keys (name and fingerprint only). |
5. Create a guest in one call
Section titled “5. Create a guest in one call”curl -s -X POST https://panel.example.com/api/v1/hosts/1/guests \ -H "Authorization: Bearer $NEXOVIRT_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "type": "qemu", "node": "auto", "name": "web-01", "plan_id": 2, "os_template": "tpl:3", "ip_source": "zone:1", "owner_id": 14, "password": "change-me-please" }'typeisqemuorlxc. QEMU takesos_template(tpl:<id>); LXC takeslxc_template_idor anos_templatevolume id.plan_idsets cores, memory and disk from a plan. Without a plan, sendcores,memory_mbanddisk_gb.node: "auto"lets placement pick the node and storage;vmidmay then be left out.- Give a
passwordor SSH keys (ssh_keys, plus the stored keys ofowner_id). ip_sourceisdhcp(default) orzone:<id>to assign the next free address from an IP zone.
The request returns at once with a queued job:
{ "success": true, "data": { "queued": true, "job_id": 381, "vmid": 112, "placement": { "host_id": 1, "node": "pve-2", "storage": "local-zfs", "explanation": "..." } }, "error": null }A 409 means the host is in maintenance, the VMID is taken, the IP zone is full or no node has room.
6. Poll the job
Section titled “6. Poll the job”curl -s https://panel.example.com/api/v1/hosts/1/jobs/381 \ -H "Authorization: Bearer $NEXOVIRT_TOKEN"status moves from queued to running to done (or failed, with the reason in error). Poll every
few seconds until it is done or failed. The same job id is shown in the panel, where the guest’s live
provisioning page tracks it step by step.
Automatic placement
Section titled “Automatic placement”Placement scores every eligible node on free RAM, CPU load and free storage and skips nodes that are offline, in maintenance, without a healthy agent or without room.
node: "auto"onPOST /hosts/{id}/guestspicks the best node on that host.POST /guests(no host in the path) picks across every host in the token’s scope;nodemust beautothere.GET /placement/suggest?type=qemu&memory_mb=2048&cores=2&disk_gb=20previews the ranking without creating anything: the best target, every ranked node with a score and explanation, and every dropped node with the reason.
Weights are set under Settings → Placement.
The request log
Section titled “The request log”The Request log on Settings → API tokens records every API request, including refused ones: time, token, source IP, method, path, status and duration. Entries are kept for 30 days.