API reference

Backups

Make, download, restore and lock backups of your server's files.

← API docs7 endpointsUpdated

Browse the docs

Backups

Make, download, restore, lock and delete backups of a server's files. A server may keep as many backups as its backup limit (feature_limits.backups on the server) allows; failed backups do not count towards it. A server with a limit of 0 cannot make backups.

A backup is in progress while completed_at is null. Once it finishes, is_successful says whether it worked. Watch the server's websocket or poll getBackup to see when it is done.

While a server is installing, suspended, being transferred, restoring a backup or being deleted, every endpoint here answers 409.

List backups

GET/servers/{server}/backups

Permission backup.read

Returns the server's backups in the order they were made, including ones still in progress and ones that failed. meta.backup_count is how many count towards the backup limit, that is every backup that has not failed.

Parameters

List backups: parameters
NameTypeDescription
serverrequiredstringThe server's 8-character identifier, as shown in the panel, or its full UUID.
pageintegerThe page of results to return, starting at 1.
per_pageintegerHow many backups to return on each page. Values above 50 are treated as 50.

Example

curl "https://sillydev.co.uk/panel/api/client/servers/1a7ce997/backups" \
  -H "Authorization: Bearer $SILLYDEV_API_KEY" \
  -H "Accept: application/json"

Response 200A page of backups.

{
    "object": "list",
    "data": [
        {
            "object": "backup",
            "attributes": {
                "uuid": "0f2a6c1e-8d3b-4f7a-9c5e-2b1d4e6f8a90",
                "is_successful": true,
                "is_locked": false,
                "name": "Before discord.py upgrade",
                "ignored_files": [
                    "node_modules",
                    "*.log"
                ],
                "checksum": "sha1:3f786850e387550fdab836ed7e6dc881de23001b",
                "bytes": 5242880,
                "created_at": "2026-10-10T12:00:00+00:00",
                "completed_at": "2026-10-10T12:00:41+00:00"
            }
        }
    ],
    "meta": {
        "pagination": {
            "total": 1,
            "count": 1,
            "per_page": 20,
            "current_page": 1,
            "total_pages": 1,
            "links": []
        },
        "backup_count": 1
    }
}
Every field in the response
List backups: response
NameTypeDescription
objectrequiredstring
datarequiredarray of object
data[].objectrequiredstring
data[].attributesrequiredobject
data[].attributes.uuidrequiredstring (uuid)The backup's ID, used in the URLs of the other backup endpoints.
data[].attributes.is_successfulrequiredbooleanTrue once the backup has finished successfully. False while it is in progress (completed_at is null) and when it failed.
data[].attributes.is_lockedrequiredbooleanA locked backup cannot be deleted.
data[].attributes.namerequiredstring
data[].attributes.ignored_filesrequiredarray of stringThe ignore patterns given when the backup was made, one per item.
data[].attributes.checksumrequiredstring | nullThe archive's checksum as <algorithm>:<hex>, e.g. sha1:.... Null until it succeeds.
data[].attributes.bytesrequiredintegerThe archive's size in bytes. 0 until it completes.
data[].attributes.created_atrequiredstring (date-time)
data[].attributes.completed_atrequiredstring (date-time) | nullWhen the backup finished, successfully or not. Null while in progress.
metarequiredobject
meta.paginationrequiredobject
meta.pagination.totalinteger
meta.pagination.countinteger
meta.pagination.per_pageinteger
meta.pagination.current_pageinteger
meta.pagination.total_pagesinteger
meta.pagination.linksobject
meta.pagination.links.previousstring (uri)
meta.pagination.links.nextstring (uri)
meta.backup_countrequiredintegerHow many of the server's backups count towards its limit: those in progress or successful, on every page.

Errors

  • 401 No API key was sent, or it is wrong, expired or deleted.
  • 403 The key is valid but may not do this: it lacks the permission or account scope, it is limited to other servers or IP addresses, or the account may not do it at all.
  • 404 There is no such resource, or the key cannot see it. Features that are switched off answer 404 too.
  • 409 The resource is busy or in a state that does not allow this right now.

Start a backup

POST/servers/{server}/backups

Permission backup.createLimited to 2 backups per 10 minutes per server

Starts a backup of the server's files and returns it at once, still in progress (completed_at is null). The server keeps running while it is backed up.

Answers 400 when the server has reached its backup limit (delete an old backup first) and 429 when it has already started 2 backups in the last 10 minutes; deleted backups still count towards that. is_locked is only applied if you also have the backup.delete permission, and is ignored otherwise.

