API reference
Every action, scriptable.
Deploy, resize, and manage compute, storage, and IP addresses — everything the control panel can do, your own code can do too. Authenticate with a single API key.
Authentication
API keys
Every request is authenticated with an API key sent in the Authorization header. There's no separate signing step, no OAuth flow — generate a key from the dashboard, send it on every request.
Authorization: Api-Key YOUR_API_KEY
Create and manage keys from Account → API Keys in the control panel. Each key can optionally be locked to a single source IP — set allowed_ip and requests from anywhere else are rejected before authentication even runs.
A key acts as you — it can see and manage everything your account owns, with no per-key permission scoping today. Treat it like a password: revoke a key (set it inactive or delete it) the moment it's no longer needed.
Not every endpoint accepts an API key. Compute, storage, IP, and reference endpoints do (marked API key throughout this page) — billing, invoices, and account-profile endpoints are dashboard-session only for now (see Dashboard-only endpoints). A key also can't create or manage other keys — that always requires being logged into the dashboard itself.
Quickstart
List your VMs in one request
curl https://iotamine.com/api/vps/ \ -H "Authorization: Api-Key YOUR_API_KEY"
Compute
VPS
Full lifecycle for your virtual machines — deploy, resize, power control, console access, backups, and the disks/IPs bundled onto one.
/api/vps/API keyList every VPS you own.
Query params
searchstringFilter by hostname/IP.Example response · 200
[
{
"id": 412, "hostname": "web-01", "status": "active",
"machine_status": "Running", "cores": 4, "ram": 8,
"primary_disk": 160, "traffic": 5, "hourly_rate": 0.0248,
"vps_country": "Germany", "vps_city": "Frankfurt",
"os_name": "ubuntu", "ip_address": [
{ "id": 88, "ip": "198.51.100.42", "is_primary": true }
],
"is_building": false, "is_failed": false,
"created_at": "2026-07-02T10:15:00Z"
}
]/api/vps/API keyDeploy a new VM — a fresh disk + OS template, or booted from an existing volume you already own.
Request body
hostname *stringServer display name.password *stringRoot/administrator password.pop *intRegion id (see GET /api/pop/).cores *intvCPU count — one of the allowed values (1–32).ram *intRAM in GB — one of the allowed values (2–64).diskintBoot disk size in GB. Required unless existing_boot_volume is set.operating_systemintOS template id (see GET /api/os/). Required unless existing_boot_volume is set.existing_boot_volumeintA volume you already own — boots the VM from it instead of provisioning a fresh disk.existing_ipintAn IP address you already own — used instead of auto-assigning a new one.ssh_keyintOne of your saved SSH key ids.disable_pwd_authboolDisable SSH password login (key-only).Example response · 201
{
"id": 413, "hostname": "web-02", "status": "active",
"cores": 4, "ram": 8, "primary_disk": 160,
"vid": "b6e2...", "created_at": "2026-08-17T09:00:00Z"
}/api/vps/{id}/API keyRetrieve one VPS, including a live-checked machine_status.
Example response · 200
{ "id": 412, "hostname": "web-01", "machine_status": "Running", "...": "..." }/api/vps/{id}/API keyResize (cores/ram — must be one of the allowed tier values) or change hostname/password. Hostname and password changes require the VPS to be stopped first.
Request body
coresintNew vCPU count.ramintNew RAM in GB.hostnamestringNew hostname — requires the VPS to be stopped.passwordstringNew root password — requires the VPS to be stopped.Example response · 200
{ "id": 412, "cores": 8, "ram": 16, "...": "..." }/api/vps/{id}/API keyDestroy a VPS (dispatches an async terminate task). Owned disks/IPs survive detached by default — list ids you want released instead.
Request body
release_ip_idsint[]Owned IPs to fully release (not just detach) along with the VPS.release_disk_idsint[]Owned volumes to fully release along with the VPS.Example response · 204
{ "message": "VPS deleted successfully." }/api/vps/{id}/start/ · stop/ · restart/ · poweroff/API keyPower actions — synchronous, plain GET requests (not POST). Blocked while a backup/restore task is already running.
Example response · 200
{ "message": "VPS started successfully." }/api/vps/{id}/vnc/API keyOpen a browser console session. Returns a WebSocket URL (and password, Virtualizor nodes only).
Example response · 200
{ "ws_url": "wss://iotamine.com/control/websockify/8123", "password": null }/api/vps/{id}/stats/API keyLive CPU/RAM/bandwidth usage from the hypervisor, cached briefly.
Example response · 200
{ "cpu": 12.4, "used_ram": 2048, "ram": 8192, "bandwidth": 5120, "used_bandwidth": 340 }/api/vps/{id}/bandwidth_history/ · metrics_history/API keyHistorical bandwidth / CPU+RAM time series for graphing.
Example response · 200
[ { "timestamp": "2026-08-17T09:00:00Z", "value": 12.4 } ]/api/vps/{id}/billing/ · getpricing/API keyThis VM's current billing breakdown, and its live hourly rate at the current spec.
Example response · 200
{ "hourly_rate": 0.0248, "monthly_estimate": 17.86 }/api/vps/{id}/rebuild/API keyReinstall the OS, wiping the boot disk. Requires the VPS to be stopped first.
Request body
osid *intOS template id to install.new_pass *stringNew root/administrator password.conf_pass *stringMust match new_pass.Example response · 200
{ "message": "VPS rebuild has been started with Ubuntu 24.04." }/api/vps/{id}/available_os/API keyOS templates installable on this VPS's region/node.
Example response · 200
[ { "id": 3, "name": "Ubuntu 24.04", "distro": "ubuntu" } ]/api/vps/{id}/build_log/API keyTail-pollable step-by-step provisioning log (regional-backed nodes only).
Query params
afterstringCursor from the previous poll — omit for the first call.Example response · 200
{ "entries": [ { "step": "Allocating disk", "status": "done" } ], "cursor": "18" }/api/vps/{id}/listbackup/ · getbackupcost/API keyList existing backups and their storage cost. Backups are supported on Virtualizor-backed nodes only — regional-backed VMs return a 400 explaining this.
Example response · 200
[ { "id": 9, "created_at": "2026-08-01T00:00:00Z", "size_gb": 40 } ]/api/vps/{id}/createbackup/ · restorebackup/ · deletebackup/API keyCreate a new backup, or restore/delete an existing one (restorebackup and deletebackup take backup_id). Async — dispatches a task.
Request body
backup_idintRequired for restorebackup and deletebackup.Example response · 200
{ "message": "Restore process has been started." }/api/vps/{id}/list_disk/ · add_disk/ · delete_disk/{disk_uuid}/API keyBundled disk management. add_disk/delete_disk are blocked (400) on regional-backed VMs — use the standalone Volumes endpoints below instead for those.
Example response · 200
{ "message": "Use the Volumes page to manage disks on this VM." }/api/vps/{id}/add_ip/ · delete_ip/{ip_addr}/API keyBundled IP management — same regional restriction as add_disk above; use the standalone IP Addresses endpoints for regional-backed VMs.
Example response · 200
{ "message": "IP added." }/api/vps/{id}/attachable_ips/API keyYour own unattached IPs eligible to attach to this VPS.
Example response · 200
[ { "id": 91, "ip": "198.51.100.7" } ]/api/vps/{id}/ip_address/{ip}/API keySet reverse DNS (rDNS) for one of this VPS's addresses.
Request body
rdns *stringThe hostname to point rDNS at.Example response · 200
{ "message": "rDNS updated." }Compute
SSH Keys
Public keys saved to your account, reusable across any VPS you deploy.
/api/sshkey/API keyList your saved SSH keys.
Example response · 200
[ { "id": 5, "title": "laptop", "ssh_key": "ssh-ed25519 AAAA...", "created_at": "2026-05-01" } ]/api/sshkey/API keySave a new public key. Validated as a real SSH public key; duplicate titles on your account are rejected.
Request body
title *stringA name for this key, unique to your account.ssh_key *stringThe public key contents (e.g. id_ed25519.pub).Example response · 201
{ "id": 6, "title": "deploy-key", "ssh_key": "ssh-ed25519 AAAA...", "created_at": "2026-08-17" }/api/sshkey/{id}/API keyRemove a saved key.
Example response · 204
{}Compute
Firewall Rules
Per-VPS firewall rules, nested under the VPS resource.
/api/vps/{vps_id}/firewall_rules/API keyList the custom rules on one VPS.
Example response · 200
[ { "id": 2, "direction": "in", "ip_type": "ipv4", "decision": "accept", "protocol": "tcp", "src_port": "any", "dest_port": "22", "source": "0.0.0.0/0" } ]/api/vps/{vps_id}/firewall_rules/updateRules/API keyReplace the full rule set for this VPS in one call — rules present in the array are kept/created, anything missing from it is deleted (a diff, not an append).
Request body
(array body) *arrayEach item: { direction, ip_type, decision, protocol, src_port, dest_port, source }.Example response · 200
{ "message": "Firewall rules updated." }Networking
IP Addresses
Standalone IPv4 addresses — purchased independently of any VM, attached or detached whenever you need to.
/api/ip-addresses/API keyList every IP you own.
Query params
popintFilter to one region.unattachedbooltrue/false — filter to addresses with (or without) a VPS attached.Example response · 200
[ { "id": 91, "ip": "198.51.100.7", "vps": null, "status": "active", "purchased_at": "2026-06-01T00:00:00Z" } ]/api/ip-addresses/available/API keyAvailability and price for purchasing new addresses in a region — the picker source before calling purchase.
Query params
pop *intRegion id.Example response · 200
{ "pop": 2, "pop_city": "Frankfurt", "monthly_price": 1.6, "available_count": 42, "remaining_quota": 8 }/api/ip-addresses/purchase/API keyBuy one or more addresses in a region. Synchronous — addresses are reserved and returned in the same response. Max 20 per call.
Request body
pop *intRegion id.quantity *int1–20.Example response · 201
[ { "id": 104, "ip": "198.51.100.88", "status": "active" } ]/api/ip-addresses/{id}/attachable_vps/API keyYour VMs in the same region as this IP, eligible to attach it to.
Example response · 200
[ { "id": 412, "hostname": "web-01", "is_stopped": false } ]/api/ip-addresses/{id}/attach/API keyAttach this address to one of your VMs (same region only). Synchronous.
Request body
vps *intTarget VPS id.Example response · 200
{ "id": 91, "ip": "198.51.100.7", "vps": 412 }/api/ip-addresses/{id}/detach/API keyDetach this address from whatever VM it's attached to. Synchronous.
Example response · 200
{ "id": 91, "ip": "198.51.100.7", "vps": null }/api/ip-addresses/{id}/API keyRelease an address for good — must be detached first.
Example response · 204
{ "message": "IP address released." }Storage
Volumes
Standalone block storage — including boot volumes. Create one, install an OS on it, set it as a VM's boot disk, or move it to a different VM entirely.
Every mutating volume action below is asynchronous — it returns 202 with a task_id immediately, not the finished result. Poll task-status until status is "completed" (or "failed").
/api/volumes/API keyList every volume you own.
Query params
popintFilter to one region.unattachedboolFilter to volumes with (or without) a VPS attached.Example response · 200
[ { "id": 55, "name": "vol-a83f", "size": 160, "kind": "data", "vps": null, "os_name": null } ]/api/volumes/available/API keyPrice and eligibility for purchasing in a region — including whether this region requires naming an existing VPS at purchase time (non-fleet regions).
Query params
pop *intRegion id.Example response · 200
{ "pop": 2, "monthly_price_per_gb": 0.0144, "allowed_sizes_gb": [20, 40, 80, 160, 320, 520], "is_fleet_backed": true, "eligible_vps": [] }/api/volumes/purchase/API keyCreate a new volume — a data disk, or a boot volume with nothing installed on it yet.
Request body
pop *intRegion id.size_gb *intOne of the allowed sizes for this region.kindstring"data" (default) or "boot".vps_idintRequired for a data disk in a non-fleet region — pins the volume to that VM's own node.Example response · 202
{ "task_id": 881, "status": "pending" }/api/volumes/task-status/{task_id}/API keyPoll the result of purchase/attach/detach/destroy/install_os/resize/set_as_boot.
Example response · 200
{ "task_id": 881, "type": "volume_create", "status": "completed", "volume": { "id": 55, "size": 160 } }/api/volumes/{id}/attachable_vps/API keyYour VMs in the same region as this volume, annotated with whether each already has a boot volume.
Example response · 200
[ { "id": 412, "hostname": "web-01", "is_stopped": true, "has_boot_volume": false } ]/api/volumes/{id}/available_os/API keyOS templates installable on this volume (fleet-backed volumes only). Always a plain list, empty if nothing's installable right now.
Example response · 200
[ { "id": 3, "name": "Ubuntu 24.04", "distro": "ubuntu" } ]/api/volumes/{id}/install_os/API keyInstall an OS onto this volume, overwriting whatever was on it. Must be detached first. Windows requires a password; others need an SSH key, a password, or both.
Request body
operating_system *intOS id from available_os.ssh_public_keystringPublic key to install (non-Windows).root_passwordstringRoot/administrator password.Example response · 202
{ "task_id": 882, "status": "pending" }/api/volumes/{id}/resize/API keyGrow a volume live — works whether it's attached or not. Grow-only, next size up from the allowed tiers.
Request body
size_gb *intMust be larger than the current size.Example response · 202
{ "task_id": 883, "status": "pending" }/api/volumes/{id}/attach/API keyAttach this volume to a VM as a plain (non-boot) data disk. Same region only.
Request body
vps *intTarget VPS id.Example response · 202
{ "task_id": 884, "status": "pending" }/api/volumes/{id}/set_as_boot/API keySet this volume as a VM's boot disk — swaps out whatever boot volume it currently has, if any. Fleet-backed volumes only; the target VM must be stopped.
Request body
vps *intTarget VPS id.Example response · 202
{ "task_id": 885, "status": "pending" }/api/volumes/{id}/detach/API keyDetach this volume from whatever VM it's on — including a boot volume.
Example response · 202
{ "task_id": 886, "status": "pending" }/api/volumes/{id}/API keyRelease a volume for good — must be detached first.
Example response · 202
{ "task_id": 887, "status": "pending" }Reference data
Regions & Operating Systems
Read-only catalogs — the region and OS ids every create/deploy request above needs.
/api/pop/API keyList every region, with per-resource hourly pricing (vCPU/RAM/disk/traffic hourly, IP monthly).
Example response · 200
[ { "id": 2, "city": "Frankfurt", "country": "Germany", "cpu_price": 0.004, "ram_price": 0.00035, "disk_price": 0.00002, "ip_price": 1.6 } ]/api/os/API keyList every installable operating system template.
Example response · 200
[ { "id": 3, "name": "Ubuntu 24.04", "distro": "ubuntu", "virt_type": "kvm" } ]Account
Account & Quota
Your current plan tier, resource limits, and live usage against them.
/api/account/quota/API keyYour plan tier, per-resource limits, current usage, balance, and what the next tier unlocks.
Example response · 200
{
"current_tier": "starter", "is_custom": false,
"limits": { "max_cores": 32, "max_ram_gb": 64, "max_disk_gb": 1040, "max_ips": 8 },
"usage": { "cores": 4, "ram_gb": 8, "disk_gb": 160, "ips": 1 },
"next_tier": "growth", "balance": 42.18,
"currency": "USD", "currency_symbol": "$"
}/api/api_keys/Dashboard onlyList or create your API keys. Dashboard session only — a key can't be used to manage keys.
Example response · 200
{ "id": 4, "name": "ci-deploy", "key": "b0e2b6b0-...-9f21", "is_active": true, "allowed_ip": null, "created_at": "2026-08-17T09:00:00Z" }/api/api_keys/{id}/Dashboard onlyUpdate (e.g. deactivate, set allowed_ip) or permanently delete a key. Dashboard session only.
Example response · 200
{ "id": 4, "is_active": false }Conventions
Errors & status codes
Most errors return a plain {"message": "..."} body. A few validation failures on POST/PATCH instead return Django REST Framework's own per-field shape — {"field_name": ["error"]} — worth handling both rather than assuming one is universal.
List endpoints are not paginated — a GET to a list route returns the full plain array of everything you own, not a wrapped {"count", "results"} object.
Scope
Dashboard-only endpoints
These exist in the same API but only accept a logged-in dashboard session today, not an API key — listed here so a script doesn't waste time on a silent 401.
Get started
Generate your first API key
$10 free credit on signup. Create a key from the dashboard and start scripting in minutes.