Dependency Vulnerability Scan API
Check up to 50 open-source dependencies against OSV.dev in a single call. Returns CVE aliases, a computed CVSS base score, CWE ids, and the exact versions that fix each advisory.
Don't have an API key?
Sign in to your account to create and manage your API keys.
Integration guide
Copy a snippet, replace your API key, run. Works in any HTTP client — examples below in cURL, JavaScript, and Python.
/api/scan-dependencieshttps://www.apipick.comCheck open-source packages against the OSV.dev vulnerability database
packagesarrayrequiredUp to 50 objects, each with ecosystem, name, and an exact installed version. [{"ecosystem":"npm","name":"lodash","version":"4.17.15"}]
curl -X POST "https://www.apipick.com/api/scan-dependencies" \
-H "Content-Type: application/json" \
-H "x-api-key: YOUR_API_KEY" \
-d '{
"packages": [
{
"ecosystem": "npm",
"name": "lodash",
"version": "4.17.15"
},
{
"ecosystem": "PyPI",
"name": "requests",
"version": "2.19.0"
}
]
}'{
"summary": {
"packages_scanned": 2,
"vulnerable_packages": 2,
"total_vulnerabilities": 8,
"by_severity": {
"critical": 1,
"high": 3,
"medium": 4,
"low": 0,
"none": 0,
"unknown": 0
},
"highest_cvss_score": 9.8
},
"results": [
{
"ecosystem": "npm",
"name": "lodash",
"version": "4.17.15",
"vulnerable": true,
"highest_severity": "HIGH",
"highest_cvss_score": 7.4,
"vulnerability_count": 6,
"vulnerabilities": [
{
"id": "GHSA-35jh-r3h4-6jhm",
"aliases": [
"CVE-2021-23337"
],
"cve": "CVE-2021-23337",
"summary": "Command Injection in lodash",
"severity": "HIGH",
"cvss_score": 7.2,
"cvss_vector": "CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:H",
"cwe_ids": [
"CWE-77"
],
"published": "2021-02-15T00:00:00Z",
"fixed_versions": [
"4.17.21"
],
"advisory_url": "https://osv.dev/vulnerability/GHSA-35jh-r3h4-6jhm"
}
],
"error": null
}
],
"source": "OSV.dev (Google Open Source Vulnerabilities, CC-BY-4.0)",
"credits_used": 5,
"remaining_credits": 95
}Built for Real-World Use Cases
Release Gating
Fail a build when any dependency crosses a CVSS threshold. The numeric score makes the policy a one-line comparison instead of a string match.
Coding Agents
Let an agent check a version before it writes it into a manifest, and suggest the fixed version in the same turn.
Lockfile Audits
Batch a whole manifest through in chunks of 50 and get one severity rollup per service, without running a scanner in CI.
Vendor Due Diligence
Score a third party's declared dependency set against public advisories before you sign, using data you can cite.
Response Fields
| Field | Type | Description |
|---|---|---|
| summary.vulnerable_packages | integer | How many of the submitted packages have at least one advisory |
| summary.by_severity | object | Advisory counts keyed by critical / high / medium / low / none / unknown |
| summary.highest_cvss_score | number | null | Highest CVSS base score across the whole scan |
| results[].vulnerable | boolean | Whether this package version has any non-withdrawn advisory |
| results[].vulnerabilities[].id | string | OSV advisory id, e.g. GHSA-35jh-r3h4-6jhm |
| results[].vulnerabilities[].cve | string | null | CVE alias where one exists |
| results[].vulnerabilities[].severity | string | CRITICAL, HIGH, MEDIUM, LOW, NONE, or UNKNOWN |
| results[].vulnerabilities[].cvss_score | number | null | CVSS v3.1 base score computed from the advisory's vector |
| results[].vulnerabilities[].cwe_ids | string[] | CWE weakness classifications for the advisory |
| results[].vulnerabilities[].fixed_versions | string[] | Versions of this package that resolve the advisory |
| results[].error | string | null | Set when this one package could not be checked; the rest still return |
| credits_used | integer | Credits deducted for this request |
| remaining_credits | integer | Credits remaining in your account |
Rate limits
Throttling is per API key, sliding 60-second window. Hit the limit and you get a clean 429 with a Retry-After header.
20req/min
Per API key, per endpoint. Sliding 60-second window.
3concurrent
Max simultaneous in-flight requests per API key.
X-RateLimit-LimitMaximum requests allowed per minuteX-RateLimit-RemainingRequests remaining in the current windowX-RateLimit-ResetSeconds until the current window resetsRetry-AfterSeconds to wait before retrying (only on 429)HTTP/1.1 429 Too Many Requests
Retry-After: 12
X-RateLimit-Limit: 20
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 12
{
"error": "rate_limit_exceeded",
"message": "Rate limit exceeded: 20 requests/minute per API key. Retry after 12s.",
"retry_after": 12
}Data Source & Licensing
Advisories come from OSV.dev, Google's open vulnerability database, published under CC-BY-4.0. OSV aggregates the GitHub Advisory Database, the Go vulnerability database, RustSec, PyPA, and the major distribution security trackers into a single schema. We add the CVSS base-score computation and the per-package rollup.
Frequently Asked Questions
Q: Where does the vulnerability data come from?
A: OSV.dev, Google's open vulnerability database. It aggregates the GitHub Advisory Database, the Go vulnerability database, RustSec, PyPA, and the distro security trackers into one schema, and publishes it under CC-BY-4.0. Advisories are typically available within hours of publication.
Q: How is the CVSS score calculated?
A: OSV advisories carry the CVSS vector string but not the number. We compute the CVSS v3.1 base score from that vector using the official formula, so you get a value you can threshold on directly. Where an advisory has no v3 vector (v4-only, or an ecosystem advisory without one), cvss_score is null and severity falls back to the publisher's own rating.
Q: Can I scan a whole lockfile?
A: Yes — parse it on your side and send up to 50 packages per call. One call costs 5 credits regardless of how many packages it carries, so a 50-package batch is 0.1 credits per package. For larger manifests, split into batches of 50.
Q: Does it support version ranges?
A: No. Send the exact installed version, the way it appears in your lockfile (4.17.15, not ^4.17.0). OSV matches ranges against a concrete version to decide whether that version is affected, so a range as input has no single answer.
Q: What happens if one package lookup fails?
A: The scan still returns. That package carries an error field and is excluded from the summary counts, while every other package reports normally. A response also sets packages_failed so you know the rollup is incomplete.