Parameters

Start a backup: parameters
NameTypeDescription
serverrequiredstringThe server's 8-character identifier, as shown in the panel, or its full UUID.

Body

Start a backup: request body
NameTypeDescription
namestring | nullA name for the backup. Defaults to Backup at <date and time>.
is_lockedboolean | nullLock the backup so it cannot be deleted until it is unlocked. Needs the backup.delete permission.
ignoredstring | nullFiles and folders to leave out, one pattern per line in .gitignore syntax. At most 32 KiB, 256 patterns and 16 * wildcards per pattern. When empty, the node uses the .backupignore file in the server's root, if there is one.

Example

curl -X POST "https://sillydev.co.uk/panel/api/client/servers/1a7ce997/backups" \
  -H "Authorization: Bearer $SILLYDEV_API_KEY" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{"name":"Before discord.py upgrade","is_locked":false,"ignored":"node_modules\n*.log"}'

Response 200The backup, now in progress.

{
    "object": "backup",
    "attributes": {
        "uuid": "0f2a6c1e-8d3b-4f7a-9c5e-2b1d4e6f8a90",
        "is_successful": false,
        "is_locked": false,
        "name": "Before discord.py upgrade",
        "ignored_files": [
            "node_modules",
            "*.log"
        ],
        "checksum": null,
        "bytes": 0,
        "created_at": "2026-10-10T12:00:00+00:00",
        "completed_at": null
    }
}
Every field in the response
Start a backup: response
NameTypeDescription
objectrequiredstring
attributesrequiredobject
attributes.uuidrequiredstring (uuid)The backup's ID, used in the URLs of the other backup endpoints.
attributes.is_successfulrequiredbooleanTrue once the backup has finished successfully. False while it is in progress (completed_at is null) and when it failed.
attributes.is_lockedrequiredbooleanA locked backup cannot be deleted.
attributes.namerequiredstring
attributes.ignored_filesrequiredarray of stringThe ignore patterns given when the backup was made, one per item.
attributes.checksumrequiredstring | nullThe archive's checksum as <algorithm>:<hex>, e.g. sha1:.... Null until it succeeds.
attributes.bytesrequiredintegerThe archive's size in bytes. 0 until it completes.
attributes.created_atrequiredstring (date-time)
attributes.completed_atrequiredstring (date-time) | nullWhen the backup finished, successfully or not. Null while in progress.

Errors

  • 400 The server has reached its backup limit, or the node refused the ignore list.
  • 401 No API key was sent, or it is wrong, expired or deleted.
  • 403 The key is valid but may not do this: it lacks the permission or account scope, it is limited to other servers or IP addresses, or the account may not do it at all.
  • 404 There is no such resource, or the key cannot see it. Features that are switched off answer 404 too.
  • 409 The resource is busy or in a state that does not allow this right now.
  • 422 Some fields were missing or invalid. There is one error per problem, and meta.source_field names the field.
  • 429 Too many requests. Wait for the number of seconds in the Retry-After header, then try again.

Get a backup

GET/servers/{server}/backups/{backup}

Permission backup.read

Returns one backup. Poll this to see when a backup in progress finishes: completed_at is set and is_successful says whether it worked.

Parameters

Get a backup: parameters
NameTypeDescription
serverrequiredstringThe server's 8-character identifier, as shown in the panel, or its full UUID.
backuprequiredstring (uuid)The backup's UUID, as uuid in the backup's attributes.

Example

curl "https://sillydev.co.uk/panel/api/client/servers/1a7ce997/backups/{backup}" \
  -H "Authorization: Bearer $SILLYDEV_API_KEY" \
  -H "Accept: application/json"

Response 200The backup.

