Contents
API v1.2 REST · JSON

API Reference

Sell and run our servers from your own website. The API lists the plans on sale at your prices, quotes and places orders paid from your wallet, and lets you power, reinstall, rename and renew every server you own.

It is a REST API over HTTPS: resource-oriented URLs, JSON request bodies, JSON replies and standard HTTP status codes. Every call acts as the account that owns the API key, and follows the same rules as the panel itself.

Import the OpenAPI spec into Postman or Insomnia to try every call.

Authentication

Every call except GET / carries an API key. Make keys in your account under Account & Support → API. A key starts with ajv_ and is shown only once.

Send it in either header. The API keeps no session and sets no cookies, so send the key on every call.

KeyCan call
FullEvery endpoint, including orders and server actions
Read-onlyEvery GET and both quote endpoints; anything else answers 403 read_only
  • Limit each key that can order to your server's IP addresses; other addresses get 403 ip_not_allowed.
  • Call the API from your server only. Never put a key in browser JavaScript, an app or a public repository.
  • Rotate a key by creating a new one, deploying it, then revoking the old one. Revoking takes effect at once.
HEADERS
Authorization: Bearer ajv_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

# or
X-API-Key: ajv_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
EXAMPLE
curl "https://www.flashprimevps.skyhostvps.com/api/v1/account" \
  -H "Authorization: Bearer $SKY_KEY"
$data = $api->call('GET', '/account');
const data = await sky('GET', '/account');
data = sky('GET', '/account')

Requests and responses

Send request bodies as JSON with Content-Type: application/json. Every reply is JSON in the same envelope: success, an optional message on actions, and data.

MoneyNumbers in rupees with up to 2 decimals, e.g. 424.8; currency is always INR
DatesISO 8601 with offset, e.g. 2026-11-03T10:00:14+05:30
Empty valuesnull when unknown or not given; some text fields that do not apply are an empty string
TimeoutsAllow 180 seconds on POST /orders, which creates servers during the call; 30 seconds elsewhere
HTTPSRequired. Plain HTTP is not supported
SUCCESS
{
  "success": true,
  "message": "Your server is ready.",
  "data": {
    "order": {
      "reference": "AJORD-261003-70B8FC32",
      "status": "active"
    }
  }
}
ERROR
{
  "success": false,
  "message": "This key can only read. Make a key with full access to order or change servers.",
  "code": "read_only"
}

Errors

Branch your code on code, and show message to people: it is written for them and says what to do. A message that says “Nothing was charged” means exactly that.

HTTPCodeWhenWhat to do
401 unauthenticated No key, a malformed or revoked key, or a suspended account Check the key; do not retry
402 insufficient_balance The wallet does not cover the order or renewal Top up, then retry
403 read_only A read-only key called an action Use a full key
403 ip_not_allowed The key is limited to other IP addresses Call from an allowed server
403 forbidden The action is not allowed for this server Show the message; do not retry
404 not_found Unknown plan, or an order or server not on your account Refresh the list or check the id
409 conflict The state changed: an IP was taken, a window closed, the server is not active Show the message; let the user choose again
409 in_progress The same Idempotency-Key is still placing its order Wait a minute, then repeat
422 invalid A field is missing or out of range, or a coupon is not valid Fix the request
429 rate_limited More than 120 calls or 10 orders in a minute Wait until the next minute
503 disabled The API is switched off Try later; contact support
502 unavailable A network behind the plan or server did not answer Retry after a few seconds, up to 3 times
500 server_error An unexpected error on our side Retry once; contact support with the time

Rate limits

Each key may make 120 calls and place 10 orders per minute. Over the limit the API answers 429 rate_limited; wait until the next minute.

  • Retry GET calls and quotes freely.
  • On 500, 502 or 503, wait a few seconds and retry up to 3 times, doubling the wait.
  • Never retry 4xx errors unchanged: fix the request first.
429 RESPONSE
{
  "success": false,
  "message": "Too many requests: this key may make 120 requests a minute. Try again in a minute.",
  "code": "rate_limited"
}

Idempotency

Network failures happen. Send an Idempotency-Key header with every POST /orders, using a unique value such as your own order number (8 to 80 letters, digits, dots, colons, dashes or underscores).

  • A repeat with the same key returns the first order with "repeated": true and charges nothing.
  • While the first call is still placing the order, a repeat answers 409 in_progress.
  • If the first call failed before anything was charged, the same key may be used again.
REPEATED ORDER · 200
{
  "success": true,
  "message": "This order was already placed.",
  "data": {
    "order": {
      "reference": "AJORD-261003-70B8FC32",
      "status": "active",
      "…": "…"
    },
    "repeated": true
  }
}

Pagination

List endpoints take page (from 1) and perPage (1 to 100, default 25), and reply with page, perPage and total. Keep asking for the next page while page × perPage < total.

GET /servers?page=2&perPage=25
{
  "success": true,
  "data": {
    "servers": [
      "…"
    ],
    "page": 2,
    "perPage": 25,
    "total": 31
  }
}

Order statuses

An order is charged when it is placed. Most orders come back active from the create call itself; otherwise poll Retrieve an order every 30 to 60 seconds until it is active or refunded.

StatusMeaningWhat your code does
activeAll servers are readyRead each server's login and deliver it
paidPaid, waiting to be set upPoll
provisioningServers are being createdPoll
failedAn attempt failed; it is retried automaticallyPoll; servers may already list some
reviewOur team is checking itPoll; contact support if it lasts hours
refundedIt could not be completed; the money is back in your walletStop polling and tell your customer

Integration flow

A shop that sells servers through the API does five things:

  1. List plans and cache them for up to 5 minutes; respect a plan's terms and maxQuantity.
  2. List the plan's images, and free IPs when ipChoosable is true.
  3. Quote the order and check total against balance.
  4. Create the order with an Idempotency-Key; poll until it is active.
  5. Retrieve each server and give your customer its IP, username and password.

