Rules API
Rules define detection. These endpoints create, preview, list, and update them. The behavior behind the fields is in Rule Evaluation and Dynamic Thresholds & Baselines.
Permissions: reads and preview require CanViewAlerts; create/update require
CanManageRules.
Target metric constraint: a rule can only target a metric that is registered in the
catalog with isActive = true and dataStatus = ACTIVE (i.e. isEvaluable = true).
| Method & path | Purpose |
|---|---|
GET /api/rules?search=&status=&page=1&pageSize=25 | List rules with server-side search and pagination. |
GET /api/rules/summary | Return aggregate rule counts. |
GET /api/rules/{id} | Get one rule by integer id. |
POST /api/rules/preview | Replay a candidate rule over history without saving. |
POST /api/rules | Create a rule. |
PUT /api/rules/{id} | Update a rule. |
GET /api/rules?search=&status=&page=1&pageSize=25
Lists saved rules. search matches rule name, metric key, status, type, or threshold
mode. status can narrow the list to values such as Active.
{
"items": [
{
"id": 42,
"name": "High impact metric event",
"metricId": "demo.api.response.duration.ms",
"type": "Dynamic",
"thresholdMode": "Percentage",
"status": "Active",
"createdAt": "2026-06-02T08:00:00Z"
}
],
"page": 1,
"pageSize": 25,
"totalCount": 1,
"totalPages": 1,
"hasPreviousPage": false,
"hasNextPage": false
}
GET /api/rules/summary
Returns aggregate rule counts without loading rule rows.
{
"totalCount": 128,
"activeCount": 122
}
Shared fields
These fields appear on preview, create, and the returned RuleDto.
| Field | Type | Meaning |
|---|---|---|
metricId | string | The metric key the rule watches. |
type | enum | Static or Dynamic. |
thresholdMode | enum | Dynamic only: Percentage, Stddev, or Envelope. |
windowMinutes | int | Evaluation/baseline window size. |
tolerancePercent | number | Used by Percentage and Envelope modes. |
stddevMultiplier | number | Used by Stddev mode (ignored otherwise). |
direction | enum | Above, Below, or Both. |
staticUpper / staticLower | number? | Fixed limits for Static rules. |
scope | object? | For a Static rule on a multidimensional metric, an optional label-equality filter that narrows the rule to a subset of fleet members (for example {"host.id":"srv-123"} for one server or {"host.group":"prod-db"} for one group). Omitted or {} watches every member; ignored for single-metric rules. On preview the series is read for just the scoped member/group; on create it is stored on the rule. |
splitBy | string? | Rule-level grouping for multidimensional metrics. Omit or send null to use the metric's default grouping, send "" to merge matching values into one fleet series, or send comma-separated declared dimension keys such as host.id,device. |
requiredViolations | int | Violations needed to consider the rule breached. |
violationWindowMinutes | int | Window over which violations are counted. |
recoveryWindowMinutes | int | Quiet window required to recover. |
recoveryNormalCount | int | Consecutive normal points required to recover. |
warningLevel / criticalLevel | object? | Optional alert levels — fleet/multidimensional rules only (see below). |
conditions | array? | Single-value rules only. One or more conditions combined into one alarm. Each condition has its own metricId, thresholdType (Static/Dynamic), operator, thresholdMode, static limits, and dynamic parameters. Omit to have the API build one condition from the flat target/threshold fields. |
conditionLogic | enum? | All (every condition must breach) or Any (at least one). Defaults to All. |
severity | enum? | Warning or Critical — the single severity a condition-based rule's alarm opens at. Defaults to Warning. |
Compound rules
A single-value rule can carry several conditions, each watching its own metric with its own
static or dynamic threshold, combined by conditionLogic into one alarm at one severity. A
rule with a single condition behaves like a classic single-metric rule. A condition-based
preview returns one series per condition; for compound previews it also returns ruleSeries,
the folded rule-level outcome after conditionLogic, trigger, and recovery are applied.
Conditions are not supported on multidimensional metrics, which continue to use
warningLevel/criticalLevel, scope, and splitBy.
Mode parameter exclusivity
The dynamic modes are mutually exclusive in evaluation:
PercentageusestolerancePercentaround the expected value.StddevusesstddevMultiplieraround the baseline standard deviation and ignorestolerancePercent.EnvelopeusestolerancePercentaround the historical min/max.
Alert levels (warningLevel / criticalLevel)
{
"severity": "Critical",
"operator": "Above",
"thresholdValue": 90,
"durationMinutes": 10,
"triggerViolationCount": 5,
"isEnabled": true
}
| Field | Meaning |
|---|---|
severity | Warning or Critical. |
operator | Comparison direction for this level. |
thresholdValue | Static rules: literal threshold. Dynamic rules: tolerance percent (Percentage/Envelope) or stddev multiplier (Stddev). |
durationMinutes | How long the breach must persist. |
triggerViolationCount | Violations that trigger this level. |
isEnabled | Whether the level is active. |
Constraints (current model): Critical must use the same operator as Warning, have
durationMinutes ≥ Warning, and be stricter than Warning. Critical is evaluated
before Warning.
POST /api/rules/preview
Replay a candidate rule over a historical range and return per-point results — without
creating anything. Use it to tune tolerances and trigger settings against real data.
For static previews, the returned band comes from staticLower / staticUpper and
expected is null. Multidimensional previews return separate member series, limited by
seriesLimit (default 20, maximum 50). Scope filtering happens before grouping. Each
series returns its stable member key plus the latest representative labels; clients
can show host.name while retaining host.id as the durable identity.
Request (extends the shared fields with a time range)
{
"metricId": "demo.api.response.duration.ms",
"from": "2026-06-01T00:00:00Z",
"to": "2026-06-02T00:00:00Z",
"type": "Dynamic",
"thresholdMode": "Percentage",
"windowMinutes": 5,
"tolerancePercent": 30,
"stddevMultiplier": 0,
"requiredViolations": 3,
"violationWindowMinutes": 5,
"recoveryWindowMinutes": 10,
"recoveryNormalCount": 3,
"direction": "Above",
"staticUpper": null,
"staticLower": null,
"splitBy": "host.id",
"seriesLimit": 20,
"warningLevel": { "severity": "Warning", "operator": "Above", "thresholdValue": 80, "durationMinutes": 5, "triggerViolationCount": 3, "isEnabled": true },
"criticalLevel": { "severity": "Critical", "operator": "Above", "thresholdValue": 90, "durationMinutes": 10, "triggerViolationCount": 5, "isEnabled": true }
}
Response 200
{
"series": [
{
"member": "host.id=srv-123",
"labels": { "host.id": "srv-123", "host.name": "payments-web-01" },
"points": [
{ "timestamp": "2026-06-01T09:00:00Z", "value": 214, "expected": 220, "lower": 154, "upper": 286, "isViolation": false, "isAlarmActive": false }
]
}
],
"ruleSeries": null,
"totalMemberCount": 12,
"from": "2026-06-01T00:00:00Z",
"to": "2026-06-02T00:00:00Z"
}
| Per-point field | Meaning |
|---|---|
value | Actual value at that timestamp. |
expected | Baseline expected value (dynamic rules). |
lower / upper | The threshold band in force at that time. |
isViolation | Whether the point breached the band. |
isAlarmActive | Whether, given the trigger logic, an alarm would be active at that point. |
Preview reads from the metric store by metric key; a catalog-only metric with no local data
cannot be previewed. Invalid parameters return 400 with a message.
POST /api/rules
Create a rule. Extends the shared fields with naming, scheduling, and baseline settings.
Additional request fields
| Field | Type | Meaning |
|---|---|---|
name | string | Rule name. |
alertingProfileId | int? | Optional routing profile; null uses the default profile or configured fallback target. |
consecutiveViolationCount | int | Consecutive breaches required. |
triggerWindowMinutes / triggerViolationCount | int | Trigger condition for opening an alert. |
lookbackWeeks | int | History span the baseline learns from. |
minimumBaselinePoints | int | Minimum clean samples for a usable baseline. |
evaluationFrequencyMinutes | int | How often the rule is evaluated. |
suppressLowConfidence | bool | Suppress alerts when baseline confidence is low. |
Response 201 (Location: /api/rules/{id}) — the full RuleDto, which also carries
baselineProfileId, status, lastEvaluatedAt, and createdAt.
{
"id": 17,
"name": "API latency – dynamic",
"metricId": "demo.api.response.duration.ms",
"type": "Dynamic",
"thresholdMode": "Percentage",
"tolerancePercent": 30,
"direction": "Above",
"status": "Active",
"createdAt": "2026-06-02T09:00:00Z",
"warningLevel": { "severity": "Warning", "...": "..." },
"criticalLevel": { "severity": "Critical", "...": "..." }
}
PUT /api/rules/{id}
Update a rule by integer id. Body is the same shape as create. Returns the updated
RuleDto, or 404 if the rule does not exist. Updating a rule invalidates the active-rule
cache so evaluation picks up the change promptly.