API Reference
Table of contents
Base URL and authentication
https://kief.dev/api/vekt
All requests must include an Authorization header with your API key:
Authorization: Bearer vkt_live_xxxxxxxxxxxxxxxxxxxx
Get an API key at kief.dev/vekt/signup.
Rate limiting
Every scan response includes rate limit headers:
| Header | Description |
|---|---|
X-Vekt-Request-Id |
Unique request identifier |
X-RateLimit-Remaining |
Scans remaining in the current period |
When your quota is exhausted, the API returns 429 Too Many Requests with a Retry-After header. On paid plans, overage scans continue and are billed at $0.005 per scan.
POST /api/vekt/scan
Submit a lockfile for scanning. Returns a list of scan results grouped by lockfile.
Request
Content type: application/json
POST /api/vekt/scan
Authorization: Bearer <api-key>
Content-Type: application/json
Request body:
{
"lockfile_type": "package-lock.json",
"content": "<raw lockfile content as a string>"
}
| Field | Type | Required | Description |
|---|---|---|---|
lockfile_type |
string | Yes | Filename of the lockfile format (see supported lockfile types) |
content |
string | Yes | Raw text content of the lockfile |
Content type: multipart/form-data
You can also upload the lockfile as a file:
POST /api/vekt/scan
Authorization: Bearer <api-key>
Content-Type: multipart/form-data
Form fields:
| Field | Type | Required | Description |
|---|---|---|---|
file |
file | Yes | The lockfile to scan. The filename is used to detect the type if lockfile_type is not provided. |
lockfile_type |
string | No | Override the lockfile type detection from the filename. |
Maximum request size: 5 MB.
Response
HTTP 200 with a JSON array of scan results. An empty array means no findings were detected.
[
{
"lockfile": "package-lock.json",
"type": "package-lock.json",
"ecosystem": "npm",
"packages_scanned": 312,
"findings": [
{
"package": "lodash",
"version": "4.17.15",
"ecosystem": "npm",
"malicious": false,
"security_holder": false,
"vulns": [
{
"id": "GHSA-jf85-cpcp-j695",
"summary": "Prototype Pollution in lodash",
"threat_level": "Vulnerability",
"aliases": ["CVE-2019-10744"],
"url": "https://osv.dev/vulnerability/GHSA-jf85-cpcp-j695"
}
]
}
]
}
]
Response fields
| Field | Type | Description |
|---|---|---|
lockfile |
string | Lockfile that was scanned |
type |
string | Lockfile format identifier |
ecosystem |
string | Ecosystem identifier (e.g., npm, PyPI, crates.io) |
packages_scanned |
number | Total packages checked |
findings |
array | Packages with findings |
findings[].package |
string | Package name |
findings[].version |
string | Package version |
findings[].ecosystem |
string | Ecosystem identifier |
findings[].malicious |
boolean | true if any finding is a confirmed malicious package |
findings[].security_holder |
boolean | true if the package is an inert registry security-placeholder |
findings[].vulns |
array | List of individual vulnerability or advisory findings |
findings[].vulns[].id |
string | Advisory identifier (e.g., GHSA-xxxx-yyyy-zzzz, CVE-2024-XXXXX, MAL-2024-XXXX) |
findings[].vulns[].summary |
string | Human-readable description of the finding |
findings[].vulns[].threat_level |
string | "Malicious", "Vulnerability", or "SecurityHolder" |
findings[].vulns[].aliases |
array | Alternative IDs for the same advisory |
findings[].vulns[].url |
string | Link to the full advisory |
Example: curl with JSON body
curl -s -X POST https://kief.dev/api/vekt/scan \
-H "Authorization: Bearer vkt_live_xxxxxxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"lockfile_type": "package-lock.json",
"content": "'"$(cat package-lock.json | jq -Rs .)"'"
}'
Example: curl with file upload
curl -s -X POST https://kief.dev/api/vekt/scan \
-H "Authorization: Bearer vkt_live_xxxxxxxxxxxxxxxxxxxx" \
-F "file=@package-lock.json"
Example: pipe a lockfile
cat Cargo.lock | \
jq -Rs '{"lockfile_type": "Cargo.lock", "content": .}' | \
curl -s -X POST https://kief.dev/api/vekt/scan \
-H "Authorization: Bearer vkt_live_xxxxxxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d @-
Example response (clean scan)
[]
An empty array means all packages in the lockfile are clean.
Error responses
All error responses use the following format:
{
"error": "Human-readable description of the problem"
}
| Status | Description |
|---|---|
| 400 | The request body is malformed, the lockfile_type is not recognized, or the content cannot be parsed |
| 401 | The Authorization header is missing or the API key is invalid |
| 413 | The request body exceeds the 5 MB limit |
| 415 | Unsupported Content-Type (must be application/json or multipart/form-data) |
| 429 | You have exceeded your scan quota for the current period |
| 500 | An unexpected server error occurred |
| 502 | The scanner binary returned an error |
Status codes
| Code | Meaning |
|---|---|
| 200 | Scan completed. Response body contains the results array (may be empty). |
| 400 | Bad request -- check the request format or lockfile type. |
| 401 | Authentication required -- check your API key. |
| 413 | Lockfile too large -- maximum 5 MB per request. |
| 415 | Unsupported Content-Type. |
| 429 | Rate limit exceeded -- check Retry-After header. |
| 500 | Server error -- safe to retry. |
| 502 | Scanner error -- the lockfile may be malformed. |