There are no webhooks yet: poll orders for progress and servers for daysLeft, and renew before expiresAt. There is no sandbox either: every order is real, so test with read-only keys and quotes, then one small order.

ORDER FLOW
curl "https://www.flashprimevps.skyhostvps.com/api/v1/plans?os=LINUX" -H "Authorization: Bearer $SKY_KEY"

curl -X POST "https://www.flashprimevps.skyhostvps.com/api/v1/orders/quote" -H "Authorization: Bearer $SKY_KEY" \
  -H "Content-Type: application/json" -d '{"plan":"PLAN_ID","image":1}'

curl -X POST "https://www.flashprimevps.skyhostvps.com/api/v1/orders" -H "Authorization: Bearer $SKY_KEY" \
  -H "Content-Type: application/json" -H "Idempotency-Key: order-1001" \
  -d '{"plan":"PLAN_ID","image":1}'
$plan  = $api->call('GET', '/plans?os=LINUX')['plans'][0];
$image = $api->call('GET', '/plans/' . $plan['id'] . '/images')['images'][0];
$order = ['plan' => $plan['id'], 'image' => $image['id']];

$quote = $api->call('POST', '/orders/quote', $order);
if ($quote['total'] > $quote['balance']) {
    exit('Top up the wallet first.');
}

$placed = $api->call('POST', '/orders', $order, ['Idempotency-Key: order-1001'], 180)['order'];
while (!in_array($placed['status'], ['active', 'refunded'], true)) {
    sleep(30);
    $placed = $api->call('GET', '/orders/' . $placed['reference'])['order'];
}
foreach ($placed['servers'] as $item) {
    $server = $api->call('GET', '/servers/' . $item['id'])['server'];
    echo $server['ip'], ' ', $server['password'], PHP_EOL;
}
const { plans } = await sky('GET', '/plans?os=LINUX');
const { images } = await sky('GET', `/plans/${plans[0].id}/images`);
const order = { plan: plans[0].id, image: images[0].id };

const quote = await sky('POST', '/orders/quote', order);
if (quote.total > quote.balance) throw new Error('Top up the wallet first.');

let { order: placed } = await sky('POST', '/orders', order, { 'Idempotency-Key': 'order-1001' }, 180000);
while (!['active', 'refunded'].includes(placed.status)) {
  await new Promise((r) => setTimeout(r, 30000));
  ({ order: placed } = await sky('GET', `/orders/${placed.reference}`));
}
for (const item of placed.servers) {
  const { server } = await sky('GET', `/servers/${item.id}`);
  console.log(server.ip, server.password);
}
plan = sky('GET', '/plans', params={'os': 'LINUX'})['plans'][0]
image = sky('GET', f"/plans/{plan['id']}/images")['images'][0]
order = {'plan': plan['id'], 'image': image['id']}

quote = sky('POST', '/orders/quote', order)
if quote['total'] > quote['balance']:
    raise SystemExit('Top up the wallet first.')

placed = sky('POST', '/orders', order, headers={'Idempotency-Key': 'order-1001'}, timeout=180)['order']
while placed['status'] not in ('active', 'refunded'):
    time.sleep(30)
    placed = sky('GET', f"/orders/{placed['reference']}")['order']
for item in placed['servers']:
    server = sky('GET', f"/servers/{item['id']}")['server']
    print(server['ip'], server['password'])

Client code

Copy the client for your language into your project and set the SKY_KEY environment variable. Each one wraps the reply envelope and turns failures into an exception that carries the HTTP status and code.

The examples under each endpoint call these clients: $api->call() in PHP and sky() in Node.js and Python. Choose your language once and every example on the page follows.

CLIENT
# Keep the key in an environment variable on your server.
export SKY_KEY="ajv_your_key_here"

curl "https://www.flashprimevps.skyhostvps.com/api/v1/account" \
  -H "Authorization: Bearer $SKY_KEY"
<?php
// SkyHostApi.php — PHP 7.4+ with the curl extension.
final class SkyHostApiException extends RuntimeException
{
    public int $status;
    public string $apiCode;

    public function __construct(string $message, int $status, string $apiCode)
    {
        parent::__construct($message, $status);
        $this->status  = $status;
        $this->apiCode = $apiCode;
    }
}

final class SkyHostApi
{
    private string $key;
    private string $base;

    public function __construct(string $key, string $base = 'https://www.flashprimevps.skyhostvps.com/api/v1')
    {
        $this->key  = $key;
        $this->base = rtrim($base, '/');
    }

    /** @return mixed the reply's "data" */
    public function call(string $method, string $path, ?array $body = null, array $headers = [], int $timeout = 30)
    {
        $ch = curl_init($this->base . $path);
        $headers[] = 'Authorization: Bearer ' . $this->key;
        $headers[] = 'Accept: application/json';
        if ($body !== null) {
            $headers[] = 'Content-Type: application/json';
            curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode((object) $body));
        }
        curl_setopt_array($ch, [
            CURLOPT_CUSTOMREQUEST  => $method,
            CURLOPT_HTTPHEADER     => $headers,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_TIMEOUT        => $timeout,
            CURLOPT_CONNECTTIMEOUT => 10,
        ]);
        $raw    = curl_exec($ch);
        $status = (int) curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
        $error  = curl_error($ch);
        curl_close($ch);

        if ($raw === false) {
            throw new SkyHostApiException('Could not reach the API: ' . $error, 0, 'network_error');
        }
        $reply = json_decode($raw, true);
        if (!is_array($reply)) {
            throw new SkyHostApiException('Unreadable reply (HTTP ' . $status . ').', $status, 'bad_reply');
        }
        if (empty($reply['success'])) {
            throw new SkyHostApiException((string) ($reply['message'] ?? 'Request refused.'), $status, (string) ($reply['code'] ?? 'invalid'));
        }

        return $reply['data'];
    }
}

