Notifications API
Configure per-channel notification settings (digest + instant), send test messages, query delivery history, and manage exposure-alert subscriptions.
Channel settings
Return the caller's notification_settings rows. Each (notification_type, delivery_class) pair is its own row — e.g. a team can have an instant+slack row and a digest+slack row configured independently.
Response
[
{
"id": "uuid",
"notification_type": "slack",
"delivery_class": "instant",
"is_enabled": true,
"config": { "webhook_url": "https://hooks.slack.com/services/..." }
},
{
"id": "uuid",
"notification_type": "slack",
"delivery_class": "digest",
"is_enabled": true,
"frequency_days": 7,
"notification_time": "09:00:00",
"config": { "webhook_url": "https://hooks.slack.com/services/..." }
}
]Upsert the settings row for a given (type, delivery_class). :type must be one of email, webhook, slack, pushover, teams. delivery_class is required in the body so digest and instant rows are addressed independently. Digest delivery is available on email, slack and teams only — a digest row for webhook or pushover is rejected with 400.
Request Body
| Parameter | Type | Required | Description |
|---|---|---|---|
| delivery_class | string | Yes | "instant" or "digest" |
| is_enabled | boolean | No | Enable or disable this channel for the given delivery class |
| frequency_days | number | No | Digest cadence (1, 7, 14, or 30). Digest delivery only. |
| notification_time | string | No | Local time of digest send, HH:MM:SS. Digest only. |
| config | object | No | Channel-specific config, e.g. { "webhook_url": "https://..." } |
| min_severity | string | No | Severity floor for instant exposure alerts: critical | high | medium | low | info. Default medium. Ignored for digest rows. |
Example request
{
"delivery_class": "digest",
"is_enabled": true,
"frequency_days": 7,
"notification_time": "09:00:00",
"config": { "webhook_url": "https://hooks.slack.com/services/..." }
}Response
{
"id": "uuid",
"notification_type": "slack",
"delivery_class": "digest",
"is_enabled": true,
"frequency_days": 7,
"notification_time": "09:00:00",
"config": { "webhook_url": "https://hooks.slack.com/services/..." }
}Test send
Queue a real test notification for a channel and recipient. The worker delivers it on its next cycle (typically under five minutes) and the attempt — success or failure — then appears in the delivery log under the returned id, making this an end-to-end delivery check rather than a config validation.
Request Body
| Parameter | Type | Required | Description |
|---|---|---|---|
| channel | string | Yes | email, webhook, slack, pushover, or teams |
| recipient | string | Yes | Email address for email; webhook URL for webhook/slack/teams; Pushover user key for pushover. |
| subject | string | No | Optional custom subject for email |
| metadata | object | No | Optional metadata echoed in the test payload |
Response
HTTP 201 Created
{
"id": "uuid",
"channel": "slack",
"recipient": "https://hooks.slack.com/services/...",
"status": "queued",
"created_at": "2026-08-18T09:00:00Z"
}Delivery log
Paginated notification delivery history, most recent first. One entry per delivery, so channels always holds a single value — the channel filter matches it exactly. status is success (delivered), failed (retries exhausted) or partial (attempted, will retry). error_message carries the last failure reason where there is one.
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| channel | string | No | email | webhook | slack | pushover | teams |
| status | string | No | success | failed | partial |
| limit | number | No | Max 100, default 50 |
| offset | number | No | Rows to skip, default 0 |
Response
[
{
"id": "uuid",
"channels": ["slack"],
"status": "success",
"message_preview": "SSL expiry — example.com",
"sent_at": "2026-04-19T09:00:00Z",
"error_message": null,
"metadata": null
}
]See also: Notifications & Alerts guide