---
title: "Trigger a real test notification"
method: POST
path: "/agent/v1/notifications/test"
tags: ["Agent"]
---

# Trigger a real test notification

`POST /agent/v1/notifications/test`

## Request

- Base URL: `https://api.run402.com`
- URL: `https://api.run402.com/agent/v1/notifications/test`
- Auth: API key in header `SIGN-IN-WITH-X`

Synthesizes a sample organization_past_due event and pushes it through the normal worker pipeline (email/webhook), AND — independently — delivers a synthetic event through the caller's Telegram routing rules (notification-channel-routing-telegram, v1.126), so one call verifies the full binding+rule+render+send chain end-to-end. Audit rows are marked is_test=true. Rate-limited per wallet at 1/min.

## Headers

- `SIGN-IN-WITH-X` string, required

## Request body

- object
  - `source` 'app' | 'platform'
  - `event_type` string: Flat snake_case, ^[a-z][a-z0-9_]{2,63}$.
  - `severity` 'info' | 'notice' | 'warn' | 'critical': event-attention-rules: the synthetic event's severity, so a rule at the default minimum matches it. A rule whose minimum sits above it is reported under `telegram.skipped_rules` instead of staying silently unmatched. Any other value is 400 `INVALID_SEVERITY`.

## Response `200`

Queued

- object
  - `status` 'queued'
  - `source_event_id` string
  - `telegram` object: Independent of status/source_event_id above (design D5's two feeders both converge on the same deliverer, but /test calls it directly). Empty destinations when the owner has no matching rule — Faithful, not an error.
    - `destinations` object[]
      - `binding_id` string, uuid
      - `label` string, nullable
      - `delivered` boolean
      - `transient` boolean: Present only when delivered=false. True for a retryable failure (429/5xx/timeout/unconfigured channel); false for a hard failure (bot blocked, chat not found).
      - `description` string: Present only when delivered=false. telegram_not_configured when the platform's notification bot secret is unprovisioned.
    - `skipped_rules` object[]: event-attention-rules: rules that did not send for the synthetic event, and why — below_min_severity (other dimensions matched, min_severity sits above the synthetic severity) or deferred_to_window (a windowed rule never sends per event; its first message arrives at next_window_closes_at). Empty when none.
      - `rule_id` string, uuid
      - `reason` 'below_min_severity' | 'deferred_to_window' | 'escalation_not_exercised'
      - `escalation_level` integer, nullable: escalation_not_exercised only: the test never pages the ladder.
      - `next_window_closes_at` string, date-time: deferred_to_window only.
      - `min_severity` 'info' | 'notice' | 'warn' | 'critical'
  - `note` string

## Other responses

- `400`: Wallet has no verified contact email, or (when source/event_type overrides are supplied) they fail the routing-rule grammar (INVALID_SOURCE / INVALID_EVENT_TYPE)
- `429`: Rate-limited; Retry-After header set

---

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