Notifications & alerts
Loca.fi has three ways to put a message in front of a user, and they build on each other:
- In-app notifications — the per-user "bell". A notification row a user sees when they next call the API, optionally mirrored to their email.
- Notification groups — reusable recipient lists (Loca.fi users plus free-text external email addresses) so you address a group instead of repeating a recipient list on every send.
- Domain-event alerts — rules that watch for a domain event (e.g. an item entering a place) and, when one matches, send to a notification group automatically. This is the closest thing Loca.fi has to webhooks — there is no outbound HTTP callback controller.
A fourth, more specialised mechanism — scheduled event monitoring
(EntityEventSchedule / EntityEventRecord) — runs time-based checks on a
CRON schedule and is covered briefly at the end.
Loca.fi does not push to third-party URLs. Integrations that need to react to
platform events either poll (getmynotifications, or the search/OData
endpoints) or receive email via a notification group. Alerts drive email;
they do not call out over HTTP.
Overview
| You want to… | Use |
|---|---|
| Tell one specific user something now | createnotification |
| Tell everyone on a list (users + external emails) | a notification group + notifygroup |
| React automatically when a domain event happens | a domain-event alert wired to a group |
| Read / clear the caller's own bell | getmynotifications, clearnotification |
The in-app notification endpoints (api/usernotifications/*) accept any
authenticated principal. Group, alert and schedule management are gated on
their module permission (NotificationGroup, Alert, EventSchedules
respectively — see the bitmask in Getting started).
Prerequisites
- A token — see Getting started. Remember the scheme is
Authorization: Token <jwt>, notBearer. - For the read/clear endpoints, a user token specifically. These operate on
the caller's own notifications, so an agent/device token (which has no
associated user) is rejected with
401rather than returning someone else's rows.
Step-by-step
1. Create a notification group
A group is a Name, an optional set of Loca.fi TargetUsers (by user id), and
an optional ExternalEmails string. External addresses may be separated by
either commas or semicolons — both are accepted everywhere a group's emails
are read.
curl -sk -X POST "http://<host>/api/notification-groups/create" \
-H "Authorization: Token $TOKEN" -H "Content-Type: application/json" \
-d '{
"Name": "Warehouse leads",
"ExternalEmails": "ops@example.com; supervisor@example.com",
"TargetUsers": ["<user-guid-1>", "<user-guid-2>"]
}'
Name is required — a create or update with a missing or empty Name
fails with 400 MissingRequiredField (field Name). Unknown user ids in
TargetUsers are skipped silently rather than failing the whole call, so
verify membership on the returned NotificationGroupSummaryDto.
Groups are scoped to your organisation. List them with
get-filtered
(OData) or, for a lightweight id/name pairing to populate a picker,
get-filtered-lookup-list.
delete refuses
(400 IllegalDeleteAttempt) if the group is still referenced by a scheduled
report or a domain-event alert. Detach those first.
2. Send a direct in-app notification
createnotification creates one
notification for one target user. The target must belong to your
organisation — a cross-org or unknown UserId is rejected with
400 InvalidReference (field UserId).
curl -sk -X POST "http://<host>/api/usernotifications/createnotification" \
-H "Authorization: Token $TOKEN" -H "Content-Type: application/json" \
-d '{
"Type": "Information",
"Subject": "Cycle count due",
"Body": "Zone A is scheduled for a count today.",
"UserId": "<target-user-guid>",
"NotifyByEmail": true
}'
Typeis aUserNotificationType(e.g.Information,Warning) — the valid values are listed on the Create notification request schema.NotifyByEmail: truealso emails the target their compiled message;falseleaves it in-app only.ReferenceType/ReferenceIdoptionally deep-link the notification to the entity it is about (an item, order, place, …). They are informational — the platform does not enforce that the reference resolves.
The response is the created UserNotificationDetailDto,
including the compiled email body.
3. Notify a whole group
notifygroup fans one message out
to every member of a group: one in-app notification per member who resolves to
a user in your organisation, plus an email to each external address (when
NotifyByEmail is set).
curl -sk -X POST "http://<host>/api/usernotifications/notifygroup" \
-H "Authorization: Token $TOKEN" -H "Content-Type: application/json" \
-d '{
"NotificationGroupId": "<group-guid>",
"Type": "Warning",
"Subject": "Stock discrepancy",
"Body": "Variance found during the last count.",
"NotifyByEmail": true
}'
Returns true once the fan-out completes.
Members are processed one at a time and the call reports success once the loop
finishes. Treat notifygroup as best-effort delivery, not a transaction — if
you need per-recipient confirmation, send with createnotification per user
and check each response.
4. Read and clear the bell
Each user reads their own notifications — there is no cross-user listing.
# Paged list (OData) of the caller's notifications
curl -sk "http://<host>/api/usernotifications/getmynotifications?%24top=20" \
-H "Authorization: Token $TOKEN"
# One notification's full detail
curl -sk "http://<host>/api/usernotifications/GetNotification/<id>" \
-H "Authorization: Token $TOKEN"
The list returns a PageResult of
UserNotificationSummaryDto; soft-cleared
rows are excluded.
Clearing (soft-delete) is available two ways — a DELETE (preferred) and a
legacy GET at the same route, kept for wire compatibility:
curl -sk -X DELETE "http://<host>/api/usernotifications/clearnotification/<id>" \
-H "Authorization: Token $TOKEN"
Clear several at once with
clearnotifications
(POST a ClearNotificationDto
{ "NotificationIds": [ ... ] }). Ids are processed one at a time with no
transaction: if an unknown id appears partway through, the ids before it are
already cleared even though the call overall returns 400 NotFound.
5. Automate with domain-event alerts
An alert turns a domain event into a group notification with no client polling. Build one against the metadata the platform exposes:
# Discover the alert types, trigger fields and notification methods available
curl -sk "http://<host>/api/domaineventalert/get-notification-meta-data" \
-H "Authorization: Token $TOKEN"
Then create the alert, pointing each notification at a group from step 1:
curl -sk -X POST "http://<host>/api/domaineventalert/createalert" \
-H "Authorization: Token $TOKEN" -H "Content-Type: application/json" \
-d '{
"AlertName": "Item left warehouse",
"AlertType": "<DomainEventAlertType>",
"AlertTriggerQuery": "<trigger expression>",
"IsEnabled": true,
"Notifications": [
{
"NotificationType": "Email",
"MessageFormat": "{item} moved to {place}",
"NotificationGroupId": "<group-guid>"
}
]
}'
AlertTypeis aDomainEventAlertType;NotificationTypeis aNotificationMethod. Useget-notification-meta-datato see the valid values and the fieldsAlertTriggerQuery/MessageFormatcan reference.IsEnabled: falsestores the alert without arming it — flip it later viaupdatealert.
Manage alerts with getfilteredalerts
(OData), getalert/{id} — which
returns 400 NotFound for an unknown id — and
DeleteAlert/{id}.
Scheduled event monitoring (advanced)
EntityEventSchedule / EntityEventRecord drive time-based checks rather
than reacting to a live event: an event type defines what to look for, a
schedule runs it on a CRON expression against a scope (organisation, place,
department or SKU), and a monitor tracks a running schedule. See the
EntityEventSchedules and
EntityEventRecords
reference pages. The four export endpoints accept both GET and POST. This
subsystem is primarily surfaced through the Loca.fi UI; most integrations only
need groups and alerts above.
Error handling
Standard error conventions apply — a
400 with a JSON array of { ErrorCode, Message, Field }, and note that on the
wire ErrorCode often collapses to InvalidOperation (read Message). The
cases specific to this domain:
| Situation | Response |
|---|---|
createnotification with a cross-org / unknown UserId | 400 InvalidReference (field UserId) |
Group create/update with empty Name | 400 MissingRequiredField (field Name) |
clearnotifications with NotificationIds: null | 400 MissingRequiredField (field NotificationIds) |
getalert / clear / an id-addressed action with an unknown id | 400 NotFound |
| Read/clear the bell with an agent/device token | 401 (no associated user) |
| Delete a group still used by a report or alert | 400 IllegalDeleteAttempt |
Related
- Concepts: Errors & conventions, Asynchronous operations.
- Reference: Create notification, Notify group, My notifications, Create group, Create alert, Alert metadata.