API and MCP

The REST API

Base URL, bearer authentication with an nhm_ key, the routes a key can reach and the scope each needs, which calls need write, and the 401, 402, 403 and 429 replies.

Updated · 4 min read

An API key reaches a fixed set of /api/* routes, listed below, each behind one scope. The same list decides what the MCP server may do with a key, so a key reaches the same data either way. Anything not listed (account deletion, API-key management, billing, the admin console and so on) answers 403 "This endpoint is not accessible via API key". The public reference is nhmohio.com/api-docs.

Authentication

curl -H "Authorization: Bearer nhm_your_key" "https://nhmohio.com/api/domains"

Base URL https://nhmohio.com/api/. Every request needs the key in the Authorization header; a key sent any other way is refused with 401. JSON in, JSON out.

What a key can reach

Path prefix Scope Examples
/api/domains domains GET/POST /api/domains, PATCH/DELETE /api/domains/:id, GET /api/domains/:id/history, /overview, /setup
/api/domains/:id/scan, /checkup-history scans POST /api/domains/:id/scan
/api/on-demand-scans scans POST /api/on-demand-scans (a quick or full scan, as in the app's Scan tab)
/api/domains/:id/seo-scan, /indexnow seo POST /api/domains/:id/seo-scan
/api/domains/:id/lookalikes, /lookalike-events, /lookalike-evidence, /lookalike-scan, /lookalike-verdict, /lookalike-watch, /verify-ownership vulnscan GET /api/domains/:id/lookalikes, POST /api/domains/:id/verify-ownership
/api/notifications, /api/groups, /api/domain-events, /api/dmarc, /api/scan-clients, /api/onboarding, /api/conversations, /api/site-checks, /api/verification, /api/scan-access, and /api/settings (exactly, not its sub-paths) domains GET /api/dmarc/summary, POST /api/groups, GET /api/scan-access
/api/darkweb, /api/vulnapps/declared-versions scans GET /api/darkweb/status
/api/vulnapps, /api/ip-targets, /api/scan-authorizations, /api/scan/ports, /api/lookalike-events, /api/settings/lookalike-alerts vulnscan GET /api/vulnapps/software, POST /api/ip-targets
/api/site-audit, /api/seo/report, /api/reports/branding seo POST /api/site-audit/start
/api/checkup scans GET /api/checkup?domain= (runs the security checkup live)
/api/scanner-reports scans Scanner issue reports (Pro and Enterprise; a read-only key is enough)
/api/seo-results, /api/seo-check, /api/page-seo, /api/website-assessment, /api/score-accessibility, /api/score-performance, /api/static-generate, /api/deep-seo, /api/local-seo seo GET /api/seo-results/:domainId, GET /api/deep-seo/intent/:domainId, GET /api/local-seo/catalog, POST /api/local-seo/ranks/check, POST /api/local-seo/geogrid/scan
/api/accessibility-audit accessibility POST /api/accessibility-audit, GET /api/accessibility-audit/:id/export
/api/vuln-scan vulnscan POST /api/vuln-scan/start, GET /api/vuln-scan/latest/:domainId, GET /api/vuln-scan/components
/api/compliance compliance GET /api/compliance, PUT /api/compliance/:id
/api/wisp compliance GET /api/wisp, POST /api/wisp, GET / PATCH / DELETE /api/wisp/:id, POST /api/wisp/:id/build, GET /api/wisp/:id/download-link, GET /api/wisp/:id/document
/api/status status GET /api/status/services, GET/PUT /api/status/subscriptions

Read and write

  • Any method other than GET (POST, PUT, PATCH, DELETE) needs the write scope as well as the resource scope, and only Enterprise can mint write. The exceptions are the record-only posts that change none of your data: POST /api/verification/results, POST /api/scanner-reports and POST /api/scanner-reports/submit.
  • Some GET routes run a live scan rather than read stored results, so they need write too: /api/checkup, /api/seo-check, /api/page-seo, /api/website-assessment, /api/score-accessibility, /api/score-performance, /api/static-generate, /api/deep-seo/sitemap, and /api/domains/:id/email-security, /subdomains and /verify-ownership. A read-only key gets 403 with "This endpoint runs a live scan"; read the stored results instead (/api/domains/:id/history, /api/seo-results/:domainId).
  • Live scans count against the plan's manual-scan allowance.

Every endpoint checks that the resource belongs to the account behind the key; a domain id from another account answers 403 or 404, never data.

Responses you will meet

Code Meaning What to do
401 No key, a revoked or expired key, or a plan below Pro Create a key on Pro or higher
402 plan_upgrade_required The capability is not on the plan; required_plan names the cheapest that has it Upgrade, or read what the plan allows
403 The route is not open to API keys, the key lacks the scope, or lacks write for a mutating method or a live scan, or the resource is not yours Mint a key with the scope, or use the dashboard for that action
403 domain_verification_required A deep scan (full on-demand scan, active vulnerability scan) of a domain the account has not verified. Basic scans need no proof Verify the domain (POST /api/domains/:id/verify-ownership/email, or publish the DNS record or file and POST /api/domains/:id/verify-ownership), or ask us to approve deep scans of any domain (POST /api/scan-access/request). See Which domains you can scan
404 No such resource on this account Check the id from the list endpoint
409 idempotency_mismatch A request_key was reused for a different request Use a fresh key for a new run
429 The key's hourly rate limit, or a manual-scan allowance Wait; the body says when it resets

Public endpoints (no key)

GET /api/status/services, /incidents, /history; POST /api/lookalike-check; GET /api/reports/:shareId (a scan report its owner chose to share); the public forms (POST /api/contact, /api/newsletter, /api/abuse-reports); and the sign-in endpoints. Everything else needs a signed-in session, and only the routes in the table above accept a key.

Common questions

Is there an OpenAPI file? Not yet. The MCP server's tools/list is the machine-readable inventory; the route table in the repository is the source of truth.

Rate limits for public tools? Per IP per hour. The signed-in scan endpoints use the plan allowances instead.

Still stuck?

Ask the people who run the scanner.

Send the domain and what you expected to see. We look at the same scan you are looking at and write back with what it means and what to change.