// Usage
$api = new SkyHostApi(getenv('SKY_KEY'));
try {
    $account = $api->call('GET', '/account');
    echo 'Wallet: ' . $account['balance'] . PHP_EOL;
} catch (SkyHostApiException $e) {
    echo $e->apiCode . ': ' . $e->getMessage() . PHP_EOL;
}
// sky.mjs — Node.js 18+ (built-in fetch).
const BASE = 'https://www.flashprimevps.skyhostvps.com/api/v1';
const KEY = process.env.SKY_KEY;

export class SkyHostError extends Error {
  constructor(message, status, code) {
    super(message);
    this.status = status;
    this.code = code;
  }
}

export async function sky(method, path, body, headers = {}, timeoutMs = 30000) {
  const res = await fetch(BASE + path, {
    method,
    headers: {
      Authorization: `Bearer ${KEY}`,
      Accept: 'application/json',
      ...(body ? { 'Content-Type': 'application/json' } : {}),
      ...headers,
    },
    body: body ? JSON.stringify(body) : undefined,
    signal: AbortSignal.timeout(timeoutMs),
  });
  const reply = await res.json().catch(() => null);
  if (!reply || !reply.success) {
    throw new SkyHostError(reply?.message ?? `HTTP ${res.status}`, res.status, reply?.code ?? 'bad_reply');
  }
  return reply.data;
}

// Usage
try {
  const account = await sky('GET', '/account');
  console.log('Wallet:', account.balance);
} catch (e) {
  console.error(e.code, e.message);
}
# sky.py — Python 3 with requests (pip install requests).
import os

import requests

BASE = 'https://www.flashprimevps.skyhostvps.com/api/v1'
session = requests.Session()
session.headers.update({'Authorization': 'Bearer ' + os.environ['SKY_KEY'], 'Accept': 'application/json'})


class SkyHostError(Exception):
    def __init__(self, message, status, code):
        super().__init__(message)
        self.status, self.code = status, code


def sky(method, path, body=None, params=None, headers=None, timeout=30):
    r = session.request(method, BASE + path, json=body, params=params, headers=headers, timeout=timeout)
    try:
        reply = r.json()
    except ValueError:
        raise SkyHostError(f'HTTP {r.status_code}', r.status_code, 'bad_reply')
    if not reply.get('success'):
        raise SkyHostError(reply.get('message', 'Request refused.'), r.status_code, reply.get('code', 'invalid'))
    return reply['data']


# Usage
try:
    account = sky('GET', '/account')
    print('Wallet:', account['balance'])
except SkyHostError as e:
    print(e.code, e)

Resource

Account

Check that a key works and how much is in your wallet.

API information

GET /api/v1

No key needed

The API name, version and the address of these docs. Needs no key; use it as a health check.

GET /
curl "https://www.flashprimevps.skyhostvps.com/api/v1/"
$data = $api->call('GET', '/');
const data = await sky('GET', '/');
data = sky('GET', '/')
RESPONSE 200 OK
{
  "success": true,
  "data": {
    "name": "SKYHOSTVPS API",
    "version": 1,
    "docs": "https://skyhostvps.com/api-access"
  }
}

Retrieve your account

GET /api/v1/account

Read-only or full key

Your name, email, wallet balance and the key making the call. Check balance before ordering to avoid a 402.

Response fields

balancenumber

Wallet balance in rupees.

key.accessstring

full or read.

GET /account
curl "https://www.flashprimevps.skyhostvps.com/api/v1/account" \
  -H "Authorization: Bearer $SKY_KEY"
$data = $api->call('GET', '/account');
const data = await sky('GET', '/account');
data = sky('GET', '/account')
RESPONSE 200 OK
{
  "success": true,
  "data": {
    "id": 378,
    "name": "Rahul Sharma",
    "email": "rahul@example.com",
    "balance": 10000,
    "currency": "INR",
    "key": {
      "name": "My website",
      "access": "full"
    }
  }
}

Resource

Catalogue

What is on sale at your prices, and what each plan can be ordered with. All work with a read-only key.

List networks

GET /api/v1/networks

Read-only or full key

The networks you can order from. Pass an id as network to List plans.

GET /networks
curl "https://www.flashprimevps.skyhostvps.com/api/v1/networks" \
  -H "Authorization: Bearer $SKY_KEY"
$data = $api->call('GET', '/networks');
const data = await sky('GET', '/networks');
data = sky('GET', '/networks')
RESPONSE 200 OK
{
  "success": true,
  "data": {
    "networks": [
      {
        "id": "primary",
        "label": "Server 1"
      },
      {
        "id": "server2",
        "label": "Server 2"
      }
    ]
  }
}

List plans

GET /api/v1/plans

Read-only or full key

Plans on sale with your monthly price. Prices and stock are refreshed from each network every few minutes: cache the list for up to 5 minutes and quote before ordering.

Query parameters

osstringoptional

LINUX (default) or WINDOWS.

networkstringoptional

all (default) or a network id.

Response fields

plans[].idstring

The plan id for images, IPs, quotes and orders.

plans[].typestring

shared or dedicated resources.

plans[].ipSeriesstring

The block the IP comes from, e.g. 103.45.12 (shown as 103.45.12.xx).

plans[].locationstring

City or country where known, else empty.

plans[].coresinteger|null

vCPU cores.

plans[].ramMb / raminteger / string

Memory in MB and as a label.

plans[].monthlyPricenumber

Your price per month in rupees.

plans[].listPricenumber|null

For an approved seller, the list price per month beside your price; null for everyone else, and for a plan at the list price.

plans[].sellerDiscountobject|null

For an approved seller, where your price comes from: type, value and label. Type price is your own price for this plan, set for you, with value the price and label your price; nothing more comes off it. Otherwise type is percent or flat, value the percentage or the rupees off a month, and label what comes off, e.g. 20% off or ₹100 off a month. A flat amount never takes more than 90% off a price; on a plan where it would, the price is 90% off and the label says so, e.g. ₹1,000 off a month, limited to 90% off. Null for everyone else.

