---
title: "List notifications with pagination and filters"
method: GET
path: "/api/v1/notifications"
tags: ["Notifications"]
---

# List notifications with pagination and filters

`GET /api/v1/notifications`

## Request

- Base URL: `https://wardenpoint.com` (the document declares no server; this is the origin it was published from)
- URL: `https://wardenpoint.com/api/v1/notifications`
- Auth: API key in header `X-API-Key`

Everything this company sent, newest first — including the rescue emails the platform sent on its behalf.

**Rows with `is_owner_fallback: true` are not alerts you asked for.** They are the umbrella guarantee at work: an alert reached nobody, so the account owner was emailed that delivery failed. They are listed rather than hidden because an email really did go out, and hiding it would be its own lie — but they must not be counted as delivered alerts. Their `recipient` is the internal "Owner (fallback delivery)" one, flagged `is_system: true`; that recipient never appears in `GET /recipients` and is not a missing person. The alert each rescue is about carries `delivered_via_owner_fallback: true` in its own `metadata` and stays `failed`.

## Query parameters

- `page` integer
- `per_page` integer
- `status` 'pending' | 'processing' | 'completed' | 'failed' | 'cancelled' | 'acknowledged' | 'escalating': Lifecycle state of a notification. FOUR of the seven are terminal and will never change again: `completed`, `failed`, `cancelled`, `acknowledged`. Poll until you see one of those four — waiting only for `completed` or `failed` hangs until your own timeout on every alert a human confirms. `pending` — created, waiting for a worker. Not terminal. `processing` — a worker is delivering it right now. Not terminal. `escalating` — delivery happened, nobody confirmed in time, and the escalation chain is walking to the next person. Not terminal: it still ends in `acknowledged` or `failed`. `completed` — delivered. TERMINAL. `failed` — every channel and attempt was exhausted without delivery. TERMINAL, and the only status `retry` accepts. `cancelled` — stopped before delivery, by the cancel endpoint. TERMINAL. `acknowledged` — a human confirmed it and the escalation chain stopped. TERMINAL, and the outcome the product exists for: an alert that reaches this has done its job.
- `priority` 'low' | 'normal' | 'high' | 'critical'

## Response `200`

Paginated notifications. The paginator sits at the top level — `data` plus `current_page`, `per_page`, `total`, `last_page` — and each entry of `data` is exactly what the card and the status poll return for that notification.

