Anomalies
Anomalies are conditions detected on your resources, such as a device that stops sending data or a value outside its expected range. The platform records each anomaly with its severity over time and notifies the right people.
Overview
Anomaly management is built on three resources:
| Resource | Purpose |
|---|---|
| Anomaly configuration | A rule: what is checked, and the severity levels with their thresholds and notification channels |
| Anomaly subscription | Applies a configuration to a set of resources |
| Anomaly | An occurrence: when it started and ended, which resources are involved and how its severity evolved |
Anomalies are detected by the anomaly detection of the Apio products running on the platform, according to the configurations and subscriptions of the project. Your applications can also record anomalies of their own through the API.
Anomaly Configurations
A configuration describes a kind of anomaly and its severity levels:
{
"name": "No data received",
"description": "The device has not sent any measurement for longer than the threshold.",
"type": "Communication",
"category": "devices",
"subCategory": "Energy meter",
"code": "COM",
"enabled": true,
"checkContext": "<provided by Apio>",
"checkFunction": "<provided by Apio>",
"severity": [
{
"level": 2,
"operator": "gt",
"threshold": "3600",
"formattedThreshold": "1",
"uom": "h",
"via": ["websocket"]
},
{
"level": 4,
"operator": "gt",
"threshold": "86400",
"formattedThreshold": "24",
"uom": "h",
"via": ["email"]
}
]
}| Field | Description |
|---|---|
name, description (required) | Shown in notifications and user interfaces |
type, category, subCategory (required) | Classify the anomaly, for example Communication / devices / Energy meter |
code | Short code, typically 3–4 uppercase letters, used for example in email subjects. Defaults to the first three letters of category |
enabled | When false, the configuration is not evaluated. Defaults to true |
checkContext, checkFunction (required) | Identify the detection logic that evaluates the configuration. Their values are provided by Apio |
permissions | Additional permissions a user must have to be notified of these anomalies |
severity | The severity levels. See below |
Severity levels
Each configuration defines one or more severity levels, from 1 (lowest) to 5 (highest):
| Field | Description |
|---|---|
level | 1 to 5 |
threshold (required) | Threshold in the base unit of the quantity, for example seconds, W or Wh |
formattedThreshold (required) | The same threshold in the unit shown to users, set in uom |
uom | Unit of measurement of formattedThreshold |
operator | How the value is compared with the threshold: gt (default), gte, lt, lte, eq, ne |
alarm | once (default) or always |
after | With alarm: once, a delay before the anomaly is notified. Not allowed with always |
repeat | With alarm: always, a cron expression that defines when the notification is repeated. Required with always, not allowed with once |
via | Notification channels: email, websocket or both. Defaults to websocket for levels 1–3 and email for levels 4–5 |
Anomaly Subscriptions
A subscription applies a configuration to the resources it should watch, optionally with its own severity levels:
{
"name": "Energy meters of plant North",
"configurationId": "my-configuration-uuid",
"resources": [
"/devices/meter-1-uuid",
"/devices/meter-2-uuid"
],
"enabled": true
}Resources are referenced as /{resourceType}/{uuid}, for example /devices/…, /nodes/…, /plants/… or /assets/…. Set enabled to false to suspend a subscription without deleting it.
Anomalies
An anomaly records an occurrence of a configuration on one or more resources:
{
"uuid": "4b8f3c2e-1d7a-4f6b-9a51-2e0c7d9f8a10",
"projectId": "my-project-id",
"configurationId": "my-configuration-uuid",
"resources": ["/devices/meter-1-uuid"],
"startedAt": "2026-10-01T08:00:00.000Z",
"severity": [
{
"level": 2,
"startedAt": "2026-10-01T08:00:00.000Z",
"endedAt": "2026-10-01T09:00:00.000Z",
"duration": 3600000
},
{
"level": 4,
"startedAt": "2026-10-01T09:00:00.000Z"
}
],
"metadata": {}
}- startedAt, endedAt, duration: when the anomaly started and ended, and its duration in milliseconds. An anomaly without
endedAtis still open - resources: the resources involved, in the same
/{resourceType}/{uuid}form used by subscriptions - severity: the history of severity levels, each with its own start, end and duration. A severity without
endedAtis still active - metadata: free-form details added by the detection
When you read an anomaly, its configuration is included in the configuration field.
Reading anomalies
To get the name and type of the resources involved in an anomaly:
{
"status": true,
"data": [
{ "uuid": "meter-1-uuid", "name": "Meter 1", "type": "devices" }
]
}Closing an anomaly
Closing sets endedAt to the current time and computes duration. Every severity that is still active is closed at the same time.
Events
Anomalies generate events like other resources: apio.core.anomalies.created, apio.core.anomalies.updated and apio.core.anomalies.closed.
Notifications
When an anomaly is created, the platform notifies it for each active severity, on the channels set in via for that level in the configuration:
- email: sent to the users of the project who have the
apio.notifications.email.receivepermission - websocket: delivered in real time to the connected users who have the
apio.notifications.websocket.receivepermission
When the configuration lists additional permissions, only users who also have those permissions are notified. Notifications are grouped and sent at short intervals.
Anomalies that are already closed when they are created, or that have no resources, are not notified.
Email content can be customized per project, and per configuration, with templates. Contact Apio to set up custom templates.
Permissions
| Permission | Allows |
|---|---|
apio.core.anomalies.read / .write | Reading / creating, updating and deleting anomalies |
apio.core.anomalyConfigurations.read / .write | Reading / managing configurations |
apio.core.anomalySubscriptions.read / .write | Reading / managing subscriptions |
apio.notifications.email.receive | Receiving email notifications |
apio.notifications.websocket.receive | Receiving real-time notifications |