Alert rules
Endpoint: /api/metrics/alert-rules/
Alert rules watch a server’s metrics and raise an alert when a value crosses a threshold, using the data the agent has already sent. Rules are evaluated on Alpacon’s own schedule, about once a minute—see Metric alerts for how a rule decides to fire and clear.
Requires the Metrics extension to be enabled for the workspace, for every action—including reading the seeded default disk-usage rule that every server carries regardless of plan. That rule is still evaluated on a workspace with the extension off; this API just isn’t how you’d read it there.
Who can edit or delete a rule
A workspace admin can update or delete any rule. So can anyone whose role carries the workspace-wide alert_rule:update (for PUT/PATCH) or alert_rule:delete permission—the built-in operator role has both, member has neither. Creating a rule doesn’t grant its creator any special access to it on its own.
Beyond those roles, an admin can give a specific person, group, or service token’s Application the right to update and delete one rule, without changing anyone’s workspace-wide role. That grant is an explicit rule-scoped alert_rule:maintainer binding, made through the RBAC role API—the console’s role pickers can’t scope a grant to a single rule yet. A service token reaches a rule only through a binding like this one; its Application’s workspace-wide roles, even operator, don’t reach a rule on their own. A personal API token acts as the person who issued it, so it follows their role and any binding they hold.
A rule created before Alpacon stopped granting this binding to creators automatically may still carry the binding its creator was given at the time, and that creator keeps updating and deleting the rule until Alpacon finishes cleaning up those older bindings.
Default rules
The extension default rules—CPU usage, memory usage, and any other non-core rule marked default—can be updated by anyone whose role carries alert_rule:update, the same as any other rule. No default rule can be deleted while it’s still marked as default, whoever asks; see Delete alert rule.
The core disk usage rule
Every workspace carries a seeded disk-usage rule (is_default: true, target disk-usage) that stays active whether or not the Metrics extension is on. Only a workspace admin may:
- Update it with
PUTorPATCH - Create, or turn an existing rule into, one with
is_default: trueand targetdisk-usage—on any device - Create, update, or delete a server override on it, or move an override onto or off it
- Detach it from a server—through the servers API’s detach-rule action, or a server update that drops it from
rules
Anyone else—an operator, a principal with a rule-scoped binding on it, and every service token—gets 403 metrics_alert_rule_core_admin_only. Attaching the rule back to a server isn’t restricted this way, and previewing what it would do (recipients or evaluation) stays open to anyone who can already read the rule.
List
List alert rules
Retrieve a paginated list of alert rules.
Request
GET /api/metrics/alert-rules/Query parameters
| Parameter | Type | Description |
|---|---|---|
name | string | Filter by rule name |
target | string | Filter by target metric |
threshold | number | Filter by threshold |
operator | string | Filter by direction (gte or lte) |
device | string | Filter by device |
severity | string | Filter by severity (critical, warning, info) |
is_default | boolean | Filter by default status |
server | UUID | Only rules attached to this server |
exclude_server | UUID | Only rules not attached to this server |
search | string | Search across name, target, and default status |
ordering | string | Sort order. Default: -added_at |
page | integer | Page number |
page_size | integer | Results per page (default: 15, max: 100) |
Response
{
"count": 2,
"next": null,
"previous": null,
"results": [
{
"id": "3f1c9b2e-6a4d-4e8f-9b1a-2c3d4e5f6a7b",
"name": "Core disk usage",
"target": "disk-usage",
"threshold": 80,
"operator": "gte",
"duration_s": 0,
"recovery_threshold": 78,
"no_data_after_s": null,
"device": "",
"severity": "warning",
"notify_email": "all",
"notify_slack_channel": true,
"is_default": true
},
{
"id": "8c4d6e2a-1b3f-4a5c-8d9e-0f1a2b3c4d5e",
"name": "Sustained high CPU",
"target": "cpu-usage",
"threshold": 80,
"operator": "gte",
"duration_s": 300,
"recovery_threshold": 70,
"no_data_after_s": 600,
"device": "",
"severity": "critical",
"notify_email": "admins",
"notify_slack_channel": false,
"is_default": false
}
]
}Required scope: alert_rule:read
Example
curl -X GET "https://your-workspace.us1.alpacon.io/api/metrics/alert-rules/?target=cpu-usage" \
-H "Authorization: token=\"alpat-xxxxxxxxxxxxxxxxxx\""Error responses
| Status | Error code | Description |
|---|---|---|
| 400 | metrics_alert_rule_exists | A default rule already exists for this target and device |
| 400 | metrics_alert_rule_recovery_threshold_invalid | recovery_threshold is not on the recovering side of threshold |
| 400 | metrics_alert_rule_override_recovery_threshold_invalid | Changing operator, threshold, or recovery_threshold would leave a server override’s own recovery threshold on the firing side |
| 400 | metrics_alert_rule_duration_too_short | duration_s is positive but shorter than two collection intervals for the target |
| 400 | metrics_alert_rule_override_duration_too_short | Changing target would leave a server override’s positive duration_s below the new target’s floor (two collection intervals) |
| 400 | metrics_alert_rule_no_data_window_too_short | no_data_after_s is shorter than this target’s collection interval |
| 400 | metrics_alert_rule_no_data_window_too_long | no_data_after_s is longer than 86400 seconds (24 hours) |
| 400 | metrics_alert_rule_device_not_supported | device was set on a host-wide target (cpu-usage or memory-usage) |
| 400 | metrics_alert_rule_cannot_be_deleted | Tried to delete a rule while is_default is still true |
| 400 | metrics_alert_rule_destination_not_allowed | notify_email or notify_slack_channel was set by an application or service token instead of a signed-in workspace member |
| 400 | server_not_found | Preview evaluation’s servers names a server you can’t reach or that doesn’t exist |
| 400 | metrics_alert_rule_preview_window_too_long | Preview evaluation’s window_s is longer than 604800 seconds (7 days) |
| 400 | metrics_alert_rule_preview_too_many_servers | Preview evaluation named more than 20 servers, or servers × window_s exceeds 5 × 604800 |
| 400 | metrics_alert_rule_preview_too_many_samples | Preview evaluation would read or judge more than 300,000 sample rows |
| 400 | metrics_alert_rule_preview_servers_required | Preview evaluation named neither rule_id nor servers |
| 401 | UNAUTHORIZED | Invalid or missing authentication |
| 403 | metrics_alert_rule_core_admin_only | A write to the core disk-usage rule—or one that would create or retarget a rule onto it—from anyone but a workspace admin |
| 403 | FORBIDDEN | Insufficient permissions, or the Metrics extension isn’t enabled for this workspace |
| 404 | NOT_FOUND | Alert rule not found |
The rule’s own values are checked first and still refuse with the non-override codes above. For the two override codes, an update is refused only after every override on the rule has been checked, and field_errors keys each affected override overrides.<server id>.recovery_threshold or overrides.<server id>.duration_s—a server hit by both carries both paths. When the caller can’t see the affected server, the response omits the overrides.* path and carries only non_field_errors with the same code. Overrides changed directly through the rule overrides API keep their own, unchanged error codes.