# Neckrez — API guide for AI agents > Neckrez rents on-demand cloud VPS, Dedicated CPU servers and bare metal > (dedicated IPv4, root access; GPU when a provider has capacity), billed by the > hour and paid for in crypto (300+ coins via NOWPayments). An email is the whole identity — no KYC. REST API over JSON. > > Base URL: https://neckrez.tech/api (same origin as the site; use your own host) > Human docs: /docs · This file: /llms.txt ## Happy path (deploy one server) 1. Get an account and an API key: - POST /api/auth/register {"email":"...","password":"min 8 chars"} -> {"token","user"} (or POST /api/auth/login for an existing account) - Create a non-expiring key in the dashboard: /dashboard/api-keys. It looks like "nek_..." and is shown once. Prefer it for any unattended agent. 2. Send "Authorization: Bearer nek_..." on every /api/v1 request below. 3. GET /api/v1/billing -> {"balance":"10.00", ...} Balance must cover >= 1 hour of the chosen plan, else POST /servers -> 402. 4. POST /api/v1/servers {"name":"my-bot","plan_id":"ion","location_code":"AMS","root_password":""} -> {"...","status":"installing"} (root_password sets root login; keep it) 5. Poll GET /api/v1/servers/ every ~5s until "status":"running" (~60s for a VPS; bare metal takes 10-30 minutes). Then "ip" is populated. 6. DELETE /api/v1/servers/ -> {"ok":true}. Hourly billing stops. ## Auth POST /api/auth/register body {"email","password"} -> 200 {"token":"","user":{...}} POST /api/auth/login body {"email","password"} -> 200 {"token":"","user":{...}} The JWT expires; fine for interactive use. For scripts/agents use an API key (nek_...) created at /dashboard/api-keys — it does not expire and is revocable. Both go in the same header: "Authorization: Bearer ". ## Endpoints (public API v1, key auth) GET /api/v1/billing Balance (decimal string) and recent transactions. -> {"balance":"9.96","transactions":[{...}]} GET /api/v1/servers List your servers. -> {"servers":[{ id, name, provider, location:{code,city,flag}, os:{name,version,app}, plan:{id,vcpu,ram_gb,disk_gb,bandwidth_tb, price_month,price_hour}, ip, status, created_at }]} POST /api/v1/servers Deploy one server. Returns the server with status "installing". body: {"name":"my-bot","plan_id":"ion","location_code":"AMS", "provider":"vultr","os_id":"ubuntu","os_version":"24.04 LTS", "app_id":"","root_password":"..."} required: name (1-60, ^[A-Za-z0-9._-]+$), plan_id, location_code optional: provider (default "vultr"; or "hetzner", "digitalocean"), os_id, os_version, app_id (one-click app), root_password POST /api/v1/servers/bulk Deploy several servers in one call (max 10). Two body forms: {"count":3,"template":{...one POST /servers body...}} -> web-1, web-2, web-3 {"servers":[{...},{...}]} -> each its own body Each server is checked and billed (first hour) exactly like POST /servers, one after another. Best effort, not all-or-nothing: a failure is listed in "failed" and the rest still deploy; if the balance runs out (402) the remaining ones are reported as not attempted. -> 200 all created, 207 some created, else the first failure's status: {"ok":true,"created":[,...],"failed":[{"index","name","status","error"}]} GET /api/v1/servers/{id} One server. Poll after a deploy until status "running". POST /api/v1/servers/{id}/reboot -> server (status "rebooting" -> "running") POST /api/v1/servers/{id}/stop -> server (status "stopped"; still billed while it exists) POST /api/v1/servers/{id}/start -> server (status "running") POST /api/v1/servers/{id}/swap-ip -> server with status "installing" Gives the server a different public IPv4. Async and slow (minutes): the disk is snapshotted, a replacement boots from it, then the original is retired — data is preserved, the address changes. Poll GET /servers/{id} until "running". DELETE /api/v1/servers/{id} -> {"ok":true} (billing stops) GET /api/v1/backups -> {"backups":[{id,server_id,label,status,location,os,plan_id,created_at,expires_at}]} POST /api/v1/backups {"server_id":"","label":"nightly"} Snapshot a server. Async: status "pending" -> "available" (minutes). Kept 7 days. POST /api/v1/backups/{id}/restore -> a NEW server (new IP) from an available backup DELETE /api/v1/backups/{id} -> {"ok":true} ## Command line (optional) A single-file client over the same API, Python 3.8+, no dependencies: curl -fsSL https://neckrez.tech/cli/neckrez -o neckrez && chmod +x neckrez NECKREZ_API_KEY=nek_... ./neckrez deploy my-bot --plan ion --location AMS --wait --json Every command takes --json. Commands: balance, plans, locations, os, deploy, ls, show, start, stop, reboot, swap-ip, rm, ssh, backups. "rm" needs --yes when not on a terminal. ## Catalog plans (cloud, same 5 names/prices on every provider — exact vCPU/disk varies a little by provider, price does not): quark (1 vCPU / 1 GB, $10/mo) · ion (1-3 vCPU / 2 GB, $18) · photon (2 vCPU / 4 GB, $34) · plasma (4-8 vCPU / 8 GB, $62) · fusion (6-16 vCPU / 16 GB, $120) Each provider also sells its own larger/extra sizes beyond these 5 (ids like vhf-*/vhp-* on Vultr, cx*/cpx* on Hetzner, s-*/m-* on DigitalOcean) — the plan catalog is fetched live, never hardcoded; do not guess a plan_id. Product lines: every plan in GET /api/meta has `product` — vps (default) · dedicated (cores reserved for you: voc-*/vx1-* on Vultr, c-*/g-*/gd-*/m-* on DigitalOcean, ccx* on Hetzner) · gpu (Vultr) · metal (a whole physical server, Vultr only, ids vbm-*) — and `available` (false = cannot be ordered right now, e.g. GPU without capacity). Only deploy plans with available true. Bare metal: no auto_backups/ddos add-ons, no snapshots or backups, and with an empty balance it is deleted together with its data. locations: ~51 combined, changes as providers change availability. Always fetch the live list from GET /api/meta (field `locations`, filter by `provider`), each with a `code` you pass as location_code. providers: vultr (default) · hetzner · digitalocean Hetzner and DigitalOcean: Linux only (no Windows), and no auto_backups/ddos add-ons (the API rejects those two add-ons for these providers). os_id (Vultr): ubuntu · debian · almalinux · rocky · centos · fedora · windows os_id (Hetzner/DigitalOcean): ubuntu · debian · almalinux · rocky · centos · fedora price_hour is on the server object and does not change for a running server. ## Server statuses installing -> running (deploy finishes, ~60s) rebooting -> running (after /reboot) running <-> stopped (/stop powers off but keeps billing; /start powers on) suspended (balance ran out or abuse hold; off but recoverable — top up) backup: pending -> available (ready, ~minutes) | expired (after 7 days) | error ## Errors 400 validation failed | 401 missing/invalid/expired token (re-auth; a revoked nek_ key stays 401) 402 insufficient balance | 403 server limit reached (destroy one or ask for a raise) 404 not yours / not found | 429 rate limited (60 req/min per key) -> exponential backoff ## Rules for agents - Deploys are quick but not instant: after POST /servers poll GET /servers/{id} every ~5s until status "running" (~60s) — do not assume it is up on the 202. - Prefer an API key (nek_..., from /dashboard/api-keys) over a login JWT: it does not expire, is revocable, and needs no re-login. A 401 on a key means revoked. - Money values (balance, price_month, price_hour) are strings — parse as decimal, never float-math them. - Check GET /api/v1/billing before deploying: balance must cover >= 1 hour/server. - Server name must match ^[A-Za-z0-9._-]+$ (1-60 chars). - provider defaults to "vultr". "hetzner" and "digitalocean" are Linux-only (no Windows) and reject addon_auto_backups/addon_ddos with a 400. - Rate limit: 60 requests/minute per key. On 429, back off exponentially. - Always DELETE servers you no longer need — billing is hourly and stops at delete. - Pay in crypto — 300+ coins via NOWPayments (BTC, ETH, USDT, LTC and more) — to fund the balance. - Backups are snapshots kept 7 days; POST /backups is async (pending -> available). Restore makes a NEW server with a new IP.