Public API and chat apps

You can drive a Reaver dashboard from a script, n8n, or a chat app (Claude, Cursor, LibreChat, Open WebUI) without using the browser. Those clients start the same backups, restores, and exports as the Run button.

AI clients that speak MCP should use the built-in MCP server at /api/v1/mcp (all paid plans, off until you enable it). The MCP server is the same control plane as this API. Setup and permissions: MCP Server for AI Agents.

There are three ways things talk to a dashboard. Do not mix them.

Who How they authenticate Can start jobs?
You, in a script or chat app A token that starts with rv2_ (or sign-in from the chat app) Yes — same as the UI
Backup agents on WordPress hosts Agent id + secret No. They only pick up and report work
You, in the browser Login cookie Yes

A full technical spec lives on your install at GET /api/v1/openapi.json (token required). In the dashboard: Security → Guide.

Create a token

Security → API tokens. Name it, pick a permission, optionally set an expiry. Copy the secret immediately — it is shown once. Revoke from the same card.

Permission Can do
read Look at sites, jobs, snapshots, schedules, agent status, destination names
backup Everything in read, plus choose storage, start backups, run a schedule now, check the host
restore Everything in backup, plus restore and export. Restore must repeat the site name in confirm_slug. Export queues an archive; it does not return the file
admin Tokens, chat-app toggle, outbound webhooks. Adding destinations and pairing agents stays in the UI

Each level includes the one above it. A User account can create read or backup tokens, not restore or admin.

Send the token as:

Authorization: Bearer rv2_…

No cookies. Other websites cannot call this API from a browser. Failures look like { "ok": false, "error": { "code", "message" } }. Responses never include destination keys, restic passwords, or agent secrets.

Names used in requests

Use these field names. A display name such as shop.example.com is mapped to the site slug.

  • site_slug — the site
  • job_id — a job number
  • dest_id — where to store data (local, or an Off-Site destination)
  • snapshot_id — one restic snapshot
  • schedule_id / webhook_id / agent_id

Work started here is labeled api:<token name> on the Jobs page.

What you can call

Everything is under /api/v1. On start-work requests, send an Idempotency-Key header (any unique string) so a retry does not create a second job. dry_run: true checks without starting work.

Call What it does
GET / What this install can do
GET /me This token’s name and permission
GET /sites · GET /sites/{site_slug} List or show a site
GET /sites/{site_slug}/snapshots Snapshots
POST /sites/{site_slug}/repo Choose storage and encryption (none or encrypted)
GET /jobs · GET /jobs/{job_id} List or watch a job
GET /agents · GET /schedules · GET /destinations Fleet, schedules, destination names
POST /backups/validate · POST /backups Check, then start a backup
POST /backups/all Start a backup for every site
POST /schedules/{schedule_id}/run Run a schedule now
POST /preflight Ask the agent to check the host (disk, dest, optional MySQL)
POST /restores Restore. Send confirm_slug equal to the site slug
POST /exports Queue an archive
GET/POST /webhooks List or create a webhook (admin)
POST /mcp Chat-app connection (off until you enable it)

Typical backup

  1. List sites if you need a slug.
  2. Check the backup. If the response asks you to pick a destination or set encryption, do that first.
  3. Optionally run a host check (POST /preflight) and wait for that job.
  4. Start the backup. Watch GET /jobs/{job_id} until it is completed or failed. Queued is not finished.
export REAVER_URL="https://reaver.example.com"
export REAVER_TOKEN="rv2_…"

curl -sS -H "Authorization: Bearer $REAVER_TOKEN" "$REAVER_URL/api/v1/sites"

curl -sS -H "Authorization: Bearer $REAVER_TOKEN" -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"site_slug":"my-site","dest_id":"local"}' "$REAVER_URL/api/v1/backups"

Restore is the same shape plus snapshot_id and confirm_slug equal to the site slug.

Host check (preflight)

Checking a backup in the API only looks at dashboard records. A preflight job asks the agent to check the real machine: site path, destination reachable, free disk on local/SSH (S3/B2 skip disk), optional MySQL from wp-config.php. It is not a backup and does not send backup emails.

Common errors

Code Meaning
needs_choice Pick a destination. The response includes the list
needs_config Choose storage and encryption first
confirm_required Restore is missing a matching confirm_slug
license The plan does not allow this (restore still works when expired)
agent_offline The site’s agent has not checked in
scope_denied This token’s permission is too low

