Fiction DraftsWordPress backup plugin

Docs

REST API

Everything the admin screen does is available over REST under the fiction-drafts/v1 namespace. The screen is a React app; it is a client of this API and has no privileged path of its own.

Routes

RoutePurpose
POST/jobsStart a backup.
GET/jobs/{uuid}One job's status and progress.
DELETE/jobs/{uuid}Cancel a running job.
GET/backupsList completed backups and their volumes.
DELETE/backups/{uuid}Delete a completed backup and its archives.
POST/backups/{uuid}/download-tokenMint a download link for one volume.
GET/settingsRead the current settings.
PUT/settingsUpdate the settings.

Two resources, two lifetimes

/jobs and /backups are separate on purpose. A job exists while work is running; a backup exists afterwards, for as long as retention keeps it. DELETE /jobs/{uuid} cancels a run and leaves nothing behind; DELETE /backups/{uuid} removes finished archives from disk.

Starting a backup

# profile: full | database_only | files_only | files_no_media | custom
curl -X POST https://example.com/wp-json/fiction-drafts/v1/jobs \
  -H "X-WP-Nonce: $NONCE" \
  -H "Content-Type: application/json" \
  --cookie "$WP_COOKIES" \
  -d '{"profile":"files_no_media","include_wp_config":false}'

Downloading a volume

Downloads are a two-step exchange, and the second step is single-use.

  1. 1POST /backups/{uuid}/download-token mints a link bound to your user, that backup and one volume.
  2. 2Request the link. It is valid for five minutes and spending it invalidates it — a second request with the same token fails.

Only the sha256 of a token is ever stored, so a backup archive containing wp_options carries no usable download credential. Range requests are honoured, so an interrupted transfer resumes.

Capability

Every route requires manage_options on a single-site install, and manage_network_options whenever is_multisite() is true. There is no unauthenticated route and no public URL for an archive.