---
title: "Get incident details"
method: GET
path: "/api/v2/{org_id}/alerts/incidents/{incident_id}"
tags: ["Incidents"]
---

# Get incident details

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

## 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/incidents/{incident_id}`
- Auth: API key in header `Authorization`
- TypeScript: <https://skmtc.dev/openobserve/apis/openobserve-api-http/docs/api/v2/:org_id/alerts/incidents/:incident_id/get.ts> (a function with typed inputs; its response is checked against the schema)

Retrieves detailed information about a specific incident including all correlated alerts.

## Path parameters

- `org_id` string, required
- `incident_id` string, required

## Response `200`

Success

- IncidentWithAlerts: Incident with its alerts (for detail view)
  - `acknowledged_at` integer, nullable
  - `acknowledged_by` string, nullable
  - `alert_count` integer, required
  - `alert_groups` IncidentAlertGroup[], nullable: Every alert that fired into the incident and how often, most-fired first; list only.
    - `alert_id` string, required
    - `alert_name` string, required
    - `count` integer, required: Times this alert fired into the incident
  - `assigned_to` string, nullable
  - `created_at` integer, required
  - `first_alert_at` integer, required: Timestamps in microseconds
  - `group_values` unknown
  - `id` string, required: KSUID (27 chars)
  - `key_type` 'alert_id' | 'secondary' | 'primary': Classification of correlation key strength for hierarchical upgrade logic Hierarchy: AlertId (weakest) → Secondary → Primary (strongest) Upgrades only move UP the hierarchy, never down.
  - `last_alert_at` integer, required
  - `muted_by_downtime_id` string, nullable: Set while a downtime mutes this incident (D3).
  - `org_id` string, required
  - `rca` RcaSummary, nullable: Run summary of an incident's latest run.
    - `current_run` RcaRun: One analysis run (`rca_runs` row).
      - `cancelled_by` string, nullable
      - `confidence` string, nullable
      - `context_used` unknown
      - `continuations` integer: Continuation turns the run used.
      - `deadline_closed_at` integer, nullable: When the sweeper closed the answer deadline, µs.
      - `ended_at` integer, nullable
      - `error` RunError: `rca_runs.error` of a `failed` run.
        - `code` string, required
        - `details` string, nullable
        - `reason` string, required
        - `trigger_type` string, nullable
      - `guidance` string, nullable
      - `incident_id` string, nullable
      - `input_deadline_at` integer, nullable: Answer deadline of a `waiting_input` run, µs.
      - `mode` 'fresh' | 'build_on_previous', required
      - `oncall_subjects` unknown
      - `outcome` string, nullable
      - `pending_question_id` string, nullable: `callID` of the open question of a `waiting_input` run.
      - `questions_asked` integer: Questions the run asked.
      - `report` string, nullable: Absent rather than null while the run has no report.
      - `report_format` 'v1' | 'v2', required: Where a report lives: `v1` in pre-run `topology_context`, `v2` in an `rca_runs` row.
      - `result` unknown
      - `run_id` string, required
      - `session_id` string, nullable
      - `stage` string, nullable: Current stage of the seven-stage protocol.
      - `stage_index` integer, nullable
      - `started_at` integer, required
      - `started_by` string, required
      - `state` 'running' | 'waiting_input' | 'completed' | 'failed' | 'cancelled', required: State of one analysis run. `stale` is computed, not a state.
      - `stats` RunStats: `rca_runs.stats`.
        - `credits` number, double, nullable
        - `duration_ms` integer, nullable
        - `ignored_acks` integer, nullable: Acks after the first for the same steering row.
        - `steered` integer, nullable
        - `steps` integer, nullable
        - `tokens` unknown
        - `tool_calls` integer, nullable
      - `subject_id` string, required
      - `subject_type` 'incident' | 'alert', required
      - `trigger` 'auto_new_incident' | 'auto_new_alert_type' | 'auto_reopen' | 'manual' | 'reanalyze' | 'oncall_page' | 'resume' | 'legacy', required: What started a run.
      - `updated_at` integer, required
    - `history` RcaRunItem[], required
      - `cancelled_by` string, nullable
      - `confidence` string, nullable
      - `ended_at` integer, nullable
      - `error_reason` string, nullable: `error.reason` of a failed run.
      - `has_record` boolean: The run stored a record, so a cancelled or failed run's partial ledger still opens.
      - `mode` 'fresh' | 'build_on_previous', required
      - `outcome` string, nullable
      - `report_format` 'v1' | 'v2', required: Where a report lives: `v1` in pre-run `topology_context`, `v2` in an `rca_runs` row.
      - `run_id` string, required
      - `started_at` integer, required
      - `started_by` string, required
      - `state` 'running' | 'waiting_input' | 'completed' | 'failed' | 'cancelled', required: State of one analysis run. `stale` is computed, not a state.
      - `subject_type` 'incident' | 'alert', required
      - `trigger` 'auto_new_incident' | 'auto_new_alert_type' | 'auto_reopen' | 'manual' | 'reanalyze' | 'oncall_page' | 'resume' | 'legacy', required: What started a run.
    - `report_run` RcaRunItem: One row of a run history list.
      - `cancelled_by` string, nullable
      - `confidence` string, nullable
      - `ended_at` integer, nullable
      - `error_reason` string, nullable: `error.reason` of a failed run.
      - `has_record` boolean: The run stored a record, so a cancelled or failed run's partial ledger still opens.
      - `mode` 'fresh' | 'build_on_previous', required
      - `outcome` string, nullable
      - `report_format` 'v1' | 'v2', required: Where a report lives: `v1` in pre-run `topology_context`, `v2` in an `rca_runs` row.
      - `run_id` string, required
      - `started_at` integer, required
      - `started_by` string, required
      - `state` 'running' | 'waiting_input' | 'completed' | 'failed' | 'cancelled', required: State of one analysis run. `stale` is computed, not a state.
      - `subject_type` 'incident' | 'alert', required
      - `trigger` 'auto_new_incident' | 'auto_new_alert_type' | 'auto_reopen' | 'manual' | 'reanalyze' | 'oncall_page' | 'resume' | 'legacy', required: What started a run.
    - `resume_run_id` string, nullable
    - `confidence` string, nullable
    - `outcome` string, nullable
    - `report_format` 'v1' | 'v2', required: Where a report lives: `v1` in pre-run `topology_context`, `v2` in an `rca_runs` row.
    - `run_id` string, required
    - `stale` boolean, required: Computed by the server.
    - `started_at` integer, required
    - `state` 'running' | 'waiting_input' | 'completed' | 'failed' | 'cancelled', required: State of one analysis run. `stale` is computed, not a state.
    - `summary` RunSummaryFields, required: The `alert_incidents.rca_summary` JSON: display-only fields of the latest run.
      - `cancelled_by` string, nullable: Who cancelled the latest run (display only).
      - `deadline_at` integer, nullable: Answer deadline of a `waiting_input` run, µs.
      - `detail` string, nullable: One short line for the list cell (the failure reason).
      - `previous` PreviousResult: The newest usable result of an earlier run.
        - `confidence` string, nullable
        - `ended_at` integer, required
        - `outcome` string, nullable
        - `run_id` string, required
      - `reusable_steps` integer, nullable: Finished steps a Resume of the ended run keeps; `None` before the run ends.
      - `stage` string, nullable
      - `stage_count` integer
      - `stage_index` integer, nullable
      - `steered_by` string[]: Up to three users who steered the latest run, newest first.
      - `steps` integer
      - `tool_calls` integer
      - `unblocked_by` string, nullable
    - `updated_at` integer, required
  - `rca_off_reason` string, nullable: Why automatic analysis runs never start for this incident (`l0_off`).
  - `resolved_at` integer, nullable
  - `severity` 'P1' | 'P2' | 'P3' | 'P4', required: Incident severity levels (P1 = highest priority)
  - `status` 'open' | 'acknowledged' | 'resolved', required: Incident status lifecycle: Open → Acknowledged → Resolved
  - `title` string, nullable
  - `topology_context` IncidentTopology: Alert flow graph showing how alerts cascaded across services over time
    - `edges` AlertEdge[], required: Edges showing temporal and service dependency relationships
      - `edge_type` 'temporal' | 'service_dependency', required: Type of relationship between alert nodes
      - `from_node_index` integer, required: Source node index
      - `to_node_index` integer, required: Target node index
    - `nodes` AlertNode[], required: Alert nodes - each unique (service, alert) pair
      - `alert_count` integer, required: Number of times this alert fired
      - `alert_id` string, required: Unique alert identifier (from alert definition)
      - `alert_name` string, required: Human-readable alert name for display
      - `first_fired_at` integer, required: Timestamp of first occurrence (microseconds)
      - `last_fired_at` integer, required: Timestamp of last occurrence (microseconds)
      - `service_name` string, required: Service name (may be "unknown")
    - `related_incident_ids` string[], required: Related incident IDs (for cross-incident correlation)
  - `updated_at` integer, required
  - `alerts` Alert[], required: Unique alerts with full details
    - `context_attributes` object, nullable
    - `creates_incident` boolean: When true, this alert creates/joins incidents instead of sending direct notifications. Notification is sent only when a new incident is created or a new alert type joins an existing incident. Repeated firings are suppressed. When false (default), the alert sends notifications directly and does not correlate to any incident.
    - `description` string
    - `destinations` string[]
    - `enabled` boolean
    - `id` string, nullable
    - `incident_title_template` string, nullable
    - `is_real_time` boolean
    - `keep_firing_for` integer: Seconds the condition must stay clear before the episode recovers. 0 recovers on the first clear evaluation, which is what every alert does today. Named after Prometheus' `keep_firing_for`, with the same meaning.
    - `last_edited_by` string, nullable
    - `last_satisfied_at` integer, nullable: Will be removed in the future.
    - `last_triggered_at` integer, nullable: Will be removed in the future.
    - `name` string
    - `notify_on_recovery` boolean: Send one notification when this alert, or each group of a multi-alert, stops firing. Off by default: an existing template that never mentions `{alert_status}` would otherwise render the firing wording twice.
    - `oncall_team` string, nullable: On-call team this alert pages, overriding ownership discovery. `None` means "work it out from the identity dimensions", which is the normal case — an explicit value is for the alert whose owner the dimensions cannot express.
    - `org_id` string
    - `owner` string, nullable
    - `pending_period_sec` integer
    - `priority` integer, nullable: How much humans care about this alert (PT-1). `None` = unset, which is every pre-Feature-2 alert. **Mutable** configuration — editable on any update, like `name`. Display + propagation only: it must never influence evaluation, silence, or delivery (PT-5 / D19). B-29 carved out one exception: when set, it takes precedence over the eval_level default for incident severity at creation/escalation — see `config::meta::alerts::priority` and `core::alerts::incidents::create_new_incident`. `value_type` is required here because the enum serializes as an integer via serde `try_from`/`into`; without it the generated OpenAPI would advertise a string enum and lie about the payload.
    - `query_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
    - `recovery_destinations` string[]: Where the recovery MESSAGE goes when it should not follow the firing. Empty = the firing's own destinations. Ticket closes are unaffected either way — a resolve has to carry the correlation key of the trigger that opened it, so it cannot be redirected.
    - `row_template` string
    - `row_template_type` 'String' | 'Json'
    - `runbook_url` string, nullable: Where the fix for this alert is written down. Copied onto every on-call response record the alert opens, so the person woken is handed the runbook in the page. Validated at save — a malformed link is refused rather than stored, because the moment it is read is the one moment nobody has the patience to debug a URL.
    - `stream_name` string
    - `stream_type` 'logs' | 'metrics' | 'traces' | 'profiles' | 'service_graph' | 'enrichment_tables' | 'file_list' | 'metadata' | 'index'
    - `suppress_repeats` boolean: Notify once per state change; enterprise only, other builds ignore it.
    - `tags` string[]: Selection tags (PT-6): bare (`prod`) or `key:value` (`service:checkout`), normalized and validated at save by `tags::normalize_tags`. NOT `context_attributes` — that field is free-form KV shipped into notification payloads with no validation. These are the filtering / scoping primitive. Skipped when empty so alerts that set no tags serialize exactly as they did before Feature 2 (G5).
    - `template` string, nullable: Optional template name. When specified, this template is used for all destinations instead of destination-level templates. This allows using different templates for different alerts while reusing the same destinations.
    - `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`.
    - `tz_offset` integer: Timezone offset in minutes. The negative secs means the Western Hemisphere
    - `updated_at` string, date-time
    - `workflows` string[]
  - `composite_alerts` CompositeAlertSummary[]: Live composite definitions for incident members (`alert_type="composite"`).
    - `alert_type` string, required
    - `enabled` boolean, required
    - `folder_id` string, required
    - `id` string, required
    - `name` string, required
  - `triggers` IncidentAlert[], required: Alert triggers (each alert firing is a separate trigger)
    - `alert_fired_at` integer, required
    - `alert_id` string, required
    - `alert_kind` 'internal' | 'external': Whether an incident's member alert is an OpenObserve alert or an externally-ingested one (External Alert Sources feature).
    - `alert_name` string, required
    - `correlation_reason` 'service_discovery' | 'primary_match' | 'secondary_match' | 'alert_id', required: How an alert was correlated to an incident
    - `created_at` integer, required
    - `detected_source` string, nullable
    - `incident_id` string, required
    - `labels` object, nullable
    - `source_url` string, nullable

## Other responses

- `404`: Not found

---

[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)