plans[].stockinteger|null

Servers left; null means in stock with no count.

plans[].ipChoosableboolean

True when the buyer may pick an exact IP.

plans[].termsinteger[]|null

The months this plan can be ordered for at once, e.g. [1, 3]; null means any from 1 to 36. Renewals use the same terms.

plans[].maxQuantityinteger|null

The most servers one order may ask for, from the network's limit and stock; null means up to 50.

plans[].notestring|null

The kind of server where a network sells more than one, such as Linux container or Virtual machine.

unavailableNetworksstring[]

Networks that did not answer this time.

Errors

422
invalid

os is not LINUX or WINDOWS.

404
not_found

Unknown network.

GET /plans
curl "https://www.flashprimevps.skyhostvps.com/api/v1/plans?os=LINUX&network=all" \
  -H "Authorization: Bearer $SKY_KEY"
$data = $api->call('GET', '/plans?os=LINUX&network=all');
const data = await sky('GET', '/plans?os=LINUX&network=all');
data = sky('GET', '/plans?os=LINUX&network=all')
RESPONSE 200 OK
{
  "success": true,
  "data": {
    "os": "LINUX",
    "plans": [
      {
        "id": "djF8cHJpbWFyeXwxfFNIQVJFRHwxfDF8MXwxfExJTlVYfA",
        "network": "primary",
        "networkLabel": "Server 1",
        "name": "Linux · 2 GB",
        "os": "LINUX",
        "type": "shared",
        "ipSeries": "103.45.12",
        "location": "",
        "cores": 2,
        "ramMb": 2048,
        "ram": "2 GB",
        "disk": "40GB-Nvme-SSD",
        "bandwidth": "5TB",
        "monthlyPrice": 424.80000000000001136868377216160297393798828125,
        "listPrice": null,
        "sellerDiscount": null,
        "currency": "INR",
        "stock": null,
        "ipChoosable": false,
        "terms": null,
        "maxQuantity": null,
        "note": null
      }
    ],
    "unavailableNetworks": []
  }
}

List plan images

GET /api/v1/plans/{plan}/images

Read-only or full key

The operating systems a plan can be ordered with. Pass an id as image when ordering.

Path parameters

planstringrequired

A plan id.

Errors

404
not_found

The plan id is not valid.

GET /plans/{plan}/images
curl "https://www.flashprimevps.skyhostvps.com/api/v1/plans/djF8cHJpbWFyeXwxfFNIQVJFRHwxfDF8MXwxfExJTlVYfA/images" \
  -H "Authorization: Bearer $SKY_KEY"
$data = $api->call('GET', '/plans/djF8cHJpbWFyeXwxfFNIQVJFRHwxfDF8MXwxfExJTlVYfA/images');
const data = await sky('GET', '/plans/djF8cHJpbWFyeXwxfFNIQVJFRHwxfDF8MXwxfExJTlVYfA/images');
data = sky('GET', '/plans/djF8cHJpbWFyeXwxfFNIQVJFRHwxfDF8MXwxfExJTlVYfA/images')
RESPONSE 200 OK
{
  "success": true,
  "data": {
    "images": [
      {
        "id": 1,
        "name": "DEBIAN-11.11"
      },
      {
        "id": 2,
        "name": "UBUNTU-22"
      },
      {
        "id": 5,
        "name": "ALMALINUX-10.1"
      }
    ]
  }
}

List free IPs

GET /api/v1/plans/{plan}/ips

Read-only or full key

Free IPv4 addresses the buyer may choose from, for plans with ipChoosable: true. Other plans answer with an empty list and choosable: false. An address is checked again when you order.

Path parameters

planstringrequired

A plan id.

Response fields

stillLoadingboolean

True while the network is still listing its addresses; order without ip and one is chosen.

GET /plans/{plan}/ips
curl "https://www.flashprimevps.skyhostvps.com/api/v1/plans/djF8cHJpbWFyeXwxfFNIQVJFRHwxfDF8MXwxfExJTlVYfA/ips" \
  -H "Authorization: Bearer $SKY_KEY"
$data = $api->call('GET', '/plans/djF8cHJpbWFyeXwxfFNIQVJFRHwxfDF8MXwxfExJTlVYfA/ips');
const data = await sky('GET', '/plans/djF8cHJpbWFyeXwxfFNIQVJFRHwxfDF8MXwxfExJTlVYfA/ips');
data = sky('GET', '/plans/djF8cHJpbWFyeXwxfFNIQVJFRHwxfDF8MXwxfExJTlVYfA/ips')
RESPONSE 200 OK
{
  "success": true,
  "data": {
    "ips": [
      "213.210.11.98",
      "213.210.11.99",
      "213.210.11.100"
    ],
    "choosable": true,
    "stillLoading": false
  }
}

Resource

Orders

Quote first, order with an Idempotency-Key, then follow the order until it is active. Orders are paid from your wallet.

Quote an order

POST /api/v1/orders/quote

Read-only or full key

Prices an order without placing it, coupon included, and returns your wallet balance. Charges nothing and works with a read-only key.

Body parameters

planstringrequired

A plan id from List plans.

imageintegerrequired

An image id from List plan images.

monthsintegeroptional

Billing term, 1 to 36. Default 1. Some plans sell only certain terms.

quantityintegeroptional

Number of servers, 1 to 50. Default 1. Some plans allow fewer at once.

ipstringoptional

An exact free IPv4 address from List free IPs. Only for plans with ipChoosable: true.

couponstringoptional

A coupon code. An invalid code is refused with its reason.

Errors

422
invalid

A field is missing or out of range, or the coupon is not valid.

409
conflict

The chosen ip was just taken.

404
not_found

The plan id is not valid.

