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.

REST + JSON·Api-Key header auth·No pagination limits

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
Getting a 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.

Scope

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.

List your VMs in one request

curl https://iotamine.com/api/vps/ \
  -H "Authorization: Api-Key YOUR_API_KEY"

VPS

Full lifecycle for your virtual machines — deploy, resize, power control, console access, backups, and the disks/IPs bundled onto one.

GET/api/vps/API key

List 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"
  }
]
POST/api/vps/API key

Deploy 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"
}
GET/api/vps/{id}/API key

Retrieve one VPS, including a live-checked machine_status.

Example response · 200

{ "id": 412, "hostname": "web-01", "machine_status": "Running", "...": "..." }
PATCH/api/vps/{id}/API key

Resize (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, "...": "..." }
DELETE/api/vps/{id}/API key

Destroy 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." }
GET/api/vps/{id}/start/ · stop/ · restart/ · poweroff/API key

Power actions — synchronous, plain GET requests (not POST). Blocked while a backup/restore task is already running.

Example response · 200

{ "message": "VPS started successfully." }
GET/api/vps/{id}/vnc/API key

Open 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 }
GET/api/vps/{id}/stats/API key

Live 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 }
GET/api/vps/{id}/bandwidth_history/ · metrics_history/API key

Historical bandwidth / CPU+RAM time series for graphing.

Example response · 200

[ { "timestamp": "2026-08-17T09:00:00Z", "value": 12.4 } ]
GET/api/vps/{id}/billing/ · getpricing/API key

This 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 }
POST/api/vps/{id}/rebuild/API key

Reinstall 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." }
GET/api/vps/{id}/available_os/API key

OS templates installable on this VPS's region/node.

Example response · 200

[ { "id": 3, "name": "Ubuntu 24.04", "distro": "ubuntu" } ]
GET/api/vps/{id}/build_log/API key

Tail-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" }
GET/api/vps/{id}/listbackup/ · getbackupcost/API key

List 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 } ]
POST/api/vps/{id}/createbackup/ · restorebackup/ · deletebackup/API key

Create 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." }
GET / POST / DELETE/api/vps/{id}/list_disk/ · add_disk/ · delete_disk/{disk_uuid}/API key

Bundled 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." }
POST / DELETE/api/vps/{id}/add_ip/ · delete_ip/{ip_addr}/API key

Bundled 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." }
GET/api/vps/{id}/attachable_ips/API key

Your own unattached IPs eligible to attach to this VPS.

Example response · 200

[ { "id": 91, "ip": "198.51.100.7" } ]
PUT/api/vps/{id}/ip_address/{ip}/API key

Set 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." }

SSH Keys

Public keys saved to your account, reusable across any VPS you deploy.

GET/api/sshkey/API key

List your saved SSH keys.

Example response · 200

[ { "id": 5, "title": "laptop", "ssh_key": "ssh-ed25519 AAAA...", "created_at": "2026-05-01" } ]
POST/api/sshkey/API key

Save 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" }
DELETE/api/sshkey/{id}/API key

Remove a saved key.

Example response · 204

{}

Firewall Rules

Per-VPS firewall rules, nested under the VPS resource.

GET/api/vps/{vps_id}/firewall_rules/API key

List 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" } ]
POST/api/vps/{vps_id}/firewall_rules/updateRules/API key

Replace 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." }

IP Addresses

Standalone IPv4 addresses — purchased independently of any VM, attached or detached whenever you need to.

GET/api/ip-addresses/API key

List 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" } ]
GET/api/ip-addresses/available/API key

Availability 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 }
POST/api/ip-addresses/purchase/API key

Buy 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" } ]
GET/api/ip-addresses/{id}/attachable_vps/API key

Your VMs in the same region as this IP, eligible to attach it to.

Example response · 200

[ { "id": 412, "hostname": "web-01", "is_stopped": false } ]
POST/api/ip-addresses/{id}/attach/API key

Attach 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 }
POST/api/ip-addresses/{id}/detach/API key

Detach this address from whatever VM it's attached to. Synchronous.

Example response · 200

{ "id": 91, "ip": "198.51.100.7", "vps": null }
DELETE/api/ip-addresses/{id}/API key

Release an address for good — must be detached first.

Example response · 204

{ "message": "IP address released." }

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").

GET/api/volumes/API key

List 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 } ]
GET/api/volumes/available/API key

Price 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": [] }
POST/api/volumes/purchase/API key

Create 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" }
GET/api/volumes/task-status/{task_id}/API key

Poll 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 } }
GET/api/volumes/{id}/attachable_vps/API key

Your 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 } ]
GET/api/volumes/{id}/available_os/API key

OS 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" } ]
POST/api/volumes/{id}/install_os/API key

Install 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" }
POST/api/volumes/{id}/resize/API key

Grow 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" }
POST/api/volumes/{id}/attach/API key

Attach 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" }
POST/api/volumes/{id}/set_as_boot/API key

Set 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" }
POST/api/volumes/{id}/detach/API key

Detach this volume from whatever VM it's on — including a boot volume.

Example response · 202

{ "task_id": 886, "status": "pending" }
DELETE/api/volumes/{id}/API key

Release a volume for good — must be detached first.

Example response · 202

{ "task_id": 887, "status": "pending" }

Regions & Operating Systems

Read-only catalogs — the region and OS ids every create/deploy request above needs.

GET/api/pop/API key

List 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 } ]
GET/api/os/API key

List every installable operating system template.

Example response · 200

[ { "id": 3, "name": "Ubuntu 24.04", "distro": "ubuntu", "virt_type": "kvm" } ]

Account & Quota

Your current plan tier, resource limits, and live usage against them.

GET/api/account/quota/API key

Your 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": "$"
}
GET / POST/api/api_keys/Dashboard only

List 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" }
PATCH / DELETE/api/api_keys/{id}/Dashboard only

Update (e.g. deactivate, set allowed_ip) or permanently delete a key. Dashboard session only.

Example response · 200

{ "id": 4, "is_active": false }

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.

200 / 201Success — 201 on resource creation, 200 otherwise.
202Accepted — the action was dispatched as a background task; poll for the real result (volumes: task-status).
400Bad request — missing or invalid fields, or a business rule was violated (e.g. wrong RAM tier, invalid size).
401Missing or invalid API key / token.
402Payment/quota required — balance below the deploy minimum, or a resource quota exceeded.
403Not permitted — often "a task is already running for this resource" or a suspended-for-non-payment guard.
404Not found, or it exists but isn't yours — ownership is never revealed via a 403.
409Conflict — e.g. already attached, wrong power state, or a live remote-provider error.
502The upstream regional/hypervisor API failed or was unreachable.

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.

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 /api/invoices/GET /api/transactions/GET /api/usage-billing/overview/GET /api/usage-billing/line-items/GET /api/users/me/PATCH /api/users/me/GET /api/activity/GET /api/trusted-ips/GET /api/tickets/GET /api/currencies/GET /api/pgs/POST /api/users/add_funds/GET/POST /api/api_keys/

Generate your first API key

$10 free credit on signup. Create a key from the dashboard and start scripting in minutes.