Appearance
REST API overview
Link Manager Pro adds a REST API to WordPress under one base URL. This page covers how to sign in, which permission each route needs, and how requests, responses and paging work.
The Link Manager Pro REST API lives at /wp-json/link-manager-pro/v1. Sign in with the WordPress login cookie plus a nonce, or with a WordPress Application Password, and send JSON.
Each route has a full entry on its resource page; Endpoint reference lists the pages.
Base URL
Every route sits under one namespace:
text
https://example.com/wp-json/link-manager-pro/v1The plugin registers its routes on the WordPress rest_api_init action with register_rest_route(), so they behave like any other WordPress REST route. Source: app/Providers/RouteServiceProvider.php and packages/framework/src/Http/WPRouterAdapter.php.
Authentication
Almost every route needs a signed-in WordPress user. How you sign in depends on where the request comes from.
Inside WordPress: cookie and nonce
Code that runs in the browser of a logged-in user sends the login cookie automatically. Add the X-WP-Nonce header with a nonce created for the action wp_rest. Without the header, WordPress treats the request as logged out and the route answers 401. With an invalid or expired nonce, WordPress refuses it with 403 and the code rest_cookie_invalid_nonce.
Create the nonce in PHP and pass it to your script:
php
add_action( 'admin_enqueue_scripts', 'myprefix_enqueue_lmp_script' );
function myprefix_enqueue_lmp_script(): void {
wp_enqueue_script( 'myprefix-lmp', plugins_url( 'lmp.js', __FILE__ ), array(), '1.0', true );
wp_add_inline_script(
'myprefix-lmp',
'window.myprefixLmp = ' . wp_json_encode(
array(
'root' => esc_url_raw( rest_url( 'link-manager-pro/v1' ) ),
'nonce' => wp_create_nonce( 'wp_rest' ),
)
) . ';',
'before'
);
}Then call a route with fetch:
js
const response = await fetch(`${window.myprefixLmp.root}/links?per_page=10`, {
credentials: 'same-origin',
headers: { 'X-WP-Nonce': window.myprefixLmp.nonce },
});
const body = await response.json();
console.log(body.data.data);The plugin's own screens use the same two pieces. They read linkManagerProData.root and linkManagerProData.nonce.
Outside WordPress: Application Passwords
For scripts and servers, use WordPress Application Passwords with HTTP Basic authentication. This is WordPress's own mechanism for REST requests. WordPress offers it on sites served over HTTPS and on sites set to the local environment type. Create a password on the user's profile screen in WordPress, then send it as the Basic password:
bash
curl -u USER:APPLICATION_PASSWORD \
"https://example.com/wp-json/link-manager-pro/v1/links?per_page=10"The routes check the permissions of the user who signs in. Link Manager Pro does not add its own API keys or tokens.
Permissions
A route is public, or it checks the signed-in user in a fixed order. Each route group has one of four levels:
| Level | Who passes | Used by |
|---|---|---|
| Public | Anyone | POST /track/internal-click, which checks its origin and, for logged-in visitors only, a nonce |
Logged in, plus link_manager_pro_access | Users with the plugin's access capability | Most routes: links, categories, tags, stats, reports, health, audits, and more |
Logged in, plus manage_options | Administrators | /system-info, /webhooks, most /settings routes, and a few setup and redirect-review routes |
Logged in, plus edit_posts or link_manager_pro_access | Anyone who can edit posts, or has the access capability | POST /links, GET /editor/optimization/{id}, /ai/* |
link_manager_pro_access is not stored on a role. The plugin works it out on every check, through the user_has_cap filter. A user has it when they are an administrator, meaning they have manage_options. They also have it when they hold the capability chosen in the access setting. The setting is Who can use Link Manager Pro under Link Manager › Settings › Advanced. A missing or unknown value falls back to administrators only. Access for editors explains the choices.
The edit_posts level checks the capability returned by the link_manager_pro_picker_capability filter, which is edit_posts by default. It is the level the editor tools use. POST /links also needs the right to create: full plugin access, or the capability returned by the link_manager_pro_picker_create_capability filter, which is publish_posts by default. Without it the route returns 403 with the code lmp_cannot_create_links. A contributor can insert existing short links but can't create one.
A request that fails a check gets one of two answers:
| Status | Code | Meaning |
|---|---|---|
401 | rest_not_logged_in | The request is not signed in. A cookie request with no nonce also lands here. |
403 | rest_forbidden | The user is signed in but lacks the capability. |
Requests
Send the body as JSON with Content-Type: application/json. The plugin reads form-encoded bodies too, and falls back to the JSON body when there are no form fields.
Routes use GET, POST, PUT, PATCH and DELETE. When a client or proxy only allows POST, send the real method in the X-HTTP-Method-Override header, or in the _method query parameter. Both come from WordPress core, which applies them before the route runs. The plugin's own screens use the header.
bash
curl -X POST \
-u USER:APPLICATION_PASSWORD \
-H "X-HTTP-Method-Override: DELETE" \
"https://example.com/wp-json/link-manager-pro/v1/links/123"Responses
Most routes answer with one envelope:
json
{
"success": true,
"data": {},
"message": "Optional human-readable text",
"meta": {}
}success and data are always present. message appears when the route has one to show, and meta when it has extra values. A route that creates something can answer 201 instead of 200.
Errors take one of these shapes:
| Status | Shape | When |
|---|---|---|
422 | { "message": "...", "errors": { "field": ["..."] } } | The request failed validation. message is the first field message, and errors is an empty object when no field applies. |
404 | { "code": "not_found", "message": "...", "data": { "status": 404 }, "status": 404 } | The record does not exist. |
401, 403 | { "code": "...", "message": "...", "data": { "status": 403 } } | A permission check failed. Errors from a controller also carry status at the top level. |
500 | WordPress error with the code route_error | An unexpected error. The details go to the PHP error log, not to the response. |
Errors a controller returns, such as 400, 401, 403 and 404, have the same shape: code, message, data.status and a top-level status. Check the HTTP status first, and then read message.
Pagination
List routes that page their results take two query parameters:
| Name | Type | Default | What it does |
|---|---|---|---|
page | int | 1 | The page to return. A value below 1 or not a whole number gives page 1. |
per_page | int | 15 | Rows per page. On the standard page object, a value below 1 or not a whole number gives the default, and there is no upper limit. Some lists build their own page object and keep per_page between 1 and 100, with their own default, such as the campaign list and an affiliate's posts and links. Each entry says which. |
The page comes back inside the envelope's data:
json
{
"success": true,
"data": {
"current_page": 1,
"data": [],
"first_page_url": "/wp-json/link-manager-pro/v1/links?page=1",
"from": null,
"last_page": 1,
"last_page_url": "/wp-json/link-manager-pro/v1/links?page=1",
"links": [],
"next_page_url": null,
"path": "/wp-json/link-manager-pro/v1/links",
"per_page": 15,
"prev_page_url": null,
"to": null,
"total": 0
}
}data.data holds the rows. from and to are the row numbers on the page, and are null on an empty page. total is the row count across all pages. links lists the page links. path and the *_url fields are paths built from the request, without the host.
Endpoint reference
Every route has a full entry with its parameters, response fields, an example and its errors, grouped by resource:
| Resource | Page |
|---|---|
| Short links, routing rules, other addresses, categories and tags | Short links |
| Affiliates and their reports | Affiliates |
| Redirects and the review of old addresses | Redirects |
| Site stats and a short link's report | Reports and stats |
| Campaigns and UTM templates | Campaigns and UTM |
| Link Health, Link Audit, Link Equity and the content scan | Link Health and Audit |
| Webhook endpoints and deliveries | Webhooks |
| Settings, the country database, SEO import and prefix updates | Settings |
| Backups, imports from other plugins and shortcode replacement | Backup and import |
| The AI Link Assistant, setup, system info and internal click tracking | Editor, AI and setup |
All endpoints lists every route on one page, each linked to its entry.
The routes serve the plugin's own screens, so a release can change a route or a field. Read the Changelog before you update an integration.