POST /orders/quote
curl -X POST "https://www.flashprimevps.skyhostvps.com/api/v1/orders/quote" \
  -H "Authorization: Bearer $SKY_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "plan": "djF8cHJpbWFyeXwxfFNIQVJFRHwxfDF8MXwxfExJTlVYfA",
    "image": 1,
    "months": 3,
    "quantity": 2
  }'
$data = $api->call('POST', '/orders/quote', [
    'plan'     => 'djF8cHJpbWFyeXwxfFNIQVJFRHwxfDF8MXwxfExJTlVYfA',
    'image'    => 1,
    'months'   => 3,
    'quantity' => 2,
]);
const data = await sky('POST', '/orders/quote', {
  plan: 'djF8cHJpbWFyeXwxfFNIQVJFRHwxfDF8MXwxfExJTlVYfA',
  image: 1,
  months: 3,
  quantity: 2,
});
data = sky('POST', '/orders/quote', {
    'plan': 'djF8cHJpbWFyeXwxfFNIQVJFRHwxfDF8MXwxfExJTlVYfA',
    'image': 1,
    'months': 3,
    'quantity': 2,
})
RESPONSE 200 OK
{
  "success": true,
  "data": {
    "subtotal": 2548.8000000000001818989403545856475830078125,
    "discount": 0,
    "total": 2548.8000000000001818989403545856475830078125,
    "currency": "INR",
    "summary": "2× 2 vCPU · 2 GB RAM · 40GB-Nvme-SSD · 5TB bandwidth · 3 months",
    "balance": 10000
  }
}

Create an order

POST /api/v1/orders

Full key

Charges your wallet and creates the servers during the call, so allow up to 180 seconds. Send an Idempotency-Key header: a repeat with the same key returns the first order with "repeated": true instead of buying again.

Headers

Idempotency-Keystringoptional

Your own unique order number, 8 to 80 letters, digits, dots, colons, dashes or underscores. Strongly recommended.

Body parameters

planstringrequired

A plan id from List plans.

imageintegerrequired

An image id from List plan images.

monthsintegeroptional

Billing term, 1 to 36. Default 1. Some plans sell only certain terms.

quantityintegeroptional

Number of servers, 1 to 50. Default 1. Some plans allow fewer at once.

ipstringoptional

An exact free IPv4 address from List free IPs. Only for plans with ipChoosable: true.

couponstringoptional

A coupon code. An invalid code is refused with its reason.

Response fields

referencestring

Our order number. Store it beside your own.

statusstring

paid, provisioning, active, failed, review or refunded. See Order statuses.

planstring

What was bought.

osstring

The operating system installed.

monthsinteger

Billing term.

quantityinteger

Number of servers.

totalnumber

Amount charged to your wallet, in rupees.

currencystring

Always INR.

createdAtstring

When the order was placed (ISO 8601).

messagestring|null

A short note while the order is not active, else null.

servers[]array

The servers created so far: id, name, ip, status, expiresAt.

Errors

402
insufficient_balance

The wallet does not cover the order; message says how much to add.

403
read_only

The key can only read.

409
conflict

The chosen IP was taken or the IP series sold out. Nothing was charged.

409
in_progress

The same Idempotency-Key is still placing its order.

422
invalid

A field is missing or out of range, or the coupon is not valid.

429
rate_limited

More than 10 orders in a minute.

POST /orders
curl -X POST "https://www.flashprimevps.skyhostvps.com/api/v1/orders" \
  -H "Authorization: Bearer $SKY_KEY" \
  -H "Idempotency-Key: order-1001" \
  -H "Content-Type: application/json" \
  -d '{
    "plan": "djF8cHJpbWFyeXwxfFNIQVJFRHwxfDF8MXwxfExJTlVYfA",
    "image": 1,
    "months": 1,
    "quantity": 1
  }'
$data = $api->call('POST', '/orders', [
    'plan'     => 'djF8cHJpbWFyeXwxfFNIQVJFRHwxfDF8MXwxfExJTlVYfA',
    'image'    => 1,
    'months'   => 1,
    'quantity' => 1,
], ['Idempotency-Key: order-1001'], 180);
const data = await sky('POST', '/orders', {
  plan: 'djF8cHJpbWFyeXwxfFNIQVJFRHwxfDF8MXwxfExJTlVYfA',
  image: 1,
  months: 1,
  quantity: 1,
}, { 'Idempotency-Key': 'order-1001' }, 180000);
data = sky('POST', '/orders', {
    'plan': 'djF8cHJpbWFyeXwxfFNIQVJFRHwxfDF8MXwxfExJTlVYfA',
    'image': 1,
    'months': 1,
    'quantity': 1,
}, headers={'Idempotency-Key': 'order-1001'}, timeout=180)
RESPONSE 201 Created
{
  "success": true,
  "message": "Your server is ready.",
  "data": {
    "order": {
      "reference": "AJORD-261003-70B8FC32",
      "status": "active",
      "plan": "2 vCPU · 2 GB RAM · 40GB-Nvme-SSD · 5TB bandwidth",
      "os": "DEBIAN-11.11",
      "months": 1,
      "quantity": 1,
      "total": 424.80000000000001136868377216160297393798828125,
      "currency": "INR",
      "createdAt": "2026-10-03T10:00:14+05:30",
      "message": null,
      "servers": [
        {
          "id": 450,
          "name": "vps-70b8fc32",
          "ip": "103.45.12.11",
          "status": "active",
          "expiresAt": "2026-11-03T10:00:14+05:30"
        }
      ]
    }
  }
}

List orders

GET /api/v1/orders

Read-only or full key

Your orders, newest first.

Query parameters

pageintegeroptional

Page number from 1. Default 1.

perPageintegeroptional

1 to 100. Default 25.

GET /orders
curl "https://www.flashprimevps.skyhostvps.com/api/v1/orders?page=1&perPage=25" \
  -H "Authorization: Bearer $SKY_KEY"
