Alerts

Endpoint: /api/alerts/

An alert is one row per episode, open or resolved—see Alert history for how the console shows the same rows. This API is read-only over the alerts themselves: you can list them, read one, and acknowledge one, but nothing here creates, edits, or deletes an alert—every alert is raised and resolved by the platform.

Unlike the alert rules API, this endpoint isn’t gated by the Metrics extension: offline and security alerts are unaffected by it either way. The one exception is a metric alert raised by an extension rule—anything beyond the seeded core disk-usage rule—which drops out of the list, and 404s on its own detail and acknowledge routes, while the workspace’s Metrics extension is off.

List alerts

Retrieve a paginated list of alerts. Without resolved, the list answers open alerts only; pass resolved=true to read the resolved history instead.

Request

GET /api/alerts/

Query parameters

ParameterTypeDescription
alert_typestringFilter by alert type: metric_threshold, server_disconnected, unauthorized_access, insecure_port_open, system_error, unknown_device, device_network_moved, system_user_conflict, agent_upgrade_failed
severitystringFilter by severity (critical, warning, info)
serverUUIDFilter by server
server_namestringFilter by server name, case-insensitive substring match
ruleUUIDFilter by the alert rule that raised it (metric alerts only)
resolvedbooleanResolution state. Omitted, the list answers open alerts only. true returns the resolved history instead; false is the explicit spelling of the default
acknowledgedbooleanWhether you’ve acknowledged the alert—checked or dismissed either count
dismissedbooleanWhether you specifically dismissed the alert, narrower than acknowledged
added_at__gte / added_at__ltedatetimeOnly alerts raised at or after / at or before this instant
searchstringSearch across title, description, and server name
orderingstringSort order, over acknowledged, added_at, updated_at, severity. Default: acknowledged,-added_at
pageintegerPage number
page_sizeintegerResults per page (default: 15, max: 100)

Response

{
  "count": 1,
  "current": 1,
  "next": null,
  "previous": null,
  "last": 1,
  "results": [
    {
      "id": "9a1c0b62-9f3a-4a3d-8a1e-2b0f2c6d5e41",
      "alert_type": "metric_threshold",
      "server": {
        "id": "7c5e2a41-6b90-4c33-a7d8-0e5f1b2c3d44",
        "name": "web-01",
        "os": "ubuntu",
        "platform": "linux",
        "is_connected": true,
        "is_deleted": false
      },
      "severity": "warning",
      "title": "CPU usage 92% ≥ 80% for 5 minutes",
      "description": "CPU usage has stayed at or above 80% since 12:00.",
      "dedup_key": "metric:cpu-usage:",
      "device": "",
      "rule": { "id": "4f2b18d0-5c77-4a0b-9d2e-1f7a3c9b4e05", "name": "cpu-high" },
      "condition": "threshold",
      "is_acknowledged": false,
      "action_type": null,
      "added_at": "2026-09-01T12:00:00Z",
      "updated_at": "2026-09-01T12:04:00Z",
      "resolved_at": null,
      "resolution_cause": "",
      "deliveries": [
        {
          "edge": "raised",
          "channel": "email",
          "state": "sent",
          "recipients": 3,
          "at": "2026-09-01T12:02:00Z"
        },
        {
          "edge": "raised",
          "channel": "slack_channel",
          "state": "sent",
          "recipients": null,
          "at": "2026-09-01T12:02:00Z"
        }
      ]
    }
  ]
}
FieldDescription
idThe alert’s ID
alert_typeSee the values under alert_type above
serverThe server the alert is about: id, name, os, platform, is_connected, is_deleted
severitycritical, warning, or info
title / descriptionThe alert’s headline and longer explanation, rendered in your own language when a translation exists
dedup_keyIdentifies the alert’s subject within (server, alert type)—so a repeat condition updates this row instead of raising a duplicate. Empty for an alert type that doesn’t dedup
deviceThe disk, partition, or network interface this alert is about, when it’s scoped to one. Empty when the alert is about the server as a whole
ruleThe alert rule that raised this alert, as {id, name}. null for an alert no rule raises (only metric alerts carry one), and once the rule has been deleted
conditionWhich condition of its rule this alert is about: threshold or no_data. Empty for an alert no rule raises
is_acknowledgedWhether you’ve acknowledged this alert—checked or dismissed either count
action_typechecked or dismissed, whichever you acknowledged it with. null if you haven’t
added_atWhen this alert (this episode) was first raised
updated_atWhen this row was last written. A sustained condition refreshes the same row rather than raising a new one, so this moves without a new episode starting
resolved_atWhen this alert was observed to have cleared. null while it’s still open. A resolved row is purged 30 days after this instant
resolution_causeWhy this alert was resolved, in a vocabulary owned by whichever app resolved it. For a metric alert, see the cause values under Alert history; other alert types carry their own. Empty while the alert is open, and on a row resolved before this field existed
deliveriesWhat this episode’s raise and resolution actually sent, one entry per edge and channel—see the shape below. Alert types that never send an interrupt carry an empty list
deliveries[].edgeraised or resolved
deliveries[].channelThe channel sent on: email, push, or slack_channel. null for an entry that names no channel—the raise’s absence when nothing was sent
deliveries[].statesent, failed (the send was attempted for that channel and failed—an email dispatch error, or a Slack post that failed after its retry; a sent row on the same edge and channel outranks it), held (still inside the hold), resolved_in_hold (the condition cleared before the hold ended, so neither edge sent), suppressed (the rule’s own destinations narrowed the channels), or unrecorded (dispatched, but nothing recorded a send—a fully muted fan-out, an empty recipient set, or a Slack post skipped because the installation was gone)
deliveries[].recipientsHow many people this channel addressed, or, for failed, didn’t reach. null for a Slack channel post, which addresses a room, and for an entry that sent nothing
deliveries[].atThe earliest send on this edge and channel—or, for failed, the earliest attempt (an email’s dispatch time; a Slack post’s give-up time, after its retry). For unrecorded, the alert’s notified_at—when its raise was claimed for sending. null for held, resolved_in_hold, and suppressed

A failure past the mail hand-off—inside the mail worker, past the SMTP step—isn’t visible here and still reads as sent: this field reports what the sender could see, not final inbox delivery.

Required scope: alert:read

Example

curl -X GET "https://your-workspace.us1.alpacon.io/api/alerts/?resolved=true&severity=critical" \
  -H "Authorization: token=\"alpat-xxxxxxxxxxxxxxxxxx\""

Error responses

StatusError codeDescription
400alert_already_acknowledgedYou already acknowledged this alert
401UNAUTHORIZEDInvalid or missing authentication
403FORBIDDENInsufficient permissions
404NOT_FOUNDAlert not found, or it’s a metric alert from an extension rule and the Metrics extension is off
Last updated: