1. Creating Alerts (Pro+ License)
Administrators with the alerts:create permission can create alerts via:
- The admin API: POST /api/admin/alerts
- Plugins with the alerts:create permission
Required Fields
| Field | Description |
|---|---|
| category | Alert category (e.g., "system", "deployment", "security") |
| severity | One of: critical, warning, info |
| targetType | One of: broadcast, role, user |
| title | Short notification title |
| message | Notification body text |
Optional Fields
| Field | Description |
|---|---|
| targetValue | Role names or user IDs (required for role and user targeting) |
| imageUrl | URL to an image to display with the alert |
| modalContent | Rich content for a modal view |
| actions | Array of action buttons: [{label, labelKey, url, style}]. An action's url must be a path in Depotex (such as /settings/plugins) or an https:// address; anything else is refused with a validation error |
| titleKey, messageKey | Message keys from the Depotex interface to show instead of title and message, in each user's language. title and message are still required: they are shown when a key isn't known and returned to API clients |
| params | Values for the placeholders in those messages: names mapped to text or numbers (up to 20) |
| metadata | Arbitrary JSON metadata |
| expiresAt | ISO 8601 timestamp after which the alert is hidden |
Example: Create a Broadcast Alert
curl -X POST /api/admin/alerts \
-H "Content-Type: application/json" \
-d '{
"category": "system",
"severity": "warning",
"targetType": "broadcast",
"title": "Scheduled Maintenance",
"message": "System will be down for maintenance at 02:00 UTC tonight.",
"actions": [{"label": "View Details", "url": "/maintenance/upcoming"}]
}'
Example: Target Specific Roles
curl -X POST /api/admin/alerts \
-H "Content-Type: application/json" \
-d '{
"category": "deployment",
"severity": "info",
"targetType": "role",
"targetValue": ["developer", "devops"],
"title": "New Release v2.1.0",
"message": "Version 2.1.0 has been deployed successfully."
}'
2. Forced Categories (Enterprise License)
Administrators with the alerts:admin permission can configure forced categories — categories that users cannot mute.
Managing Forced Categories
Access the Forced Categories panel in the admin settings. From there you can:
- View the current list of forced categories
- Add new categories (type the name and click "Add" or press Enter)
- Remove categories (click the X button)
- Save changes (click "Save Changes")
When to Use Forced Categories
Use forced categories for notifications that all users must receive regardless of their preferences:
- Security alerts
- Compliance notifications
- Critical system announcements
- Billing/payment issues
API
# Get current forced categories
GET /api/admin/alerts/config
# Update forced categories
PUT /api/admin/alerts/config
{
"forcedCategories": ["security", "compliance", "billing"]
}
3. Viewing All Alerts (Enterprise License)
Administrators with the alerts:admin permission can view all alerts system-wide:
GET /api/admin/alerts?category=system&severity=critical&limit=50
This returns all alerts regardless of targeting, with optional filtering by category, severity, and target type.
4. Scheduler Health Alerts
The system monitors background jobs. When a scheduled job fails several times in a row (3 by default, set with SCHEDULER_UNHEALTHY_THRESHOLD), super admins and organization admins get an alert, shown in each person's language:
- Job failing (critical) — "Job cleanup is failing", with the number of failures and the last error
- Job recovered (info) — when the job succeeds again
Both link to Settings → Advanced → Scheduled Jobs. They are built-in automation rules: super admins can change who gets them or switch them off under Settings → Automation. Each job has its own category ("Scheduled job: <name>"), so a job's recovery replaces its own failure alert and doesn't hide other jobs' alerts. Muting that category mutes that one job's health alerts.
Alerts that administrators and plugins write are shown exactly as written; they are not translated.
5. Backup Alerts
When a backup can't be written or fails its integrity check, super admins get a critical alert ("The scheduled backup failed its integrity check (checksum_mismatch). Open Settings → Backups for details."). See Backups.
6. Automatic Cleanup
Alerts are automatically cleaned up based on their state:
| State | Retention Period |
|---|---|
| Active (unread) | 30 days |
| Read | 7 days |
| Cleared | 1 day |
| Superseded | 3 days |
These defaults can be configured via environment variables. The cleanup job runs daily at 02:00 by default and can be managed from the Scheduler UI.
7. Audit Trail
All administrative alert actions are audit logged:
- Alert creation (who created it, what was the payload)
- Forced categories changes (before/after state)
Audit logs are accessible to Enterprise-tier administrators via the audit log viewer.
8. API Reference
User Endpoints
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/alerts?status= | List your alerts (paginated): your inbox, or status=unread or status=cleared |
| GET | /api/alerts/counts | How many are unread, in your inbox and cleared |
| POST | /api/alerts/{id}/read | Mark alert as read |
| POST | /api/alerts/{id}/unread | Mark alert as unread |
| POST | /api/alerts/{id}/restore | Put a cleared alert back in your inbox |
| POST | /api/alerts/read-all | Mark all as read |
| POST | /api/alerts/bulk | Mark several of your alerts read or unread, clear or restore them, in one request: {"ids": [1, 2], "action": "read"} (read, unread, clear or restore; up to 500 ids). Ids that aren't yours are skipped; the answer is {"updated": n}, how many changed |
| POST | /api/alerts/{id}/clear | Clear an alert |
| POST | /api/alerts/clear-all | Clear all alerts |
| GET | /api/alerts/preferences | Get your preferences |
| PUT | /api/alerts/preferences | Update your preferences |
Admin Endpoints
| Method | Endpoint | Permission | License |
|---|---|---|---|
| POST | /api/admin/alerts | alerts:create | Pro+ |
| GET | /api/admin/alerts | alerts:admin | Enterprise |
| GET | /api/admin/alerts/config | alerts:admin | Any |
| PUT | /api/admin/alerts/config | alerts:admin | Enterprise |
Pagination
All list endpoints use cursor-based pagination:
{
"data": [...],
"pagination": {
"nextCursor": "eyJ2Ijp...",
"prevCursor": "",
"hasNext": true,
"hasPrev": false,
"limit": 20
}
}
Pass ?cursor=<nextCursor>&limit=20 to fetch the next page.
Error Responses
| Status | Meaning |
|---|---|
| 400 | Invalid request (missing fields, bad cursor) |
| 401 | Not authenticated |
| 402 | Feature requires higher license tier |
| 403 | Missing required permission |
| 404 | Alert not found |
| 422 | Alert creation blocked by a hook |
Preferences Request Body
{
"optedOut": false,
"mutedCategories": ["marketing", "tips"]
}
If you include a forced category in mutedCategories, it will be automatically stripped from the list. The response shows your effective preferences after stripping.
9. WebSocket Connection
Connect to /api/ws for real-time notifications. Authentication uses your session cookie (same as REST API).
Message Format
All messages use a JSON envelope:
{
"type": "alert.new",
"payload": { ... },
"timestamp": "2026-06-01T10:00:00.123Z"
}
Message Types
| Type | Direction | Description |
|---|---|---|
| alert.init | Server → Client | Initial state on connect (alerts + count) |
| alert.new | Server → Client | New alert targeting you |
| alert.count | Server → Client | Updated unread count |
| alert.superseded | Server → Client | An alert was replaced |
Reconnection
If the WebSocket connection drops, the client automatically reconnects with exponential backoff (1s, 2s, 4s, ... up to 30s max). On reconnect, the server sends a fresh alert.init message to catch up on any missed notifications.