All systems operational
Support
EN
Language

More languages are on the way.

API reference

CheapServ API v1: Bearer authentication, plans and locations endpoints, ordering servers, opening top-ups, rate limits, examples and error codes.

The CheapServ API is a small JSON API for the things you automate: listing plans and locations, ordering servers from your balance, reading your servers, and opening and tracking top-ups. It is the same interface the dashboard uses, with no extra features hidden behind it.

Base URL
https://cheapserv.com/v1
Format
JSON request bodies and responses, UTF-8
Authentication
Authorization: Bearer cs_…
Rate limit
120 requests per minute per key

Authentication

Generate a key under Account → API. The full key, prefixed cs_, is shown once; store it in your secret manager. Send it on every authenticated request in the Authorization header:

curl https://cheapserv.com/v1/account \
  -H "Authorization: Bearer cs_0038063…"

Keys carry the full rights of the account. Revoke a leaked key immediately from the dashboard; revocation takes effect on the next request. GET /v1/plans and GET /v1/locations are public and need no key.

Rate limits

Each key may make 120 requests per minute. Every response carries X-RateLimit-Limit and X-RateLimit-Remaining; when the limit is exhausted the API answers 429 with the error code rate_limited. Poll a top-up no more often than every 10 seconds — the state changes only on network confirmations.

Errors

Errors are returned as a JSON object with a stable code and a human-readable message:

{"error":{"code":"validation","message":"The hostname is invalid."}}
HTTPCodeMeaning
400validationA field is missing or invalid; the message names it (also: a top-up below $25 or above $5,000, or an unsupported coin)
401unauthorizedMissing, unknown or revoked key
402insufficient_balanceThe balance does not cover the order; see POST /v1/servers
404not_foundUnknown endpoint, or an object that is not yours
429rate_limitedMore than 120 requests in the last minute, or too many deposit addresses opened in a short while
503orchestrator_downThe payment network did not answer; nothing was created, retry in a moment

GET /v1/plans

Public. Returns every plan grouped by product, with live stock. Use the slug when ordering.

curl https://cheapserv.com/v1/plans
{
  "vps": [
    {"slug":"vps-4","name":"VPS-4","monthly_usd":6.99,"stock":"in_stock",
     "specs":{"vcpu":"4","ram":"8 GB","nvme":"160 GB","traffic":"12 TB"}},
    {"slug":"hf-2","name":"HF-2","monthly_usd":12.39,"stock":"low",
     "specs":{"cores":"2","ram":"8 GB","nvme":"120 GB","traffic":"8 TB"}}
  ],
  "dedicated": [ {"slug":"ds-9950x","name":"DS-9950X","monthly_usd":239, "stock":"in_stock","specs":{"cpu":"AMD Ryzen 9 9950X", "ram":"192 GB","storage":"2× 4 TB NVMe Gen4","net":"1 Gbps unmetered"}} ],
  "gpu": [ {"slug":"h100-sxm","name":"H100 SXM","monthly_usd":979,"stock":"in_stock","specs":{"vram":"80 GB HBM3","vcpu":"32","ram":"256 GB","nvme":"2 TB","net":"10 Gbps"}} ],
  "rdp": [ {"slug":"rdp-4","name":"RDP-4","monthly_usd":15.19,"stock":"in_stock","specs":{"vcpu":"4","ram":"8 GB","nvme":"160 GB","os":"Windows Server 2022/2025"}} ]
}

stock is in_stock, low (four units or fewer) or sold_out. Ordering a sold-out plan fails with a validation error. The VPS group contains all three lines; slugs starting with hf- are High-frequency and st- are Storage plans.

GET /v1/locations

Public. Lists the six sites and the products each one can host. Plan availability follows the product list: vps_hf and vps_storage are listed separately from vps.

