Download OpenAPI specification:
Submit packages (PURL or uploaded archive) for analysis and retrieve task status/results.
This API supports two analysis engines selected by the optional Engine header:
dynamic-analysis (default): dynamic analysis pipeline for npm, PyPI, and VS Code extensionslastpymile: LastPyMile analysis pipeline (supports npm and PyPI only)Two submission modes are supported:
POST /api/v1/analyze/purl/POST /api/v1/archives/upload-url/ to obtain a signed upload URL + gcs_pathPUT the file to the signed URL (Google Cloud Storage)POST /api/v1/analyze/archive/ with purl + gcs_path (+ optional GitHub URL)Queues analysis for the given PURL.
The Engine header selects analysis engine:
dynamic-analysisdynamic-analysis => dynamic analysis (npm, pypi, vscode-extension)lastpymile => LastPyMile (npm and pypi only)Notes:
| Engine | string Default: dynamic-analysis Enum: "dynamic-analysis" "lastpymile" Select analysis engine. Missing/empty defaults to |
| purl required | string Package URL (must start with |
{- "purl": "pkg:npm/axios@1.14.1"
}{- "success": true,
- "request_id": "d96c0c9a-6e3c-44cb-bfb1-1b1c5b3c50b0",
- "data": {
- "task_id": 456,
- "status": "processing",
- "message": "Analysis already processing"
}
}Queues analysis for an archive previously uploaded to GCS via the signed URL from POST /api/v1/archives/upload-url/.
The Engine header selects analysis engine (same as PURL scan).
When using Engine: lastpymile, only npm and PyPI packages are supported.
Optional GitHub URL:
github_url or archive_github_url (alias); backend stores it as archive_github_url.| Engine | string Default: dynamic-analysis Enum: "dynamic-analysis" "lastpymile" Select analysis engine. Missing/empty defaults to |
| purl required | string |
| gcs_path required | string GCS object path returned by /api/v1/archives/upload-url/ |
| github_url | string or null <uri> Optional source repository URL (alias of archive_github_url) |
| archive_github_url | string or null <uri> Optional source repository URL (alias of github_url) |
{- "purl": "pkg:npm/axios@1.14.1",
- "gcs_path": "uploads/uuid/axios-1.14.1.tgz"
}{- "success": true,
- "request_id": "string",
- "data": {
- "task_id": 0,
- "status_url": "string",
- "message": "string"
}
}Returns a signed URL for direct upload to GCS plus a gcs_path token to pass to POST /api/v1/analyze/archive/.
After receiving the signed URL, upload the file using:
PUT {url} with the archive bytes (content-type depends on file type).| filename required | string Original archive filename (e.g. .tgz, .whl, .tar.gz, .zip, .vsix) |
{- "filename": "axios-1.14.1.tgz"
}{- "success": true,
- "request_id": "5a7ffdf8-44a9-4c7f-84b5-68e5a38cb7fb",
- "data": {
- "gcs_path": "uploads/uuid/axios-1.14.1.tgz",
- "message": "Upload URL generated successfully"
}
}Returns task metadata. When status is completed and a report is available,
the field report_blob_url is included.
Report payload at report_blob_url depends on engine:
dynamic-analysis -> DynamicAnalysisReportlastpymile -> LastPyMileReport| task_id required | integer >= 1 |
{- "success": true,
- "request_id": "0b7d1d7f-6b9c-4e14-9a67-f5f0d2d6b9bf",
- "data": {
- "task_id": 123,
- "purl": "pkg:pypi/requests@2.25.1",
- "engine_type": "dynamic-analysis",
- "status": "processing",
- "created_at": "2026-04-09T10:20:30.123456+00:00"
}
}| page | integer >= 1 Default: 1 |
| page_size | integer [ 1 .. 100 ] Default: 20 |
| status | string (TaskStatus) Enum: "queued" "processing" "completed" "failed" "timeout" |
{- "success": true,
- "request_id": "string",
- "data": {
- "items": [
- {
- "task_id": 0,
- "purl": "string",
- "engine_type": "dynamic-analysis",
- "status": "queued",
- "created_at": "string",
- "status_url": "string",
- "error_message": "string"
}
], - "page": 0,
- "page_size": 0,
- "total": 0
}
}