ClouisleClouisle

Notifications & External Channels

View notifications, configure delivery channels, and choose which events create automatic notifications

The notification center aggregates site-wide, team, and personal notifications, with search, unread filtering, and bulk mark-as-read. Automatic notifications are triggered by system events: administrators decide which event types produce a notification and which external channels deliver it — regular users can only view and mark as read.

View Notifications

Notifications have three scopes, and visibility is computed server-side from team membership:

ScopeValueWho sees it
GlobalglobalEvery signed-in user
TeamteamMembers of the target team
UseruserOne specific user

Levels are low / medium / high. Read state is per-user (a NotificationRead row), so marking something read never affects anyone else. Expired notifications (expires_at in the past) are hidden by default — so a notification "disappearing" usually means it expired, not that it was deleted.

Filters accepted by GET /api/v1/notifications:

ParameterDescription
scopeFilter by scope (global, team, user)
typeExact event type, e.g. kb.doc_failed
levelFilter by level (low, medium, high)
searchCase-insensitive substring over title, content, and type
unread_onlyReturn unread only
created_from / created_toFilter by creation time range
page / page_sizePagination; page_size max 100 (default 20)

There is no PATCH /api/v1/notifications/{id}, and no per-user single-item delete. Marking read is bulk-only via POST /api/v1/notifications/read (pass notification_ids or mark_all: true); deleting is admin-only. Clearing one specific item is therefore not possible today — filter, then mark the batch as read.

Configure Channels

Configure channels under Site Settings → Notification Channels. A channel delivers only when both conditions hold: its *_enabled flag is true and the required credentials are filled in. Every channel switch defaults to false.

ChannelKey settingsTest endpoint
Emailsmtp_enabled, smtp_host, smtp_port, smtp_encryption (none/ssl/tls), smtp_username, smtp_password, email_from_name, email_from_address/test-email
DingTalkdingtalk_enabled, dingtalk_notification_type (webhook or app), webhook URL/secret, or app key/secret/agent ID/test-dingtalk
WeComwechat_enabled, wechat_notification_type (webhook or app), webhook URL, or corp ID (wechat_corp_id) / agent ID (wechat_agent_id) / app secret (wechat_secret)/test-wechat
Feishufeishu_enabled, feishu_notification_type (webhook or app), webhook URL/secret, or app ID/secret/test-feishu
Slackslack_enabled, slack_webhook_url/test-slack
Webhookwebhook_enabled, webhook_url, webhook_method (POST/GET), webhook_headers, webhook_body_template, webhook_secret/test-webhook

Send a test message before saving. Never put a signing secret in a URL query parameter — query strings end up in proxies, gateways, and browser history.

When a Webhook channel has webhook_secret configured, outgoing requests carry X-Webhook-Signature: sha256=<hex> and X-Webhook-Signature-256: <hex>, both HMAC-SHA256 over the raw request body. Receivers MUST verify against the unparsed, unmodified raw body using a constant-time comparison, otherwise verification fails or gives false positives.

webhook_body_template supports the placeholders {{title}}, {{content}}, and {{link_url}}. If a receiver rejects the payload, the delivery record moves to failed — but the in-app notification has already been created, so an external channel outage never loses the message.

Notification channel settings
Notification channel settings

Automatic Notifications

The Automatic Notifications page controls two things:

  • channels: which external channels participate in delivery (multi-select; selecting none keeps notifications in-app only)
  • enabled_types: which event types create a notification

Endpoints are GET / PUT /api/v1/admin/site-settings/auto-notifications; reading requires admin:settings:read, updating requires admin:settings:update. Submitting an unknown type is rejected (invalid_notification_type) rather than silently dropped.

There are 25 available types, of which 19 are enabled by default:

