Docs › Connect an agent or use the API
REST API reference
Routes, scopes, headers and errors.
Base address: https://YOUR-SITE/wp-json/wpbr/v1. Authentication is HTTP Basic with the connection’s username and password. The machine-readable description is GET /openapi.
Starting a run is switched off in this release: starting a run, and advancing a run that is still replacing, answer 403 wpbr_writes_disabled (the error’s data.reason is not_enabled or kill_switch). Rolling back and cancelling an existing run work either way, so recovery is never held up. Reading, staging and preparing plans work.
Scopes and headers
Scopes: read (always), reports, prepare, execute, rollback. A connection holds only the scopes an administrator gave it. Send an Idempotency-Key header (8–128 characters) where marked: the same key with the same request returns the same answer, and with a different request is refused. Every answer carries X-WPBR-Request-Id; a rate-limited answer carries Retry-After.
Prepare a plan
curl -X POST https://YOUR-SITE/wp-json/wpbr/v1/plans \
-u "CONNECTION_USER:CONNECTION_PASSWORD" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: price-list-2026-10" \
-d '{"items":[{"target_id":"TARGET_ID","staged_file_id":"STAGED_FILE_ID"}]}'
A plan changes nothing on the site. Whether it then waits for approval follows the site’s approval setting and the connection’s mode.
Routes
| Method and path | Scope | What it does |
|---|---|---|
| GET /capabilities | read | Versions, whether new work may start (and why not), and what this connection may do. |
| GET /integrations/me | read | The calling connection: label, status and policy. Never a secret. |
| GET /openapi | read | The OpenAPI 3.1 description of the routes that exist. |
| GET /sites | read | The sites this connection may address. |
| GET /targets | read | Files the pages point at, in the places this connection is allowed. Empty until an administrator allows places. |
| GET /targets/{id} | read | One target: file facts (never a path) and who else points at the same file. |
| GET /targets/{id}/history | read | What the plugin has done to the target’s post, newest first. |
| POST /staged-files | prepare | Stage a replacement file: upload it (multipart field “file”) or name a Media Library attachment_id. |
| GET /staged-files/{id} | read | One staged file: facts only. |
| DELETE /staged-files/{id} | prepare | Remove a staged file no open plan uses. |
| POST /plans | prepare | Prepare a plan from explicit (target_id, staged_file_id) pairs. Needs an Idempotency-Key. |
| GET /plans/{id} | read | A plan, checked against the site as it is now (valid, stale or expired), with its preview. |
| POST /plans/{id}/cancel | prepare | Cancel a plan that has not been executed. |
| POST /plans/{id}/approval-request | prepare | Ask a person to approve the plan. There is no endpoint to approve. |
| GET /runs | read | Runs, newest first, with counts by state. |
| POST /plans/{id}/runs | execute | Start a run from an approved plan. Refused while automated writes are off. Needs an Idempotency-Key. |
| POST /runs/{id}/advance | execute | Take one step of a run. Safe to repeat. Refused for a run that is still replacing while automated writes are off. |
| POST /runs/{id}/cancel | execute | Stop a run before its next row. Repeating it is harmless; works while automated writes are off. |
| POST /runs/{id}/rollback | rollback | Put a finished or cancelled run’s files back, only over the bytes it wrote. Needs the rollback scope; works while automated writes are off. Needs an Idempotency-Key. |
| GET /runs/{id} | read | One run with the outcome of each row. No file paths. |
| GET /runs/{id}/report | reports | Totals by outcome and the activity log of a run. |
Errors
Every error has a code (prefixed wpbr_), a worded message, data.status and data.request_id.
| Code | HTTP | Meaning |
|---|---|---|
| wpbr_unauthenticated | 401 | Authentication is required. |
| wpbr_integration_inactive | 403 | This connection is revoked, expired or disabled. |
| wpbr_privileged_user | 403 | A login bound to an administrator is refused. |
| wpbr_scope_denied | 403 | This connection does not hold the scope this needs. |
| wpbr_addon_required | 402 | This needs the AI Assistant, API and MCP add-on. |
| wpbr_writes_disabled | 403 | Automated writes are not enabled on this site (data.reason: not_enabled or kill_switch). |
| wpbr_idempotency_key_required | 400 | An Idempotency-Key header (8–128 characters) is required. |
| wpbr_idempotency_key_reuse | 409 | That key was used with a different request. |
| wpbr_plan_stale | 409 | Something the plan was built on has changed. |
| wpbr_plan_expired | 410 | The plan has expired. |
| wpbr_approval_required | 409 | A person must approve this plan first. |
| wpbr_unsupported_engine | 503 | This needs a newer WP Bulk Replace (Free). |
| wpbr_rate_limited | 429 | Too many requests. Retry after the time given. |
| wpbr_run_in_progress | 429 | A run is already in progress. Retry later. |
Identifiers (tgt_, stg_, pln_, apr_, run_N, row_N) are opaque. No answer contains a server path or a secret; text that comes from your site is listed separately so a client can treat it as data, not instructions.