Skip to main content

Notifications & alerts

Loca.fi has three ways to put a message in front of a user, and they build on each other:

  1. In-app notifications — the per-user "bell". A notification row a user sees when they next call the API, optionally mirrored to their email.
  2. 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.
  3. 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.

No webhooks

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 nowcreatenotification
Tell everyone on a list (users + external emails)a notification group + notifygroup
React automatically when a domain event happensa domain-event alert wired to a group
Read / clear the caller's own bellgetmynotifications, 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>, not Bearer.
  • 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 401 rather 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 is blocked while in use

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
}'
  • Type is a UserNotificationType (e.g. Information, Warning) — the valid values are listed on the Create notification request schema.
  • NotifyByEmail: true also emails the target their compiled message; false leaves it in-app only.
  • ReferenceType / ReferenceId optionally 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.

Best-effort fan-out

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>"
}
]
}'
  • AlertType is a DomainEventAlertType; NotificationType is a NotificationMethod. Use get-notification-meta-data to see the valid values and the fields AlertTriggerQuery / MessageFormat can reference.
  • IsEnabled: false stores the alert without arming it — flip it later via updatealert.

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:

SituationResponse
createnotification with a cross-org / unknown UserId400 InvalidReference (field UserId)
Group create/update with empty Name400 MissingRequiredField (field Name)
clearnotifications with NotificationIds: null400 MissingRequiredField (field NotificationIds)
getalert / clear / an id-addressed action with an unknown id400 NotFound
Read/clear the bell with an agent/device token401 (no associated user)
Delete a group still used by a report or alert400 IllegalDeleteAttempt