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
writescope as well as the resource scope, and only Enterprise can mintwrite. The exceptions are the record-only posts that change none of your data:POST /api/verification/results,POST /api/scanner-reportsandPOST /api/scanner-reports/submit. - Some GET routes run a live scan rather than read stored results, so they need
writetoo:/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,/subdomainsand/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.
Keep reading
Related articles
- API and MCP: 401, 402, 403, 429, or a missing toolWhat each response means when a key or an MCP client is refused, and the one fix that usually applies: mint a key with the right scope on the right plan.Troubleshooting ·Updated
- Connecting the MCP serverAdd https://nhmohio.com/api/mcp to Claude Code, Claude Desktop, Cursor, VS Code, Codex or any HTTP MCP client with an nhm_ key, keep the key to the job, confirm what it can reach, and use the prompts.API and MCP ·Updated
- MCP tool referenceAll 233 tools a customer key can be offered, by scope, with each one's access level. 125 read, 99 write, 9 destructive; 7 spend credits.API and MCP ·Updated
