API Reference

The Nano EASM REST API lets you manage assets, trigger scans, pull findings, run discovery, manage monitoring alerts, enroll domains for credential exposure monitoring, and generate reports — all the things you'd wire into CI/CD, a SOAR, or a SIEM.

Quick start

A 30-second working call. Generate an API key from Settings → API Keys, then list the assets in your organization:

curl -H "X-API-Key: ag_sk_..." https://nanoeasm.com/api/assets

Once that returns, the rest of the API works the same way — every endpoint takes the same X-API-Key header, returns JSON, and respects your plan's limits and your key’s role. Keep reading for auth detail, error shapes, and the full endpoint list, or jump straight to a section in the left sidebar.

Authentication

All API endpoints require an API key. Send it on every request as the X-API-Key header.

curl -H "X-API-Key: ag_sk_..." https://nanoeasm.com/api/findings

You can also pass the key as a Bearer token if you prefer:

curl -H "Authorization: Bearer ag_sk_..." https://nanoeasm.com/api/findings

Permissions

An API key inherits the role of the user who created it. A viewer's key is read-only; an analyst's key can create assets and trigger scans. Plan limits (asset count, scans per month, etc.) apply exactly as they do in the UI.

What API keys can't do

For safety, account-credential and billing-state actions are not callable with API keys: changing your password, inviting members, changing roles, switching plans, or deleting your organization. These return 403 API_KEY_NOT_ALLOWED.

Errors

Errors are returned as JSON with an error field and the appropriate HTTP status code.

{
  "error": "invalid or expired API key"
}
400Bad request — missing or invalid fields
401Missing or invalid API key
403Permission denied (role or API_KEY_NOT_ALLOWED)
402Plan limit reached
404Resource not found
429Rate-limited — back off and retry
500Internal server error

Pagination

List endpoints accept page (1-indexed) and perPage (max 100). Responses include the total count.

curl -H "X-API-Key: ag_sk_..." "https://nanoeasm.com/api/findings?page=2&perPage=50"
{
  "items": [ ... ],
  "total": 247,
  "page": 2,
  "perPage": 50
}

Versioning & stability

The endpoints documented on this page are stable. We add new endpoints, fields, and optional query parameters without notice; we never remove or rename existing fields without first deprecating them on the changelog and emailing organisation owners.

There is currently no version segment in the URL. If a breaking change becomes necessary, it will land under /api/v2/ and the existing paths will keep working alongside it for at least 12 months. Treat any endpoint not listed on this page as internal — it may change without notice.

Assets

Manage the domains, IPs, and cloud resources you monitor. Assets are scoped to your organization and grouped by AssetGroup.

GET/assets

List all assets in your organization.

curl -H "X-API-Key: ag_sk_..." https://nanoeasm.com/api/assets
Sample response →
[
  {
    "id": "42",
    "value": "example.com",
    "type": "domain",
    "groupId": "1",
    "createdAt": "2026-04-12T08:21:33"
  }
]
POST/groups/<group_id>/assets

Add an asset to a group. Subject to plan asset limit.

curl -X POST -H "X-API-Key: ag_sk_..." -H "Content-Type: application/json" \
  -d '{"value":"api.example.com","type":"domain"}' \
  https://nanoeasm.com/api/groups/1/assets
POST/groups/<group_id>/assets/bulk

Bulk-import assets to a group (CSV-style array payload).

curl -X POST -H "X-API-Key: ag_sk_..." -H "Content-Type: application/json" \
  -d '{"assets":[{"value":"a.com","type":"domain"},{"value":"b.com","type":"domain"}]}' \
  https://nanoeasm.com/api/groups/1/assets/bulk
GET/assets/<asset_id>

Fetch a single asset by ID.

curl -H "X-API-Key: ag_sk_..." https://nanoeasm.com/api/assets/42
PATCH/assets/<asset_id>

Update asset attributes (group, tags, criticality).

curl -X PATCH -H "X-API-Key: ag_sk_..." -H "Content-Type: application/json" \
  -d '{"groupId":2,"criticality":"high"}' \
  https://nanoeasm.com/api/assets/42
DELETE/assets/<asset_id>

Remove an asset. Findings tied to it are kept for history.

curl -X DELETE -H "X-API-Key: ag_sk_..." https://nanoeasm.com/api/assets/42
GET/assets/<asset_id>/risk

Composite risk score and severity breakdown for an asset.

