REST API + MCP server

SEO Report API for
Developers and AI Agents

Create reports over REST, poll them to completion, and read the same saved report your team sees on the website. The same API key from your paid plan connects any MCP-capable agent.

Access model

Paid plan + API key

API access is account-linked and key-gated. Choose a plan, create an API key in your account, and every new site you run through the API uses your plan's credits, exactly as it would on the website. Credits reset on the first day of each month (UTC) and never roll over.

One report object

Website sessions, API calls, and agent sessions read from the same saved report state.

Straightforward flow

Create a report, poll for status, then read the full results from the same object.

Available endpoints

POST/api/v1/reports/preview

Create a score preview for partner integrations on a paid plan.

POST/api/v1/reports

Create a new report or reuse one that already exists. Add "forceRerun": true to scan the site again instead.

GET/api/v1/reports/:id

Get the latest report status and sections.

GET/api/v1/reports/:id/result

Read the full report results.

GET/api/v1/reports/:id/download?format=json

Export the report payload as JSON for programmatic integrations.

Quickstart: an SEO report from curl

Three requests cover the whole flow, using an API key from your paid plan. The first creates the report, the second polls it until its status is no longer queued or running, and the third exports it. A new site uses one credit; running a site you already have a report for again does not use a credit.

Create, poll and export a reportBash
export SEOREPORT_API_KEY="sr__live_your_api_key"
# Send the key as a header file so it never sits in curl's argv, where ps shows
# it to every local user. printf is a shell builtin, so it spawns no process.
auth() { printf 'Authorization: Bearer %s\n' "$SEOREPORT_API_KEY"; }

# 1. Create a report and keep its job ID
JOB_ID=$(curl -s -X POST https://seoreport.dev/api/v1/reports \
  -H @<(auth) \
  -H "Content-Type: application/json" \
  -d '{"url": "example.com"}' | jq -r '.report.jobId')

# 2. Poll until the report is no longer queued or running
while :; do
  STATUS=$(curl -s "https://seoreport.dev/api/v1/reports/$JOB_ID" \
    -H @<(auth) | jq -r '.report.status')
  case "$STATUS" in queued|running) sleep 3 ;; *) break ;; esac
done
echo "status: $STATUS"

# 3. Export the finished report (format=pdf, md and txt also work)
curl -s "https://seoreport.dev/api/v1/reports/$JOB_ID/download?format=json" \
  -H @<(auth) -o report.json

What the SEO report API returns

Every finished report exports as one JSON document: the overall score and its band, a score for each area, how many pages were analysed, open issues by severity, and every finding in fix order with why it matters, how to fix it, how to verify the fix, and the evidence and pages behind it. Markdown, text and PDF are rendered from the same diagnosis.

GET /api/v1/reports/:id/download?format=json (trimmed)JSON
{
  "exportVersion": 1,
  "jobId": "3f6c2a1e-8d4b-4c7a-9e21-5b0d7f4a6c18",
  "targetUrl": "https://example.com",
  "status": "completed",
  "isSnapshotReady": true,
  "auditedAt": "2026-10-14T09:12:41.000Z",
  "locale": "en",
  "score": { "overall": 72, "band": "stable" },
  "areas": [
    { "id": "access_crawl", "name": "Crawl & Index", "score": 61 },
    { "id": "metadata_onpage", "name": "On-Page SEO", "score": 78 },
    { "id": "security", "name": "Security", "score": 84 }
  ],
  "pagesAnalyzed": 24,
  "openIssues": { "critical": 0, "high": 2, "medium": 5, "low": 3, "total": 10 },
  "findings": [
    {
      "rank": 1,
      "title": "Render parity mismatch",
      "status": "fail",
      "severity": "high",
      "area": { "id": "access_crawl", "name": "Crawl & Index" },
      "whyItMatters": "Raw HTML and rendered DOM should tell the same SEO story so crawlers and AI systems do not see conflicting versions of the page.",
      "fix": "Ensure raw HTML and rendered DOM contain the same critical SEO elements (title, H1, canonical, meta description, structured data). If content is injected by JavaScript, move it to server-side rendering so crawlers see it immediately.",
      "verification": [
        "Recheck these recorded examples: https://example.com/pricing. Method: compare the raw HTML with the rendered DOM. Previously observed: H1 present only after rendering",
        "Expected after the change: the same critical elements in both. Obtain a fresh capture and compare the same check and URLs; a changed sample alone does not verify a fix."
      ],
      "evidence": ["Raw HTML and rendered DOM were compared for critical elements."],
      "pages": ["https://example.com/pricing"]
    }
  ]
}

