---
title: "Preview what would actually alert this recipient"
method: GET
path: "/api/v1/recipients/{recipient}/notification-settings/preview"
tags: ["Notification settings"]
---

# Preview what would actually alert this recipient

`GET /api/v1/recipients/{recipient}/notification-settings/preview`

## 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/recipients/{recipient}/notification-settings/preview`
- Auth: API key in header `X-API-Key`

Resolves the rules the way delivery does and explains the outcome. Use this before trusting a configuration — it is the only endpoint that answers "who wins" rather than "what is stored". It reads state only and sends nothing.

**It answers for two different sends, because there are two.** `source`, `steps` and `resolution` describe an alert addressed to THIS PERSON: most specific wins — the personal rule beats a group rule, except that a group rule with `override_recipient_settings` beats the personal one; when nothing is configured the account-wide default steps apply. `group_delivery` describes an alert addressed to a GROUP the person belongs to, which is how inbound integrations page people. That path never consults the personal rule at all: the group has either its own rule or the account-wide default, and one decision covers every member. The two sections disagreeing is normal and is exactly what this endpoint exists to show.

**Read `warnings` first.** They are the facts that break delivery while every individual field still reads healthy — most often a group that carries the traffic having no rule of its own. `delivery.allowed` is NOT a verdict on the configuration: it answers only "may an alert go out at this very minute", i.e. quiet hours and the schedule grid. It stays `true` for a configuration that would reach nobody.

## Path parameters

- `recipient` string, uuid, required

## Query parameters

- `priority` 'low' | 'normal' | 'high' | 'critical'

## Response `200`

The resolved configuration and how it was reached.

