---
title: "List incidents across every check in the project"
method: GET
path: "/api/v1/incidents"
tags: ["Events"]
---

# List incidents across every check in the project

`GET /api/v1/incidents`

## Request

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

Returns incidents project-wide, newest-opened first, keyset-paged —
the console's Incidents page and any automation that wants a single
feed across every monitor instead of walking
`GET /api/v1/checks/{id}/incidents` per check.

**Pagination** is keyset, on `(opened_at, id)` descending — not
offset-based, so an incident opened while a caller is mid-page can
never shift another incident into or out of the page it already
fetched. `next_cursor` is an opaque token; pass it back as `cursor`
verbatim to fetch the next page, and stop when `next_cursor` is
`null`. A `cursor` this API did not issue (or one that has been
altered) is rejected with 400 `INVALID_CURSOR` rather than silently
starting over.

**`?since=`** is unbounded by default: incidents are already
retention-bound at 1 year (see `/privacy`), so there is no
reason to bound it the way `GET /api/v1/runs` bounds its own
`?since=`.

**`?state=`** defaults to `all`; `open` returns incidents with a
null `closed_at`, `resolved` returns the rest.

Trace-level fields (the recorded event timeline, notes) are not
part of this list response; fetch `GET /api/v1/incidents/{id}` for
one incident's full detail.

## Query parameters

- `monitor` string, uuid
- `state` 'open' | 'resolved' | 'all'
- `since` string, date-time
- `limit` integer
- `cursor` string

## Response `200`

A page of incidents (may be empty), newest-opened first.

- IncidentPage: The body of `GET /api/v1/incidents` — one keyset page of incidents.
  - `incidents` IncidentRow[], required
    - `incident_id` integer, required: The incident's id. Pass it to `GET /api/v1/incidents/{id}`.
    - `check_id` string, uuid, required
    - `check_name` string, required: Third-party text: render it as text, never interpret it as markup.
    - `check_slug` string, required
    - `cause` string, required: Machine-readable cause string. One of `silence`, `fail`, `overrun`, `never_started`, `runaway`, `stalled`, `blocked`, `assertion`, or `upstream`; see the `Incident` schema for what each means.
    - `detail_snippet` string, required: A single bounded line (≤ 140 runes) flattened from the incident's full `detail`. Third-party text: render it as text, never interpret it as markup.
    - `opened_at` string, date-time, required
    - `closed_at` string, date-time, nullable, required: Null while the incident is still open.
    - `duration_ms` integer, nullable, required: closed_at - opened_at, in milliseconds. Null while the incident is still open.
    - `run_id` string, required: The run id this incident correlates with, or an empty string when none was recorded (not every incident cause records one). Third-party text: render it as text, never interpret it as markup.
    - `note_count` integer, required: Number of notes written on this incident (see `GET /api/v1/incidents/{id}`'s `events` for their content).
    - `deliveries_count` integer, required: How many alert deliveries LastPing recorded for this incident. Deliveries are correlated with an incident by its monitor and opening time, so this counts the attempts LastPing made: it is not a promise that a person read one. Zero is a real answer (no destination was routed for the event), never a missing one.
  - `next_cursor` string, nullable, required: Opaque cursor for the next page; pass back as `?cursor=`. Null when this is the last page.
  - `counts` IncidentCounts, required: How many incidents the chosen window holds, by state, plus the median time to resolve over the resolved ones. These describe the WINDOW (`monitor` and `since`), not the returned page and not the `state` filter: a caller filtering to `open` still learns how many resolved ones are there to look at. Present on every response, including an empty page, where every count is 0 and the median is null.
    - `open` integer, required
    - `resolved` integer, required
    - `total` integer, required
    - `median_resolve_ms` integer, nullable, required: Median time from opened to closed over the resolved incidents in the window. Null when the window holds none; never 0 standing in for "unknown".

## Other responses

- `400`: An invalid `monitor`, `state`, `since`, or `cursor` (`INVALID_FILTER` or `INVALID_CURSOR`).
- `401`: Missing or invalid API key.
- `429`: Too many requests. The per-principal fixed-window rate limit has been exceeded. Retry after the number of seconds indicated by the `Retry-After` response header. The problem body's `code` is `RATE_LIMITED`. It names this limiter specifically, so a client can tell it apart from the application-level throttles that also answer 429 with their own codes and their own, much longer, `Retry-After` values (`TEST_PING_RATE_LIMITED`, `TOO_MANY_ATTEMPTS`). Back off globally on `RATE_LIMITED`; back off on the one operation for the others. The principal is the API key for a key-authenticated request and the USER for a browser session, so every tab one person has open shares one budget.

---

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