API Reference
Complete REST API reference for Respira for WordPress, including v1 and v2 endpoints for pages, posts, builders, snapshots, and more.
Overview
Respira for WordPress exposes a comprehensive REST API for managing your WordPress site with duplicate-first safety, builder-aware updates, and fidelity workflows.
This REST API underpins multiple Respira surfaces:
- the standalone Respira MCP server
- the official WordPress Abilities + MCP Adapter integration
- built-in Browser AI/WebMCP
- the curated Elementor Angie bridge
Base URLs
Respira currently exposes two namespaces:
https://your-site.com/wp-json/respira/v1/
https://your-site.com/wp-json/respira/v2/
v1: broad compatibility endpoints used across older and mixed environmentsv2: capability negotiation, fidelity/snapshot flows, and builder patch operations
Browser-auth Angie endpoints use a separate namespace:
https://your-site.com/wp-json/respira/browser/v1/
See Elementor Angie for the browser-auth flow, and WordPress AI Stack Compatibility for the official Abilities/MCP Adapter path.
Capability status endpoint (v2)
Use this endpoint to detect v2 feature support:
GET /wp-json/respira/v2/status
Authentication
Include your API key with every request:
X-Respira-API-Key: respira_your-api-key-here
Site Context
Get site context
Returns comprehensive information about the WordPress site including version, theme, plugins, and detected page builders.
GET /context/site-info
Get theme docs
Returns theme documentation and available template files.
GET /context/theme-docs
Get builder info
Returns information about the active page builder including available modules/widgets.
GET /context/builder-info
Snapshots and fidelity (v2)
Snapshot endpoints support safer compare/restore flows:
GET /snapshots
GET /snapshots/{uuid}
POST /snapshots/diff
POST /snapshots/restore
Builder patch endpoint:
POST /builder/{builder}/patch/{post_id}
Pages
Bind an edit or approval to the reviewed version
Reads and writes for one page return content_version and
content_version_post_id. Treat the version as an opaque string: store it
unchanged and compare for equality only. Do not parse it, sort it, increment it
or construct it yourself.
The current format is v2- followed by 24 lowercase hexadecimal characters,
for example v2-bac62a0329c59755b20bb40e. It is a deterministic hash of the
stored builder payload, page content, title, status and supported SEO fields.
Changing any of those can change the value. An unchanged state keeps the same
value; returning to an earlier state can return an earlier value. It is not a
timestamp, revision counter or proof that the public page head has refreshed.
The format is stable within a plugin minor release line unless the changelog
announces a format change. Plugin 9.2.10 changed the prefix from v1- to v2-
because SEO fields joined the hash. A held v1- token is still checked against
the old content-only material for compatibility. For SEO approval, read a
current v2- token rather than reusing a token from before the upgrade.
Send the version from the page or draft you reviewed on each write:
PUT /wp-json/respira/v2/pages/123
Content-Type: application/json
X-Respira-API-Key: YOUR_KEY
{"expected_version":"v2-bac62a0329c59755b20bb40e","seo":{"description":"Reviewed description"}}
A successful write returns the new version. A duplicate-first write returns the draft's ID and version, because that is where the edit landed. Review that draft, then approve its current version:
POST /wp-json/respira/v2/duplicates/123/approve
Content-Type: application/json
X-Respira-API-Key: YOUR_KEY
{"expected_version":"VERSION_RETURNED_FOR_THE_REVIEWED_DRAFT"}
If it changed, the request returns HTTP 409 respira_version_conflict and
performs no write. A stale or made-up value is refused; an empty or non-text
value is refused. force does not override a version conflict. Read the draft
again and have the changed version reviewed before approving it. Omitting a
version on legacy duplicate approvals provides no version binding.
After an approval, content_version_post_id identifies the live page. Use
that ID when checking the stored result and fetch the public page separately
to verify what visitors receive.
Published content with incomplete SEO
From plugin 9.2.12, approval returns HTTP 200 when the content is live even if
an SEO field fails read-back. Check complete, not only the HTTP status or
success. The response names the fields in warnings and retains the
respira_approve_seo_not_carried code:
{
"success": true,
"published": true,
"complete": false,
"live_post_id": 42,
"warnings": [{
"code": "respira_approve_seo_not_carried",
"fields": [{
"field": "_yoast_wpseo_metadesc",
"where": "yoast_indexable",
"expected": "Reviewed description",
"actual": null
}]
}]
}
This replaces the HTTP 500 response for this partial outcome in 9.2.10 and
9.2.11. Update integrations that relied on that status. A completed approval
returns published: true, complete: true and an empty warnings array.
Version conflicts and permission refusals remain non-2xx. A partial approval
has already changed the public page: do not retry the same approval. Read the
live page and decide whether to repair its SEO through another reviewed draft
or ask an administrator to restore the saved snapshot.
Reviewed menu and redirect changes
Plugin 9.2.13 adds a separate pending-change workflow. A Publish only key can propose, read, approve, reject and undo these changes. Its direct menu and redirect write routes remain forbidden (HTTP 403).
All paths below start at /wp-json/respira/v2. Use your site key in
X-Respira-API-Key. Cookie-authenticated administrators use the WordPress REST
nonce. Records are private and local to this WordPress site.
| Method and path | Result |
|---|---|
GET /pending-changes/target?target[kind]=menu&target[id]=3 | Complete state and target version for one existing classic menu. |
GET /pending-changes/target?target[kind]=redirects | Complete readable redirect list and target version. |
POST /pending-changes | Save exact target, before, after and optional expires_in seconds. No live write. |
GET /pending-changes/{id} | Full proposal, versions, author key/user, creation, expiry, status and receipt. |
POST /pending-changes/{id}/approve | Require expected_version from the proposal that was reviewed. |
POST /pending-changes/{id}/reject | Reject an unexpired proposal without changing the live target. |
POST /pending-changes/{id}/undo | Create a reverse proposal; approve it separately. |
GET /pending-changes?status=pending&page=1&per_page=25 | Paginated site history, optionally filtered by status and target[kind]/target[id]. |
POST /pending-changes/expire | Mark up to 100 expired records per call; repeat while remaining is positive. No live write. |
- Read the target. Copy its entire
stateinto bothbeforeandafter. - Edit only
after. Save{ "target": {"kind":"menu","id":3}, "before": ORIGINAL_STATE, "after": PROPOSED_STATE }. - Read the returned change by its ID. Show the full before/after to the approver
and retain that change's
versionunchanged. - Approve with
{ "expected_version": "VERSION_FROM_THE_REVIEWED_CHANGE" }. - Inspect
published,complete,warnings,appliedandactual_after, then check the public URLs separately.
The pending version (pc1-…) binds the exact proposal, author, site and expiry.
The target_version (pt1-…) binds the live menu or redirect configuration.
Both are opaque strings, distinct from page content_version. Creation refuses
stale before with HTTP 409 respira_version_conflict. Approval returns the same
409 if the reviewed proposal or the live target changed. There is no force
override. A busy target returns 423; an expired proposal returns 410.
Menu v1 edits items: add, update, remove, reorder and parent relationships.
Keep the menu's name, description, theme, configuration and locations unchanged.
Copy every existing item's fields and integer ID. New items use a unique
new:client-reference, configuration: null and consecutive positions starting
at 1; a parent is 0 or another ID/reference in the proposed menu. For a custom
link use type: "custom", object: "custom", object_id: 0 and a safe URL.
Published post links, taxonomy links and post type archives must match their
current URLs. Cycles and missing targets or parents are refused.
Redirect v1 edits rules in the full state, retaining engines unchanged.
Existing IDs are engine-qualified, such as respira:2 or redirection:5.
New rules use new:client-reference, configuration: null, a writable engine
(respira or active redirection), source, target, match (exact or regex),
query mode (ignore, exact or pass), status code, enabled flag and note.
Other redirect managers remain read-only. Unsafe schemes, duplicate sources,
loops and protected WordPress URLs are refused. Use canonical paths; validation
refuses proposals that would need silent normalization.
A complete target snapshot is limited to 1,000 items/rules. A redirect proposal
may change at most 50 rules, with at most 200 native regular expressions.
Oversize or incomplete reads are refused. Default expiry is seven days;
expires_in accepts 1 through 2,592,000 seconds (30 days). List status values are
pending, applying, applied, rejected and expired; per_page is capped
at 100. Expiry preserves history and applied receipts.
Approval reads the target back and stores a durable receipt:
{
"published": true,
"complete": false,
"warnings": [{
"code": "respira_pending_change_not_carried",
"fields": [{"field":"target.items.0.title","where":"stored_target","expected":"Reviewed title","actual":"Filtered title"}]
}],
"applied": {"created":[45],"updated":[],"removed":[],"references":{"new:link":45}}
}
HTTP 200 alone does not mean complete. A partial receipt includes the expected
and actual states, attempted writes and cache purge report. Repeating an applied
approval with the same reviewed version returns that stored receipt without
applying again, including an incomplete receipt. Read it and propose a reviewed
repair or undo. An interrupted applying record refuses blind re-execution;
inspect the live target before recovery.
Undo's before is the current target and its after is the saved prior state.
Review it carefully: restoring that state can also remove changes made since the
original approval. Nothing goes live until the undo's own version is approved.
Recreating deleted entries allocates new engine IDs; the receipt maps those IDs.
Ordinary new entries use engine defaults. Undo retains the saved configuration
for recreated entries, including menu metadata and writable Redirection options;
read-back reports a mismatch if an integration changes that restored state.
Menus can appear throughout a site, so resource approval calls the shared
site-wide cache purge path. cache_purge reports the integrations called; it
does not prove a host/CDN cache was cleared or that a visitor received the new
page. Fetch the public URL to verify it.
The npm server (8.6.8+) exposes wordpress_read_change_target,
wordpress_create_pending_change, wordpress_get_pending_change,
wordpress_list_pending_changes, wordpress_approve_pending_change,
wordpress_reject_pending_change, wordpress_undo_pending_change and
wordpress_expire_pending_changes (also listed with the respira_ prefix).
The native endpoint exposes the same eight operations as respira_wordpress_*.
In wp-admin, proposals appear in Respira → Activity → Approval queue for
individual review.
Create a new page with a Publish only key
From plugin 9.2.12, use the existing creation endpoint:
POST /wp-json/respira/v1/post-types/page/posts
Content-Type: application/json
X-Respira-API-Key: YOUR_KEY
{"type":"page","title":"New page","content":"<h1>Review this page</h1>","status":"draft"}
For this key profile, creation accepts title, content, slug and excerpt. New page drafts include slug and excerpt in their version token, so changing either after review invalidates approval.
status defaults to draft; other statuses and post types are refused.
Author changes, taxonomy creation and arbitrary metadata are refused. Edit
the returned page through PUT /respira/v2/pages/{id} and set its SEO there.
Review it, then call POST /respira/v2/duplicates/{id}/approve with its current
content_version as expected_version. Approval publishes the new page at
the same ID, with approval_mode: "publish_new_page". The version is required
for this path and force-publishing is refused. Direct menu and redirect writes
remain outside this key's permissions; use pending changes for those targets.
List pages
List all pages with optional filtering.
GET /pages
Query parameters:
status- Filter by status (publish, draft, pending)search- Search termpage- Page number for paginationperPage- Items per page
Read page
Get full content of a specific page including meta data and builder information.
GET /pages/{id}
Create page duplicate
Create a duplicate of an existing page for safe editing.
POST /pages/{id}/duplicate
Always use this before making changes to an original page. Edit the duplicate, then approve in WordPress admin (Respira → Approve Edits).
Update page
Update a page. Respira automatically creates a duplicate for safety.
PUT /pages/{id}
Body parameters:
title- New page titlecontent- New page content (HTML)status- Page status (publish, draft, pending)meta- Post meta data
Delete page
Delete a page. Only works on Respira-created duplicates by default.
DELETE /pages/{id}
Posts
List posts
List all blog posts with optional filtering.
GET /posts
Read post
Get full content of a specific post.
GET /posts/{id}
Create post duplicate
Create a duplicate of an existing post for safe editing.
POST /posts/{id}/duplicate
Update post
Update a post. Respira automatically creates a duplicate for safety.
PUT /posts/{id}
Delete post
Delete a post. Only works on Respira-created duplicates by default.
DELETE /posts/{id}
Custom Post Types
List post types
List all registered post types.
GET /post-types
Get post type
Get post type details.
GET /post-types/{type}
List custom posts
List posts of a custom post type.
GET /post-types/{type}/posts
Get custom post
Get custom post details.
GET /post-types/{type}/posts/{id}
Create custom post
Create a new custom post.
POST /post-types/{type}/posts
Update custom post
Update a custom post.
PUT /post-types/{type}/posts/{id}
Delete custom post
Delete a custom post.
DELETE /post-types/{type}/posts/{id}
Page Builder Tools
Extract builder content
Extract structured content from a page builder (Divi, Elementor, Bricks, etc.).
GET /builder/{builder}/pages/{id}/content
Inject builder content
Inject structured content into a page builder.
POST /builder/{builder}/pages/{id}/content
Update module
Update a specific module within a page builder page. Supports finding modules by admin_label, path, or type.
PUT /builder/{builder}/pages/{id}/module
Body parameters:
moduleIdentifier- Object withadmin_label,path, ortypeupdates- Object withcontentand/orattributes
Media
List media
List all media files (images, videos, etc.).
GET /media
Get media
Get single media item details.
GET /media/{id}
Upload media
Upload a media file to WordPress.
POST /media
Body parameters:
file- File content as base64 string, URL, or file pathfilename- Filename for the uploaded filemimeType- MIME type (e.g., image/jpeg)alt- Alt text for imagestitle- Media titlecaption- Media caption
Update media
Update media metadata (title, alt text, caption).
PUT /media/{id}
Delete media
Delete a media file.
DELETE /media/{id}
Menus
List menus
List all navigation menus.
GET /menus
Get menu
Get menu with all items and hierarchy.
GET /menus/{id}
Get menu locations
Get all registered menu locations.
GET /menus/locations
Create menu
Create a new navigation menu.
POST /menus
Update menu
Update a menu.
PUT /menus/{id}
Delete menu
Delete a menu.
DELETE /menus/{id}
Create menu item
Add an item to a menu.
POST /menus/{id}/items
Update menu item
Update a menu item.
PUT /menus/{id}/items/{item_id}
Delete menu item
Delete a menu item.
DELETE /menus/{id}/items/{item_id}
Assign menu location
Assign a menu to a theme location.
POST /menus/{id}/location
Taxonomies
List taxonomies
List all registered taxonomies.
GET /taxonomies
Get taxonomy
Get taxonomy details.
GET /taxonomies/{taxonomy}
List terms
List terms in a taxonomy.
GET /taxonomies/{taxonomy}/terms
Get term
Get term details.
GET /taxonomies/{taxonomy}/terms/{id}
Create term
Create a new term.
POST /taxonomies/{taxonomy}/terms
Update term
Update a term.
PUT /taxonomies/{taxonomy}/terms/{id}
Delete term
Delete a term.
DELETE /taxonomies/{taxonomy}/terms/{id}
Users
List users
List all users with optional filtering.
GET /users
Get user
Get user details by ID.
GET /users/{id}
Create user
Create a new user.
POST /users
Update user
Update user information.
PUT /users/{id}
Delete user
Delete a user.
DELETE /users/{id}
Comments
List comments
List all comments with optional filtering.
GET /comments
Get comment
Get comment details.
GET /comments/{id}
Create comment
Create a new comment.
POST /comments
Update comment
Update a comment.
PUT /comments/{id}
Delete comment
Delete a comment.
DELETE /comments/{id}
Options
List options
List WordPress options (with optional search filter).
GET /options
Get option
Get option value by name.
GET /options/{option}
Update option
Update an option value.
PUT /options/{option}
Delete option
Delete an option.
DELETE /options/{option}
Performance Analysis
Analyze performance
Analyze page performance including load time, images, CSS/JS, caching, and plugin impact.
GET /analyze/performance/{page_id}
Get Core Web Vitals
Get Core Web Vitals metrics (LCP, FID, CLS) for a page.
GET /analyze/core-web-vitals/{page_id}
Analyze images
Analyze image optimization opportunities including missing alt text and large files.
GET /analyze/images/{page_id}
SEO Analysis
Analyze SEO
Comprehensive SEO analysis including meta tags, headings, image alt text, internal linking, and schema markup.
GET /analyze/seo/{page_id}
Check SEO issues
Quick check for common SEO issues with recommendations.
GET /analyze/seo-issues/{page_id}
Analyze readability
Analyze content readability including Flesch Reading Ease score and paragraph structure.
GET /analyze/readability/{page_id}
AI Engine Optimization (AEO)
Analyze AEO
Analyze content for AI search engine optimization (Perplexity, ChatGPT). Checks structured data, content clarity, and semantic HTML.
GET /analyze/aeo/{page_id}
Check structured data
Check schema markup and structured data (JSON-LD, microdata) for AI parsing. Since plugin 9.1.11 the answer lists every JSON-LD block with its values and the plugin that printed it.
GET /analyze/structured-data/{page_id}
Query parameters:
contains- Optional. Keep only the JSON-LD blocks whose text contains this
See wordpress_check_structured_data.
Find in page
Find text in the published HTML of a page, head included, and name the snippet or setting on the site that holds it. Read only. Plugin 9.1.11 or newer.
GET /analyze/find-in-page
Query parameters:
post_id- Page or post ID. Give this orurlurl- Address on the same site. Give this orpost_idcontains- Text to find. Required unlesskindisjsonldkind-any(default),headorjsonldlimit- Most matches to return, default 8, at most 20
See respira_find_in_page.
Security
Validate security
Validate content for security issues before saving.
POST /security/validate
Plugin Management (Experimental)
Plugin management is experimental and disabled by default. Enable in Respira settings before use.
List plugins
List all installed plugins with status and update availability.
GET /plugins
Install plugin
Install a plugin from WordPress.org or ZIP URL.
POST /plugins/install
Activate plugin
Activate a plugin.
POST /plugins/{slug}/activate
Deactivate plugin
Deactivate a plugin.
POST /plugins/{slug}/deactivate
Update plugin
Update a plugin to latest version.
POST /plugins/{slug}/update
Delete plugin
Delete a plugin (must be deactivated first).
DELETE /plugins/{slug}
Multi-Site
Switch site
Switch to a different WordPress site (for multi-site setups).
POST /sites/switch
Response Format
All responses follow this structure:
Success:
{
"success": true,
"data": { ... }
}
Error:
{
"success": false,
"message": "Error message"
}