Skip to content

Beta tier API

The Beta endpoints live alongside the v2 API and add npm coverage, an optional full advisory body, a consistent nested response shape, and cursor pagination. They are the recommended endpoints for new integrations; v2 remains available for backwards compatibility.

https://vdp-api.patchstack.com/database/api/beta/

Every request must include your API key in the PSKey HTTP request header. You can request an API key by reaching out on https://patchstack.com/for-hosts/.

PSKey: <your-api-key>

All responses are JSON. Beta responses are cached until the database updates, at which point the cache is cleared. A single response shape is shared across all three list endpoints (/all, /latest, /product/npm/...) so clients can parse them interchangeably.

Pass ?platform=npm (or ?platform=wordpress — the default) on list endpoints. Platform names are case-insensitive.

Same policy as the Extended Threat Intelligence API — please contact https://patchstack.com/for-hosts/ if you need an elevated quota.


MethodEndpointPurpose
GET/database/api/beta/allPaginated listing of every published vulnerability for a platform
GET/database/api/beta/latestVulnerabilities added in the last 24 hours
GET/database/api/beta/product/{type}/{name}/{version}Match a single product/version (npm & WordPress family)
GET/database/api/beta/product/{type}/{name}/{version}/existsBoolean-only variant of the above
POST/database/api/beta/batchCheck up to 50 products in a single request

Description: Paginated listing of every published vulnerability for the given platform, ordered by descending id. Endpoint: /database/api/beta/all Method: GET

NameTypeDefaultDescription
platformstringwordpressnpm or wordpress. Case-insensitive.
pageinteger1Offset-pagination page (1-indexed).
per_pageinteger100Page size, max 500.
cursorstringOpaque cursor (see below). Presence of the param switches to cursor mode.
includestringPass details to include the full advisory body in each item.

/all supports two independent pagination strategies. Use whichever fits your client:

  • Offset (?page=&per_page=) — returns a pagination block with totals, has_next_page, has_previous_page, etc. Easy to jump to a specific page; slower at depth and susceptible to row-shift when new vulnerabilities land while you’re paging.
  • Cursor (?cursor=) — returns a cursor block with next_cursor, has_more, per_page. Stable under concurrent inserts and faster at any depth. No total count (deliberately skipped to keep cursor mode fast).

cursor and page are mutually exclusive; passing both returns 422 Unprocessable Entity.

Terminal window
curl 'https://patchstack.com/database/api/beta/all?platform=npm&page=1&per_page=25' \
-H 'PSKey: <your-api-key>'

Response:

{
"vulnerabilities": [ /* 25 items */ ],
"pagination": {
"current_page": 1,
"per_page": 25,
"total": 6115,
"total_pages": 245,
"has_next_page": true,
"has_previous_page": false,
"next_page": 2,
"previous_page": null,
"from": 1,
"to": 25
}
}

First page — send cursor= with an empty value to bootstrap:

Terminal window
curl 'https://patchstack.com/database/api/beta/all?platform=npm&per_page=25&cursor=' \
-H 'PSKey: <your-api-key>'

Response:

{
"vulnerabilities": [ /* 25 items */ ],
"cursor": {
"next_cursor": "djE6NDYzMzk",
"has_more": true,
"per_page": 25
}
}

Follow next_cursor on the next request:

Terminal window
curl 'https://patchstack.com/database/api/beta/all?platform=npm&per_page=25&cursor=djE6NDYzMzk' \
-H 'PSKey: <your-api-key>'

Stop when has_more: false and next_cursor: null.

Terminal window
curl 'https://patchstack.com/database/api/beta/all?platform=npm&per_page=25&include=details' \
-H 'PSKey: <your-api-key>'

Adds an advisory_details field (markdown) to every item.


Description: Returns vulnerabilities whose row was inserted into the Patchstack database in the last 24 hours. The filter is on created_at (insertion time), not disclosure_date. Endpoint: /database/api/beta/latest Method: GET

Accepts the same query parameters as /allplatform, page, per_page, cursor, include.

Terminal window
curl 'https://patchstack.com/database/api/beta/latest?platform=npm&per_page=50' \
-H 'PSKey: <your-api-key>'

Cursor pagination works identically:

Terminal window
curl 'https://patchstack.com/database/api/beta/latest?platform=npm&per_page=50&cursor=' \
-H 'PSKey: <your-api-key>'

Description: Match a specific product + version against the vulnerability database and return every applicable advisory. Endpoint: /database/api/beta/product/{type}/{name}/{version}/{exists?} Method: GET

Path paramDescription
typenpm, plugin, theme, or wordpress.
namenpm package slug or WordPress plugin/theme slug. Use wordpress when type=wordpress.
versionConcrete version (e.g. 0.21.4) or * to return every advisory for the product.
existsOptional. Pass the literal string exists to get a boolean response only.
NameTypeDescription
includestringPass details to include the full advisory body (advisory_details) per item. Applies only to npm.
Terminal window
curl 'https://patchstack.com/database/api/beta/product/npm/axios/0.21.4?include=details' \
-H 'PSKey: <your-api-key>'

Example — npm, wildcard version (all advisories for the package)

Section titled “Example — npm, wildcard version (all advisories for the package)”
Terminal window
curl 'https://patchstack.com/database/api/beta/product/npm/axios/*' \
-H 'PSKey: <your-api-key>'
Terminal window
curl 'https://patchstack.com/database/api/beta/product/npm/axios/0.21.4/exists' \
-H 'PSKey: <your-api-key>'

Response:

{ "vulnerable": true }

npm package slugs that include a / (e.g. @scope/pkg) conflict with the route separator. URL-encode the / as %2F or contact us for guidance on the encoding helper.


Description: Check up to 50 products in a single request. Mirrors the format documented for the Extended tier’s /batch endpoint. Endpoint: /database/api/beta/batch Method: POST Payload: Raw JSON array, ≤ 50 objects.

Terminal window
curl -X POST 'https://patchstack.com/database/api/beta/batch' \
-H 'PSKey: <your-api-key>' \
-H 'Content-Type: application/json' \
-d '[
{ "type": "npm", "name": "axios", "version": "0.21.4", "exists": false },
{ "type": "plugin", "name": "tutor", "version": "1.5.2", "exists": true },
{ "type": "wordpress","name":"wordpress","version": "6.0.0", "exists": true }
]'

The three list endpoints (/all, /latest, /product/npm/...) share the same per-item shape when platform=npm. advisory_details is only present when ?include=details was passed.

{
"id": 46500,
"title": "NPM: OpenClaw: ...",
"disclosed_at": "2026-04-03T03:15:56+00:00",
"created_at": "2026-04-21T08:38:34+00:00",
"url": "https://patchstack.com/database/npm/npm/openclaw/vulnerability/...",
"vuln_type": "Other Vulnerability Type",
"cve": "2026-41331",
"is_exploited": false,
"patch_priority": 2,
"advisory_details": "## Summary\n...",
"product": {
"id": 23595,
"name": "openclaw",
"slug": "openclaw"
},
"cvss": {
"score": 6.9,
"vector": "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:L/SC:N/SI:N/SA:N"
},
"cwe": {
"id": 770,
"name": "Allocation of Resources Without Limits or Throttling"
},
"capec": {
"id": null,
"name": null
},
"references": [
"https://github.com/openclaw/openclaw/security/advisories/GHSA-m6fx-m8hc-572m",
"https://github.com/openclaw/openclaw/releases/tag/v2026.3.31"
],
"ghsa": "GHSA-m6fx-m8hc-572m",
"version_info": {
"affected": "<= 2026.3.28",
"fixed": "2026.3.31",
"patched_ranges": []
}
}
FieldTypeDescription
idintegerStable Patchstack vulnerability id.
titlestringHuman-readable title (prefixed with NPM: for npm advisories).
disclosed_atISO-8601When the vulnerability was publicly disclosed.
created_atISO-8601When the row was inserted into the Patchstack DB. Drives /latest windowing.
urlstringPublic Patchstack vulnerability page (token-tagged).
vuln_typestringHigh-level vulnerability category.
cvestringFirst CVE identifier, or "" when none is assigned.
is_exploitedbooleanWhether exploitation has been observed in the wild.
patch_priorityinteger1 (low) to 3 (high).
advisory_detailsstring | absentFull advisory body. Only present with ?include=details.
product.{id,name,slug}objectThe affected package/product.
cvss.{score,vector}objectCVSS score and vector (may be null).
cwe.{id,name}objectCWE classification (may be null).
capec.{id,name}objectCAPEC classification (may be null).
referencesstring[]External reference URLs (advisories, commits, tags).
ghsastringGHSA identifier when the advisory came from the GitHub Advisory Database.
version_info.affectedstringAffected version range (e.g. <= 2026.3.28).
version_info.fixedstringFirst fixed version.
version_info.patched_rangesarrayStructured list of {from_version, to_version, fixed_in} entries for advisories with multiple patch ranges.

