---
title: "List organization alerts"
method: GET
path: "/api/v2/{org_id}/alerts"
tags: ["Alerts"]
---

# List organization alerts

`GET /api/v2/{org_id}/alerts`

## Request

- Base URL: `https://api.openobserve.ai` (the document declares no server; this is the origin it was published from)
- URL: `https://api.openobserve.ai/api/v2/{org_id}/alerts`
- Auth: API key in header `Authorization`
- TypeScript: <https://skmtc.dev/openobserve/apis/openobserve-api-http/docs/api/v2/:org_id/alerts/get.ts> (a function with typed inputs; its response is checked against the schema)

Retrieves a list of all alerts in the organization with filtering and pagination options. Shows alert summaries including names, status, folder organization, and basic configuration details for monitoring and management purposes.

## Path parameters

- `org_id` string, required

## Query parameters

- `folder` string
- `slo_id` string
- `stream_type` 'logs' | 'metrics' | 'traces' | 'profiles' | 'service_graph' | 'enrichment_tables' | 'file_list' | 'metadata' | 'index'
- `stream_name` string
- `alert_name_substring` string
- `owner` string
- `enabled` boolean
- `page_size` integer
- `page_idx` integer
- `alert_type` 'all' | 'scheduled' | 'realtime' | 'anomaly_detection' | 'slo' | 'composite': Filters the alert list by alert type (scheduled, realtime, anomaly detection, or all).
- `priority` string[]
- `tags` string
- `sort_by` string
- `sort_order` string
- `include_dependencies` boolean

## Response `200`

Success

