ONIE

API documentation

ONIE API v1 — call it from your own servers with an API key.

Get an API keyDownload the OpenAPI spec

Authentication

Attach the key to every request header. No key or a bad key returns 401.

curl -H "Authorization: Bearer vk_xxxxxxxx" \
     https://onie.net/v1/vm

Scopes

A key can only call endpoints within the scopes you picked when creating it. Missing scope returns 403 with code `scope_required`.

catalog:readRead plans and catalog
vm:readRead VMs, metrics and VM invoices
vm:writePower actions, minor changes, firewall, snapshots
vm:createCREATE new VMs (costs money)
vm:planCHANGE PLAN / custom resize (costs money)
vm:destroyDELETE VMs
vm:consoleOpen VNC console tickets
sshkey:readRead stored SSH keys
sshkey:writeAdd/remove SSH keys
billing:readRead wallet, invoices, payments (READ ONLY)
shield:readRead your own DDoS Shield
shield:writeWrite your own DDoS Shield rules

Endpoints

62 endpoints. “Scope” is what the key must have.

catalog

EndpointWhat it doesScope
GET /v1/vm/catalogPlans, regions and OS images catalog:read
GET /v1/public/plansPublic price list of the site catalog:read
GET /v1/vm/pricesUnit prices per component (vCPU, RAM, disk) catalog:read
GET /v1/vm/custom-quoteQuote a custom configuration catalog:read

vm

EndpointWhat it doesScope
GET /v1/vmList VMs vm:read
GET /v1/vm/:idGet one VM vm:read
GET /v1/vm/:id/metricsCPU/RAM/disk/network over time vm:read
GET /v1/vm/:id/bandwidthBandwidth usage vm:read
GET /v1/vm/:id/volumesVolumes of the VM vm:read
GET /v1/vm/:id/nicsNetwork interfaces and IPs vm:read
GET /v1/vm/:id/eventsVM event log vm:read
GET /v1/vm/:id/jobsRunning jobs of the VM vm:read
GET /v1/vm/:id/billingBilling of this VM vm:read
GET /v1/vm/:id/plan-quoteQuote before changing plan vm:read
GET /v1/vm/:id/plan-optionsPlans this VM can switch to (same zone) vm:read
GET /v1/vm/:id/delete-previewPreview before delete vm:read
GET /v1/vm/:id/firewallFirewall rules vm:read
GET /v1/vm/:id/port-forwardingPort forwarding rules vm:read
GET /v1/vm/:id/snapshotsList snapshots vm:read
GET /v1/vm/ops-keyThe pre-attached ops SSH key (name + fingerprint, not a secret) vm:read
POST /v1/vm/:id/startStart the VM vm:write
POST /v1/vm/:id/stopStop the VM (graceful) vm:write
POST /v1/vm/:id/force-stopForce stop the VM vm:write
POST /v1/vm/:id/rebootReboot the VM vm:write
POST /v1/vm/:id/reset-passwordReset the admin password vm:write
POST /v1/vm/:id/ssh-keyAttach an SSH key to the VM vm:write
PATCH /v1/vm/:idRename / notes vm:write
POST /v1/vm/:id/firewallAdd a firewall rule vm:write
DELETE /v1/vm/:id/firewall/:rule_idDelete a firewall rule vm:write
POST /v1/vm/:id/port-forwardingAdd a port-forwarding rule vm:write
DELETE /v1/vm/:id/port-forwarding/:rule_idDelete a port-forwarding rule vm:write
POST /v1/vm/:id/snapshotsCreate a snapshot vm:write
DELETE /v1/vm/:id/snapshots/:sidDelete a snapshot vm:write
POST /v1/vmCreate a VM (charges the wallet) Idempotency-Key requiredvm:create
POST /v1/vm/:id/change-planChange plan (prorated) Idempotency-Key requiredvm:plan
POST /v1/vm/:id/change-customCustom resize Idempotency-Key requiredvm:plan
DELETE /v1/vm/:idDelete the VM (data is lost) Idempotency-Key requiredvm:destroy
GET /v1/vm/:id/consoleGet a one-time VNC console ticket vm:console
POST /v1/vm/:id/ssh-tokenGet a one-time SSH WebSocket token vm:console
GET /v1/vm/:id/ai-agent/statusAI SSH Agent status and history vm:read
POST /v1/vm/:id/ai-agent/clearStart a new AI SSH Agent session vm:write
POST /v1/vm/:id/ai-agentRun AI SSH Agent (SSE stream) vm:console
GET /v1/vm/:id/console-sharesList active SSH session share links vm:read
POST /v1/vm/:id/console-sharesCreate an SSH session share link vm:console
DELETE /v1/vm/:id/console-shares/:sidRevoke an SSH session share link vm:console

sshkey

EndpointWhat it doesScope
GET /v1/vm/sshkeysList SSH keys sshkey:read
POST /v1/vm/sshkeysAdd an SSH key sshkey:write
DELETE /v1/vm/sshkeys/:idDelete an SSH key sshkey:write

billing

EndpointWhat it doesScope
GET /v1/billing/walletWallet balance billing:read
GET /v1/billing/summaryBilling overview billing:read
GET /v1/billing/invoicesList invoices billing:read
GET /v1/billing/invoices/:idGet one invoice billing:read
GET /v1/billing/paymentsPayment history billing:read
GET /v1/billing/ordersOrder history billing:read
GET /v1/client/usageCurrent usage billing:read

shield

EndpointWhat it doesScope
GET /v1/tenants/:tid/summaryDDoS Shield overview shield:read
GET /v1/tenants/:tid/targetsProtected IPs shield:read
GET /v1/tenants/:tid/targets/:id/rulesRules of one IP shield:read
GET /v1/tenants/:tid/targets/:id/eventsAttack events of one IP shield:read
GET /v1/tenants/:tid/trafficEdge traffic shield:read
POST /v1/tenants/:tid/targets/:id/rulesAdd a blocking rule shield:write
DELETE /v1/tenants/:tid/targets/:id/rules/:ridDelete a blocking rule shield:write

Rate limits

120 per key per minute, 300 per account per minute. Every response carries X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset; over the limit you get 429 with Retry-After (seconds to wait).

X-RateLimit-Limit: 120
X-RateLimit-Remaining: 118
X-RateLimit-Reset: 1758658800
Retry-After: 37          ← chỉ có khi 429
X-Request-Id: r7f2a9c1b4e8d0a63

Money-spending calls

Creating a VM, changing plan and deleting a VM require an Idempotency-Key header. Repeating the same value returns the earlier result instead of doing it again — a flaky network will not charge you twice.

curl -X POST https://onie.net/v1/vm \
     -H "Authorization: Bearer vk_xxxxxxxx" \
     -H "Idempotency-Key: don-hang-2026-09-23-001" \
     -H "Content-Type: application/json" \
     -d '{"plan":"vm-1-2","template":"ubuntu-24.04","hostname":"web-01"}'

Error shape

Every error uses the same shape, with X-Request-Id so support can trace it.

{
  "error": {
    "code": "scope_required",
    "message": "Khoá thiếu phạm vi quyền 'vm:write' cho POST /v1/vm/:id/start"
  }
}

Where to call from

This API is for your servers. CORS is not enabled, so it cannot be called from a browser. Never embed a key in client-side code.