REST API
One base URL, one bearer key, JSON in and out. Everything the app shows for a website is available here.
Base URL and authentication
https://app.monoranks.com/api/v1
Authorization: Bearer mr_ws_… (or mr_site_…)
Machine-readable description of every endpoint and webhook event: https://app.monoranks.com/api/v1/openapi.json (OpenAPI 3.1). Paste it into Postman, Insomnia, Bruno or a client generator.
Make a workspace key in the app under Settings → API and MCP → New credential. It covers every website, or only the ones you tick. A website key (mr_site_…) is made when the WordPress plugin or the Shopify app connects, and covers one website. Keys are shown once. See API keys and scopes.
Endpoints
All paths below start with the base URL.
Websites and scores
| Method and path | What it returns | Scope |
|---|---|---|
GET /sites |
Websites this key can read, with their ids | sites:read |
GET /portfolio |
Every website the key covers in one call, like the Websites list: scores, change since the last audit and last week, open issues, waiting actions, last audit, next audit, and Search Console clicks (with search:read) |
sites:read |
GET /sites |
Summary: scores, last audit, open issues, WordPress access, and how fresh each connection’s data is | sites:read |
GET /sites |
Current score and 13 weeks of history with score versions | sites:read |
GET /sites |
Speed per tested page: the lab test next to real-visitor data from Chrome users, and which of the two each speed finding uses | sites:read |
Issues and actions
| Method and path | What it returns | Scope |
|---|---|---|
GET /sites |
Issues, the same list as the Issues screen (default: open, reopened, in progress, recheck queued; status= takes a comma-separated list) |
issues:read |
GET /sites |
One issue with affected pages, evidence, the AI explanation, the suggested new values and the last approved change | issues:read |
POST /sites |
Queue a recheck; the issue is resolved only when the recheck no longer finds it | issues:recheck |
GET /sites |
Actions ordered by priority, with the estimated score gain and how long each has been open (limit, default 25, at most 100) |
issues:read |
POST /sites |
Approve new SEO titles, descriptions, canonicals or noindex and write them through the WordPress connector | actions:apply |
Pages
| Method and path | What it returns | Scope |
|---|---|---|
GET /sites |
Crawled pages (q to search, page, per up to 200) |
pages:read |
GET /sites |
Page facts, scores and findings | pages:read |
GET /sites |
Same, looked up by address | pages:read |
Search Console
| Method and path | What it returns | Scope |
|---|---|---|
GET /sites |
Totals for 7, 28 or 90 days (days=) against the period before, top pages and queries |
search:read |
GET /sites |
Rows for a date range, by query, page, query and page, or day; paged, or as one CSV file with format=csv |
search:read |
AI visibility and AI readiness
| Method and path | What it returns | Scope |
|---|---|---|
GET /sites |
What AI assistants answered to the website’s tracked questions, per week | ai:read |
GET /sites |
Questions where AI answers name other websites but never this one | ai:read |
GET /sites |
AI crawler access in robots.txt, llms.txt and entity signals from the last audit | ai:read |
GET /sites |
The live /llms.txt, read now, and a ready-to-publish draft built from your pages |
ai:read |
POST /sites |
Approve a new /llms.txt and write it through the WordPress connector |
actions:apply |
GET /sites |
What robots.txt, read now, says to each AI crawler, and the rules MonoRanks last wrote | ai:read |
POST /sites |
Approve allow or deny rules per AI crawler and write them into robots.txt | actions:apply |
GET /sites |
Agentic browsing results (can an AI agent use the page), per tested page and device, with what to fix | ai:read |
POST /sites |
Re-run the Agentic browsing check for one page; answers 202 with a job id |
issues:recheck |
GET /sites |
The status and result of one re-run | ai:read |
Audits
| Method and path | What it returns | Scope |
|---|---|---|
GET /sites |
The latest audits, the one running now, the next weekly audit, the page budgets and the starts left today | sites:read |
POST /sites |
Start a full audit now, with an optional pageBudget; answers 202 with an audit id |
audits:run |
GET /sites |
One audit: status, pages crawled so far, sitemap coverage, why it stopped early | sites:read |
Public, no key
| Method and path | What it returns |
|---|---|
GET /openapi.json |
The OpenAPI 3.1 document for all of the above |
GET /plans |
Plans and prices |
GET /changelog |
Release notes as Markdown |
Paging
Each list pages its own way, and the OpenAPI document gives the details:
GET /portfolio,GET /sites/{siteId}/pagesandGET /sites/{siteId}/agentictakepage(from 1) andper(default 50, at most 200).GET /sites/{siteId}/search/rowsreturnsnextCursor; send it back ascursoruntil it isnull.limitis 1 to 10,000 (default 1,000).- Suggestions on an issue come 100 at a time; see below.
GET /sites/{siteId}/actionstakeslimit;GET /sites/{siteId}/auditstakeslimit(default 5, at most 25).
Suggested values on an issue
For an issue MonoRanks can fix (SEO title, meta description, canonical or redirect), GET /sites/{siteId}/issues/{issueId} also returns suggestions: for each affected page, the current value and the value MonoRanks suggests. These are the same values the app shows before you press Apply.
"suggestions": [
{ "url": "https://example.com/pricing/", "pageId": "…", "current": "Pricing", "suggested": "Pricing | Example", "writable": true }
],
"suggestionsTotal": 240,
"suggestionsOffset": 0,
"suggestionsLimit": 100,
"suggestionsNextOffset": 100,
"suggestionsTruncated": true
- Paging. Each call returns up to 100. For the next ones, call again with
?suggestions_offset=set tosuggestionsNextOffset; it isnullafter the last page.suggestions_limit(1 to 100) sets the page size. The spellingssuggestionsOffsetandsuggestionsLimitwork too. suggestedisnullwhen MonoRanks has no good new value for that page. A title that is too long is shortened by fixed rules that keep the page’s topic and never cut a phrase in half; when no shorter title works,suggestedisnulland you can draft one in the app.suggestionsNote(titles only) is set when the website changes the letter case of titles on the page, for example Rank Math’s Capitalize Titles setting.writableisfalse, withnotWritableReason, when apply cannot write that page, for example a category archive that is not a WordPress post or page. Do not send those to apply.advice(meta descriptions only) says when a page may not need a description: a legal page or an archive (leave it empty or set noindex), an empty archive (add posts or set noindex), or a login, account, cart or checkout page (set noindex; no description is suggested).titleTemplate(titles that are too long) is set when one shared ending from the SEO plugin’s title template makes most titles too long, so one change to the template fixes them all.lastRechecksays what the last recheck found. A recheck reads every listed page again, fresh, so pages you already fixed leave the list. A page that did not answer stays listed and is counted inlastRecheck.notRechecked.lastChangeis the last approved batch, with each change’s status.not_livemeans it was written but the page still shows another value;notLiveReasonsays why, including whether the website’s page cache was cleared after the write. A recheck looks at such changes again. Titles and descriptions count as live when only the letter case, spaces, quotes or dashes differ;liveNotethen says what changed them.
Send the values you approve to POST /sites/{siteId}/actions/{issueId}/apply as { "changes": [ { "url": "…", "value": "…" } ] } (at most 500). Through the API, apply writes SEO titles, meta descriptions, canonicals and noindex; image alt text and redirects are applied in the app.
Personal email addresses in the page text MonoRanks stores are hidden, for example j•••@gmail.com.
Example
curl -H "Authorization: Bearer mr_ws_…" \
"https://app.monoranks.com/api/v1/sites/SITE_ID/actions?limit=5"
{
"waiting": 1,
"actions": [
{ "rank": 1, "issueId": "…", "title": "Missing meta description", "severity": "serious", "effort": "low",
"priority": 8.4, "estimatedScoreGain": 3.2, "status": "open", "ageDays": 16, "waitingWeeks": 2,
"writableField": "seo_description", "link": "https://app.monoranks.com/sites/SITE_ID/actions/…" }
]
}
Start an audit
curl -X POST -H "Authorization: Bearer mr_ws_…" -H "Content-Type: application/json" \
-d '{ "pageBudget": 1000 }' "https://app.monoranks.com/api/v1/sites/SITE_ID/audits"
The call answers 202 at once with an auditId and a poll address; follow it with GET /sites/{siteId}/audits/{auditId} about once a minute. pageBudget is optional and can be at most your plan’s pages per audit: Free 200, Starter 500, Agency 1,000, Enterprise 10,000. Only one crawl runs per website at a time, and at most 3 audits per website a day can be started through the API and MCP. The weekly audit runs as usual.
Errors and limits
Errors are { "error": { "code": "…", "message": "…" } }:
| Status | Meaning |
|---|---|
| 400 | a bad parameter or body, for example a bad date range, a page budget above the plan, or a page that cannot be written |
| 401 | key missing, unknown or revoked |
| 403 | scope missing, website not covered by the key, or the key’s owner lost access |
| 404 | no such website, issue, page, audit or route |
| 409 | something is already queued or running (a recheck, an audit, the same Agentic browsing run), or the website has no WordPress connector that can write |
| 429 | hourly limit reached (1,200 requests per key per hour), the daily speed test budget is used up, or 3 audits were already started today |
| 503 | the API or this feature is switched off for now |
A key acts as the person who created it. If that person leaves the workspace or becomes a client viewer, the key stops working.
Common questions
Is there an SDK?
Not yet. The OpenAPI document at /api/v1/openapi.json works with the usual generators (openapi-generator, Kiota, oazapfts) if you want typed clients.
Can I write data through the API?
A few writes exist, each behind its own scope: queue a recheck or re-run the Agentic browsing check (issues:recheck), start a full audit (audits:run), and approve new SEO titles, descriptions, canonicals, an llms.txt file or AI crawler rules that MonoRanks then writes through the WordPress connector (actions:apply). Every approved write can be undone in the app for 30 days. Everything else is read-only.
What about the public endpoints?
GET /api/v1/plans and GET /api/v1/changelog need no key; the website uses them to show prices and release notes.