curl -H "X-API-Key: ag_sk_..." https://nanoeasm.com/api/assets/42/risk
GET/assets/<asset_id>/coverage

Which scan profiles have run against the asset and when.

curl -H "X-API-Key: ag_sk_..." https://nanoeasm.com/api/assets/42/coverage
GET/assets/<asset_id>/health

Reachability + service status snapshot.

curl -H "X-API-Key: ag_sk_..." https://nanoeasm.com/api/assets/42/health
GET/assets/<asset_id>/timeline

Event timeline (scans, findings, status changes).

curl -H "X-API-Key: ag_sk_..." https://nanoeasm.com/api/assets/42/timeline
GET/groups/<group_id>/assets

List assets within a specific group.

curl -H "X-API-Key: ag_sk_..." https://nanoeasm.com/api/groups/1/assets

Asset Groups

Asset groups are the unit of organisation — every asset belongs to exactly one group, and many platform features (scheduled scans, monitors, group-level reports) are scoped at this layer.

GET/groups

List all asset groups. Response includes per-group asset counts.

curl -H "X-API-Key: ag_sk_..." https://nanoeasm.com/api/groups
Sample response →
[
  {
    "id": "1",
    "name": "Production",
    "assetCount": 24,
    "createdAt": "2026-04-12T08:21:33"
  }
]
POST/groups

Create a new asset group.

curl -X POST -H "X-API-Key: ag_sk_..." -H "Content-Type: application/json" \
  -d '{"name":"Staging"}' \
  https://nanoeasm.com/api/groups
PATCH/groups/<group_id>

Rename a group. Body: { name }.

curl -X PATCH -H "X-API-Key: ag_sk_..." -H "Content-Type: application/json" \
  -d '{"name":"Pre-prod"}' \
  https://nanoeasm.com/api/groups/1
DELETE/groups/<group_id>

Delete a group. Assets must be moved or deleted first.

curl -X DELETE -H "X-API-Key: ag_sk_..." https://nanoeasm.com/api/groups/1
GET/groups/<group_id>/summary

Group rollup — total/scanned assets, asset-type breakdown, recent scan stats.

curl -H "X-API-Key: ag_sk_..." https://nanoeasm.com/api/groups/1/summary

Scans

Trigger and inspect vulnerability scans. Scans run asynchronously — POST returns immediately with a job ID you can poll.

POST/scan-jobs

Start a scan job for an asset. Profile: quick | standard | deep.

curl -X POST -H "X-API-Key: ag_sk_..." -H "Content-Type: application/json" \
  -d '{"asset_id":42,"profile":"standard"}' \
  https://nanoeasm.com/api/scan-jobs
Sample response →
{
  "id": "917",
  "status": "queued",
  "asset_id": "42",
  "profile": "standard",
  "createdAt": "2026-04-30T11:02:14"
}
GET/scan-jobs

List recent scan jobs (paginated).

curl -H "X-API-Key: ag_sk_..." "https://nanoeasm.com/api/scan-jobs?status=running&perPage=20"
POST/scan-jobs/<job_id>/run

Re-run a finished scan job (creates a new job, same config).

curl -X POST -H "X-API-Key: ag_sk_..." https://nanoeasm.com/api/scan-jobs/917/run
DELETE/scan-jobs/<job_id>

Delete a scan job and its findings (irreversible).

curl -X DELETE -H "X-API-Key: ag_sk_..." https://nanoeasm.com/api/scan-jobs/917
GET/scan-jobs/<job_id>/findings

Findings produced by a specific scan job.

curl -H "X-API-Key: ag_sk_..." https://nanoeasm.com/api/scan-jobs/917/findings

Findings

Read and triage vulnerability findings. Each finding has a status (open, acknowledged, resolved, ignored) and a severity (info, low, medium, high, critical).

GET/findings

List findings. Filter with severity, status, asset_id, since, q.

curl -H "X-API-Key: ag_sk_..." "https://nanoeasm.com/api/findings?severity=critical&status=open&since=2026-04-01"
Sample response →
{
  "items": [
    {
      "id": "5510",
      "templateId": "tls.expired-cert",
      "severity": "high",
      "status": "open",
      "assetId": "42",
      "createdAt": "2026-04-29T17:08:21"
    }
  ],
  "total": 47,
  "page": 1,
  "perPage": 50
}
GET/findings/<finding_id>

Full detail for a single finding incl. evidence + remediation.

curl -H "X-API-Key: ag_sk_..." https://nanoeasm.com/api/findings/5510
PATCH/findings/<finding_id>

