Backups
List, create, download and restore backups.
List backups
GET/api/v1/sites/{site_id}/backupsScope backups:read
The site's backups, newest first (automatic daily ones, manual ones and uploaded ones).
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
site_id | path | integer | yes | The site id (see GET /sites). |
state | query | string (one of: Pending, Creating, Ok, Error, Storing) | no | Only backups in this state. |
limit | query | integer | no | Items per page (1-200). Default: 50. |
cursor | query | string | no | The next_cursor value of the previous page. Omit for the first page. |
Example
curl -s "https://app.pbn.ltd/api/v1/sites/123/backups?limit=10" \
-H "Authorization: Bearer $PBN_API_KEY"
import os
import requests
headers = {"Authorization": "Bearer " + os.environ["PBN_API_KEY"]}
r = requests.get("https://app.pbn.ltd/api/v1/sites/123/backups?limit=10", headers=headers, timeout=120)
print(r.status_code, r.json())
const res = await fetch("https://app.pbn.ltd/api/v1/sites/123/backups?limit=10", {
method: "GET",
headers: {Authorization: `Bearer ${process.env.PBN_API_KEY}`}
});
console.log(res.status, await res.json());
Response
200
{
"data": [
{
"id": 88001,
"created_at": "2026-09-19T09:12:00Z",
"type": "Automatic",
"state": "Ok",
"size_bytes": 52428800,
"is_blueprint": false,
"locked": false
}
],
"next_cursor": null,
"has_more": false
}
Errors: not_found, rate_limited, scope_missing, unauthorized
Create a backup now
POST/api/v1/sites/{site_id}/backupsScope backups:write
Takes a full backup (files + database) now, as Create backup in the panel. Follow the job until the backup is Ok.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
site_id | path | integer | yes | The site id (see GET /sites). |
Example
curl -s -X POST "https://app.pbn.ltd/api/v1/sites/123/backups" \
-H "Authorization: Bearer $PBN_API_KEY"
import os
import requests
headers = {"Authorization": "Bearer " + os.environ["PBN_API_KEY"]}
r = requests.post("https://app.pbn.ltd/api/v1/sites/123/backups", headers=headers, timeout=120)
print(r.status_code, r.json())
const res = await fetch("https://app.pbn.ltd/api/v1/sites/123/backups", {
method: "POST",
headers: {Authorization: `Bearer ${process.env.PBN_API_KEY}`}
});
console.log(res.status, await res.json());
Response
202
{
"data": {
"id": 88001,
"created_at": "2026-09-19T09:12:00Z",
"type": "Manual",
"state": "Pending",
"size_bytes": 52428800,
"is_blueprint": false,
"locked": false
}
}
Errors: conflict, not_found, rate_limited, scope_missing, unauthorized
Get one backup
GET/api/v1/sites/{site_id}/backups/{backup_id}Scope backups:read
One backup of the site.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
site_id | path | integer | yes | The site id (see GET /sites). |
backup_id | path | integer | yes | The backup id. |
Example
curl -s "https://app.pbn.ltd/api/v1/sites/123/backups/88001" \
-H "Authorization: Bearer $PBN_API_KEY"
import os
import requests
headers = {"Authorization": "Bearer " + os.environ["PBN_API_KEY"]}
r = requests.get("https://app.pbn.ltd/api/v1/sites/123/backups/88001", headers=headers, timeout=120)
print(r.status_code, r.json())
const res = await fetch("https://app.pbn.ltd/api/v1/sites/123/backups/88001", {
method: "GET",
headers: {Authorization: `Bearer ${process.env.PBN_API_KEY}`}
});
console.log(res.status, await res.json());
Response
200
{
"data": {
"id": 88001,
"created_at": "2026-09-19T09:12:00Z",
"type": "Automatic",
"state": "Ok",
"size_bytes": 52428800,
"is_blueprint": false,
"locked": false
}
}
Errors: not_found, rate_limited, scope_missing, unauthorized
Download link
POST/api/v1/sites/{site_id}/backups/{backup_id}/download-linkScope backups:read
A temporary link to download the backup archive (tar.gz) - valid about 4 hours.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
site_id | path | integer | yes | The site id (see GET /sites). |
backup_id | path | integer | yes | The backup id. |
Example
curl -s -X POST "https://app.pbn.ltd/api/v1/sites/123/backups/88001/download-link" \
-H "Authorization: Bearer $PBN_API_KEY"
import os
import requests
headers = {"Authorization": "Bearer " + os.environ["PBN_API_KEY"]}
r = requests.post("https://app.pbn.ltd/api/v1/sites/123/backups/88001/download-link", headers=headers, timeout=120)
print(r.status_code, r.json())
const res = await fetch("https://app.pbn.ltd/api/v1/sites/123/backups/88001/download-link", {
method: "POST",
headers: {Authorization: `Bearer ${process.env.PBN_API_KEY}`}
});
console.log(res.status, await res.json());
Response
200
{
"data": {
"url": "https://dl.dropboxusercontent.com/...",
"expires_in_seconds": 14400,
"size_bytes": 52428800
}
}
Errors: conflict, not_found, rate_limited, scope_missing, unauthorized, unavailable
Restore a backup
POST/api/v1/sites/{site_id}/backups/{backup_id}/restoreScope backups:write · destructive
Replaces the site's files and database with the backup (as Restore in the panel). Refused while the site is busy, switched off or the plan has expired. Follow the job.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
site_id | path | integer | yes | The site id (see GET /sites). |
backup_id | path | integer | yes | The backup id. |
confirm | body | boolean | yes | Must be true: this action overwrites the site. |
Example
curl -s -X POST "https://app.pbn.ltd/api/v1/sites/123/backups/88001/restore" \
-H "Authorization: Bearer $PBN_API_KEY" \
-H "Content-Type: application/json" \
-d '{"confirm": true}'
import os
import requests
headers = {"Authorization": "Bearer " + os.environ["PBN_API_KEY"]}
r = requests.post("https://app.pbn.ltd/api/v1/sites/123/backups/88001/restore", headers=headers, json={"confirm": True}, timeout=120)
print(r.status_code, r.json())
const res = await fetch("https://app.pbn.ltd/api/v1/sites/123/backups/88001/restore", {
method: "POST",
headers: {Authorization: `Bearer ${process.env.PBN_API_KEY}`, "Content-Type": "application/json"},
body: JSON.stringify({"confirm": true})
});
console.log(res.status, await res.json());
Response
202
{
"data": {
"restoring": true
}
}
Errors: conflict, not_found, payment_required, rate_limited, scope_missing, unauthorized, validation_failed
Delete a backup
DELETE/api/v1/sites/{site_id}/backups/{backup_id}Scope backups:write · destructive
Deletes a backup. A backup that a blueprint uses cannot be deleted.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
site_id | path | integer | yes | The site id (see GET /sites). |
backup_id | path | integer | yes | The backup id. |
Example
curl -s -X DELETE "https://app.pbn.ltd/api/v1/sites/123/backups/88001" \
-H "Authorization: Bearer $PBN_API_KEY"
import os
import requests
headers = {"Authorization": "Bearer " + os.environ["PBN_API_KEY"]}
r = requests.delete("https://app.pbn.ltd/api/v1/sites/123/backups/88001", headers=headers, timeout=120)
print(r.status_code, r.json())
const res = await fetch("https://app.pbn.ltd/api/v1/sites/123/backups/88001", {
method: "DELETE",
headers: {Authorization: `Bearer ${process.env.PBN_API_KEY}`}
});
console.log(res.status, await res.json());
Response
200
{
"data": {
"deleted": true,
"id": 88001
}
}
Errors: conflict, not_found, rate_limited, scope_missing, unauthorized