---
title: "List an agent's open incidents (the failure inbox)"
method: GET
path: "/api/v1/agents/{id}/open-incidents"
tags: ["Agents"]
---

# List an agent's open incidents (the failure inbox)

`GET /api/v1/agents/{id}/open-incidents`

## Request

- Base URL: `https://app.lastping.dev`
- URL: `https://app.lastping.dev/api/v1/agents/{id}/open-incidents`
- Auth: API key in header `X-Api-Key`

Everything currently broken on the monitors this agent owns, newest
first, as a JSON array (never null). This is the **pull** half of
failure delivery: an agent polls it at the start of its next run and
learns what broke while it was not looking — no webhook, no inbox, no
chat integration to configure.

Only **open** incidents are returned. There is no `closed_at` field:
it would be null on every row this endpoint can emit.

The payload carries what an agent cannot work out from its own run:

- `cause` — `silence` and `fail` demand opposite responses. A `fail`
  means the job ran and reported an error; a `silence` means it never
  reported at all, which usually implicates the scheduler or the host
  rather than the job.
- `body_excerpt` — the error text the failing run printed.
- `failed_step` — where it died. For a `stalled` incident this is the
  whole diagnosis: the run is alive but has not moved past this step.
- `failure_signature` — **new problem, or the fortieth repeat.** The
  single fact that decides retry versus escalate.
- `duration_vs_normal` — a comparison, never a bare number. "40
  minutes" is a measurement; "8.3x the typical run" is a diagnosis.

**Every enrichment degrades to absent rather than erroring.** A
brand-new monitor has no fingerprint history and no archived daily
stats; an incident opened by silence has no failure body because
nothing was reported — that is the complaint itself. The thin payload
is still useful and thickens on its own as history accumulates. This
endpoint never fails over a missing enrichment.

- `exit_code` — the status the run exited with, when it sent one.
  `137` (SIGKILL, usually the OOM killer) and `1` demand different
  responses, and only the numeric ping form `/ping/{id}/{code}` carries
  one. The field is **absent when no code was reported**, which is not
  the same as `0`; see the `OpenIncident` schema.

## Response `200`

Array of open incidents (may be empty).