Update a finding's status, notes, or assignee.

curl -X PATCH -H "X-API-Key: ag_sk_..." -H "Content-Type: application/json" \
  -d '{"status":"resolved","notes":"Patched in PR #1234"}' \
  https://nanoeasm.com/api/findings/5510
POST/findings/bulk-status

Set status on multiple findings in one request.

curl -X POST -H "X-API-Key: ag_sk_..." -H "Content-Type: application/json" \
  -d '{"ids":[5510,5511,5512],"status":"acknowledged"}' \
  https://nanoeasm.com/api/findings/bulk-status
GET/findings/export

CSV export of findings matching the filter query.

curl -H "X-API-Key: ag_sk_..." "https://nanoeasm.com/api/findings/export?severity=high" -o findings.csv

Discovery

Run subdomain and asset discovery against root domains. Discovery jobs surface unknown subdomains, IPs, and services that you can promote into your asset inventory.

POST/discovery/run

Launch a discovery job against one or more domains.

curl -X POST -H "X-API-Key: ag_sk_..." -H "Content-Type: application/json" \
  -d '{"domains":["example.com"],"deep":false}' \
  https://nanoeasm.com/api/discovery/run
GET/discovery/jobs

List discovery jobs (paginated).

curl -H "X-API-Key: ag_sk_..." https://nanoeasm.com/api/discovery/jobs
GET/discovery/jobs/<job_id>

Job detail incl. discovered subdomains, IPs, and modules used.

curl -H "X-API-Key: ag_sk_..." https://nanoeasm.com/api/discovery/jobs/123
POST/discovery/jobs/<job_id>/cancel

Cancel a running discovery job.

curl -X POST -H "X-API-Key: ag_sk_..." https://nanoeasm.com/api/discovery/jobs/123/cancel
POST/discovery/jobs/<job_id>/add-assets

Promote discovered items into your asset inventory (subject to asset limit).

curl -X POST -H "X-API-Key: ag_sk_..." -H "Content-Type: application/json" \
  -d '{"values":["api.example.com","www.example.com"]}' \
  https://nanoeasm.com/api/discovery/jobs/123/add-assets

Monitoring

Continuous monitors watch assets for change events (new ports, cert changes, DNS drift) and emit alerts. Use the alerts endpoints to ack/resolve from your SIEM or SOAR.

GET/monitors

List monitors configured for your organization.

curl -H "X-API-Key: ag_sk_..." https://nanoeasm.com/api/monitors
POST/monitors

Create a monitor for an asset or asset group.

curl -X POST -H "X-API-Key: ag_sk_..." -H "Content-Type: application/json" \
  -d '{"assetId":42,"frequencyHours":24}' \
  https://nanoeasm.com/api/monitors
PATCH/monitors/<monitor_id>

Update monitor frequency, scope, or enabled state.

curl -X PATCH -H "X-API-Key: ag_sk_..." -H "Content-Type: application/json" \
  -d '{"enabled":false}' \
  https://nanoeasm.com/api/monitors/8
DELETE/monitors/<monitor_id>

Remove a monitor.

curl -X DELETE -H "X-API-Key: ag_sk_..." https://nanoeasm.com/api/monitors/8
GET/monitors/alerts

List alerts. Filter by status, severity, monitor_id.

curl -H "X-API-Key: ag_sk_..." "https://nanoeasm.com/api/monitors/alerts?status=open"
POST/monitors/alerts/<alert_id>/acknowledge

Acknowledge an alert (tracks who/when).

curl -X POST -H "X-API-Key: ag_sk_..." https://nanoeasm.com/api/monitors/alerts/3/acknowledge
POST/monitors/alerts/<alert_id>/resolve

Mark an alert as resolved.

curl -X POST -H "X-API-Key: ag_sk_..." https://nanoeasm.com/api/monitors/alerts/3/resolve

Credential Monitoring

Enroll domain assets to run daily breach-database checks for exposed employee credentials. New exposures surface as findings in the Leaked Secrets & Configs category. Subject to your plan's credential-monitor slot limit; analyst+ role required.

GET/credential-monitors

List all credential monitors enrolled for your organization.

curl -H "X-API-Key: ag_sk_..." https://nanoeasm.com/api/credential-monitors
Sample response →
[
  {
    "id": 3,
    "domain": "acme.com",
    "assetId": 42,
    "enabled": true,
    "lastCheckedAt": "2026-05-21T08:00:00",
    "nextCheckAt": "2026-05-22T08:00:00",
    "lastFindingCount": 2
  }
]
POST/credential-monitors