{
    "object": "backup",
    "attributes": {
        "uuid": "0f2a6c1e-8d3b-4f7a-9c5e-2b1d4e6f8a90",
        "is_successful": true,
        "is_locked": true,
        "name": "Before discord.py upgrade",
        "ignored_files": [
            "node_modules",
            "*.log"
        ],
        "checksum": "sha1:3f786850e387550fdab836ed7e6dc881de23001b",
        "bytes": 5242880,
        "created_at": "2026-10-10T12:00:00+00:00",
        "completed_at": "2026-10-10T12:00:41+00:00"
    }
}
Every field in the response
Get a backup: response
NameTypeDescription
objectrequiredstring
attributesrequiredobject
attributes.uuidrequiredstring (uuid)The backup's ID, used in the URLs of the other backup endpoints.
attributes.is_successfulrequiredbooleanTrue once the backup has finished successfully. False while it is in progress (completed_at is null) and when it failed.
attributes.is_lockedrequiredbooleanA locked backup cannot be deleted.
attributes.namerequiredstring
attributes.ignored_filesrequiredarray of stringThe ignore patterns given when the backup was made, one per item.
attributes.checksumrequiredstring | nullThe archive's checksum as <algorithm>:<hex>, e.g. sha1:.... Null until it succeeds.
attributes.bytesrequiredintegerThe archive's size in bytes. 0 until it completes.
attributes.created_atrequiredstring (date-time)
attributes.completed_atrequiredstring (date-time) | nullWhen the backup finished, successfully or not. Null while in progress.

Errors

  • 401 No API key was sent, or it is wrong, expired or deleted.
  • 403 The key is valid but may not do this: it lacks the permission or account scope, it is limited to other servers or IP addresses, or the account may not do it at all.
  • 404 There is no such resource, or the key cannot see it. Features that are switched off answer 404 too.
  • 409 The resource is busy or in a state that does not allow this right now.

Delete a backup

DELETE/servers/{server}/backups/{backup}

Permission backup.delete

Deletes a backup and its archive. This cannot be undone. A locked backup that completed successfully cannot be deleted (400) until it is unlocked with toggleBackupLock; failed backups can always be deleted.

Parameters

Delete a backup: parameters
NameTypeDescription
serverrequiredstringThe server's 8-character identifier, as shown in the panel, or its full UUID.
backuprequiredstring (uuid)The backup's UUID, as uuid in the backup's attributes.

Example

curl -X DELETE "https://sillydev.co.uk/panel/api/client/servers/1a7ce997/backups/{backup}" \
  -H "Authorization: Bearer $SILLYDEV_API_KEY" \
  -H "Accept: application/json"

Response 204Done. There is no response body.

Errors

  • 400 The backup is locked.
  • 401 No API key was sent, or it is wrong, expired or deleted.
  • 403 The key is valid but may not do this: it lacks the permission or account scope, it is limited to other servers or IP addresses, or the account may not do it at all.
  • 404 There is no such resource, or the key cannot see it. Features that are switched off answer 404 too.
  • 409 The resource is busy or in a state that does not allow this right now.

Get a download link for a backup

GET/servers/{server}/backups/{backup}/download

Permission backup.download

Returns a signed URL from which the backup's .tar.gz archive can be downloaded. This is step one of two: then send a plain GET to the returned URL, with no API key. For backups kept on the node, the URL is on the node, works once and expires after 15 minutes. For backups kept in S3 storage, it is a pre-signed S3 URL that expires after 5 minutes.

Only ask for the link once the backup has completed successfully. Asking for it is recorded in the server's activity log.

Parameters

Get a download link for a backup: parameters
NameTypeDescription
serverrequiredstringThe server's 8-character identifier, as shown in the panel, or its full UUID.
backuprequiredstring (uuid)The backup's UUID, as uuid in the backup's attributes.

Example

curl "https://sillydev.co.uk/panel/api/client/servers/1a7ce997/backups/{backup}/download" \
  -H "Authorization: Bearer $SILLYDEV_API_KEY" \
  -H "Accept: application/json"

Response 200A download link for the backup.

{
    "object": "signed_url",
    "attributes": {
        "url": "https://node1.sillydev.co.uk:8080/download/backup?token=eyJhbGciOi..."
    }
}
Every field in the response
Get a download link for a backup: response
NameTypeDescription
objectrequiredstring
attributesrequiredobject
attributes.urlrequiredstring (uri)Where to download the archive: a single-use URL on the node valid for 15 minutes, or a pre-signed S3 URL valid for 5 minutes.

Errors

  • 400 The request could not be carried out as sent. detail says why.
  • 401 No API key was sent, or it is wrong, expired or deleted.
  • 403 The key is valid but may not do this: it lacks the permission or account scope, it is limited to other servers or IP addresses, or the account may not do it at all.
  • 404 There is no such resource, or the key cannot see it. Features that are switched off answer 404 too.
  • 409 The resource is busy or in a state that does not allow this right now.

Lock or unlock a backup

POST/servers/{server}/backups/{backup}/lock

Permission backup.delete

