HelipodDocs

Errors

Every error code the VPS API returns, with its HTTP status and what to do about it.

Every error uses the same envelope. Branch on code; error is a human-readable message you can show or log.

{
  "success": false,
  "error": "The VPS is restarting. Try again when it has finished.",
  "code": "VPS_BUSY"
}

Access

StatusCodeMeaningWhat to do
401NO_API_KEYNo Authorization: Bearer header, or an empty key.Send the key.
401INVALID_API_KEYThe key is unknown or revoked.Check the key, or create a new one.
401API_KEY_EXPIREDThe key is past its expiry date.Create a new key.
403SCOPE_NOT_ALLOWEDThe key does not include the VPS API product.Create a key with VPS API enabled.
429RATE_LIMITEDMore than 10 requests per second with this key.Wait for the Retry-After header (seconds), then retry.

Request shape

StatusCodeMeaningWhat to do
422VALIDATIONA body or query field is missing, has the wrong type, or is out of range (for example a name shorter than 3 characters). error names the field, such as Invalid request: /planId.Fix the request.
400PARSEThe body is not valid JSON.Send JSON with Content-Type: application/json.

Not found and scope

Anything the key cannot reach answers 404, whether it does not exist, belongs to another account, or lies outside the key's project. The API never answers 403 for a resource, so ids cannot be probed.

StatusCodeMeaning
404INSTANCE_NOT_FOUNDNo server with this id within the key's reach.
404PROJECT_NOT_FOUNDThe projectId is not a project of the key owner, or not the key's own project.
400PROJECT_REQUIREDprojectId is empty on create.
404SNAPSHOT_NOT_FOUNDNo snapshot with this id within the key's reach.
404FIREWALL_RULE_NOT_FOUNDA firewall rule to remove does not exist. Nothing was removed.

Server state

StatusCodeMeaningWhat to do
409VPS_BUSYThe server is mid-action (being created, starting, stopping, restarting, reinstalling, upgrading), or a backup, restore, backup setup, snapshot or snapshot rollback is in progress on it.Poll GET /vps/:id and retry when it is settled.

VPS_BUSY applies to start, stop, restart, terminate, reinstall, reset password, upgrade, snapshots and firewall changes. Reads, renewals and auto-renew are never blocked.

Business rules

StatusCodeMeaning
400INVALID_BILLING_PERIODbillingPeriod on create or renew is not monthly, 3month, 6month or yearly.
402INSUFFICIENT_BALANCEThe wallet cannot cover a create, renew or upgrade. error gives the required and available amounts.
400INVALID_FIREWALL_RULEA firewall rule to add is invalid (protocol, action, a port outside 1 to 65535 or a reversed range, or a malformed IP or CIDR), or a remove request named neither ids nor rules.
400INVALID_SNAPSHOT_NAMEA snapshot name is not 1 to 60 characters of letters, numbers, spaces, dots, dashes and underscores, starting with a letter or number.
400REQUEST_ERRORThe request is well formed but another rule refused it. error says which.