Enroll a domain asset. Body: { assetId }. Asset must be type 'domain'. Subject to plan credentialMonitors limit.

curl -X POST -H "X-API-Key: ag_sk_..." -H "Content-Type: application/json" \
  -d '{"assetId":42}' \
  https://nanoeasm.com/api/credential-monitors
PATCH/credential-monitors/<id>

Enable or disable a monitor. Body: { enabled: true | false }.

curl -X PATCH -H "X-API-Key: ag_sk_..." -H "Content-Type: application/json" \
  -d '{"enabled":false}' \
  https://nanoeasm.com/api/credential-monitors/3
POST/credential-monitors/<id>/run

Manually trigger a credential check immediately, outside the daily schedule.

curl -X POST -H "X-API-Key: ag_sk_..." https://nanoeasm.com/api/credential-monitors/3/run
GET/credential-monitors/<id>/logs

Run history for a monitor (last 20 by default). Includes status, duration, emails checked, and new findings count.

curl -H "X-API-Key: ag_sk_..." https://nanoeasm.com/api/credential-monitors/3/logs
Sample response →
[
  {
    "id": 8,
    "status": "completed",
    "checkedAt": "2026-05-21T08:00:00",
    "durationSeconds": 12,
    "emailsChecked": 45,
    "newFindings": 2
  }
]
DELETE/credential-monitors/<id>

Unenroll a domain. Frees the slot; existing findings are kept.

curl -X DELETE -H "X-API-Key: ag_sk_..." https://nanoeasm.com/api/credential-monitors/3

Scheduled Scans

Recurring scans against an asset or asset group on a fixed cadence. Subject to your plan's scheduled-scan limit; analyst+ role required to create or modify.

GET/scan-schedules

List all scan schedules in your organization.

curl -H "X-API-Key: ag_sk_..." https://nanoeasm.com/api/scan-schedules
POST/scan-schedules

Create a schedule. scheduleType: 'asset' | 'group'. Provide assetId or groupId accordingly.

curl -X POST -H "X-API-Key: ag_sk_..." -H "Content-Type: application/json" \
  -d '{"scheduleType":"asset","assetId":42,"profile":"standard","frequencyDays":7}' \
  https://nanoeasm.com/api/scan-schedules
PATCH/scan-schedules/<schedule_id>

Update frequency, profile, or enabled state.

curl -X PATCH -H "X-API-Key: ag_sk_..." -H "Content-Type: application/json" \
  -d '{"enabled":false}' \
  https://nanoeasm.com/api/scan-schedules/8
DELETE/scan-schedules/<schedule_id>

Delete a schedule (existing scan-job history is retained).

curl -X DELETE -H "X-API-Key: ag_sk_..." https://nanoeasm.com/api/scan-schedules/8
POST/scan-schedules/<schedule_id>/run-now

Trigger the schedule immediately without waiting for the next cycle.

curl -X POST -H "X-API-Key: ag_sk_..." https://nanoeasm.com/api/scan-schedules/8/run-now

Reports

Generate and download PDF/Excel reports. Generation is async — the response returns a report ID you can poll until status='ready', then download.

POST/reports/generate

Start report generation. Type: executive | technical.

curl -X POST -H "X-API-Key: ag_sk_..." -H "Content-Type: application/json" \
  -d '{"type":"executive","scope":"org"}' \
  https://nanoeasm.com/api/reports/generate
Sample response →
{
  "id": "204",
  "status": "queued",
  "type": "executive",
  "createdAt": "2026-04-30T12:11:01"
}
GET/reports

List reports (paginated).

curl -H "X-API-Key: ag_sk_..." https://nanoeasm.com/api/reports
GET/reports/<report_id>

Report metadata (status, type, scope).

curl -H "X-API-Key: ag_sk_..." https://nanoeasm.com/api/reports/204
GET/reports/<report_id>/download

Download the rendered report (PDF or Excel binary).

curl -H "X-API-Key: ag_sk_..." https://nanoeasm.com/api/reports/204/download -o report.pdf

Audit Log Webhook

Forward every audit-log event to a customer-configured HTTPS endpoint (typically a SIEM ingestion URL). HMAC-signed POST per event, idempotency key included. Plan-gated to tiers with audit_log = true (Enterprise Gold + Custom). Owner role required to set the URL or rotate the secret.

GET/settings/audit-webhook