curl https://cheapserv.com/v1/locations
[
  {"code":"fra","city":"Frankfurt","country":"DE","hub":true,
   "products":["vps","vps_hf","vps_storage","dedicated","gpu","rdp"]},
  {"code":"hel","city":"Helsinki","country":"FI","hub":false,
   "products":["vps","vps_hf","vps_storage","dedicated","rdp"]}
]

GET /v1/account

curl https://cheapserv.com/v1/account \
  -H "Authorization: Bearer $CS_KEY"
{"email":"[email protected]","balance_usd":142.50,"created_at":"2026-09-05T14:40:12Z"}

GET /v1/servers

Returns your servers, newest first. Each server object carries the addresses assigned at provisioning and the next renewal date.

curl https://cheapserv.com/v1/servers \
  -H "Authorization: Bearer $CS_KEY"
[
  {"id":1041,"hostname":"web-01","product":"vps","plan":"vps-4","plan_name":"VPS-4",
   "location":"ams","image":"debian-13-12","ipv4":"198.51.100.86","ipv6":"2001:db8:2:411::1",
   "status":"active","rescue":false,"backups":false,"monthly_usd":6.99,
   "renews_at":"2026-10-05 14:41:03","created_at":"2026-09-05 14:41:03"}
]

status is provisioning (about 60 seconds after payment), active, stopped, rebooting, reinstalling, starting, stopping, suspended or cancelled.

POST /v1/servers

Creates an order and pays it from your prepaid balance. When the balance covers the plan price, the servers are created at once and provisioning starts; they are online within about 60 seconds. When it does not, nothing is created and the API answers 402 with the missing amount — top up first, then send the order again.

FieldTypeRequiredNotes
productstringyesvps, dedicated, gpu or rdp
planstringyesPlan slug from /v1/plans
locationstringyesfra, ams, hel, nyc, lax or sin
imagestringnoImage slug; defaults to the first image of the product
hostnamestringnoLowercase letters, digits, dashes, dots; max 63 characters; generated if omitted
qtyintegerno1 to 10 for VPS and RDP, always 1 otherwise
curl -X POST https://cheapserv.com/v1/servers \
  -H "Authorization: Bearer $CS_KEY" \
  -H "Content-Type: application/json" \
  -d '{"product":"vps","plan":"vps-4","location":"fra",
       "image":"ubuntu-24-04-22-04","hostname":"web-01","qty":1}'
HTTP/2 201
{"order_id":1041,"paid":true,
 "servers":[
   {"id":1041,"hostname":"web-01","product":"vps","plan":"vps-4","plan_name":"VPS-4",
    "location":"fra","image":"ubuntu-24-04-22-04","ipv4":"198.51.100.49","ipv6":"2001:db8:1:411::1",
    "status":"provisioning","rescue":false,"backups":false,"monthly_usd":6.99,
    "renews_at":"2026-10-05 14:41:03","created_at":"2026-09-05 14:41:03"}
 ]}

When the balance is short:

HTTP/2 402
{"error":{"code":"insufficient_balance","message":"Your balance does not cover this order. Top up first."},
 "balance_usd":4.20,"total_usd":6.99,"missing_usd":2.79,
 "topup_url":"https://cheapserv.com/account/topup"}

A plan that is not offered in the chosen location, a sold-out plan or an invalid hostname returns 400 validation. With qty above 1, one server object is returned per machine, with hostnames suffixed -1, -2 and so on.

Slugs

Plan slugs are the plan name in lowercase with spaces replaced by dashes and × by x: vps-4, hf-2, st-1, ds-9950x, rtx-5090, h100-sxm, 8x-h100-sxm, rdp-4, rdp-gpu. Image slugs are the image name and version in lowercase with every run of non-alphanumeric characters replaced by a dash: ubuntu-24-04-22-04, debian-13-12, rocky-linux-10-9, windows-server-2022-2025.

GET /v1/topups

Lists your top-ups, newest first, as top-up objects (see below).

curl https://cheapserv.com/v1/topups \
  -H "Authorization: Bearer $CS_KEY"

