CVE/Analytics
API Reference
Programmatic SBOM scanning

Automate the SBOM scanner. curl-friendly. CI-ready.

The same engine that powers /sbom is a plain HTTP API. Point it at a CycloneDX, SPDX, package.json, or requirements.txt and it returns JSON, SARIF, CSV, or a CycloneDX VEX document. Perfect for GitHub Actions, nightly jobs, or a tiny Python script. Full OpenAPI spec lives at /api/docs.

Endpoints

POST
/api/sbom/scan

Scan an SBOM/manifest. Accepts JSON, multipart, or raw CycloneDX/SPDX. Query: format (json|sarif|csv|vex), include=vex, fail_on=any|low|medium|high|critical.

GET
/api/sbom/{scan_id}

Re-fetch a stored scan in any format. Query: format (json|sarif|csv|vex).

GET
/api/sbom/{scan_id}/export.pdf

Branded PDF report with VEX-style findings table.

POST
/api/sbom/vex

Build a CycloneDX VEX 1.5 document from an array of triage decisions.

Authentication

The API is public: no key is required and you get 5 scans/min per IP out of the box. For CI/CD you'll want a key so a shared pool of runners doesn't throttle itself. Ask the admin to create one for you.

Authorization: Bearer cvea_<your-key>
Or send it as X-API-Key. Default rate limit for keyed clients: 60 req/min (configurable per key).

Recipes

1. Minimal public scan

curl · public
# Public rate limit: 5 scans / minute per IP, 20 / hour
curl -s -X POST "https://cveanalytics.in/api/sbom/scan" \
  -H "Content-Type: application/json" \
  --data '{"content":"{\"name\":\"my-app\",\"dependencies\":{\"lodash\":\"4.17.15\"}}", "name":"my-app"}'

2. Authenticated scan with API key

curl · api-key
# With API key (ask the admin for one). Default limit: 60 req/min
export CVEA_KEY="cvea_your_key_here"

curl -s -X POST "https://cveanalytics.in/api/sbom/scan" \
  -H "Authorization: Bearer $CVEA_KEY" \
  -H "Content-Type: application/json" \
  --data-binary @sbom.json

3. File upload (multipart/form-data)

curl · multipart
# Upload the SBOM as a file (great for ci/cd runners)
curl -s -X POST "https://cveanalytics.in/api/sbom/scan" \
  -H "Authorization: Bearer $CVEA_KEY" \
  -F "file=@sbom.cdx.json" \
  -F "name=my-service"

4. Raw CycloneDX body

curl · cyclonedx
# Raw CycloneDX / SPDX body (what most tools produce)
curl -s -X POST "https://cveanalytics.in/api/sbom/scan" \
  -H "Content-Type: application/vnd.cyclonedx+json" \
  -H "X-SBOM-Name: my-app" \
  --data-binary @sbom.cdx.json

5. SARIF output for GitHub Code Scanning

curl · sarif
# SARIF output (ingestible by GitHub Code Scanning)
curl -s -X POST "https://cveanalytics.in/api/sbom/scan?format=sarif" \
  -H "Authorization: Bearer $CVEA_KEY" \
  -H "Content-Type: application/vnd.cyclonedx+json" \
  --data-binary @sbom.cdx.json \
  -o report.sarif

6. CSV output for spreadsheets / Jira

curl · csv
# CSV output (spreadsheet / Jira import)
curl -s -X POST "https://cveanalytics.in/api/sbom/scan?format=csv" \
  -H "Content-Type: application/json" \
  --data '{"content": "$(cat requirements.txt | jq -Rs .)"}' \
  -o findings.csv

7. Pipeline gating with fail_on

The endpoint returns HTTP 422 when findings at or above the requested severity exist, so your pipeline can fail without extra tooling.

curl · fail_on=high
# Pipeline gating: exit non-zero when HIGH+ findings exist
RES=$(curl -s -o /tmp/report.json -w "%{http_code}" \
  -X POST "https://cveanalytics.in/api/sbom/scan?fail_on=high" \
  -H "Authorization: Bearer $CVEA_KEY" \
  -H "Content-Type: application/vnd.cyclonedx+json" \
  --data-binary @sbom.cdx.json)

if [ "$RES" = "422" ]; then
  echo "::error::High+ vulnerabilities found - failing the build"
  cat /tmp/report.json | jq '.severity_counts'
  exit 1
fi

8. Re-fetch a prior scan

curl · fetch
# Re-fetch a prior scan (great for multi-step pipelines)
SCAN_ID="4e31e967de9b4109926524536b139500"
curl -s "https://cveanalytics.in/api/sbom/$SCAN_ID?format=sarif" -o report.sarif

9. GitHub Action — SARIF + Code Scanning

yaml · github workflow
# .github/workflows/sbom-scan.yml
name: SBOM Vulnerability Scan
on: [push, pull_request]

jobs:
  scan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Generate CycloneDX SBOM
        uses: anchore/sbom-action@v0
        with:
          format: cyclonedx-json
          output-file: sbom.cdx.json

      - name: Scan with CVE/Analytics
        id: scan
        env:
          CVEA_KEY: ${{ secrets.CVEA_API_KEY }}
        run: |
          HTTP=$(curl -s -o report.sarif -w "%{http_code}" \
            -X POST "https://cveanalytics.in/api/sbom/scan?format=sarif&fail_on=high" \
            -H "Authorization: Bearer $CVEA_KEY" \
            -H "Content-Type: application/vnd.cyclonedx+json" \
            --data-binary @sbom.cdx.json)
          echo "http=$HTTP" >> $GITHUB_OUTPUT

      - name: Upload SARIF to GitHub Code Scanning
        if: always()
        uses: github/codeql-action/upload-sarif@v3
        with:
          sarif_file: report.sarif

      - name: Fail on high+ severity
        if: steps.scan.outputs.http == '422'
        run: exit 1

10. Python one-liner

python · requests
# scan.py — one-shot programmatic client
import os, sys, requests

API  = "https://cveanalytics.in/api"
KEY  = os.environ["CVEA_API_KEY"]
SBOM = open("sbom.cdx.json","rb").read()

r = requests.post(
    f"{API}/sbom/scan",
    params={"format": "json", "fail_on": "high"},
    headers={
        "Authorization": f"Bearer {KEY}",
        "Content-Type":  "application/vnd.cyclonedx+json",
    },
    data=SBOM,
    timeout=60,
)

print("status:", r.status_code)
print("findings:", r.json().get("stats", {}))
if r.status_code == 422:
    print("Gate fired. Severity counts:", r.json()["severity_counts"])
    sys.exit(1)

Severity derivation

We parse the OSV-provided CVSS v3.x vector string on every finding and map the computed base score to CRITICAL / HIGH / MEDIUM / LOW using FIRST.org's standard buckets. When a finding has no vector, severity falls back to UNKNOWN and does not trip fail_on gates (set fail_on=any if you want zero-tolerance builds).