{"openapi":"3.1.0","info":{"title":"Cloudvix API","version":"1.0.0","description":"Manage your Cloudvix account with an API key. Create keys in the dashboard under API keys and send them as `Authorization: Bearer cvx_…`. Each key may make 60 requests per minute."},"servers":[{"url":"/api/v1"}],"security":[{"apiKey":[]}],"paths":{"/account":{"get":{"operationId":"getAccount","summary":"The account that owns the API key","responses":{"200":{"description":"The account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Account"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/servers":{"get":{"operationId":"listServers","summary":"List your servers","responses":{"200":{"description":"Your servers, newest first.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServerList"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}},"post":{"operationId":"createServer","summary":"Order a server (hourly or daily billing, paid from the balance)","description":"Creates the server record in status `pending`; it is then set up automatically. Nothing is charged at order time: charges start when the server is running. Your balance must cover the first hour (or day) of the new server plus the next hour of your other servers. At most 10 servers per account and 5 orders per 10 minutes.","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"description":"Any unique string (1–200 printable ASCII characters), e.g. a UUID. Repeating a request with the same key returns the same server.","schema":{"type":"string","minLength":1,"maxLength":200}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateServerRequest"}}}},"responses":{"200":{"description":"Same Idempotency-Key as an earlier request: the server ordered then.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Server"}}}},"201":{"description":"The server was ordered.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Server"}}}},"400":{"description":"The request is not valid: `invalid_request`, `invalid_idempotency_key`, `invalid_name`, `invalid_location`, `invalid_image`, `invalid_plan`, `invalid_billing`, `invalid_access`, `invalid_ssh_key`, `password_required` (Windows Server images take password access only).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"description":"Your balance does not cover the first billing period (`insufficient_balance`). Top up in the dashboard.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"`out_of_stock`, `server_limit_reached`, or `idempotency_conflict` (the key was used for a different order).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests for this key, or more than 5 orders in 10 minutes (`rate_limited`).","headers":{"Retry-After":{"description":"Seconds to wait.","schema":{"type":"integer","minimum":1}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"$ref":"#/components/responses/InternalError"},"503":{"description":"Ordering is paused for a moment while the catalog updates (`catalog_unavailable`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/servers/{id}":{"get":{"operationId":"getServer","summary":"One of your servers","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"The server.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Server"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"description":"No server of yours with this id (`not_found`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}},"delete":{"operationId":"deleteServer","summary":"Delete a server (all data is destroyed)","description":"Allowed for servers that are `pending`, `running`, `stopped` or `failed` (not while `provisioning`). A running server's usage up to now is charged first. Confirm with the server's name: JSON body `{\"confirm\": \"<name>\"}` or the query parameter `confirm`. The answer shows the server as `deleted`, or `deleting` while the data centre still has to confirm.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"Idempotency-Key","in":"header","required":false,"description":"Any unique string (1–200 printable ASCII characters), e.g. a UUID. Repeating a request with the same key does not do the action twice.","schema":{"type":"string","minLength":1,"maxLength":200}},{"name":"confirm","in":"query","required":false,"description":"The server's name (instead of the body).","schema":{"type":"string"}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteServerRequest"}}}},"responses":{"200":{"description":"The server was deleted (or is being deleted).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServerActionResult"}}}},"400":{"description":"`invalid_request`, `invalid_idempotency_key`, `confirm_mismatch` (send the server's name in `confirm`), and for `reinstall`: `invalid_image`, `invalid_access`, `invalid_ssh_key`, `password_required` (Windows Server images take password access only).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"description":"`start`: your balance does not cover the first hour (or day) of the server (`insufficient_balance`). Top up in the dashboard.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No server of yours with this id (`not_found`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"`invalid_state` (not possible in the server's current status), `action_in_progress` (another action on this server is still running), or `idempotency_conflict` (the key was used for a different action).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests for this key, more than 10 actions on this server or 30 on your account in 10 minutes, or more than 3 reinstalls of this server in an hour (`rate_limited`).","headers":{"Retry-After":{"description":"Seconds to wait.","schema":{"type":"integer","minimum":1}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"$ref":"#/components/responses/InternalError"},"502":{"description":"The data centre could not do the action (`action_failed`): nothing was changed, try again in a few minutes. `action_unconfirmed` (start): no clear answer — the server stays stopped and is not charged; we check it and switch it off if it did start.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The action is not available right now (`actions_unavailable`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/servers/{id}/actions":{"post":{"operationId":"serverAction","summary":"Start, stop, reboot, reinstall or delete a server","description":"`start`: stopped servers; your balance must cover the server's first hour (or day) plus the next hour of your running servers. `stop`: running servers; usage up to now is charged first, a stopped server is not charged. `reboot`: running servers. `reinstall`: running or stopped servers — all data is destroyed; confirm with the server's name. `delete`: as DELETE /servers/{id}. At most 10 actions per server and 30 per account in 10 minutes, 3 reinstalls per server per hour, 3 starts at a time (`action_in_progress`). Stop, start, reboot and reinstall answer `actions_unavailable` while server actions are paused on our side.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"Idempotency-Key","in":"header","required":false,"description":"Any unique string (1–200 printable ASCII characters), e.g. a UUID. Repeating a request with the same key does not do the action twice.","schema":{"type":"string","minLength":1,"maxLength":200}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServerActionRequest"}}}},"responses":{"200":{"description":"The action was done. Same Idempotency-Key as an earlier request: the answer of that request, nothing done twice.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServerActionResult"}}}},"400":{"description":"`invalid_request`, `invalid_idempotency_key`, `confirm_mismatch` (send the server's name in `confirm`), and for `reinstall`: `invalid_image`, `invalid_access`, `invalid_ssh_key`, `password_required` (Windows Server images take password access only).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"description":"`start`: your balance does not cover the first hour (or day) of the server (`insufficient_balance`). Top up in the dashboard.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No server of yours with this id (`not_found`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"`invalid_state` (not possible in the server's current status), `action_in_progress` (another action on this server is still running), or `idempotency_conflict` (the key was used for a different action).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests for this key, more than 10 actions on this server or 30 on your account in 10 minutes, or more than 3 reinstalls of this server in an hour (`rate_limited`).","headers":{"Retry-After":{"description":"Seconds to wait.","schema":{"type":"integer","minimum":1}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"$ref":"#/components/responses/InternalError"},"502":{"description":"The data centre could not do the action (`action_failed`): nothing was changed, try again in a few minutes. `action_unconfirmed` (start): no clear answer — the server stays stopped and is not charged; we check it and switch it off if it did start.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The action is not available right now (`actions_unavailable`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}},"components":{"securitySchemes":{"apiKey":{"type":"http","scheme":"bearer","description":"API key from the dashboard, for example `cvx_AbCd…`. It is shown once when created."}},"schemas":{"Account":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"Your account id."},"email":{"type":"string","format":"email","pattern":"^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$","description":"Email address of the account."},"locale":{"type":"string","enum":["en","de","nl","fr"],"description":"Language of emails and messages."},"created_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$","description":"When the account was created (UTC, ISO 8601)."}},"required":["id","email","locale","created_at"],"additionalProperties":false,"description":"The account that owns the API key."},"Error":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["missing_api_key","invalid_api_key","rate_limited","internal_error","invalid_request","invalid_idempotency_key","invalid_name","invalid_location","invalid_image","invalid_plan","invalid_billing","invalid_access","invalid_ssh_key","password_required","insufficient_balance","not_found","out_of_stock","server_limit_reached","idempotency_conflict","catalog_unavailable","invalid_state","action_in_progress","confirm_mismatch","actions_unavailable","action_failed","action_unconfirmed"],"description":"Stable machine-readable code. New codes may be added."},"message":{"type":"string","description":"Explanation for a human, in English. Do not parse it."}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false,"description":"Every error response has this shape."},"Server":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","description":"Server id."},"name":{"type":"string","description":"Hostname: lower-case letters, digits and dashes."},"status":{"type":"string","enum":["pending","provisioning","running","stopped","failed","deleting","deleted"],"description":"`pending` = ordered, waiting to be created; `provisioning` = being created (usually a few minutes); `running` = ready, `ipv4` is set; `failed` = could not be created, nothing was charged (see `failure_reason`); later `stopped`, `deleting` (being deleted) and `deleted` (only in the answer to a delete: deleted servers are not listed). Poll this endpoint until the status is `running` or `failed`."},"location":{"type":"string","description":"Location code, e.g. `DE`, `NL`, `PL`, `US`."},"image":{"type":"string","description":"Operating system, e.g. `ubuntu-24.04`."},"plan":{"type":"string","description":"Plan code, e.g. `R-START`."},"billing":{"type":"string","enum":["hourly","daily"],"description":"How the server is paid from the prepaid balance."},"access":{"type":"string","enum":["ssh_key","password"],"description":"SSH key, or a root password shown once when the server is ready."},"ssh_key_id":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}],"description":"The SSH key installed on the server (null for password access or a removed key)."},"ipv4":{"anyOf":[{"type":"string","format":"ipv4","pattern":"^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])$"},{"type":"null"}],"description":"Public IPv4 address once the server is `running` (or `stopped`); otherwise null."},"failure_reason":{"anyOf":[{"type":"string","enum":["insufficient_balance","unavailable","rejected","provider_error","timeout"]},{"type":"null"}],"description":"Why a `failed` server could not be created, otherwise null: `insufficient_balance` (the balance no longer covered the first period), `unavailable` (plan, image or location no longer offered), `rejected`, `provider_error` or `timeout` (a problem on our side; support is told)."},"price":{"type":"object","properties":{"currency":{"type":"string","const":"EUR"},"hourly":{"type":"string","pattern":"^\\d+\\.\\d{4}$","description":"Price per hour in euro, fixed at order time, e.g. `0.0118`."},"daily":{"type":"string","pattern":"^\\d+\\.\\d{2}$","description":"Price per day in euro (24 hours, rounded up to a cent), fixed at order time."}},"required":["currency","hourly","daily"],"additionalProperties":false,"description":"Excluding VAT. Nothing is charged until the server is running."},"created_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$","description":"When the server was ordered (UTC, ISO 8601)."},"updated_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$","description":"Last status change (UTC, ISO 8601)."}},"required":["id","name","status","location","image","plan","billing","access","ssh_key_id","ipv4","failure_reason","price","created_at","updated_at"],"additionalProperties":false,"description":"A server of your account."},"ServerList":{"type":"object","properties":{"servers":{"type":"array","items":{"$ref":"#/components/schemas/Server"},"description":"Your servers, newest first. Deleted servers are not listed."}},"required":["servers"],"additionalProperties":false,"description":"Servers of the account."},"CreateServerRequest":{"type":"object","properties":{"name":{"description":"Hostname (1–63 lower-case letters, digits, dashes). Omit for a generated name like `cvx-de-7f3a`.","anyOf":[{"type":"string","maxLength":63},{"type":"null"}]},"location":{"type":"string","maxLength":8,"description":"Location code from the catalog, e.g. `DE`."},"image":{"type":"string","maxLength":64,"description":"Operating system slug, e.g. `ubuntu-24.04`."},"plan":{"type":"string","maxLength":32,"description":"Plan code, e.g. `R-START`."},"billing":{"type":"string","enum":["hourly","daily"],"description":"`hourly` or `daily`, paid from the prepaid balance. Monthly and yearly billing are not available yet."},"access":{"type":"string","enum":["ssh_key","password"],"description":"`ssh_key` (needs `ssh_key_id`) or `password` (a root password is shown once when the server is ready). Windows Server images: `password` only."},"ssh_key_id":{"description":"Id of one of your SSH keys; required when `access` is `ssh_key`.","anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]}},"required":["location","image","plan","billing","access"],"additionalProperties":false,"description":"Order a server. Your balance must cover the first hour (or day) plus the next hour of your other servers. Send an `Idempotency-Key` header: repeating a request with the same key returns the same server instead of a second one."},"ServerActionRequest":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","const":"start","description":"Start a stopped server. Your balance must cover its first hour (or day) plus the next hour of your running servers."}},"required":["type"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"stop","description":"Stop a running server. Usage up to now is charged first; a stopped server is not charged."}},"required":["type"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"reboot","description":"Restart a running server (soft reboot)."}},"required":["type"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"reinstall","description":"Reinstall the operating system of a running or stopped server. ALL DATA ON THE SERVER IS DESTROYED."},"image":{"type":"string","maxLength":64,"description":"Operating system slug, available in the server's location, e.g. `debian-12`."},"access":{"type":"string","enum":["ssh_key","password"],"description":"`ssh_key` (needs `ssh_key_id`) or `password` (a new root password, shown once in the dashboard). Windows Server images: `password` only."},"ssh_key_id":{"description":"Id of one of your SSH keys; required when `access` is `ssh_key`.","anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"confirm":{"type":"string","maxLength":64,"description":"The server's name, typed again to confirm: all data on the server is destroyed."}},"required":["type","image","access","confirm"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"delete","description":"Delete the server (same as DELETE /servers/{id}). ALL DATA IS DESTROYED."},"confirm":{"type":"string","maxLength":64,"description":"The server's name, typed again to confirm: all data on the server is destroyed."}},"required":["type","confirm"],"additionalProperties":false}],"description":"An action on one of your servers. Send an `Idempotency-Key` header: a repeated request with the same key is not done twice."},"DeleteServerRequest":{"type":"object","properties":{"confirm":{"type":"string","maxLength":64,"description":"The server's name, typed again to confirm: all data on the server is destroyed."}},"required":["confirm"],"additionalProperties":false,"description":"Confirmation of a deletion: the server's name. It may also be sent as the query parameter `confirm`."},"ServerActionResult":{"type":"object","properties":{"type":{"type":"string","enum":["start","stop","reboot","reinstall","delete"],"description":"The action that was done."},"queued":{"type":"boolean","description":"Stop and delete only: `true` when the server is stopped or deleted on our side but the data centre has not confirmed it yet (it is retried automatically)."},"server":{"$ref":"#/components/schemas/Server"}},"required":["type","queued","server"],"additionalProperties":false,"description":"The server after the action."}},"responses":{"Unauthorized":{"description":"The API key is missing, malformed, unknown or revoked (`missing_api_key`, `invalid_api_key`).","headers":{"WWW-Authenticate":{"schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"RateLimited":{"description":"More than 60 requests in the current minute for this key (`rate_limited`).","headers":{"Retry-After":{"description":"Seconds until the next minute starts.","schema":{"type":"integer","minimum":1}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"InternalError":{"description":"Unexpected error on our side (`internal_error`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}