$data = $api->call('GET', '/orders?page=1&perPage=25');
const data = await sky('GET', '/orders?page=1&perPage=25');
data = sky('GET', '/orders?page=1&perPage=25')
RESPONSE 200 OK
{
  "success": true,
  "data": {
    "orders": [
      {
        "reference": "AJORD-261003-70B8FC32",
        "status": "active",
        "plan": "2 vCPU · 2 GB RAM · 40GB-Nvme-SSD · 5TB bandwidth",
        "os": "DEBIAN-11.11",
        "months": 1,
        "quantity": 1,
        "total": 424.80000000000001136868377216160297393798828125,
        "currency": "INR",
        "createdAt": "2026-10-03T10:00:14+05:30",
        "message": null,
        "servers": [
          {
            "id": 450,
            "name": "vps-70b8fc32",
            "ip": "103.45.12.11",
            "status": "active",
            "expiresAt": "2026-11-03T10:00:14+05:30"
          }
        ]
      }
    ],
    "page": 1,
    "perPage": 25,
    "total": 1
  }
}

Retrieve an order

GET /api/v1/orders/{reference}

Read-only or full key

One order with its servers. Poll this every 30 to 60 seconds until status is active or refunded.

Path parameters

referencestringrequired

The order reference.

Response fields

referencestring

Our order number. Store it beside your own.

statusstring

paid, provisioning, active, failed, review or refunded. See Order statuses.

planstring

What was bought.

osstring

The operating system installed.

monthsinteger

Billing term.

quantityinteger

Number of servers.

totalnumber

Amount charged to your wallet, in rupees.

currencystring

Always INR.

createdAtstring

When the order was placed (ISO 8601).

messagestring|null

A short note while the order is not active, else null.

servers[]array

The servers created so far: id, name, ip, status, expiresAt.

Errors

404
not_found

The order is not on your account.

GET /orders/{reference}
curl "https://www.flashprimevps.skyhostvps.com/api/v1/orders/AJORD-261003-70B8FC32" \
  -H "Authorization: Bearer $SKY_KEY"
$data = $api->call('GET', '/orders/AJORD-261003-70B8FC32');
const data = await sky('GET', '/orders/AJORD-261003-70B8FC32');
data = sky('GET', '/orders/AJORD-261003-70B8FC32')
RESPONSE 200 OK
{
  "success": true,
  "data": {
    "order": {
      "reference": "AJORD-261003-70B8FC32",
      "status": "active",
      "plan": "2 vCPU · 2 GB RAM · 40GB-Nvme-SSD · 5TB bandwidth",
      "os": "DEBIAN-11.11",
      "months": 1,
      "quantity": 1,
      "total": 424.80000000000001136868377216160297393798828125,
      "currency": "INR",
      "createdAt": "2026-10-03T10:00:14+05:30",
      "message": null,
      "servers": [
        {
          "id": 450,
          "name": "vps-70b8fc32",
          "ip": "103.45.12.11",
          "status": "active",
          "expiresAt": "2026-11-03T10:00:14+05:30"
        }
      ]
    }
  }
}

Resource

Servers

Read, power, reinstall, rename and renew the servers you own. A server on another account always answers 404.

List servers

GET /api/v1/servers

Read-only or full key

Your servers with their live power state. Terminated servers are not listed.

Query parameters

pageintegeroptional

Page number from 1. Default 1.

perPageintegeroptional

1 to 100. Default 25.

searchstringoptional

Matches a name or IP.

Response fields

statusstring

Our record: active or suspended.

powerstring|null

Live state such as running or stopped; null if the network did not answer.

daysLeftinteger|null

Days until expiresAt; negative once expired.

GET /servers
curl "https://www.flashprimevps.skyhostvps.com/api/v1/servers?page=1&perPage=25" \
  -H "Authorization: Bearer $SKY_KEY"
$data = $api->call('GET', '/servers?page=1&perPage=25');
const data = await sky('GET', '/servers?page=1&perPage=25');
data = sky('GET', '/servers?page=1&perPage=25')
RESPONSE 200 OK
{
  "success": true,
  "data": {
    "servers": [
      {
        "id": 450,
        "name": "vps-70b8fc32",
        "ip": "103.45.12.11",
        "os": "DEBIAN-11.11",
        "osFamily": "LINUX",
        "plan": "2 vCPU · 2 GB RAM · 40GB-Nvme-SSD · 5TB bandwidth",
        "order": "AJORD-261003-70B8FC32",
        "status": "active",
        "power": "running",
        "expiresAt": "2026-11-03T10:00:14+05:30",
        "daysLeft": 31,
        "monthlyPrice": 424.80000000000001136868377216160297393798828125
      }
    ],
    "page": 1,
    "perPage": 25,
    "total": 1
  }
}

Retrieve a server

GET /api/v1/servers/{id}

Read-only or full key

Everything in the list plus specs, the login and the actions this server supports.

Path parameters

idintegerrequired

The server id, from List servers or an order.

Response fields

usernamestring|null

Given when the network names it; when null, the login is normally root on Linux and Administrator on Windows.

passwordstring|null

The password set at creation or by the last reset through the panel or API; null when the network does not share it.

featuresstring[]

console, password (you choose one), newpassword (the network generates one), rename, rebuild, network, mac. Hide actions not listed.

lockedboolean

True while the network works on the server; actions are refused until it clears.

renewalobject

terms it renews for; open, with opensAt and closesAt, where the network renews only from 5 days before expiry to 1 day after; note says when in words.

Errors

404
not_found

The server is not on your account.

GET /servers/{id}
curl "https://www.flashprimevps.skyhostvps.com/api/v1/servers/450" \
  -H "Authorization: Bearer $SKY_KEY"