Flips the backup's lock: a locked backup becomes unlocked and an unlocked one becomes locked. A locked backup cannot be deleted. There is no body; read is_locked in the response to see the new state.

Parameters

Lock or unlock a backup: parameters
NameTypeDescription
serverrequiredstringThe server's 8-character identifier, as shown in the panel, or its full UUID.
backuprequiredstring (uuid)The backup's UUID, as uuid in the backup's attributes.

Example

curl -X POST "https://sillydev.co.uk/panel/api/client/servers/1a7ce997/backups/{backup}/lock" \
  -H "Authorization: Bearer $SILLYDEV_API_KEY" \
  -H "Accept: application/json"

Response 200The backup with its new lock state.

{
    "object": "backup",
    "attributes": {
        "uuid": "0f2a6c1e-8d3b-4f7a-9c5e-2b1d4e6f8a90",
        "is_successful": true,
        "is_locked": true,
        "name": "Before discord.py upgrade",
        "ignored_files": [
            "node_modules",
            "*.log"
        ],
        "checksum": "sha1:3f786850e387550fdab836ed7e6dc881de23001b",
        "bytes": 5242880,
        "created_at": "2026-10-10T12:00:00+00:00",
        "completed_at": "2026-10-10T12:00:41+00:00"
    }
}
Every field in the response
Lock or unlock a backup: response
NameTypeDescription
objectrequiredstring
attributesrequiredobject
attributes.uuidrequiredstring (uuid)The backup's ID, used in the URLs of the other backup endpoints.
attributes.is_successfulrequiredbooleanTrue once the backup has finished successfully. False while it is in progress (completed_at is null) and when it failed.
attributes.is_lockedrequiredbooleanA locked backup cannot be deleted.
attributes.namerequiredstring
attributes.ignored_filesrequiredarray of stringThe ignore patterns given when the backup was made, one per item.
attributes.checksumrequiredstring | nullThe archive's checksum as <algorithm>:<hex>, e.g. sha1:.... Null until it succeeds.
attributes.bytesrequiredintegerThe archive's size in bytes. 0 until it completes.
attributes.created_atrequiredstring (date-time)
attributes.completed_atrequiredstring (date-time) | nullWhen the backup finished, successfully or not. Null while in progress.

Errors

  • 401 No API key was sent, or it is wrong, expired or deleted.
  • 403 The key is valid but may not do this: it lacks the permission or account scope, it is limited to other servers or IP addresses, or the account may not do it at all.
  • 404 There is no such resource, or the key cannot see it. Features that are switched off answer 404 too.
  • 409 The resource is busy or in a state that does not allow this right now.

Restore a backup

POST/servers/{server}/backups/{backup}/restore

Permission backup.restoreLimited to 3 per 15 minutes per server

Restores the backup's files over the server's files. The request returns at once and the restore runs on the node: the server is stopped, its files are deleted first if truncate is true, and the archive is unpacked. Without truncate, files that are not in the backup are left as they are and files that are in it are overwritten.

While the restore runs, the server's other endpoints answer 409. Only a backup that completed successfully can be restored (400 otherwise). Limited to 3 restores per 15 minutes per server, shared by everyone using it.

Parameters

Restore a backup: parameters
NameTypeDescription
serverrequiredstringThe server's 8-character identifier, as shown in the panel, or its full UUID.
backuprequiredstring (uuid)The backup's UUID, as uuid in the backup's attributes.

Body

Restore a backup: request body
NameTypeDescription
truncaterequiredbooleanDelete all of the server's files before restoring, so the result matches the backup exactly.

Example

curl -X POST "https://sillydev.co.uk/panel/api/client/servers/1a7ce997/backups/{backup}/restore" \
  -H "Authorization: Bearer $SILLYDEV_API_KEY" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{"truncate":true}'

Response 204The restore has started. There is no response body.

Errors

  • 400 The backup is still in progress or failed, or the server is not in a state that allows a restore.
  • 401 No API key was sent, or it is wrong, expired or deleted.
  • 403 The key is valid but may not do this: it lacks the permission or account scope, it is limited to other servers or IP addresses, or the account may not do it at all.
  • 404 There is no such resource, or the key cannot see it. Features that are switched off answer 404 too.
  • 409 The resource is busy or in a state that does not allow this right now.
  • 422 Some fields were missing or invalid. There is one error per problem, and meta.source_field names the field.
  • 429 Too many requests. Wait for the number of seconds in the Retry-After header, then try again.