POST /v1/topups

Opens a top-up and returns its deposit details: a unique address, the exact crypto amount and a 30-minute validity. Amounts are in USD, between $25 and $5,000. Coin codes: BTC, ETH, XMR, USDTTRC (Tether on TRC-20) and USDT (Tether on ERC-20). Opening a second top-up with the same coin and amount while the first address is still valid returns the existing one instead of a new address.

curl -X POST https://cheapserv.com/v1/topups \
  -H "Authorization: Bearer $CS_KEY" \
  -H "Content-Type: application/json" \
  -d '{"amount_usd":50,"coin":"USDTTRC"}'
HTTP/2 201
{"ref":"cs-k7m2qp4xh9b1zt3v6nwd","amount_usd":50,"bonus_usd":0,"coin":"USDTTRC","status":"pending",
 "deposit_address":"TX3…","deposit_amount":"50.01","deposit_network":"TRX","deposit_tag":null,
 "received":null,"missing":null,"txid":null,
 "expires_at":"2026-09-05 15:11:03","paid_at":null,"created_at":"2026-09-05 14:41:03",
 "url":"https://cheapserv.com/account/topup/cs-k7m2qp4xh9b1zt3v6nwd"}

Send exactly deposit_amount in coin to deposit_address on deposit_network before expires_at. An amount below $25 or above $5,000, or an unsupported coin, returns 400 validation; too many addresses opened in a short while returns 429 rate_limited; if the payment network does not answer, 503 orchestrator_down and nothing was created.

GET /v1/topups/{ref}

Returns one top-up and refreshes its status from the payment network. status is pending (awaiting deposit), confirming, underpaid (received and missing then carry the crypto amounts; send missing to the same address), completed (the balance is credited), expired, cancelled or error. An expired top-up cannot be revived: open a new one instead.

curl https://cheapserv.com/v1/topups/cs-k7m2qp4xh9b1zt3v6nwd \
  -H "Authorization: Bearer $CS_KEY"
{"ref":"cs-k7m2qp4xh9b1zt3v6nwd","amount_usd":50,"bonus_usd":0,"coin":"USDTTRC","status":"completed",
 "deposit_address":"TX3…","deposit_amount":"50.01","deposit_network":"TRX","deposit_tag":null,
 "received":null,"missing":null,"txid":"7c1e…",
 "expires_at":"2026-09-05 15:11:03","paid_at":"2026-09-05 14:52:40","created_at":"2026-09-05 14:41:03",
 "url":"https://cheapserv.com/account/topup/cs-k7m2qp4xh9b1zt3v6nwd"}

Example: top up, wait for the credit, then order

#!/bin/sh
set -e
API=https://cheapserv.com/v1
ref=$(curl -sf -X POST "$API/topups" \
  -H "Authorization: Bearer $CS_KEY" -H "Content-Type: application/json" \
  -d '{"amount_usd":50,"coin":"USDTTRC"}' | jq -r .ref)
echo "top-up $ref — send the deposit shown at $API/topups/$ref"
while :; do
  st=$(curl -sf "$API/topups/$ref" -H "Authorization: Bearer $CS_KEY" | jq -r .status)
  [ "$st" = completed ] && break
  [ "$st" = expired ] && { echo expired; exit 1; }
  sleep 10
done
curl -sf -X POST "$API/servers" \
  -H "Authorization: Bearer $CS_KEY" -H "Content-Type: application/json" \
  -d '{"product":"vps","plan":"hf-2","location":"nyc","hostname":"db-01"}' | jq '.servers[]'

Versioning

The path prefix /v1 is the version. Fields are only ever added to responses, never removed or renamed, within a version; ignore fields you do not know. Breaking changes will ship as /v2 with both versions running side by side for at least six months, announced on Status and by e-mail to every account holding an API key.

Something missing or wrong on this page? Open a ticket and tell us.