Errors and limits

Each refusal below names its code. Handle these and a script never retries blindly.

402PAYMENT_REQUIREDNo paid plan is behind the request: the key is missing, invalid or revoked, or the account has no active plan. A missing key returns 402, not 401.
402REPORT_CREDITS_EXHAUSTEDThis month's new-site credits are used up. Re-running a site you already have a report for still works, and credits reset on the first day of each month (UTC).
429FRESH_RUN_LIMITMore than 30 fresh runs (forceRerun) in an hour for one account. Wait for the time in the Retry-After header.
200status: failed | dead_letteredThe report could not finish. GET /api/v1/reports/:id returns error.code, error.message and error.retryable when the cause was recorded; retry only when retryable is true.
200pollAfterMsHow long to wait before asking for the status again; 0 once the report is finished.

SEO monitoring API

A domain registered for monitoring is re-audited every week. When something changes, the alert address receives an email: a new critical or high-severity finding, a resolved critical finding, or a move to a different score band. A week without a change sends nothing.

PUT/api/v1/monitors

Starts weekly monitoring for a domain; "enabled": false pauses it.

GET/api/v1/monitors

Lists the domains this account monitors.

DELETE/api/v1/monitors?url=

Stops monitoring a domain and deletes its stored results.

Monitor a domainBash
# Uses the auth() helper from the quickstart above.
# Re-audit a domain every week and email [email protected] when it changes
curl -X PUT https://seoreport.dev/api/v1/monitors \
  -H @<(auth) \
  -H "Content-Type: application/json" \
  -d '{"url": "example.com", "alertEmail": "[email protected]"}'

# List monitored domains
curl https://seoreport.dev/api/v1/monitors \
  -H @<(auth)

# Stop monitoring (pass the host the list returns)
curl -X DELETE "https://seoreport.dev/api/v1/monitors?url=example.com" \
  -H @<(auth)

Monitoring is included with paid plans and does not spend report credits.

Official TypeScript Client

A typed client for the REST API. Authenticate with your plan's API key, then create, poll and export reports from TypeScript.

Command Line

Run reports from your terminal with your API key. One global install.

Bash
npm install -g @seoreport/client

MCP server — same API, same key

Point any MCP-capable client at https://seoreport.dev/mcp and authenticate with the same Bearer API key you use for REST. The report and account tools are advertised on connect, so an agent can run an audit and read the findings without any glue code.

MCP client configJSON
{
  "mcpServers": {
    "seoreport": {
      "url": "https://seoreport.dev/mcp",
      "headers": {
        "Authorization": "Bearer sr__live_your_api_key"
      }
    }
  }
}
seoreport_create_report

Start a report for a URL and get a job ID back.

seoreport_get_report_status

Poll a job until the report is ready.

seoreport_get_report

Read the finished report with its score and findings.

seoreport_list_reports

List the reports on the account.

seoreport_get_report_download

Get a download URL for JSON, Markdown, text, or PDF.

seoreport_get_account

Read the account's plan, remaining credits and renewal date.

Checkout returns a browser link instead of charging directly: an agent can start it, and only a person can pay. Cancelling a plan, managing API keys and deleting the account stay in your dashboard.

Ready to build?

Choose a plan, create an API key, and start integrating SEO reports into your product.