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, sms, webhook, slack, pushover, teams. delivery_class is required in the body so digest and instant rows are addressed independently.
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://..." } |
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
Send a one-off test notification to verify a channel is configured correctly. Does not persist to the notification log.
Request Body
| Parameter | Type | Required | Description |
|---|---|---|---|
| channel | string | Yes | email, sms, webhook, slack, pushover, or teams |
| recipient | string | Yes | Email address for email; webhook URL for webhook/slack/teams; phone number for sms. |
| subject | string | No | Optional custom subject for email |
| metadata | object | No | Optional metadata echoed in the test payload |
Response
HTTP 201 Created
{
"channel": "slack",
"recipient": "https://hooks.slack.com/services/...",
"status": "sent",
"created_at": "2026-04-19T20:00:00Z"
}Delivery log
Paginated notification delivery history. The channel filter matches rows whose channels array contains the given value.
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| channel | string | No | email | sms | webhook | slack | pushover | teams |
| status | string | No | success | failed | partial |
| limit | number | No | Max 100, default 50 |
Response
[
{
"id": "uuid",
"channels": ["slack", "email"],
"status": "success",
"message_preview": "SSL expiring in 7 days: example.com",
"sent_at": "2026-04-19T09:00:00Z",
"metadata": { "domain": "example.com" }
}
]Exposure subscriptions
Per-user subscriptions that control which exposure events (new findings, severity thresholds) trigger alerts, via which channels. Scoped to a single domain or the whole team.
List the caller's exposure subscriptions for the current team.
Response
[
{
"id": "uuid",
"domain_id": "uuid-or-null",
"subscription_type": "critical_exposure_only",
"alert_threshold": "high",
"alert_on_new_exposure": true,
"notification_channels": ["slack", "email"],
"is_enabled": true
}
]Create an exposure subscription.
Request Body
| Parameter | Type | Required | Description |
|---|---|---|---|
| domain_id | string (uuid) | No | Scope to a single domain; omit to cover all team domains. |
| subscription_type | string | Yes | critical_exposure_only | all_exposures | all_team_exposures |
| alert_threshold | string | Yes | critical | high | medium | low | info |
| alert_on_new_exposure | boolean | No | Default true — alert on every new exposure event meeting the threshold. |
| notification_channels | array | Yes | Non-empty array of channels: email | sms | webhook | slack | pushover | teams |
| is_enabled | boolean | No | Default true. |
| config | object | No | Free-form per-subscription config. |
Response
HTTP 201 Created
{
"id": "uuid",
"domain_id": "uuid",
"subscription_type": "critical_exposure_only",
"alert_threshold": "high",
"alert_on_new_exposure": true,
"notification_channels": ["slack", "email"],
"is_enabled": true
}Update a subscription owned by the caller.
Request Body
| Parameter | Type | Required | Description |
|---|---|---|---|
| subscription_type | string | No | See create endpoint |
| alert_threshold | string | No | See create endpoint |
| alert_on_new_exposure | boolean | No | |
| notification_channels | array | No | Non-empty array of channels |
| is_enabled | boolean | No | |
| config | object | No |
Response
{
"id": "uuid",
"alert_threshold": "critical",
"is_enabled": true
}Delete an exposure subscription owned by the caller.
Response
{
"id": "uuid",
"deleted": true
}See also: Notifications & Alerts guide