JSON API
Reference for cve.now's public JSON endpoints - fetch one entry, browse the catalog, read source status and aggregate statistics, and upload a lockfile. No authentication.
cve.now's API is public and needs no authentication. Every endpoint is a GET unless noted and returns JSON. The GET endpoints allow cross-origin requests. POST /api/stack accepts uploads from cve.now or from a server-side client, not from browsers on other sites. Base URL: https://cve.now.
| Endpoint | Returns |
|---|---|
GET /api/v1/entries/<id> | One vulnerability entry |
GET /api/v1/entries | A page of the catalog, newest first |
GET /api/v1/status | Source freshness and historical coverage |
GET /api/stats | Aggregate counts shown on the homepage |
POST /api/stack | A stack id for an uploaded lockfile |
GET /<id>.md | One entry, or a browse index, as Markdown |
GET /feed, GET /stack | Feeds; see Subscribe to feeds and Check your stack |
Get one entry
curl -L https://cve.now/api/v1/entries/CVE-2021-44228<id> is a CVE, GHSA, or OSV id; case does not matter, and an alias returns the merged entry. The response may be a 302 redirect to a cached public JSON copy of the entry, so follow redirects (curl -L). An unknown id returns 404 with { "error": "not found" }.
Markdown copies
curl https://cve.now/CVE-2021-44228.mdEvery entry page has a Markdown copy at the same URL plus .md, written for coding agents: severity, affected versions, fixed versions, references, and links to related entries. A request for /<id> with Accept: text/markdown returns the same Markdown. Markdown browse indexes link each entry's copy: /latest.md, /critical.md, and /kev.md (100 entries per page, with a next-page link), /tech/<slug>.md, and /ecosystem/<eco>.md. /tech.md lists every valid tech slug and ecosystem. cve.now/llms.txt lists them all.
Entry fields
| Field | Description |
|---|---|
id | The entry's id, the CVE id when one exists |
aliases | Other ids for the same vulnerability, such as GHSA and OSV ids |
status | published, rejected, provisional, or superseded |
supersededBy | Ids that replace a superseded or rejected entry |
title | The vulnerability's title |
summary | The model-written summary as { text, model, promptVersion }, or null |
originalDescription | The source's description, unmodified |
severity | { cvss, vector, source }, where source is the score's provider (cna, cisa-adp, adp, nvd, ghsa, or euvd), or null |
statedSeverity | A publisher's rating without a score, as { value, source }, or null |
exploitation.kev | { dateAdded, dueDate } when listed in CISA KEV, otherwise null |
exploitation.epssReached | { date } when the EPSS score first reached 0.1, otherwise null |
exploitation.exploitDb, metasploit, nuclei, githubPoc | Public exploit code, modules, templates, and proof-of-concept repositories, when known |
ssvc | CISA's SSVC decision points (exploitation, automatable, technicalImpact), when published |
context | Plain-English context read from the vendor advisory, or null when there is none: sentence, the attacker conditions with the exact quote and sourceUrl behind each, impact, fix (versions, workaround, partial), vendorSeverity ({ value, source, sourceUrl }), conflicts between the advisory and the CVSS vector, and the entry page's faq answers. Every claim was checked against the source text before it was stored |
exposure | How many real-world setups can hit the bug, computed from context and CISA data: Actively exploited, Default setups, Specific setups only, or Unclear; null when there is no context. It describes the vulnerability, not your setup |
affected | Affected packages or products, with ecosystem, name, version ranges, and fixed versions |
references | Links, each typed as advisory, fix, report, exploit, or other |
sources | The sources merged into the entry, each with name, url, firstSeenAt, and license |
firstSeenAt | When cve.now first saw the vulnerability |
publishedAt | When the source published it, or null |
modifiedAt | When the entry last changed |
Optional fields may be absent on older entries. Treat unknown fields as additive.
Browse entries
curl "https://cve.now/api/v1/entries?filter=critical"| Parameter | Values | Default |
|---|---|---|
filter | critical, kev, or both as critical,kev (an entry must match either) | Every entry |
cursor | The nextCursor from the previous page | First page |
The response is { "entries": [...], "nextCursor": "..." }, newest first, 30 entries per page. Each entry is a summary row with the entry's id, title, dates, severity, and KEV status. Fetch the full entry with /api/v1/entries/<id>. nextCursor is null on the last page. An unknown filter or an invalid cursor returns 400.
Status
curl https://cve.now/api/v1/statusReports when cve.now last checked each source and whether that check succeeded, the latest polling run, and the historical catalog's coverage: whether the CVE List snapshot is complete, and how many records it holds. Use it to tell whether the data is current before you rely on an empty result.
Statistics
curl https://cve.now/api/statsThe aggregate numbers on the homepage: vulnerabilitiesTracked, newThisWeek, criticalFlagged, and sourcesMerged. Values change continuously.
Upload a lockfile
curl --data-binary @bun.lock -H 'X-Lockfile-Name: bun.lock' https://cve.now/api/stackPOST the lockfile as the request body, with its file name in the X-Lockfile-Name header. A parsed lockfile returns 201 with { "id": "...", "href": "/stack?s=..." }. Use id as the stack_id for the MCP check_stack tool, or href as a stack feed. A file that is not a supported lockfile returns 422 with an error message. See Check your stack.
Caching and rate of change
Responses are served from a CDN, and cache lifetimes vary by endpoint: about a minute for browsing and status, and up to five minutes for a single entry or the stats, which can be served slightly stale while they refresh. Data changes as sources are polled, every few minutes for most sources. See Data and coverage.