Read the current configuration. Secret returned masked (whsec_…last4) — never the full value.

curl -H "X-API-Key: ag_sk_..." https://nanoeasm.com/api/settings/audit-webhook
PUT/settings/audit-webhook

Create or update the webhook. First save generates a signing secret server-side and returns the raw value once; pass { regenerateSecret: true } to rotate. Owner only.

curl -X PUT -H "X-API-Key: ag_sk_..." -H "Content-Type: application/json" \
  -d '{"url":"https://siem.example.com/ingest","enabled":true}' \
  https://nanoeasm.com/api/settings/audit-webhook
DELETE/settings/audit-webhook

Disable and remove the webhook config. Existing delivery logs are retained.

curl -X DELETE -H "X-API-Key: ag_sk_..." https://nanoeasm.com/api/settings/audit-webhook
POST/settings/audit-webhook/test

Fire a test event at the configured URL. Useful for verifying signature handling on the receiver side.

curl -X POST -H "X-API-Key: ag_sk_..." https://nanoeasm.com/api/settings/audit-webhook/test
GET/settings/audit-webhook/deliveries

Recent delivery attempts with status code, duration, and error message. No retries today — failed deliveries are logged but not re-attempted.

curl -H "X-API-Key: ag_sk_..." https://nanoeasm.com/api/settings/audit-webhook/deliveries

MCP Server

Nano EASM also speaks the Model Context Protocol — the open standard for connecting AI assistants (Claude Desktop, Cursor, custom agents) to external tools. The MCP server is a separate surface from the REST API above: different URL, different key kind, JSON-RPC 2.0 instead of REST, and read-only in this first release.

JSON-RPChttps://mcp.nanoeasm.com

Hosted MCP Streamable HTTP endpoint. POST a JSON-RPC 2.0 envelope with your MCP key in the Authorization header.

curl -X POST https://mcp.nanoeasm.com \
  -H "Authorization: Bearer mcp_sk_..." \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
Sample response →
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "tools": [
      {
        "name": "list_findings",
        "description": "List findings in the caller's org. Filter by severity, status, asset, template, or age.",
        "inputSchema": { "type": "object", "properties": { ... } }
      },
      ...
    ]
  }
}

MCP keys are separate from REST API keys

Generate one at Settings → API Keys → MCP keys. Keys with the mcp_sk_ prefix only work against the MCP endpoint. REST ag_sk_ keys are rejected here, and MCP keys are rejected by the REST API. Revoke either independently — blast radius stays contained.

14 read-only tools, six domains

Each tool is scoped to the caller's organisation and writes an audit_log row with category='mcp'. The full catalogue with input schemas is in docs/mcp-tools.md and auto-regenerates from the registry — what's documented is exactly what's live.

DomainTools
Assetslist_assets · get_asset · search_assets
Findingslist_findings · get_finding · count_findings
Scan jobslist_scan_jobs · get_scan_job
Discovery jobslist_discovery_jobs · get_discovery_job
Monitorslist_monitors · get_monitor
Dashboardget_dashboard_stats · get_org_info
tools/callInvoke a tool

Each tool returns its result in the JSON-RPC result.content array as a JSON-encoded text block.

curl -X POST https://mcp.nanoeasm.com \
  -H "Authorization: Bearer mcp_sk_..." \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "id": 2,
    "method": "tools/call",
    "params": {
      "name": "list_findings",
      "arguments": { "severity": "critical", "status": "open" }
    }
  }'

Stdio bridge (Claude Desktop)

Clients that only speak stdio MCP (current Claude Desktop builds) can use our bridge package — a thin stdio ↔ HTTPS shim with no business logic.

pip install nano-easm-mcp

Then in your Claude Desktop config:

{
  "mcpServers": {
    "nano-easm": {
      "command": "nano-easm-mcp",
      "args": ["--url", "https://mcp.nanoeasm.com",
               "--key", "mcp_sk_..."]
    }
  }
}

Rate limit

60 tool calls per minute per key. Exceeding it returns JSON-RPC error code -32000 with message: "rate limit: 60 calls/min".

Errors

Standard JSON-RPC error codes: -32601 (unknown method/tool), -32602 (invalid params), -32603 (internal error). Auth failures return HTTP 401 with a plain JSON {error}.

More on what shipped, why, and how to wire it up in the launch article: Your Attack Surface, From Any AI Client →

Need an endpoint we haven’t documented? Some surface is reachable only via the session API used by the UI — let us know what you’re trying to do via the contact form.