HelipodDocs

Backups

Nightly backups as a paid add-on. Turn them on, run one now, browse restore points, restore files or the whole server, and download archives.

Backups are an add-on for a server. Once turned on, the server is backed up every night at the hour you choose, older backups are kept according to the plan, and you can restore single files, restore the whole server, or download files as an archive.

The add-on has its own billing period (monthly or yearly), separate from the server's. It is charged to the wallet up front.

Backups are available for Linux servers that have finished provisioning. Times in this API are in WIB (UTC+7): the nightly hour, and the daily limits that reset at midnight WIB.

While a backup, a restore or a backup setup is queued or running, other changes to the server (power, reinstall, snapshots, firewall) answer 409 VPS_BUSY.

Backup plans

GET/backup/plans
List the backup plans on sale.

Note the path: https://api.helipod.io/api/backup/plans, not under /vps.

curl https://api.helipod.io/api/backup/plans \
  -H "Authorization: Bearer hel_your_key"
{
  "success": true,
  "data": [
    {
      "code": "basic",
      "name": "Backup Basic",
      "quotaBytes": 21474836480,
      "priceMonthly": 15000,
      "priceYearly": 150000,
      "keepDaily": 7,
      "keepWeekly": 4,
      "keepMonthly": 3
    }
  ]
}
FieldDescription
codePlan code. Send it as planCode.
nameDisplay name.
quotaBytesStorage allowed for all backups of the server, after compression and deduplication.
priceMonthly, priceYearlyPrice of one month or one year, in Rupiah.
keepDaily, keepWeekly, keepMonthlyHow many daily, weekly and monthly restore points are kept.

Backup status

GET/vps/:id/backup
Return the server's backup add-on, or null if it never had one.
curl https://api.helipod.io/api/vps/1f757fd5-98d1-490a-81a0-58b5798a5815/backup \
  -H "Authorization: Bearer hel_your_key"
{
  "success": true,
  "data": {
    "id": "3c2b1a09-8f7e-4d6c-b5a4-938271605f4e",
    "status": "active",
    "eligible": true,
    "reason": null,
    "plan": { "code": "basic", "name": "Backup Basic", "quotaBytes": 21474836480, "priceMonthly": 15000 },
    "nextPlan": null,
    "period": { "start": "2026-10-16T09:00:00.000Z", "end": "2026-11-16T09:00:00.000Z", "months": 1 },
    "price": 15000,
    "autoRenew": true,
    "graceUntil": null,
    "purgeAfter": null,
    "storage": {
      "usedBytes": 3221225472,
      "quotaBytes": 21474836480,
      "protectedBytes": 0,
      "measuredAt": "2026-10-17T19:40:00.000Z",
      "historyReduced": false
    },
    "lastBackup": { "at": "2026-10-17T19:31:05.000Z", "status": "ok", "error": null },
    "nextRunAt": "2026-10-18T19:17:00.000Z",
    "scheduleHour": 2,
    "manualRunsLeft": 3,
    "activeRun": null
  }
}
FieldDescription
statusSee Add-on statuses.
eligible, reasonWhether the server can use backups, and why not.
plan, nextPlanCurrent plan, and a smaller plan scheduled for the next renewal.
periodCurrent billing period and its length in months (1 or 12).
pricePrice of one full period.
autoRenewWhether the add-on renews itself from the wallet at period.end.
graceUntilEnd of the grace period after a failed renewal.
purgeAfterWhen the stored backups will be deleted, after the add-on ended.
storageSpace used, the quota, and whether older history was trimmed to fit (historyReduced).
lastBackupTime and outcome (ok or failed) of the last backup.
nextRunAtNext scheduled backup, or null when backups are not running.
scheduleHourHour (0 to 23, WIB) the nightly backup starts. The exact minute within that hour is fixed per server.
manualRunsLeftManual backups you can still start today.
activeRunThe backup, restore or setup holding the server right now, with kind, status and since.

Add-on statuses

StatusMeaning
setting_upBackups are being prepared.
activeBackups run every night.
over_quotaStorage is over the quota. Backups still run, and older history is trimmed.
paused_quotaStorage is far over the quota. Backups are paused until you upgrade the plan.
graceA renewal failed. For 7 days no new backups run, but you can still restore and download.
expiredThe period ended without renewal. Restores and downloads work until purgeAfter.
cancelledEnded after auto-renew was switched off. Restores and downloads work until purgeAfter.
setup_failedThe add-on could not be set up.

Stored backups are deleted 7 days after the add-on expires or is cancelled.

Turn backups on

POST/vps/:id/backupcharges your wallet
Buy the backup add-on for a server.

Prop

Type

