VulnSea

API usage guide

VulnSea exposes a small, agent-friendly HTTP API over the CVE corpus — structured JSON, raw markdown, full-text search, and an incremental feed built for agents that poll for new vulnerabilities. Base URL: https://beta.vulnsea.com.

Authentication

The whole corpus is open — no auth is needed to read anything. Authentication only changes your rate limit: anonymous callers get 60 requests/min per IP; an API key or a logged-in browser session gets 600 requests/min.

Create a key on your account page (shown once — store it). Send it as a bearer token or x-api-key:

# bearer
curl -H "Authorization: Bearer vsk_your_key" https://beta.vulnsea.com/api/cve

# or x-api-key
curl -H "x-api-key: vsk_your_key" https://beta.vulnsea.com/api/cve

An invalid key → 401. No key → same data, anonymous rate limit.

Endpoints

GET/api/cve

Paginated, filterable CVE feed.

Query params:

  • q — full-text filter
  • severity — comma list: critical,high,medium,low
  • vendor, exploited=true
  • since — ISO date or epoch ms (by ingestedAt)
  • orderasc | desc (default desc)
  • cursor — opaque, from the previous response's next
  • limit — 1–500 (default 50)
curl -H "$AUTH" "https://beta.vulnsea.com/api/cve?severity=critical&limit=20"
GET/api/cve/{id}

One CVE as a structured JSON record. A real id that is not in the corpus yet is fetched live from CVE.org / NVD on first request (a few seconds), then served normally.

curl -H "$AUTH" https://beta.vulnsea.com/api/cve/CVE-2021-44228
GET/cve/{id}.md

Raw canonical markdown — ideal for LLM ingestion.

curl -H "$AUTH" https://beta.vulnsea.com/cve/CVE-2021-44228.md
GET/api/digest

Compact one-line-per-CVE view for cheap triage scans.

Same filters/paging as /api/cve, plus format=json|text|ndjson.

curl -H "$AUTH" "https://beta.vulnsea.com/api/digest?format=text&limit=50"
GET/api/search

Typo-tolerant full-text search (FTS5).

curl -H "$AUTH" "https://beta.vulnsea.com/api/search?q=log4shell&kev=true"
GET/api/changes

Change feed: per-CVE field-change events (KEV added, severity bumped, EPSS moved) with an exact cursor — the re-triage trigger.

/api/cve?since= answers "what's new"; this answers "what changed about records you already triaged". Store the response's nextSeq, pass it as after next poll.

curl -H "$AUTH" "https://beta.vulnsea.com/api/changes?after=$SEQ&field=kev"
GET/api/resolve

Resolve any advisory identifier (GHSA id, alias) to its canonical CVE record.

curl -H "$AUTH" "https://beta.vulnsea.com/api/resolve?id=GHSA-jfh8-c2jp-5v3q"
GET/api/movers

EPSS movers — the CVEs whose exploit probability climbed the most over a recent window.

curl -H "$AUTH" "https://beta.vulnsea.com/api/movers?days=14&minDelta=0.1"
POST/api/osv/v1/query

OSV-compatible query (osv.dev schema) — point existing OSV clients here unchanged; VulnSea signal rides in database_specific.

curl -H "$AUTH" -H "content-type: application/json" \
     https://beta.vulnsea.com/api/osv/v1/query \
     -d '{"package":{"purl":"pkg:npm/[email protected]"}}'
GET/llms.txt

Machine-readable index for LLMs (llmstxt.org).

curl -H "$AUTH" https://beta.vulnsea.com/llms.txt

Incremental polling (for agents)

To watch for new CVEs: track the highest ingestedAt you have seen (your high-water mark), then ask for everything after it, oldest → newest, paging via next until it's null. Send If-None-Match with the last ETag to get a 304 when nothing changed.

AUTH="Authorization: Bearer vsk_your_key"

# first run — page through, remember max ingestedAt → HWM
curl -H "$AUTH" "https://beta.vulnsea.com/api/cve?order=asc&limit=100"

# each poll — only what's new since the high-water mark
curl -H "$AUTH" -H "If-None-Match: $ETAG" \
     "https://beta.vulnsea.com/api/cve?since=$HWM&order=asc&limit=100"
#   304 => nothing new   |   200 => process, advance HWM + ETag

# cheap triage scan
curl -H "$AUTH" "https://beta.vulnsea.com/api/digest?since=$HWM&order=asc&format=text"

Why ingestedAt? It's when VulnSea added the record — unlike published (which can be backdated), so deltas never miss a late-published CVE.

Caching & limits

  • Responses carry an ETag; use If-None-Match for 304 Not Modified.
  • Rate limit: anonymous 60/min per IP; API key or signed-in 600/min. Over the limit → 429 with Retry-After.
  • Every response carries x-ratelimit-limit, x-ratelimit-remaining, and x-ratelimit-reset.
  • Data licence: VulnSea's own fields (depth score, zones, tags, notes, aggregations) are CC BY 4.0 — reuse freely with attribution; source data stays under its publishers' terms. See the Terms.

Generate a client

Point any OpenAPI codegen / tool-use model at https://beta.vulnsea.com/openapi.json to build a typed client or agent tool automatically.