Notifications
Configuring which events alert you and how.
Notifications
The notification settings page lets you control which events send alerts and how they're delivered. This is the UI-side companion to the Automation: notifications page, which covers the backend.
Accessing notification settings
Go to Settings in the sidebar, then Notifications.
Two sections:
- Channels — email and webhook configuration
- Events — which events trigger notifications
Channels
To enable email notifications, configure SMTP:
- SMTP host — your mail server or provider
- SMTP port — usually 587 or 465
- Username — SMTP login
- Password — SMTP password
- From address — the "from" shown to recipients
- To address — where notifications go
- Use TLS — toggle for encrypted connections
Click Test to send a test email. If it arrives, the configuration is correct.
These settings write to apps/web/.env.local under the hood. Restart the
worker after changing them for them to take effect.
Webhook
To enable webhook notifications:
- URL — the endpoint to POST to
- Secret — HMAC-SHA256 signing key
Click Test to send a test webhook. Your endpoint should receive a POST with a test payload signed with the secret.
See Automation: notifications for the payload format and signature verification code.
Events
The events section lists every event type that can trigger a notification. For each:
- Email — on/off toggle
- Webhook — on/off toggle
- Priority — normal or high
High-priority notifications bypass quiet hours.
Defaults
The starting configuration:
| Event | Webhook | Priority | |
|---|---|---|---|
| finding.critical | on | on | high |
| report.delivered | on | off | normal |
| delivery.viewed | off | on | normal |
| invoice.paid | on | off | normal |
| invoice.overdue | on | off | normal |
| cert.expiring | on | off | normal |
| backup.completed | off | off | normal |
| backup.failed | on | on | high |
Change any of these to match your preferences.
Quiet hours
Set a window where notifications are suppressed:
- Start — e.g. 22:00
- End — e.g. 07:00
During quiet hours:
- Normal priority events queue and deliver at the end of quiet hours
- High priority events deliver immediately
Use high priority for events you'd want to know about at 3am — backup failures, critical findings on active engagements.
Digest mode
For less important events, batch them:
- Digest enabled — toggle
- Digest hour — when to send (e.g. 08:00)
In digest mode, normal-priority events accumulate and are sent as one email per day.
High-priority events still deliver immediately.
Testing notifications
From the notifications page:
- Test email — sends a test email to the configured address
- Test webhook — POSTs a test payload to the configured URL
Both send a payload marked "event": "test.notification". Your handlers
should ignore it or handle it specially.
Notification history
Below the settings, a log of recent notifications:
- Event — what fired
- Channel — email or webhook
- Status — delivered, failed, queued
- Timestamp
Failed notifications show the error. Click into a failed delivery to see the full response.
Retry button appears for failed deliveries (up to 6 attempts as per the retry policy).
Email templates
The default emails are plain text. They include:
- Event type
- Timestamp
- Key details from the payload
- A link to the relevant page in ATHELOS (if applicable)
To customize:
- Open the notification template editor
- Edit the subject and body
- Use
{{variable}}placeholders for dynamic content - Save
Templates are stored in the database. Changes take effect on the next notification.
Webhook retries
Webhooks retry with exponential backoff:
- 1 second
- 4 seconds
- 16 seconds
- 1 minute
- 5 minutes
- 30 minutes
After 6 failures, the notification moves to the failed queue and stops retrying. Failed notifications appear in the history log.
Webhook idempotency
Because retries can deliver the same event multiple times, your webhook receiver should be idempotent. Each payload includes:
event.id— a unique ID for the notificationtimestamp
Use event.id as a deduplication key if you're taking action on the
notification.
Signature verification
Every webhook carries an X-ATHELOS-Signature header — HMAC-SHA256 of
the raw body, using your webhook secret.
Verify on receipt:
import { createHmac, timingSafeEqual } from "crypto";
function verify(rawBody: string, signature: string, secret: string) {
const expected = createHmac("sha256", secret).update(rawBody).digest("hex");
return timingSafeEqual(
Buffer.from(expected),
Buffer.from(signature),
);
}Reject any webhook whose signature doesn't verify.
Rate limiting
Notifications are rate-limited per channel:
- Email — 30 per hour
- Webhook — 60 per hour
If you exceed the limit, notifications queue and deliver as the window clears.
Disabling all notifications
Toggle both channels off, or set EMAIL_NOTIFICATIONS=false and
WEBHOOK_NOTIFICATIONS=false in the env.
Nothing sends unless configured. A fresh install has notifications off.
Common issues
Test email doesn't arrive
- Check spam folder
- Verify SMTP credentials
- Check the worker is running
- Look in the notification history log
Webhook returns 4xx
- Your endpoint is rejecting the request
- Check the URL is correct
- Verify the signature verification is using the right secret
- Check the notification history log for the response
Notifications delayed
- Quiet hours may be active
- Digest mode may be on
- Rate limit may be throttling
Check the history log — queued notifications show their scheduled time.
Duplicate notifications
- Retries can cause duplicates
- Ensure your receiver is idempotent
- Use
event.idfor deduplication
Where to go next
- Automation: notifications — backend details
- Event bus — how events flow
- Security — threat model