curl -X POST https://api.helipod.io/api/vps/1f757fd5-98d1-490a-81a0-58b5798a5815/backup \
  -H "Authorization: Bearer hel_your_key" \
  -H "Content-Type: application/json" \
  -d '{ "planCode": "basic", "months": 1, "scheduleHour": 2 }'

Returns the backup status with status: "active".

  • The server must be an eligible Linux server and running.
  • The wallet is charged for the first period at once. Without enough balance the call answers 402 INSUFFICIENT_BALANCE and nothing is created.
  • Preparation happens in the background before the first scheduled backup. The first backup runs at the next scheduleHour; start one earlier with run now.
  • A server can have one add-on at a time: a second call answers 409 ALREADY_SUBSCRIBED.

Change the plan, hour or auto-renew

PATCH/vps/:id/backupcharges your wallet
Upgrade or downgrade the plan, move the nightly hour, or switch auto-renew.

Prop

Type

curl -X PATCH https://api.helipod.io/api/vps/1f757fd5-98d1-490a-81a0-58b5798a5815/backup \
  -H "Authorization: Bearer hel_your_key" \
  -H "Content-Type: application/json" \
  -d '{ "planCode": "pro" }'

Returns the updated backup status. Send only the fields you want to change.

  • Larger plan: applies at once. The wallet is charged the price difference for the time left in the current period (rounded up to whole Rupiah), and a paused add-on resumes.
  • Smaller plan: scheduled for the next renewal and shown as nextPlan; nothing is charged. Refused with 409 OVER_NEW_QUOTA if your backups already use more than the smaller plan allows.
  • Same plan as now: cancels a scheduled downgrade.

Cancel

DELETE/vps/:id/backup
Switch auto-renew off so the add-on ends with the current period.
curl -X DELETE https://api.helipod.io/api/vps/1f757fd5-98d1-490a-81a0-58b5798a5815/backup \
  -H "Authorization: Bearer hel_your_key"

Returns the backup status with autoRenew: false. Backups keep running until period.end; there is no refund. Switch it back on with PATCH and { "autoRenew": true } before the period ends.

Run a backup now