GroupTypeEnabled by default
Teamteam.member_added, team.member_removed, team.role_changed, team.ownership_transferred, team.model_granted, team.model_revokedyes
Useruser.activated, user.deactivated, user.password_reset, user.pending_approvalyes
Knowledge basekb.doc_indexed, kb.doc_failedyes
Workflowworkflow.run_failedyes
Workflowworkflow.pause_pendingyes
Workflowworkflow.run_successno
Agentagent.published, agent.unpublishedno
API keyapikey.expiring, apikey.expiredyes
Securitysecurity.login_anomaly, security.account_locked, security.password_changedyes
Password expirypassword.expiring, password.expiredno
Password expirypassword.force_changeno (no producing code)

Disabling a type drops the event permanently

If a type is not in enabled_types, the notification is never created when the event fires (the check happens before creation), and enabling it later cannot backfill the missed events. workflow.run_success is off by default on purpose — notifying on every successful run quickly drowns the notification center. Turn it on only if you genuinely need per-run confirmation.

Scheduled Checks

These automatic notifications are produced by Celery Beat, in the server timezone:

TaskTimeBehaviour
tasks.check_api_key_expirationDaily at 09:00Finds keys expiring within 7 days and reminds only at exactly 7, 3, and 1 day remaining (apikey.expiring); already-expired keys send apikey.expired
tasks.check_password_expirationDaily at 08:00Expired passwords send password.expired; inside the warning window (password_expiration_warning_days, default 7 days) it reminds only at 7, 3, and 1 day remaining (password.expiring)

The "remind only at 7/3/1 days" rule is deliberate de-duplication — without it the same user would be pinged every single day.

Login Anomaly Detection

Login anomaly notifications are not a rules engine; they compare against a stored login fingerprint:

  • Each user keeps the last 30 days of at most 10 IPs and 10 user agents (oldest entries are evicted).
  • Seeing an IP or user agent outside the known set flags the login and sends security.login_anomaly.
  • A first-ever login is never flagged (there is no history to compare against), so a brand-new account produces a clean first record.
  • The history lives in Redis; when Redis is unavailable the check is skipped rather than reporting a false anomaly.

A single proxy egress IP hides the real origin, and shared NAT egress makes "new IP" unreliable. High-security deployments should pair anomaly notifications with audit logs (login_success / login_failed) instead of relying on anomaly detection alone.

Delivery States

External delivery states are pending, sending, success, and failed. Failures record a retry count.

Do not rely on external channels alone. Confirm important security events in both the notification center and the audit log: the audit log is the authoritative persisted record, while an external channel can fail silently due to expired credentials or network problems.

Notification API

MethodPathDescriptionPermission
GET/api/v1/notificationsList visible notifications (scope/type/level/search/unread/time filters, paginated)Signed-in user
GET/api/v1/notifications/unread-countUnread countSigned-in user
POST/api/v1/notifications/readBulk mark read (notification_ids or mark_all)Signed-in user
GET / PUT/api/v1/admin/site-settings/auto-notificationsRead/update auto-notification configadmin:settings:read / admin:settings:update
GET/api/v1/admin/notificationsAdmin list of all notifications (includes per-channel deliveries)Signed-in user + admin scoping checks
POST/api/v1/admin/notificationsAdmin creates a notificationadmin:notification:create
DELETE/api/v1/admin/notifications/{id}Admin deletes a notificationadmin:notification:delete

The admin list adds scoping checks: a non-global-admin caller (has_global_admin_access false) cannot request scope=global (insufficient_privileges, 403) and must supply team_id (notification_scope_requires_team, 400) and pass that team's admin check. This is what stops a team admin from seeing or managing another team's notifications.

Administrator Notes

  • Users: check the notification center regularly; act on security notifications immediately and change the password when prompted.
  • Administrators: configure and successfully test a channel before selecting it in Automatic Notifications — selecting an unconfigured channel sends nothing and creates a false sense of coverage.
  • Choose enabled types deliberately: workflow.run_success and the agent.* events are high-volume and should be enabled only when truly needed.

See also:

How is this guide?

On this page