Alerts
An alert is a signal that an
alerting detection sent into triage,
carried as a resource so Perpetual can score it, merge it, and either promote it
to a case or expire it. An alert's id is prefixed ALR_.
An alert belongs to a Space and pairs one to one with the
signal that created it, so its name is that signal's id. Perpetual writes
alerts, and the API exposes no create or update route. Beyond the signal it
came from, an alert carries the priority and summary that scoring assigned, a
retained copy of the signal rows behind it, and the promotion bar and remaining
budget it faced at the moment Perpetual decided it. Perpetual never deletes an
alert. Alert triage covers how Perpetual
makes the decision.
Statuses
An alert's status is one of seven values.
| Value | Description |
|---|---|
Processing | Awaiting the routing decision that either merges the alert into an existing one or sends it on to scoring. |
Queued | Awaiting the promotion decision. Scoring runs from here. |
Accumulating | A buffer holding follow-up signals that share this alert's accumulationKeyValue until its window closes. |
Promoted | Perpetual opened a case from the alert and linked the two. |
Merged | Another alert absorbed this one, along with the signals behind it. The survivor is the alert Perpetual scores and promotes. |
Expired | The alert aged out of the queue without promoting, past the window its Space sets. |
TriageFailure | Routing or scoring exhausted its retries. Perpetual never promotes such an alert on its own. |
Signal evidence
An alert keeps its own copy of the signal rows behind it, so the evidence
survives later changes to the source dataset. signalSnapshotColumns carries
the merged column schema and signalSnapshotRows carries the rows.
Perpetual retains at most ten rows. An alert that absorbed more signals than
that still names every one of them in signalIds and counts them all in
totalSignalCount, so both can exceed the number of rows you get back.
primarySignalId names the one signal Perpetual created the alert from.
Promotion reads that row specifically and fails without it.
Timeline
The timeline is the alert's audit log. getById returns it under auditLogs,
and each entry records one change.
| Field | Type | Description |
|---|---|---|
id | integer | Audit-log entry ID. |
version | integer | The alert version this entry produced. |
timestamp | timestamp | When the change occurred. |
userId | string | The user who made the change. Null when the actor was not a user. |
chatId | string | The chat that made the change, prefixed CHT_. Null when not a chat. |
changes | object | The fields that changed. Covers status, currentPriority, summary, signalIds, promotionThresholdAtDecision, and budgetRemainingAtDecision. |
addedRelationships | array<object> | The relationships the change added, each with a relationshipKind and a toResourceId. |
removedRelationships | array<object> | The relationships the change removed, with the same two fields. |
reason | string | Why triage made the change. Null when triage recorded none. |
A merge or a promotion writes only a ContainsAlert relationship, so its entry
carries addedRelationships and an empty changes.
Inputs
No caller creates or updates an alert. The one field a caller supplies belongs
to promotion, which opens a case from a Queued or TriageFailure alert and
bypasses both the promotion bar and the budget gate. Promotion returns the
caseId it opened, and it fails on an alert in any other status.
| Field | Type | Required | Description |
|---|---|---|---|
promoteWithoutInvestigation | boolean | Required | Whether to open the case without running the automated investigation on it. |
Outputs
The list endpoint returns a subset. sourceViewName, signalSnapshotColumns,
signalSnapshotRows, totalSignalCount, promotionThresholdAtDecision,
budgetRemainingAtDecision, promotedCaseId, mergedIntoAlertId,
mergedAlertIds, and auditLogs come back from getById only.
| Field | Type | Description |
|---|---|---|
status | enum | The alert's status. |
createdByDetectionId | string | The detection whose signal created the alert, prefixed DET_. Null when the alert records no detection. |
createdByDetectionName | string | The detection's display name as it stood when Perpetual created the alert, so a later rename does not change it. Null when the alert records no detection. |
primarySignalId | string | The signal Perpetual created the alert from. |
signalIds | array<string> | Every signal the alert covers, including the ones it absorbed from merged alerts. |
currentPriority | integer | The priority scoring assigned, on a scale of 1 to 10. A re-score never lowers it. Null before scoring runs. |
summary | string | What scoring concluded the activity looks like. Reachable through $search rather than $filter or $orderby. Empty until scoring runs. |
responseInstructionsSnapshot | string | The detection's responseInstructions as they stood when Perpetual created the alert, which is what scoring reads. Null when the detection carries none. |
accumulationKeyValue | string | The grouping key that decides which alerts cover the same finding, derived from the detection's accumulationKey fields. Null when the detection does no grouping. |
sourceViewName | string | The signals view Perpetual created the alert against, which it uses to resolve the alert's signals later. Null when the alert records none, which blocks promotion. |
signalSnapshotColumns | array<object> | The merged column schema for the retained signal rows, each column with a name and a type. |
signalSnapshotRows | array<array> | The retained signal rows, at most ten. |
totalSignalCount | integer | How many signals the alert covers, counting signalIds rather than retained rows. |
promotionThresholdAtDecision | integer | The promotion bar the alert faced when Perpetual decided it, on the same 1 to 10 scale. Null before scoring runs. |
budgetRemainingAtDecision | number | What was left of the Space's weekly budget in USD when Perpetual decided the alert. Null before scoring runs, and when the Space carries no budget. |
promotedCaseId | string | The case promotion opened from the alert, prefixed CAS_. Null until the alert promotes. |
mergedIntoAlertId | string | The surviving alert that absorbed this one, prefixed ALR_. Null unless status is Merged. |
mergedAlertIds | array<string> | The alerts this one absorbed. A merge re-parents the absorbed alerts' own children onto the survivor, so this list is flat. |
auditLogs | array<object> | The alert's timeline. |
Plus the common resource fields.
Related
- Signals vs alerts, which signals become alerts and why most do not.
- Alert triage, how Perpetual scores an alert and decides whether to promote it.
- Cases, what promotion opens.
- Detections, the content that
produces alerts, whose
createCase,accumulationKey,minimumPriority, andresponseInstructionsfields govern them. - Signal schema reference, the fields of the signal behind an alert.