Skip to content
Current coupon:10% offUse it in your order

API for custom panels and reselling

Manage your services from your own system: the same features as in your customer account, with keys and permissions you set yourself.

What the API is for

The API is for anyone who wants to manage StormHost services from their own environment: resellers with their own panel for their customers, companies with internal tools, or developers who want to handle server restarts, backups or DNS with a script.

Almost everything you do in your customer account works through the API: power and restart, statistics, reinstall, firewall, rDNS, backups, files, databases, game server and Minecraft settings, Discord bots, domain DNS, plan changes, renewals and paying with credit.

A key acts on your behalf, but only within the permissions you give it. For a service someone shares with you, the permissions its owner gave you apply as well.

Quick start

  1. In your customer account, open Account settings, the API keys tab, and create a key. Choose a name, permissions, optionally the services and IP addresses you'll use it from, and a validity period. You confirm creation with an authenticator code or your password.
  2. The key is shown only once. Copy it and store it securely, for example in an environment variable on your server. We only keep its fingerprint, so we can't show it again.
  3. Try your first request. The /api/v1/key endpoint returns information about the key and works with any valid key:
curl https://stormhost.eu/api/v1/key \
  -H "Authorization: Bearer shk_…"

Authentication

  • Every request sends the key in the Authorization header as Bearer shk_… (you can use the X-API-Key header instead).
  • The API doesn't use cookies. It rejects requests carrying a customer account login cookie, so the key can't be abused from a browser.
  • Never put the key in code that runs in a browser or a mobile app. It belongs on your server only.
  • After a password change or reset and when an account is blocked, existing keys stop working. Create new ones afterwards.
Authorization: Bearer shk_ab12cd34ef56_…

Permissions

Give a key only the permissions it really needs. A missing permission is rejected with 403, code insufficient_scope and the required permission in the requiredScope field.

PermissionWhat it allows
account:readAccount details (read only)
services:readService list, status and statistics
services:powerStart, stop, restart
services:consoleConsole
services:networkNetwork: rDNS, private network, addresses
services:firewallFirewall
services:filesFiles, worlds, plugins and mods
services:databaseDatabases
services:backupsBackups and restore
services:settingsService settings (games, bots, scheduler, alerts, ISO)
services:secretsSensitive: reinstall, passwords, SFTP, domain transfer codeonly with an IP restriction
domains:readDNS records (read only)
domains:writeDNS records and nameservers (changes)
billing:readInvoices and credit (read only)
billing:writeUpgrade orders, renewals and paying with credit

Service and IP restrictions

You can restrict a key to selected services. It then can't reach other services and the API answers 404 as if they didn't exist. A restricted key has no access to the account's invoices and credit. Without a restriction it works for all your services, including future ones.

You can restrict a key to IP addresses or ranges (e.g. 203.0.113.10 or 203.0.113.0/24, up to 20). From any other address the API answers 403 with code ip_not_allowed. The sensitive services:secrets permission requires this restriction.

You choose the validity when creating the key (30 to 365 days, or no expiry). You can revoke a key at any time and it stops working immediately.

Requests and responses

  • The API base address is https://stormhost.eu/api/v1. All responses are JSON in UTF-8, except file and PDF downloads.
  • Send requests with a body (POST, PUT, PATCH, DELETE) as JSON with the Content-Type: application/json header.
  • Choose the message language with ?locale=cs, en, sk, pl or de, and for writes also with a locale field in the body. Without it we answer in Czech.
  • The service identifier {id} is in the service list (GET /api/v1/services) or in the service address in your customer account.
  • A successful response has status 200. An error has status 4xx or 5xx with an error field (human-readable text) and usually a code field (machine-readable).
{
  "error": "This API key lacks the services:power scope.",
  "code": "insufficient_scope",
  "requiredScope": "services:power"
}

Errors

Errors shared by all endpoints. Endpoint-specific errors are listed with each endpoint in the reference.

StatusCodeMeaning
400cookies_not_allowedThe request carries cookies. The API is used with a key only.
401missing_keyThe Authorization header with a key is missing.
401invalid_keyThe key is invalid, expired or revoked.
403ip_not_allowedThe key can't be used from this IP address.
403insufficient_scopeThe key lacks the required permission (requiredScope field).
403email_unverifiedThe account e-mail is not verified.
404not_foundUnknown address, or a service the key has no access to.
400—The endpoint doesn't apply to this service type (e.g. Minecraft settings on a VPS).
409—The service is not active (pending setup, suspended or terminated).
405method_not_allowedMethod not allowed; the Allow header lists the allowed ones.
429rate_limitedRate limit exceeded; retry after the time in the Retry-After header.
503unavailableTemporarily unavailable, please try again shortly.

Limits

  • One key may send at most 300 requests per minute (all endpoints together).
  • Some endpoints have their own stricter limit, the same as in the customer account, for example power actions at 5 per minute.
  • When a limit is exceeded the API answers 429 and the Retry-After header says how many seconds to wait. Repeated invalid keys from one IP address are blocked for a while.
  • An account can have at most 20 active keys.

Code examples

The examples check the key and list services. They read the key from the STORMHOST_API_KEY environment variable. A typical reseller flow: list services, check the status and restart a service when needed.

curl

curl https://stormhost.eu/api/v1/key \
  -H "Authorization: Bearer $STORMHOST_API_KEY"

curl "https://stormhost.eu/api/v1/services?status=active" \
  -H "Authorization: Bearer $STORMHOST_API_KEY"

curl -X POST https://stormhost.eu/api/v1/services/SERVICE_ID/power \
  -H "Authorization: Bearer $STORMHOST_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"action":"restart"}'

JavaScript (Node.js)

const API = "https://stormhost.eu/api/v1";
const headers = { Authorization: `Bearer ${process.env.STORMHOST_API_KEY}` };

const res = await fetch(`${API}/services`, { headers });
if (!res.ok) throw new Error((await res.json()).error);
const { data } = await res.json();

for (const s of data) console.log(s.id, s.name, s.status);

await fetch(`${API}/services/${data[0].id}/power`, {
  method: "POST",
  headers: { ...headers, "Content-Type": "application/json" },
  body: JSON.stringify({ action: "restart" }),
});

PHP

<?php
$api = "https://stormhost.eu/api/v1";
$key = getenv("STORMHOST_API_KEY");

function call(string $method, string $url, string $key, ?array $body = null): array {
    $ch = curl_init($url);
    curl_setopt_array($ch, [
        CURLOPT_CUSTOMREQUEST => $method,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_HTTPHEADER => ["Authorization: Bearer $key", "Content-Type: application/json"],
        CURLOPT_POSTFIELDS => $body ? json_encode($body) : null,
    ]);
    $out = json_decode(curl_exec($ch), true);
    curl_close($ch);
    return $out;
}

$services = call("GET", "$api/services", $key)["data"];
call("POST", "$api/services/{$services[0]['id']}/power", $key, ["action" => "restart"]);

Python

import os, requests

API = "https://stormhost.eu/api/v1"
s = requests.Session()
s.headers["Authorization"] = f"Bearer {os.environ['STORMHOST_API_KEY']}"

services = s.get(f"{API}/services").json()["data"]
for svc in services:
    print(svc["id"], svc["name"], svc["status"])

r = s.post(f"{API}/services/{services[0]['id']}/power", json={"action": "restart"})
r.raise_for_status()

Endpoint reference

Each endpoint shows the method, address, required permission, parameters and a sample response. Values in the samples are made up.

Key and account

GET/keyAPI key details

Returns the key name, its scopes, service and IP restrictions and expiry. Needs no scope, so it's handy for checking a key.

Permission: –

Sample response

{
  "name": "Můj panel",
  "key": "shk_a1b2c3d4_…",
  "scopes": [
    "services:read",
    "services:power"
  ],
  "serviceIds": [],
  "allowedIps": [
    "203.0.113.10"
  ],
  "expiresAt": null,
  "createdAt": "2026-10-01T08:00:00.000Z"
}

Possible errors

  • 401invalid_key The key is invalid, expired or revoked.
GET/meAccount details

Returns basic details of the account the key belongs to: e-mail, name, company, company ID, VAT ID and country.

Permission: account:read

Sample response

{
  "id": "clx9k2m4p0000cus01abcdef",
  "email": "[email protected]",
  "firstName": "Jan",
  "lastName": "Novák",
  "companyName": null,
  "ico": null,
  "dic": null,
  "country": "CZ",
  "emailVerified": true,
  "createdAt": "2026-03-12T09:30:00.000Z"
}

Possible errors

  • 401invalid_key The key's account wasn't found.

Services

GET/overview/metricsLive service metrics

Returns the current state and usage of up to 8 services at once: power, CPU, memory and uptime for VPS and game servers, players for Minecraft, power draw for rack housing, expiry date for domains. When data can't be read, the service has state: unavailable with the reason in reason.

Permission: services:read

Query parameters

NameTypeRequiredDescription
idsstringnoComma-separated service IDs, at most 8. Without it, the first 8 services are returned. Unknown IDs are silently skipped. A key restricted to selected services may only send their IDs.
localestringnoLanguage of error messages: cs, en, sk, pl or de. Default is cs.

Sample response

{
  "at": "2026-11-07T10:00:00.000Z",
  "ttlMs": 2500,
  "truncated": false,
  "services": [
    {
      "serviceId": "clx9k2m4p0000svc01abcdef",
      "sampledAt": "2026-11-07T09:59:58.000Z",
      "kind": "vps",
      "state": "ok",
      "power": "running",
      "cpuPercent": 12.5,
      "cpuAt": "2026-11-07T09:59:00.000Z",
      "memUsedMib": 1536,
      "memTotalMib": 4096,
      "uptimeSeconds": 864000,
      "cpuSeries": [
        {
          "t": 1794045540000,
          "v": 11.2
        },
        {
          "t": 1794045600000,
          "v": 12.5
        }
      ]
    },
    {
      "serviceId": "clx9k2m4p0001svc02abcdef",
      "sampledAt": "2026-11-07T09:59:58.000Z",
      "kind": "game",
      "state": "ok",
      "power": "running",
      "cpuPercent": 34.1,
      "memUsedMib": 2900,
      "memTotalMib": 6144,
      "uptimeSeconds": 7200,
      "players": {
        "state": "ok",
        "online": 5,
        "max": 20,
        "at": "2026-11-07T09:55:00.000Z",
        "stale": false
      }
    },
    {
      "serviceId": "clx9k2m4p0002svc03abcdef",
      "sampledAt": "2026-11-07T09:59:58.000Z",
      "kind": "domain",
      "state": "ok",
      "expiresOn": "2027-05-01"
    },
    {
      "serviceId": "clx9k2m4p0003svc04abcdef",
      "sampledAt": "2026-11-07T09:59:58.000Z",
      "kind": "vps",
      "state": "unavailable",
      "reason": "provider"
    }
  ]
}

Possible errors

  • 404not_found The key is restricted to selected services and ids contains another service.
  • 429rate_limited Limit of 40 requests per minute exceeded.
  • 503unavailable The service list can't be loaded right now. Try again in a few seconds.
GET/servicesList services

Returns your services and services shared with you (role member, without price and with your permissions). A key restricted to selected services sees only those.

Permission: services:read

Query parameters

NameTypeRequiredDescription
statusstringnoFilter by status: PENDING, ACTIVE, SUSPENDED or TERMINATED (case-insensitive).
localestringnoLanguage of service names: cs, en, sk, pl or de. Default is cs.

Sample response

{
  "data": [
    {
      "id": "clx9k2m4p0000svc01abcdef",
      "name": "VPS Start",
      "type": "VPS",
      "kind": "vps",
      "status": "ACTIVE",
      "role": "owner",
      "plan": "vps-start",
      "address": "203.0.113.25",
      "priceCzk": 249,
      "currency": "CZK",
      "expiresAt": "2026-12-01T00:00:00.000Z",
      "createdAt": "2026-06-01T10:00:00.000Z"
    },
    {
      "id": "clx9k2m4p0001svc02abcdef",
      "name": "Minecraft server",
      "type": "GAME_SERVER",
      "kind": "game",
      "status": "ACTIVE",
      "role": "member",
      "permissions": [
        "power",
        "console"
      ],
      "plan": null,
      "address": "mc.example.com",
      "priceCzk": null,
      "currency": "CZK",
      "expiresAt": "2026-11-20T00:00:00.000Z",
      "createdAt": "2026-08-15T12:00:00.000Z"
    }
  ]
}
GET/services/{id}Service details

Returns one service in the same shape as the service list. Works for suspended and terminated services too.

Permission: services:read

Query parameters

NameTypeRequiredDescription
localestringnoLanguage of the service name and error messages: cs, en, sk, pl or de. Default is cs.

Sample response

{
  "data": {
    "id": "clx9k2m4p0000svc01abcdef",
    "name": "VPS Start",
    "type": "VPS",
    "kind": "vps",
    "status": "ACTIVE",
    "role": "owner",
    "plan": "vps-start",
    "address": "203.0.113.25",
    "priceCzk": 249,
    "currency": "CZK",
    "expiresAt": "2026-12-01T00:00:00.000Z",
    "createdAt": "2026-06-01T10:00:00.000Z"
  }
}

Possible errors

  • 404 The service doesn't exist, isn't yours, or the key has no access to it.
  • 400 This kind of service isn't supported by the API.
  • 403mfa_required The owner of the shared service requires two-factor authentication, which isn't enabled on your account.

Services in general

POST/services/{id}/console-tokenToken for the console connection

Issues a one-time token valid for 30 s for the console websocket of a VPS (VNC or terminal) or a game server. A console opened with a token from the API runs for about a minute at most; active services only, limit 10 per minute.

Permission: services:console

Request body (JSON)

NameTypeRequiredDescription
modestringyesVPS only: vnc or term. Ignored for game servers.

Sample body

{
  "mode": "vnc"
}

Sample response

{
  "token": "eyJhbGciOi…example",
  "password": "example-rfb-ticket"
}

Possible errors

  • 400 For a VPS, mode is missing or invalid.
  • 403 Missing Console permission on a shared service.
  • 404 Service not found or it has no console.
  • 409 The service isn't active or the VPS is locked (backup restore).
  • 412NOT_PROVISIONED The server isn't ready yet.
  • 429 More than 10 tokens per minute.
GET/services/{id}/crashServer crash and log analysis

Analyses the log, crash report or console output of a game server or bot and returns findings with suggested fixes. Changes nothing on the server; findings carry an id and parameters, not ready-made texts. Limit 10 analyses per minute per service.

Permission: services:read

Query parameters

NameTypeRequiredDescription
sourcestringnoauto (default), latest, crash-report, console or file.
namestringnoFile for source=file, e.g. logs/latest.log, crash-reports/crash-….txt or hs_err_pid….log (max 120 characters).
liststringnofiles returns the list of files that can be analysed (at most 50).
langstringnoMessage language: cs, en, sk, pl or de.
tplstringno1 = also allow fixes that send a fixed console command.

Sample response

{
  "result": {
    "v": 1,
    "kind": "mc",
    "findings": [
      {
        "id": "mc.oom",
        "sev": "critical",
        "p": {
          "heapMb": 2048
        },
        "evidence": [
          {
            "line": 412,
            "text": "java.lang.OutOfMemoryError: Java heap space"
          }
        ],
        "fix": {
          "type": "recalc-memory"
        },
        "alt": [
          {
            "type": "upgrade"
          }
        ]
      }
    ],
    "rootCause": {
      "cls": "java.lang.OutOfMemoryError",
      "msg": "Java heap space",
      "line": 412
    },
    "stats": {
      "lines": 1830,
      "truncated": false,
      "ms": 42,
      "timedOut": false,
      "crashReport": false
    }
  },
  "sources": [
    {
      "kind": "log",
      "name": "logs/latest.log",
      "mtime": 1762508000,
      "truncated": false
    }
  ]
}

Possible errors

  • 400bad-request Invalid parameter. Code bad-name: this file can't be analysed.
  • 403forbidden Missing Console or Files permission on a shared service.
  • 404no-source No log found, the server may not have run yet.
  • 412not-ready The server isn't ready yet.
  • 413too-large The log is too large to analyse (over 16 MiB).
  • 429rate Rate limit exceeded. Code busy: other servers are being analysed right now.
  • 502failed The log couldn't be loaded.
GET/services/{id}/databaseDatabase server on the VPS and overview

Detects whether MariaDB/MySQL or PostgreSQL is on the VPS and, once connected, returns the version, databases and users. VPS only.

Permission: services:database

Query parameters

NameTypeRequiredDescription
localestringnoLanguage of the reason in connectError: cs, en, sk, pl or de.

Sample response

{
  "detection": {
    "mysql": {
      "installed": true,
      "listening": true
    },
    "postgres": {
      "installed": false,
      "listening": false
    },
    "os": {
      "id": "debian",
      "like": "",
      "name": "Debian GNU/Linux 12 (bookworm)"
    },
    "canAutoInstall": true,
    "install": {
      "running": false,
      "engine": null,
      "exitCode": null,
      "logTail": null
    }
  },
  "config": {
    "engine": "mysql",
    "port": 3306,
    "username": "stormhost_panel",
    "auto": true
  },
  "overview": {
    "version": "10.11.6-MariaDB",
    "databases": [
      {
        "name": "shop",
        "sizeBytes": 5242880,
        "tables": 14,
        "system": false
      }
    ],
    "users": [
      {
        "name": "shop",
        "host": "localhost",
        "databases": [
          "shop"
        ],
        "system": false
      }
    ]
  },
  "connectError": null
}

Possible errors

  • 403 Missing the Databases permission.
  • 401AUTH_FAILED The VPS rejected the login credentials.
  • 409HOST_KEY_CHANGED The VPS SSH key fingerprint changed (new one in presentedHostKey); confirm it with the trustHostKey action.
  • 412NO_TARGET The VPS has no address or credentials yet (also NO_CREDENTIALS).
  • 502UNREACHABLE The VPS is unreachable (also TIMEOUT, FAILED).
POST/services/{id}/databaseInstall, connect, databases and users

Manages the database server on a VPS, chosen by the action field. Installation runs in the background (Debian/Ubuntu only); deleting a database or user cannot be undone. A generated password is returned only once.

Permission: services:database

Request body (JSON)

NameTypeRequiredDescription
actionstringyesinstall, connectAuto, connectManual, disconnect, createDatabase, dropDatabase, createUser, dropUser, setPassword or grant.
enginestringnoinstall, connectAuto, connectManual: mysql or postgres. connectAuto creates the panel account using local root access.
portintegernoconnectManual: database server port.
usernamestringnoconnectManual: user the panel connects as.
passwordstringnoconnectManual: password (required). createUser, setPassword: new password, 8–128 characters; generated if omitted.
namestringnoDatabase actions: database or user name, ASCII letters, digits and underscore, up to 63 characters, not starting with a digit.
createUserbooleannocreateDatabase: also create a user with the same name and full rights.
hoststringnocreateDatabase, createUser (MySQL): localhost (default) or %. dropUser: a specific host, otherwise all.
databasestringnocreateUser (optional), grant (required): database the user gets full rights to.

Sample body

{
  "action": "createDatabase",
  "name": "shop",
  "createUser": true,
  "host": "localhost"
}

Sample response

{
  "ok": true,
  "username": "shop",
  "password": "<generated>"
}

Possible errors

  • 400 Invalid request, reserved name, install already running, the system does not support automatic install, or an error from the database server.
  • 412 The database server is not connected yet.
  • 403 Missing the Databases permission.
  • 500 Internal error (the response includes a ref for support).
  • 401AUTH_FAILED The VPS rejected the login credentials.
  • 409HOST_KEY_CHANGED The VPS SSH key fingerprint changed (new one in presentedHostKey); confirm it with the trustHostKey action.
  • 412NO_TARGET The VPS has no address or credentials yet (also NO_CREDENTIALS).
  • 502UNREACHABLE The VPS is unreachable (also TIMEOUT, FAILED).
GET/services/{id}/database/browseTables and rows of a VPS database

Without table it returns the tables of a database with estimated row counts and sizes. With table it returns rows, 50 per page. VPS with a connected database server only.

Permission: services:database

Query parameters

NameTypeRequiredDescription
dbstringyesDatabase name.
tablestringnoTable name; without it the table list is returned.
schemastringnoPostgreSQL: table schema, default public.
pageintegernoPage from 0, 50 rows each.

Sample response

{
  "columns": [
    "id",
    "name",
    "created_at"
  ],
  "rows": [
    [
      "1",
      "Alice",
      "2026-10-01 12:00:00"
    ],
    [
      "2",
      "Bob",
      "2026-10-03 08:30:00"
    ]
  ],
  "page": 0,
  "pageSize": 50,
  "total": 2
}

Possible errors

  • 400 Invalid name or an error from the database server.
  • 412 The database server is not connected yet.
  • 403 Missing the Databases permission.
  • 401AUTH_FAILED The VPS rejected the login credentials.
  • 409HOST_KEY_CHANGED The VPS SSH key fingerprint changed (new one in presentedHostKey); confirm it with the trustHostKey action.
  • 412NO_TARGET The VPS has no address or credentials yet (also NO_CREDENTIALS).
  • 502UNREACHABLE The VPS is unreachable (also TIMEOUT, FAILED).
POST/services/{id}/database/queryRun an SQL query on the VPS

Runs an SQL query under the account the panel uses to connect to the VPS database server. Returns up to 500 rows, 25 s limit. The query can also change or delete data.

Permission: services:database

Request body (JSON)