$data = $api->call('GET', '/servers/450');
const data = await sky('GET', '/servers/450');
data = sky('GET', '/servers/450')
RESPONSE 200 OK
{
  "success": true,
  "data": {
    "server": {
      "id": 450,
      "name": "vps-70b8fc32",
      "ip": "103.45.12.11",
      "os": "DEBIAN-11.11",
      "osFamily": "LINUX",
      "plan": "2 vCPU · 2 GB RAM · 40GB-Nvme-SSD · 5TB bandwidth",
      "order": "AJORD-261003-70B8FC32",
      "status": "active",
      "power": "running",
      "expiresAt": "2026-11-03T10:00:14+05:30",
      "daysLeft": 31,
      "monthlyPrice": 424.80000000000001136868377216160297393798828125,
      "cores": 2,
      "ramMb": 2048,
      "ram": "2 GB",
      "disk": "40 GB NVMe",
      "location": "Germany",
      "locked": false,
      "username": null,
      "password": "sLw5EqO03u0n",
      "features": [
        "console",
        "password",
        "rename",
        "rebuild",
        "network",
        "mac"
      ],
      "renewal": {
        "terms": [
          1,
          2,
          3,
          6,
          12
        ],
        "open": true,
        "opensAt": null,
        "closesAt": null,
        "note": null
      }
    }
  }
}

List reinstall images

GET /api/v1/servers/{id}/images

Read-only or full key

Images this server may be reinstalled with. A Linux plan may use Linux only; a Windows plan may use Windows or Linux.

Path parameters

idintegerrequired

The server id, from List servers or an order.

Errors

404
not_found

The server is not on your account.

GET /servers/{id}/images
curl "https://www.flashprimevps.skyhostvps.com/api/v1/servers/450/images" \
  -H "Authorization: Bearer $SKY_KEY"
$data = $api->call('GET', '/servers/450/images');
const data = await sky('GET', '/servers/450/images');
data = sky('GET', '/servers/450/images')
RESPONSE 200 OK
{
  "success": true,
  "data": {
    "images": [
      {
        "id": 1,
        "name": "DEBIAN-11.11",
        "family": "LINUX"
      },
      {
        "id": 2,
        "name": "UBUNTU-22",
        "family": "LINUX"
      }
    ]
  }
}

Retrieve usage metrics

GET /api/v1/servers/{id}/metrics

Read-only or full key

Usage now and a series of samples. time is a Unix timestamp in seconds. Disk usage reads 0 when the guest agent is not running; totalBytes is still correct.

Path parameters

idintegerrequired

The server id, from List servers or an order.

Query parameters

periodstringoptional

hour (default), day or week.

Errors

422
invalid

Unknown period.

404
not_found

The server is not on your account.

GET /servers/{id}/metrics
curl "https://www.flashprimevps.skyhostvps.com/api/v1/servers/450/metrics?period=hour" \
  -H "Authorization: Bearer $SKY_KEY"
$data = $api->call('GET', '/servers/450/metrics?period=hour');
const data = await sky('GET', '/servers/450/metrics?period=hour');
data = sky('GET', '/servers/450/metrics?period=hour')
RESPONSE 200 OK
{
  "success": true,
  "data": {
    "period": "hour",
    "uptimeSeconds": 93600,
    "cpuPercent": 87.7000000000000028421709430404007434844970703125,
    "memory": {
      "usedBytes": 2891116202,
      "totalBytes": 4294967296,
      "percent": 67.31000000000000227373675443232059478759765625
    },
    "disk": {
      "usedBytes": 0,
      "totalBytes": 42949672960,
      "percent": 0
    },
    "network": {
      "inBytes": 20746,
      "outBytes": 1647
    },
    "series": [
      {
        "time": 1791001353,
        "cpuPercent": 39,
        "memoryPercent": 23.3299999999999982946974341757595539093017578125
      }
    ]
  }
}

Start, stop or reboot

POST /api/v1/servers/{id}/power

Full key

Sends a power action. The server must be active.

Path parameters

idintegerrequired

The server id, from List servers or an order.

Body parameters

actionstringrequired

start, stop or reboot. Some networks also accept pause, hibernate and resume.

Errors

422
invalid

Unknown action.

409
conflict

The server is suspended or locked.

404
not_found

The server is not on your account.

POST /servers/{id}/power
curl -X POST "https://www.flashprimevps.skyhostvps.com/api/v1/servers/450/power" \
  -H "Authorization: Bearer $SKY_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "action": "reboot"
  }'
$data = $api->call('POST', '/servers/450/power', [
    'action' => 'reboot',
]);
const data = await sky('POST', '/servers/450/power', {
  action: 'reboot',
});
data = sky('POST', '/servers/450/power', {
    'action': 'reboot',
})
RESPONSE 200 OK
{
  "success": true,
  "message": "VM REBOOT sequence initiated successfully.",
  "data": null
}

Reinstall the operating system

POST /api/v1/servers/{id}/reinstall

Full key

Erases all data on the server and installs the image. On networks that set a new root password, the reply carries it in data.password; otherwise data is null and the current password stays valid.

Path parameters

idintegerrequired

The server id, from List servers or an order.

Body parameters

imageintegerrequired

An image id from List reinstall images.

Errors

403
forbidden

The image is not allowed for this plan, e.g. Windows on a Linux plan.

422
invalid

The image is not offered for this server.

404
not_found

The server is not on your account.

POST /servers/{id}/reinstall
curl -X POST "https://www.flashprimevps.skyhostvps.com/api/v1/servers/450/reinstall" \
  -H "Authorization: Bearer $SKY_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "image": 2
  }'
$data = $api->call('POST', '/servers/450/reinstall', [
    'image' => 2,
]);
const data = await sky('POST', '/servers/450/reinstall', {
  image: 2,
});
data = sky('POST', '/servers/450/reinstall', {
    'image': 2,
})
RESPONSE 200 OK
{
  "success": true,
  "message": "Rebuild initiated.",
  "data": null
}

Set or generate the password

POST /api/v1/servers/{id}/password

Full key

Where features lists password, send the new password. Where it lists newpassword, send an empty body and the network generates one, returned once in data.password. The old password stops working at once.

Path parameters

idintegerrequired

The server id, from List servers or an order.

