Notification System — Backend Documentation
Table of Contents
- Overview
- How It Works
- SMTP Rule
- Configuration
smtp_thresholdbatch_size
- Notification Types
- Request Body Fields
- Postman Examples
- 1. Send to a Single User (In-App Only)
- 2. Send to Multiple Specific Users
- 3. Send to a Single User + Email (SMTP)
- 4. Send to an Entire Role (e.g., All Students)
- 5. Send to Multiple Roles
- 6. Send to an Entire Company
- 7. Send to Multiple Companies
- 8. One Target per Request (No Combining)
- 9. Scheduled Notification (Future)
- 10. Scheduled + SMTP to a Single User
- 11. Each Notification Type — Quick Reference Payloads
- Other Notification Endpoints
- Architecture Summary
- Postman Setup Tips
- Common Error Responses
Overview
Boot list (19/10/2026):All notification sending goes through a single unified endpoint:GET /auth/userships only the 3 newest non-archived notifications (id,student_id,title,message,notification_type_id,notif_read_status,notif_archive_status,created_at) plusnotification_count(unread). The bell popup / notifications page load more withGET /notifications/user/{user_id}?per_page=10&page=1(see “Other Notification Endpoints”). It used to be the 10 newest rows with every column.
How It Works
- The request hits
NotificationController@sendUnified SendUnifiedNotificationRequestvalidates the payloadNotificationService::resolveRecipients()collects the target user IDs from the one target sent:user_ids,role_idsorcompany_ids(user_idsandrole_idsonly match users of the sender’s company)NotificationService::createDispatch()creates the dispatch record and individual notification rows in chunks ofbatch_size- If
scheduled_atis set and is in the future → aProcessNotificationDispatchjob is queued with a delay - Otherwise →
NotificationService::sendNow()fires immediately
SMTP Rule
The original guard blocks SMTP for role/company targets. The
smtp_threshold adds a second layer: even when targeting user_ids directly, if the resolved recipient count exceeds the threshold, SMTP is forced off and a warning is logged. This prevents accidental mass email blasts through the “allowed” path.
This is enforced in NotificationService::sendNow() — see the Configuration section below.
Configuration
Two runtime-tunable values are extracted intoconfig/notifications_config.php so they can be changed via environment variables without touching application code.
smtp_threshold
Default: 20
After resolveRecipients() produces the final user list, sendNow() checks the count. If it exceeds smtp_threshold, notif_smtp_status is forced to false — regardless of what was passed in the request — and a warning is logged.
batch_size
Default: 1000
When creating Notification rows in bulk, a single Notification::insert() on thousands of rows causes PHP memory exhaustion and can hit DB statement size limits. The full recipient list is split with array_chunk() and inserted in separate queries.
The defaults innotifications_config.phpare used when the.envkeys are absent — so existing deployments that haven’t set them will automatically behave as if they were set to20and1000respectively.
Notification Types
These are stored in thenotification_types table. Use the id value in notification_type_id:
Request Body Fields
*Exactly one ofuser_ids,role_idsorcompany_idsmust be a non-empty array; leave the others empty or out. Sending none, or two of them, is a422on thetargetkey (see example 8).
Postman Examples
1. Send to a Single User (In-App Only)
The simplest case — one user, no email, no scheduling.2. Send to Multiple Specific Users
3. Send to a Single User + Email (SMTP)
Setnotif_smtp_status to true. This only works when targeting user_ids (not roles/companies) and when the recipient count does not exceed smtp_threshold.
Make sure SMTP settings are configured via POST /api/platform/smtp-settings before testing this.
4. Send to an Entire Role (e.g., All Students)
Role IDs are fixed by the seeder and by theRole constants in the backend:
The app’s Reminders screen sends the same ids: All students →
1, All instructors → 2, All content creators → 3, All admins → 4. Its Everyone option is not a role: the app sends company_ids: [<your company>] instead (example 6).
notif_smtp_statusis forced to false here even if you passtrue.
5. Send to Multiple Roles
Notify all instructors and students at once:6. Send to an Entire Company
Every user in company ID 1:SMTP is also forced off for company-wide broadcasts.
7. Send to Multiple Companies
If you have a multi-tenant setup:8. One Target per Request (No Combining)
You can’t mix targets in one request. This body, sending to two users and the student role, is refused:"role_ids": [1], one with "user_ids": [7, 9] (the second one may also use notif_smtp_status).
9. Scheduled Notification (Future)
Send a reminder that gets delivered at a specific time:Thescheduled_atdatetime is parsed inAfrica/Tunistimezone. If the datetime is in the past, it sends immediately instead of scheduling.
10. Scheduled + SMTP to a Single User
11. Each Notification Type — Quick Reference Payloads
Danger (2):Other Notification Endpoints
These manage notifications after they’ve been sent.Mark as Read
Mark as Unread
Mark All as Read (per user)
Archive
Unarchive
Get Notifications by User
unread_count.
Get Notifications by Company
Get Notifications by Role
Get Single Notification
Delete Notification
Architecture Summary
Key Models
Key Files
Postman Setup Tips
- Environment variables — set
{{base_url}}(e.g.,http://localhost:8000/api) and{{token}} - Get a token — call
POST {{base_url}}/auth/loginfirst and grab the token from the response - Role IDs —
1Student,2Instructor,3Content Manager,4Admin,5Super Admin (SELECT * FROM roles;shows the same rows) - Check your users table — run
SELECT id, first_name, email, role_id FROM users;to get valid user IDs - SMTP testing — configure SMTP first via
POST /api/platform/smtp-settings, then test withPOST /api/platform/test-smtpbefore tryingnotif_smtp_status: true