QoCloud REST API
The API covers the same operations as the dashboard: create a server, reboot it, reinstall the OS, renew it. JSON over HTTPS, read-only or full-access keys, and events through webhooks.
https://qocloud.tech/api/v1Create a key under Settings → API keys and send it in the Authorization: Bearer … header. Store the key as you would a password.
Your first request
Store the token in an environment variable and list your servers.
$ export QOCLOUD_TOKEN="qc_live_…"$ curl https://qocloud.tech/api/v1/servers -H "Authorization: Bearer $QOCLOUD_TOKEN"/catalogPlans and prices
Locations, plans with monthly prices in rubles, available operating systems, billing periods and period discounts (in percent). No key required.
$ curl -X GET https://qocloud.tech/api/v1/catalog \ -H "Authorization: Bearer $QOCLOUD_TOKEN"{ "locations": [ { "code": "nl", "name": "Нидерланды", "available": true } ], "plans": [ { "id": "2c-4g-60", "line": "start", "cpu": 2, "ram_gb": 4, "disk_gb": 60, "monthly": { "nl": 945 } } ], "os": [ "ubuntu2404", "debian12" ], "periods": [ "1m", "3m", "6m", "1y" ], "discounts": { "1m": 0, "3m": 15, "6m": 20, "1y": 25 }}/balanceBalance
Account balance, monthly spend on running servers and auto-renewal status. Scope: read.
$ curl -X GET https://qocloud.tech/api/v1/balance \ -H "Authorization: Bearer $QOCLOUD_TOKEN"{ "balance": 4820, "currency": "RUB", "monthly_spend": 6241, "auto_renew": true}/serversList servers
All servers on the account. status: provisioning, active, suspended, expired, failed; power: running or stopped. Scope: read.
$ curl -X GET https://qocloud.tech/api/v1/servers \ -H "Authorization: Bearer $QOCLOUD_TOKEN"{ "servers": [ { "id": "6f1c2a9e-8b1d-4c1e-9f7a-2d3b4c5e6f70", "name": "web-01", "status": "active", "power": "running", "plan": "2c-4g-60", "cpu": 2, "ram_gb": 4, "disk_gb": 60, "location": "nl", "os": "ubuntu2404", "ip": "203.0.113.10", "price_month": 945, "paid_until": "2026-12-02T09:00:00.000Z", "created_at": "2026-06-02T09:00:00.000Z", "last_error": null } ]}/serversCreate a server
Charges the period price to your balance (with the 3, 6 or 12 month discount) and creates the server in 1–3 minutes. Send an Idempotency-Key header: a retry with the same key within 24 hours won’t create a second server. If your balance is insufficient, the API returns 402 with a need field. Scope: manage.
| Parameter | Description |
|---|---|
planstring · required | plan id from /catalog |
locationstring · required | location code: nl, de, pl, ee, cz, ch, se |
osstring · required | image from /catalog |
periodstring · required | 1m, 3m, 6m or 1y |
namestring · required | Latin letters, digits and hyphens, 2–60 characters |
$ curl -X POST https://qocloud.tech/api/v1/servers \ -H "Authorization: Bearer $QOCLOUD_TOKEN" \ -H "Content-Type: application/json" \ -d '{"plan":"2c-4g-60","location":"nl","os":"ubuntu2404","period":"1m","name":"web-02"}'{ "server": { "id": "6f1c2a9e-8b1d-4c1e-9f7a-2d3b4c5e6f70", "name": "web-02", "status": "provisioning", "power": null, "plan": "2c-4g-60", "cpu": 2, "ram_gb": 4, "disk_gb": 60, "location": "nl", "os": "ubuntu2404", "ip": null, "price_month": 945, "paid_until": "2026-12-02T09:00:00.000Z", "created_at": "2026-06-02T09:00:00.000Z", "last_error": null }}/servers/{id}Get a server
Current server details (status is checked against the data center). Scope: read.
| Parameter | Description |
|---|---|
idstring · required | server id |
$ curl -X GET https://qocloud.tech/api/v1/servers/6f1c2a9e-8b1d-4c1e-9f7a-2d3b4c5e6f70 \ -H "Authorization: Bearer $QOCLOUD_TOKEN"{ "server": { "id": "6f1c2a9e-8b1d-4c1e-9f7a-2d3b4c5e6f70", "name": "web-01", "status": "active", "power": "running", "plan": "2c-4g-60", "cpu": 2, "ram_gb": 4, "disk_gb": 60, "location": "nl", "os": "ubuntu2404", "ip": "203.0.113.10", "price_month": 945, "paid_until": "2026-12-02T09:00:00.000Z", "created_at": "2026-06-02T09:00:00.000Z", "last_error": null }}/servers/{id}/passwordRoot password
The current root password. Every request is recorded in the security log. Scope: manage.
$ curl -X GET https://qocloud.tech/api/v1/servers/6f1c2a9e-8b1d-4c1e-9f7a-2d3b4c5e6f70/password \ -H "Authorization: Bearer $QOCLOUD_TOKEN"{ "id": "6f1c2a9e-…", "root_password": "k3P…"}/servers/{id}/eventsServer log
Who managed the server and when: the control panel (user), an API key (api, with the key name in api_key), support (admin) or automation (system). Amount: negative for a charge, positive for a refund. Newest entries first. Scope: read.
| Parameter | Description |
|---|---|
idstring · required | server id |
limitnumber | number of entries to return, 1–200 (default 100) |
$ curl -X GET https://qocloud.tech/api/v1/servers/6f1c2a9e-8b1d-4c1e-9f7a-2d3b4c5e6f70/events \ -H "Authorization: Bearer $QOCLOUD_TOKEN"{ "events": [ { "id": "0b7e…", "at": "2026-06-02T09:05:00.000Z", "action": "change_ip", "label": "Смена IP", "actor": "api", "api_key": "deploy", "ok": true, "detail": "Прежний 203.0.113.10", "amount": -150 } ]}/servers/{id}/actions/{action}Server action
start, stop, reboot, reinstall (requires os), reset-password, change-ip (paid), renew (one month from your balance), upgrade (requires plan, you pay the difference for the rest of the period). Actions run asynchronously: the API returns 202 and the status changes within seconds to minutes. Scope: manage.
| Parameter | Description |
|---|---|
actionstring · required | start, stop, reboot, reinstall, reset-password, change-ip, renew, upgrade |
osstring | reinstall only |
planstring | upgrade only |
$ curl -X POST https://qocloud.tech/api/v1/servers/6f1c2a9e-8b1d-4c1e-9f7a-2d3b4c5e6f70/actions/reinstall \ -H "Authorization: Bearer $QOCLOUD_TOKEN" \ -H "Content-Type: application/json" \ -d '{"os":"debian12"}'{ "ok": true, "action": "reinstall", "message": "Переустановка началась", "server": { "id": "6f1c2a9e-…", "status": "active", "power": "running" }}/servers/{id}Update a server
Name, note, tags and auto-renewal. Send only the fields you change; auto_renew: null falls back to the account setting. Scope: manage.
| Parameter | Description |
|---|---|
namestring | Latin letters, digits and hyphens, 2–60 characters |
notestring | null | a note up to 1000 characters; null removes it |
tagsstring[] | the full tag list (replaces the old one) |
auto_renewboolean | null | auto-renewal for this server |
$ curl -X PATCH https://qocloud.tech/api/v1/servers/6f1c2a9e-8b1d-4c1e-9f7a-2d3b4c5e6f70 \ -H "Authorization: Bearer $QOCLOUD_TOKEN" \ -H "Content-Type: application/json" \ -d '{"name":"web-02","tags":["prod","eu"],"auto_renew":true}'{ "server": { "id": "6f1c2a9e-8b1d-4c1e-9f7a-2d3b4c5e6f70", "name": "web-02", "status": "active", "power": "running", "plan": "2c-4g-60", "cpu": 2, "ram_gb": 4, "disk_gb": 60, "location": "nl", "os": "ubuntu2404", "ip": "203.0.113.10", "price_month": 945, "paid_until": "2026-12-02T09:00:00.000Z", "created_at": "2026-06-02T09:00:00.000Z", "last_error": null, "note": null, "tags": [ "eu", "prod" ], "auto_renew": true }}/ssh-keysList SSH keys
Public keys on the account with SHA256 fingerprints, the same as in Settings. Scope: read.
$ curl -X GET https://qocloud.tech/api/v1/ssh-keys \ -H "Authorization: Bearer $QOCLOUD_TOKEN"{ "ssh_keys": [ { "id": "3a1b…", "name": "laptop", "type": "ssh-ed25519", "fingerprint": "SHA256:4f2A…", "public_key": "ssh-ed25519 AAAAC3Nza… laptop", "created_at": "2026-06-02T09:00:00.000Z" } ]}/ssh-keysAdd an SSH key
Accepts ed25519, ECDSA and RSA keys of 2048 bits or more. Adding the same key twice returns 409. Up to 20 keys. Responds with 201. Scope: manage.
| Parameter | Description |
|---|---|
public_keystring · required | the line from ~/.ssh/id_ed25519.pub |
namestring | a label; defaults to the key comment |
$ curl -X POST https://qocloud.tech/api/v1/ssh-keys \ -H "Authorization: Bearer $QOCLOUD_TOKEN" \ -H "Content-Type: application/json" \ -d '{"name":"laptop","public_key":"ssh-ed25519 AAAAC3Nza… laptop"}'{ "ssh_key": { "id": "3a1b…", "name": "laptop", "type": "ssh-ed25519", "fingerprint": "SHA256:4f2A…", "public_key": "ssh-ed25519 AAAAC3Nza… laptop", "created_at": "2026-06-02T09:00:00.000Z" }}/ssh-keys/{id}Delete an SSH key
Removes the key from the account. Servers you already created keep it in authorized_keys, so remove it there yourself. Scope: manage.
$ curl -X DELETE https://qocloud.tech/api/v1/ssh-keys/6f1c2a9e-8b1d-4c1e-9f7a-2d3b4c5e6f70 \ -H "Authorization: Bearer $QOCLOUD_TOKEN"{ "id": "3a1b…", "deleted": true}/servers/{id}Delete a server
Deletes the server and all its data. This can’t be undone. Requires an X-Confirm-Name header with the server name. The prepaid period is not refunded (see the refund policy). Scope: manage.
$ curl -X DELETE https://qocloud.tech/api/v1/servers/6f1c2a9e-8b1d-4c1e-9f7a-2d3b4c5e6f70 \ -H "Authorization: Bearer $QOCLOUD_TOKEN" \ -H "X-Confirm-Name: web-01"{ "id": "6f1c2a9e-…", "status": "deleted"}Events sent to your server
Set the URL and events under Settings → API → Webhooks. We send a JSON POST and wait up to 10 seconds for a 2xx response. On failure we retry after 1, 5 and 30 minutes, then 2, 6 and 12 hours. We don’t follow redirects.
server.readythe server is created and ready; data.server has the id, name and IPserver.expiringthe term is ending: 7 and 3 days ahead, 3 hours ahead and after it ends (stage)server.renewedthe server was renewed; data.amount is the amount chargedbalance.lowthe balance won’t cover upcoming renewals or dropped below your thresholdalert.firinga monitoring or uptime check alert firedalert.resolvedthe alert clearedpayment.succeededa payment was credited to your balance
Verifying the signature
The X-QoCloud-Signature header is t=<timestamp>,v1=<HMAC-SHA256 of “t.body” with the endpoint secret>. Check the signature and reject requests older than 5 minutes.
import crypto from 'node:crypto';function verify(body, header, secret) { const { t, v1 } = Object.fromEntries(header.split(',').map((p) => p.split('='))); if (Math.abs(Date.now() / 1000 - Number(t)) > 300) return false; const expected = crypto.createHmac('sha256', secret).update(`${t}.${body}`).digest('hex'); return crypto.timingSafeEqual(Buffer.from(v1, 'hex'), Buffer.from(expected, 'hex'));}Error codes
Error responses look like { "error": { "code", "message" } }. Codes do not change, so your scripts can branch on them.
- 401
unauthorizedThe key is missing, revoked or expired. - 403
forbiddenThe key is read-only, or the account is blocked. - 400
bad_requestInvalid fields; details are in fields. - 402
insufficient_balanceInsufficient balance; the missing amount is in need. - 404
not_foundServer not found (or it belongs to another account). - 409
conflictThe action isn’t available right now, for example while the server is being created or is stopped. - 429
rate_limited120 requests per minute per key; heavy operations are limited to 10 per 10 minutes.