Developer Access

Site audit API for websites and AI-visibility

Run website audits, monitor AI visibility, and pull prioritized fixes programmatically. Call the REST API directly, or let Claude and other AI assistants call it for you through the Website Auditor MCP server.

Authentication

Details

All API requests require an API key in the X-API-Key header. Keys start with wa_.

Quickstart

Getting Your API Key

  1. Visit api.website-auditor.io/admin_portal and sign in with Google
  2. Create a new API key — the plaintext key is shown once, copy it immediately
  3. Send the key in the X-API-Key header on every request
  4. Revoke or rotate keys any time from the portal

Example Request

curl "https://api.website-auditor.io/api/audit?businessUrl=example.com&businessName=Example+Inc&businessCity=Seattle" \
  -H "X-API-Key: wa_your_api_key_here"

Rate Limits

10 audits per API key per day. The audit limit applies to /api/audit only — the read endpoints (recommendations, fixes, history, benchmark, report) don't consume it, comparison doesn't consume it, and scheduled weekly re-audits of tracked domains run on a separate server-side budget. No endpoint other than /api/audit ever starts an audit.

10 custom AI visibility queries per API key per day. POST /api/ai-query has its own allowance, fully independent of the audit limit: AI queries never consume audit allowance and audits never consume AI-query allowance.

10 comparisons per API key per day. POST /api/compare likewise carries its own independent allowance. All three counters reset at UTC midnight and report their state in the same headers:

X-RateLimit-Limit: 10
X-RateLimit-Remaining: 7
X-RateLimit-Reset: 2026-03-31T23:59:59.999Z

Get Pro API Access

PRO $10/mo


  • Queries Claude, ChatGPT, Gemini & Perplexity
  • 8 parallel, sector-specific queries per run
  • Full API and MCP server access included
Upgrade Now

$10/month after a 7-day free trial — payment method required to start; no charge until the trial ends.

API Routes

Click an endpoint to expand it. Most routes need an active Pro subscription or trial and a valid API key — a key without one gets a 403. Two exceptions: /api/subscription answers for any valid key, even a lapsed one, so you can check your own standing; and /health takes no authentication at all.

Headers

X-API-Key: wa_your_api_key_here

Query Parameters

ParameterRequiredDescription
businessUrl Required Website URL to audit — example.com or https://example.com
businessName Optional Name of the business, e.g. Example Inc. Omit it and the audit will detect the name from the site and flag it when it could not be verified. Send one only when you actually know it — a supplied name overrides detection and is treated as confirmed.
businessCity Optional City for local search analysis, e.g. Seattle, WA. Omit it and the audit will detect the location; when none can be found the questions widen to the country or drop the place entirely, which suits a national or global business but not a local one.

Example URL

GET /api/audit?businessUrl=example.com&businessName=Example+Inc&businessCity=Seattle

The call is synchronous: it triggers the audit, polls until it finishes, and returns the finished report in one response. Expect it to take a while — the poll runs for up to 3 minutes before giving up with a 504.

Response — 200 OK

{
  "success": true,
  "request_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "run_id": "8ae42039-b30",
  "timestamp": "2026-03-31T12:00:00.000Z",
  "duration_ms": 15230,
  "audit": {
    "run_id": "8ae42039-b30",
    "base_url": "https://example.com",
    "environment": "production",
    "started_at": "2026-03-31T11:59:44.770Z",
    "finished_at": "2026-03-31T12:00:00.000Z",
    "duration_s": 15.2,
    "status": "completed",
    "summary": {
      "total": 163,
      "passed": 154,
      "failed": 3,
      "warnings": 6,
      "errors": 0,
      "pass_rate": 94.5
    },
    "results": [ ... ],
    "performance_metrics": { ... },
    "ai_visibility": { ... }
  }
}

