API: backups, restores and clones
Run backups, change schedules, build .zip downloads, restore and clone.
Updated Oct 11, 2026
List and run backups
GET /sites/{id}/backups
POST /sites/{id}/backups
GET /backups/{id}
Reading needs read (filter with ?status=failed); running needs backups. Running answers 202. Poll GET /backups/{id} until status is succeeded or failed.
curl -X POST https://app.wpforeman.com/api/v1/sites/12/backups \
-H "Authorization: Bearer YOUR_TOKEN"
{ "data": { "id": 481, "site_id": 12, "trigger": "manual", "status": "queued", "stage": null, ... } }
Storage
GET /storage
Ability: read. Your connected storage: id, provider (gdrive, dropbox, s3), name, status, last_error.
PUT /sites/{id}/backup-storage
Ability: backups. Body: {"connection_id": 3} to keep the site’s backups in that storage, or {"connection_id": null} for WP Foreman storage. Returns 202; the move runs in the background (see Storage options). Restores accept from_copy (a connection id) to restore from the site’s extra copy.
Backup fields: status (queued, running, succeeded, failed, expired = removed by the keep rules), stage (files, database, upload), files_total, bytes_total, files_changed, bytes_changed, tables_total, tables_changed, added_bytes (storage this backup added, after dedup and compression), copy_status (queued, running, succeeded, failed, or null when there is no extra copy) and copied_at, skipped_files, error, timestamps.
Backup settings
GET /sites/{id}/backup-settings
PATCH /sites/{id}/backup-settings
Ability: backups to change. Send only what you’re changing:
{
"enabled": true,
"frequency": "6h", // monthly | weekly | daily | 12h | 6h | 1h
"start_time": "00:17", // your account timezone
"day_of_week": 1, // weekly, 0 = Sunday
"day_of_month": 15, // monthly, 1–28
"exclude_paths": ["wp-content/uploads/videos"],
"exclude_tables": ["wp_wfhits"],
"foreign_tables": "exclude", // include | exclude
"notify": "failures", // failures | all | none
"copy_connection_id": 3 // extra copy to a connected Google Drive / Dropbox, or null
}
Download as .zip
POST /backups/{id}/zip
Ability: backups. Starts building the .zip (202) or returns the ready one (200) with download_url and expires_at. Call again to poll. The download link itself needs a signed-in browser.
Restore
POST /backups/{id}/restore
Ability: restore. Body:
{ "scope": "full" } // whole site
{ "scope": "files" } // files only
{ "scope": "database" } // database only
{ "scope": "paths", "paths": ["wp-content/uploads/2026/10/logo.png"] }
// optional: "include_wp_config": true
Answers 202 with a restore record. Poll GET /restores/{id}; stage moves through safety, download, files, database, finish (clones also pass through replace while URLs are updated). safety_backup_id is the backup taken just before, for undoing.
Clone to another site
POST /backups/{id}/clone
Ability: restore. Body: { "target_site_id": 15 }. The destination must be connected with plugin 0.5.0+. URLs and table prefixes are fixed automatically; rows_replaced reports how many database rows had URLs updated.
Restore history
GET /sites/{id}/restores
GET /restores/{id}
Thanks. If something was missing, tell us what.