- object
  - `data` object
    - `source` 'recipient_setting' | 'group_setting' | 'global_default': Which layer supplied the steps.
    - `steps` EscalationStep[]: The chain that would actually run.
      - `trigger` 'initial' | 'on_fail' | 'timeout': When the step runs. `initial` — the first dispatch. `on_fail` — the preceding dispatch could not be delivered at all (not a timeout: delivery failed). `timeout` — nobody acknowledged within delay_minutes; this is the step that escalates.
      - `action` 'send' | 'retry' | 'notify_manager': `send` — deliver over this step's channel/provider. `retry` — repeat the previous dispatch to the same target. `notify_manager` — deliver to somebody else; requires target_recipient_uuid.
      - `delay_minutes` union: How long the step waits before it runs, counted from the moment the chain reached it. On a timeout step this is therefore the acknowledgement window of the previous step. 0 means immediately, and is honoured literally — a timeout step at 0 runs as soon as the preceding dispatch is out, which is how you reach everybody at once. The literal string "adaptive" derives the delay from the alert priority and from how fast this company usually acknowledges; the `bounds_minutes` and `priority_defaults_minutes` the vocabulary reports under `adaptive` constrain that derived value only and never the number you send here.
        - integer
        - 'adaptive'
      - `channel` 'voice_call' | 'text_message' | 'voice_message', nullable: `text_message` — a written message. `voice_message` — a pre-rendered voice note inside a messenger. `voice_call` — a call that rings the person. Omit and the step delivers as a `text_message`, with the provider picked from the contacts that recipient can actually receive on — the same thing `provider: auto` does. Omitting it does not mean "no delivery": a step always names a channel by the time it runs.
      - `provider` 'telegram' | 'telegram_bot' | 'platform_asterisk' | 'custom_asterisk' | 'whatsapp' | 'viber' | 'email' | 'sms' | 'slack' | 'msteams' | 'auto', nullable: Who delivers it: telegram, telegram_bot, platform_asterisk, custom_asterisk, email, sms, whatsapp, viber, slack, msteams — or "auto" to pick the first provider the recipient actually has a contact for. A slug outside this list is refused, and so is a provider that cannot carry the step's channel — email cannot place a voice_call. Which providers this company may use depends on its plan; call GET /escalation-policies/vocabulary for the live list.
      - `ack_on` 'button' | 'read' | 'delivered', nullable: What counts as acknowledgement and therefore stops the chain. `button` — the person pressed acknowledge (the only mode that proves a human saw it). `read` — the provider reported a read receipt. `delivered` — the provider reported delivery; for voice_call it means the call was answered. Not every provider supports every mode — see ack_capabilities in the vocabulary. A mode the provider cannot report never acknowledges.
      - `target_recipient_uuid` string, uuid, nullable: Deliver this step to a specific person instead of the alert recipient. Required when action is notify_manager.
      - `schedule_targets` object[], nullable: Priority-ordered on-call targets. The first entry that resolves to somebody wins.
        - `schedule_uuid` string, uuid: An active schedule of this company.
        - `role` 'primary' | 'secondary' | 'manager': Which slot of the rotation to page. These are parallel duty tiers, not an order of escalation: `secondary` is the person covering alongside `primary` right now, NOT the person who takes over from them. For "the next one" use `occupant`.
        - `occupant` 'current' | 'next', nullable: Which person of that rotation this entry means. `current` — the default, and what every step written before this field existed does: whoever is on duty in that role right now. `next` — whoever takes that same role at the next handoff of that same rotation. This is how you say "if nobody answers, wake the next one" without inventing a second rotation shifted by one person: two rotations agree only until somebody regenerates one of them with a different line-up, and nothing in this API would report the drift. `next` is counted from the moment the alert was raised, not from the moment the step runs — a chain can cross a handoff, and an alert at 08:55 whose second rung fires at 09:05 must reach the person who came on at 09:00, not the one after them. An override on the next shift wins, so `next` names whoever will actually answer. It can legitimately resolve to nobody: when the next person is the one already on duty (a single-member rotation, or an override handing the shift back to them) it does not page them twice — escalating to the same person is what `retry` is for — and when the rotation has no shift after this one it has nobody to name. Either way the step moves on to its next candidate and then to fallback_recipient_uuid, and the outcome is reported to the operator, not through this API: a warning naming the reason (`same_as_current`, `no_upcoming_shift`) and the `wardenpoint_next_on_call_unmet_total` counter.
      - `fallback_recipient_uuid` string, uuid, nullable: Used when no schedule target resolved to anybody.
      - `target_priority` 'schedule_first', nullable: Send "schedule_first" to consult the rotations before target_recipient_uuid. Omit for the default order: specific person, then rotations, then fallback.
      - `audio_source` 'tts' | 'file', nullable: For voice channels: `tts` synthesises the alert text, `file` plays a stored recording.
      - `audio_file_uuid` string, uuid, nullable: The recording to play. Required when audio_source is file.
      - `tts_engine` string, nullable: Speech engine override. Premium engines need a plan that includes them.
      - `tts_text_override` string, nullable: Say this instead of the alert text.
      - `ai_processing` boolean, nullable: Let the AI rewrite the alert into speakable prose before synthesis. Requires a plan with custom TTS.
    - `delivery` object: Whether an alert may be delivered at this very moment.
      - `allowed` boolean
      - `blocked_by` string, nullable: Null when allowed; otherwise quiet_hours or schedule_blocked.
      - `retry_after` string, date-time, nullable: When the quiet window closes.
    - `quiet_hours` object
    - `limits` object: Effective rate limits plus how many alerts this recipient already got today.
    - `warnings` object[]: Facts that break delivery even though every other field reads healthy. Empty means there is nothing to say. Each entry carries a stable `code`, a human sentence and the group it is about (null when it is not about a group). Codes: `group_has_no_rule`, `group_rule_has_no_immediate_step`, `group_ignores_recipient_rule`, `unreachable_on_group_channel`, `group_has_no_route`, `recipient_has_no_route`.
      - `code` string
      - `message` string
      - `group` object, nullable
        - `uuid` string, uuid
        - `name` string
    - `group_delivery` object[]: What would happen for each group this recipient belongs to, when the alert is addressed to the GROUP. The personal rule plays no part here.
      - `group` object
        - `uuid` string, uuid
        - `name` string
      - `has_setting` boolean: False means the group has no usable rule for this priority and the account-wide default carries its traffic.
      - `source` 'group_rule' | 'group_policy' | 'company_default_no_group_rule' | 'company_default_empty_group_rule': Where the steps came from.
      - `source_description` string: The same fact as a sentence.
      - `steps` object[]: Channel and provider of each resolved rung, in order.
      - `reaches_this_recipient` boolean: False means a group alert would build no route to this person at all.
      - `routes` object[]: The routes a group alert would actually build for this person.
    - `resolution` object: Which layers competed, which one won and why the others were skipped. Describes the PERSONAL path only.

## Other responses

- `401`: API key missing, invalid, revoked or expired.
- `403`: API key lacks the config.read ability, or the recipient belongs to another company.
- `404`: No recipient with this UUID.

---

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