audit is the complete report document — the same JSON served at /report/{run_id}/json — not a link to it. results, performance_metrics and ai_visibility are abridged above because they are large; their real contents are described below. platform, total_annual_impact, total_annual_impact_range and total_pages_audited appear only when the audit produced them. total_annual_impact_range is {"low", "high"} with high equal to total_annual_impact — the same estimate published as a category range (the AI-visibility term spans a stated 0.1%–1% influence band).

Shape of an audit.results[] entry

{
  "test_id": "f7013b72",
  "module": "base",
  "name": "AI Visibility Score",
  "description": "Business appears in 0/32 AI recommendations (0% visibility)",
  "status": "failed",
  "severity": "high",
  "url": "https://example.com",
  "details": "Tested across 4 AI platforms with 8 queries each.",
  "recommendation": "Improve your online presence, reviews, and structured data.",
  "screenshot": null,
  "duration_ms": 0,
  "timestamp": "2026-03-31T11:59:45.730Z",
  "logs": [],
  "has_fix": true,
  "impact_pages": 1,
  "impact_estimate": 5500
}

status is one of passed, failed, warning, skipped, error; severity is one of critical, high, medium, low, info. The has_fix, impact_* and build_time_* keys appear only on findings that carry them.

Fix content is not included in the API payload. has_fix tells you a fix exists, but fix_snippet, fix_filename and fix_instructions are stripped from every result on this path — retrieve the full generated fix files via GET /api/fixes, read them from the signed-in report at report_url, or get ranked advice via GET /api/recommendations.

Shape of an audit.ai_visibility.sources[] entry

{
  "domain": "forbes.com",
  "answers": 6,
  "platforms": ["ChatGPT", "Perplexity", "Claude"],
  "ownership": "third_party",
  "url": "https://www.forbes.com/advisor/best-password-managers/",
  "title": "Best Password Managers Of 2026"
}

audit.ai_visibility.sources is the ranked list the report page renders as Where the assistants looked: the cited documents, deduplicated by domain, ordered by how many platforms independently read the domain first (cross-engine agreement), then by how many answers cited it, capped at the top ten. answers counts answers, not citation entries — one answer citing three pages of a site counts once. platforms is listed in a fixed platform order (ChatGPT, Perplexity, Claude, Gemini); any other engine name follows them alphabetically. ownership is one of yours, competitor, third_party; treat competitor rows as context, not as placement targets. url and title name one representative page. url is null when no citation for the domain named a directly linkable page (Gemini often reaches pages through a grounding redirect, which does not count), and title is always empty in that case; a linkable page can also arrive with an empty title when its citation carried none. sources itself is null when no recorded citation named an attributable domain — including answers whose only citations were grounding redirects with no identifiable site — and the key is omitted entirely when the audit holds no readable citation records: AI visibility not scored, deferred by the daily budget, an audit predating citation capture — or, rarely, a server-side ranking failure (logged, never a 5xx). The raw per-answer citations remain available in ai_visibility.all_results[].citations.

Response — 400 Validation Error

{
  "success": false,
  "error": "Validation failed",
  "details": [
    "businessUrl is required. Provide the website URL to audit."
  ]
}

Response — 401 Invalid API Key

{
  "success": false,
  "error": "Invalid API key. Check that your key is correct.",
  "reason": "unknown_key"
}