POST/vps/:id/backup/run
Start a manual backup.
curl -X POST https://api.helipod.io/api/vps/1f757fd5-98d1-490a-81a0-58b5798a5815/backup/run \
  -H "Authorization: Bearer hel_your_key"
{ "success": true, "data": { "runId": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d" } }
  • The add-on must be active or over_quota (409 NOT_RUNNABLE otherwise) and the server running (409 VPS_NOT_RUNNING).
  • Only one backup or restore at a time (409 BUSY), and not while the server itself is busy (409 VPS_BUSY).
  • Each plan allows a few manual backups per day (manualRunsLeft in the status). Over the limit: 429 LIMIT.

Follow the run in backup runs.

Backup runs

GET/vps/:id/backup/runs
List the last 50 backup, restore and maintenance jobs.
curl https://api.helipod.io/api/vps/1f757fd5-98d1-490a-81a0-58b5798a5815/backup/runs \
  -H "Authorization: Bearer hel_your_key"
{
  "success": true,
  "data": [
    {
      "id": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
      "kind": "backup",
      "trigger": "manual",
      "status": "ok",
      "skipReason": null,
      "error": null,
      "bytesProcessed": 4831838208,
      "bytesAdded": 52428800,
      "createdAt": "2026-10-17T03:10:00.000Z",
      "startedAt": "2026-10-17T03:10:02.000Z",
      "finishedAt": "2026-10-17T03:14:40.000Z"
    }
  ]
}
FieldValues
kindsetup, backup, restore_files, restore_full, prune, download, purge
triggerschedule, manual, pre_reinstall, admin, system
statusqueued, running, ok, failed, skipped
errorReason, when status is failed.

Returns an empty list when the server has no add-on.

Restore points

GET/vps/:id/backup/points
List the restore points, newest first (up to 200).
curl https://api.helipod.io/api/vps/1f757fd5-98d1-490a-81a0-58b5798a5815/backup/points \
  -H "Authorization: Bearer hel_your_key"
{
  "success": true,
  "data": [
    {
      "id": "f0e1d2c3-b4a5-4968-8776-655443322110",
      "takenAt": "2026-10-17T19:31:05.000Z",
      "kind": "daily",
      "sizeAdded": 52428800,
      "filesTotal": 48213
    }
  ]
}

kind is daily, weekly (taken on a Sunday), monthly (taken on the 1st), manual, or pre_reinstall (taken automatically before a full restore). sizeAdded is the new data the point added, in bytes.

Browse a restore point

GET/vps/:id/backup/points/:pointId/files
List one folder of a restore point.

Prop

Type

curl "https://api.helipod.io/api/vps/1f757fd5-98d1-490a-81a0-58b5798a5815/backup/points/f0e1d2c3-b4a5-4968-8776-655443322110/files?path=/etc/nginx" \
  -H "Authorization: Bearer hel_your_key"
{
  "success": true,
  "data": {
    "path": "/etc/nginx",
    "entries": [
      { "name": "nginx.conf", "path": "/etc/nginx/nginx.conf", "type": "file", "size": 1482, "mtime": "2026-09-30T04:12:00.000Z" },
      { "name": "sites-enabled", "path": "/etc/nginx/sites-enabled", "type": "dir", "size": 0, "mtime": "2026-10-01T02:00:00.000Z" }
    ]
  }
}

type is file, dir or symlink. The server itself is not touched. The answer can take several seconds; if it does not come within about 20 seconds the call answers 400 with a message to try again.

Restore

POST/vps/:id/backup/points/:pointId/restore
Restore files or the whole server from a restore point.

Prop

Type

curl -X POST https://api.helipod.io/api/vps/1f757fd5-98d1-490a-81a0-58b5798a5815/backup/points/f0e1d2c3-b4a5-4968-8776-655443322110/restore \
  -H "Authorization: Bearer hel_your_key" \
  -H "Content-Type: application/json" \
  -d '{ "mode": "files", "paths": ["/etc/nginx", "/var/www/html/index.php"], "target": "folder" }'
{ "success": true, "data": { "runId": "b2c3d4e5-f6a7-4b8c-9d0e-1f2a3b4c5d6e" } }

Follow runId in backup runs (kind restore_files or restore_full).

  • The server must be running (409 VPS_NOT_RUNNING), with no other backup or restore in progress (409 BUSY) and not busy itself (409 VPS_BUSY).
  • A full restore reinstalls the server's current operating system, restores every file from the point and restarts the server. Anything written since the point is lost. When backups are active, a backup of the current state (pre_reinstall) is taken first, so you can go back; the restore then goes ahead whatever that backup's outcome.
  • Restores also work in the grace, expired and cancelled statuses, until the backups are deleted.

Download files

POST/vps/:id/backup/points/:pointId/download
Prepare a compressed archive of files from a restore point.

Prop

Type

curl -X POST https://api.helipod.io/api/vps/1f757fd5-98d1-490a-81a0-58b5798a5815/backup/points/f0e1d2c3-b4a5-4968-8776-655443322110/download \
  -H "Authorization: Bearer hel_your_key" \
  -H "Content-Type: application/json" \
  -d '{ "paths": ["/var/www"] }'
{
  "success": true,
  "data": {
    "id": "c3d4e5f6-a7b8-4c9d-8e0f-2a3b4c5d6e7f",
    "status": "queued",
    "sizeBytes": null,
    "expiresAt": null,
    "url": null,
    "error": null
  }
}

The archive (.tar.gz) is built in the background, without touching the server. Each plan allows a few downloads per day; over the limit the call answers 429 LIMIT.

Download status

GET/vps/:id/backup/downloads/:downloadId
Check a download and get its link.
curl https://api.helipod.io/api/vps/1f757fd5-98d1-490a-81a0-58b5798a5815/backup/downloads/c3d4e5f6-a7b8-4c9d-8e0f-2a3b4c5d6e7f \
  -H "Authorization: Bearer hel_your_key"
{
  "success": true,
  "data": {
    "id": "c3d4e5f6-a7b8-4c9d-8e0f-2a3b4c5d6e7f",
    "status": "ready",
    "sizeBytes": 734003200,
    "expiresAt": "2026-10-18T10:20:00.000Z",
    "url": "https://download.example/archive.tar.gz?signature=...",
    "error": null
  }
}

status moves from queued to building to ready (or failed, with error). Poll every few seconds. url is a signed link, present only while the status is ready; it works until expiresAt (about 24 hours), after which the status reads expired.

Errors

StatusCodeWhen
404INSTANCE_NOT_FOUNDNo server with this id within the key's reach: unknown, another account's, or outside the key's project.
404NOT_FOUNDUnknown restore point or download.
400NOT_ELIGIBLEThe server cannot use backups (error says why, for example not Linux or not provisioned).
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 planCode.
409ALREADY_SUBSCRIBEDThe server already has the add-on.
409BONUS_IN_USEA bundled backup bonus for this server is already being claimed.
402INSUFFICIENT_BALANCEThe wallet cannot cover the charge.
404NOT_SUBSCRIBEDNo add-on, or no backups to read yet.
409OVER_NEW_QUOTAThe smaller plan cannot hold your current backups.
409NOT_RUNNABLEThe add-on is not in a status that runs backups.
409BUSYAnother backup or restore is in progress.
409VPS_BUSYThe server is busy with another action.
429LIMITDaily manual backup or download limit reached.
409NO_BLUEPRINTThe server's 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 or too many paths. Read error.

On this page