GET /v1/organizations/{org_id}/projects/{id}/alerts
Alerts are created automatically when a vulnerability matches an item in a project’s stack: a CVE, or a GHSA or OSV advisory without a CVE identifier. The cve_id field carries the primary identifier. aliases lists the others, and fusion_de lists advisories that became this vulnerability (the case history is kept).
List Project Alerts
Section titled “List Project Alerts”GET /api/v1/organizations/{org_id}/projects/{project_id}/alertsAuthorization: Bearer twa_your_key_herePath Parameters
Section titled “Path Parameters”| Parameter | Type | Description |
|---|---|---|
org_id |
UUID |
Organization identifier |
project_id |
UUID |
Project identifier |
Query Parameters
Section titled “Query Parameters”| Parameter | Type | Default | Description |
|---|---|---|---|
unread_only |
boolean |
false |
If true, returns only unread alerts |
severity |
string |
— | Filter by severity (comma-separated). Values: CRITICAL, HIGH, MEDIUM, LOW |
since |
datetime (ISO 8601) |
— | Returns only alerts triggered after this date |
page |
integer ≥ 1 |
1 |
Page number |
limit |
integer 1–200 |
50 |
Alerts per page |
Response 200 OK
Section titled “Response 200 OK”{ "items": [ { "id": "018e9999-0000-7000-8000-000000000030", "cve_id": "CVE-2024-11477", "triggered_at": "2024-11-05T14:32:00Z", "is_read": false, "severity": "CRITICAL", "description": "7-Zip contains a heap-based buffer overflow vulnerability...", "vendor": "7-zip", "product": "7-zip", "cvss_score": 7.8, "is_kev": false, "has_poc": true, "tags": [ { "id": "018ec0de-0000-7000-8000-0000000000a1", "name": "production", "color": "#ef4444" }, { "id": "018ec0de-0000-7000-8000-0000000000a2", "name": "to-patch", "color": "#f59e0b" } ] }, { "id": "018e9999-0000-7000-8000-000000000031", "cve_id": "CVE-2024-38816", "triggered_at": "2024-09-13T08:00:00Z", "is_read": true, "severity": "HIGH", "description": "Applications serving static resources through the functional web...", "vendor": "vmware", "product": "spring_framework", "cvss_score": 7.5, "is_kev": false, "has_poc": false, "tags": [] } ], "total": 42, "unread_count": 7}Fields — Envelope
Section titled “Fields — Envelope”| Field | Type | Description |
|---|---|---|
items |
array |
Alerts on the current page |
total |
integer |
Total alerts matching the active filters |
unread_count |
integer |
Total unread alerts in this project (independent of filters) |
Fields — Alert
Section titled “Fields — Alert”| Field | Type | Description |
|---|---|---|
id |
string (UUID) |
Alert identifier |
cve_id |
string |
CVE identifier (e.g. CVE-2024-11477) |
triggered_at |
string (ISO 8601) |
Trigger timestamp |
is_read |
boolean |
true if at least one member has read the alert. The key is nobody: reading stays the team’s |
severity |
string |
CVE severity: CRITICAL, HIGH, MEDIUM, LOW, NONE, UNKNOWN |
description |
string | null |
English description of the CVE |
vendor |
string | null |
Identified primary vendor |
product |
string | null |
Identified primary product |
cvss_score |
float | null |
CVSS score (0.0 – 10.0) |
is_kev |
boolean |
true if listed in the CISA KEV catalog |
has_poc |
boolean |
true if at least one public PoC or exploit is known (GitHub via nomi-sec/PoC-in-GitHub, Exploit-DB, Metasploit, Nuclei) |
tags |
array<Tag> |
Team tags assigned to this CVE in this project (see Tag object) |
Tag object
Section titled “Tag object”Organization-wide shared vocabulary, assigned by the team to a CVE within a project. Empty array if none.
| Field | Type | Description |
|---|---|---|
id |
string (UUID) |
Tag identifier |
name |
string |
Label (e.g. production, to-patch) |
color |
string |
Hex color #rrggbb |
Get a Single Alert
Section titled “Get a Single Alert”GET /api/v1/organizations/{org_id}/projects/{project_id}/alerts/{alert_id}Authorization: Bearer twa_your_key_herePath Parameters
Section titled “Path Parameters”| Parameter | Type | Description |
|---|---|---|
org_id |
UUID |
Organization identifier |
project_id |
UUID |
Project identifier |
alert_id |
UUID |
Alert identifier |
Response 200 OK
Section titled “Response 200 OK”Same structure as a list item.
Errors
Section titled “Errors”| Code | Detail | Cause |
|---|---|---|
404 |
Projet introuvable |
Project does not exist, belongs to another organization, or is outside the key’s project restriction |
403 |
Cette clé API n'a pas le droit d'accéder à cette ressource. |
The alerts scope is missing from the key |
404 |
Alerte introuvable |
alert_id does not exist or does not belong to this project |
Examples
Section titled “Examples”Unread critical alerts from the last 30 days
SINCE=$(date -u -d '30 days ago' +%Y-%m-%dT%H:%M:%SZ 2>/dev/null \ || date -u -v-30d +%Y-%m-%dT%H:%M:%SZ)
curl -s \ -H "Authorization: Bearer twa_your_key_here" \ "https://app.techwatchalert.com/api/v1/organizations/${ORG_ID}/projects/${PROJECT_ID}/alerts?severity=CRITICAL,HIGH&unread_only=true&since=${SINCE}&limit=100" \ | jq '.items[] | {cve: .cve_id, score: .cvss_score, kev: .is_kev, poc: .has_poc}'CI/CD script — fail build on critical CVE with PoC
#!/bin/bashset -euo pipefail
ORG_ID="${TWA_ORG_ID}"PROJECT_ID="${TWA_PROJECT_ID}"API_KEY="${TWA_API_KEY}"BASE="https://app.techwatchalert.com/api/v1"
CRITICAL_POC=$(curl -sf \ -H "Authorization: Bearer ${API_KEY}" \ "${BASE}/organizations/${ORG_ID}/projects/${PROJECT_ID}/alerts?severity=CRITICAL&unread_only=true&limit=200" \ | jq '[.items[] | select(.has_poc == true)] | length')
if [ "$CRITICAL_POC" -gt 0 ]; then echo "ERROR: ${CRITICAL_POC} critical CVE(s) with PoC unaddressed." exit 1fi
echo "OK — no critical CVEs with PoC."Python — export alerts to CSV
import csv, httpxfrom datetime import datetime, timedelta, timezone
BASE = "https://app.techwatchalert.com/api/v1"headers = {"Authorization": "Bearer twa_your_key_here"}org_id = "018e5678-abcd-7000-8000-000000000001"project_id = "018e1234-abcd-7000-8000-000000000010"
since = (datetime.now(timezone.utc) - timedelta(days=7)).isoformat()page, all_alerts = 1, []
while True: r = httpx.get( f"{BASE}/organizations/{org_id}/projects/{project_id}/alerts", headers=headers, params={"since": since, "limit": 200, "page": page}, ).json() all_alerts.extend(r["items"]) if len(all_alerts) >= r["total"]: break page += 1
with open("alerts.csv", "w", newline="") as f: w = csv.DictWriter(f, fieldnames=["cve_id", "severity", "cvss_score", "is_kev", "has_poc", "triggered_at"]) w.writeheader() w.writerows(all_alerts)
print(f"{len(all_alerts)} alerts exported.")Project GHSA and OSV advisories
Section titled “Project GHSA and OSV advisories”Same scope as alerts (alerts). Each advisory is shown with its primary identifier, its aliases, its tier (a_patcher, haute, or none) and the stack matches.
GET /api/v1/organizations/{org_id}/projects/{project_id}/vulnerabilitiesAuthorization: Bearer twa_your_key_here| Parameter | Description |
|---|---|
source |
ghsa or osv |
palier |
a_patcher, haute or aucun |