Contents

REST API - Plugixa Permalink Manager

Everything the admin screens do goes through a REST API, and you can use it from your own code. It lives under:

/wp-json/plugixa-permalink-manager/v1/

Authentication and permissions

Every route requires a signed-in user with the right permission; there are no public routes. Use a cookie with a REST nonce from inside WordPress, or an application password from outside.

Permission Needed for
View Reading, except the import sources (Import)
Edit Changing addresses, and POST /uris/check
Redirects Adding, changing and deleting redirects PRO
Tools Running the bulk tools
Import Running an import
Settings Changing settings, patterns and integrations

The capability behind each one is listed in Roles and permissions.

Administrators have all of them. Changing an address also requires that the user may edit that post or term in WordPress. Nothing is ever changed by a GET request.

The envelope

A successful response:

{ "success": true, "data": { }, "meta": { "total": 18, "page": 1, "per_page": 50, "pages": 1 } }

meta is present on lists. An error is a standard WordPress REST error with a code, a message and the HTTP status.

Status Meaning
400 The request is malformed
401 / 403 Not signed in, or not allowed
404 No such item, job, tool or source
409 The address is taken, or the item changed since you read it
413 More than 200 changes in one /uris/bulk request. Other over-size requests return 400
422 The value is not acceptable (reserved address, unknown setting, broken regular expression)

Addresses

Method and route Does
GET /uris List items. Parameters: kind (post or term), type, search, status, filter (all, custom, native), orderby, order, page, per_page (up to 100)
GET /uris/types Content types and taxonomies with their counts
GET /uris/{post|term}/{id} One item
PUT /uris/{post|term}/{id} Set the address and/or mode
GET /uris/{post|term}/{id}/default The address its pattern would give. Writes nothing
GET /uris/{post|term}/{id}/history Its change history
GET /uris/{post|term}/{id}/redirects Its old addresses
POST /uris/check Check up to 100 addresses without saving
POST /uris/bulk Save up to 200 changes; each reports its own result

Setting an address:

PUT /uris/post/36
{ "uri": "shop/tents/skyline-2", "mode": -1, "expected_modified_at": "2026-10-08 12:23:38" }
  • uri - the address. An empty string, or "reset": true, returns the item to its default.
  • mode - 0 follow the global setting, -1 keep, -2 keep and skip bulk tools, 1 update on save, 2 disable the custom permalink.
  • expected_modified_at - optional. Send the modified_at you read; if the item changed since, the save is refused with a 409 instead of overwriting.

A taken address returns 409 with the owner and a free suggestion.

Patterns

Method and route Does
GET /permastructures Every pattern, with the tags each type offers
PUT /permastructures/{post_type|taxonomy}/{name} Save a pattern: { "pattern": "shop/%product_cat%/%postname%" }
DELETE /permastructures/{post_type|taxonomy}/{name} Restore the WordPress structure
POST /permastructures/preview Preview a pattern on real items, with any unknown tags

Tools and jobs

Method and route Does
POST /tools/regenerate Start a regenerate run: kind, type, mode (default or native), include_manual
POST /tools/consistency Start a health check
POST /tools/find-replace PRO Start a find and replace: find, replace, regex, case_sensitive, kind, type
GET /jobs/{id} A job’s state
POST /jobs/{id}/tick Do a few seconds of work and return the job
POST /jobs/{id}/cancel Cancel a running job
POST /jobs/{id}/undo Start an undo job for a finished run

Every tool is a preview unless you send "dry_run": false. Starting a tool returns a job; call tick until its status is no longer queued or running. The job reports total, processed, changed, skipped, failed and a sample of the items it touched.

POST /tools/regenerate
{ "dry_run": false, "kind": "post", "type": "product", "mode": "default" }

Redirects PRO

Method and route Does
GET /redirects List: group (old, manual, external), search, page, per_page
POST /redirects Add: source, target, status_code (301, 302, 307, 308), note
PUT /redirects/{id} Change status_code, is_enabled, note; and source / target on manual ones
DELETE /redirects/{id} Delete one
POST /redirects/bulk-delete Delete up to 500: { "ids": [ ] }

Settings and the rest

Method and route Does
GET /settings All settings and the choices each one offers
PUT /settings Change some settings. Send only the keys you are changing; an unknown key refuses the whole request
GET /integrations The integration cards and their state
PUT /integrations/{id} Switch one on or off: { "enabled": false }
GET /import Import sources found on the site
POST /import/{source} Start an import (a job, preview by default)
GET /dashboard The dashboard’s numbers
GET /bootstrap The admin app’s startup data: permissions, modes, modules
GET /conflicts Other permalink plugins found, and whether routing is serving
POST /conflicts/deactivate-permalink-manager Deactivate Permalink Manager (Lite or Pro) so this plugin can serve addresses. Returns 404 when it is not active. Needs the WordPress permission to activate and deactivate plugins, not one of the plugin’s own
GET /debug/resolve?url=... What the Debug screen shows. Add live=1 to request the address too

Import sources

{source} in POST /import/{source} is one of these. GET /import lists the ones registered on the site, with present, active and counts for each.

Source Imports from Edition
pmp Permalink Manager (Lite or Pro) Free
custom-permalinks Custom Permalinks Free
rank-math The exact-match redirects of Rank Math Pro
yoast The exact-match redirects of Yoast SEO Premium Pro
seopress The exact-match redirects of SEOPress Pro

An unknown source returns 404. More in Import.

Setting keys

These are the keys PUT /settings accepts. Each one is a field on a tab of the Settings screen, where its effect is described.

Addresses

Key Values Default
auto_update_uris 0, 1 or 2, in the order of the choices under When content is saved 0
force_custom_slugs 0 the WordPress slug, 1 a slug made from the title, 2 the parent’s custom address plus the slug 0
trailing_slashes 0 follow the WordPress permalink setting, 1 always add one, 2 never add one 0
keep_accents true or false false
disable_slug_sanitization true keeps punctuation and capitals as typed false

Content

Key Values Default
partial_disable { "post_types": [ ], "taxonomies": [ ] }: the types that do not have custom addresses The four post types listed in Content settings, no taxonomies
partial_disable_strict true skips content types that are not meant to be visited true
exclude_post_ids, exclude_term_ids A string of IDs and ranges, such as "12, 40-45, 318" Empty
ignore_drafts 0 drafts get an address, 1 no address for drafts, 2 no address for drafts and pending items 1

Redirects

Key Values Default
redirect_status 301, 302, 307, 308, or 0 for no redirects at all 301
setup_redirects true keeps the old address when an address changes true
extra_redirects true serves redirects from old addresses true
canonical_redirect true sends WordPress addresses to the custom ones true
trailing_slash_redirect true redirects a missing or extra trailing slash true
copy_query_redirect true keeps the query string when redirecting true
sslwww_redirect true corrects http/https and www in the same redirect true
external_redirect_policy allowlist or any allowlist
external_redirect_hosts A list of host names Empty
max_redirects_per_item 1 to 500 50

Advanced

Key Values Default
edit_uris_cap edit_posts, publish_posts, publish_pages or edit_theme_options publish_posts
history_retention_days 0 to 3650. Stored, but not yet acted on in version 1.0.0 90
safe_mode true or false false
delete_data_on_uninstall true or false. Changing it also needs the WordPress permission to manage options false

From PHP

If your code runs inside WordPress, the functions and hooks are simpler than calling the API.

Quick Links