دیدن یک مشکل
/sites/{siteId}/issues/{issueId}- Scope
issues:read- ابزار MCP
issue_detail
Get an issue with pages, evidence and suggestions For a writable field other than alt, suggestions gives the rule-based value per affected page, 100 per call: page with suggestions_offset. A recheck reads every listed page fresh, so affected, evidence and suggestions show what the pages say now.
توضیح ها از سند OpenAPI می آیند و انگلیسی اند.
پارامترها
| نام | محل | توضیح |
|---|---|---|
siteIdاجباری | path | stringWebsite id, from GET /sites. |
issueIdاجباری | path | stringIssue id, from GET /sites/{siteId}/issues or /actions. |
suggestions_offset | query | integerdefault 0, min 0, max 1000000Suggestions to skip (suggestionsNextOffset of the previous page). |
suggestions_limit | query | integerdefault 100, min 1, max 100Most suggestions to return, 1 to 100. |
suggestionsOffset | query | integerdefault 0, min 0, max 1000000Same as suggestions_offset; the snake_case name wins when both are sent. |
suggestionsLimit | query | integerdefault 100, min 1, max 100Same as suggestions_limit. |
پاسخ
200 · application/json
| فیلد | توضیح |
|---|---|
id | string · required; Issue id |
ruleId | string · required; Rule that found it, for example SEO-ONP-011 |
title | string · required; Issue title |
category | string · required; Rule category, for example Technical, On-page, Internal linking, Performance, Structured data, AEO readiness or Google Ads (the Ads waste checks, ADS-* rules: about the Ads account, so they list no pages and carry their rows in example.rows) |
severity | critical | serious | warning | low · required; How much it hurts |
confidence | high | medium | low · required; How sure the rule is |
status | open | in_progress | recheck_queued | resolved | ignored | reopened · required; Where the issue stands |
affectedPages | integer · required; Pages the issue lists |
template | string · required; The group of pages: Template: /blog/*, Site-level, or a count of URLs |
summary | string · required; One line on what was found |
firstSeen | string · required; First found |
lastSeen | string · required; Last found |
lastRecheck | required; What the last recheck found; null before any recheck |
link | string · required; The issue in the app |
why | string or null · required; Why it matters |
affected | list of object · required; Affected pages (first 50) |
affected[].url | string · required; Page address |
affected[].evidence | required; What the rule saw on the page |
affectedTotal | integer · required; All affected pages |
explanation | object or null · required; The AI explanation when drafted; null otherwise |
explanation.summary | string · required; What is wrong |
explanation.summaryRefs | list of string · required; Evidence the summary is based on |
explanation.why | string · required; Why it matters |
explanation.steps | list of object · required |
explanation.steps[].text | string · required; Fix step |
explanation.steps[].refs | list of string · required; Evidence for the step |
explanation.doNotTouch | list of string · required; What to leave alone |
explanation.verify | string · required; How to check the fix |
explanation.drafted | string · required; Always "AI-drafted from evidence" |
writableField | seo_title | seo_description | canonical | noindex | alt | redirect | · required; The field MonoRanks can write for this issue; null when none |
suggestions | list of object · Writable fields other than alt: the suggested value per affected page, the same as the app shows before Apply |
suggestions[].url | string · required; Page address |
suggestions[].pageId | string · required; Page id |
suggestions[].current | string · required; What the page shows now |
suggestions[].suggested | string or null · required; The rule-based value MonoRanks suggests; null when there is none |
suggestions[].advice | object or null · Meta descriptions only: advice for pages that may not need one |
suggestions[].advice.pageKind | legal | archive | empty_archive | empty_page | account · required; legal page, archive, empty archive, near-empty page, or a logged-in, cart or checkout page |
suggestions[].advice.legalKind | privacy | cookie | terms | imprint | legal · Kind of legal page |
suggestions[].advice.recommended | leave_or_noindex | add_posts_or_noindex | add_content_or_noindex | noindex · required; What to do besides or instead of a description |
suggestions[].advice.message | string · required; The advice in words |
suggestions[].writable | true or false · required; Whether apply can write this page |
suggestions[].notWritableReason | string · Why apply cannot write this page |
suggestionsNote | string or null · Titles only: the site changes the letter case of every title (for example Rank Math's Capitalize Titles) |
suggestionsTotal | integer · Suggestions over all pages |
suggestionsOffset | integer · Suggestions skipped |
suggestionsLimit | integer · Most suggestions in this answer |
suggestionsNextOffset | integer or null · Send as suggestions_offset for the next page; null after the last |
suggestionsTruncated | true or false · More suggestions after this page |
titleTemplate | object or null · Too-long titles (SEO-ONP-005) only: one template ending that makes most titles too long |
titleTemplate.suffix | string · required; The shared ending |
titleTemplate.count | integer · required; Titles carrying it |
titleTemplate.note | string · required; Where to shorten it once |
lastChange | object or null · required; The last approved change batch; null when none |
lastChange.batchId | string · required; Batch id |
lastChange.approvedBy | string · required; Who approved it |
lastChange.approvedAt | string · required; When it was approved |
lastChange.changes | list of object · required; First 50 changes |
lastChange.changes[].url | string · required; Page address |
lastChange.changes[].field | string · required; Field written, for example seo_description |
lastChange.changes[].value | string · required; The approved value |
lastChange.changes[].status | approved | applying | applied | not_live | failed | refused | stale | reverting | reverted | revert_failed · required; applied: written and seen on the live page; not_live: written, but the page still shows another value; refused: the plugin cannot write this field here; stale: the field changed in WordPress after the review, so it is back in review |
lastChange.changes[].appliedAt | string or null · required; When it was written |
lastChange.changes[].live | true or false or null · required; Whether the recheck saw the value on the live page |
lastChange.changes[].liveValue | string or null · required; What the live page showed |
lastChange.changes[].notLiveReason | string or null · required; not_live only: why, including whether the page cache was cleared |
lastChange.changes[].liveNote | string or null · required; applied only: for example the page shows the value in another letter case |
lastChange.changes[].error | string or null · required; Why it failed or was refused |
نکته ها
برای مشکل هایی که MonoRanks می تواند اصلاحشان کند (عنوان سئو، توضیحات متا، canonical یا ریدایرکت)، GET /sites/{siteId}/issues/{issueId} فیلد suggestions را هم برمی گرداند: برای هر صفحه درگیر، مقدار فعلی و مقداری که MonoRanks پیشنهاد می کند. این ها همان مقدارهایی هستند که اپ قبل از زدن 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
| مورد | توضیح |
|---|---|
| صفحه بندی | هر درخواست حداکثر 100 مورد برمی گرداند. برای بقیه، دوباره درخواست بدهید و ? را برابر suggestionsNextOffset بگذارید؛ بعد از آخرین صفحه این مقدار null است. اندازه هر صفحه را با suggestions_limit (1 تا 100) تعیین کنید. نوشتن به شکل suggestionsOffset و suggestionsLimit هم کار می کند. |
suggested |
وقتی null است که MonoRanks مقدار جدید خوبی برای آن صفحه ندارد. عنوان های خیلی بلند با قوانین ثابت کوتاه می شوند؛ موضوع صفحه حفظ می شود و هیچ عبارتی از وسط بریده نمی شود. اگر هیچ عنوان کوتاه تری جواب ندهد، suggested برابر null است و می توانید خودتان در اپ عنوان بنویسید. |
suggestionsNote |
(فقط برای عنوان ها) وقتی پر می شود که سایت حروف بزرگ و کوچک عنوان ها را روی صفحه تغییر می دهد؛ مثلاً تنظیم Capitalize Titles در Rank Math. |
writable |
وقتی false است (همراه با notWritableReason) که apply نمی تواند روی آن صفحه بنویسد؛ مثلاً آرشیو یک دسته بندی که پست یا برگه WordPress نیست. این صفحه ها را برای apply نفرستید. |
advice |
(فقط برای توضیحات متا) می گوید کدام صفحه شاید اصلاً توضیحات لازم نداشته باشد: صفحه حقوقی یا آرشیو (خالی بگذارید یا noindex کنید)، آرشیو خالی (پست اضافه کنید یا noindex کنید)، یا صفحه ورود، حساب کاربری، سبد خرید یا پرداخت (noindex کنید؛ برای این ها توضیحاتی پیشنهاد نمی شود). |
titleTemplate |
(برای عنوان های خیلی بلند) وقتی پر می شود که یک بخش مشترک در انتهای قالب عنوان افزونه سئو بیشتر عنوان ها را بلند کرده؛ در این حالت با یک تغییر در قالب، همه درست می شوند. |
lastRecheck |
نتیجه آخرین بررسی دوباره است. بررسی دوباره همه صفحه های لیست را از نو می خواند، پس صفحه هایی که درستشان کرده اید از لیست بیرون می روند. صفحه ای که پاسخ نداده در لیست می ماند و در lastRecheck.notRechecked شمرده می شود. |
lastChange |
آخرین دسته تغییر تأییدشده است، با وضعیت هر تغییر. not_live یعنی مقدار نوشته شده، ولی صفحه هنوز مقدار دیگری نشان می دهد؛ notLiveReason دلیلش را می گوید، از جمله اینکه کش صفحه های سایت بعد از نوشتن پاک شده یا نه. بررسی دوباره این تغییرها را هم دوباره چک می کند. اگر عنوان یا توضیحات فقط در حروف بزرگ و کوچک، فاصله، گیومه یا خط تیره فرق داشته باشد، live حساب می شود؛ در این حالت liveNote می گوید چه چیزی آن را تغییر داده است. |
مقدارهایی را که تأیید می کنید با این شکل به POST /sites/{siteId}/actions/{issueId}/apply بفرستید: { "changes": [ { "url": "…", "value": "…" } ] } (حداکثر 500 مورد). apply از طریق API فقط عنوان سئو، توضیحات متا، canonical و noindex را می نویسد؛ متن alt تصویرها و ریدایرکت ها را باید در اپ اعمال کنید.
آدرس های ایمیل شخصی در متن صفحه هایی که MonoRanks ذخیره می کند پنهان می شوند؛ مثلاً j•••@gmail.com.
خطاها
| کد | معنی |
|---|---|
400 | Bad request. Codes: bad_paging. |
401 | Missing, unknown or revoked key. Codes: missing_key, invalid_key. |
403 | The key lacks the scope, covers another website, or its owner lost access. Codes: missing_scope, other_site, owner_left, no_owner, forbidden. |
404 | Not found. Codes: not_found. |
429 | Too many requests this hour for this key. Codes: rate_limited. |
نمونه درخواست
curl \
-H "Authorization: Bearer mr_ws_…" \
"https://app.monoranks.com/api/v1/sites/SITE_ID/issues/ISSUE_ID"const res = await fetch("https://app.monoranks.com/api/v1/sites/SITE_ID/issues/ISSUE_ID", {
headers: { Authorization: "Bearer mr_ws_…" },
});
if (!res.ok) throw new Error((await res.json()).error.message);
const data = await res.json();import requests
res = requests.get(
"https://app.monoranks.com/api/v1/sites/SITE_ID/issues/ISSUE_ID",
headers={"Authorization": "Bearer mr_ws_…"},
)
res.raise_for_status()
data = res.json()<?php
$ch = curl_init("https://app.monoranks.com/api/v1/sites/SITE_ID/issues/ISSUE_ID");
curl_setopt_array($ch, [
CURLOPT_HTTPHEADER => ["Authorization: Bearer mr_ws_…"],
CURLOPT_RETURNTRANSFER => true,
]);
$data = json_decode(curl_exec($ch), true);import axios from "axios";
const { data } = await axios.get("https://app.monoranks.com/api/v1/sites/SITE_ID/issues/ISSUE_ID", { headers: { Authorization: "Bearer mr_ws_…" } });نمونه پاسخ
{
"id": "b2e4c6a8-1d3f-4a5b-9c7d-0e2f4a6b8c1d",
"ruleId": "SEO-ONP-011",
"title": "Meta description missing on 3 pages (/products/*)",
"category": "On-page",
"severity": "warning",
"confidence": "high",
"status": "open",
"affectedPages": 3,
"template": "Template: /products/*",
"summary": "3 pages have no meta description. Google shows a snippet cut from the page instead.",
"firstSeen": "2026-09-20T02:40:03.000Z",
"lastSeen": "2026-10-04T02:41:12.000Z",
"lastRecheck": {
"at": "2026-10-02T09:12:44.000Z",
"present": 3,
"checked": 3,
"crawlId": "e5a7c9e1-3f5b-4d7f-9b1d-5f7b9d1f3b5c",
"passed": false
},
"link": "https://app.monoranks.com/sites/3f6c2a1e-8b4d-4c7a-9e21-5d0b7a6f4c13/issues/b2e4c6a8-1d3f-4a5b-9c7d-0e2f4a6b8c1d",
"why": "A written description raises click-through from results; it is the one line of ad copy you control.",
"affected": [
{
"url": "https://acmebikes.com/products/trail-pro-29",
"evidence": {
"title": "Trail Pro 29 Mountain Bike | Acme Bikes"
}
},
{
"url": "https://acmebikes.com/products/city-glide-7",
"evidence": {
"title": "City Glide 7 | Acme Bikes"
}
}
],
"affectedTotal": 3,
"explanation": null,
"writableField": "seo_description",
"suggestions": [
{
"url": "https://acmebikes.com/products/trail-pro-29",
"pageId": "c7a9e1b3-5d7f-4b9c-8e1a-3c5e7a9b1d2f",
"current": "",
"suggested": "Trail Pro 29: a light aluminium trail bike with 140 mm travel and a 12-speed drivetrain. Free delivery and 30-day returns.",
"advice": null,
"writable": true
}
],
"suggestionsNote": null,
"suggestionsTotal": 3,
"suggestionsOffset": 0,
"suggestionsLimit": 1,
"suggestionsNextOffset": 1,
"suggestionsTruncated": true,
"lastChange": {
"batchId": "f6b8d0f2-4a6c-4e8a-ac2e-6a8cae2a4c6d",
"approvedBy": "sam@acmebikes.com",
"approvedAt": "2026-10-01T14:03:00.000Z",
"changes": [
{
"url": "https://acmebikes.com/products/city-glide-7",
"field": "seo_description",
"value": "City Glide 7: a comfortable seven-speed city bike with mudguards and a rack.",
"status": "applied",
"appliedAt": "2026-10-01T14:03:41.000Z",
"live": true,
"liveValue": "City Glide 7: a comfortable seven-speed city bike with mudguards and a rack.",
"notLiveReason": null,
"liveNote": null,
"error": null
}
]
}
}{
"error": {
"code": "bad_paging",
"message": "suggestionsLimit must be a whole number from 1 to 100."
}
}{
"error": {
"code": "missing_key",
"message": "Send the key as Authorization: Bearer mr_site_…"
}
}{
"error": {
"code": "missing_scope",
"message": "This key does not have the scope this call needs."
}
}{
"error": {
"code": "not_found",
"message": "Issue not found."
}
}{
"error": {
"code": "rate_limited",
"message": "More than 1200 requests this hour for this key."
}
}سرور MCP همین کار را با ابزار issue_detail انجام می دهد.