A 401 covers four different problems, and reason says which without your having to read error: missing_key (no X-API-Key header), malformed_key (doesn't start with wa_), unknown_key (well-formed, no such key) and revoked_key (the key existed and was turned off). Branch on reason, not on error — the wording is free to change, these values are not. Only revoked_key means access you previously had was withdrawn; the first two mean the key never reached us intact.

Response — 403 Subscription Required

{
  "success": false,
  "error": "This endpoint requires a Website Auditor Pro subscription.",
  "tier": "free"
}

Response — 429 Rate Limited

{
  "success": false,
  "error": "Rate limit exceeded. You can make 10 requests per day.",
  "rate_limit": {
    "limit": 10,
    "remaining": 0,
    "resets_at": "2026-03-31T23:59:59.999Z"
  }
}

Response — 502 Upstream Rejected

{
  "success": false,
  "request_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "error": "The audit service rejected the request.",
  "upstream_status": 500,
  "details": "...first 500 characters of the upstream body...",
  "duration_ms": 812
}

Only upstream 5xx responses become a 502; an upstream 4xx is passed through with its own status. If the audit service accepts the request but returns no run ID, the status is 502 with The audit service did not return a run ID.

Response — 503 Rate Limiting Unavailable

{
  "success": false,
  "error": "Rate limiting is temporarily unavailable, so requests are paused. Please try again shortly."
}

The daily cap fails closed: if the counter can't be read, the audit is refused rather than run uncapped. Sent with a Retry-After: 60 header.

Response — 504 Audit Timed Out

{
  "success": false,
  "request_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "run_id": "8ae42039-b30",
  "error": "The audit did not complete within 3 minutes. The site may be very large. The audit may still be running on website-auditor.io.",
  "duration_ms": 180000
}

Response — 500 Audit Failed

{
  "success": false,
  "request_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "run_id": "8ae42039-b30",
  "error": "The audit failed. Check website-auditor.io for details.",
  "status": "failed",
  "duration_ms": 42310
}

An unhandled proxy error also returns 500, with An internal error occurred while processing the audit request. and no run_id.

MCP server

Everything the REST API does is also callable from Claude, Cursor and any other MCP client, through the published website-auditor-mcp server. Same API key, same Pro subscription, same daily allowances — the assistant makes the calls instead of your code.

Install

Claude Desktop (claude_desktop_config.json), Cursor (~/.cursor/mcp.json) and most other clients take the same shape:

{
  "mcpServers": {
    "website-auditor": {
      "command": "npx",
      "args": ["-y", "website-auditor-mcp"],
      "env": { "WA_API_KEY": "wa_your_key_here" }
    }
  }
}

Claude Code adds it from the CLI:

claude mcp add website-auditor -e WA_API_KEY=wa_your_key_here -- npx -y website-auditor-mcp

Restart the client and the tools appear.

Tools

get_ai_visibility
How visible a domain is to AI assistants right now — overall score, per-engine breakdown across ChatGPT, Perplexity, Claude and Gemini, the top competitor appearing in its place, and 7- and 30-day movement.
run_audit
A full one-time audit: AI visibility plus SEO, security headers, broken links and performance, with a link to the report.
compare_competitors
Head-to-head AI visibility against named competitors. Each uncached competitor costs one audit against the daily quota; when the quota cannot cover them all it ranks what it could and names the rest, rather than dropping them silently.
get_recommendations
Ranked fixes with expected impact.
generate_schema
Ready-to-paste JSON-LD for a domain — Organization, LocalBusiness, Product, FAQPage, or auto-detected.
track_site, get_changes
Track a domain and report what moved since the last check: score deltas, engines gained or lost, competitors that overtook it, issues opened and resolved.

Source and releases: github.com/SpikeyCoder/website-auditor-mcp

HTTP Status Codes

The API uses standard HTTP status codes to indicate the result of your request.

200 OK
Audit completed successfully
400 Bad Request
Missing or invalid query parameters
401 Unauthorized
Missing or invalid API key
403 Forbidden
Endpoint requires an active Pro subscription
404 Not Found
No audit on record yet for the requested domain
409 Conflict
Tracked-domain cap reached (5 domains per account)
429 Too Many Requests
Daily limit exceeded (10 audits, 10 AI queries, or 10 comparisons per key per day — independent counters)
502 Bad Gateway
The audit service rejected the request or returned no run ID
503 Service Unavailable
Daily-cap counter unreadable; audits are paused rather than run uncapped
504 Gateway Timeout
Audit did not finish within 3 minutes; it may still be running

Ready to unlock full API access?

Upgrade to Pro