Alert Triage API
The legacy Alert Triage API held one table that did two jobs: pattern rules that changed the action for a class of packages, and entries that suppressed one specific finding. In the new API those are two different resources — policy rules and alert resolutions — so the first step of any migration is deciding which job each legacy entry was doing.
- Matches by pattern (ecosystem, version prefix, severity range, …) → policy rule
- Suppresses one finding in one place, or was created from an alert you dismissed → alert resolution
Legacy Contract
GET /orgs/{org_slug}/triage/alerts returns { "results": [...], "nextPage": ... }, paginated with page and per_page (1–100, default 30) and sorted by created_at or updated_at via sort and direction. nextPage is null on the last page. Each entry carries the matcher fields listed in the translation table below, plus state, note, and timestamps.
POST /orgs/{org_slug}/triage/alerts is a batch under the alertTriage key: omit uuid to create an entry, provide it to update one. Returns { "result": "..." }, as does DELETE /orgs/{org_slug}/triage/alerts/{uuid}.
Translating Values
Legacy state to rule action:
Legacy state | New action | Notes |
|---|---|---|
block | error | Shown as Block in the dashboard |
warn | warn | |
monitor | monitor | |
ignore | ignore | Consider an alert resolution instead when the entry targeted one specific finding |
inherit | — | No rule needed; the baseline preset decides |
Legacy matcher fields to selector fields:
| Legacy field | Selector |
|---|---|
packageType | artifact.type |
packageNamespace | artifact.namespace |
packageName | artifact.name |
packageVersion (exact) | artifact.version |
packageVersion with a * suffix, e.g. 4.* | "artifact.version": { "$prefix": "4." } |
alertType | finding.alertType |
cvssScoreCmp, e.g. >=7.5 | "finding.cvss": { "$gte": 7.5 } |
cveOrGhsaId | finding.cveId or finding.ghsaId; use $or to match either |
fixAvailable: "available" / "unavailable" | "finding.fixAvailable": true / false |
kevs: "exist" / "none" | "finding.hasKEV": true / false |
reachability: "reachable" / "unreachable" | "finding.reachability": "reachable" / "unreachable" |
reachability: "other" | "finding.reachability": { "$in": ["maybe_reachable", "direct_dependency", "pending", "missing_support", "undeterminable_reachability", "unknown", "error"] } |
Any field set to "*" or null | Omit it |
patchAvailable has no equivalent and does not translate. The legacy field tested your patch entitlement, while the new finding.cvePatchStatus reports whether a Socket patch exists or is applied for the finding — a different question. If you relied on patchAvailable, decide what you actually want those rules to do (for many orgs that is finding.fixAvailable, possibly combined with finding.cvePatchStatus) and write them fresh rather than translating mechanically.
Legacy entries carrying an alertKey identified one specific alert instance. There is no selector field for it — recreate those as alert resolutions scoped to the repository, package, version, and alert type of the finding they were suppressing.
Example: A Pattern Rule Becomes a Policy Rule
A legacy entry monitoring unreachable critical CVEs in the lodash 4.x line:
{
"alertTriage": [
{
"packageType": "npm",
"packageName": "lodash",
"packageVersion": "4.*",
"alertType": "criticalCVE",
"cvssScoreCmp": ">=7.5",
"reachability": "unreachable",
"state": "monitor",
"note": "Unreachable in our services"
}
]
}becomes a rule on the policy that governs the relevant repositories:
curl -u "$SOCKET_API_TOKEN:" -X POST \
-H "Content-Type: application/json" \
-d '{
"name": "Monitor unreachable critical CVEs in lodash 4.x",
"action": "monitor",
"note": "Unreachable in our services",
"position": "last",
"vigil_selector": {
"finding.alertType": "criticalCVE",
"finding.cvss": { "$gte": 7.5 },
"finding.reachability": "unreachable",
"artifact.type": "npm",
"artifact.name": "lodash",
"artifact.version": { "$prefix": "4." }
}
}' \
https://api.socket.dev/v0/orgs/$ORG/alert-policies/default/rulesReturns 201 with the stored rule:
{
"id": "1b2c3d4e-5f60-4718-9a2b-3c4d5e6f7a8b",
"alert_policy_id": "7d9e2f10-4a3b-4c5d-8e6f-1a2b3c4d5e6f",
"rank": "a1",
"name": "Monitor unreachable critical CVEs in lodash 4.x",
"vigil_selector": {
"finding.alertType": "criticalCVE",
"finding.cvss": { "$gte": 7.5 },
"finding.reachability": "unreachable",
"artifact.type": "npm",
"artifact.name": "lodash",
"artifact.version": { "$prefix": "4." }
},
"action": "monitor",
"note": "Unreachable in our services",
"created_by": "0f8a3c1e-2b4d-4e5f-9a6b-7c8d9e0f1a2b",
"updated_by": "0f8a3c1e-2b4d-4e5f-9a6b-7c8d9e0f1a2b",
"created_at": "2026-08-06T09:15:02.000Z",
"updated_at": "2026-08-06T09:15:02.000Z"
}Placement is controlled by exactly one of position (first or last), before_rule_id, after_rule_id, or an explicit rank. Send none of them and the rule is placed first. Prefer position and the before/after forms over raw ranks. GET .../rules returns { "items": [ ... ] } in evaluation order, PUT .../rules/{rule_id} changes only the fields you send and moves the rule if you include a placement field, and DELETE .../rules/{rule_id} returns { "result": "..." }.
Example: A Suppressed Finding Becomes an Alert Resolution
A legacy entry that suppressed one specific CVE in one repository — an exact package version, a specific CVE, state ignore — was never really a rule. It becomes a resolution:
curl -u "$SOCKET_API_TOKEN:" -X POST \
-H "Content-Type: application/json" \
-d '{
"reason": "tolerable_risk",
"comment": "Dev-only dependency, not shipped",
"vigil_selector": {
"finding.alertType": "criticalCVE",
"finding.cveId": "CVE-2024-29041",
"location.repo": "my-org/internal-tools",
"artifact.type": "npm",
"artifact.name": "lodash",
"artifact.version": "4.17.20"
}
}' \
https://api.socket.dev/v0/orgs/$ORG/alerts/resolutionscomment is the free-form note (up to 1024 characters); there is also reason_text (up to 256 characters), meant for a short label when reason is other. Both are optional.
Returns 201 with the resolution: its uuid, the selector, and the derived summary fields (alert_type, repo, repo_label, artifact_type, artifact_namespace, artifact_name, artifact_version), each null when the resolution is not limited to a single value for that dimension.
GET /orgs/{org_slug}/alerts/resolutions lists them with cursor pagination — pass the previous response's endCursor as startAfterCursor, with per_page (1–100, default 30) and direction. DELETE .../resolutions/{uuid} returns { "result": "..." }, and the alerts it was hiding reappear on the next refresh.
Related Pages
- Security Policy API — the other half of the legacy configuration.
- Vigil Selectors — the full field and operator reference.
- Resolve Alerts — scopes, reasons, and repository-restricted tokens.
- Updating API Integrations — endpoint mapping and token scopes.
Updated 1 day ago
