Every route the plugin registers, under the namespace clara-ve/v1.
Twenty-nine of them: twenty-five require a capability, four are public and are
listed together at the end.
Unless stated otherwise, the permission callback is:
current_user_can( 'edit_theme_options' ) && current_user_can( 'unfiltered_html' )key defaults to front-page everywhere it appears.
Search appearance for the VE sidebar inside Gutenberg. Requires
current_user_can( 'edit_post', {post} ) and accepts only pages and posts.
POST accepts title, description, ogImage and noindex; it merges them
onto the full stored SEO record and mirrors them to Yoast or Rank Math.
Submissions from the Form block (clara-ve/form). Public, like /submit, with
the same checks — origin token, honeypot, signed time-trap, rate limit, Akismet —
through Clara_VE_Forms::handle_submit(). to, form_type and list_id are
honoured only when cve_delivery signs them. That field is written by
Clara_VE_Tokens::connect_form(), which connects every form this plugin
renders, so the same rule covers [wp-form] forms on /submit and block forms
here: a posted recipient is not a mail relay and a posted list id cannot write
into the owner's contacts. Anything unsigned falls back to an enquiry to the
Form Settings recipient. A converted theme that renders its own forms calls in
through html2wp_theme_form_handle, and reaches the same handle_submit() with
the same check: what that filter receives is the raw request body the theme
forwarded, so a recipient in it is indistinguishable from one a visitor retyped.
Until the converter emits cve_delivery in its own markup, a per-form Send
to on such a theme falls back to Form Settings.
Registered on every theme, including themes that take over the public runtime
(those stand down only the theme's own form delivery).
Custom HTML in block markup as native blocks, for the workspace when it adds a
theme section. markup (required, ≤ 200000 chars), post (optional). Same
permission as render-shortcode. Returns { markup, changed, converted, keptHtml } from Clara_VE_Block_Convert::convert_document(); nothing is
stored. Headings, paragraphs, lists, details, images, buttons, separators,
quotes and plain wrappers convert; anything else stays Custom HTML byte for byte.
What a shortcode puts on the page, for the workspace canvas (WordPress's
shortcode block shows only its text). text (required, ≤ 2000 chars),
post (optional). Requires edit_post for post, or edit_theme_options
without one. Returns { html }, filtered with wp_kses using the post
allowlist plus form controls — no scripts or event handlers. Empty when the
text holds no registered shortcode.
key → { source, hasEdits, menuManaged }
key, source (required), pseudo (array) → { saved }
Validates the structural anchors, seeds a history baseline, writes the option, mirrors to the render target, records a version.
Pseudo rules are validated as path-N-N… ids with [a-zA-Z]+ property names
and no {}; in values.
key → the page's SEO record plus the effective values read back from Yoast
or Rank Math when present.
For a chrome key returns { editable: false, reason } — header and footer are
fragments of every page, not pages.
key, title, description, ogImage, noindex → { saved, … }
Merges onto the stored record rather than replacing it, so canonical, Twitter tags and structured data survive an edit from the small panel.
No args → { reset: true }. Front page only.
→ [{ key, label, url }] — the page picker, with preview URLs resolved
(article → newest post, 404 → a guaranteed-missing URL, header/footer → the
first tagged page).
originalTitle, originalUrl, title, url (required), blank,
location → { updated: true }
Matches the item by its current title and URL. It looks in the location the
request names first, then every zone the theme's contract declares, and falls
back to CLARA_VE_NAV_LOCATION last — so an item in a drawer or a footer menu
is found, not only one in the front-page nav.
GET → { catalog, selected, max }
POST families (required) → { selected, cssUrl }, or an error over the
5-family cap.
Everything here uses can_edit_target_post, an object-level check — the
capability is edit_post for the post named in the request, not a blanket
one.
post (required), title, slug → the copy
Copies a page with everything hanging off it: content, meta, terms, the search appearance record — but never the canonical, which belongs to the address and would tell search engines to ignore the copy. The copy is a draft.
post (required)
post (required), patches (required) → the updated document
The block-mode write path: an array of operations (set-text, set-attrs,
set-style, set-link, set-image, set-responsive, …) applied to one
post. The queue is all-or-nothing — one refused patch rejects the batch —
and the result must pass the block gate before it is stored.
post (required), op (required)
Structural edits the patch vocabulary cannot express: remove, duplicate, move, insert a pattern.
page → the active theme's own patterns, with content and a text preview
What + Section offers. Each row carries a source and its categories.
Core's bundled patterns and anything the theme marked inserter: false are
excluded. On a native block theme the list also holds the sections saved from
this site (source: "saved", named core/block/<id>): published, unsynced
wp_block posts, minus any filed under header or footer and any holding a
synced reference or a template part.
→ the mailing lists at the connected provider
Empty when no provider is configured — which is what the editor's List control reads to decide whether to offer the choice at all.
src (required), alt → the new attachment
Copies one image the design points at on somebody else's server into this site's Media Library. The URL comes from the editor, not from a visitor.
Registered by Clara_VE_Native_History, and keyed by an entity string
rather than a page key, because these versions belong to templates, template
parts, navigation and Global Styles as well as to posts.
entity (required) → the versions for that entity
entity (required) → one snapshot, for staging a restore into the editor
entity, message (required, ≤255) → renames that version
key → [{ id, hash, message, kind, isHead, createdAt }], newest first,
capped at 300 per key. Seeds the "Original" baseline as a side effect.
key, message (required) → { renamed: true }. Empty message restores
the automatic label.
key → { source, pseudo, history }
Writes the old content back as live. Records no new version — checkout, not revert.
Four routes have permission_callback => '__return_true'. Each is public
because it must be, and each has a specific gate. POST /form-submit, the
fourth, is documented above with the other editor routes because it is the
form blocks' own endpoint; the same layers protect it.
key, page (required, 2–500) → { html, has_more }
Registered only when the theme has not taken over the public runtime
(includes/class-rest.php:197): a converted theme that ships its own runtime
answers this itself.
What protects it: the card template is read from the site's own stored source, never from the request. The only caller-controlled inputs are a sanitised key and a bounded page number. It returns already-published content in markup the site already serves.
Free-form. Reserved names: clara_ve_nonce, form_id, to, redirect,
cve_hp, cve_ts, form_type, list_id.
What protects it: five layers — honeypot, an HMAC origin token, a signed minimum-fill-time stamp, a per-IP rate limit with CDN-aware address resolution, and optional Akismet. See Security.
Returns JSON when the request carries X-Clara-VE-Inline, otherwise a
redirect.
id, t (required) → always a redirect, never JSON
What protects it: a 32-character random token, stored only as a SHA-256 hash and compared in constant time. Every outcome — valid, invalid, already used, prefetched by a mail client — lands on the same page, so the endpoint cannot be used to probe whether an address is on a list.
- REST is the only editing interface; there is no admin-ajax path
- Errors are
WP_Errorwith meaningful codes (clara_ve_rate_limited,clara_ve_stale_form,clara_ve_bundle_newer, …) - Nothing here is versioned independently of the plugin. The namespace is
clara-ve/v1and has not changed