---
title: "API: backups, restores and clones"
url: https://wpforeman.com/docs/api-backups/
description: "Run backups, change schedules, build .zip downloads, restore and clone."
updated: 2026-10-12
---

# API: backups, restores and clones

## 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](https://wpforeman.com/docs/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": "daily", // monthly | weekly | daily
  "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}

---

WP Foreman: WordPress site management for agencies and freelancers. First site free, no card: https://app.wpforeman.com/signup
