REST API
The API is served by crypto-discovery-api (default :8080) and versioned under
/api/v1. Responses are JSON.
Authentication
Three access levels, enforced by middleware:
- Public —
GET /healthzand the sign-in / initial-setup routes. - User session (cookie) — every read, CBOM, compliance, knowledge, settings, node,
GitHub, and issue endpoint. You sign in through the dashboard and the browser carries the
session cookie; a missing or invalid session returns
401. - Node credential — scan ingest and node-discovery endpoints. Send the node-issued
credential as
X-API-Key: <credential>(anAuthorization: Bearer <credential>header is also accepted). An invalid credential returns401.
Errors
Errors are returned as JSON:
{ "error": "message describing what went wrong" }
| Status | Meaning |
|---|---|
400 | Invalid request. |
401 | Missing or invalid authentication. |
403 | Authenticated but not permitted. |
409 | Conflict with current state. |
429 | Per-IP rate limit exceeded. |
500 | Server error. |
503 | Service unavailable (e.g. the database is unreachable). |
The per-IP rate limit is configurable with --rate-limit-requests and
--rate-limit-window (see Configuration).
Health
curl -s http://localhost:8080/healthz
# {"status":"ok"} (200, or 503 if the database ping fails)
Ingest a scan (node credential)
curl -s -X POST http://localhost:8080/api/v1/scans \
-H 'Content-Type: application/json' \
-H 'X-API-Key: ndc_example_node_credential' \
--data-binary @out/inventory.json
The body is the normalized inventory the scanner writes with --json (see
Schemas). A successful upload returns 202 Accepted.
Read endpoints (session)
| Method and path | Returns |
|---|---|
GET /api/v1/orgs/{org}/summary | Organization posture summary. |
GET /api/v1/orgs/{org}/repos | Repositories in an organization. |
GET /api/v1/orgs/{org}/top-risks | Top risks across an organization. |
GET /api/v1/orgs/{org}/assets | Cryptographic asset inventory. |
GET /api/v1/repos/{repoID}/latest-scan | Latest scan for a repository. |
GET /api/v1/repos/{repoID}/scans | Scan history for a repository. |
GET /api/v1/repos/{repoID}/findings | Findings for a repository. |
GET /api/v1/repos/{repoID}/context | Repository context. |
Compliance and policy (session)
| Method and path | Returns |
|---|---|
GET /api/v1/orgs/{org}/compliance/report | Compliance report across active frameworks. |
GET /api/v1/orgs/{org}/compliance/pqc | Post-quantum readiness. |
GET /api/v1/orgs/{org}/policy/frameworks | Available policy frameworks. |
CBOM export (session)
| Method and path | Returns |
|---|---|
GET /api/v1/orgs/{org}/cbom | Product CBOM read model. |
GET /api/v1/orgs/{org}/cbom/standards/{standardID} | Standards export (e.g. cyclonedx-1.7, cyclonedx-1.6). |
See Export a CBOM for the export contents.
Audit (session)
| Method and path | Returns |
|---|---|
GET /api/v1/orgs/{org}/audit/snapshots | Audit snapshots. |
GET /api/v1/orgs/{org}/audit/snapshots/{snapshotID} | A single snapshot. |
GET /api/v1/orgs/{org}/audit/snapshots/{snapshotID}/export.json | Snapshot export. |
Knowledge (session)
These power the dashboard, the assistant, and the MCP tools. Each returns summary,
sources, and limitations alongside its payload (limit defaults to 50, clamps at 200):
POST /api/v1/orgs/{org}/knowledge/find-crypto-risksPOST /api/v1/orgs/{org}/knowledge/finding-contextPOST /api/v1/orgs/{org}/knowledge/repo-posturePOST /api/v1/orgs/{org}/knowledge/migration-candidatesPOST /api/v1/orgs/{org}/knowledge/developer-context
Schemas
Field names below are the JSON keys the API uses; values are illustrative. Fields marked optional are omitted when empty.
Scan inventory (ingest body)
The body of POST /api/v1/scans — normally the file the scanner wrote with --json:
{
"scan_id": "01H...",
"org_name": "acme",
"repo_name": "payments-service",
"scanned_path": "./payments-service",
"generated_at": "2026-01-01T12:00:00Z",
"tool_version": "0.1.0",
"commit_sha": "a7c3f9...",
"summary": {
"files_scanned": 128,
"total_findings": 17,
"by_severity": { "critical": 2, "high": 5 },
"by_category": { "weak-algorithm": 9 },
"by_rule": { "crypto.weak.rsa-1024": 3 },
"languages": ["go", "python"]
},
"modules": [
{ "module_id": "native/pqc-readiness", "kind": "native", "status": "ok", "findings": 4 }
],
"findings": [ /* Finding objects, see below */ ]
}
org_name, commit_sha, and modules are optional.
Finding
Returned by GET /api/v1/repos/{repoID}/findings (an array) and embedded in the inventory:
{
"id": "f_01H...",
"category": "weak-algorithm",
"rule_id": "crypto.weak.rsa-1024",
"title": "RSA-1024 key",
"severity": "critical",
"confidence": "high",
"file_path": "legacy/sign.py",
"line": 91,
"algorithm": "RSA-1024",
"key_size_bits": 1024,
"library": "crypto/rsa"
}
Optional fields include canonical_rule_id, source_rule_id, effective_confidence,
language, symbol, api, hash, cipher_mode, randomness_source,
material_reference_type, and custody_provider.
Organization summary
Returned by GET /api/v1/orgs/{org}/summary:
{
"org_name": "acme",
"repository_count": 12,
"scan_count": 34,
"total_findings": 489,
"by_severity": { "critical": 7, "high": 22 },
"top_rules": [ /* most frequent rules */ ]
}