NameTypeRequiredDescription
sqlstringyesSQL query, up to 100,000 characters.
dbstringnoDatabase to run the query in.

Sample body

{
  "db": "shop",
  "sql": "SELECT id, name FROM customers ORDER BY id LIMIT 10"
}

Sample response

{
  "columns": [
    "id",
    "name"
  ],
  "rows": [
    [
      "1",
      "Alice"
    ],
    [
      "2",
      "Bob"
    ]
  ],
  "rowCount": 2,
  "affectedRows": null,
  "truncated": false,
  "command": "SELECT",
  "durationMs": 7
}

Possible errors

  • 400 Invalid request or an error from the database server.
  • 412 The database server is not connected yet.
  • 403 Missing the Databases permission.
  • 429 At most 60 queries per minute.
  • 401AUTH_FAILED The VPS rejected the login credentials.
  • 409HOST_KEY_CHANGED The VPS SSH key fingerprint changed (new one in presentedHostKey); confirm it with the trustHostKey action.
  • 412NO_TARGET The VPS has no address or credentials yet (also NO_CREDENTIALS).
  • 502UNREACHABLE The VPS is unreachable (also TIMEOUT, FAILED).
GET/services/{id}/filesList a folder on the server

Lists a folder on a VPS (via SFTP) or on a game server or Discord bot, up to 5000 entries. For a VPS it adds access details without the password.

Permission: services:files

Query parameters

NameTypeRequiredDescription
pathstringnoAbsolute folder path. Default / for games and bots, the user's home folder for a VPS.

Sample response

{
  "path": "/home/app",
  "entries": [
    {
      "name": "logs",
      "type": "dir",
      "size": 4096,
      "mtime": 1762500000,
      "mode": "drwxr-xr-x",
      "owner": "app",
      "group": "app"
    },
    {
      "name": "config.yml",
      "type": "file",
      "size": 1832,
      "mtime": 1762489123,
      "mode": "-rw-r--r--",
      "owner": "app",
      "group": "app"
    },
    {
      "name": "current",
      "type": "link",
      "size": 12,
      "mtime": 1762400000,
      "mode": "lrwxrwxrwx",
      "owner": "app",
      "group": "app",
      "linkTarget": "/srv/releases/42",
      "linkType": "dir"
    }
  ],
  "truncated": false,
  "access": {
    "host": "203.0.113.20",
    "port": 22,
    "username": "root",
    "customCredentials": false,
    "hasDefaultPassword": true,
    "hostKey": "SHA256:AbCdEfGhIjKlMnOpQrStUvWxYz0123456789abcdefg"
  }
}

Possible errors

  • 400 Invalid path or SFTP error.
  • 403 Missing the Files permission.
  • 404 The folder does not exist on the game server.
  • 401AUTH_FAILED The VPS rejected the login credentials.
  • 409HOST_KEY_CHANGED The VPS SSH key fingerprint changed (new one in presentedHostKey); confirm it with the trustHostKey action.
  • 412NO_TARGET The VPS has no address or credentials yet (also NO_CREDENTIALS).
  • 502UNREACHABLE The VPS is unreachable (also TIMEOUT, FAILED).
POST/services/{id}/filesCreate, rename, edit or delete files

Runs a file action on a VPS, game server or Discord bot, chosen by the action field. Deleting cannot be undone; on a VPS folders are deleted with their content. Uploads are not available via the API, use SFTP.

Permission: services:files

Request body (JSON)

NameTypeRequiredDescription
actionstringyesmkdir, touch, rename, delete, chmod, write; VPS and owner only: credentials, resetCredentials, trustHostKey; games and bots only: compress, decompress.
pathstringnomkdir, touch, rename, chmod, write, decompress: absolute path of the item.
tostringnorename: new absolute path.
pathsstring[]nodelete: 1–200 absolute paths.
modestringnochmod: octal permissions, 3–4 digits (e.g. 644).
contentstringnowrite: full new file content in UTF-8, up to 2 MB.
usernamestringnocredentials: SSH user for the file manager (instead of root).
passwordstringnocredentials: SSH user password, stored encrypted after a successful login.
portintegernocredentials: SSH port 1–65535.
fingerprintstringnotrustHostKey: new key fingerprint in the form SHA256:….
dirstringnocompress: folder containing the items to pack.
namesstring[]nocompress: 1–200 names from the dir folder.
archiveNamestringnocompress: name of the .tar.gz archive, up to 120 characters.
intostringnodecompress: here (default) or newFolder.
folderNamestringnodecompress: name of the new folder, up to 120 characters.
localestringnoLanguage of messages: cs, en, sk, pl or de. Default cs.

Sample body

{
  "action": "write",
  "path": "/server.properties",
  "content": "motd=Můj server\nmax-players=20\n"
}

Sample response

{
  "ok": true
}

Possible errors

  • 400 Invalid request, path or name; system folders and /proc, /sys, /dev cannot be changed.
  • 403 Only the owner can change credentials; or the Files permission is missing.
  • 409 A file or folder with this name already exists.
  • 409JOB_RUNNING A software change or modpack install is running on the Minecraft server.
  • 409ARCHIVE_BUSY Another pack or unpack is running.
  • 413 The write content is larger than 2 MB.
  • 429 At most 10 packs and unpacks per 10 minutes.
  • 401AUTH_FAILED The VPS rejected the login credentials.
  • 409HOST_KEY_CHANGED The VPS SSH key fingerprint changed (new one in presentedHostKey); confirm it with the trustHostKey action.
  • 412NO_TARGET The VPS has no address or credentials yet (also NO_CREDENTIALS).
  • 502UNREACHABLE The VPS is unreachable (also TIMEOUT, FAILED).
GET/services/{id}/files/downloadDownload a file or read its text

Downloads a file from a VPS, game server or Discord bot. With as=text it returns the content of a UTF-8 text file as JSON, up to 1 MB.

Permission: services:files

Query parameters

NameTypeRequiredDescription
pathstringyesAbsolute file path.
asstringnotext = return the content as JSON instead of a download.

Sample response

{
  "path": "/server.properties",
  "content": "motd=Můj server\nmax-players=20\n",
  "eol": "lf",
  "bom": false
}

Possible errors

  • 400 Invalid path, not a regular file, or /proc, /sys, /dev on a VPS.
  • 413TOO_LARGE as=text: the file is larger than 1 MB.
  • 415BINARY as=text: the file is not UTF-8 text.
  • 403 Missing the Files permission.
  • 401AUTH_FAILED The VPS rejected the login credentials.
  • 409HOST_KEY_CHANGED The VPS SSH key fingerprint changed (new one in presentedHostKey); confirm it with the trustHostKey action.
  • 412NO_TARGET The VPS has no address or credentials yet (also NO_CREDENTIALS).
  • 502UNREACHABLE The VPS is unreachable (also TIMEOUT, FAILED).
GET/services/{id}/liveCurrent server state and usage

Returns the power state and current CPU, RAM, disk and network usage of a VPS or game server. For continuous monitoring use live/stream; if the state can't be read, the response is 200 with ok: false.

Permission: services:read

Query parameters

NameTypeRequiredDescription
pollstringnoValue live for repeated polling (every 2 s); the answer comes from the latest live sample.

Sample response

{
  "ok": true,
  "status": {
    "status": "ACTIVE",
    "details": {
      "vmStatus": "running",
      "gameState": null,
      "cpuPercent": 12.4,
      "memUsedMib": 1840,
      "memTotalMib": 4096,
      "diskUsedGb": 18.2,
      "diskTotalGb": 60,
      "netinMbps": 0.42,
      "netoutMbps": 1.1,
      "uptimeSeconds": 86400,
      "diskVolumes": [
        {
          "mountpoint": "/",
          "usedBytes": 19542261760,
          "totalBytes": 64424509440
        }
      ],
      "netInBps": 420000,
      "netOutBps": 1100000,
      "diskReadBytesPerSec": 0,
      "diskWriteBytesPerSec": 24576
    }
  }
}

Possible errors

  • 403mfa_required The service owner requires two-factor authentication for members.
  • 404 Service not found.
  • 429 More than 240 requests per minute.
GET/services/{id}/live/streamLive statistics over SSE

Opens a Server-Sent Events stream with usage samples of a VPS or game server about every second (hello, backfill, sample, disk, status, unavailable, end). A connection made with an API key ends after about a minute with an end event; then reconnect.

Permission: services:read

Sample response

event: hello
data: {"v":1,"kind":"vps","intervalMs":1000,"serverNow":1762508460000}

event: sample
data: {"t":1762508461000,"power":"running","vmStatus":"running","gameState":null,"cpuPercent":8.3,"memUsedMib":1840,"memTotalMib":4096,"netInBps":420000,"netOutBps":1100000,"diskReadBytesPerSec":0,"diskWriteBytesPerSec":24576,"uptimeSeconds":86401}

event: end
data: {"reason":"rotate"}

Possible errors

  • 403mfa_required The service owner requires two-factor authentication for members.
  • 404 Service not found.
  • 200 Other problems arrive as an end event with a reason: unsupported, busy (with retryInMs), revoked, inactive, moved, rotate.
PATCH/services/{id}/nameRename a service

Sets a custom service name, returned afterwards in the name field (productName keeps the plan name). null or an empty string restores the original name. Service owner only.

Permission: services:settings

Request body (JSON)

NameTypeRequiredDescription
namestring | nullyesNew name, at most 60 characters.
localestringnoLanguage of error messages (cs, en, sk, pl, de).

Sample body

{
  "name": "Survival server"
}

Sample response

{
  "name": "Survival server"
}

Possible errors

  • 400invalid The name is longer than 60 characters or the body contains other fields.
  • 404not_allowed The service doesn't belong to your account.
GET/services/{id}/outletsPDU outlet state and events

Returns the state of the rackhousing outlets (on, off, power, current), whether you may control them, and the last 20 PDU events. Rackhousing only; without outlets, view is null.

Permission: services:read

Query parameters

NameTypeRequiredDescription
beforestringnoEvent ID to load older events from (paging).

Sample response

{
  "view": {
    "canControl": true,
    "controlBlocked": null,
    "measuredAt": "2026-11-07T09:41:00.000Z",
    "stale": false,
    "outlets": [
      {
        "n": 3,
        "state": "on",
        "pending": false,
        "powerW": 120,
        "currentA": 0.52
      }
    ],
    "events": [
      {
        "id": "clx9k2m4p0001",
        "at": "2026-11-06T18:12:00.000Z",
        "kind": "command",
        "severity": "info",
        "outlet": 3,
        "action": "reboot",
        "result": "ok",
        "actorType": "customer",
        "actor": "vy",
        "serviceRef": "#A1B2C3",
        "message": "Restart zásuvky 3 — provedeno."
      }
    ],
    "eventsMore": false,
    "eventsAvailable": true
  }
}

Possible errors

  • 400 The service is not rackhousing.
  • 404 Service not found.
POST/services/{id}/outletsSwitch or restart PDU outlets

Sends a command to the PDU outlets that belong to your rackhousing service. Works only for an active service where support has enabled control; limit 6 per minute per account and 5 per minute per service.

Permission: services:power

Request body (JSON)

NameTypeRequiredDescription
outletsnumber[]yesOutlet numbers 1–48 (1 to 48 items), only outlets of this service.
commandstringyeson, off, reboot or cancel (cancels a pending command).

Sample body

{
  "outlets": [
    3,
    4
  ],
  "command": "reboot"
}

Sample response

{
  "ok": true,
  "outlets": [
    {
      "n": 3,
      "state": "on",
      "pending": true
    },
    {
      "n": 4,
      "state": "on",
      "pending": true
    }
  ]
}

Possible errors

  • 400not_yours An outlet does not belong to this service. Without a code: invalid request body.
  • 403not_allowed Outlet control is not enabled for the service.
  • 409inactive The service is not active. Code no_config: the PDU is not available right now.
  • 429 Rate limit exceeded.
  • 502pdu_failed The PDU did not carry out the command.
GET/services/{id}/powerRackhousing power consumption

Returns the outlet power draw against the contracted power, kWh for this and last month and a daily breakdown. Rackhousing only, data come from the last PDU reading; without outlets or data, view is null.

Permission: services:read

Sample response

{
  "view": {
    "contractedW": 500,
    "currentW": 212,
    "measuredAt": "2026-11-07T09:41:00.000Z",
    "stale": false,
    "monthKwh": 38.4,
    "lastMonthKwh": 151.2,
    "month": {
      "y": 2026,
      "m": 11,
      "days": 30,
      "today": 7
    },
    "daily": [
      5.1,
      5.3,
      5.4,
      5.6,
      5.5,
      5.7,
      5.8,
      null,
      null,
      null,
      null,
      null,
      null,
      null,
      null,
      null,
      null,
      null,
      null,
      null,
      null,
      null,
      null,
      null,
      null,
      null,
      null,
      null,
      null,
      null
    ],
    "outlets": [
      {
        "n": 3,
        "powerW": 120,
        "monthKwh": 21.6
      },
      {
        "n": 4,
        "powerW": 92,
        "monthKwh": 16.8
      }
    ]
  }
}

Possible errors

  • 400 The service is not rackhousing.
  • 404 The service does not exist or you have no access to it.
POST/services/{id}/powerStart, stop or restart a server

Starts, stops or restarts a VPS or a game server (also a bot). Active services only, at most 5 requests per minute per service; the billing status does not change.

Permission: services:power

Request body (JSON)

NameTypeRequiredDescription
actionstringyesstart, stop or restart.

Sample body

{
  "action": "restart"
}

Sample response

{
  "ok": true
}

Possible errors

  • 400 action is missing or invalid.
  • 404 Service not found, or power control is not available for it (e.g. rackhousing, web).
  • 409 The service is not active, a server software change is running, or a backup restore is still running.
  • 429 More than 5 requests per minute for the service.
  • 502 The action failed, try again.
GET/services/{id}/rackhousingRackhousing overview

Returns the rack position, height, contracted power, ports with link state and IP addresses of a rackhousing service. Port state comes from the last poll; the request changes nothing.

Permission: services:read

Sample response

{
  "view": {
    "site": "Praha",
    "rack": "R12",
    "unitRange": "U20–U21",
    "heightU": 2,
    "powerW": 500,
    "ports1g": 1,
    "ports10g": 1,
    "ports": [
      {
        "port": "port 3",
        "speed": "1g",
        "speedText": "1 Gbit",
        "status": "up"
      },
      {
        "port": "port 4",
        "speed": "10g",
        "speedText": "10 Gbit",
        "status": "down"
      }
    ],
    "ipv4": [
      {
        "address": "203.0.113.10",
        "prefix": 29,
        "gateway": "203.0.113.9"
      }
    ],
    "ipv6": "2001:db8:100::/48",
    "equipment": "1× server 2U",
    "polledAt": "2026-11-07T09:40:00.000Z"
  }
}

Possible errors

  • 400 The service is not rackhousing.
  • 404 Service not found.
GET/services/{id}/sftpSFTP login details

Returns the SFTP host, port and user name of a game server or bot; the password is never returned. A member of a shared service gets only owner: false. The feature isn't live yet and returns 404.

Permission: services:secrets

Query parameters

NameTypeRequiredDescription
langstringnoen for English messages, otherwise Czech.

Sample response

{
  "owner": true,
  "host": "203.0.113.40",
  "port": 2022,
  "username": "user.1a2b3c4d",
  "canSetPassword": true
}

Possible errors

  • 404 SFTP isn't live yet, or the service wasn't found.
  • 400 The service is neither a game server nor a bot.
  • 502 The details couldn't be loaded.
POST/services/{id}/sftpSet the SFTP password

Sets the given password for SFTP of a game server or bot; the password isn't stored anywhere and the owner gets an e-mail. Owner only, limit 5 per hour, the portal confirmation is replaced by the services:secrets scope. The feature isn't live yet and returns 404.

Permission: services:secrets

Query parameters

NameTypeRequiredDescription
langstringnoen for English messages, otherwise Czech.

Request body (JSON)

NameTypeRequiredDescription
actionstringyesAlways setPassword.
passwordstringyesNew password, 10–200 characters, not a common or leaked password.

Sample body

{
  "action": "setPassword",
  "password": "example-Sftp-Pass-2026"
}

Sample response

{
  "ok": true,
  "username": "user.1a2b3c4d"
}

Possible errors

  • 400weak_password The password doesn't meet the rules or the body is invalid.
  • 403insufficient_scope The key lacks the services:secrets scope. Code not_owner: you are not the owner.
  • 404 SFTP isn't live yet.
  • 409admin_user Support will set up SFTP for this service. Other codes: email_mismatch, foreign_server, inactive.
  • 429 More than 5 attempts per hour.
  • 502failed The password couldn't be set. Code unavailable: the service isn't available right now.

VPS and rackhousing

GET/services/{id}/backupsList VPS backups

