API and MCP

The REST API

Base URL, bearer authentication with an nhm_ key, the domain check endpoint, the resource endpoints behind the dashboard, and the 401, 402, 403 and 429 replies.

Updated · 2 min read

Every /api/* route the dashboard uses is available to an API key with the right scope. The public reference is nhmohio.com/api-docs; the MCP server exposes the same data as tools and is usually the easier way to script.

Authentication

curl -H "Authorization: Bearer nhm_your_key" "https://nhmohio.com/api/?domain=example.com"

Base URL https://nhmohio.com/api/. Every request needs the header; without it the endpoints answer 401. JSON in, JSON out.

The domain check

GET /api/?domain=<domain> runs the domain scan (DNS, nameservers, SPF, DKIM, DMARC, MX, registration) and returns the parsed records and statuses. GET /api/checkup?domain= runs the security checkup; GET /api/seo-check?url= the lightweight SEO check. These count against the website scan allowance.

The resource endpoints

Area Examples
Domains GET/POST /api/domains, PATCH/DELETE /api/domains/:id, POST /api/domains/:id/scan, GET /api/domains/:id/history, /overview, /setup, /subdomains, /email-security
Events GET /api/domain-events, POST /api/domain-events/:id/authorize or /deny
Lookalikes GET /api/domains/:id/lookalikes, /lookalike-events, /lookalike-evidence
Email GET /api/dmarc/summary, /senders, /diagnostics?domain=, /setup-status?domain=
Exposure POST /api/vuln-scan/start, GET /api/vuln-scan/latest/:domainId, /api/scan/ports/:domainId, /api/vuln-scan/components, /api/vulnapps/alerts
Dark web GET /api/darkweb/status, POST /api/darkweb/scan, POST /api/darkweb/emails
SEO GET /api/seo-results/:domainId, POST /api/site-audit/start, GET /api/deep-seo/intent/:domainId, GET /api/seo/report/:domainId
Local SEO GET /api/local-seo/catalog, POST /api/local-seo/ranks/check, POST /api/local-seo/geogrid/scan
Accessibility POST /api/accessibility-audit, GET /api/accessibility-audit/:id/export
Compliance GET /api/compliance, PUT /api/compliance/:id
Status GET /api/status/services (public), GET/POST /api/status/custom-checks
Network GET/POST /api/ip-targets, POST /api/ip-targets/:id/scan
Account GET /api/auth/me, GET/PUT /api/settings, GET /api/notifications

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 key lacks the scope, or lacks write for a mutating method, or the resource is not yours Mint a key with the scope
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; POST /api/contact. Everything else needs a session or 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.