WordPress REST API
The plugin registers its own namespace, vergeml/v1, at
/wp-json/vergeml/v1/…. It is what the plugin's own screens are built on, and it
is available to you for the same reason.
Media taxonomies are also exposed through core's REST API — media_category is
registered with show_in_rest, so wp/v2/media reports which folders a file is in
and wp/v2/media_category lists the folders themselves. If all you need is
"which folders is this file in", use core's routes.
Authentication #
These are logged-in admin endpoints, not a public API. They authenticate the same way any WordPress REST route does:
- From the browser: the logged-in cookie plus a nonce in the
X-WP-Nonceheader, fromwp_create_nonce( 'wp_rest' ). - From outside: application passwords, or whatever authentication plugin your site uses.
Every route has a permission callback. There is no anonymous access to any of them.
Capabilities #
| Capability | Covers |
|---|---|
upload_files | Reading the tree, reading folder lists |
manage_categories | Creating and changing folders, assigning files, running the AI, folder sorting, duplicates, the importer |
manage_options | Settings, including the licence key |
delete_posts | Removing a duplicate from the duplicates screen |
edit_post (per object) | Quick edit, and assigning terms to a specific post |
Assignment uses a coarse gate at the endpoint and then decides per object inside the handler, which is where it has always really been decided.
Folders and the tree #
| Route | Method | Capability | Purpose |
|---|---|---|---|
/tree | GET | upload_files | The whole folder tree with counts |
/state | GET | upload_files | The tree's UI state for the current user |
/folder | POST | manage_categories | Create, rename, move, colour, reorder, delete a folder |
/assign | POST | upload_files / per object | File attachments into folders |
/folder-privacy | POST | manage_categories | Make a folder private, or public again |
/gallery-folders | GET | upload_files | Folder list for the gallery block and builder elements |
/tree is the hot path and is built to stay flat: 4 queries whatever the folder
count, measured from 200 to 2,000 folders. See Performance.
Smart folders and search #
| Route | Method | Capability | Purpose |
|---|---|---|---|
/smart-scan | POST | manage_categories | Run one chunk of the reference scan |
/search-meaning | GET | upload_files | Search by meaning |
/similar | GET | manage_categories | Files like this one |
Duplicates and setting aside #
| Route | Method | Capability | Purpose |
|---|---|---|---|
/health-scan | POST | manage_categories | Hash one batch |
/health-report | GET | manage_categories | Duplicate groups, sizes, totals |
/health-uses | GET | manage_categories | Where one file is referenced |
/health-delete | POST | delete_posts | Delete a duplicate and repoint references |
/merge-plan | GET | manage_categories | Which copy would be kept, and why |
/merge-run | POST | manage_categories | Apply that plan |
/quarantine | GET | manage_categories | What has been set aside |
/quarantine-act | POST | manage_categories | Set aside, or take back |
/quarantine-manifest | GET | manage_categories | The downloadable manifest |
There is no delete endpoint in the set-aside feature. See Set aside.
Importing #
| Route | Method | Capability | Purpose |
|---|---|---|---|
/import | POST | manage_categories | Plan, run a chunk, or undo an import |
The AI #
| Route | Method | Capability | Purpose |
|---|---|---|---|
/ai-status | GET | manage_categories | Whether a key is set (has_license, boolean), credits, counts |
/ai-settings | POST | manage_options | Write settings, including the licence key |
/ai-index | POST | manage_categories | Describe the next few files |
/ai-run | GET | manage_categories | State of the background run |
/ai-alt | GET | manage_categories | The alt-text gap report |
/alt-fill-step | POST | manage_categories | Fill alt text from stored descriptions |
/alt-undo | POST | manage_categories | Remove alt text this plugin wrote |
/ai-status never returns the licence key. It reports a boolean.
Folder sorting #
| Route | Method | Capability | Purpose |
|---|---|---|---|
/librarian-schemes | GET | manage_categories | Available schemes |
/librarian-preflight | GET, POST | manage_categories | What a scheme would propose |
/librarian-batches | GET | manage_categories | Past runs |
/librarian-apply-step | POST | manage_categories | Apply one chunk |
/librarian-pause | POST | manage_categories | Pause a run |
/librarian-undo-step | POST | manage_categories | Undo one chunk |
/organize-quote | GET | manage_categories | Cost and shape of a subject run |
/organize-run | GET | manage_categories | State of a clustering run |
/organize-step | POST | manage_categories | One clustering step |
/organize-cancel | POST | manage_categories | Cancel it |
Folder talk and instructions #
| Route | Method | Capability | Purpose |
|---|---|---|---|
/folders-propose | POST | manage_categories | Revise a folder plan from an instruction |
/folders-apply | POST | manage_categories | Apply the plan you were shown |
/folders-undo | POST | manage_categories | Undo it |
/say-plan | POST | manage_categories | Parse a sentence into a plan |
/say-run | POST | manage_categories | Run a plan you were shown |
/say-run takes a plan, never the text. Four verbs are allowed — move, tag, rename,
create — and there is no delete in the file to reach.
Auto-filing #
| Route | Method | Capability | Purpose |
|---|---|---|---|
/autofile-step | POST | manage_categories | Suggest folders for unfiled files |
/autofile-act | POST | manage_categories | Accept or dismiss a suggestion |
Miscellaneous #
| Route | Method | Capability | Purpose |
|---|---|---|---|
/stats-opt | POST | manage_categories | Opt in or out of the local statistics summary |
A worked example #
Read the tree from the browser:
fetch( wpApiSettings.root + 'vergeml/v1/tree', {
headers: { 'X-WP-Nonce': wpApiSettings.nonce },
} )
.then( r => r.json() )
.then( tree => console.log( tree ) );
File two attachments into folder 42, keeping them where they already are:
fetch( wpApiSettings.root + 'vergeml/v1/assign', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-WP-Nonce': wpApiSettings.nonce,
},
body: JSON.stringify( {
taxonomy: 'media_category',
attachments: [ 1841, 1842 ],
add: [ 42 ],
} ),
} );
/assign takes taxonomy (required), then attachments with add and remove
lists — or a batch array carrying its own attachments per group. mode decides
whether a drop moves or adds, and post_type says which list the caller is looking
at, so the counts that come back are the ones it is showing.
The permission callback is a coarse gate. The real check is per attachment inside the handler, because a batch is a batch of separate permissions: one call naming forty files must not be authorised by whether the caller may edit the first.
Or skip all of it and use core, since folders are terms:
wp_set_object_terms( 1841, array( 42 ), 'media_category', true );
That last line is the whole argument for the taxonomy decision.
Written from version 3.15.0 of the plugin. Last updated 2026-10-02. All documentation · Legal · Support