Bulk CVE Lookup
Fetch the CVE List V5 record for multiple CVEs in a single request (up to 50 CVEs).
This endpoint reads CVE List V5 only. For the aggregated record (NVD, GitHub, OSV, nixpkgs security data, EPSS and KEV) use CVE Lookup; for publication badges across a list, use Batch Status.
Endpoint
POST /api/v1/cve/batchRequest Body
| Field | Type | Required | Description |
|---|---|---|---|
cves | string[] | Yes | Array of CVE IDs to look up (max 50) |
Alternative Field Name
You can also use ids instead of cves for the array field name.
Response
json
{
"success": true,
"data": {
"CVE-2024-3094": {
"found": true,
"status": "found",
"data": {
"id": "CVE-2024-3094",
"state": "PUBLISHED",
"datePublished": "2024-03-29T16:51:12.588Z",
"datePublic": "2024-03-29T00:00:00.000Z",
"dateUpdated": "2026-08-04T07:05:54.671Z",
"dateReserved": "2024-03-29T15:38:13.249Z",
"tags": [],
"assignerOrgId": "53f830b8-0a3f-465b-8143-3b8a9948e749",
"assignerShortName": "redhat",
"ssvc": { /* ... */ },
"adp": { /* ... */ },
"title": "Xz: malicious code in distributed source",
"description": "Malicious code was discovered in the upstream tarballs of xz, starting with version 5.6.0. ...",
"severity": "critical",
"cvssScore": 10,
"cvssVersion": "3.1",
"cvssVector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H",
"severitySource": "cna",
"affected": [ /* ... */ ],
"references": [ /* ... */ ],
"problemTypes": [ { "cweId": "CWE-506", "description": "Embedded Malicious Code" } ],
"capecs": [],
"source": "cve-list-v5"
},
"sourceUrl": "https://raw.githubusercontent.com/CVEProject/cvelistV5/main/cves/2024/3xxx/CVE-2024-3094.json"
},
"CVE-2026-100895": {
"found": false,
"status": "reserved",
"note": "The CVE Program has reserved this id for a CNA, and no record has been published for it yet."
},
"CVE-2099-99999": {
"found": false,
"status": "not_found",
"error": "CVE not found"
},
"CVE-2026-2222": {
"found": false,
"status": "unavailable",
"error": "CVE List API returned 503"
}
},
"summary": {
"requested": 5,
"found": 1,
"notFound": 1,
"reserved": 1,
"rejected": 0,
"awaitingIngest": 0,
"unavailable": 1,
"partial": true,
"invalidIds": ["not-a-cve"]
},
"timestamp": "2026-10-15T19:58:05.210Z"
}Response Fields
Summary Object
| Field | Type | Description |
|---|---|---|
requested | number | Number of entries in the request array, including invalid ones |
found | number | CVEs with a CVE List V5 record |
notFound | number | Valid CVE ids the CVE Program's own register also has no allocation for |
reserved | number | Valid CVE ids the CVE Program's register says are RESERVED (allocated, no record published yet) |
rejected | number | Valid CVE ids the CVE Program's register says are REJECTED, with no CVE List V5 record ingested here yet |
awaitingIngest | number | Valid CVE ids listed in MITRE's recent delta feed but not yet ingested here, or confirmed PUBLISHED by the CVE Program's register but not yet ingested here |
unavailable | number | Valid CVE ids that could not be checked because the upstream request failed |
partial | boolean | true when one or more valid CVE ids could not be checked |
invalidIds | array | Entries that are not well-formed CVE ids, as sent (only present if any) |
CVE Result Object
| Field | Type | Description |
|---|---|---|
found | boolean | Whether a CVE List V5 record was returned |
status | string | found, reserved, rejected, awaiting_ingest, not_found, or unavailable |
data | object | The normalized CVE List V5 record (when found). Same shape as data in CVE Lookup. |
sourceUrl | string | The CVE List V5 JSON file for this id (when found) |
note | string | Why there is no record yet (reserved, rejected, or awaiting_ingest) |
error | string | Why no record was returned (not_found or unavailable) |
Non-found results
found: false is retained for compatibility. Read status for the answer:
reserved: cvelistV5 only commits a file once a record is PUBLISHED or REJECTED, so this id 404s there — but the CVE Program's own register (asked the same way CVE Lookup does) says it is RESERVED: allocated to a CNA, no record published yet.rejected: the CVE Program's own register says this id is REJECTED, but no CVE List V5 record has been ingested here for it yet.awaiting_ingest: either listed in MITRE's recent delta feed but this service has not ingested it yet, or the CVE Program's own register says the id is PUBLISHED but no source has ingested a record for it yet.not_found: neither CVE List V5 nor the CVE Program's own register has anything for the id.unavailable: the fetch, or the register check behindreserved/rejected/not_found, failed and the id was not conclusively checked. Retry it. The summary setspartial: trueand counts it underunavailable, nevernotFound.
Record Fields
The commonly used fields of data:
| Field | Type | Description |
|---|---|---|
id | string | CVE id |
state | string | CVE record state, e.g. "PUBLISHED" |
datePublished | string | null | When the CVE Program published the record |
dateUpdated | string | null | Last update to the record |
title | string | CNA-provided title |
description | string | English description |
severity | string | Lowercase: critical, high, medium, low, or unknown |
cvssScore | number | CVSS base score (0 when none is available) |
cvssVersion | string | CVSS version of that score |
cvssVector | string | CVSS vector string |
severitySource | string | null | Container that supplied the score: cna or an ADP container name such as cisa_adp |
See CVE Lookup for the full field list. Unlike CVE Lookup, this endpoint does not fill a missing score from OSV or GitHub, so a record whose CNA and ADP containers carry no score has severity: "unknown" here.
Examples
Basic Request
bash
curl -X POST "https://api.vulnpatch.dev/api/v1/cve/batch" \
-H "Content-Type: application/json" \
-d '{"cves": ["CVE-2024-3094", "CVE-2021-44228", "not-a-cve", "CVE-2099-99999"]}'Response (trimmed)
json
{
"success": true,
"data": {
"CVE-2024-3094": {
"found": true,
"status": "found",
"data": {
"id": "CVE-2024-3094",
"state": "PUBLISHED",
"datePublished": "2024-03-29T16:51:12.588Z",
"dateUpdated": "2026-08-04T07:05:54.671Z",
"title": "Xz: malicious code in distributed source",
"severity": "critical",
"cvssScore": 10,
"cvssVersion": "3.1",
"cvssVector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H",
"severitySource": "cna",
/* ... */
},
"sourceUrl": "https://raw.githubusercontent.com/CVEProject/cvelistV5/main/cves/2024/3xxx/CVE-2024-3094.json"
},
"CVE-2021-44228": {
"found": true,
"status": "found",
"data": {
"id": "CVE-2021-44228",
"state": "PUBLISHED",
"datePublished": "2021-12-10T00:00:00.000Z",
"dateUpdated": "2025-10-21T23:25:23.121Z",
"title": "Apache Log4j2 JNDI features do not protect against attacker controlled LDAP and other JNDI related endpoints",
"severity": "critical",
"cvssScore": 10,
"cvssVersion": "3.1",
"cvssVector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H",
"severitySource": "cisa_adp",
/* ... */
},
"sourceUrl": "https://raw.githubusercontent.com/CVEProject/cvelistV5/main/cves/2021/44xxx/CVE-2021-44228.json"
},
"CVE-2099-99999": {
"found": false,
"status": "not_found",
"error": "CVE not found"
}
},
"summary": {
"requested": 4,
"found": 2,
"notFound": 1,
"unavailable": 0,
"partial": false,
"invalidIds": ["not-a-cve"]
},
"timestamp": "2026-10-15T19:52:31.418Z"
}Code Examples
javascript
async function lookupCVEs(cveIds) {
const response = await fetch('https://api.vulnpatch.dev/api/v1/cve/batch', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ cves: cveIds })
});
const { data, summary } = await response.json();
console.log(`Found ${summary.found}/${summary.requested} CVEs`);
for (const [cveId, result] of Object.entries(data)) {
if (result.found) {
console.log(`${cveId}: ${result.data.severity} (CVSS ${result.data.cvssScore})`);
} else if (result.status === 'not_found') {
console.log(`${cveId}: no CVE List V5 record`);
} else {
console.log(`${cveId}: not checked (${result.error}), retry`);
}
}
return data;
}
// Usage
lookupCVEs(['CVE-2024-3094', 'CVE-2021-44228']);python
import requests
def lookup_cves(cve_ids):
response = requests.post(
'https://api.vulnpatch.dev/api/v1/cve/batch',
json={'cves': cve_ids}
)
result = response.json()
print(f"Found {result['summary']['found']}/{result['summary']['requested']} CVEs")
for cve_id, cve_result in result['data'].items():
if cve_result['found']:
data = cve_result['data']
print(f"{cve_id}: {data.get('severity', 'N/A')} (CVSS {data.get('cvssScore', 'N/A')})")
elif cve_result['status'] == 'not_found':
print(f"{cve_id}: no CVE List V5 record")
else:
print(f"{cve_id}: not checked ({cve_result['error']}), retry")
return result['data']
# Usage
lookup_cves(['CVE-2024-3094', 'CVE-2021-44228'])Error Responses
No CVEs Provided (400)
json
{
"success": false,
"error": "Request body must contain a \"cves\" array of CVE IDs",
"example": { "cves": ["CVE-2024-1234", "CVE-2024-5678"] }
}Too Many CVEs (400)
json
{
"success": false,
"error": "Maximum 50 CVEs per batch request",
"requested": 75
}No Valid CVE IDs (400)
json
{
"success": false,
"error": "No valid CVE IDs provided",
"invalidIds": ["invalid-id", "also-invalid"]
}Server Error (500)
json
{
"success": false,
"error": "Batch CVE lookup failed"
}Notes
POSTonly. AGETto this path is read as a CVE id by CVE Lookup and returns400 Invalid CVE ID format.- CVE IDs are case-insensitive (
cve-2024-1234works) - Invalid CVE IDs are skipped and reported in
summary.invalidIds - Results are keyed by the normalized (uppercase) CVE ID; a repeated id appears once in
databut is counted each time insummary.requested - Records are fetched live from CVE List V5 on each request
- This endpoint is more efficient than making individual requests when you need the CVE List V5 record for multiple CVEs