- OpenIncident[]
  - `incident_id` integer, required: Identifies this incident. Stable for its lifetime.
  - `check_id` string, uuid, required: The monitor this incident is about.
  - `check_slug` string, required
  - `check_name` string, required
  - `cause` 'silence' | 'fail' | 'overrun' | 'never_started' | 'runaway' | 'stalled' | 'blocked' | 'assertion' | 'upstream', required: Why the incident opened. These need different responses, which is the reason this field leads the payload: - `fail` — the job ran and explicitly reported failure. - `upstream`: runs in a row ended on the model provider's API error (`server_error`, `overloaded` or `rate_limit`), not on the agent's own work: 3 of them, or the monitor's `failure_threshold` when that is higher. `detail` names the last error type. Fewer are recorded on the run and page no one. - `assertion` — the job reported success, but its output violated criteria the agent itself declared at the start of that run. - `silence` — nothing was reported within the expected window. Suspect the scheduler or the host before the job. - `never_started` — the monitor has never reported at all; the wiring is probably wrong. - `overrun` — the run exceeded its maximum runtime. - `stalled` — the run is alive but has reported no step progress. `failed_step` is the diagnosis here. - `runaway` — the monitor exceeded a ping-rate ceiling or a metric guard. - `blocked` — a run is waiting on a human.
  - `opened_at` string, date-time, required: RFC 3339 UTC timestamp when the incident opened.
  - `detail` string: Why it opened, when the opener knew more than the cause code can say — which assertion rejected the output, which metric guard tripped, the last API error type of an `upstream` incident (`Last error: server_error`), or a CI job's own failure detail. Omitted when empty.
  - `run_id` string: The `rid` of the run this incident is about, so the agent can line it up against its own logs. Recorded when the incident opens, which is the only moment it can be: the transition that opens an incident also clears the monitor's in-flight run, so the identity does not survive anywhere else. Omitted when there was no run to name — a `never_started` incident, or a monitor that reported without ever opening a run.
  - `body_excerpt` string: The failure output the run reported: the body of the ping that opened the incident, or — for an incident opened by a missed deadline, where no ping coincides with `opened_at` — the latest `fail` reported while the incident has been open. That second case matters more than it looks. Incidents open only on the transition into down, so a cron that runs late and then fails keeps its original `silence` incident: without the fallback the agent would be told "silence" while the error text sat unread. Omitted only when nothing was reported at all, which for `never_started` and an ongoing `silence` is the incident itself.
  - `exit_code` integer: The status the run exited with, as sent through the numeric ping form `POST /ping/{check_id}/{code}`. Read from the **same ping** `body_excerpt` comes from, so the output and the status always describe one run. **Omitted means no exit code was reported. It never means "exited cleanly".** A job reports a status only through the numeric form; the word forms (`/fail`, `/start`, …) carry none, an incident opened by a missed deadline has no ping at all, and pings recorded before this field existed did not keep the number and cannot be backfilled. A clean exit is the **present** value `0` — which does occur on an incident, since an `assertion` incident opens on a run that reported success and then failed the criteria the agent declared for it. Two conventions are worth decoding, and are what the console shows in words beside the number: - **128 + n is death by signal** — `137` is SIGKILL (most often the OOM killer or a container runtime), `143` is SIGTERM (a shutdown the job did not survive), `139` is SIGSEGV. - **`124` is a `timeout(1)` kill** — the status GNU `timeout` uses when it kills the command it wrapped. Everything else is **application-defined**: `1`, `2` and the rest mean whatever the program that exited chose them to mean, and LastPing does not guess.
  - `failed_step` object: The last step the run reported before it stopped progressing — where it died. Omitted when the run reported no steps.
    - `name` string
    - `seq` integer: Position in the run's step timeline, starting at 1.
    - `at` string, date-time
  - `failure_signature` object: **New problem, or the fortieth repeat.** The recurrence record for this exact failure, matched by fingerprinting the failure body through the same normalisation the writer used — timestamps, UUIDs, IPs, absolute paths, hex runs and integers are replaced by placeholders, so the same underlying failure matches across runs even though its text differs every time. Omitted when the incident has no failure body, or when this body has no recorded history yet.
    - `fingerprint` string: 16 hex characters. Exposed so an agent can correlate two incidents as "the same failure" itself, across monitors and across polls.
    - `occurrences` integer: How many times this exact failure has been recorded on this monitor — every occurrence, not only the ones that opened an incident, so a job that fails repeatedly while already down still accrues history.
    - `first_seen` string, date-time: When this failure was first recorded. Survives ping retention: the signature history is deliberately never pruned, so this can predate the oldest ping still stored.
    - `last_seen` string, date-time
  - `duration_vs_normal` object: Was this run unusually slow — the only form of the duration question worth asking. Omitted when the run's duration is unknown, or when there is no baseline to compare against: no archived day and fewer than 5 measured runs in the last 30 days (a brand-new monitor has neither). A monitor with no archived day but at least 5 measured runs in the last 30 days is compared against the median of those runs, and `summary` says so. `run_ms` is the run's measured duration when it completed; otherwise — for a `fail`, and for every run that never finished, which is every `overrun` and `stalled` — it is how long the run had been going when the incident opened. That figure is fixed at the moment of judgement, so polling the same open incident twice always reports the same number.
    - `run_ms` integer
    - `typical_ms` integer: What a normal run costs. Named `typical_ms`, not `p50_ms`, on purpose: it is a median of the archived daily medians, since percentiles do not recombine. Calling it a p50 would claim a precision the daily summaries cannot deliver. On a monitor with no archived day it is the median of its measured runs in the last 30 days instead.
    - `ratio` number, double: `run_ms / typical_ms`. This is the diagnosis.
    - `days_sampled` integer: How many archived days the baseline was computed from, so a thirty-day norm can be told from a two-day one instead of both reading as settled. 0 when the baseline came from recent runs rather than archived days; `summary` then names the run count ("from 5 runs in the last 30 days").
    - `summary` string: The comparison as one sentence.
  - `ci` object: Provider-side context for a CI failure, decoded from the failing run's CI metadata. Omitted entirely for non-CI monitors. `run_url` is the valuable one: it is where the agent goes for the full log when `body_excerpt` is not enough.
    - `run_url` string
    - `failing_stage` string
    - `outcome` string
    - `branch` string
    - `commit_sha` string

## Other responses

- `400`: id is not a valid UUID.
- `401`: Missing or invalid API key.
- `404`: Agent not found in this project.

---

[API](https://skmtc.dev/lastping/apis/lastping-management-api.md) · [All operations](https://skmtc.dev/lastping/apis/lastping-management-api/llms.txt) · [OpenAPI document](https://skmtc.dev/lastping/apis/lastping-management-api/revisions/bbc6eda91c46?raw)
