Notifications — technical overview
Central multi-channel notification gateway: templates, per-patient channel preferences, clinic settings, delivery logs, and a single POST /send entry point that resolves the channel per recipient.
Channels
- email — via clinic SMTP settings (
/smtp-settings, testable). - whatsapp — opt-out prefs (
whatsapp_opt_in_atconsent trail). - sms (roadmap #231 PR1) —
Channel.SMS; resolves topatients.phone(E.164, single source of truth — no separatesms_phonecolumn in v1). Text-only: no attachments. Opt-out like email/whatsapp: explicitsms_enabled=Falseblocks (evenforce_send); a missing prefs row means reachable.sms_opt_in_atmirrors the whatsapp consent trail. Per-clinic cost guard:sms_daily_limit(default 100/UTC day,0= blocked, skips and inbound rows don't consume). An exhausted cap behaves like an unreachable channel: withfallback_enabledthe next connected channel takes the send, and only when none is viable is the row skipped withsms_rate_limited. Email/whatsapp are uncapped flat-rate transports. Delivery itself arrives with thesms_gatewaymodule (pluggable providers); until then SMS resolves but has no transport backend.
API surface
DELETE /api/v1/notifications/templates/{template_id}GET /api/v1/notifications/logsGET /api/v1/notifications/preferences/patient/{patient_id}GET /api/v1/notifications/settingsGET /api/v1/notifications/smtp-settingsGET /api/v1/notifications/templatesGET /api/v1/notifications/templates/{template_id}POST /api/v1/notifications/sendPOST /api/v1/notifications/smtp-settings/testPOST /api/v1/notifications/templatesPOST /api/v1/notifications/testPUT /api/v1/notifications/preferences/patient/{patient_id}PUT /api/v1/notifications/settingsPUT /api/v1/notifications/smtp-settingsPUT /api/v1/notifications/templates/{template_id}
Frontend
backend/app/modules/notifications/frontend/pages/settings/notifications.vue→/settings/notifications
Permissions
templates.read, templates.write, preferences.read, preferences.write, logs.read, send, settings.read, settings.write
See ./permissions.md for the full role mapping.
Events
- Emits: (none)
- Subscribes:
appointment.cancelled,appointment.scheduled,budget.accepted,budget.sent,invoice.sent,patient.created
See ./events.md for the per-event detail (when the module participates in the event bus).
See also
- Module CLAUDE notes:
backend/app/modules/notifications/CLAUDE.md - Documentation portal contract