Terminal window
# Latest 24h, npm
curl 'https://patchstack.com/database/api/beta/latest?platform=npm&per_page=10' \
-H 'PSKey: <your-api-key>'
# Cursor pagination walk (bootstrap + follow)
curl 'https://patchstack.com/database/api/beta/all?platform=npm&per_page=50&cursor=' \
-H 'PSKey: <your-api-key>'
# Check a specific npm package/version with full advisory text
curl 'https://patchstack.com/database/api/beta/product/npm/axios/0.21.4?include=details' \
-H 'PSKey: <your-api-key>'
# Boolean-only exists check
curl 'https://patchstack.com/database/api/beta/product/npm/axios/0.21.4/exists' \
-H 'PSKey: <your-api-key>'
  1. Create a new request, set the method, paste the URL.
  2. Under Headers, add:
    • Key: PSKey
    • Value: your API key
  3. Under Headers, add (recommended):
    • Key: Accept
    • Value: application/json
  4. For POST /batch, set the body to raw → JSON and paste the array payload.
async function* allVulnerabilities(apiKey, platform = 'npm', perPage = 100) {
const base = 'https://patchstack.com/database/api/beta/all';
let cursor = ''; // empty = bootstrap cursor mode
while (true) {
const url = `${base}?platform=${platform}&per_page=${perPage}&cursor=${encodeURIComponent(cursor)}`;
const res = await fetch(url, { headers: { PSKey: apiKey } }).then(r => r.json());
for (const vuln of res.vulnerabilities) {
yield vuln;
}
if (!res.cursor.has_more) return;
cursor = res.cursor.next_cursor;
}
}
// usage
for await (const vuln of allVulnerabilities(process.env.PATCHSTACK_KEY)) {
console.log(vuln.id, vuln.title);
}
<?php
$apiKey = getenv('PATCHSTACK_KEY');
$cursor = '';
do {
$url = 'https://patchstack.com/database/api/beta/all'
.'?platform=npm&per_page=100&cursor='.urlencode($cursor);
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['PSKey: '.$apiKey, 'Accept: application/json'],
]);
$response = json_decode(curl_exec($ch), true);
curl_close($ch);
foreach ($response['vulnerabilities'] as $vuln) {
// handle $vuln
}
$cursor = $response['cursor']['next_cursor'] ?? null;
} while ($response['cursor']['has_more'] ?? false);

StatusMeaning
401 UnauthorizedMissing or invalid PSKey header.
403 ForbiddenAPI key not authorised for the requested endpoint.
422 Unprocessable EntityInvalid parameter combination (e.g. cursor + page), invalid platform, or per_page > 500.
429 Too Many RequestsRate limit exceeded.
500Server error — please include the request id in any bug report.

When a cursor is malformed (invalid base64 or missing the v1: prefix), the endpoint returns 200 with an empty page:

{
"vulnerabilities": [],
"cursor": { "next_cursor": null, "has_more": false, "per_page": 100 }
}

  • Beta npm responses use nested objects (product, cvss, cwe, capec, version_info) whereas the v2 shape is flat. Update parsers accordingly.
  • ghsa_id was renamed to ghsa at the top level.
  • direct_url was renamed to url (the npm-flavoured shape exposes a single URL only).
  • The description field was dropped for npm (the title already includes it).
  • The response body always contains a vulnerabilities array, plus either pagination (offset mode) or cursor (cursor mode).

You can find more information about the Patchstack Threat Intelligence API on https://patchstack.com/for-hosts/. If you have integration questions, email dave.jong@patchstack.com.