For AI agents: markdown of this page — /docs-content-en/infra/database/backups.md documentation index — /llms.txt
List database backups
GET /v1/infra/servers/:id/db/backups
Returns backups of the application's SQLite database from newest to oldest and the state of the latest database restore. The list is read from the platform history, so the request does not wake the host and does not access the container.
Parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
Parameterid (path) |
Typestring (UUID) | Requiredyes | Default— | DescriptionID of an application with kind equal to GALAXY_APP. List: GET /v1/infra/servers |
Parameterlimit (query) |
Typenumber | Requiredno | Default50 |
DescriptionBackups per page, from 1 to 100 |
Parametercursor (query) |
Typestring | Requiredno | Default— | DescriptionThe data.nextCursor value from the previous response, unchanged. Up to 1024 characters: Latin letters, digits, - and _ |
ParametersourceAppId (query) |
Typestring | Requiredno | Defaultthe id value |
DescriptionID of another application in the same Bitrix24 account whose backups to show, including a deleted one. List: GET /v1/infra/servers; the ID of a deleted application is the sourceAppId field of its backups. If the key has no access to this application's data or no such application exists, data.items comes back empty rather than as an error |
Pagination. Backups are ordered by createdAt, with ties broken by id, both descending. There is no page number: request the next page with cursor equal to data.nextCursor. A null value in data.nextCursor means the end of the list. The cursor is valid only for the same application and the same sourceAppId. The response does not contain the total number of backups.
Examples
curl — personal key
curl "https://vibecode.bitrix24.com/v1/infra/servers/APP_ID/db/backups?limit=3" \
-H "X-Api-Key: YOUR_API_KEY"
curl — OAuth application
curl "https://vibecode.bitrix24.com/v1/infra/servers/APP_ID/db/backups?limit=3" \
-H "X-Api-Key: YOUR_APP_KEY" \
-H "Authorization: Bearer USER_SESSION_TOKEN"
JavaScript — personal key
const res = await fetch(
`https://vibecode.bitrix24.com/v1/infra/servers/${appId}/db/backups?limit=3`,
{ headers: { 'X-Api-Key': 'YOUR_API_KEY' } }
)
const { success, data, error } = await res.json()
if (!success) throw new Error(`${error.code}: ${error.message}`)
for (const copy of data.items) {
console.log(copy.id, copy.triggerType, copy.status, copy.expiresAt)
}
if (data.restore) {
console.log('Restore:', data.restore.status, data.restore.phase)
}
// Next page: pass data.nextCursor to the cursor parameter unchanged
JavaScript — OAuth application
const res = await fetch(
`https://vibecode.bitrix24.com/v1/infra/servers/${appId}/db/backups?limit=3`,
{
headers: {
'X-Api-Key': 'YOUR_APP_KEY',
'Authorization': 'Bearer USER_SESSION_TOKEN',
},
}
)
const { success, data, error } = await res.json()
if (!success) throw new Error(`${error.code}: ${error.message}`)
Response fields
| Field | Type | Description |
|---|---|---|
Fieldsuccess |
Typeboolean | Descriptiontrue on success |
Fielddata.items |
Typearray | DescriptionDatabase backups on the current page |
Fielddata.items[].id |
Typestring | DescriptionBackup ID. Pass it in backupId when restoring |
Fielddata.items[].sourceAppId |
Typestring (UUID) | DescriptionID of the application whose database the backup was taken from |
Fielddata.items[].platformPaid |
Typeboolean | Descriptiontrue — the platform pays for storing the backup, false — it is stored in the Bitrix24 account's paid storage |
Fielddata.items[].captureScope |
Typestring | DescriptionWhat was backed up. Always SQLITE for database backups |
Fielddata.items[].status |
Typestring | DescriptionQUEUED — the backup is queued, RUNNING — being created, COMPLETED — ready, FAILED — failed, EXPIRED — the retention period has expired, FLAGGED — the backup was stopped and awaits the support team, DELETED — deleted |
Fielddata.items[].triggerType |
Typestring | DescriptionMANUAL — a manual backup, SCHEDULED — daily, PRE_CHANGE — protective, before a database change, PRE_DELETE — before the application is deleted |
Fielddata.items[].file |
Typestring | null | DescriptionPath of the backed-up file relative to the /data volume |
Fielddata.items[].sizeBytes |
Typestring | null | DescriptionBackup size in bytes, a decimal number in a string. null until the backup is complete |
Fielddata.items[].createdAt |
Typestring | DescriptionTime the backup was queued, ISO 8601 in UTC |
Fielddata.items[].completedAt |
Typestring | null | DescriptionTime the backup completed, ISO 8601 in UTC. null until the backup is complete |
Fielddata.items[].expiresAt |
Typestring | null | DescriptionEnd of the retention period, ISO 8601 in UTC. null until the backup is complete |
Fielddata.items[].errorCode |
Typestring | null | DescriptionFailure cause for a backup with status FAILED: APP_DB_BUSY, APP_DB_WAL_CLOSED, APP_DB_BACKUP_TIMEOUT, APP_DB_CORRUPT, APP_DB_TOOL_UNAVAILABLE, APP_DB_BACKUP_INVALID. null for causes without a public code |
Fielddata.nextCursor |
Typestring | null | DescriptionCursor of the next page. null — there are no more pages |
Fielddata.restore |
Typeobject | null | DescriptionRestore of this application's database: the one in progress, or, if there is none, the latest. null if the application's database has never been restored. Does not depend on sourceAppId |
Fielddata.restore.restoreId |
Typestring | DescriptionRestore ID from the POST /db/restore response |
Fielddata.restore.backupId |
Typestring | DescriptionID of the backup the database is restored from |
Fielddata.restore.targetAppId |
Typestring (UUID) | DescriptionID of the application whose database is being restored |
Fielddata.restore.sourceAppId |
Typestring (UUID) | DescriptionID of the application whose database the backup was taken from |
Fielddata.restore.status |
Typestring | DescriptionQUEUED — queued, RUNNING — in progress, COMPLETED — the database was replaced, FAILED — the restore failed |
Fielddata.restore.phase |
Typestring | null | DescriptionRestore step. Normal order: VALIDATE, PREPARE, PRE_CHANGE, STAGE, STOPPING, SWAPPING, VERIFY, STARTING, CLEANUP. CLEANUP remains after completion, with both COMPLETED and FAILED. ROLLBACK — returning the original file after a failure, RECOVERY_REQUIRED — the restore was stopped and awaits the support team |
Fielddata.restore.errorCode |
Typestring | null | DescriptionFailure cause, for example APP_DB_RESTORE_FAILED. null while there is no failure |
Fielddata.restore.backupCreatedAt |
Typestring | DescriptionCreation time of the source backup, ISO 8601 in UTC |
Fielddata.restore.createdAt |
Typestring | DescriptionTime the restore request was accepted, ISO 8601 in UTC |
Fielddata.restore.completedAt |
Typestring | null | DescriptionCompletion time, ISO 8601 in UTC. null while the restore is in progress |
Response example
First page of three backups (?limit=3), no restores so far:
{
"success": true,
"data": {
"restore": null,
"items": [
{
"id": "9e4d2c1b-6a3f-4b8e-a7d5-0c1f2e3d4b5a",
"sourceAppId": "5c0e8f2a-3d1b-4a7e-9f60-2b8c4d1e7a93",
"platformPaid": false,
"captureScope": "SQLITE",
"status": "COMPLETED",
"triggerType": "MANUAL",
"file": "app.db",
"sizeBytes": "937",
"createdAt": "2026-10-20T08:26:17.942Z",
"completedAt": "2026-10-20T08:28:00.046Z",
"expiresAt": "2026-10-27T08:28:00.046Z",
"errorCode": null
},
{
"id": "1f7a3b9c-2e4d-4c6a-8b0e-5d9f7a1c3e2b",
"sourceAppId": "5c0e8f2a-3d1b-4a7e-9f60-2b8c4d1e7a93",
"platformPaid": false,
"captureScope": "SQLITE",
"status": "COMPLETED",
"triggerType": "PRE_CHANGE",
"file": "app.db",
"sizeBytes": "937",
"createdAt": "2026-10-20T08:23:15.565Z",
"completedAt": "2026-10-20T08:25:00.061Z",
"expiresAt": "2026-10-27T08:25:00.061Z",
"errorCode": null
},
{
"id": "4b8c6d2e-9f1a-4e3b-b5c7-7a2d0e6f8c19",
"sourceAppId": "5c0e8f2a-3d1b-4a7e-9f60-2b8c4d1e7a93",
"platformPaid": false,
"captureScope": "SQLITE",
"status": "COMPLETED",
"triggerType": "PRE_CHANGE",
"file": "app.db",
"sizeBytes": "937",
"createdAt": "2026-10-20T08:21:47.863Z",
"completedAt": "2026-10-20T08:23:00.087Z",
"expiresAt": "2026-10-27T08:23:00.087Z",
"errorCode": null
}
],
"nextCursor": "eyJjcmVhdGVkQXQiOiIyMDI2In0"
}
}
After a restore has completed (?limit=2). The first item is the protective backup the platform saved before replacing the file:
{
"success": true,
"data": {
"restore": {
"restoreId": "cm2r7x4k10003qv8n5d2b6w1z",
"backupId": "9e4d2c1b-6a3f-4b8e-a7d5-0c1f2e3d4b5a",
"targetAppId": "5c0e8f2a-3d1b-4a7e-9f60-2b8c4d1e7a93",
"sourceAppId": "5c0e8f2a-3d1b-4a7e-9f60-2b8c4d1e7a93",
"status": "COMPLETED",
"phase": "CLEANUP",
"errorCode": null,
"backupCreatedAt": "2026-10-20T08:26:17.942Z",
"createdAt": "2026-10-20T08:28:12.755Z",
"completedAt": "2026-10-20T08:40:30.029Z"
},
"items": [
{
"id": "7d3e1a5b-8c2f-4d9a-9e6b-3f0a4c7d2e81",
"sourceAppId": "5c0e8f2a-3d1b-4a7e-9f60-2b8c4d1e7a93",
"platformPaid": false,
"captureScope": "SQLITE",
"status": "COMPLETED",
"triggerType": "PRE_CHANGE",
"file": "app.db",
"sizeBytes": "937",
"createdAt": "2026-10-20T08:30:30.278Z",
"completedAt": "2026-10-20T08:32:00.080Z",
"expiresAt": "2026-10-27T08:32:00.080Z",
"errorCode": null
},
{
"id": "9e4d2c1b-6a3f-4b8e-a7d5-0c1f2e3d4b5a",
"sourceAppId": "5c0e8f2a-3d1b-4a7e-9f60-2b8c4d1e7a93",
"platformPaid": false,
"captureScope": "SQLITE",
"status": "COMPLETED",
"triggerType": "MANUAL",
"file": "app.db",
"sizeBytes": "937",
"createdAt": "2026-10-20T08:26:17.942Z",
"completedAt": "2026-10-20T08:28:00.046Z",
"expiresAt": "2026-10-27T08:28:00.046Z",
"errorCode": null
}
],
"nextCursor": "eyJjcmVhdGVkQXQiOiIyMDI2In1"
}
}
Error response example
400 — the cursor was modified or issued for a different source application:
{
"success": false,
"error": {
"code": "APP_DB_INVALID_FILE",
"message": "Invalid database file inside /data"
}
}
Errors
| HTTP | Code | Description |
|---|---|---|
| HTTP400 | CodeAPP_DB_INVALID_FILE |
DescriptionThe cursor value cannot be read as a cursor of this list: it was modified manually or issued for a different sourceAppId. The message text refers to a file, but in this method the code refers to the cursor. Restart pagination without cursor |
| HTTP400 | CodeVALIDATION_ERROR |
DescriptionAn unknown query parameter, limit outside the 1–100 range, invalid characters in cursor or sourceAppId |
| HTTP400 | CodeAPP_DB_UNSUPPORTED_PLACEMENT |
DescriptionThe application is not hosted in Galaxy |
| HTTP401 | CodeMISSING_API_KEY |
DescriptionThe X-Api-Key header is missing |
| HTTP401 | CodeINVALID_API_KEY |
DescriptionThe key is not recognized |
| HTTP403 | CodeINFRA_SCOPE_REQUIRED |
DescriptionThe key lacks the vibe:infra scope |
| HTTP403 | CodeAPP_DB_DISABLED |
DescriptionApplication database access is not enabled for the portal |
| HTTP404 | CodeNOT_FOUND |
DescriptionThere is no application with this id on the portal, it was deleted or the key has no access to it |
| HTTP429 | CodeRATE_LIMITED |
DescriptionThe read request limit for the portal was exceeded — Limits. The wait time is in the Retry-After header |
| HTTP503 | CodeAPP_DB_TOOL_UNAVAILABLE |
DescriptionThe platform temporarily cannot serve this application's database. Retry the request later |
| HTTP503 | Codeuser_self_deletion_pending |
DescriptionThe key owner requested deletion of their account on the portal. Access is restored once the deletion is cancelled |
Full list of common API errors — Errors.
Known specifics
Waiting for a backup and a restore. Check whether a manual backup or a restore has completed by calling this list again: a backup — by the status of the item with the matching id, a restore — by data.restore with the matching restoreId. For typical durations, see Create a database backup and Restore the database from a backup. Each poll counts against the read request limit, which is shared by all database reads in the Bitrix24 account.
Stopped operations that need support. A backup with status FLAGGED and a restore in the RECOVERY_REQUIRED phase do not complete on their own: in this case the restore remains in status RUNNING. Repeated polls do not change the response — contact support and give the backup id or the restoreId.