API reference Resources
Issues
The standing conditions alerts group into, their triage and mutes.
9 operations
The Issues index
Query parameters
The filter expression, e.g. all;severity~in~critical;tags~nin~needs review.
The first segment is the join (all or any); each later segment is field~op~values, with op one of in, nin, before, after and values separated by commas. A malformed segment is ignored; a field this list does not have is a 400 naming it.
Free text over the title, summary, rule, source and subject name. ANDs with the expression whichever way its conditions are joined.
Where the previous page stopped: its next_cursor, carried back as given. Opaque. One that cannot be read starts from the top rather than failing the page — it is a link a browser kept.
Rows on this page. Default 50, clamped to 1..=200.
Response200
How many issues match this filter and search, across every page. What the list's position rail counts against; not what is left after the cursor.
How many are open. The count beside the page title.
Every issue this workspace holds, whatever the filter.
The cursor for the next page; null on the last one.
List issue groups
Issues grouped by what raised them (by=source, the default) or by what they are about (by=subject), with counts over the whole match rather than a page. Narrowed by f and q only: status, severity, kind, subject_kind and subject_id are accepted by GET /issues but ignored here, so say those in f (for example status~in~open).
Query parameters
The filter expression, exactly as listIssues takes it.
Free text, exactly as listIssues takes it.
What to group by: source (what raised the issue — a policy, an engine, a scanner; the default) or subject (what it is about). Anything else is a 400.
Response200
Worst severity first, then the larger group, then the key.
Issues in this group across the whole match, not a page of it.
source_id or subject_id. Expanding the group is listIssues with source~in~<key> (or subject~in~<key>) added to f.
source_kind (policy, engine, scanner) or subject_kind (artifact, machine, …), by by.
The most recent last_seen_at in the group, RFC 3339.
How many different rules the group's issues were raised under: for an engine or a scanner, how many kinds of problem the group holds.
The source kinds among them, sorted.
Every mute holding in this workspace right now
Gated on ViewAlert and not TriageAlert: reading what has been silenced is exactly the review this mechanism depends on, and requiring the grant that creates mutes in order to read them would hide the silencers from everybody except the people who make them.
Response200
Live only — neither expired nor lifted. The question this answers is what is being silenced right now, and a list mixing in last quarter's is one nobody can read the answer off. The audit log is where an expired mute is still visible.
When it lifts on its own. Always within 90 days of created_at. null: it holds until somebody lifts it.
Why, in the words of whoever muted it. Never empty.
Errors
- 401
No valid session
- 403
Caller lacks alerts:read in this workspace
Lift a mute
Lifts a mute before it expires. Answers 204 whether or not the mute was still in force, so lifting twice is not an error. A malformed id is a 404.
Path parameters
Response204
Lifted, or there was nothing live to lift
Errors
- 401
No valid session
- 403
Caller lacks alerts:triage in this workspace
One issue
The same fields as a row of GET /issues, plus evidence. An unknown id, another workspace's, a deleted one, or a string that is not an id at all is a 404. A suppressed issue is returned, although the default list hides it.
Path parameters
Response200
What raised this issue: engine, policy or scanner; source_id says which one. Both are always present.
The free-text labels somebody put on this issue — not on the artifact it is about, which carries its own set. Present on the list so a queue renders them without a second call per row.
For an issue an AI-tool policy raised: each item the policy matched in the tool's latest settings read, with the file, its scope and project, the vendor's key, and the item. Recomputed on every GET /issues/{id}, so it never shows a match that no longer holds. Absent on the list and on issues no AI-tool policy raised; empty when the policy no longer matches the latest read.
What matched. kind says which of the optional fields can be present.
Where the item was read from — a file, a registry key or a tool's own settings store — with the home folder shown as ~.
The vendor's own key: permissions.allow, mcpServers, env.
managed, user, project or default.
For a project file: which project, ~-collapsed.
The person this issue is about.
Only two subject kinds carry a person: a connection_record that is a person's account, and an os_user. An issue about an artifact or a machine always has null here.
The suggested fix, as a paragraph. null where none is proposed; today only machine_tamper issues carry one.
The subject's own name where it has one. null for a subject that is not an artifact, or one that has since been removed — an issue outlives its artifact, because "what was wrong with the file that used to be here" stays worth asking.
An issue Oxelone closed by itself, and why. Both fields are always present together. It is never set when a person closed the issue.
Why it was closed, in one sentence.
Who closed it: always Oxelone.
Errors
- 404
No such issue in this workspace
Move an issue through triage
Gated on TriageAlert, not ViewAlert: deciding that a condition is dealt with is a different act from reading that it exists, and only one of them changes what the next person sees.
Path parameters
Request bodyTriageRequest
open, acknowledged, resolved or suppressed.
suppressed only hides the issue from the default list; it stops nothing. Alerts keep being written and last_seen_at keeps moving. To silence an issue, mute it with POST /issues/{issue}/mute, which takes a reason and an expiry and is audited.
Response200
Triaged
Errors
- 400
Unknown status
- 404
No such issue in this workspace
Mute an issue
Silences the condition the issue groups on: its subject, source and rule. Needs the permission to triage alerts. A reason is required, and expires_at must be sent, either as a date within 90 days or as null for a mute that holds until somebody lifts it.
Path parameters
Request bodyMuteRequest
When it lifts, RFC 3339. Must be in the future and within 90 days.
Required, and may be null: null holds the mute until somebody lifts it. Leaving the field out is a 400, so a missing date never silences an issue forever by accident.
Why this is being silenced. Required, and it is the whole reason the mechanism is safe to have.
Response200
When it lifts on its own. Always within 90 days of created_at. null: it holds until somebody lifts it.
Why, in the words of whoever muted it. Never empty.
What this mute silences, with subject_id, source_kind, source_id and rule: compare these against an issue's own fields to tell whether it is muted.
Who silenced it. null only if the user row is gone, which ON DELETE RESTRICT exists to prevent — optional so a reader is never a NOT NULL promise away from a 500.
Errors
- 400
No reason, no
expires_atfield, or a date that is past or beyond 90 days- 401
No valid session
- 403
Caller lacks alerts:triage in this workspace
- 404
No such issue in this workspace
Tamper events behind an issue
The tamper events behind a machine_tamper issue, newest first, at most 200. A 404 for an id this workspace does not hold and for an issue that is not machine_tamper.
Path parameters
Response200
The events behind this issue, newest first: those received since the issue was first seen, at most 200.
RFC 3339, the agent's clock.
false for a blocked attempt, which changed nothing and never holds Tampered.
What happened: entry_removed, entry_modified, file_deleted, acl_changed, user_disable_setting, system_path_override, restore_backoff, service_stopped_unsanctioned, service_dacl_changed, binary_mismatch, config_mismatch, companion_killed or self_protect_denied.
The event described in one sentence.
self_protect_denied: what it would have done — delete, stop_service, ….
The machine the issue is about.
Its hostname; null if the workspace no longer holds the row.
Errors
- 404
No such machine_tamper issue in this workspace