- object
  - `data` NotificationDetail[]
    - `uuid` string, uuid
    - `status` 'pending' | 'processing' | 'completed' | 'failed' | 'cancelled' | 'acknowledged' | 'escalating': Lifecycle state of a notification. FOUR of the seven are terminal and will never change again: `completed`, `failed`, `cancelled`, `acknowledged`. Poll until you see one of those four — waiting only for `completed` or `failed` hangs until your own timeout on every alert a human confirms. `pending` — created, waiting for a worker. Not terminal. `processing` — a worker is delivering it right now. Not terminal. `escalating` — delivery happened, nobody confirmed in time, and the escalation chain is walking to the next person. Not terminal: it still ends in `acknowledged` or `failed`. `completed` — delivered. TERMINAL. `failed` — every channel and attempt was exhausted without delivery. TERMINAL, and the only status `retry` accepts. `cancelled` — stopped before delivery, by the cancel endpoint. TERMINAL. `acknowledged` — a human confirmed it and the escalation chain stopped. TERMINAL, and the outcome the product exists for: an alert that reaches this has done its job.
    - `priority` 'low' | 'normal' | 'high' | 'critical'
    - `message` string: The text as it was sent.
    - `audio_file` string, nullable
    - `recipient` object, nullable: Null when the recipient has been deleted since.
      - `uuid` string, uuid
      - `name` string
      - `is_system` boolean: True only for the internal "Owner (fallback delivery)" recipient that carries rescue emails. Such a recipient is deliberately absent from `GET /recipients` — it is not a person anybody configured and there is nothing to fix about it; it exists so a rescue email travels the ordinary delivery pipeline and gets routes, attempts and a status like every other send. A name here that you cannot find in the recipient list is this, not a deletion.
    - `is_owner_fallback` boolean: True when this notification IS the rescue email to the account owner rather than an alert of yours. The alert it was sent about is named by `original_notification_uuid` in `metadata`, and `owner_fallback_reason` there says why delivery failed.
    - `channels` object[]: One entry per channel attempted, in the order they were attempted. A notification that reads `completed` can still carry a failed channel here — that is the fallback working as intended.
      - `type` string: Channel slug: text_message, voice_message, voice_call, email, sms, …
      - `provider` string: Provider slug: telegram, platform_asterisk, smtp, …
      - `status` string: Per-channel outcome. Independent of the notification status above.
      - `attempts` integer
      - `max_attempts` integer
    - `total_attempts` integer: Delivery attempts across all channels.
    - `external_id` string, nullable: Provider-side identifier of the delivered message or call, when the provider gives one.
    - `error_message` string, nullable: Last delivery error. Present on `failed`, and possibly on a notification that later succeeded through a fallback.
    - `metadata` object, nullable
    - `escalation` object, nullable: The escalation chain this alert started, or null when it started none. Null is the ordinary case rather than a fault: a chain opens only when the rule governing the alert has timeout rungs to walk. An observability alert matched by a `message` routing action never opens one — only `escalate` does. This is the answer to "what happens next", and until now the API had none: the card said nothing about escalation at all, and the listing exposed only the chain's internal numeric id, which no other endpoint accepts. The notification's own step counter is deliberately not surfaced — it writes 0 both when a chain starts and when its first rung runs, so the number cannot tell those apart. Count from here instead.
      - `uuid` string, uuid: The chain's UUID.
      - `status` 'active' | 'acknowledged' | 'completed' | 'failed' | 'cancelled': `active` while rungs are still coming. `acknowledged` when a human took the alert, `completed` when the ladder ran out, `cancelled` or `failed` otherwise — all four are terminal and nothing further will be paged.
      - `steps_taken` integer: How many rungs of the ladder have already run. Zero means none has yet — the alert was paged and the first rung is waiting for `next_step_at`. One unit in every state, deliberately: it means the same thing whether the chain is still active or has stopped, and it only ever grows. A field that counted "the rung now running" while active and "rungs that ran" once stopped would show 1 and then 0 for a chain acknowledged before its first rung, and a client rendering progress would watch it go backwards.
      - `total_steps` integer: Rungs in the ladder. `steps_taken` equal to this means the ladder is spent and nobody is left to page, whatever the status says.
      - `next_step_at` string, date-time, nullable: When the next rung was scheduled to fire. Null on a stopped chain, and null on an active one whose next rung is not scheduled yet. **It is a schedule, not a promise, and it can be in the past.** The value is written when the rung is queued and is not rewritten while it waits, so a busy escalation queue leaves behind an instant that has already gone. Read a past value as "due, not yet run": a countdown built on it will go negative, and that is the queue running late rather than the chain being broken.
      - `started_at` string, date-time, nullable
      - `completed_at` string, date-time, nullable: When the chain stopped, for whatever reason. Null while it runs.
    - `created_at` string, date-time
    - `completed_at` string, date-time, nullable: Set once the notification reaches a terminal status; null while it is still moving.
    - `acknowledged_at` string, date-time, nullable: When a human took the alert. Null on anything that was never acknowledged. This is the moment the escalation chain stopped, so `acknowledged_at - created_at` is the response time of this incident.
    - `acknowledged_via` string, nullable: The label recorded with the acknowledgement — the `source` you sent to the acknowledge endpoint (default `api`), or the surface the platform acknowledged from on its own: `telegram_callback`, `dtmf`, `dashboard`, `email_link`, and so on. Null on anything that was never acknowledged. Together with `acknowledged_at` this is the audit trail the acknowledge endpoint promises; nothing else exposes it.
  - `current_page` integer
  - `per_page` integer
  - `total` integer
  - `last_page` integer

## Other responses

- `401`: API key missing, invalid, revoked or expired.
- `403`: API key lacks the notifications.read ability.

---

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