The API does not download archive files, add destinations, pair agents, or destroy repositories. Use the dashboard for those.

Connect a chat app

Reaver V2 ships a built-in MCP server for AI agents. Full guide: MCP Server for AI Agents.

Security → MCP server (off until you turn it on). Then add this URL in Claude, Cursor, LibreChat, Open WebUI, or LM Studio:

https://your-dashboard.example/api/v1/mcp

The app can then list sites, start backups, and check jobs — limited by the token’s permission. Point the app at this URL, not at /openapi.json.

If the app lets you paste a header instead of signing in:

{
  "mcpServers": {
    "reaver-backup": {
      "url": "https://reaver.example.com/api/v1/mcp",
      "headers": {
        "Authorization": "Bearer rv2_…"
      }
    }
  }
}

Sign-in from a chat app

Most chat apps open a browser and ask you to sign in. That is expected. You sign in to this Reaver dashboard, pick a permission, and Approve. The app receives a token; a new row appears under Security → API tokens. You do not need a third-party login provider.

LibreChat: it builds the return address from DOMAIN_SERVER (default http://localhost:3080). If you open LibreChat at a LAN IP or hostname, set both DOMAIN_SERVER and DOMAIN_CLIENT to that URL and restart. HTTP on the LAN is fine. The Reaver approve page can also send this one login back to the address you actually use.

After the first approve, LibreChat sometimes opens a second connection without the token. Connect once from that host; Reaver reuses the token from that same IP for the chat-app URL only. Revoke the token row to drop it.

Get notified when a job finishes

Security → Outbound webhooks, or POST /api/v1/webhooks with an admin token.

Public internet URLs must be HTTPS. HTTP is allowed to localhost and your LAN. The signing secret (whsec_…) is shown once. Deliveries are queued so they never slow down agents.

X-Reaver-Event: backup.completed
X-Reaver-Delivery-Id: whd_…
X-Reaver-Timestamp: 1710000000
X-Reaver-Signature: sha256=<hex>

The signature is HMAC-SHA256 of timestamp + '.' + delivery_id + '.' + raw_body. Three HTTP 401 or 410 responses in a row disable the webhook.

Events: backup.queued / started / completed / failed; restore.started / completed / failed; job.completed / job.failed; agent.connected / agent.offline.

Nginx

The installer nginx template already routes /api/v1* and forwards the Authorization header. After you change nginx: sudo nginx -t && sudo systemctl reload nginx.

Agent poll (not for scripts)

Agents authenticate with pairing secrets and call api/jobs.php and related paths. Those URLs can carry restic and destination secrets. Do not use them from n8n or a chat app.

Website APIs (account / license / feedback)

These live on the Reaver marketing site (this website), not on your dashboard. They use a different token than rv2_.

Endpoint Purpose
POST /api/link-license.php Link dashboard to website account; returns plan, limits, api_token
POST /api/verify-license.php Re-check plan/limits
POST /api/encryption-waiver.php Record restic encryption waiver accept
POST /api/feedback.php Product feedback
POST /api/telemetry.php Anonymous product stats (default on; opt out anytime)

License responses include limits.max_sites and limits.max_offsite so the dashboard can enforce quotas locally. Dashboards also send installation_id, optional machine_id, used_sites, and used_offsite so usage is counted across every install on the account.

Encryption waiver

When you accept the restic encryption liability waiver, the linked dashboard posts it here so it is stored on the account. If the website is unreachable, local policy still applies.

POST /api/encryption-waiver.php
Authorization: Bearer <api_token>
Content-Type: application/json

{
  "waiver_version": "restic-encryption-v1",
  "accepted_by": "admin",
  "accepted_at": 1712345678,
  "recovery_ack": true,
  "recovery_ack_at": 1712345678,
  "installation_id": "…",
  "machine_id": "…",
  "install_label": "backup-host",
  "dashboard_version": "0.3.x"
}

Anonymous product stats

Limited, non-identifying heartbeats for product planning. Not license usage. Default on; opt out with anonymous_statistics: false. Prefer schema_version: 2.

Rules: no hostnames, emails, paths, tokens, or error text. Clients fail open — stats never block backups. Details: Configuration and the Privacy Policy.