Common REQUEST_ERROR reasons:

  • The account reached its server limit (terminated servers do not count).
  • Unknown plan, or no image for the requested osType and osVersion.
  • Invalid server name or root password (the message gives the rule: 12 to 30 characters, letters, numbers and ! @ # $ % ^ *).
  • The server is in a status the action does not accept, for example Cannot start instance in 'running' status.
  • Upgrade to a plan in another region or family, a plan that is not larger, or an upgrade with nothing left to pay.
  • Snapshot limit reached, snapshots not available on the plan, or a snapshot that is not ready or not on this server.

Nothing is charged when a request fails with one of these.

Failed jobs

A paid job that fails after the call returned is settled automatically, once:

JobOn failure
CreateCharge refunded. Status error.
RenewCharge refunded, previous expiresAt restored. The status does not change.
UpgradeCharge refunded, old plan restored. Back to the status before the call.
Start, stop, restart, reinstall, snapshot rollbackBack to the status before the call. A reinstall keeps the old password.
Reset passwordStatus unchanged. The old password stays valid.

In every case lastJobStatus is error and lastJobError says why.

Ports, SSH, metrics and upgrade options

StatusCodeMeaning
409FEATURE_NOT_AVAILABLEThe server does not offer this feature: port forwarding and SSH keys and access only exist on servers that share a public address, and upgrade options only on servers the API can upgrade.
409INSTANCE_NOT_RUNNINGThe change is applied on the running server. Start it first.
400INVALID_PORTA port outside the server's range, a wrong port for http (80) or https (443), or a missing or invalid domain.
409PORT_TAKENThe public port is already forwarded, or the domain already has a route.
404PORT_NOT_FOUNDNo port forward with this id on the server.
400INVALID_SSH_KEYNot a single-line OpenSSH public key of a supported type.
400PRIVATE_KEY_REJECTEDA private key was sent. It is not stored.
400SSH_KEY_LIMITThe server already has 10 SSH keys.
409SSH_KEY_EXISTSThe key is already on the server.
404SSH_KEY_NOT_FOUNDNo key with this fingerprint on the server.

Backups

The backup routes add their own codes:

StatusCodeMeaning
404INSTANCE_NOT_FOUNDUnknown server, or one outside the key's reach.
404NOT_FOUNDUnknown restore point or download.
400NOT_ELIGIBLEThe server cannot use backups (not Linux, not provisioned, or terminated).
400 / 409VPS_NOT_RUNNINGThe server must be running.
409AGENT_OFFLINEThe server's management agent does not answer. Restart the server and try again.
409NODE_NOT_READYBackups are not available on this server yet.
404PLAN_NOT_FOUNDUnknown or retired backup planCode.
409ALREADY_SUBSCRIBEDThe server already has the backup add-on.
409BONUS_IN_USEA bundled backup bonus for this server is already being claimed.
402INSUFFICIENT_BALANCEThe wallet cannot cover the backup charge.
404NOT_SUBSCRIBEDNo backup add-on, or nothing to read yet.
409OVER_NEW_QUOTAThe smaller plan cannot hold the current backups.
409NOT_RUNNABLEThe add-on is not in a status that runs backups.
409BUSYAnother backup or restore is in progress.
429LIMITDaily limit of manual backups or downloads reached.
409NO_BLUEPRINTThe operating system cannot be determined for a full restore.
503BACKUP_NOT_CONFIGUREDBackups are temporarily unavailable.
400 / 404 / 409BACKUP_ERRORAny other backup rule, for example an invalid path. Read error.

A path longer than 1024 characters on the file list answers 422 VALIDATION.

Server errors

StatusCodeMeaningWhat to do
500INTERNAL_ERRORSomething failed on our side. The message is generic on purpose.Retry with backoff. For a create, list your servers before retrying so you do not buy twice.

Handling errors

async function vpsApi(path, { method = 'GET', body, key } = {}) {
  for (let attempt = 0; attempt < 5; attempt++) {
    const res = await fetch(`https://api.helipod.io/api${path}`, {
      method,
      headers: {
        Authorization: `Bearer ${key}`,
        ...(body ? { 'Content-Type': 'application/json' } : {}),
      },
      body: body ? JSON.stringify(body) : undefined,
    });
    const json = await res.json();
    if (json.success) return json.data;

    if (json.code === 'RATE_LIMITED') {
      const wait = Number(res.headers.get('retry-after') ?? 1);
      await new Promise((r) => setTimeout(r, wait * 1000));
      continue;
    }
    if (json.code === 'VPS_BUSY') {
      await new Promise((r) => setTimeout(r, 10_000));
      continue;
    }
    throw Object.assign(new Error(json.error), { code: json.code, status: res.status });
  }
  throw new Error('Gave up after 5 attempts');
}

The helper retries RATE_LIMITED and VPS_BUSY only. INTERNAL_ERROR is safe to retry for reads and power actions. Do not retry paid calls (POST /vps, renew, upgrade, backup activation) blindly: check the current state first.

On this page