Returns VPS backups from all storages, only from the current owner's time. Results are cached for 20 s, limit 10 requests per minute; partial: true means a storage didn't respond. Backups and storages have opaque ids (a backup's storageId = a storage id in storages); send the backup id to backups/restore.

Permission: services:backups

Sample response

{
  "backups": [
    {
      "id": "Q2xP7rT0aN4mVb8sKe1wYg",
      "storageId": "h5Jd9LkQ2pWm0ZcR7tUv3A",
      "storageLabel": "Backup 1",
      "sizeBytes": 8589934592,
      "createdAt": 1762394400,
      "name": "vps-000001"
    }
  ],
  "storages": [
    {
      "id": "h5Jd9LkQ2pWm0ZcR7tUv3A",
      "label": "Backup 1",
      "enabled": true
    },
    {
      "id": "Xo3bN6qE8yTf1GsD4lHk9w",
      "label": "Backup 2",
      "enabled": false
    }
  ]
}

Possible errors

  • 403 Missing Backups permission on a shared service.
  • 409 The service isn't active, or a backup restore is running.
  • 412NOT_PROVISIONED The VPS isn't ready yet.
  • 429 More than 10 requests per minute.
  • 502 Backups couldn't be loaded.
POST/services/{id}/backups/restoreRestore the VPS from a backup

Hard-stops the VPS and overwrites its disk with the chosen backup; irreversible. For larger disks the restore finishes in the background (pending: true) and the VPS can be started when it ends. Limit 3 per minute per service.

Permission: services:backups

Request body (JSON)

NameTypeRequiredDescription
idstringyesBackup id from the backups list.

Sample body

{
  "id": "Q2xP7rT0aN4mVb8sKe1wYg"
}

Sample response

{
  "ok": true,
  "pending": true,
  "message": "Obnova ze zálohy běží. VPS půjde zapnout, až skončí (u větších disků i několik minut)."
}

Possible errors

  • 400 id is missing.
  • 403 The backup doesn't belong to this service or no longer exists.
  • 409 The service isn't active or another restore is already running.
  • 429 More than 3 attempts per minute.
  • 502 The restore couldn't be started or completed.
GET/services/{id}/ddosAnti-DDoS protection availability

Tells whether Anti-DDoS settings are available for the VPS IP addresses. Currently always returns available: false; on a shared service a member needs the Network permission.

Permission: services:read

Sample response

{
  "available": false
}

Possible errors

  • 400 The service is not a VPS.
  • 409 The service isn't active.
GET/services/{id}/firewallVPS firewall rules

Returns the VPS firewall settings and all rules, including managed ones (field managed) that can't be changed. Send the digest value when editing a rule.

Permission: services:firewall

Sample response

{
  "digest": "3f2a9c0d1e5b7a8c4d6e2f1a0b9c8d7e6f5a4b3c",
  "baseline": true,
  "enabled": true,
  "ipfilter": true,
  "macfilter": true,
  "policyIn": "DROP",
  "policyOut": "ACCEPT",
  "inboundDefault": "accept",
  "scannerBlock": true,
  "ipfilterEntries": [
    "203.0.113.25",
    "2001:db8:10::/64"
  ],
  "rules": [
    {
      "pos": 0,
      "managed": "censys",
      "type": "in",
      "action": "DROP",
      "proto": "",
      "dport": "",
      "sport": "",
      "source": "+dc/censys",
      "dest": "",
      "macro": "",
      "comment": "",
      "enable": true
    },
    {
      "pos": 1,
      "managed": null,
      "type": "in",
      "action": "DROP",
      "proto": "tcp",
      "dport": "3306",
      "sport": "",
      "source": "",
      "dest": "",
      "macro": "",
      "comment": "MySQL ven ne",
      "enable": true
    },
    {
      "pos": 2,
      "managed": "allowIn",
      "type": "in",
      "action": "ACCEPT",
      "proto": "",
      "dport": "",
      "sport": "",
      "source": "",
      "dest": "+guest/ipfilter-net0",
      "macro": "",
      "comment": "",
      "enable": true
    }
  ]
}

Possible errors

  • 403 Missing Firewall permission on a shared service.
  • 409 The service isn't active or the action can't be done right now.
  • 412 The VPS isn't ready yet.
  • 502 The firewall couldn't be loaded.
POST/services/{id}/firewallEdit VPS firewall rules

Adds, edits, enables or disables, deletes or moves a custom rule, switches default inbound traffic or applies the recommended setup. Actions on a position need digest from GET; at most 50 custom rules, messages are in Czech.

Permission: services:firewall

Request body (JSON)

NameTypeRequiredDescription
actionstringyesadd, update, toggle, delete, move, setInbound or applyBaseline.
posnumbernoFor update, toggle, delete and move: position of a custom rule from GET.
digeststringnoFor update, toggle, delete and move: digest from GET.
ruleobjectnoFor add and update: type (in, out), action (ACCEPT, DROP, REJECT), proto ("", tcp, udp, icmp, ipv6-icmp), dport, sport (e.g. 22, 80,443, 25565:25570; TCP and UDP only), source, dest (IP or range, at most 10), comment (max 100), enable.
enablebooleannoFor toggle: enable or disable the rule.
directionstringnoFor move: up or down (only among custom rules).
valuestringnoFor setInbound: accept or drop (default inbound traffic).

Sample body

{
  "action": "add",
  "rule": {
    "type": "in",
    "action": "ACCEPT",
    "proto": "tcp",
    "dport": "22",
    "source": "198.51.100.0/24",
    "comment": "SSH z kanceláře"
  }
}

Sample response

{
  "ok": true,
  "firewall": {
    "digest": "9b1c2d3e4f5a6b7c8d9e0f1a2b3c4d5e6f7a8b9c",
    "baseline": true,
    "enabled": true,
    "ipfilter": true,
    "macfilter": true,
    "policyIn": "DROP",
    "policyOut": "ACCEPT",
    "inboundDefault": "accept",
    "scannerBlock": true,
    "ipfilterEntries": [
      "203.0.113.25"
    ],
    "rules": []
  }
}

Possible errors

  • 400 Invalid body or rule (port, address, protocol), or more than 50 custom rules.
  • 403 A managed rule can't be changed, or the Firewall permission is missing.
  • 409 The firewall changed meanwhile (reload digest), the service isn't active, a restore is running or the recommended setup can't be applied.
  • 502 The change couldn't be saved.
GET/services/{id}/historyVPS usage history

Returns CPU, RAM, network and disk history of a VPS for the chosen range (at most 300 points), CPU peaks and traffic for 30 days and since the start of the month. Results are cached for 20 s, limit 30 requests per minute.

Permission: services:read

Query parameters

NameTypeRequiredDescription
rangestringnohour, day, week, month or year. Default day.
langstringnoen for English error messages, otherwise Czech.

Sample response

{
  "range": "day",
  "points": [
    {
      "t": 1762473600,
      "cpu": 6.2,
      "ram": 44.8,
      "netIn": 52000,
      "netOut": 138000,
      "diskRead": 0,
      "diskWrite": 20480
    }
  ],
  "cpuPeak": [
    {
      "t": 1762473600,
      "cpu": 31.5
    }
  ],
  "cpu": {
    "avg": 7.1,
    "max": 64.2
  },
  "transfer30d": {
    "inBytes": 18253611008,
    "outBytes": 42949672960
  },
  "transferMonth": {
    "inBytes": 4294967296,
    "outBytes": 9663676416
  }
}

Possible errors

  • 400 The service is not a VPS.
  • 409 The VPS is neither active nor suspended, or can't be verified right now.
  • 429 More than 30 requests per minute.
  • 502 Statistics can't be loaded right now.
GET/services/{id}/installVPS installation status

Returns the phase of a VPS installation or reinstall (image, create, start, finish, done) and whether it is still running. Useful for polling after a reinstall, limit 90 requests per minute.

Permission: services:read

Sample response

{
  "status": "ACTIVE",
  "phase": "finish",
  "active": true,
  "source": "reinstall",
  "restarting": false,
  "running": true,
  "reboot": true,
  "failed": false
}

Possible errors

  • 400 The service is not a VPS.
  • 404 Service not found.
  • 429 More than 90 requests per minute.
GET/services/{id}/isoISO images and the attached ISO

Returns the ISO catalogue, your own ISOs, limits, the currently attached ISO with the boot setting and the state of the last action. VPS owner only.

Permission: services:settings

Sample response

{
  "available": true,
  "catalog": [
    {
      "id": "clx9a0iso0001",
      "kind": "catalog",
      "name": "Debian 13 netinst",
      "osFamily": "debian",
      "sizeBytes": 754974720,
      "createdAt": "2026-10-20T08:00:00.000Z",
      "lastUsedAt": null,
      "expiresAt": null
    }
  ],
  "own": [
    {
      "id": "clx9a0iso0002",
      "kind": "custom",
      "name": "Rescue tools",
      "osFamily": null,
      "sizeBytes": 524288000,
      "createdAt": "2026-11-02T12:00:00.000Z",
      "lastUsedAt": "2026-11-03T09:00:00.000Z",
      "expiresAt": "2026-12-03T09:00:00.000Z"
    }
  ],
  "limits": {
    "count": 2,
    "maxBytes": 10737418240,
    "retentionDays": 30
  },
  "status": {
    "attached": false,
    "bootFromIso": false,
    "isoId": null,
    "name": null
  },
  "job": null
}

Possible errors

  • 400 The service is not a VPS.
  • 403 You are not the service owner.
  • 409 The service isn't active.
POST/services/{id}/isoAdd, attach or detach an ISO

Depending on action, adds your own ISO from an HTTPS link, deletes it, attaches an ISO to the VPS, switches boot or ejects the ISO. Attaching runs as a background action (the file is downloaded first); owner only, at most 2 own ISOs up to 10 GB.

Permission: services:settings

Request body (JSON)

NameTypeRequiredDescription
actionstringyesadd, delete, attach, boot or detach.
namestringnoFor add: ISO name (max 80 characters), otherwise taken from the file.
urlstringnoFor add: public https:// link to the ISO file that reports its size.
isoIdstringnoFor delete and attach: ISO ID from GET.
bootbooleannoFor attach and boot: true = boot from ISO, otherwise from disk.

Sample body

{
  "action": "attach",
  "isoId": "clx9a0iso0001",
  "boot": true
}

Sample response

{
  "ok": true,
  "job": {
    "id": "clx9r1t7w0004",
    "kind": "iso",
    "state": "running",
    "step": null,
    "startedAt": "2026-11-07T10:00:00.000Z",
    "updatedAt": "2026-11-07T10:00:00.000Z"
  }
}

Possible errors

  • 400url The link can't be used (not HTTPS, non-public network, over 10 GB, no size, not a file). Other codes: limit, attached; without a code, invalid action.
  • 404not_found ISO not found.
  • 409unavailable ISOs aren't available right now. Without a code: another action is running on the VPS.
  • 429 More than 10 ISOs added per day.
  • 502 The action failed.
GET/services/{id}/private-networkPrivate networks in the VPS location

Returns your private networks in the VPS location, their members, limits and the state of this VPS in each network. VPS owner only.

Permission: services:network

Sample response

{
  "enabled": true,
  "scope": "location",
  "maxNetworks": 5,
  "maxMembers": 20,
  "priceCzk": null,
  "networks": [
    {
      "id": "clx9p7net0001",
      "name": "zalohy",
      "cidr": "10.20.0.0/24",
      "prefix": 24,
      "createdAt": "2026-10-18T08:00:00.000Z",
      "members": [
        {
          "serviceId": "clx9svc000001",
          "shortId": "#000001",
          "ipv4": "203.0.113.25",
          "address": "10.20.0.1",
          "state": "active",
          "isThis": true,
          "own": true
        }
      ],
      "me": {
        "address": "10.20.0.1",
        "mac": "BC:24:11:00:00:01",
        "nicIndex": 1,
        "state": "active",
        "cloudInit": false,
        "failed": false
      },
      "canDelete": false
    }
  ]
}

Possible errors

  • 403 You are not the service owner.
  • 409 The service isn't active.
  • 503unavailable Private networks aren't available right now.
POST/services/{id}/private-networkCreate, attach or detach a network

Creates a private network, attaches or detaches this VPS, or deletes an empty network. Attaching needs the recommended firewall setup; when pendingRestart is true, the change takes effect after a VPS restart.

Permission: services:network

Request body (JSON)

NameTypeRequiredDescription
actionstringyescreate, attach, detach or delete.
namestringnoFor create: network name, 1–40 characters (letters, digits, space, . _ -).
cidrstringnoFor create: private range /16 to /29 starting at the network address, e.g. 10.20.0.0/24.
networkIdstringnoFor attach, detach and delete: network ID from GET.
addressstring|nullnoFor attach: VPS address in the network; empty = first free one.
cloudInitbooleannoFor attach: true = also write the address into the VPS cloud-init.

Sample body

{
  "action": "attach",
  "networkId": "clx9p7net0001",
  "address": "10.20.0.5"
}

Sample response

{
  "ok": true,
  "address": "10.20.0.5",
  "mac": "BC:24:11:00:00:05",
  "pendingRestart": true,
  "view": {
    "enabled": true,
    "scope": "location",
    "maxNetworks": 5,
    "maxMembers": 20,
    "priceCzk": null,
    "networks": []
  }
}

Possible errors

  • 400invalid_request Invalid body. Other codes: name_invalid, cidr_invalid, address_invalid, address_outside, address_reserved.
  • 404network_not_found Network not found. Code not_member: the VPS isn't in the network.
  • 409firewall_required Apply the recommended firewall setup first. Other codes: cidr_overlap, limit_networks, limit_members, address_taken, network_full, not_empty, detaching, other_location, other_node, no_slot, vm_locked, disabled, no_vlan.
  • 412vm_not_ready The VPS isn't ready yet.
  • 502apply_failed The change couldn't be completed.
  • 503unavailable Private networks aren't available right now.
GET/services/{id}/rdnsReverse DNS of VPS addresses

Returns PTR records of the VPS IP addresses: current, default and custom value, plus the service's IPv6 ranges. On a shared service a member needs the Network permission.

Permission: services:network

Sample response

{
  "configured": true,
  "error": null,
  "entries": [
    {
      "ip": "203.0.113.25",
      "family": 4,
      "current": "mail.example.com",
      "default": "25.113.0.203.example.net",
      "custom": "mail.example.com"
    },
    {
      "ip": "2001:db8:10::2",
      "family": 6,
      "current": null,
      "default": "vps.example.net",
      "custom": null
    }
  ],
  "ranges": [
    {
      "cidr": "2001:db8:10::/64",
      "family": 6
    }
  ],
  "vmIpv6": "2001:db8:10::2"
}

Possible errors

  • 400 The service is not a VPS.
  • 403 Missing Network permission on a shared service.
  • 409 The service isn't active.
POST/services/{id}/rdnsSet or reset a PTR record

Sets a custom reverse DNS for an IP address assigned to the VPS, or with hostname null restores the default record. At most 32 custom records, limit 20 changes per minute; messages are in Czech.

Permission: services:network

Request body (JSON)

NameTypeRequiredDescription
ipstringyesIPv4 or IPv6 address of the service (also from its IPv6 range).
hostnamestring|nullyesHost name, e.g. mail.example.com (max 253 characters); null or empty = default record.

Sample body

{
  "ip": "203.0.113.25",
  "hostname": "mail.example.com"
}

Sample response

{
  "ok": true,
  "ip": "203.0.113.25",
  "ptr": "mail.example.com",
  "isDefault": false
}

Possible errors

  • 400 Invalid host name, reverse or reserved domain, or more than 32 custom records.
  • 403 The IP address doesn't belong to this service, or the Network permission is missing.
  • 502 rDNS couldn't be saved right now.
GET/services/{id}/reinstallSystems available for VPS reinstall

Returns the systems that can be installed on the VPS, the current system, the time of the last reinstall and the state of the last action. Service owner only.

Permission: services:read

Sample response

{
  "options": [
    {
      "key": "ubuntu-2404",
      "label": "Ubuntu 24.04 LTS"
    },
    {
      "key": "debian-13",
      "label": "Debian 13"
    }
  ],
  "job": {
    "id": "clx9r1t7w0002",
    "kind": "reinstall",
    "state": "done",
    "step": null,
    "startedAt": "2026-11-01T10:00:00.000Z",
    "updatedAt": "2026-11-01T10:06:12.000Z",
    "finishedAt": "2026-11-01T10:06:12.000Z",
    "error": null
  },
  "os": "ubuntu-2404",
  "reinstalledAt": "2026-11-01T10:06:12.000Z"
}

Possible errors

  • 400 The service is not a VPS.
  • 403 You are not the service owner.
  • 409 The service isn't active.
POST/services/{id}/reinstallReinstall the VPS

Wipes the VPS disk and installs the chosen system; runs in the background, follow progress via install. The new root password is only in this response. Owner only, at most 3 times a day; the portal confirmation is replaced by the services:secrets scope.

Permission: services:secrets

Request body (JSON)

NameTypeRequiredDescription
osstringyesSystem key from GET, e.g. ubuntu-2404 or debian-13.
sshKeysstringnoPublic SSH keys, one per line, at most 10 (ssh-ed25519, ssh-rsa, ecdsa-…).

Sample body

{
  "os": "debian-13",
  "sshKeys": "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIExampleKeyExampleKeyExampleKeyExample user@laptop"
}

Sample response

{
  "started": true,
  "password": "example-Root-Pass-123",
  "job": {
    "id": "clx9r1t7w0003",
    "kind": "reinstall",
    "state": "running",
    "step": null,
    "startedAt": "2026-11-07T10:00:00.000Z",
    "updatedAt": "2026-11-07T10:00:00.000Z"
  }
}

Possible errors

  • 400 Missing or invalid system, invalid SSH key or more than 10 keys.
  • 403insufficient_scope The key lacks the services:secrets scope, or you are not the owner.
  • 409 Another action is running, the VPS is in rescue mode, the node is busy or reinstall is unavailable.
  • 429 The reinstall has already run 3 times in the last 24 hours.
  • 502 The reinstall couldn't be started.
POST/services/{id}/reveal-secretReveal the stored VPS root password

Returns the stored VPS root password from creation, reinstall or the last change. Every reveal is audited and the owner gets an e-mail; limit 5 per 10 minutes, the portal confirmation is replaced by the services:secrets scope.

Permission: services:secrets

Sample response

{
  "password": "example-Root-Pass-789"
}

Possible errors

  • 403insufficient_scope The key lacks the services:secrets scope. Without a code: missing permission on a shared service.
  • 404 Service not found or no password is stored for it.
  • 429 More than 5 reveals in 10 minutes.
  • 503 The password can't be shown right now, try again.
GET/services/{id}/root-passwordCan a new root password be set?

Checks whether the VPS root password can be changed right now through qemu-guest-agent and returns the reason if not. The result is cached for 60 s.

Permission: services:secrets

Query parameters

NameTypeRequiredDescription
langstringnoen for English messages, otherwise Czech.

Sample response

{
  "available": false,
  "reason": "stopped",
  "message": "VPS je vypnutá. Heslo jde nastavit jen u běžící VPS."
}

Possible errors

  • 400 The service is not a VPS.
  • 403 Missing Secrets permission on a shared service.
  • 409 The service isn't active.
POST/services/{id}/root-passwordSet a new VPS root password

Generates a new root password, sets it in the running VPS through qemu-guest-agent and returns it only in this response; the owner gets an e-mail. Limit 3 per hour per service and 10 per day per account; the portal confirmation is replaced by the services:secrets scope.

Permission: services:secrets

Query parameters

NameTypeRequiredDescription
langstringnoen for English messages, otherwise Czech.

Sample response

{
  "password": "example-Root-Pass-456"
}

Possible errors

  • 403insufficient_scope The key lacks the services:secrets scope. Without a code: missing permission on a shared service.
  • 409 The password can't be set right now; field reason: agent_down, stopped, rescue, command_disabled, not_configured, no_permission or busy.
  • 429 Limit of 3 per hour or 10 per day exceeded.
  • 502 The agent didn't set the password, the old one still works (reason failed or unavailable).

Game servers

GET/services/{id}/alertsCrash and outage alert settings

Returns the alert settings of a game server or Discord bot (e-mail, Discord webhook, events) and the history of recent alerts. The webhook address is never returned, only its ending. Owner only.

Permission: services:settings

Query parameters

NameTypeRequiredDescription
langstringnoLanguage of messages: en, otherwise cs.

Sample response

{
  "settings": {
    "enabled": true,
    "email": true,
    "discord": {
      "hint": "discord.com/api/webhooks/…ab12",
      "disabled": false
    },
    "events": {
      "crash": true,
      "down": true,
      "recovered": true,
      "cleanExit": false,
      "node": true
    },
    "includeLog": true,
    "updatedAt": "2026-11-02T18:20:00.000Z"
  },
  "history": [
    {
      "id": "alr_01",
      "at": "2026-11-06T21:14:03.000Z",
      "kind": "crash",
      "exitCode": 137,
      "oom": true,
      "reason": null,
      "cause": null,
      "suppressed": null,
      "channels": {
        "email": "sent",
        "discord": "sent"
      },
      "extra": 0,
      "downtimeMin": null
    }
  ]
}

Possible errors

  • 403 Only for the service owner.
POST/services/{id}/alertsSave, test or turn off alerts

Changes the alert settings, chosen by the action field. A new Discord webhook is saved only if a test message gets through. The body must not contain other fields. Owner only.

Permission: services:settings

Query parameters

NameTypeRequiredDescription
langstringnoLanguage of messages: en, otherwise cs.

Request body (JSON)

NameTypeRequiredDescription
actionstringyessave, test (test message to the saved webhook, once a minute and 5 times an hour), removeDiscord or disable.
enabledbooleannosave: turn monitoring on.
emailbooleannosave: send alerts by e-mail to the owner.
eventsobjectnosave: which events to report, keys crash, down, recovered, cleanExit, node (boolean).
includeLogbooleannosave: attach the end of the log.
webhookstringnosave: new Discord webhook address (https://discord.com/api/webhooks/…), up to 300 characters.

Sample body

{
  "action": "save",
  "enabled": true,
  "email": true,
  "events": {
    "crash": true,
    "down": true,
    "recovered": true,
    "cleanExit": false,
    "node": true
  },
  "includeLog": true
}

Sample response

{
  "ok": true,
  "settings": {
    "enabled": true,
    "email": true,
    "discord": null,
    "events": {
      "crash": true,
      "down": true,
      "recovered": true,
      "cleanExit": false,
      "node": true
    },
    "includeLog": true,
    "updatedAt": "2026-11-07T10:05:00.000Z"
  }
}

Possible errors

  • 400bad-request Invalid body or extra fields.
  • 400webhook The address is not a Discord webhook.
  • 400test-failed The test message could not be delivered.
  • 400no-webhook test: no webhook is saved.
  • 400no-channel Enabled monitoring needs e-mail or a webhook.
  • 429rate A test message can be sent once a minute and 5 times an hour.
  • 500failed The settings could not be saved.
  • 403 Only for the service owner.
GET/services/{id}/gameNetwork, databases, backups or startup

Returns one part of a game server or Discord bot setup, chosen by the section parameter. Database passwords and secret variable values are returned only to the owner and members with the Secrets permission.

Permission: services:settings

Query parameters

NameTypeRequiredDescription
sectionstringyesnetwork (ports and SFTP), databases, backups (backups and the backup add-on) or startup (startup command and variables).
localestringnoLanguage of access error messages: cs, en, sk, pl or de.

Sample response

{
  "allocations": [
    {
      "id": 1201,
      "ip": "203.0.113.10",
      "port": 25565,
      "notes": null,
      "primary": true
    },
    {
      "id": 1202,
      "ip": "203.0.113.10",
      "port": 25566,
      "notes": "Dynmap",
      "primary": false
    }
  ],
  "limit": 3,
  "sftp": {
    "ip": "203.0.113.10",
    "port": 2022
  }
}

Possible errors

  • 400 The section is missing or unknown.
  • 403 Missing permission for this section (Network, Databases, Backups or Settings).
  • 412 The server is not available in the game panel yet.
POST/services/{id}/gameDatabases, backups, variables, ports and reinstall

Runs one action on a game server or Discord bot, chosen by the action field. Restoring or deleting a backup, deleting a database and reinstalling cannot be undone; reinstall stops the server and overwrites files.

Permission: services:settings

Request body (JSON)

NameTypeRequiredDescription
actionstringyescreateDatabase, rotateDatabasePassword, deleteDatabase, createBackup, restoreBackup, deleteBackup, lockBackup (locks or unlocks), setVariable, reinstall, addAllocation or removeAllocation.
namestringnocreateDatabase: database name, 1–48 characters (letters, digits, underscore), required. createBackup: optional backup name, up to 191 characters.
remotestringnocreateDatabase: where connections to the database are allowed from (IP address or %). Default % = anywhere.
databaseIdstringnorotateDatabasePassword, deleteDatabase: database id from GET ?section=databases.
uuidstring (uuid)norestoreBackup, deleteBackup, lockBackup: backup uuid from GET ?section=backups.
truncatebooleannorestoreBackup: delete all server files before restoring. Default false.
keystringnosetVariable: name of the startup variable (uppercase letters, digits, underscore).
valuestringnosetVariable: new value, up to 4096 characters, no control characters.
allocationIdintegernoremoveAllocation: port id from GET ?section=network. The primary port cannot be removed.
localestringnoLanguage of messages: cs, en, sk, pl or de. Default cs.

Sample body

{
  "action": "setVariable",
  "key": "MAX_PLAYERS",
  "value": "32"
}

Sample response

{
  "ok": true,
  "value": "32"
}

Possible errors

  • 400 Invalid request body or database name.
  • 400CONTROL_CHARS The variable value contains control characters.
  • 403 Missing permission for the action; reinstall also needs Files and Power.
  • 403SECRETS_REQUIRED A secret variable can only be changed by the owner or a member with the Secrets permission.
  • 403FILES_REQUIRED The Discord bot code source can only be changed with the Files permission.
  • 404 The backup does not exist.
  • 409MANAGED_VARIABLE The variable is managed by StormHost and cannot be changed.
  • 409MC_MANAGED_VARIABLE For Minecraft this variable is set in the Software tab.
  • 409PROTECTED_ARGUMENT Free arguments must not override protected parameters (e.g. RCON).
  • 409JOB_RUNNING A software change is running on the Minecraft server.
  • 409PORT_LIMIT The package has no free port left.
  • 409NO_FREE_PORT There is no free port on the node right now.
  • 412 The server is not available in the game panel yet.
GET/services/{id}/game/backup-downloadDownload a game server backup

Downloads the backup archive (.tar.gz) of a game server or Discord bot. The archive contains all files including secrets, so members also need the Files permission.

Permission: services:backups

Query parameters

NameTypeRequiredDescription
uuidstring (uuid)yesBackup uuid from GET …/game?section=backups.
localestringnoLanguage of access error messages: cs, en, sk, pl or de.

Sample response

Binární soubor (Content-Type: application/gzip, Content-Disposition: attachment; filename="backup-….tar.gz")

Possible errors

  • 400 The uuid is missing or invalid.
  • 403 Missing the Backups or Files permission.
  • 404 The backup does not exist.
  • 502 The backup could not be downloaded from the game panel.
  • 429 At most 10 downloads per minute.
GET/services/{id}/schedulesSchedules of a game server or bot

Returns the scheduled tasks (restart, backup, command, start or stop) of a game server or Discord bot, their next and last run, limits and available backup slots.

Permission: services:settings

Query parameters

NameTypeRequiredDescription
localestringnoLanguage of texts in the response: en, otherwise cs.

Sample response

{
  "schedules": [
    {
      "id": 41,
      "name": "Denní restart",
      "cron": {
        "minute": "0",
        "hour": "5",
        "dom": "*",
        "month": "*",
        "dow": "*"
      },
      "target": {
        "minute": "0",
        "hour": "5",
        "dom": "*",
        "month": "*",
        "dow": "*"
      },
      "active": true,
      "onlyWhenOnline": false,
      "processing": false,
      "stuck": false,
      "lastRunAt": "2026-11-07T04:00:00.000Z",
      "nextRunAt": "2026-11-08T04:00:00.000Z",
      "kind": "restart",
      "preset": {
        "kind": "restart",
        "repeat": {
          "kind": "daily",
          "time": "05:00"
        },
        "countdown": {
          "m5": true,
          "m1": true,
          "s10": true
        }
      },
      "origin": "portal",
      "author": "you",
      "lastResult": "ok",
      "lastResultCause": null,
      "allowed": true
    }
  ],
  "panelZone": {
    "expected": "Europe/Prague",
    "detected": "Europe/Prague",
    "ok": true,
    "preview": "Europe/Prague"
  },
  "backupSlots": 1,
  "canBackup": true,
  "backupAddonPriceCzk": 120,
  "game": "minecraft",
  "countdown": true,
  "mcVersion": "1.21.4",
  "isOwner": true,
  "permissions": {
    "console": true,
    "power": true,
    "backups": true
  },
  "limits": {
    "maxSchedules": 10,
    "nameMax": 60,
    "commandMax": 256,
    "messageMax": 100,
    "hourSteps": [
      1,
      2,
      3,
      4,
      6,
      8,
      12
    ]
  }
}

Possible errors

  • 403 Missing the Settings permission.
  • 412 The server is not available in the game panel yet.
POST/services/{id}/schedulesCreate, edit, run or delete a schedule

Manages schedules, chosen by the action field. A server can have up to 10 schedules; a command at most every 15 minutes, restart and start or stop every hour, a backup once a day and only one backup schedule.

Permission: services:settings

Request body (JSON)

NameTypeRequiredDescription
actionstringyescreate, update, delete, toggle (enable or disable), run (run now, at most once a minute) or unstick (release a stuck schedule).
scheduleIdintegernoAll actions except create: schedule id from GET.
presetobjectnocreate, update: kind restart (repeat, countdown {m5, m1, s10}, message up to 100 characters), backup (repeat), command (repeat, command up to 256 characters, onlyWhenOnline) or power (repeat, signal start|stop).
preset.repeatobjectnoRepeat: {kind: daily, time: "HH:MM"}, {kind: weekly, days: [0–6, 0 = Sunday], time}, {kind: hours, every: 1|2|3|4|6|8|12, minute: 0–59} or {kind: cron, expr}.
namestringnocreate, update: schedule name, up to 60 characters.
ackbooleannocreate, update: must be true for a backup schedule (confirms the new backup replaces the older one).
activebooleannotoggle: true enables, false disables.
localestringnoLanguage of messages: cs, en, sk, pl or de. Default cs.

Sample body

{
  "action": "create",
  "name": "Noční restart",
  "preset": {
    "kind": "restart",
    "repeat": {
      "kind": "daily",
      "time": "04:30"
    },
    "countdown": {
      "m5": true,
      "m1": true,
      "s10": false
    },
    "message": "Server se za chvíli restartuje."
  }
}

Sample response

{
  "ok": true,
  "id": 42
}

Possible errors

  • 400INVALID The schedule is not filled in correctly.
  • 400GAP The schedule would run too often.
  • 400BACKUP_ACK ack: true is missing for a backup schedule.
  • 400COMMAND_FORBIDDEN The command would stop or restart the server; use the restart or power preset.
  • 403FORBIDDEN Missing permission for the schedule (Console, Power or Backups depending on tasks).
  • 404NOT_FOUND The schedule does not exist.
  • 409LIMIT The server already has 10 schedules.
  • 409BACKUP_SLOTS Scheduled backups need the backup add-on.
  • 409BACKUP_EXISTS A backup schedule already exists.
  • 409NOT_EDITABLE The schedule was created outside the portal; it can only be disabled or deleted.
  • 409PANEL_TZ Schedules at a specific time cannot be set right now, only hourly repeats.
  • 409SUSPENDED The server is suspended.
  • 409JOB_RUNNING A software change is running on the Minecraft server.
  • 429RATE A schedule can be run at most once a minute.
  • 502PARTIAL The schedule was not saved completely and stays disabled.
GET/services/{id}/vip-shopVIP shop of a Minecraft server

Returns the VIP shop of a Minecraft server: shop details, items with a price breakdown, current rates and a monthly sales summary. Owner only.

Permission: services:settings

Query parameters

NameTypeRequiredDescription
langstringnoLanguage of messages: cs, en, sk, pl or de. Default cs.

Sample response

{
  "view": {
    "state": {
      "mode": "live",
      "open": true,
      "checkoutOpen": true
    },
    "usable": true,
    "shop": {
      "id": "shp_3k9d",
      "slug": "muj-server",
      "title": "Můj server",
      "status": "active",
      "sellerName": "Jan Novák",
      "sellerIco": null,
      "sellerEmail": "[email protected]",
      "sellerAddress": null,
      "playerTerms": null,
      "termsVersion": "2026-10-29",
      "termsAcceptedAt": "2026-11-01T09:00:00.000Z",
      "termsCurrent": true,
      "suspendedReason": null,
      "createdAt": "2026-11-01T09:00:00.000Z"
    },
    "items": [
      {
        "id": "itm_8f2a",
        "title": "VIP na 30 dní",
        "description": "Barevné jméno a /fly",
        "priceCzk": 99,
        "category": "Ranky",
        "durationDays": 30,
        "commandsBuy": [
          "lp user {player} parent addtemp vip 30d"
        ],
        "commandsExpire": [],
        "active": true,
        "sortOrder": 0,
        "breakdown": null
      }
    ],
    "rates": null,
    "termsVersion": "2026-10-29",
    "summary": [
      {
        "month": "2026-11",
        "count": 3,
        "priceHaler": 29700,
        "commissionHaler": 1485,
        "feeHaler": 1020,
        "creditHaler": 27195
      }
    ]
  }
}

Possible errors

  • 400not_minecraft The VIP shop is only for Minecraft servers.
  • 404disabled The VIP shop is not available for the account right now.
  • 503disabled The VIP shop is not ready yet.
  • 500failed The action failed.
  • 403 Only for the service owner.
POST/services/{id}/vip-shopEdit the VIP shop and its items

Creates or edits the VIP shop, pauses it and manages items, chosen by the action field. Shop details are always sent in full; terms: true is required when creating and after the terms change. Owner only.

Permission: services:settings

Query parameters

NameTypeRequiredDescription
langstringnoLanguage of messages: cs, en, sk, pl or de. Default cs.

Request body (JSON)

NameTypeRequiredDescription
actionstringyessaveShop, setStatus, saveItem or deleteItem.
slugstringnosaveShop: shop address, 3–32 characters a–z, 0–9 and hyphen.
titlestringnosaveShop: shop name (2–60 characters). saveItem: item name (2–60 characters).
sellerNamestringnosaveShop: seller name or company (2–120 characters).
sellerIcostringnosaveShop: seller's Czech company ID (optional).
sellerEmailstringnosaveShop: seller contact e-mail.
sellerAddressstringnosaveShop: seller address, 5–200 characters (optional).
playerTermsstringnosaveShop: your own terms for players, up to 20,000 characters (optional).
termsbooleannosaveShop: acceptance of the shop operator terms.
statusstringnosetStatus: active or paused.
idstringnosaveItem: item id to edit (without id a new one is created, up to 50). deleteItem: item id (required).
descriptionstringnosaveItem: description, up to 500 characters.
priceCzkintegernosaveItem: price in CZK, 10–10,000 (required).
categorystringnosaveItem: category, up to 40 characters.
durationDaysinteger | nullnosaveItem: duration in days 1–3650, null = permanent.
commandsBuystring[]nosaveItem: 1–10 commands after purchase, each up to 300 characters; the only variable is {player}; commands such as stop, restart, op are not allowed.
commandsExpirestring[]nosaveItem: up to 10 commands when the item expires.
activebooleannosaveItem: offer the item in the shop. Default true.
sortOrderintegernosaveItem: sort order 0–10,000.

Sample body

{
  "action": "saveItem",
  "title": "VIP na 30 dní",
  "priceCzk": 99,
  "category": "Ranky",
  "durationDays": 30,
  "commandsBuy": [
    "lp user {player} parent addtemp vip 30d"
  ],
  "commandsExpire": [],
  "active": true
}

Sample response

{
  "ok": true,
  "item": {
    "id": "itm_8f2a",
    "title": "VIP na 30 dní",
    "description": null,
    "priceCzk": 99,
    "category": "Ranky",
    "durationDays": 30,
    "commandsBuy": [
      "lp user {player} parent addtemp vip 30d"
    ],
    "commandsExpire": [],
    "active": true,
    "sortOrder": 0,
    "breakdown": null
  }
}

Possible errors

  • 400bad Invalid request or unknown action.
  • 400 Invalid field; the code and field say which, e.g. slug, title, seller_email, terms, item_price, command_denied.
  • 404no_shop The service has no shop yet.
  • 404item_not_found The item does not exist.
  • 409slug_taken The shop address is taken.
  • 409suspended The shop is suspended by the operator.
  • 409items_max The shop already has 50 items.
  • 400not_minecraft The VIP shop is only for Minecraft servers.
  • 500failed The action failed.
  • 403 Only for the service owner.
GET/services/{id}/vip-shop/salesVIP shop sales and deliveries

Returns the last 50 VIP shop sales with command delivery state, commission, fee and credited amount. Amounts are in hellers (1/100 CZK). Works for inactive services too. Owner only.

Permission: services:settings

Query parameters

NameTypeRequiredDescription
langstringnoLanguage of messages: cs, en, sk, pl or de. Default cs.
beforestring (ISO 8601)noSales older than this time (paging).

Sample response

{
  "sales": [
    {
      "id": "sal_51c0",
      "number": "VIP-2026-000123",
      "createdAt": "2026-11-05T19:02:11.000Z",
      "paidAt": "2026-11-05T19:03:40.000Z",
      "state": "paid",
      "refundState": null,
      "test": false,
      "itemTitle": "VIP na 30 dní",
      "durationDays": 30,
      "playerName": "Steve_42",
      "buyerEmail": "[email protected]",
      "priceHaler": 9900,
      "commissionHaler": 495,
      "feeHaler": 340,
      "creditHaler": 9065,
      "reversedHaler": null,
      "deliveries": [
        {
          "id": "dlv_77aa",
          "kind": "purchase",
          "state": "done",
          "attempts": 1,
          "nextAttemptAt": null,
          "doneAt": "2026-11-05T19:03:52.000Z",
          "lastErrorCode": null,
          "sent": 1,
          "total": 1
        }
      ]
    }
  ]
}

Possible errors

  • 404no_shop The service has no shop yet.
  • 400not_minecraft The VIP shop is only for Minecraft servers.
  • 500failed The action failed.
  • 403 Only for the service owner.
POST/services/{id}/vip-shop/salesRetry delivering commands for a sale

Immediately retries sending the commands of one delivery to the server. At most 10 times a minute per service. Owner only.

Permission: services:settings

Query parameters

NameTypeRequiredDescription
langstringnoLanguage of messages: cs, en, sk, pl or de. Default cs.

Request body (JSON)

NameTypeRequiredDescription
actionstringyesretry.
deliveryIdstringyesDelivery id from GET (deliveries[].id).

Sample body

{
  "action": "retry",
  "deliveryId": "dlv_77aa"
}

Sample response

{
  "ok": true,
  "state": "done",
  "code": null
}

Possible errors

  • 400bad Invalid request.
  • 404no_shop The service has no shop yet.
  • 404delivery_not_found The delivery does not exist.
  • 409delivery_state The delivery cannot be retried right now.
  • 429rate At most 10 attempts per minute.
  • 400not_minecraft The VIP shop is only for Minecraft servers.
  • 500failed The action failed.
  • 403 Only for the service owner.

Minecraft

GET/services/{id}/minecraft/datapacksDatapacks of the active world

Without parameters it returns the datapacks of the active world. With `q` it searches Modrinth for the server version, with `project` it lists versions of one datapack.

Permission: services:files

Query parameters

NameTypeRequiredDescription
qstringnoSearch text (up to 80 characters).
offsetintegernoOffset in search results, default 0.
projectstringnoModrinth project ID or slug, returns its versions with a file.

Sample response

{
  "version": "1.21.4",
  "world": "world",
  "worldValid": true,
  "worldExists": true,
  "power": "running",
  "busy": null,
  "items": [
    {
      "name": "example-pack.zip",
      "kind": "zip",
      "size": 48211,
      "mtime": 1730970000,
      "source": "modrinth",
      "title": "Example Pack",
      "versionName": "1.2.0",
      "projectId": "AbCdEf12",
      "enabled": true,
      "compat": "ok"
    }
  ],
  "evidenceBroken": false,
  "canConsole": true,
  "maxUploadMb": 50
}

Possible errors

  • 409NOT_IMPORTED The server software is not set yet, use minecraft/software first.
  • 412NO_PANEL The server is not available in the game panel right now.
  • 429 Too many requests, try again shortly.
POST/services/{id}/minecraft/datapacksInstall, remove and reload datapacks

`install` downloads a datapack from Modrinth into the active world; on a running server it takes effect after `reload`. `remove` disables and deletes it, `reload` runs the `reload` command (running server only, on a shared service with the Console permission). Uploading your own ZIP is not available via the API.

Permission: services:files

Request body (JSON)

NameTypeRequiredDescription
actionstringyes`install`, `remove` or `reload`.
projectIdstringno`install` only: Modrinth project ID (1–64 characters).
versionIdstringno`install` only: version ID from `GET ?project=` (1–16 characters).
namestringno`remove` only: datapack file or folder name from the listing (up to 120 characters).

Sample body

{
  "action": "install",
  "projectId": "AbCdEf12",
  "versionId": "XyZ98765"
}

Sample response

{
  "ok": true,
  "file": "example-pack.zip",
  "replaced": null,
  "needsReload": true,
  "packFormat": "61",
  "compat": "ok"
}

Possible errors

  • 400INVALID Invalid request body.
  • 403FORBIDDEN `reload` without the Console permission on a shared service.
  • 404NO_SUCH_PACK No datapack with this name in the world.
  • 409NAME_TAKEN A datapack with the same name already exists, remove it first.
  • 409TOO_MANY The world already has 100 datapacks.
  • 409NOT_RUNNING The server is not running, start it and try again.
  • 409JOB Another change or add-on installation is running on the server.
  • 422INCOMPATIBLE This datapack version does not match the server version.
  • 422NO_PACK_MCMETA The file is not a valid datapack (pack.mcmeta missing).
  • 429RATE_LIMITED Limit: install and remove 20 per 10 minutes, `reload` 10 per 10 minutes.
GET/services/{id}/minecraft/dnsCustom server address

Returns the custom address state (A/AAAA and SRV records), the default server port and the direct address. With `check` it only tests whether a name is free. If the server IP or port changed, the records are fixed on read (`resynced`).

Permission: services:network

Query parameters

NameTypeRequiredDescription
checkstringnoName to check for availability, returns `{ name, fqdn, available, code?, error? }`.
localestringnoLanguage of access check error messages: cs, en, sk, pl, de.

Sample response

{
  "enabled": true,
  "zone": "play.example.com",
  "ttl": 300,
  "nameMin": 3,
  "nameMax": 32,
  "current": {
    "name": "mujserver",
    "fqdn": "mujserver.play.example.com",
    "zone": "play.example.com",
    "ip": "203.0.113.10",
    "port": 25565,
    "recordType": "A",
    "srvName": "_minecraft._tcp.mujserver.play.example.com",
    "createdAt": "2026-11-07T10:15:00.000Z",
    "updatedAt": null,
    "records": {
      "address": "ok",
      "srv": "ok"
    }
  },
  "allocation": {
    "ip": "203.0.113.10",
    "alias": null,
    "port": 25565
  },
  "directAddress": "203.0.113.10:25565",
  "allocationError": null,
  "allocationErrorCode": null,
  "recordsError": null,
  "recordsErrorCode": null,
  "resynced": false,
  "canManage": true
}

Possible errors

  • 400NOT_MINECRAFT The service is not a Minecraft server.
  • 503PANEL Server management is temporarily unavailable.
  • 500SETUP_FAILED Could not complete, try again later.
POST/services/{id}/minecraft/dnsCreate, rename or delete address

Creates the address `<name>.<zone>`, renames or deletes it, or rewrites the records for the current IP and port (`resync`). The service must be active; the address can change at most 5 times per hour and 20 times per day.

Permission: services:network

Query parameters

NameTypeRequiredDescription
localestringnoLanguage of access check error messages: cs, en, sk, pl, de.

Request body (JSON)

NameTypeRequiredDescription
actionstringyes`create`, `rename`, `delete` or `resync`.
namestringnoFor `create` and `rename`: 3–32 characters, lowercase a–z, digits and hyphens (not at the start or end).

Sample body

{
  "action": "create",
  "name": "mujserver"
}

Sample response

{
  "ok": true,
  "current": {
    "name": "mujserver",
    "fqdn": "mujserver.play.example.com",
    "zone": "play.example.com",
    "ip": "203.0.113.10",
    "port": 25565,
    "recordType": "A",
    "srvName": "_minecraft._tcp.mujserver.play.example.com",
    "createdAt": "2026-11-07T10:15:00.000Z",
    "updatedAt": null,
    "records": {
      "address": "ok",
      "srv": "ok"
    }
  }
}

Possible errors

  • 400INVALID Invalid request body.
  • 400INVALID_NAME The name does not meet the rules.
  • 400RESERVED The name is reserved.
  • 400SAME_NAME The server already has this address.
  • 404NONE The server has no custom address.
  • 409TAKEN The address is taken.
  • 409EXISTS The server already has a custom address, use `rename`.
  • 409NO_ALLOCATION The server has no default port.
  • 409NOT_PUBLIC The default server address is not public.
  • 412NO_PANEL_LINK The server is not available in the game panel right now.
  • 429RATE_LIMITED Change limit exceeded, try again later.
  • 503DISABLED Custom addresses are not available right now.
  • 502DNS Writing the DNS records failed.
GET/services/{id}/minecraft/eulaEULA acceptance state

Returns whether the Minecraft licence is accepted in eula.txt. `accepted: null` means the file does not exist yet.

Permission: services:settings

Sample response

{
  "accepted": false,
  "acceptedAt": null,
  "url": "https://aka.ms/MinecraftEULA"
}

Possible errors

  • 412 The server is not available in the game panel right now (message `panel.unavailable` in `msg`).
  • 429 Too many requests, try again shortly.
POST/services/{id}/minecraft/eulaAccept the EULA

Writes `eula=true` to eula.txt. With `start: true` it also starts the server if it is offline (on a shared service with the Power permission). Limit 10 per 10 minutes.

Permission: services:settings

Request body (JSON)

NameTypeRequiredDescription
acceptbooleanyesMust be `true`.
startbooleannoStart the server after accepting if it is offline.

Sample body

{
  "accept": true,
  "start": true
}

Sample response

{
  "ok": true,
  "accepted": true,
  "acceptedAt": "2026-11-07T10:15:00.000Z",
  "started": true,
  "startError": null,
  "startErrorMsg": null
}

Possible errors

  • 400 `accept: true` is missing.
  • 403 `start` without the Power permission.
  • 409 A change (job) is running on the server.
  • 412 The server is not available in the game panel right now (message `panel.unavailable` in `msg`).
GET/services/{id}/minecraft/gamerulesGame rules of the active world

Returns the game rules valid for the server version with current and default values. On a shared service the Console permission is required.

Permission: services:settings

Query parameters

NameTypeRequiredDescription
langstringnoLanguage of rule labels: `cs` (default) or `en`.

Sample response

{
  "version": "1.21.4",
  "world": "world",
  "worldValid": true,
  "power": "running",
  "busy": null,
  "perDimension": true,
  "source": "file",
  "fileAt": "2026-11-07T10:15:00.000Z",
  "pending": [],
  "rules": [
    {
      "id": "minecraft:keep_inventory",
      "name": "keepInventory",
      "type": "bool",
      "min": null,
      "max": null,
      "group": "players",
      "common": true,
      "label": "Keep inventory after death",
      "value": false,
      "default": false
    }
  ]
}

Possible errors

  • 409NOT_IMPORTED The server software is not set yet, use minecraft/software first.
  • 412NO_PANEL The server is not available in the game panel right now.
  • 413FILE_TOO_LARGE The rules file is too large.
  • 422FILE_CORRUPT The rules file is corrupted.
  • 429 Too many requests, try again shortly.
POST/services/{id}/minecraft/gamerulesChange game rules

Sets the rules with the `gamerule` command on the running server; they apply immediately without a restart. Up to 30 rules at once, limit 30 requests per 10 minutes.

Permission: services:settings

Request body (JSON)

NameTypeRequiredDescription
rulesobjectyesMap of rule `id` (from GET) to a `boolean` or integer value.
allDimensionsbooleannoOn Paper and its forks, set in all dimensions, default `true`.

Sample body

{
  "rules": {
    "minecraft:keep_inventory": true,
    "minecraft:spawn_radius": 0
  },
  "allDimensions": true
}

Sample response

{
  "ok": true,
  "world": "world",
  "results": [
    {
      "id": "minecraft:keep_inventory",
      "status": "set"
    },
    {
      "id": "minecraft:spawn_radius",
      "status": "unchanged"
    }
  ]
}

Possible errors

  • 400INVALID Invalid request body.
  • 400NO_CHANGES `rules` is empty.
  • 400UNKNOWN_RULE The rule does not exist in the server version (field `rule`).
  • 400INVALID_VALUE Invalid rule value (field `rule`).
  • 409NOT_RUNNING The server is not running, start it and try again.
  • 409NOT_IMPORTED The server software is not set yet, use minecraft/software first.
  • 409JOB Another change or add-on installation is running on the server.
  • 429CONSOLE_BUSY The server console is busy.
  • 412NO_PANEL The server is not available in the game panel right now.
GET/services/{id}/minecraft/jobState of the running server change

Returns the last job (software change, reinstall, modpack, world) with step, log and progress. After starting a job, poll roughly every 2 s until `status` is `done` or `failed`; a stuck job is marked `failed` with `interrupted: true`.

Permission: services:settings

Sample response

{
  "job": {
    "id": "k3j9x2m1q8",
    "kind": "switch",
    "status": "running",
    "step": "install",
    "log": [
      {
        "at": "2026-11-07T10:15:00.000Z",
        "key": "job.log.installing",
        "params": {
          "label": "Paper 1.21.4"
        }
      }
    ],
    "startedAt": "2026-11-07T10:15:00.000Z",
    "updatedAt": "2026-11-07T10:16:10.000Z",
    "error": null,
    "errorMsg": null,
    "progress": {
      "done": 42,
      "total": 168,
      "unit": "files",
      "bytesDone": null,
      "bytesTotal": null
    },
    "from": {
      "type": "paper",
      "version": "1.21.1",
      "build": "130"
    },
    "target": {
      "type": "paper",
      "version": "1.21.4",
      "build": "232"
    },
    "destructive": true,
    "finishedAt": null
  },
  "active": true
}

Possible errors

  • 429 Too many requests, try again shortly.
POST/services/{id}/minecraft/jobDismiss a finished job

Hides a finished or failed job so GET no longer returns it. A running job cannot be dismissed.

Permission: services:settings

Request body (JSON)

NameTypeRequiredDescription
actionstringyesAlways `dismiss`.
jobIdstringyesJob `id` from GET (8–40 lowercase letters and digits).

Sample body

{
  "action": "dismiss",
  "jobId": "k3j9x2m1q8"
}

Sample response

{
  "ok": true
}

Possible errors

  • 400 Invalid request body (message key in `msg`).
  • 409 The job is still running or is no longer the latest one.
GET/services/{id}/minecraft/modpacksModpacks: state, search and preview

Without parameters it returns the installed modpack, set-aside files and the queue. `search` searches Modrinth, `project` returns a project with versions, `preview` shows what an install would do (changes nothing), `serverFiles=1` lists .mrpack files in the server root.

Permission: services:files

Query parameters

NameTypeRequiredDescription
searchstringnoSearch text on Modrinth.
mcstringnoWith `search`: Minecraft version, e.g. `1.21.1`.
loaderstringnoWith `search`: `fabric`, `forge` or `neoforge`.
sortstringnoWith `search`: `downloads`, `relevance` or `newest`.
offsetintegernoWith `search`: offset in results.
projectstringnoProject ID or slug; with `preview=modrinth` the ID only (8 characters).
previewstringno`modrinth` (with `project` and `version`) or `upload` (with `upload`).
versionstringnoWith `preview=modrinth`: version ID (8 characters).
uploadstringnoWith `preview=upload`: `id` from the `stageServerFile` action (24 hex characters).
modestringnoWith `preview`: `all` (default), `keep-world` or `wipe`.
serverFilesstringno`1` lists .mrpack files in the server root.

Sample response

{
  "installed": null,
  "aside": null,
  "recovering": false,
  "server": {
    "type": "fabric",
    "version": "1.21.1",
    "memoryMib": 8192
  },
  "perms": {
    "install": true,
    "rollback": true,
    "deleteAside": true,
    "wipe": true,
    "replaceBackup": true
  },
  "queue": {
    "active": 0,
    "waiting": 0,
    "limit": 2
  },
  "limits": {
    "uploadMaxMb": 95,
    "serverFileMaxMb": 1024,
    "serverMb": 3072,
    "files": 30000
  }
}

Possible errors

  • 400 Invalid project, version, upload or mode (message key in `msg`).
  • 429 Too many requests, try again shortly.
POST/services/{id}/minecraft/modpacksInstall or roll back a modpack

`install` and `rollback` start a background job (response 202), follow it via minecraft/job. The server is stopped during install; `all` sets old files aside (undo with `rollback`), `wipe` deletes everything (owner only). Limit 3 per hour per service (shared with software changes) and 10 per day per customer; upload your own .mrpack via SFTP and stage it with `stageServerFile`.

Permission: services:files

Request body (JSON)

NameTypeRequiredDescription
actionstringyes`install`, `rollback`, `deleteAside` or `stageServerFile`.
originstringno`install`: `modrinth` or `mrpack` (own file).
projectIdstringno`install` from Modrinth: project ID (8 characters).
versionIdstringno`install` from Modrinth: version ID (8 characters).
uploadIdstringno`install` with `mrpack`: `id` from `stageServerFile` (24 hex characters).
modestringno`install`: `all` (replace everything, set old aside), `keep-world` (keep world and server.properties) or `wipe` (delete everything, owner only).
replaceBackupbooleannoIf backup slots are full, overwrite the oldest backup (owner or Backups permission).
acceptEulabooleannoAccept the Minecraft licence (EULA) as part of the install.
confirmDowngradebooleannoConfirm installing an older Minecraft version than the world has.
namestringno`stageServerFile`: name of the .mrpack file in the server root (up to 1 GB).

Sample body

{
  "action": "install",
  "origin": "modrinth",
  "projectId": "AbCdEf12",
  "versionId": "XyZ98765",
  "mode": "all",
  "acceptEula": true
}

Sample response

{
  "ok": true,
  "job": {
    "id": "k3j9x2m1q8",
    "kind": "modpack",
    "status": "queued",
    "step": "queued",
    "log": [],
    "startedAt": "2026-11-07T10:15:00.000Z",
    "updatedAt": "2026-11-07T10:15:00.000Z",
    "error": null,
    "errorMsg": null,
    "progress": null
  },
  "warnings": []
}

Possible errors

  • 400 Invalid request body (message key in `msg`).
  • 403 Settings, Files and Power permissions are missing (message key in `msg`).
  • 403WIPE_OWNER Only the owner may use `wipe`.
  • 403BACKUP_PERMISSION `replaceBackup` without the Backups permission.
  • 409JOB_RUNNING Another job is already running on the server.
  • 409ADDON_RUNNING A plugin or mod installation is in progress.
  • 409QUEUE_FULL The install queue is full, try again later.
  • 409DISK Not enough disk space on the server (`details.freeMb`, `details.needMb`).
  • 409DOWNGRADE The modpack uses an older Minecraft version, confirm with `confirmDowngrade`.
  • 422LOADER The modpack loader cannot be installed right now.
  • 429 Install limit exceeded (hourly per service or daily per customer).
GET/services/{id}/minecraft/player-statsPlayer count chart

Returns chart points of online players for the chosen range with average, peak and record. If collection is off, `enabled` is `false` and `points` is empty.

Permission: services:settings

Query parameters

NameTypeRequiredDescription
rangestringno`24h` (default, 5 min points), `7d` (hourly) or `30d` (every 4 h).

Sample response

{
  "enabled": true,
  "collecting": true,
  "range": "24h",
  "canToggle": true,
  "bucketSec": 300,
  "points": [
    {
      "t": 1730973600000,
      "peak": 4,
      "avg": 2.5,
      "slots": 20,
      "state": "up"
    }
  ],
  "average": 2.1,
  "peak": {
    "online": 6,
    "at": "2026-11-07T10:15:00.000Z"
  },
  "record": {
    "online": 14,
    "at": "2026-10-20T19:40:00.000Z"
  },
  "last": {
    "at": "2026-11-07T10:15:00.000Z",
    "online": 3,
    "max": 20
  }
}

Possible errors

  • 503unavailable The player chart is not available yet.
  • 502ERROR The chart could not be loaded.
  • 429 Too many requests, try again shortly.
POST/services/{id}/minecraft/player-statsTurn the player chart on or off

Turns player count collection on or off. Turning it off deletes all collected data of the service (`deleted`). Limit 10 per 10 minutes.

Permission: services:settings

Request body (JSON)

NameTypeRequiredDescription
enabledbooleanyes`true` to enable, `false` to disable and delete data.

Sample body

{
  "enabled": false
}

Sample response

{
  "ok": true,
  "enabled": false,
  "deleted": 2016
}

Possible errors

  • 400INVALID Invalid request body.
  • 503unavailable The player chart is not available yet.
  • 429 Too many requests, try again shortly.
GET/services/{id}/minecraft/playersPlayers, whitelist, operators and bans

Returns whitelist, operators, bans and IP bans from the server files, settings from server.properties and online players (Console permission only). With `lookup` it checks a nickname with Mojang.

Permission: services:settings

Query parameters

NameTypeRequiredDescription
lookupstringnoPlayer nickname to check, returns `{ lookup: { query, found, name, uuid } }` (Console permission).

Sample response

{
  "power": "running",
  "busy": null,
  "canConsole": true,
  "version": "1.21.4",
  "settings": {
    "whitelist": true,
    "enforceWhitelist": false,
    "onlineMode": true,
    "opLevel": 4,
    "propsMissing": false
  },
  "propsInvalid": false,
  "floodgatePrefix": null,
  "online": {
    "online": 1,
    "max": 20,
    "players": [
      {
        "name": "Steve",
        "uuid": "0f3c1e2a-4b5d-4c6e-8f70-1a2b3c4d5e6f"
      }
    ],
    "truncated": false,
    "source": "console",
    "at": "2026-11-07T10:15:00.000Z"
  },
  "onlineError": null,
  "onlineErrorMsg": null,
  "lists": {
    "whitelist": {
      "status": "ok",
      "entries": [
        {
          "uuid": "0f3c1e2a-4b5d-4c6e-8f70-1a2b3c4d5e6f",
          "name": "Steve"
        }
      ]
    },
    "ops": {
      "status": "ok",
      "entries": [
        {
          "uuid": "0f3c1e2a-4b5d-4c6e-8f70-1a2b3c4d5e6f",
          "name": "Steve",
          "level": 4,
          "bypassesPlayerLimit": false
        }
      ]
    },
    "bans": {
      "status": "absent",
      "entries": []
    },
    "ipBans": {
      "status": "absent",
      "entries": []
    }
  },
  "known": [],
  "owner": true
}

Possible errors

  • 400INVALID_NICK Invalid nickname in `lookup`.
  • 403FORBIDDEN `lookup` without the Console permission.
  • 503MOJANG_BUSY Mojang lookup is unavailable now, try again in a minute.
  • 412 The server is not available in the game panel right now (message `panel.unavailable` in `msg`).
  • 429 Too many requests, try again shortly.
POST/services/{id}/minecraft/playersWhitelist, operators, bans and kick

On a running server the change is made by command, on a stopped one by editing the file (`mode`). On a shared service the Console permission is required; limit 30 changes per 10 minutes per service and 60 per customer.

Permission: services:settings

Request body (JSON)

NameTypeRequiredDescription
actionstringyes`whitelist-add`, `whitelist-remove`, `whitelist-toggle`, `op`, `deop`, `ban`, `pardon`, `pardon-ip`, `kick`, `bedrock-whitelist-add` or `bedrock-whitelist-remove`.
nickstringnoPlayer nickname (up to 40 characters); for `bedrock-*` the Bedrock player name.
uuidstringnoUUID from the list, for removal on a stopped server even without a valid nickname.
levelintegerno`op`: operator level 1–4.
bypassesPlayerLimitbooleanno`op`: the operator can join a full server.
reasonstringno`ban` and `kick`: reason (up to 200 characters).
ipstringno`pardon-ip`: the banned IP address.
enabledbooleanno`whitelist-toggle` (required): turn the whitelist on or off.

Sample body

{
  "action": "op",
  "nick": "Steve",
  "level": 4
}

Sample response

{
  "ok": true,
  "mode": "command",
  "result": "done",
  "player": {
    "name": "Steve",
    "uuid": "0f3c1e2a-4b5d-4c6e-8f70-1a2b3c4d5e6f"
  }
}

Possible errors

  • 400INVALID Invalid request body.
  • 400INVALID_NICK Invalid nickname or UUID.
  • 400INVALID_REASON Invalid reason.
  • 400INVALID_IP Invalid IP address.
  • 409NOT_RUNNING The action needs a running server (e.g. `kick`).
  • 409PLAYER_OFFLINE The player is not online.
  • 409NO_FLOODGATE `bedrock-*` actions need Floodgate.
  • 409CONFLICT The file changed in the meantime, try again.
  • 409JOB Another change is running on the server.
  • 422PLAYER_UNKNOWN No player with this nickname exists.
  • 429RATE_LIMITED Change limit exceeded, try again later.
  • 503MOJANG_BUSY Mojang lookup is unavailable now.
GET/services/{id}/minecraft/pluginsServer plugins and mods

Without parameters it lists installed plugins or mods and `restartRequired`. The switches `search`, `versions`, `plan` and `updates` need no value (e.g. `?search&source=modrinth&q=maps`); `op` returns the state of a background install.

Permission: services:files

Query parameters

NameTypeRequiredDescription
searchflagnoCatalogue search (with `source`, `q`, `offset`).
versionsflagnoCompatible versions of a project (with `source`, `project`).
planflagnoInstall preview with dependencies, nothing is written (with `source`, `project`, `version`, `deps`).
updatesflagnoNewer versions of files installed via the portal.
sourcestringno`modrinth` or `hangar` (Hangar for plugins only).
qstringnoSearch text.
offsetintegernoOffset in search results.
projectstringnoProject ID or slug (1–64 characters).
versionstringnoWith `plan`: version ID, otherwise the newest compatible one.
depsstringnoWith `plan`: `0` without dependencies.
opstringnoOperation ID (UUID) from a POST 202 response.

Sample response

{
  "context": {
    "type": "paper",
    "kind": "plugins",
    "gameVersion": "1.21.4",
    "versionKnown": true,
    "versionSource": "metadata",
    "dir": "/plugins"
  },
  "sources": [
    "modrinth",
    "hangar"
  ],
  "maxBytes": 104857600,
  "items": [
    {
      "file": "ExamplePlugin-1.2.0.jar",
      "filename": "ExamplePlugin-1.2.0.jar",
      "enabled": true,
      "size": 512000,
      "modifiedAt": 1730970000,
      "managed": true,
      "source": "modrinth",
      "projectId": "AbCdEf12",
      "title": "Example Plugin",
      "icon": null,
      "url": "https://modrinth.com/plugin/example-plugin",
      "versionId": "XyZ98765",
      "versionName": "1.2.0",
      "publishedAt": "2026-11-07T10:15:00.000Z",
      "installedAt": "2026-11-07T10:15:00.000Z",
      "installedByYou": true,
      "dependencyOf": null,
      "unverified": true,
      "fromModpack": null,
      "dataFolder": "ExamplePlugin"
    }
  ],
  "dataFolders": [
    "ExamplePlugin"
  ],
  "folderExists": true,
  "changedAt": "2026-11-07T10:15:00.000Z",
  "restartRequired": true,
  "serverState": "running",
  "jobRunning": false,
  "op": null
}

Possible errors

  • 400BAD_REQUEST Unknown source, project or version.
  • 400UNSUPPORTED_TYPE The server type supports neither plugins nor mods (Vanilla).
  • 404OP_NOT_FOUND The operation does not exist or has expired.
  • 429RATE_LIMITED Catalogue query limit: 60 per minute.
  • 502SOURCE_ERROR The catalogue is not responding.
POST/services/{id}/minecraft/pluginsInstall and manage plugins and mods

`install` and `update` run in the background: the final response arrives within 40 s, otherwise 202 with `pending: true` and `op`; then read the state via `GET ?op=`. Changes take effect after a server restart; limit 20 changes per 10 minutes per service.

Permission: services:files

Request body (JSON)

NameTypeRequiredDescription
actionstringyes`install`, `update`, `remove` or `toggle`.
sourcestringno`install`: `modrinth` or `hangar`.
projectstringno`install`: project ID or slug.
versionstringno`install` and `update`: version ID, otherwise the newest compatible one.
dependenciesbooleanno`install`: also install required dependencies, default `true`.
skipstring[]no`install`: dependency IDs to skip (up to 50).
replacebooleanno`install`: replace conflicting files, default `false`.
filestringno`update`, `remove`, `toggle`: file name from the listing (up to 255 characters).
dataFolderstringno`remove`: also delete the plugin data folder (name from `dataFolders`).
enabledbooleanno`toggle` (required): enable or disable the file.

Sample body

{
  "action": "install",
  "source": "modrinth",
  "project": "example-plugin",
  "dependencies": true
}

Sample response

{
  "ok": true,
  "op": {
    "id": "3f1c2a7e-9b4d-4e21-8c3a-5d6e7f809a1b",
    "action": "install",
    "status": "done",
    "step": "Hotovo",
    "stepMsg": {
      "key": "plugin.step.done"
    },
    "startedAt": "2026-11-07T10:15:00.000Z",
    "finishedAt": "2026-11-07T10:15:12.000Z",
    "result": {
      "installed": [
        {
          "file": "ExamplePlugin-1.2.0.jar",
          "title": "Example Plugin",
          "versionName": "1.2.0",
          "role": "target"
        }
      ],
      "removed": [],
      "skipped": [],
      "missing": []
    },
    "error": null,
    "errorMsg": null,
    "code": null,
    "data": null
  },
  "result": {
    "installed": [
      {
        "file": "ExamplePlugin-1.2.0.jar",
        "title": "Example Plugin",
        "versionName": "1.2.0",
        "role": "target"
      }
    ],
    "removed": [],
    "skipped": [],
    "missing": []
  }
}

Possible errors

  • 400BAD_REQUEST Invalid request body or project/version reference.
  • 404NOT_FOUND File or project not found.
  • 404NO_VERSION No compatible version.
  • 409JOB_RUNNING Another change is running on the server.
  • 409INSTALLING The server is being installed.
  • 409EXISTS The file already exists, use `replace`.
  • 409UP_TO_DATE The file is already up to date.
  • 413TOO_LARGE The file is larger than 100 MB.
  • 422INCOMPATIBLE The version does not fit this server.
  • 422EXTERNAL The project can only be downloaded from the author's page.
  • 429RATE_LIMITED Limit of 20 changes per 10 minutes.
  • 502SOURCE_ERROR The catalogue is not responding.
GET/services/{id}/minecraft/propertiesContents of server.properties

Returns server.properties as text and as a key list with an `etag` for saving. Secret values (RCON and Management Protocol passwords) are masked; `reveal` shows one, only with the Secrets permission.

Permission: services:settings

Query parameters

NameTypeRequiredDescription
revealstringno`rcon.password`, `management-server-secret` or `management-server-tls-keystore-password`; returns `{ key, value }`.

Sample response

{
  "locked": [
    "server-ip",
    "server-port",
    "query.port"
  ],
  "secretKeys": [
    "rcon.password",
    "management-server-secret",
    "management-server-tls-keystore-password"
  ],
  "privilegedKeys": [
    "enable-rcon",
    "rcon.port",
    "management-server-enabled",
    "management-server-host",
    "management-server-port",
    "management-server-tls-enabled",
    "management-server-tls-keystore",
    "management-server-allowed-origins"
  ],
  "allocationPorts": [
    25565,
    25566
  ],
  "canSecrets": true,
  "canPower": true,
  "jobActive": false,
  "exists": true,
  "etag": "9b1f0c2d4e6a8b0c1d2e3f4a5b6c7d8e9f0a1b2c",
  "raw": "motd=A Minecraft Server\nmax-players=20\nrcon.password=********\n",
  "entries": [
    {
      "key": "motd",
      "value": "A Minecraft Server"
    },
    {
      "key": "max-players",
      "value": "20"
    },
    {
      "key": "rcon.password",
      "value": "********"
    }
  ]
}

Possible errors

  • 400 Unknown key in `reveal`.
  • 403 `reveal` without the Secrets permission.
  • 422 The file is too large or not text.
  • 412 The server is not available in the game panel right now (message `panel.unavailable` in `msg`).
  • 429 Too many requests, try again shortly.
POST/services/{id}/minecraft/propertiesSave server.properties

Saves single keys (`fields`) or the whole file (`raw`), always with the `etag` from GET. Locked keys (IP and ports) stay unchanged; secrets and remote management need the Secrets permission. Changes apply after a restart; `restart: true` restarts right away (Power permission).

Permission: services:settings

Request body (JSON)

NameTypeRequiredDescription
etagstringyes`etag` from GET; `absent` if the file does not exist.
fieldsobjectnoKey to value (string, number or boolean). Not together with `raw`.
rawstringnoWhole file content (up to 80,000 characters, result up to 64 KB). Locked and secret keys are reset to their stored value.
createbooleannoCreate the file from defaults if it does not exist yet.
restartbooleannoRestart the running server after saving.

Sample body

{
  "etag": "9b1f0c2d4e6a8b0c1d2e3f4a5b6c7d8e9f0a1b2c",
  "fields": {
    "motd": "Vítejte",
    "max-players": 30
  },
  "restart": true
}

Sample response

{
  "ok": true,
  "unchanged": false,
  "etag": "0c1d2e3f4a5b6c7d8e9f0a1b2c9b1f0c2d4e6a8b",
  "changed": [
    "motd",
    "max-players"
  ],
  "restored": [],
  "restarted": true,
  "restartError": null,
  "restartErrorMsg": null
}

Possible errors

  • 400 Invalid request body (message key in `msg`).
  • 400UNKNOWN_KEY The key cannot be changed via `fields` (field `key`).
  • 400LOCKED The key is locked (field `key`).
  • 400INVALID Invalid key value (field `key`).
  • 400RAW_INVALID The file text is too long or contains forbidden characters.
  • 403SECRETS Changing a secret or remote management without the Secrets permission.
  • 403 `restart` without the Power permission.
  • 409CONFLICT The file changed meanwhile, fetch a new `etag`.
  • 409NO_FILE The file does not exist, send `create: true`.
  • 409 A change (job) is running on the server.
  • 412 The server is not available in the game panel right now (message `panel.unavailable` in `msg`).
GET/services/{id}/minecraft/softwareServer software and available versions

Without parameters it returns the server type and version, change history, running job, backup slots, EULA and permissions. `versions` and `builds` list versions and builds of a type, `preview` shows the impact of a change (Java, image, disk, warnings) without writing.

Permission: services:settings

Query parameters

NameTypeRequiredDescription
versionsstringnoServer type: `paper`, `purpur`, `folia`, `vanilla`, `fabric`, `forge` or `neoforge`; returns up to 250 versions.
prereleasestringnoWith `versions`: `1` includes pre-releases.
buildsstringnoServer type; with `version` returns up to 100 builds.
previewstringnoServer type for the change preview (with `version`, `build`).
versionstringnoMinecraft version (for `preview` default `latest`).
buildstringnoWith `preview`: a specific build or loader version.
unstablestringno`1` allows unstable builds (`builds`, `preview`).

Sample response

{
  "state": {
    "type": "paper",
    "version": "1.21.4",
    "build": "232",
    "loaderVersion": null,
    "javaMajor": 21,
    "launch": {
      "kind": "jar",
      "file": "server.jar"
    },
    "history": [],
    "importedAt": null,
    "installedAt": "2026-11-07T10:15:00.000Z"
  },
  "job": null,
  "jobActive": false,
  "server": {
    "memoryMib": 8192,
    "diskMib": 40960,
    "javaMajor": 21,
    "imageOfficial": true,
    "busy": null
  },
  "panelError": null,
  "clientError": null,
  "backups": {
    "used": 1,
    "limit": 3
  },
  "diskFreeMb": 35200,
  "diskFreeUnknown": false,
  "eula": {
    "accepted": true,
    "acceptedAt": "2026-11-07T10:15:00.000Z"
  },
  "importSuggestion": null,
  "perms": {
    "change": true,
    "import": true,
    "eula": true,
    "power": true,
    "skipBackup": true
  },
  "types": [
    "paper",
    "purpur",
    "folia",
    "vanilla",
    "fabric",
    "forge",
    "neoforge"
  ]
}

Possible errors

  • 400 Unknown type, version or build (message key in `msg`).
  • 422 The version or build cannot be found.
  • 502 The version source is not responding.
  • 412 The server is not available in the game panel right now (message `panel.unavailable` in `msg`).
  • 429 Too many requests, try again shortly.
POST/services/{id}/minecraft/softwareChange server type and version

`switch` and `reinstall` start a job (202), follow it via minecraft/job: the server is stopped, backed up, the new software is installed and a server that was running is started again. A free backup slot is needed (or `skipBackup`, owner only); at most 3 per hour. `import` only records which software is already on the server and changes nothing.

Permission: services:settings

Request body (JSON)

NameTypeRequiredDescription
actionstringyes`switch`, `reinstall` or `import`.
typestringno`switch` and `import`: `paper`, `purpur`, `folia`, `vanilla`, `fabric`, `forge` or `neoforge`.
versionstringno`switch` and `import`: Minecraft version (1–40 characters); `switch` also accepts `latest`.
buildstringnoBuild or loader version, otherwise the newest stable one.
allowUnstablebooleanno`switch`: allow an unstable build.
modestringno`switch`: `keep` (default, delete nothing), `clean` (delete everything except world, settings and player lists) or `wipe` (delete everything).
acceptEulabooleanno`switch` and `reinstall`: accept the EULA.
confirmDowngradebooleanno`switch`: confirm switching to an older or unknown version.
skipBackupbooleanno`switch` and `reinstall`: without a backup, owner only.

Sample body

{
  "action": "switch",
  "type": "paper",
  "version": "1.21.4",
  "mode": "keep",
  "acceptEula": true
}

Sample response

{
  "ok": true,
  "job": {
    "id": "k3j9x2m1q8",
    "kind": "switch",
    "status": "queued",
    "step": "queued",
    "log": [],
    "startedAt": "2026-11-07T10:15:00.000Z",
    "updatedAt": "2026-11-07T10:15:00.000Z",
    "error": null,
    "errorMsg": null,
    "progress": null
  },
  "warnings": []
}

Possible errors

  • 400 Invalid request body (message key in `msg`).
  • 403 A change needs the Settings, Files and Power permissions.
  • 403SKIP_BACKUP_OWNER Only the owner may use `skipBackup`.
  • 409JOB_RUNNING Another job is already running on the server.
  • 409ADDON_RUNNING A plugin or mod installation is in progress.
  • 409BACKUP_SLOT Backup slots are full.
  • 409BACKUP_DISABLED The service has no backups; the change only works with `skipBackup`.
  • 409DISK Not enough disk space (`details.freeMb`, `details.needMb`).
  • 409DOWNGRADE Older version, confirm with `confirmDowngrade`.
  • 409UNKNOWN_VERSION The current version is unknown, confirm with `confirmDowngrade`.
  • 409NOT_IMPORTED `reinstall` without known software, use `import` or `switch` first.
  • 409INSTALLING The server is installing or restoring a backup.
  • 422NEED_BUILD `import`: for Forge and NeoForge provide `build`.
  • 429 At most 3 changes per hour.
GET/services/{id}/minecraft/startupStartup command and memory

Returns the current startup command, heap size, available JVM presets with heap preview, stored state and the out-of-memory risk. With `java=1` it also lists the Java versions the server offers.

Permission: services:settings

Query parameters

NameTypeRequiredDescription
javastringno`1` adds `javaOptions` (Java versions the egg offers).

Sample response

{
  "type": "paper",
  "imported": true,
  "javaMajor": 21,
  "arch": "x86_64",
  "envPrefix": true,
  "memoryMib": 8192,
  "launch": {
    "kind": "jar",
    "file": "server.jar"
  },
  "command": "java -Xms6656M -Xmx6656M -XX:+UseG1GC -jar server.jar nogui",
  "heapMb": 6656,
  "addons": 12,
  "modpack": false,
  "presets": [
    {
      "preset": "standard",
      "heapMb": 6656,
      "isDefault": true,
      "vectors": true
    },
    {
      "preset": "zgc",
      "heapMb": 5888,
      "isDefault": false,
      "vectors": true
    },
    {
      "preset": "none",
      "heapMb": 6656,
      "isDefault": false,
      "vectors": true
    }
  ],
  "defaultPreset": "standard",
  "vectors": true,
  "memory": null,
  "stored": {
    "preset": "standard",
    "heapMb": 6656,
    "memoryMib": 8192,
    "vectors": true,
    "extraFlags": [],
    "appliedAt": "2026-11-07T10:15:00.000Z",
    "custom": false,
    "hasPrevious": true,
    "check": null
  },
  "lastSync": null,
  "managed": true,
  "matchesStored": true,
  "drifted": false,
  "needsSync": false,
  "busy": null,
  "jobActive": false,
  "canPower": true,
  "canExtraFlags": true,
  "canJava": true
}

Possible errors

  • 502 The game panel is not responding.
  • 429 Too many requests, try again shortly.
POST/services/{id}/minecraft/startupChange startup command or Java

Without `action` (or with `apply`) it applies a JVM preset, `recalculate` recomputes the heap for the current memory, `revert` restores the previous command, `java` switches the image to another Java without reinstalling. The change applies from the next start; `restart: true` restarts now (Power permission).

Permission: services:settings

Request body (JSON)

NameTypeRequiredDescription
actionstringno`apply` (default), `recalculate`, `revert` or `java`.
presetstringno`apply` (required): `standard`, `zgc` (Java 21+), `proxy` or `none`.
extraFlagsstring | string[]no`apply`: custom JVM flags (text up to 4000 characters or up to 60 items); new flags only with the Power permission.
dryRunbooleanno`apply`: only build the command and save nothing.
majorintegerno`java` (required): Java major version 8–99.
restartbooleannoRestart after the change (start an offline server).

Sample body

{
  "preset": "standard",
  "extraFlags": [],
  "restart": true
}

Sample response

{
  "ok": true,
  "command": "java -Xms6656M -Xmx6656M -XX:+UseG1GC -jar server.jar nogui",
  "heapMb": 6656,
  "preset": "standard",
  "restarted": true,
  "restartError": null,
  "restartErrorMsg": null
}

Possible errors

  • 400 Invalid request body (message key in `msg`).
  • 403EXTRA_FLAGS_PERMISSION New custom flags without the Power permission (field `token`).
  • 403 `restart` or `java` without the required permissions.
  • 409NEED_IMPORT The server software is not set.
  • 409NO_MEMORY_LIMIT The server has no memory limit.
  • 409CHANGED The startup changed meanwhile.
  • 409 A software change or install is running.
  • 422PRESET The preset does not fit this Java.
  • 422EXTRA_FLAGS Forbidden flag (field `token`).
  • 422TOO_OLD `java`: the version is too old for the Minecraft version.
  • 422NO_IMAGE `java`: no image for this Java.
  • 429 Limit: preset changes 10 per hour, Java switches 3 per hour.
GET/services/{id}/minecraft/textColoured nick and prefix: options

Returns whether the server is running, the text syntax era for its version and which plugins (EssentialsX, LuckPerms, TAB) are installed. On a shared service the Console permission is required.

Permission: services:settings

Sample response

{
  "running": true,
  "state": "running",
  "version": "1.21.4",
  "era": "components",
  "eraKnown": true,
  "plugins": {
    "essentials": true,
    "luckperms": true,
    "tab": false
  }
}

Possible errors

  • 412 The server is not available in the game panel right now (message `panel.unavailable` in `msg`).
  • 429 Too many requests, try again shortly.
POST/services/{id}/minecraft/textApply coloured text on the server

Builds a command on the server from `spans` or `doc` (EssentialsX nick, LuckPerms or TAB prefix, name tag, tellraw) and sends it to the running server console. Limit 20 per 10 minutes.

Permission: services:settings

Request body (JSON)

NameTypeRequiredDescription
actionstringyes`essentials-nick`, `lp-prefix`, `tab-prefix`, `give-nametag` or `tellraw`.
targetstringyesPlayer or group (1–36 characters); for `tellraw` also `@a`.
targetKindstringno`lp-prefix` and `tab-prefix`: `group` (default) or `player`.
priorityinteger | nullno`lp-prefix`: priority 0–1000.
prefixFormatstringno`lp-prefix`: `ampHex` (default), `amp`, `minimessage` or `bungeeHex`.
tabFieldstringno`tab-prefix`: `tabprefix` (default) or `tagprefix`.
tabFormatstringno`tab-prefix`: `tabGradient` (default), `ampHex` or `minimessage`.
erastringnoSyntax era (`legacy`, `json`, `jsonHex`, `components`, `snbt`), used only when the server version is unknown.
spansobject[]noSpans `{ text, color: "#rrggbb" | null, bold?, italic?, underlined?, strikethrough?, obfuscated? }`, up to 200. Send either `spans` or `doc`.
docobjectno`{ segments: [{ text, fill, … }] }` where `fill` is `{ kind: "solid", color }`, `{ kind: "gradient", colors: [2–5 colours] }` or `{ kind: "rainbow" }`.

Sample body

{
  "action": "lp-prefix",
  "target": "vip",
  "targetKind": "group",
  "priority": 50,
  "doc": {
    "segments": [
      {
        "text": "[VIP] ",
        "fill": {
          "kind": "solid",
          "color": "#ffaa00"
        },
        "bold": true
      }
    ]
  }
}

Sample response

{
  "ok": true,
  "command": "lp group vip meta setprefix 50 \"&#FFAA00&l[VIP] \"",
  "warnings": [],
  "delivered": null
}

Possible errors

  • 400INVALID Invalid request body.
  • 400TARGET Invalid player or group.
  • 400PRIORITY Priority must be an integer 0–1000.
  • 400EMPTY The text is empty.
  • 400TOO_LONG The text is too long (nick up to 64 characters, others 256).
  • 400TOO_MANY_PARTS The text has too many coloured parts.
  • 409JOB A change (job) is running on the server.
  • 409 The server is not running.
  • 429RATE_LIMITED Change limit exceeded, try again later.
  • 412 The server is not available in the game panel right now (message `panel.unavailable` in `msg`).
GET/services/{id}/minecraft/worldsServer worlds and prepared downloads

Returns the active and saved worlds (up to 5), prepared downloads, the running world job, backup slots and server state.

Permission: services:files

Sample response

{
  "active": "world",
  "activeValid": true,
  "worlds": [
    {
      "name": "world",
      "active": true,
      "exists": true,
      "extraFolders": [],
      "version": "1.21.4",
      "mtime": 1730970000,
      "seed": null,
      "createdAt": null
    },
    {
      "name": "creative",
      "active": false,
      "exists": true,
      "extraFolders": [],
      "version": "1.21.4",
      "mtime": 1730800000,
      "seed": "12345",
      "createdAt": "2026-11-01T18:00:00.000Z"
    }
  ],
  "unchecked": 0,
  "maxWorlds": 5,
  "exports": [
    {
      "id": "a1b2c3d4e5",
      "world": "world",
      "status": "ready",
      "createdAt": "2026-11-07T10:15:00.000Z",
      "expiresAt": "2026-11-07T12:15:00.000Z",
      "bytes": 104857600,
      "error": null,
      "errorMsg": null
    }
  ],
  "job": null,
  "jobOther": false,
  "backups": {
    "used": 1,
    "limit": 3,
    "free": true
  },
  "power": "running",
  "busy": null,
  "version": "1.21.4",
  "uploadMaxMb": 95,
  "canPower": true
}

Possible errors

  • 412NO_PANEL The server is not available in the game panel right now.
  • 429 Too many requests, try again shortly.
POST/services/{id}/minecraft/worldsExport, switch, delete or reset a world

`export` prepares a world archive in the background (202), download it via worlds/download, at most 3 per hour. `switch` and `reset` start a job (202, progress via minecraft/job); the server is stopped and started again; `delete` permanently deletes a saved world. Except `export`, the Power permission is also needed; at most 10 changes per hour.

Permission: services:files

Request body (JSON)

NameTypeRequiredDescription
actionstringyes`export`, `switch`, `delete` or `reset`.
worldstringno`export`, `switch`, `delete`: world name from the listing (1–64 characters).
oldstringno`reset` (required): `delete` the old world or `keep` it as a saved world.
keepAsstringno`reset` with `keep`: new name for the old world (1–32 characters A–Z, a–z, 0–9, _ and -).
seedstringno`reset`: seed of the new world (up to 128 characters), empty means random.
levelTypestringno`reset`: `normal` (default), `flat`, `large_biomes` or `amplified`.
structuresbooleanno`reset`: generate structures, default `true`.
confirmNoBackupbooleanno`reset` with `delete`: confirm deleting without a backup when no backup slot is free.

Sample body

{
  "action": "reset",
  "old": "keep",
  "keepAs": "stary_svet",
  "seed": "",
  "levelType": "normal",
  "structures": true
}

Sample response

{
  "ok": true,
  "job": {
    "id": "k3j9x2m1q8",
    "kind": "world-reset",
    "status": "queued",
    "step": "queued",
    "log": [],
    "startedAt": "2026-11-07T10:15:00.000Z",
    "updatedAt": "2026-11-07T10:15:00.000Z",
    "error": null,
    "errorMsg": null,
    "progress": null
  }
}

Possible errors

  • 400INVALID Invalid request body.
  • 400BAD_NAME Invalid world name.
  • 400RESERVED_NAME The name belongs to a server folder.
  • 400BAD_SEED Invalid seed.
  • 403FORBIDDEN The Power permission is missing.
  • 404NO_SUCH_WORLD The world is not on the server.
  • 409ACTIVE_WORLD The world is currently active.
  • 409NAME_TAKEN A folder with this name already exists.
  • 409TOO_MANY_WORLDS A server can have at most 5 worlds.
  • 409NEEDS_CONFIRM The old world would be deleted without a backup, send `confirmNoBackup: true`.
  • 409JOB_RUNNING Another change is already running on the server.
  • 409EXPORT_RUNNING A world download is already being prepared.
  • 409DISK Not enough disk space on the server.
  • 409STATE The server is starting or stopping.
  • 429RATE_LIMITED Change limit exceeded, try again later.
  • 412NO_PANEL The server is not available in the game panel right now.
GET/services/{id}/minecraft/worlds/downloadDownload a prepared world

Downloads an archive prepared by the `export` action (ZIP or tar.gz). After a complete download the archive is deleted from the server; one download per service at a time, at most 10 per hour.

Permission: services:files

Query parameters

NameTypeRequiredDescription
idstringyesDownload `id` from `exports` (10 hex characters).
formatstringno`zip` (default) or `tar.gz`.

Sample response

HTTP/1.1 200 OK
Content-Type: application/zip
Content-Disposition: attachment; filename="world-2026-11-07.zip"

(binary archive)

Possible errors

  • 400INVALID `id` is missing or invalid.
  • 404EXPORT_GONE The download is no longer prepared, prepare it again.
  • 429DOWNLOAD_BUSY A download is already in progress.
  • 429RATE_LIMITED Too many downloads.
  • 412NO_PANEL The server is not available in the game panel right now.

Domains

POST/services/{id}/domain/auth-infoSend AUTH-ID for domain transfer

Asks the registrar to e-mail the AUTH-ID (the code for transferring the domain to another registrar) to the domain holder. The code isn't returned in the response. Owner only, at most 3 times per hour. The services:secrets scope can only be given to a key restricted to IP addresses.

Permission: services:secrets

Request body (JSON)

NameTypeRequiredDescription
localestringnoLanguage of error messages: cs, en, sk, pl or de. Default is cs.

Sample body

{
  "locale": "cs"
}

Sample response

{
  "ok": true
}

Possible errors

  • 400invalid The request body contains an unknown field.
  • 403 Only the domain owner can do this, not a member of a shared service.
  • 404 The service doesn't exist, isn't yours, or the key has no access to it.
  • 409inactive The domain isn't active yet.
  • 429 Limit of 3 requests per hour exceeded.
  • 503unavailable Sending is temporarily unavailable. Try again later.
  • 422failed The registrar rejected the request.
GET/services/{id}/domain/connectPlan connecting a domain to a service

Works out the DNS records that point the domain or a subdomain to your VPS or game server (Minecraft, FiveM) and shows what will be added and replaced in the zone. Changes nothing. For a domain not on our DNS it returns mode manual with records to set up yourself.

Permission: domains:read

Query parameters

NameTypeRequiredDescription
servicestringyesID of your active VPS or game server (Minecraft, FiveM). Shared services aren't allowed.
hoststringyesName in the domain: @ for the domain itself, or a subdomain (letters, digits, hyphens, no * or _).
localestringnoLanguage of error messages: cs, en, sk, pl or de. Default is cs.

Sample response

{
  "mode": "zone",
  "domain": "example.com",
  "host": "@",
  "kind": "vps",
  "records": [
    {
      "type": "A",
      "host": "@",
      "fqdn": "example.com",
      "value": "203.0.113.25",
      "ttl": 300
    },
    {
      "type": "AAAA",
      "host": "@",
      "fqdn": "example.com",
      "value": "2001:db8::25",
      "ttl": 300
    }
  ],
  "notes": [],
  "add": [
    {
      "type": "AAAA",
      "host": "@",
      "fqdn": "example.com",
      "value": "2001:db8::25",
      "ttl": 300
    }
  ],
  "replace": [
    {
      "type": "A",
      "host": "@",
      "fqdn": "example.com",
      "value": "198.51.100.7",
      "ttl": 3600
    }
  ],
  "unchanged": false,
  "withinLimit": true,
  "planHash": "3f9a0c1b2d4e5f60718293ab"
}

Possible errors

  • 403 Only the domain owner can do this, not a member of a shared service.
  • 404 The service doesn't exist, isn't yours, or the key has no access to it.
  • 409inactive The domain isn't active yet.
  • 400host Invalid name: use @ for the domain itself, or a subdomain made of letters, digits and hyphens.
  • 404service The service doesn't exist, isn't yours, isn't active or can't be connected.
  • 409no_address The service has no public address to point the domain to.
  • 503unavailable The service address or DNS state can't be read right now.
  • 429 Limit of 60 requests per 10 minutes exceeded.
POST/services/{id}/domain/connectConnect a domain to a service

Creates the planned records in the zone (A, AAAA and for Minecraft also SRV _minecraft._tcp, TTL 300). Send the planHash from GET; if the plan replaces existing records, confirm: true is required. Only for a domain on our DNS.

Permission: domains:write

Request body (JSON)

NameTypeRequiredDescription
serviceIdstringyesID of your active VPS or game server, same as in GET.
hoststringyesName in the domain, same as in GET (@ or a subdomain).
planHashstringyesPlan fingerprint from GET (24 hex characters). If the zone has changed in the meantime, you get 409 changed with a new plan.
confirmbooleannoConfirms that the existing records in replace will be replaced. Required when replace isn't empty.
localestringnoLanguage of error messages: cs, en, sk, pl or de. Default is cs.

Sample body

{
  "serviceId": "clx9k2m4p0000svc01abcdef",
  "host": "@",
  "planHash": "3f9a0c1b2d4e5f60718293ab",
  "confirm": true
}

Sample response

{
  "ok": true,
  "mode": "zone",
  "domain": "example.com",
  "host": "@",
  "kind": "vps",
  "records": [
    {
      "type": "A",
      "host": "@",
      "fqdn": "example.com",
      "value": "203.0.113.25",
      "ttl": 300
    },
    {
      "type": "AAAA",
      "host": "@",
      "fqdn": "example.com",
      "value": "2001:db8::25",
      "ttl": 300
    }
  ],
  "notes": [],
  "add": [],
  "replace": [],
  "unchanged": true,
  "withinLimit": true,
  "planHash": "3f9a0c1b2d4e5f60718293ab"
}

Possible errors

  • 400invalid A required field is missing or malformed.
  • 403 Only the domain owner can do this, not a member of a shared service.
  • 404 The service doesn't exist, isn't yours, or the key has no access to it.
  • 409inactive The domain isn't active yet.
  • 400host Invalid name: use @ for the domain itself, or a subdomain made of letters, digits and hyphens.
  • 404service The service doesn't exist, isn't yours, isn't active or can't be connected.
  • 409no_address The service has no public address to point the domain to.
  • 503unavailable The service address or DNS state can't be read right now.
  • 409manual The domain doesn't use our DNS. Set the records up with your DNS provider.
  • 409changed The zone has changed since GET. The response contains the new plan in the plan field.
  • 409confirm The plan replaces existing records and confirm: true is missing. The response contains the plan in the plan field.
  • 409limit The zone would exceed the 200-record limit.
  • 429 Limit of 60 DNS changes per 10 minutes (shared with DNS record writes) exceeded.
GET/services/{id}/domain/dnsList DNS records

Returns the records of the domain's zone on our DNS (A, AAAA, CNAME, MX, TXT, SRV, CAA), the nameservers and the record count against the 200 limit. delegated: false means the zone is ready but the domain doesn't point to our DNS yet.

Permission: domains:read

Query parameters

NameTypeRequiredDescription
localestringnoLanguage of error messages: cs, en, sk, pl or de. Default is cs.

Sample response

{
  "zone": "example.com",
  "unicode": "example.com",
  "records": [
    {
      "id": "a1b2c3d4e5f60718293a",
      "type": "A",
      "host": "@",
      "ttl": 3600,
      "value": "203.0.113.25",
      "fields": {
        "host": "@",
        "ttl": "3600",
        "address": "203.0.113.25"
      }
    },
    {
      "id": "b2c3d4e5f60718293a4b",
      "type": "MX",
      "host": "@",
      "ttl": 3600,
      "value": "10 mail.example.com",
      "fields": {
        "host": "@",
        "ttl": "3600",
        "preference": "10",
        "exchange": "mail.example.com"
      }
    },
    {
      "id": "c3d4e5f60718293a4b5c",
      "type": "TXT",
      "host": "@",
      "ttl": 3600,
      "value": "v=spf1 mx -all",
      "fields": {
        "host": "@",
        "ttl": "3600",
        "text": "v=spf1 mx -all"
      }
    }
  ],
  "nameservers": [
    "ns1.stormhost.eu",
    "ns2.stormhost.eu"
  ],
  "count": 3,
  "limit": 200,
  "delegated": true
}

Possible errors

  • 403 Only the domain owner can do this, not a member of a shared service.
  • 404 The service doesn't exist, isn't yours, or the key has no access to it.
  • 400 The service isn't a domain.
  • 409inactive The domain isn't active yet.
  • 409no_zone The domain has no zone on our DNS. Create it via domain/zone or switch the nameservers to ours.
  • 503unavailable The DNS server isn't responding right now. Try again later.
  • 422failed The change couldn't be made.
POST/services/{id}/domain/dnsAdd a DNS record

Adds a record to the domain's zone on our DNS. All values in record are sent as strings. The response contains the new record's ID and the full updated zone listing.

Permission: domains:write

Request body (JSON)

NameTypeRequiredDescription
recordobjectyesThe new record.
record.typestringyesRecord type: A, AAAA, CNAME, MX, TXT, SRV or CAA.
record.hoststringnoName: @ or empty for the domain itself, a relative name (www, _dmarc, *.dev) or a full name ending with the domain.
record.ttlstringnoTTL in seconds as a string, 60 to 86400. Empty means 3600.
record.addressstringnoA: IPv4 address, AAAA: IPv6 address.
record.targetstringnoCNAME and SRV: target name (for SRV also . meaning no service). A CNAME can't be on the domain itself or next to another record with the same name.
record.preferencestringnoMX: priority 0 to 65535 as a string.
record.exchangestringnoMX: mail server name (not an IP address).
record.textstringnoTXT: text up to 2000 characters, no control characters.
record.prioritystringnoSRV: priority 0 to 65535 as a string. The SRV name must look like _service._protocol (tcp, udp, tls, sctp).
record.weightstringnoSRV: weight 0 to 65535 as a string.
record.portstringnoSRV: port 0 to 65535 as a string.
record.flagsstringnoCAA: flag 0 or 128 as a string.
record.tagstringnoCAA: issue, issuewild or iodef.
record.valuestringnoCAA: for issue and issuewild the certificate authority's domain, for iodef a mailto: or https: address.
localestringnoLanguage of error messages: cs, en, sk, pl or de. Default is cs.

Sample body

{
  "record": {
    "type": "MX",
    "host": "@",
    "ttl": "3600",
    "preference": "10",
    "exchange": "mail.example.com"
  }
}

Sample response

{
  "ok": true,
  "id": "b2c3d4e5f60718293a4b",
  "zone": "example.com",
  "unicode": "example.com",
  "records": [
    {
      "id": "a1b2c3d4e5f60718293a",
      "type": "A",
      "host": "@",
      "ttl": 3600,
      "value": "203.0.113.25",
      "fields": {
        "host": "@",
        "ttl": "3600",
        "address": "203.0.113.25"
      }
    },
    {
      "id": "b2c3d4e5f60718293a4b",
      "type": "MX",
      "host": "@",
      "ttl": 3600,
      "value": "10 mail.example.com",
      "fields": {
        "host": "@",
        "ttl": "3600",
        "preference": "10",
        "exchange": "mail.example.com"
      }
    },
    {
      "id": "c3d4e5f60718293a4b5c",
      "type": "TXT",
      "host": "@",
      "ttl": 3600,
      "value": "v=spf1 mx -all",
      "fields": {
        "host": "@",
        "ttl": "3600",
        "text": "v=spf1 mx -all"
      }
    }
  ],
  "nameservers": [
    "ns1.stormhost.eu",
    "ns2.stormhost.eu"
  ],
  "count": 3,
  "limit": 200,
  "delegated": true
}

Possible errors

  • 400 The record failed validation. The code field says why (e.g. type, host, host_zone, cname_apex, srv_host, ipv4, ipv6, target, text, ttl, caa_flags, caa_tag, caa_value, cname_conflict, duplicate, limit) and field says which field is affected.
  • 403 Only the domain owner can do this, not a member of a shared service.
  • 404 The service doesn't exist, isn't yours, or the key has no access to it.
  • 400 The service isn't a domain.
  • 409inactive The domain isn't active yet.
  • 409no_zone The domain has no zone on our DNS. Create it via domain/zone or switch the nameservers to ours.
  • 503unavailable The DNS server isn't responding right now. Try again later.
  • 422failed The change couldn't be made.
  • 429 Limit of 60 changes per 10 minutes exceeded.
PATCH/services/{id}/domain/dnsUpdate a DNS record

Updates a record by its ID from the listing. Omitted or empty fields stay unchanged; the record type can't be changed. The ID is derived from the record's value, so after changing the name or value the response returns a new ID.

Permission: domains:write

Request body (JSON)

NameTypeRequiredDescription
idstringyesRecord ID from the listing (20 hex characters).
recordobjectyesFields to change (same as when adding, without type).
record.hoststringnoName: @ or empty for the domain itself, a relative name (www, _dmarc, *.dev) or a full name ending with the domain.
record.ttlstringnoTTL in seconds as a string, 60 to 86400. Empty means 3600.
record.addressstringnoA: IPv4 address, AAAA: IPv6 address.
record.targetstringnoCNAME and SRV: target name (for SRV also . meaning no service). A CNAME can't be on the domain itself or next to another record with the same name.
record.preferencestringnoMX: priority 0 to 65535 as a string.
record.exchangestringnoMX: mail server name (not an IP address).
record.textstringnoTXT: text up to 2000 characters, no control characters.
record.prioritystringnoSRV: priority 0 to 65535 as a string. The SRV name must look like _service._protocol (tcp, udp, tls, sctp).
record.weightstringnoSRV: weight 0 to 65535 as a string.
record.portstringnoSRV: port 0 to 65535 as a string.
record.flagsstringnoCAA: flag 0 or 128 as a string.
record.tagstringnoCAA: issue, issuewild or iodef.
record.valuestringnoCAA: for issue and issuewild the certificate authority's domain, for iodef a mailto: or https: address.
localestringnoLanguage of error messages: cs, en, sk, pl or de. Default is cs.

Sample body

{
  "id": "a1b2c3d4e5f60718293a",
  "record": {
    "address": "203.0.113.26",
    "ttl": "600"
  }
}

Sample response

{
  "ok": true,
  "id": "d4e5f60718293a4b5c6d",
  "zone": "example.com",
  "unicode": "example.com",
  "records": [
    {
      "id": "a1b2c3d4e5f60718293a",
      "type": "A",
      "host": "@",
      "ttl": 3600,
      "value": "203.0.113.25",
      "fields": {
        "host": "@",
        "ttl": "3600",
        "address": "203.0.113.25"
      }
    },
    {
      "id": "b2c3d4e5f60718293a4b",
      "type": "MX",
      "host": "@",
      "ttl": 3600,
      "value": "10 mail.example.com",
      "fields": {
        "host": "@",
        "ttl": "3600",
        "preference": "10",
        "exchange": "mail.example.com"
      }
    },
    {
      "id": "c3d4e5f60718293a4b5c",
      "type": "TXT",
      "host": "@",
      "ttl": 3600,
      "value": "v=spf1 mx -all",
      "fields": {
        "host": "@",
        "ttl": "3600",
        "text": "v=spf1 mx -all"
      }
    }
  ],
  "nameservers": [
    "ns1.stormhost.eu",
    "ns2.stormhost.eu"
  ],
  "count": 3,
  "limit": 200,
  "delegated": true
}

Possible errors

  • 400 The record failed validation. The code field says why (e.g. type, host, host_zone, cname_apex, srv_host, ipv4, ipv6, target, text, ttl, caa_flags, caa_tag, caa_value, cname_conflict, duplicate, limit) and field says which field is affected.
  • 404not_found No record with this ID in the zone (it may have changed in the meantime).
  • 403 Only the domain owner can do this, not a member of a shared service.
  • 404 The service doesn't exist, isn't yours, or the key has no access to it.
  • 400 The service isn't a domain.
  • 409inactive The domain isn't active yet.
  • 409no_zone The domain has no zone on our DNS. Create it via domain/zone or switch the nameservers to ours.
  • 503unavailable The DNS server isn't responding right now. Try again later.
  • 422failed The change couldn't be made.
  • 429 Limit of 60 changes per 10 minutes exceeded.
DELETE/services/{id}/domain/dnsDelete a DNS record

Deletes a record by its ID from the listing. The ID is sent in the JSON request body. The response contains the updated zone listing.

Permission: domains:write

Request body (JSON)

NameTypeRequiredDescription
idstringyesRecord ID from the listing (20 hex characters).
localestringnoLanguage of error messages: cs, en, sk, pl or de. Default is cs.

Sample body

{
  "id": "c3d4e5f60718293a4b5c"
}

Sample response

{
  "ok": true,
  "zone": "example.com",
  "unicode": "example.com",
  "records": [
    {
      "id": "a1b2c3d4e5f60718293a",
      "type": "A",
      "host": "@",
      "ttl": 3600,
      "value": "203.0.113.25",
      "fields": {
        "host": "@",
        "ttl": "3600",
        "address": "203.0.113.25"
      }
    },
    {
      "id": "b2c3d4e5f60718293a4b",
      "type": "MX",
      "host": "@",
      "ttl": 3600,
      "value": "10 mail.example.com",
      "fields": {
        "host": "@",
        "ttl": "3600",
        "preference": "10",
        "exchange": "mail.example.com"
      }
    },
    {
      "id": "c3d4e5f60718293a4b5c",
      "type": "TXT",
      "host": "@",
      "ttl": 3600,
      "value": "v=spf1 mx -all",
      "fields": {
        "host": "@",
        "ttl": "3600",
        "text": "v=spf1 mx -all"
      }
    }
  ],
  "nameservers": [
    "ns1.stormhost.eu",
    "ns2.stormhost.eu"
  ],
  "count": 3,
  "limit": 200,
  "delegated": true
}

Possible errors

  • 400invalid The id is missing or malformed.
  • 404not_found No record with this ID in the zone.
  • 403 Only the domain owner can do this, not a member of a shared service.
  • 404 The service doesn't exist, isn't yours, or the key has no access to it.
  • 400 The service isn't a domain.
  • 409inactive The domain isn't active yet.
  • 409no_zone The domain has no zone on our DNS. Create it via domain/zone or switch the nameservers to ours.
  • 503unavailable The DNS server isn't responding right now. Try again later.
  • 422failed The change couldn't be made.
  • 429 Limit of 60 changes per 10 minutes exceeded.
POST/services/{id}/domain/nameserversChange the domain's nameservers

Changes the nameservers at the registry: ours = our DNS (the zone is created if missing), custom = your own servers (2 to 6), wedos = the registrar's default DNS. The zone on our DNS isn't deleted when you switch away, so you can switch back. The change takes effect worldwide only after the registry TTL expires.

Permission: domains:write

Request body (JSON)

NameTypeRequiredDescription
modestringyesours, custom or wedos.
nameserversarraynoOnly for custom: 2 to 6 servers as { name, ipv4?, ipv6? }.
nameservers[].namestringyesServer name, e.g. ns1.example.net.
nameservers[].ipv4stringnoIPv4 address. Only for a server inside the domain itself (e.g. ns1.example.com for example.com), where at least one address is required. Ignored otherwise.
nameservers[].ipv6stringnoIPv6 address, same rules as ipv4.
localestringnoLanguage of error messages: cs, en, sk, pl or de. Default is cs.

Sample body

{
  "mode": "custom",
  "nameservers": [
    {
      "name": "ns1.example.com",
      "ipv4": "203.0.113.53"
    },
    {
      "name": "ns2.example.net"
    }
  ]
}

Sample response

{
  "ok": true,
  "mode": "custom",
  "nsset": null,
  "nameservers": [
    "ns1.example.com",
    "ns2.example.net"
  ]
}

Possible errors

  • 400invalid Invalid request body (e.g. unknown mode).
  • 400ns_count custom needs 2 to 6 distinct servers.
  • 400ns_name Invalid server name. The index field says which one.
  • 400ns_glue A server inside the domain needs an IPv4 or IPv6 address.
  • 400ns_ip Invalid server IP address.
  • 400ns_ours The custom servers are only ours. Use mode ours.
  • 403 Only the domain owner can do this, not a member of a shared service.
  • 404 The service doesn't exist, isn't yours, or the key has no access to it.
  • 409inactive The domain isn't active yet.
  • 429 Limit of 10 changes per 10 minutes exceeded.
  • 503unavailable The registry or DNS server is unavailable right now. Try again later.
  • 422failed The registry rejected the change.
POST/services/{id}/domain/zonePrepare a zone on our DNS

Creates an empty zone for the domain on our DNS without changing the nameservers. Useful after a domain transfer: fill in the records via domain/dns first, then switch the NS. Records from the previous DNS aren't copied. If the zone already exists, it returns ok: true and existed: true.

Permission: domains:write

Request body (JSON)

NameTypeRequiredDescription
localestringnoLanguage of error messages: cs, en, sk, pl or de. Default is cs.

Sample body

{
  "locale": "cs"
}

Sample response

{
  "ok": true
}

Possible errors

  • 400invalid The request body contains an unknown field.
  • 403 Only the domain owner can do this, not a member of a shared service.
  • 404 The service doesn't exist, isn't yours, or the key has no access to it.
  • 409inactive The domain isn't active yet.
  • 429 Limit of 10 requests per 10 minutes exceeded.
  • 503not_ready DNS for domains isn't ready right now. Try again later.
  • 422failed The zone couldn't be created.

Billing and invoices

GET/creditCredit balance and history

Returns the credit balance in CZK, split into bonus, non-refundable and refundable parts, pending top-ups and the transaction history (50 per page, newest first). If credit isn't available yet, it returns only available: false.

Permission: billing:read

Query parameters

NameTypeRequiredDescription
pageintegernoHistory page, starting at 1. Default is 1.
localestringnoLanguage of error messages: cs, en, sk, pl or de. Default is cs.

Sample response

{
  "available": true,
  "balanceCzk": 450,
  "bonusCzk": 50,
  "nonRefundableCzk": 0,
  "refundableCzk": 400,
  "pending": [
    {
      "orderId": "clx9k2m4p0001ord02abcdef",
      "invoiceId": "clx9k2m4p0001inv02abcdef",
      "number": "DK-2026-0007",
      "amountCzk": 200,
      "dueAt": "2026-11-14T23:59:59.000Z",
      "createdAt": "2026-11-06T12:00:00.000Z",
      "paymentStarted": false
    }
  ],
  "history": {
    "items": [
      {
        "id": "clx9k2m4p0000ctx01abcdef",
        "seq": 2,
        "type": "SPEND",
        "kind": null,
        "amountCzk": -249,
        "balanceAfterCzk": 450,
        "createdAt": "2026-11-02T10:15:00.000Z",
        "invoiceId": "clx9k2m4p0000inv01abcdef",
        "invoiceNumber": "2026-0042",
        "orderId": "clx9k2m4p0000ord01abcdef",
        "note": null,
        "refundRequestId": null
      },
      {
        "id": "clx9k2m4p0000ctx00abcdef",
        "seq": 1,
        "type": "TOPUP",
        "kind": null,
        "amountCzk": 699,
        "balanceAfterCzk": 699,
        "createdAt": "2026-10-20T08:00:00.000Z",
        "invoiceId": "clx9k2m4p0000inv00abcdef",
        "invoiceNumber": "DK-2026-0005",
        "orderId": "clx9k2m4p0000ord00abcdef",
        "note": null,
        "refundRequestId": null
      }
    ],
    "page": 1,
    "pages": 1,
    "total": 2
  }
}

Possible errors

  • 429rate_limited Limit of 60 requests per minute exceeded.
POST/credit/payPay an invoice from credit

Pays an unpaid order invoice (e.g. a new service or an upgrade) from the account credit. The credit is deducted right away; setting up the service or applying the upgrade finishes after the response. Credit top-up invoices can't be paid this way.

Permission: billing:write

Request body (JSON)

NameTypeRequiredDescription
invoiceIdstringyesID of the unpaid invoice.
expectedAmountCzknumberyesThe invoice amount in CZK you expect. It must match the order price exactly, otherwise you get 409 amount_changed with the current amount.
ackOpenGatewaybooleannoConfirms you want to pay with credit even though a payment gateway payment is open for the invoice. Default is false.
localestringnoLanguage of error messages: cs, en, sk, pl or de. Default is cs.

Sample body

{
  "invoiceId": "clx9k2m4p0000inv01abcdef",
  "expectedAmountCzk": 249
}

Sample response

{
  "ok": true,
  "orderId": "clx9k2m4p0000ord01abcdef",
  "amountCzk": 249,
  "balanceCzk": 201,
  "next": "/cs/order/clx9k2m4p0000ord01abcdef?credit=paid"
}

Possible errors

  • 400invalid A required field is missing or malformed.
  • 403locked The account is temporarily locked.
  • 404invoice_not_found The invoice doesn't exist or isn't yours.
  • 409insufficient Not enough credit. The response contains balanceCzk and neededCzk.
  • 409amount_changed The amount has changed. The current one is in amountCzk.
  • 409closed The invoice is already paid or cancelled.
  • 409expired The proforma invoice expired after its due date.
  • 409upgrade_expired The upgrade offer was valid only until the end of the service period and has been cancelled.
  • 409gateway_open A payment gateway payment is open for the invoice. Send ackOpenGateway: true.
  • 409payment_in_progress A gateway payment is in progress.
  • 409paid_unreconciled A payment has already arrived but isn't matched yet.
  • 409topup_not_payable A credit top-up invoice can't be paid with credit.
  • 409not_payable The invoice doesn't belong to a payable order.
  • 409capacity There's no free capacity for the ordered service right now.
  • 409billing_profile_incomplete The account's billing details are missing. The response contains settingsUrl.
  • 409foreign_eu_vat Orders from businesses in other EU countries are currently handled individually.
  • 429rate_limited Limit of 10 attempts per minute exceeded.
  • 503unavailable Credit isn't available right now.
  • 503gateway_check_failed The gateway payment status can't be checked right now. Try again later.
  • 503capacity_busy Capacity can't be checked right now. Try again shortly.
GET/invoicesList invoices

Returns the account's invoices, newest first, including line items. Amounts are in CZK.

Permission: billing:read

Query parameters

NameTypeRequiredDescription
statusstringnoFilter by status: PENDING, PAID, CANCELLED or REFUNDED. Any other value is ignored.
limitintegernoNumber of invoices, 1 to 200. Default is 50.

Sample response

{
  "data": [
    {
      "id": "clx9k2m4p0000inv01abcdef",
      "number": "2026-0042",
      "status": "PAID",
      "totalCzk": 249,
      "currency": "CZK",
      "items": [
        {
          "description": "VPS Start (1 měsíc)",
          "priceCzk": 249,
          "quantity": 1
        }
      ],
      "dueAt": "2026-11-14T23:59:59.000Z",
      "paidAt": "2026-11-02T10:15:00.000Z",
      "createdAt": "2026-11-01T08:00:00.000Z"
    }
  ]
}
GET/invoices/{id}/pdfInvoice PDF

Downloads the PDF of a paid or refunded invoice. Unpaid documents have no PDF.

Permission: billing:read

Query parameters

NameTypeRequiredDescription
langstringnoen gives an English file name, otherwise Czech.

Sample response

application/pdf (Content-Disposition: attachment; filename="faktura-2026-0042.pdf")

Possible errors

  • 404not_found The invoice doesn't exist, isn't yours or isn't paid.
  • 409preparing The invoice is still being issued. Try again later.
  • 429rate_limited Limit of 20 downloads per minute exceeded.
  • 503not_ready The PDF is being prepared. Try again in a few seconds (Retry-After header).
  • 503unavailable The PDF can't be loaded right now. Try again later.
GET/services/{id}/external-invoices/{key}/pdfPDF of a recurring-billing invoice

Downloads the PDF of an invoice for a service you pay by recurring invoice outside the portal. {key} is the 22-character invoice key from the service's payment overview in the portal. Service owner only (VPS, game server, web hosting).

Permission: billing:read

Query parameters

NameTypeRequiredDescription
langstringnoLanguage of the file name: cs, en, sk, pl or de. Default is cs.

Sample response

application/pdf (Content-Disposition: attachment; filename="faktura-2026-0042.pdf")

Possible errors

  • 404not_found The invoice or service doesn't exist, isn't yours, or you aren't the owner. The response is always the same.
  • 429rate_limited Limit of 20 downloads per minute exceeded.
  • 503not_ready The PDF is being prepared. Try again in a few seconds (Retry-After header).
  • 503unavailable The PDF can't be loaded right now. Try again later.
GET/services/{id}/game-upgradePlan change options for a game or bot

Returns the current package of a game server or Discord bot, bigger and smaller packages with prices and the extra charge, the backup add-on and pending or scheduled changes. Owner only.

Permission: services:read

Query parameters

NameTypeRequiredDescription
viewstringnorestart = returns only { restartPending } (whether the server waits for a restart after a plan change); also works for members.
localestringnoLanguage of texts in the response: en, otherwise cs.

Sample response

{
  "product": "minecraft",
  "productName": "Minecraft",
  "current": {
    "planLabel": "Minecraft 4 GB",
    "packageId": "mc-4gb",
    "legacy": false,
    "memoryMib": 4096,
    "diskMib": 30720,
    "cpu": 200,
    "databases": 1,
    "allocations": 2,
    "backups": 0
  },
  "backups": {
    "included": 0,
    "addon": 0,
    "grandfathered": 0,
    "addonAvailable": true,
    "addonPriceCzk": 120,
    "addonUnitCzk": 0,
    "maxAddon": 1
  },
  "monthlyCzk": 249,
  "period": {
    "start": "2026-11-01T00:00:00.000Z",
    "end": "2026-12-01T00:00:00.000Z",
    "remainingDays": 24,
    "periodDays": 30
  },
  "packages": [
    {
      "id": "mc-6gb",
      "name": "Minecraft 6 GB",
      "cores": 3,
      "cpuUnlimited": false,
      "ramGb": 6,
      "diskGb": 45,
      "ports": 3,
      "databases": 2,
      "includedBackups": 0,
      "priceCzk": 349,
      "recommended": true,
      "fits": true,
      "message": null
    }
  ],
  "options": [
    {
      "packageId": "mc-6gb",
      "addon": 0,
      "monthlyCzk": 349,
      "chargeCzk": 80,
      "after": {
        "memoryMib": 6144,
        "diskMib": 46080,
        "cpu": 300,
        "databases": 2,
        "allocations": 3,
        "backups": 0
      }
    }
  ],
  "effectiveAt": "2026-12-01T00:00:00.000Z",
  "lowerPackages": [],
  "downgradeOptions": [],
  "removeBackup": {
    "available": false
  },
  "downgradeBlocker": null,
  "customStartup": false,
  "scheduled": null,
  "lastChange": null,
  "nextPeriodPriceCzk": 249,
  "pendingOrder": null,
  "upgradeInProgress": false,
  "blocker": null,
  "restartPending": false,
  "recurringMaxCzk": null,
  "billingIncomplete": false,
  "customerType": "consumer"
}

Possible errors

  • 403 Only for the service owner.
  • 409unavailable The plan cannot be changed right now (unknown package or service state).
  • 503 The game panel is not responding right now.
POST/services/{id}/game-upgradeOrder a bigger or schedule a smaller plan

Without action (or with action order) it creates an order for a bigger package or the backup add-on with a proforma invoice; the change is applied after payment. A smaller package is scheduled from the next period, nothing is charged or refunded. Owner only.

Permission: billing:write

Request body (JSON)

NameTypeRequiredDescription
actionstringnoorder (default), cancelPending (cancel the unpaid order), scheduleDowngrade (smaller plan from the next period) or cancelScheduled (cancel the scheduled change).
packageIdstring | nullnoorder, scheduleDowngrade: target package id from GET (packages, lowerPackages). Without it the current package stays.
backupsintegernoorder, scheduleDowngrade: number of backup add-ons, 0 or 1.
immediateStartRequestedbooleannoorder: a consumer requests the change to start immediately (terms art. 9.8). Must be true for accounts without a company ID.
businessPurposebooleannoorder: declaration that the order is for business purposes.
expectedChargeCzknumber | nullnoorder: the extra charge you saw. If it differs, 409 price_changed is returned and nothing is created.
expectedMonthlyCzknumber | nullnoorder, scheduleDowngrade: the new monthly price you saw. If it differs, 409 price_changed is returned.
changeIdstringnocancelScheduled: id of the scheduled change (scheduled.id from GET); if it does not match, 409 changed is returned.
localestringnoLanguage of messages: cs, en, sk, pl or de. Default cs.

Sample body

{
  "packageId": "mc-6gb",
  "backups": 0,
  "immediateStartRequested": true,
  "expectedChargeCzk": 80,
  "expectedMonthlyCzk": 349,
  "locale": "cs"
}

Sample response

{
  "orderId": "ord_7Hq2mX9pLk",
  "chargeCzk": 80,
  "monthlyToCzk": 349,
  "scheduledCancelled": false
}

Possible errors

  • 400 Invalid request or a package that cannot be chosen.
  • 400immediate_start_required A consumer must send immediateStartRequested: true.
  • 403 Only for the service owner.
  • 404none cancelScheduled: there is no scheduled change.
  • 409billing_profile_incomplete The account billing details are incomplete.
  • 409pending_order An unpaid upgrade order already exists (orderId in the response).
  • 409upgrade_in_progress A paid upgrade is still being applied.
  • 409price_changed The price has changed; the response includes newChargeCzk and newMonthlyCzk.
  • 409capacity The bigger package does not fit on the server.
  • 409does_not_fit scheduleDowngrade: the data does not fit into the smaller package (see reasons).
  • 409transfer_pending The service is waiting for a transfer.
  • 409refund_open A withdrawal or refund is open for the service.
  • 409renewal_paid The next period is paid at the price of the scheduled smaller package.
  • 409change_applying The smaller package is being applied right now.
  • 409too_late cancelScheduled: the change has already taken effect.
  • 503price_list_unavailable The price list cannot be loaded right now; nothing is charged.
GET/services/{id}/order-upgradeVPS upgrade offer

Returns the current VPS configuration, monthly price, rates, the highest possible values based on free capacity, the billing period and any unpaid upgrade order. Owner only.

Permission: services:read

Query parameters

NameTypeRequiredDescription
localestringnoen for English texts, otherwise Czech.

Sample response

{
  "tier": "vps-performance",
  "tierName": "VPS Performance",
  "current": {
    "cores": 2,
    "ramGb": 4,
    "diskGb": 60,
    "ipv4": 1
  },
  "monthlyCzk": 390,
  "rates": {
    "perCore": 0,
    "perGbRam": 95,
    "perGbDisk": 0,
    "perIpv4": 60
  },
  "priceList": {
    "fp": "a1b2c3d4",
    "rates": {
      "perCore": 0,
      "perGbRam": 95,
      "perGbDisk": 0,
      "perIpv4": 60
    },
    "packages": [],
    "diskAddon": {
      "perGb": 2,
      "stepGb": 10
    }
  },
  "limits": {
    "max": {
      "cores": 16,
      "ramGb": 24,
      "diskGb": 500,
      "ipv4": 5
    },
    "staticMax": {
      "cores": 16,
      "ramGb": 32,
      "diskGb": 500,
      "ipv4": 5
    }
  },
  "capacity": "limited",
  "unavailable": null,
  "upgradeInProgress": false,
  "period": {
    "start": "2026-11-01T00:00:00.000Z",
    "end": "2026-12-01T00:00:00.000Z",
    "remainingDays": 24,
    "periodDays": 30
  },
  "pendingOrder": null,
  "pendingRestart": false,
  "ipv4Pending": 0,
  "recurringMaxCzk": null,
  "billingIncomplete": false,
  "customerType": "consumer"
}

Possible errors

  • 400 The service is not a VPS.
  • 403 You are not the service owner.
  • 409 The service isn't active.
POST/services/{id}/order-upgradeOrder a VPS upgrade

Creates a VPS upgrade order with a proforma invoice for the prorated charge until the end of the period; the upgrade runs only after payment. The server prices by RAM, disk can only grow; action cancelPending cancels an unpaid order.

Permission: billing:write

Request body (JSON)

NameTypeRequiredDescription
actionstringnoorder (default) or cancelPending.
ramGbnumbernoNew RAM in GB (1–32); vCPU is derived from RAM. Missing = unchanged.
diskGbnumbernoDisk in GB (20–500), only upwards.
ipv4numbernoNumber of IPv4 addresses (1–5).
coresnumbernovCPU (1–16); derived from RAM under RAM-based pricing.
localestringnoLanguage of messages and order description: cs, en, sk, pl or de.
immediateStartRequestedbooleannoConsumer: true = request to carry out the change immediately; required to place the order.
businessPurposebooleannoAccount with a company ID: true = business purpose declaration (then immediate start isn't required).
expectedChargeCzknumbernoThe charge you displayed; different from the computed one = 409 price_changed.
expectedMonthlyCzknumbernoThe new monthly price you displayed; different = 409 price_changed.

Sample body

{
  "ramGb": 8,
  "diskGb": 100,
  "locale": "cs",
  "immediateStartRequested": true,
  "expectedChargeCzk": 312,
  "expectedMonthlyCzk": 780
}

Sample response

{
  "orderId": "clx9o4ord0001",
  "chargeCzk": 312,
  "monthlyToCzk": 780
}

Possible errors

  • 400immediate_start_required The immediate start request is missing. Without a code: invalid values (field) or nothing moved up.
  • 409pending_order An open order already exists (orderId). Other codes: billing_profile_incomplete, foreign_eu_vat, unavailable, transfer_pending, upgrade_in_progress, refund_open, renewal_payment, renewal_overdue, capacity.
  • 409price_changed The price changed; new values in newChargeCzk and newMonthlyCzk, nothing was created.
  • 503capacity_unknown Free capacity can't be checked right now. Code price_list_unavailable: the price list can't be loaded right now.
GET/services/{id}/renewalService renewal and payment status

Returns the service renewal status, end of the paid period, next payment, automatic payments and the history of payment requests. For VPS, games, web and domains; a member of a shared service gets only managed, status and paidUntil.

Permission: services:read

Query parameters

NameTypeRequiredDescription
localestringnoen for English texts, otherwise Czech.

Sample response

{
  "serviceId": "clx9svc000001",
  "managed": true,
  "status": "awaiting_payment",
  "paidUntil": "2026-12-01T00:00:00.000Z",
  "owner": {
    "nextPayment": {
      "amountCzk": 390,
      "periodStart": "2026-12-01T00:00:00.000Z",
      "periodEnd": "2027-01-01T00:00:00.000Z",
      "issueAt": "2026-11-17T00:00:00.000Z",
      "dueAt": "2026-12-01T00:00:00.000Z",
      "method": "manual",
      "invoice": {
        "orderId": "clx9o4ord0002",
        "invoiceId": "clx9i5inv0002",
        "number": "ZF2026110042",
        "status": "PENDING",
        "payUrl": "/cs/order/clx9o4ord0002"
      }
    },
    "suspendAt": null,
    "terminateAt": null,
    "autoPay": {
      "credit": {
        "enabled": true,
        "globallyAllowed": true,
        "held": false,
        "balanceCzk": 120,
        "sufficient": false
      },
      "card": {
        "enabled": false,
        "available": false,
        "last4": null,
        "maxAmountCzk": null,
        "unavailableReason": null
      }
    },
    "endAtTermEnd": null,
    "canPay": true,
    "canExtendEarly": false,
    "canEndAtTermEnd": true,
    "history": []
  }
}

Possible errors

  • 400 This service type has no renewal in the portal (e.g. rackhousing).
  • 404not_found Service not found.
POST/services/{id}/renewalPay or renew early

Returns the open payment request, or issues a request for the next period early (at most one period ahead), with a payment link. A new request returns 201; owner only, limit 20 per hour, body as application/json.

Permission: billing:write

Request body (JSON)

NameTypeRequiredDescription
actionstringyesAlways pay.
localestringnoLanguage of messages and the request: cs, en, sk, pl or de.

Sample body

{
  "action": "pay",
  "locale": "cs"
}

Sample response

{
  "orderId": "clx9o4ord0003",
  "payUrl": "/cs/order/clx9o4ord0003",
  "created": true
}

Possible errors

  • 400invalid Invalid body.
  • 409not_allowed Renewal isn't possible right now. Other codes: not_managed, terminated, term_end, payment_started, failed.
  • 429rate_limited More than 20 requests per hour.
  • 503failed The request couldn't be issued right now.
PATCH/services/{id}/renewalAutomatic payments and termination at term end

Turns payment from credit and by card on or off and files or withdraws termination at the end of the paid period. Termination cancels open payment requests without payment, the service ends with the period and a confirmation e-mail is sent. Owner only, body as application/json.

Permission: billing:write

Request body (JSON)

NameTypeRequiredDescription
autoCreditbooleannoPay the renewal automatically from credit.
autoCardbooleannoPay the renewal automatically with the saved card.
endAtTermEndbooleannotrue = terminate at the end of the paid period, false = withdraw termination.
localestringnoMessage language: cs, en, sk, pl or de.

Sample body

{
  "endAtTermEnd": true,
  "locale": "cs"
}

Sample response

{
  "serviceId": "clx9svc000001",
  "managed": true,
  "status": "ending",
  "paidUntil": "2026-12-01T00:00:00.000Z",
  "owner": {
    "nextPayment": null,
    "suspendAt": null,
    "terminateAt": null,
    "autoPay": {
      "credit": {
        "enabled": true,
        "globallyAllowed": true,
        "held": false,
        "balanceCzk": 120,
        "sufficient": null
      },
      "card": {
        "enabled": false,
        "available": false,
        "last4": null,
        "maxAmountCzk": null,
        "unavailableReason": null
      }
    },
    "endAtTermEnd": {
      "requestedAt": "2026-11-07T10:00:00.000Z",
      "by": "customer",
      "termEnd": "2026-12-01T00:00:00.000Z"
    },
    "canPay": false,
    "canExtendEarly": false,
    "canEndAtTermEnd": false,
    "history": []
  }
}

Possible errors

  • 400invalid Invalid body (fields other than allowed).
  • 404not_allowed The service doesn't belong to your account.
  • 409not_managed The service has no billing period set. Other codes: terminated, not_active, period_over, too_late, payment_started.
  • 415 The body isn't application/json.
GET/services/{id}/web-upgradeWeb hosting plan upgrade offer

Returns the current web hosting plan and higher plans with the charge until the end of the period. For now it returns 409 coming_soon, web hosting can't be changed online yet; owner only.

Permission: services:read

Query parameters

NameTypeRequiredDescription
localestringnoen for English texts, otherwise Czech.

Sample response

{
  "current": {
    "tier": "starter",
    "name": "Starter",
    "storageGb": 10,
    "sites": 1
  },
  "monthlyCzk": 59,
  "period": {
    "start": "2026-11-01T00:00:00.000Z",
    "end": "2026-12-01T00:00:00.000Z",
    "remainingDays": 24,
    "periodDays": 30
  },
  "options": [
    {
      "tier": "business",
      "name": "Business",
      "storageGb": 30,
      "sites": 5,
      "priceCzk": 119,
      "monthlyCzk": 119,
      "chargeCzk": 48
    }
  ],
  "pendingOrder": null,
  "upgradeInProgress": false,
  "blocker": null,
  "recurringMaxCzk": null,
  "billingIncomplete": false,
  "customerType": "consumer"
}

Possible errors

  • 409coming_soon A web hosting plan change can't be ordered online yet. Code unavailable: the plan can't be determined or the service doesn't allow an upgrade.
  • 400 The service isn't web hosting.
  • 403 You are not the service owner.
POST/services/{id}/web-upgradeOrder a higher web hosting plan

Creates an order for a higher plan with a proforma invoice for the prorated charge; the change runs after payment, a lower plan isn't possible. For now it returns 409 coming_soon; action cancelPending cancels an unpaid order.

Permission: billing:write

Request body (JSON)

NameTypeRequiredDescription
actionstringnoorder (default) or cancelPending.
tierstringyesFor order: business or pro (only higher than the current one).
localestringnoLanguage of messages and order description: cs, en, sk, pl or de.
immediateStartRequestedbooleannoConsumer: true = request to carry out the change immediately; required to place the order.
businessPurposebooleannoAccount with a company ID: true = business purpose declaration.
expectedChargeCzknumbernoThe charge you displayed; different = 409 price_changed.
expectedMonthlyCzknumbernoThe new monthly price you displayed; different = 409 price_changed.

Sample body

{
  "tier": "business",
  "locale": "cs",
  "immediateStartRequested": true
}

Sample response

{
  "orderId": "clx9o4ord0004",
  "chargeCzk": 48,
  "monthlyToCzk": 119
}

Possible errors

  • 409coming_soon A plan change can't be ordered online yet. Other codes: price_changed, pending_order, billing_profile_incomplete, unavailable, unknown_current.
  • 400downgrade A lower or the same plan isn't possible. Other codes: unknown_tier, immediate_start_required.
  • 503price_list_unavailable The price list can't be loaded right now, nothing is charged.

Security

  • Give every application and environment its own key with the smallest possible permissions. If one leaks, you revoke only that one.
  • Revoke keys you don't need. The key list shows when and from where each key was last used.
  • For sensitive actions (reinstall, passwords, domain transfer) use a key restricted to your server's IP address.
  • Revoke a leaked key in your customer account right away and create a new one. If you suspect abuse, contact us.

What the API can't do

  • sign-in, password, two-factor authentication, passkeys and signed-in devices
  • sharing a service with other accounts and transferring a service
  • withdrawal from the contract and refunds
  • creating further API keys
  • uploading files (use SFTP, you get the access details via the API)