POST /v1/organizations/{org_id}/projects/{id}/scans
Uploads a vulnerability scanner report for a project: JSON from Trivy, Grype or any CycloneDX report that carries vulnerabilities, or a network scanner export — Tenable Nessus (.nessus or CSV), Greenbone/OpenVAS (XML report), Qualys VMDR (XML or CSV), Rapid7 InsightVM/Nexpose (XML Export 2.0 or CSV). It is the API’s only write route: built for CI, to call on every deployment.
The scan becomes dated evidence (NIS2: Implementing Regulation 2024/2690, Annex, § 6.10.2(b)) and is checked against the project’s tracking records: a CVE declared fixed that the scan still finds is flagged “contradicted” (dementi), a CVE nothing tracks is “untracked” (hors_suivi).
Request
Section titled “Request”POST /api/v1/organizations/{org_id}/projects/{project_id}/scans?fichier=trivy.jsonAuthorization: Bearer twa_your_key_hereContent-Type: application/json
{ …the report as the scanner produced it… }| Parameter | Where | Description |
|---|---|---|
org_id |
path | The key’s organization |
project_id |
path | Scanned project (within the key’s project restriction, if any) |
fichier |
query, optional | Report name, kept in the trace (255 characters max) |
The body is the raw report, 20 MB max (beyond that, 413 without reading the rest). The format is recognised from the content: JSON, XML, then CSV recognised by its header row; the Content-Type (application/json, application/xml, text/csv) is only indicative. XML is read without entities or external references: a document that declares any is refused (422).
Only vulnerabilities with a CVE identifier are tracked; a GHSA that cites its CVE is attached to it, the others are counted (nb_hors_cve). For a network scanner, a finding citing several CVEs gives one row per CVE, purely informational findings without a CVE are ignored, and duplicates (same CVE, same host, same component, same version) are merged.
outil |
Report |
|---|---|
trivy, grype, cyclonedx |
JSON |
nessus |
.nessus (XML v2) or CSV |
openvas |
Greenbone XML report (GMP / GSA) |
qualys |
XML or CSV scan results, XML Asset Data Report |
insightvm |
XML Export 2.0 or CSV |
CI example
Section titled “CI example”trivy image --format json -o trivy.json registry.example.com/app:1.4curl -X POST "https://app.techwatchalert.com/api/v1/organizations/$ORG_ID/projects/$PROJECT_ID/scans?fichier=trivy.json" \ -H "Authorization: Bearer $TWA_API_KEY" -H "Content-Type: application/json" \ --data-binary @trivy.json
# Network scanner: the latest scan's export, as iscurl -X POST "https://app.techwatchalert.com/api/v1/organizations/$ORG_ID/projects/$PROJECT_ID/scans?fichier=network.nessus" \ -H "Authorization: Bearer $TWA_API_KEY" -H "Content-Type: application/xml" \ --data-binary @network.nessusResponse 201 Created
Section titled “Response 201 Created”Same shape as the French page: scan (tool, target, file, via: "api", counts), constats (one per CVE × host × component, with its etat), par_etat, par_actif, non_retrouvees (tracked CVEs this scan does not find: fixed, or outside what it covers).
For a network scanner, each finding also carries actif (host: IP address, or its name), actif_nom (DNS or NetBIOS name), systeme (detected OS), port (443/tcp; null for a host-level finding), reference (test identifier: Nessus plugin, Greenbone OID, Qualys QID, Rapid7 id) and titre (test name); composant is the detected product (CPE, service fingerprint), otherwise the test name. par_actif summarises the scan host by host — actif, actif_nom, systeme, ports, nb_cve (distinct CVEs), nb_dementi, nb_hors_suivi — hosts disproving a fix first. These fields are null (and par_actif an empty list) for Trivy, Grype and CycloneDX.
etat |
Meaning |
|---|---|
dementi |
declared fixed, still detected |
ecartee |
declared not applicable, detected |
hors_suivi |
no record: the component is missing from the stack, or the policy filtered it |
suivie |
open record |
acceptee |
accepted risk: its presence is expected |
Errors
Section titled “Errors”| Code | Cause |
|---|---|
403 |
key without the scans right, or plan without API access |
404 |
project outside the organization or the key’s restriction |
413 |
report larger than 20 MB |
422 |
unreadable report: malformed JSON or XML, XML declaring entities or external references, unknown format, more than 20,000 vulnerabilities, or SBOM without vulnerabilities (import it from the stack) |