Back up a VPS
3 steps · Checked against the API code 3 November 2026
A guide does one task from start to finish. Every endpoint, with all its fields and cases, is in the API reference.
A backup is a full copy of the VPS disk. It is kept on separate backup storage. You start one with a single call and follow the job until it is done. To put a backup back, see Restore a VPS from a backup. For a quick undo point that lasts about a day, take a snapshot instead (Snapshot or backup).
Before you start
Section titled “Before you start”- An API key with the scope
backup:vm. It covers every read on this page. A schedule needswrite:vmas well. The requests use the key as$HOSTUP_API_KEY(Quickstart). Keys and scopes - The ID of the VPS,
vps_…. List VPS instances if you don’t have it.
export VPS_ID="vps_…" # your VPS: List VPS instances1. Check that a backup can be taken
Section titled “1. Check that a backup can be taken”GET /api/v2/vps/{id}/backups lists the backups of the VPS, the slots they use and what you may do next.
curl "https://cloud.hostup.se/api/v2/vps/$VPS_ID/backups" \ -H "Authorization: Bearer $HOSTUP_API_KEY"{ "backups": [ { "id": "bkp_01hxa3b4c5d6e7f8g9h0j1k2m3", "createdAt": "2026-10-30T02:17:00.000Z", "sizeGb": 12, "backupType": "scheduled", "note": "Scheduled daily backup", "actions": { "canRestore": { "allowed": true, "reason": null } }, "…": "…" } ], "listing": { "status": "complete", "reason": null }, "quotaInfo": { "used": 1, "limit": 3, "remaining": 2 }, "actions": { "canCreateBackup": { "allowed": true, "reason": null }, "canRestore": { "allowed": true, "reason": null }, "…": "…" }, "…": "…"}quotaInfo.limitis how many backups the VPS can keep.quotaInfo.remainingis how many slots are free. Manual and scheduled backups share these slots.actions.canCreateBackup.allowedmust betrue. When it isfalse,reasonsays why. The usual reasons are full slots and a backup or restore that is already running. A VPS that isn’t active gets “This action requires an active service.”- When
listing.statusisunavailable, the list is empty because the backups could not be read right then. They are still there. Try again in a moment.
If every slot is used
Section titled “If every slot is used”Do this only when quotaInfo.remaining is 0. Pick a backup you no longer need from backups. Keep its id.
export BACKUP_ID="bkp_…" # backups[].id of the backup to deleteDelete it with DELETE /api/v2/vps/{id}/backups/{backupId}. A deleted backup is gone for good.
curl -X DELETE "https://cloud.hostup.se/api/v2/vps/$VPS_ID/backups/$BACKUP_ID" \ -H "Authorization: Bearer $HOSTUP_API_KEY"The answer is 204 with no body.
2. Take the backup
Section titled “2. Take the backup”POST /api/v2/vps/{id}/backups starts the backup. The body is optional. note is stored with the backup. The API keeps its first 1,024 characters. The VPS keeps running while the backup is taken.
curl -X POST "https://cloud.hostup.se/api/v2/vps/$VPS_ID/backups" \ -H "Authorization: Bearer $HOSTUP_API_KEY" \ -H "Content-Type: application/json" \ -d '{"note": "Before the PHP 8.4 upgrade"}'{ "operation": { "status": "queued", "jobId": "job_01hxa3b4c5d6e7f8g9h0j1k2m3", "pollUrl": "/api/jobs/job_01hxa3b4c5d6e7f8g9h0j1k2m3" }}export JOB_ID="job_…" # operation.jobId above3. Wait for the backup to finish
Section titled “3. Wait for the backup to finish”Poll the job until data.status is completed or failed. While it runs, it is waiting or running.
curl "https://cloud.hostup.se/api/jobs/$JOB_ID" \ -H "Authorization: Bearer $HOSTUP_API_KEY"{ "success": true, "data": { "jobId": "job_01hxa3b4c5d6e7f8g9h0j1k2m3", "type": "backup", "status": "completed", "progress": 100, "…": "…" }, "…": "…"}To poll until it ends, run the script from Jobs:
./wait-for-job.sh "/api/jobs/$JOB_ID"If it ends failed, data.progressText says why when it is known. List the backups as in step 1 and start the backup again.
When it is completed, list the backups again as in step 1. The new one has backupType manual and your note. Without a note it says “Manual backup”. Its id (bkp_…) is what a restore takes.
Back up on a schedule
Section titled “Back up on a schedule”Read the current schedule and its limits with GET /api/v2/vps/{id}/backup-schedules.
curl "https://cloud.hostup.se/api/v2/vps/$VPS_ID/backup-schedules" \ -H "Authorization: Bearer $HOSTUP_API_KEY"{ "schedules": [], "settings": { "autoDeleteOldest": true, "…": "…" }, "limits": { "maxSchedules": 1, "maxRetention": 3, "availableScheduledSlots": 2, "…": "…" }, "actions": { "canCreate": { "allowed": true, "reason": null }, "…": "…" }, "…": "…"}A VPS has one schedule at most. limits.availableScheduledSlots is what the manual backups leave free.
Create the schedule with POST /api/v2/vps/{id}/backup-schedules.
curl -X POST "https://cloud.hostup.se/api/v2/vps/$VPS_ID/backup-schedules" \ -H "Authorization: Bearer $HOSTUP_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "frequency": "daily", "hour": 3, "retentionCount": 3, "enabled": true, "name": "Nightly backup" }'{ "id": "bks_01hxa3b4c5d6e7f8g9h0j1k2m3", "name": "Nightly backup", "frequency": "daily", "time": "03:17", "retentionCount": 3, "enabled": true, "nextRun": "2026-11-03T02:17:00.000Z", "…": "…"}houris Swedish time (Europe/Stockholm). Hostup sets the minute for each VPS.timeshows the result.weeklyalso needsdayOfWeek, 0 to 6 with 0 for Sunday.monthlyneedsdayOfMonth, 1 to 31. In a shorter month a day past its end runs on the last day.retentionCountcan’t be higher thanlimits.maxRetention. Each run keeps at mostretentionCountscheduled backups. It never keeps more thanlimits.availableScheduledSlots. It deletes the oldest scheduled backups beyond that. With the example above (retentionCount3, two free slots) the schedule keeps two. A schedule never deletes a manual backup.- When every slot is taken, a run goes ahead only if
settings.autoDeleteOldestistrue. It then deletes the oldest scheduled backup first. When manual backups fill every slot, scheduled runs are skipped. Change the setting with Update VPS backup settings. - Sending the same
frequencyagain replaces the schedule. A different one answers409 backup_schedule_limit_reached. Delete the old schedule first with Delete a VPS backup schedule.
What happens next
Section titled “What happens next”- Taking a backup creates no invoice. Hostup sends the account holder no e-mail about it.
- A manual backup holds its slot until you delete it.
- Restore a VPS from a backup puts a backup back onto the same VPS or onto a new Cloud VPS.
Errors you may hit
Section titled “Errors you may hit”- 403
forbiddenwithrequiredScopes: the key lacks the scope named there (When a key is refused). - 403
forbiddenwithoutrequiredScopes:detaildoes not say what is wrong. Two things cause it:- The VPS has used up its bandwidth allowance. Backups stay blocked until the usage resets or the limit is raised.
- The backup you delete was already deleted or belongs to another VPS. List the backups again and pick an
idfrom there.
- 409
backup_slots_full: every backup slot of the VPS is used.detailgives the count. Delete a backup you no longer need (If every slot is used) and try again. - 409
backup_temporarily_lockedon a delete: another operation is using the backup. Wait the seconds in theRetry-Afterheader and try again. - 404
backup_not_found: no backup has that ID. Read the list right before you delete. Schedules delete old backups.