Body parameters

passwordstringoptional

8 to 64 characters. Leave out to have one generated where supported.

Errors

422
invalid

Too short, or this server takes the other kind of reset.

404
not_found

The server is not on your account.

POST /servers/{id}/password
curl -X POST "https://www.flashprimevps.skyhostvps.com/api/v1/servers/450/password" \
  -H "Authorization: Bearer $SKY_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "password": "New-Root-Pass-42"
  }'
$data = $api->call('POST', '/servers/450/password', [
    'password' => 'New-Root-Pass-42',
]);
const data = await sky('POST', '/servers/450/password', {
  password: 'New-Root-Pass-42',
});
data = sky('POST', '/servers/450/password', {
    'password': 'New-Root-Pass-42',
})
RESPONSE 200 OK
{
  "success": true,
  "message": "Password updated successfully.",
  "data": null
}

Rename a server

POST /api/v1/servers/{id}/rename

Full key

Changes the server's hostname. data.name is the name now in use.

Path parameters

idintegerrequired

The server id, from List servers or an order.

Body parameters

namestringrequired

2 to 64 characters.

Errors

422
invalid

The name is missing or too long.

404
not_found

The server is not on your account.

POST /servers/{id}/rename
curl -X POST "https://www.flashprimevps.skyhostvps.com/api/v1/servers/450/rename" \
  -H "Authorization: Bearer $SKY_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "shop-web-1"
  }'
$data = $api->call('POST', '/servers/450/rename', [
    'name' => 'shop-web-1',
]);
const data = await sky('POST', '/servers/450/rename', {
  name: 'shop-web-1',
});
data = sky('POST', '/servers/450/rename', {
    'name': 'shop-web-1',
})
RESPONSE 200 OK
{
  "success": true,
  "message": "VM renamed successfully",
  "data": {
    "name": "shop-web-1"
  }
}

Open a console

POST /api/v1/servers/{id}/console

Full key

A single-use console link that expires once used. Depending on the network you get a browser url, or a VNC-over-WebSocket wsUrl with its password for a noVNC client.

Path parameters

idintegerrequired

The server id, from List servers or an order.

Errors

502
unavailable

The console is not available right now.

404
not_found

The server is not on your account.

POST /servers/{id}/console
curl -X POST "https://www.flashprimevps.skyhostvps.com/api/v1/servers/450/console" \
  -H "Authorization: Bearer $SKY_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'
$data = $api->call('POST', '/servers/450/console', []);
const data = await sky('POST', '/servers/450/console', {});
data = sky('POST', '/servers/450/console', {})
RESPONSE 200 OK
{
  "success": true,
  "data": {
    "url": null,
    "wsUrl": "wss://console.example.com/api/ws/vnc?vncToken=…",
    "password": "…",
    "note": "This console link is single-use and expires as soon as it connects."
  }
}

Quote a renewal

GET /api/v1/servers/{id}/renew/quote

Read-only or full key

Prices a renewal without renewing. coupon is null without a code, or carries APPLIED or INVALID with a message.

Path parameters

idintegerrequired

The server id, from List servers or an order.

Query parameters

monthsintegeroptional

Default 1. 1, 2, 3, 6 or 12 on most networks.

couponstringoptional

A coupon code.

Errors

422
invalid

A term this server does not renew for; message names the allowed ones.

404
not_found

The server is not on your account.

GET /servers/{id}/renew/quote
curl "https://www.flashprimevps.skyhostvps.com/api/v1/servers/450/renew/quote?months=3" \
  -H "Authorization: Bearer $SKY_KEY"
$data = $api->call('GET', '/servers/450/renew/quote?months=3');
const data = await sky('GET', '/servers/450/renew/quote?months=3');
data = sky('GET', '/servers/450/renew/quote?months=3')
RESPONSE 200 OK
{
  "success": true,
  "data": {
    "months": 3,
    "monthlyPrice": 424.80000000000001136868377216160297393798828125,
    "subtotal": 1274.40000000000009094947017729282379150390625,
    "discount": 0,
    "total": 1274.40000000000009094947017729282379150390625,
    "currency": "INR",
    "coupon": null,
    "daysRemaining": 31
  }
}

Renew a server

POST /api/v1/servers/{id}/renew

Full key

Adds months to the server, paid from your wallet. Some networks renew only from 5 days before expiry until 1 day after.

Path parameters

idintegerrequired

The server id, from List servers or an order.

Body parameters

monthsintegerrequired

1, 2, 3, 6 or 12 on most networks.

couponstringoptional

A coupon code.

Errors

402
insufficient_balance

The wallet does not cover the renewal.

409
conflict

Outside the renewal window; message gives the dates.

422
invalid

A term this server does not renew for.

404
not_found

The server is not on your account.

POST /servers/{id}/renew
curl -X POST "https://www.flashprimevps.skyhostvps.com/api/v1/servers/450/renew" \
  -H "Authorization: Bearer $SKY_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "months": 3
  }'
$data = $api->call('POST', '/servers/450/renew', [
    'months' => 3,
]);
const data = await sky('POST', '/servers/450/renew', {
  months: 3,
});
data = sky('POST', '/servers/450/renew', {
    'months': 3,
})
RESPONSE 200 OK
{
  "success": true,
  "message": "Renewed for 3 months.",
  "data": {
    "expiresAt": "2027-01-03T10:00:14+05:30",
    "charged": 1274.40000000000009094947017729282379150390625,
    "currency": "INR"
  }
}

Changelog

The version is in the path. New fields and endpoints are added within v1; a change that would break an existing integration would come as a new version.

DateVersionChange
4 Oct 20261.2Plans carry terms, maxQuantity and note; servers carry renewal; plan prices refresh every few minutes
3 Oct 20261.1Order and renewal quotes, server login fields and features, password, rename, console and usage metrics
3 Oct 20261.0First release: account, networks, plans, images, IPs, orders, servers, power, reinstall, renew