- object: HTTP response body for `ListAlerts` endpoint.
  - `list` ListAlertsResponseBodyItem[], required
    - `ack` AlertAckSummary: The alert list item's ack summary.
      - `ack_source` 'ui' | 'api' | 'slack' | 'oncall' | 'incident'
      - `acked_at` integer, required
      - `acked_by` string, required
      - `groups_acked` integer
    - `active_downtime` ActiveDowntime
      - `alert_groups` AlertGroupRef[], nullable
        - `alert_id` string, required
        - `group_key` string
        - `group_labels` object, nullable: Captured at mute time because `group_key` is a hash the UI cannot show.
      - `end_on_clear` EndOnClear: "Until it clears": `group_key` null ends the downtime when no group of the alert is firing.
        - `alert_id` string, required
        - `group_key` string, nullable
      - `ends_at` integer, required
      - `id` string, required
      - `incident_mode` 'muted' | 'none': What a suppressed alert firing does to incidents during the window.
      - `name` string, required
      - `source` 'slack' | 'openobserve' | 'api': Where a quick mute came from; the web app's own calls are `openobserve`.
      - `version` integer: The row's version, which an extend sends back; 0 from an older node.
    - `alert_id` string, required
    - `alert_type` string, required: Discriminator: "scheduled" | "realtime" | "slo" | "anomaly_detection" | "composite"
    - `child_count` integer, nullable: Composite rows only: number of referenced children.
    - `condition` QueryCondition
      - `aggregation` Aggregation
        - `function` 'avg' | 'min' | 'max' | 'sum' | 'count' | 'median' | 'p50' | 'p75' | 'p90' | 'p95' | 'p99', required
        - `group_by` string[], nullable
        - `having` Condition, required
          - `column` string, required
          - `ignore_case` boolean
          - `operator` '=' | '!=' | '>' | '>=' | '<' | '<=' | 'contains' | 'not_contains' | 'is_null' | 'is_not_null' | 'is_empty' | 'is_not_empty', required
          - `value` object, required
        - `multi_alert` boolean: Opt-in to per-group evaluation — multi-alerts, `alerts_2.md` M-9/D26. `#[serde(default)]` is the whole backward-compatibility guarantee: an aggregation stored before this field existed cannot contain it, so it deserializes to `false` and the alert keeps its legacy collapsed evaluation byte-for-byte. Nothing is inferred from `group_by` being present — that would silently change paging cadence and reset silence fingerprints for every existing grouped alert. Validated by [`grouping::validate_multi_alert`] (M-10): requires a non-empty `group_by`, an orderable `having.operator`, and "any group" count gates.
        - `warning_value` number, double, nullable: WARNING threshold, sharing `having.operator` and `having.column` with critical (alerts_2.md §4.4). `None` = single-level aggregation alert, i.e. exactly the legacy behaviour. Stored as f64 because aggregate values (averages, percentiles) are not integers. Same lenient deserialization as `promql_warning_value`, for the same reason (D61) — aggregate warnings are the field most likely to be fractional.
      - `conditions` object, nullable
      - `multi_time_range` CompareHistoricData[], nullable
        - `offSet` string, required
      - `promql` string, nullable
      - `promql_condition` Condition
        - `column` string, required
        - `ignore_case` boolean
        - `operator` '=' | '!=' | '>' | '>=' | '<' | '<=' | 'contains' | 'not_contains' | 'is_null' | 'is_not_null' | 'is_empty' | 'is_not_empty', required
        - `value` object, required
      - `promql_multi_alert` boolean: Per-group alerting for a PromQL alert (M-9), where a "group" is one returned SERIES. A sibling of `promql_condition` rather than a member of [`Aggregation::multi_alert`], because a PromQL alert has no `aggregation` at all — its grouping is expressed in the PromQL itself (`sum by (pod) (…)`), not in a `group_by` column list. The group key is the series' FULL label set. That is what a series' identity already is in Prometheus, and it means the expression stays the single place grouping is decided — a separate label picker could only ever disagree with the `by (…)` clause beside it. `#[serde(default)]` carries the same backward-compatibility guarantee as its aggregation counterpart: an alert stored before this field existed deserializes to `false` and keeps its collapsed evaluation byte-for-byte. Nothing is inferred from the query returning several series — that would change paging cadence for every existing PromQL alert that happens to be unaggregated.
      - `promql_rule_mode` boolean
      - `promql_warning_value` number, double, nullable: WARNING value for the PromQL condition (alerts_2.md Feature 1). A sibling field rather than a member of `Condition`, which is shared by every filter in the product and must not grow alert-specific knobs. Shares `promql_condition.operator` with critical. `None` = single-level. Lenient deserialization: this arrives through `CreateAlertRequestBody`'s `#[serde(flatten)]`, which buffers via `Value`, where `arbitrary_precision` makes a number a map (D61). Without it a FRACTIONAL warning is rejected while an integer one works — found by end-to-end testing.
      - `search_event_type` 'ui' | 'dashboards' | 'reports' | 'alerts' | 'values' | 'other' | 'rum' | 'derivedstream' | 'searchjob' | 'download' | 'insights' | 'public_dashboard'
      - `slo_condition` SloCondition: The SLO alert's condition, persisted in `alerts.query_slo_condition` (D42). `slo_id` is additionally written to the indexed `alerts.slo_id` column, which is authoritative for reverse lookups (D60).
        - `critical` number, double, required: Finite and strictly positive (SA-3). Lenient deserialization is required, not cosmetic: this struct arrives nested inside `CreateAlertRequestBody`'s `#[serde(flatten)]`, and a flatten buffers through `Value`, where `arbitrary_precision` represents every number as a map (D61). A plain `f64` fails there with `invalid type: map, expected f64`.
        - `kind` 'error_budget' | 'burn_rate', required: The two SLO-alert shapes we offer.
        - `long_window_secs` integer, nullable: `BurnRate` only. 1h–48h, ≤ the SLO window, an exact multiple of and ≥ 2× the slice interval (SA-8).
        - `multi_alert` boolean: Per-group fan-out — Feature 3's flag, same semantics (SA-13).
        - `operator` '=' | '!=' | '>' | '>=' | '<' | '<=' | 'contains' | 'not_contains' | 'is_null' | 'is_not_null' | 'is_empty' | 'is_not_empty', required
        - `short_window_secs` integer, nullable: `BurnRate` only. Defaults to long ÷ 12 (Google SRE workbook).
        - `slo_id` string, required
        - `warning` number, double, nullable
      - `sql` string, nullable
      - `type` 'custom' | 'sql' | 'promql' | 'slo'
      - `vrl_function` string, nullable
    - `description` string, nullable
    - `destinations` string[]: Names of the notification destinations this alert delivers to (`Alert.destinations`). Lets the destination↔alert dependency view build the linkage from the list alone; omitted when empty.
    - `enabled` boolean, required
    - `expression_summary` string, nullable: Composite rows only: the trigger expression with child IDs resolved to names.
    - `firing_started_at` integer, nullable: Start of the alert's current firing (µs); absent when not firing or for a multi-alert.
    - `folder_id` string, required
    - `folder_name` string, required
    - `groups_firing` integer, nullable: Multi-alerts only: how many of those groups were warning-or-worse, also counted pre-cap. With `groups_observed` this is the "N of M groups firing" chip. Counting retained state rows instead would silently under-report whenever more than the cap's worth of groups fire, which is the silent truncation M-6 forbids.
    - `groups_firing_is_lower_bound` boolean, nullable: Whether `groups_firing` is a `>=` lower bound. Tracked separately because the two diverge: a full page that still reached healthy groups has seen every firing group, so this stays exact while `groups_observed` does not.
    - `groups_observed` integer, nullable: Multi-alerts only (§5.4): how many groups the last evaluation observed, counted **before** the M-6 cap truncated them. Absent for every alert that has not opted in.
    - `groups_observed_is_lower_bound` boolean, nullable: Whether `groups_observed` is a `>=` lower bound — the bounded fetch page came back full, so groups beyond it were never seen. Render the count with a `≥`.
    - `incident` AlertIncidentLink: The incident a list row links to.
      - `id` string, required
      - `status` 'open' | 'acknowledged' | 'resolved', required: Incident status lifecycle: Open → Acknowledged → Resolved
      - `title` string, nullable
    - `is_real_time` boolean, required
    - `last_error` string, nullable: Last error message from training or detection. Only present for `anomaly_detection` items.
    - `last_outcome` string, nullable: Outcome of the most recent evaluation: "firing" | "normal" | "error" | "notify_failed" | "succeeded". Absent when the alert has never run. This is the LAST RUN OUTCOME, not a live "currently firing" flag — always render it alongside `last_outcome_at`. See Part IV of alerts.md.
    - `last_outcome_at` integer, nullable: When `last_outcome` was recorded (microseconds).
    - `last_outcome_since` integer, nullable: When `last_outcome` last CHANGED (microseconds) — i.e. how long the alert has been in its current state.
    - `last_satisfied_at` integer, nullable
    - `last_trained_at` integer, nullable: Timestamp (µs) when the anomaly model was last successfully trained. Only present for `anomaly_detection` items.
    - `last_triggered_at` integer, nullable
    - `level` string, nullable: Severity of the last classification: "ok" | "warning" | "critical". A SEPARATE axis from `last_outcome`: that says whether the evaluation fired, this says how bad. An alert can be `firing` at `warning`. Absent for single-level alerts that never classified.
    - `level_since` integer, nullable: When `level` last CHANGED — powers "critical for 20 minutes".
    - `name` string, required
    - `oncall_team` string, nullable: The on-call team this alert names, when it names one. Routing's highest-precedence tier, and the only tier a list row can report: every other one resolves from the identity dimensions of the row that fires, which an alert definition does not carry. Absent means "resolved at fire time", not "pages nobody". The list has always had a column for this and never had the field, so every alert read as unbound — including ones deliberately pinned.
    - `owner` string, nullable
    - `priority` integer, nullable: Configured priority as the integer storage id 1..=5 (Feature 2, PT-3). A THIRD axis: `enabled` is is-it-running, `last_outcome` is did-it-fire, `level` is how-bad-now, and this is how much humans care. Absent when unset, which is every pre-Feature-2 alert.
    - `referenced_by_composite_count` integer, nullable: Count of parent composites currently readable to the caller.
    - `status` string, nullable: Scheduler status string. Only present for `anomaly_detection` items. Values: "waiting" | "ready" | "training" | "failed" | "disabled"
    - `stream_name` string, nullable: The stream this alert watches. Absent for `composite` alerts (which watch children, not a stream) and for an `anomaly_detection` config that predates stream selection.
    - `stream_type` string, nullable: Paired with `stream_name` — present and absent together.
    - `tags` string[]: Normalized selection tags (PT-6). Omitted when empty.
    - `template` string, nullable: Alert-level template override (`Alert.template`): when set it replaces the destination-level template for every destination above. Absent when the alert defers to each destination's own template.
    - `trigger_condition` TriggerCondition
      - `align_time` boolean
      - `cron` string
      - `frequency` integer: (seconds)
      - `frequency_type` 'cron' | 'minutes'
      - `notify_on_warning` boolean, nullable: Whether a Warning-level match delivers a notification (D11). `None` = true — warnings notify unless explicitly opted out. Persisted in `trigger_thresholds`.
      - `operator` '=' | '!=' | '>' | '>=' | '<' | '<=' | 'contains' | 'not_contains' | 'is_null' | 'is_not_null' | 'is_empty' | 'is_not_empty'
      - `period` integer: (minutes)
      - `silence` integer: (minutes)
      - `threshold` integer
      - `timezone` string, nullable
      - `tolerance_in_secs` integer, nullable: (seconds)
      - `warning_threshold` integer, nullable: Warning threshold, sharing `operator` with `threshold` — one operator for both levels, no mixed directions (T-2). `None` = single-level alert, i.e. exactly the legacy behaviour. Validated by `level::validate_thresholds` — "less severe" is direction-dependent, so this is NOT simply `< threshold`.

---

[API](https://skmtc.dev/openobserve/apis/openobserve-api-http.md) - [All operations](https://skmtc.dev/openobserve/apis/openobserve-api-http/llms.txt) - [OpenAPI document](https://skmtc.dev/openobserve/apis/openobserve-api-http/revisions/0529b8a10252?raw)
