Skip to content

Alerting

Tutorial for creating and managing alert rules on time series and meta-data.

Overview

In this article, you will learn how to set up alert rules on time series and meta-data on the aedifion.io platform. Currently, the aedifion.io platform supports three types of alert rules:

  • Threshold — on the observations for a datapoint
  • Throughput — on the observations received per time interval, for a datapoint or a whole project
  • Discrete — fires while a datapoint's value is one of a configured set of values

You will specify one of each and configure it to send out alert notifications via email or Microsoft Teams.

This article uses three terms precisely:

Term Meaning
Alert rule The configuration you create, update, enable, disable and delete through the API. It defines what is watched and when to alert.
Alert event A single occurrence: the rule's condition became true, or its severity level changed.
Alert notification The message an alert event produces, delivered by email, Microsoft Teams, or Telegram. Enabling the alarm dashboard additionally records the event in Alerta, aedifion's internal alarm dashboard — that is not a customer-facing channel.

Severity levels appear under two spellings: the API field names are info, warn and crit, and this article calls them info, warning and critical in prose. They are the same three levels throughout.

Preliminaries

The examples provided in this article partly build on each other. For the sake of brevity, boiler plate code such as imports or variable definitions is only shown once and left out in subsequent examples.

To execute the examples provided in this tutorial, the following is needed:

  • A valid login (username and password) to the aedifion.io platform. If you do not have a login yet, please contact us regarding a demo login. The login used in the example will not work!
  • A project with live data ingress.
  • Optionally, a working installation of Python or Curl.

Replace the API host in every example

The examples use https://<your-api-host> as a placeholder. Substitute the API URL of the aedifion deployment your project lives on — the examples will not work as copied. If you do not know your deployment's API URL, please contact us.

Types of alert rules

The aedifion.io platform supports three versatile types of alert rules:

  • Threshold alert rules are defined on single datapoints and raise an alert event whenever the measured values for that datapoint exceed (or fall below) a certain threshold. Up to three severity levels are supported: info, warning, and critical. You configure only the levels you actually need — a single critical threshold is a perfectly valid alert rule and is often all you want. Each configured level can optionally have a separate reset threshold to implement hysteresis and prevent flapping. A typical use case for threshold alert rules is notifying about unwanted system conditions such as high CO2 concentration in offices.
  • Throughput alert rules are defined on single datapoints or whole projects and raise an alert event whenever the measured throughput for that datapoint or project crosses certain thresholds. Throughput is measured as the number of values received per period, where period is a configurable time window (e.g., the number of values received every 10 minutes). Up to three severity levels (info, warning, critical) indicate the severity of abnormal throughput. A typical use case for throughput alert rules is fault detection by monitoring of the operational health of the building automation systems, e.g., alerting about the unscheduled shut-down of a critical component or notifying when a sensor is dead.
  • Discrete alert rules are defined on single datapoints and fire while the datapoint's value is one of a configured set of values (or, when negated, while it is not). Use them for enumerated signals — status words, operating modes, or fault codes — where the interesting values are not a contiguous range and therefore cannot be expressed as thresholds. A single value is the binary/equality case, e.g., alerting while a fault flag reads 1. Discrete alert rules fire at exactly one severity level and have no reset value: membership is exact, so the alert event clears as soon as the value leaves the set.

Comparing the alert rule types

The three types share most of their configuration and differ mainly in what defines the alert condition.

Threshold Throughput Discrete
Endpoint POST /v2/alert/threshold POST /v2/alert/throughput POST /v2/alert/discrete
Watches A datapoint's values Values received per period, on a datapoint or the whole project A datapoint's values
Fires when The value crosses a threshold The count per period crosses a threshold The value is in a set of values
dataPointID Required Optional — omit to measure the whole project Required
Condition is defined by thresholds thresholds (as values per period) values (1–50 numbers)
Severity levels Up to three: info, warn, crit Up to three: info, warn, crit Exactly one, chosen with level
thresholds.order asc / desc; inferred from two or more levels, required for a single one Same as threshold Not applicable
Reset thresholds Optional *_reset per level (hysteresis) Optional *_reset per level None — clears when the value leaves the set
period — Required —
delay (debounce) Optional Not supported — tune period instead Optional
negate — — Optional; fires while the value is not in the set
repeat default 1h 1d 1h

All three additionally accept name, description, timezone, disabled, notification and attributes, which behave identically across types. repeat is accepted by all three too, but its default differs per type — see the row above.

A threshold or discrete rule cannot detect a datapoint that stops delivering

Both evaluate incoming values, so when a datapoint goes quiet they simply stop evaluating and stay silent — no alert event, no notification. Silence therefore does not mean the monitored value is healthy. To be told that a datapoint or project has stopped delivering, add a throughput rule; that is exactly what it is for.

Further types of alert rules will be added in future. If you have a special request, please contact us.

Adding alert rules

Each alert rule type is created through its own endpoint. The parameters that specify the alert rule must be encoded as a JSON object and sent in the body of the request.

Unknown fields are rejected

The create and update endpoints reject request bodies that contain fields the alert rule does not define. A misspelled field (e.g. periods instead of period) results in HTTP 400 instead of being silently ignored.

Adding a threshold alert rule

A new threshold alert rule is created through the POST /v2/alert/threshold endpoint. The project_id is passed as a query parameter.

Threshold alert rules are defined through the following parameters.

Parameter Datatype Type Required Description Example
name string body (JSON) yes The name of the new alert rule. Must be unique within the project scope. CO2_Office100
description string body (JSON) no Free text description of the alert rule. Alert on indoor CO2 level
dataPointID string body (JSON) yes The alphanumeric id of the datapoint on which to alert. bacnet100-4120-CO2
thresholds.info float body (JSON) no* The threshold at which the info severity level is triggered. 600
thresholds.info_reset float body (JSON) no The threshold at which the info level is reset. Defaults to the value of info. 500
thresholds.warn float body (JSON) no* The threshold at which the warning severity level is triggered. 1000
thresholds.warn_reset float body (JSON) no The threshold at which the warning level is reset. Defaults to the value of warn. 900
thresholds.crit float body (JSON) no* The threshold at which the critical severity level is triggered. 2500
thresholds.crit_reset float body (JSON) no The threshold at which the critical level is reset. Defaults to the value of crit. 2000
thresholds.order string body (JSON) no† Alert direction, asc or desc. Inferred from the values when two or more levels are configured; required when only one level is configured. asc
repeat string body (JSON) no Minimum interval after which an unchanged alert is re-notified, in addition to notifying on every level change (w = weeks, d = days, h = hours, m = minutes, s = seconds). Use never (or 0s) to notify only on level changes. Defaults to 1h. 2h
delay string body (JSON) no Debounce. The threshold condition must hold continuously for this duration before the alert fires; if it clears sooner, nothing is sent. Omit to fire as soon as the condition is met. 5m
timezone string body (JSON) no IANA timezone used to render the timestamps in notifications. Defaults to the project's building timezone, falling back to UTC. Europe/Berlin
disabled boolean body (JSON) no Create the alert rule in a paused state — it does not fire until it is enabled. Defaults to false. false
notification.email.recipients list of strings body (JSON) no Email addresses to which notifications are sent when the rule fires. ["john.doe@aedifion.com"]
notification.ms_teams.webhook_urls list of strings body (JSON) no Microsoft Teams incoming webhook URLs to which notifications are sent. Each must be a valid https:// URL and must not contain commas, quotes, or backslashes. Each URL is itself the credential for its channel. ["https://..."]
notification.telegram.chat_ids list of strings body (JSON) no Telegram chat IDs where notifications are sent (must be chats that involve @aedifion_bot). ["-219643311"]
notification.dashboard.enabled boolean body (JSON) no Whether to show alert events on the alarm dashboard. Defaults to false. false
attributes object body (JSON) no Key-value tags to assign to the alert rule for categorization. Shown in notifications and in the rule; they cannot be filtered on when listing. {"category": "comfort", "team": "Operations"}

* At least one of thresholds.info, thresholds.warn, and thresholds.crit must be provided. Levels you omit are not evaluated and never notify — see single-threshold alert rules below. † Required exactly when a single level is configured.

Threshold order decides in which direction the alert gets more critical:

  • asc — the rule fires when values rise to or above a level. With three levels, that means info < warn < crit.
  • desc — the rule fires when values fall to or below a level. With three levels, that means info > warn > crit.

asc and desc refer to the order of the configured threshold values, and therefore to the direction in which the alert becomes more critical.

When you configure two or more levels, the order is inferred from the values and you may omit thresholds.order. Supplying it anyway is allowed, but it is rejected with HTTP 400 if it contradicts the values. Configured levels must be strictly monotonic in the order info, warn, crit — a set that is neither consistently rising nor consistently falling is rejected with HTTP 400. The same check runs on every PATCH, against the merged result: a patch that lifts crit below warn is rejected with HTTP 400 and nothing is changed.

Reset thresholds implement hysteresis. For example, with an ascending rule, a critical alert event is raised when observations reach or exceed thresholds.crit and resets only when they fall below thresholds.crit_reset. This prevents the rule from rapidly toggling on and off when values hover around a threshold. If you do not need hysteresis, simply omit the reset values — they will default to the trigger values.

The reset value always sits on the less critical side of its trigger: below it for asc, above it for desc. The descending throughput example further down follows this rule — it triggers critical at 0 values per period and resets at 2. A reset on the wrong side of its trigger is rejected with HTTP 400 rather than silently misbehaving.

Delay suppresses short-lived excursions. With "delay": "5m", a sensor that briefly spikes over the threshold and recovers within five minutes never produces a notification — the condition has to hold continuously for the whole duration first. This is the tool of choice for noisy or flapping signals; reset thresholds handle the opposite problem of values hovering right at the boundary.

Let's add a threshold alert rule on CO2 concentration and see what happens.

from requests import post, get, patch, delete

project_id = 4
api_url = 'https://<your-api-host>'
auth_john = ("john.doe@aedifion.com", "mys3cr3tp4ssw0rd")
newalert = {
    "name": "CO2_Office100",
    "description": "Alert on indoor CO2 level with three severity levels.",
    "dataPointID": "bacnet100-4120-CO2",
    "thresholds": {
        "info": 600,
        "info_reset": 500,
        "warn": 1000,
        "warn_reset": 900,
        "crit": 2500,
        "crit_reset": 2000
    },
    "repeat": "2h",
    "notification": {
        "email": {
            "recipients": ["john.doe@aedifion.com"]
        },
        "ms_teams": {
            "webhook_urls": ["https://example.webhook.office.com/webhookb2/..."]
        },
        "dashboard": {
            "enabled": False
        }
    },
    "attributes": {
        "category": "comfort",
        "team": "Operations"
    }
}

r = post(f"{api_url}/v2/alert/threshold",
         auth=auth_john,
         params={"project_id": project_id},
         json=newalert)

print(r.status_code, r.text)
curl "https://<your-api-host>/v2/alert/threshold?project_id=4"
    -X POST
    -u john.doe@aedifion.com:mys3cr3tp4ssw0rd
    -H 'Content-Type: application/json'
    -d '{
          "name": "CO2_Office100",
          "description": "Alert on indoor CO2 level with three severity levels.",
          "dataPointID": "bacnet100-4120-CO2",
          "thresholds": {
              "info": 600,
              "info_reset": 500,
              "warn": 1000,
              "warn_reset": 900,
              "crit": 2500,
              "crit_reset": 2000
          },
          "repeat": "2h",
          "notification": {
              "email": {
                  "recipients": ["john.doe@aedifion.com"]
              },
              "ms_teams": {
                  "webhook_urls": ["https://example.webhook.office.com/webhookb2/..."]
              },
              "dashboard": {
                  "enabled": false
              }
          },
          "attributes": {
              "category": "comfort",
              "team": "Operations"
          }
        }'
  1. Point your browser to https:///ui/.
  2. Click "Authorize" on the upper right and provide your login.
  3. From the main tags, select the Alert tag, then the POST /v2/alert/threshold endpoint (green).
  4. Enter the project_id in the query parameter field.
  5. Enter the following JSON example in the new_alert body field:
    {
      "name": "CO2_Office100",
      "description": "Alert on indoor CO2 level with three severity levels.",
      "dataPointID": "bacnet100-4120-CO2",
      "thresholds": {
          "info": 600,
          "info_reset": 500,
          "warn": 1000,
          "warn_reset": 900,
          "crit": 2500,
          "crit_reset": 2000
      },
      "repeat": "2h",
      "notification": {
          "email": {
              "recipients": ["john.doe@aedifion.com"]
          },
          "ms_teams": {
              "webhook_urls": ["https://example.webhook.office.com/webhookb2/..."]
          },
          "dashboard": {
              "enabled": false
          }
      },
      "attributes": {
          "category": "comfort",
          "team": "Operations"
      }
    }
    
  6. Click "Try it out!".
  7. Inspect the response body and code.

The JSON-formatted response (HTTP 201) confirms that the alert rule was successfully created and returns its details:

{
  "id": 6,
  "name": "CO2_Office100",
  "description": "Alert on indoor CO2 level with three severity levels.",
  "alert_type": "threshold",
  "project_id": 4,
  "status": "Enabled",
  "created": "2024-01-15T10:30:00.000000Z",
  "updated": "2024-01-15T10:30:00.000000Z",
  "dataPointID": "bacnet100-4120-CO2",
  "threshold_info": 600,
  "threshold_info_reset": 500,
  "threshold_warn": 1000,
  "threshold_warn_reset": 900,
  "threshold_crit": 2500,
  "threshold_crit_reset": 2000,
  "threshold_order": "asc",
  "repeat": "2h",
  "timezone": "Europe/Berlin",
  "email": "john.doe@aedifion.com",
  "telegram_chatid": "",
  "teams_webhook": "https://example.webhook.office.com/webhookb2/...",
  "alarm_dashboard": false,
  "attributes": {"category": "comfort", "team": "Operations"}
}

Note that the alert rule has received a unique numeric id (6) and has been enabled immediately. The repeat value you provided during creation is returned in the repeat field. Threshold alert rules have no measurement period — that field is only present on throughput rules. The timezone is always returned, even when you did not set it, so you can see which timezone the notification timestamps are rendered in.

Response format differs from request

The response uses a flat structure while the request uses nested objects. Specifically:

  • thresholds.info, thresholds.warn, thresholds.crit (and their _reset variants) become flat fields threshold_info, threshold_warn, threshold_crit, etc.
  • thresholds.order becomes threshold_order.
  • notification.email.recipients (a list) becomes a single email string with recipients joined by commas.
  • notification.ms_teams.webhook_urls (a list) becomes a single teams_webhook string with URLs joined by commas.
  • notification.telegram.chat_ids (a list) becomes a single telegram_chatid string with IDs joined by commas.
  • notification.dashboard.enabled becomes alarm_dashboard.

Numeric and duration fields that are not set are omitted from the response rather than returned as null. An alert rule with only a critical threshold therefore has no threshold_info or threshold_warn field at all, and one without a debounce has no delay field.

The string-valued fields behave differently: email, telegram_chatid, teams_webhook, dataPointID and attributes are always present, and come back as an empty string when unset. That is why the examples below show "dataPointID": "" for a project-wide throughput rule and "attributes": "" when no tags were assigned.

You may already receive alert notifications or try to provoke some by gathering a few people in your office or by directly breathing into the CO2 sensor. But first, we will look at simpler single-threshold alert rules and then add a rule of the second type, i.e., throughput. Later, we will also look at how to test your alert rules by deliberately setting low thresholds.

Single-threshold alert rules

You rarely need all three severity levels. If you only care about one condition, configure just that level — the rule then sends a single notification per alert event instead of up to three.

Because a single value cannot tell the platform whether the rule should fire above or below it, you must state the direction explicitly via thresholds.order:

newalert = {
    "name": "CO2_Office100_critical_only",
    "description": "Notify once when indoor CO2 becomes critical.",
    "dataPointID": "bacnet100-4120-CO2",
    "thresholds": {
        "crit": 2500,
        "crit_reset": 2000,
        "order": "asc"
    },
    "delay": "5m",
    "repeat": "never",
    "notification": {
        "email": {
            "recipients": ["john.doe@aedifion.com"]
        }
    }
}

r = post(f"{api_url}/v2/alert/threshold",
         auth=auth_john,
         params={"project_id": project_id},
         json=newalert)

print(r.status_code, r.text)
curl "https://<your-api-host>/v2/alert/threshold?project_id=4"
    -X POST
    -u john.doe@aedifion.com:mys3cr3tp4ssw0rd
    -H 'Content-Type: application/json'
    -d '{
          "name": "CO2_Office100_critical_only",
          "description": "Notify once when indoor CO2 becomes critical.",
          "dataPointID": "bacnet100-4120-CO2",
          "thresholds": {
              "crit": 2500,
              "crit_reset": 2000,
              "order": "asc"
          },
          "delay": "5m",
          "repeat": "never",
          "notification": {
              "email": {
                  "recipients": ["john.doe@aedifion.com"]
              }
          }
        }'

This rule fires only once CO2 has stayed at or above 2500 ppm for five uninterrupted minutes, notifies a single time, and stays quiet until the level actually changes again — because "repeat": "never" disables re-notification. It clears when CO2 falls below 2000 ppm.

The response contains only the configured level; threshold_info, threshold_warn and their resets are absent:

{
  "id": 8,
  "name": "CO2_Office100_critical_only",
  "description": "Notify once when indoor CO2 becomes critical.",
  "alert_type": "threshold",
  "project_id": 4,
  "status": "Enabled",
  "created": "2024-01-15T10:40:00.000000Z",
  "updated": "2024-01-15T10:40:00.000000Z",
  "dataPointID": "bacnet100-4120-CO2",
  "threshold_crit": 2500,
  "threshold_crit_reset": 2000,
  "threshold_order": "asc",
  "repeat": "never",
  "delay": "5m",
  "timezone": "Europe/Berlin",
  "email": "john.doe@aedifion.com",
  "telegram_chatid": "",
  "teams_webhook": "",
  "alarm_dashboard": false,
  "attributes": ""
}

A descending threshold rule

The examples so far all alert on a value getting too high. The opposite case — a value falling too low — is just as common in building operation: a flow temperature that drops away from its setpoint, or a pressure that decays.

Set "order": "desc" and let the thresholds fall as severity rises. Note that each reset sits above its trigger, the mirror image of the ascending case:

newalert = {
    "name": "Heating_flow_temperature_low",
    "description": "Flow temperature of the heating circuit dropping away from setpoint.",
    "dataPointID": "bacnet100-4120-HeatingCircuit-FlowTemp",
    "thresholds": {
        "info": 60,
        "info_reset": 62,
        "warn": 55,
        "warn_reset": 57,
        "crit": 50,
        "crit_reset": 52,
        "order": "desc"
    },
    "delay": "10m",
    "notification": {
        "email": {
            "recipients": ["john.doe@aedifion.com"]
        }
    }
}

r = post(f"{api_url}/v2/alert/threshold",
         auth=auth_john,
         params={"project_id": project_id},
         json=newalert)

print(r.status_code, r.text)
curl "https://<your-api-host>/v2/alert/threshold?project_id=4"
    -X POST
    -u john.doe@aedifion.com:mys3cr3tp4ssw0rd
    -H 'Content-Type: application/json'
    -d '{
          "name": "Heating_flow_temperature_low",
          "description": "Flow temperature of the heating circuit dropping away from setpoint.",
          "dataPointID": "bacnet100-4120-HeatingCircuit-FlowTemp",
          "thresholds": {
              "info": 60,
              "info_reset": 62,
              "warn": 55,
              "warn_reset": 57,
              "crit": 50,
              "crit_reset": 52,
              "order": "desc"
          },
          "delay": "10m",
          "notification": {
              "email": {
                  "recipients": ["john.doe@aedifion.com"]
              }
          }
        }'

The rule escalates as the temperature falls — info at 60 °C, warning at 55 °C, critical at 50 °C — and each level clears only once the temperature has recovered two degrees past its trigger. The ten-minute delay keeps a brief dip during a setpoint change from notifying anyone.

Creating a paused alert rule

Set "disabled": true on any of the create endpoints to create an alert rule in a paused state. It is stored with all its settings but never fires until you enable it.

newalert = {
    "name": "CO2_Office100_draft",
    "dataPointID": "bacnet100-4120-CO2",
    "thresholds": {"crit": 2500, "order": "asc"},
    "disabled": True,
    "notification": {"email": {"recipients": ["john.doe@aedifion.com"]}}
}

r = post(f"{api_url}/v2/alert/threshold",
         auth=auth_john,
         params={"project_id": project_id},
         json=newalert)

print(r.status_code, r.text)
curl "https://<your-api-host>/v2/alert/threshold?project_id=4"
    -X POST
    -u john.doe@aedifion.com:mys3cr3tp4ssw0rd
    -H 'Content-Type: application/json'
    -d '{
          "name": "CO2_Office100_draft",
          "dataPointID": "bacnet100-4120-CO2",
          "thresholds": {"crit": 2500, "order": "asc"},
          "disabled": true,
          "notification": {"email": {"recipients": ["john.doe@aedifion.com"]}}
        }'

The alert rule is returned with "status": "Disabled". This is the recommended way to set up an alert rule whose recipients or thresholds you still want to verify — unlike creating it and disabling it afterwards, the rule never runs in between.

Adding a throughput alert rule

A new throughput alert rule is created through the POST /v2/alert/throughput endpoint. The project_id is passed as a query parameter.

Throughput alert rules are defined through the following parameters.

Parameter Datatype Type Required Description Example
name string body (JSON) yes The name of the new alert rule. Must be unique within the project scope. EON_ERC_Throughput
description string body (JSON) no Free text description of the alert rule. Alert on project data ingress
dataPointID string body (JSON) no The alphanumeric id of the datapoint on which to measure throughput. If not provided, throughput of the whole project is measured. bacnet100-4120-CO2
thresholds.info float body (JSON) no* First threshold at which throughput is considered slightly abnormal (values per period). 50
thresholds.info_reset float body (JSON) no Threshold at which the info level is reset. Defaults to the value of info. 60
thresholds.warn float body (JSON) no* Second threshold at which throughput is considered significantly abnormal (values per period). 20
thresholds.warn_reset float body (JSON) no Threshold at which the warning level is reset. Defaults to the value of warn. 25
thresholds.crit float body (JSON) no* Third threshold at which throughput is considered critically abnormal (values per period). 0
thresholds.crit_reset float body (JSON) no Threshold at which the critical level is reset. Defaults to the value of crit. 2
thresholds.order string body (JSON) no† Alert direction, asc or desc. Inferred from the values when two or more levels are configured; required when only one level is configured. desc
period string body (JSON) yes Measurement window: the time over which received values are counted (w = weeks, d = days, h = hours, m = minutes, s = seconds). Not to be confused with repeat below, which controls re-notification. 10m
repeat string body (JSON) no Minimum interval after which an unchanged alert is re-notified, in addition to notifying on every level change. Use never (or 0s) to notify only on level changes. Defaults to 1d. 1d
timezone string body (JSON) no IANA timezone used to render the timestamps in notifications. Defaults to the project's building timezone, falling back to UTC. Europe/Berlin
disabled boolean body (JSON) no Create the alert rule in a paused state — it does not fire until it is enabled. Defaults to false. false
notification.email.recipients list of strings body (JSON) no Email addresses to which notifications are sent. ["john.doe@aedifion.com"]
notification.ms_teams.webhook_urls list of strings body (JSON) no Microsoft Teams incoming webhook URLs to which notifications are sent. Each must be a valid https:// URL and must not contain commas, quotes, or backslashes. ["https://..."]
notification.telegram.chat_ids list of strings body (JSON) no Telegram chat IDs where notifications are sent. ["-219643311"]
notification.dashboard.enabled boolean body (JSON) no Whether to show alert events on the alarm dashboard. Defaults to false. false
attributes object body (JSON) no Key-value tags to assign to the alert rule. Shown in notifications and in the rule; they cannot be filtered on when listing. {"category": "network", "team": "IT"}

* At least one of thresholds.info, thresholds.warn, and thresholds.crit must be provided. † Required exactly when a single level is configured.

As with threshold alert rules, the threshold order is inferred as soon as two or more levels are configured:

  • If info < warn < crit, the rule gets more critical as throughput grows (ascending).
  • If info > warn > crit, the rule gets more critical as throughput drops (descending).

A single-level throughput alert rule — for example "notify me when this project stops delivering data at all" — needs thresholds.order set explicitly, exactly as for threshold alert rules.

No debounce for throughput alert rules

Throughput alert rules do not support the delay field. Their period already serves that purpose: a longer measurement period tolerates temporary drops in throughput, a shorter one reacts faster.

How period behaves, since it decides both what is measured and how quickly you hear about it:

  • It is the measurement window and the evaluation interval at once. Values are counted per window, and the rule is evaluated once per window — not continuously.
  • Windows are consecutive and aligned, not rolling. A window is assessed only when it ends, so detecting a datapoint that has gone quiet takes up to one full period.
  • The first window after creating the rule is partial, because it starts mid-window. If the partial count falls under a threshold, that alone can raise an alert event which clears at the end of the next full window. Patching period restarts the windows and has the same effect.

Match period to how often the datapoint actually delivers

period must be long enough to contain the number of values your thresholds expect. A period of 10m on a datapoint that reports every 15 minutes counts zero or one value per window, so a rule with "crit": 0 or "warn": 20 sits permanently in alarm. As a rule of thumb, choose a period spanning several sampling intervals, and set thresholds from the count you actually observe over that window.

newalert = {
    "name": "EON_ERC_Throughput",
    "description": "Alert on project data ingress throughput.",
    "thresholds": {
        "info": 50,
        "info_reset": 60,
        "warn": 20,
        "warn_reset": 25,
        "crit": 0,
        "crit_reset": 2
    },
    "period": "10m",
    "repeat": "1d",
    "notification": {
        "email": {
            "recipients": ["john.doe@aedifion.com"]
        },
        "ms_teams": {
            "webhook_urls": ["https://example.webhook.office.com/webhookb2/..."]
        }
    }
}

r = post(f"{api_url}/v2/alert/throughput",
         auth=auth_john,
         params={"project_id": project_id},
         json=newalert)

print(r.status_code, r.text)
curl "https://<your-api-host>/v2/alert/throughput?project_id=4"
    -X POST
    -u john.doe@aedifion.com:mys3cr3tp4ssw0rd
    -H 'Content-Type: application/json'
    -d '{
          "name": "EON_ERC_Throughput",
          "description": "Alert on project data ingress throughput.",
          "thresholds": {
              "info": 50,
              "info_reset": 60,
              "warn": 20,
              "warn_reset": 25,
              "crit": 0,
              "crit_reset": 2
          },
          "period": "10m",
          "repeat": "1d",
          "notification": {
              "email": {
                  "recipients": ["john.doe@aedifion.com"]
              },
              "ms_teams": {
                  "webhook_urls": ["https://example.webhook.office.com/webhookb2/..."]
              }
          }
        }'
  1. Point your browser to https:///ui/.
  2. Click "Authorize" on the upper right and provide your login.
  3. From the main tags, select the Alert tag, then the POST /v2/alert/throughput endpoint (green).
  4. Enter the project_id in the query parameter field.
  5. Enter the following JSON example in the new_alert body field:
    {
      "name": "EON_ERC_Throughput",
      "description": "Alert on project data ingress throughput.",
      "thresholds": {
          "info": 50,
          "info_reset": 60,
          "warn": 20,
          "warn_reset": 25,
          "crit": 0,
          "crit_reset": 2
      },
      "period": "10m",
      "repeat": "1d",
      "notification": {
          "email": {
              "recipients": ["john.doe@aedifion.com"]
          },
          "ms_teams": {
              "webhook_urls": ["https://example.webhook.office.com/webhookb2/..."]
          }
      }
    }
    
  6. Click "Try it out!".
  7. Inspect the response body and code.

The response (HTTP 201) confirms the creation:

{
  "id": 7,
  "name": "EON_ERC_Throughput",
  "description": "Alert on project data ingress throughput.",
  "alert_type": "throughput",
  "project_id": 4,
  "status": "Enabled",
  "created": "2024-01-15T11:00:00.000000Z",
  "updated": "2024-01-15T11:00:00.000000Z",
  "dataPointID": "",
  "threshold_info": 50,
  "threshold_info_reset": 60,
  "threshold_warn": 20,
  "threshold_warn_reset": 25,
  "threshold_crit": 0,
  "threshold_crit_reset": 2,
  "threshold_order": "desc",
  "period": "10m",
  "repeat": "1d",
  "timezone": "Europe/Berlin",
  "email": "john.doe@aedifion.com",
  "telegram_chatid": "",
  "teams_webhook": "https://example.webhook.office.com/webhookb2/...",
  "alarm_dashboard": false,
  "attributes": ""
}

Since no dataPointID was provided, the throughput of the whole project is measured. Throughput alert rules are the only type that returns a period — it is the measurement window, and it is distinct from repeat, which controls how often an unchanged alert re-notifies.

Response format differs from request

As with threshold alert rules, the response uses a flat structure. See the note above for details on how nested request fields map to flat response fields.

Adding a discrete alert rule

A new discrete alert rule is created through the POST /v2/alert/discrete endpoint. The project_id is passed as a query parameter.

Discrete alert rules are defined through the following parameters.

Parameter Datatype Type Required Description Example
name string body (JSON) yes The name of the new alert rule. Must be unique within the project scope. Chiller_01_fault
description string body (JSON) no Free text description of the alert rule. Alert on chiller fault codes
dataPointID string body (JSON) yes The alphanumeric id of the datapoint whose values are checked. bacnet100-4120-Chiller01-Status
values list of floats body (JSON) yes The discrete values to alert on, e.g. the fault codes [2, 5, 7]. Between 1 and 50 unique values. [2, 5, 7]
level string body (JSON) no The single severity the rule fires at: info, warn, or crit. Defaults to crit. crit
negate boolean body (JSON) no Fire while the value is not one of values instead of while it is. Defaults to false. false
repeat string body (JSON) no Minimum interval after which an unchanged alert is re-notified. Use never (or 0s) to notify only on level changes. Defaults to 1h. 2h
delay string body (JSON) no Debounce. The value must stay in the set for this duration before the alert fires. Omit to fire as soon as the value enters the set. 5m
timezone string body (JSON) no IANA timezone used to render the timestamps in notifications. Defaults to the project's building timezone, falling back to UTC. Europe/Berlin
disabled boolean body (JSON) no Create the alert rule in a paused state — it does not fire until it is enabled. Defaults to false. false
notification.email.recipients list of strings body (JSON) no Email addresses to which notifications are sent. ["john.doe@aedifion.com"]
notification.ms_teams.webhook_urls list of strings body (JSON) no Microsoft Teams incoming webhook URLs to which notifications are sent. ["https://..."]
notification.telegram.chat_ids list of strings body (JSON) no Telegram chat IDs where notifications are sent. ["-219643311"]
notification.dashboard.enabled boolean body (JSON) no Whether to show alert events on the alarm dashboard. Defaults to false. false
attributes object body (JSON) no Key-value tags to assign to the alert rule. {"category": "fault", "team": "Operations"}

Discrete alert rules have no thresholds, no order, and no reset values. Membership in values is exact, so the alert event clears as soon as the value leaves the set.

Let's alert on a chiller that reports the fault codes 2, 5 and 7, while ignoring the informational codes 3, 4 and 6 — a condition that cannot be expressed with thresholds because the interesting values are not a contiguous range.

newalert = {
    "name": "Chiller_01_fault",
    "description": "Alert while the chiller reports one of the fault codes 2, 5 or 7.",
    "dataPointID": "bacnet100-4120-Chiller01-Status",
    "values": [2, 5, 7],
    "level": "crit",
    "negate": False,
    "delay": "5m",
    "notification": {
        "email": {
            "recipients": ["john.doe@aedifion.com"]
        }
    }
}

r = post(f"{api_url}/v2/alert/discrete",
         auth=auth_john,
         params={"project_id": project_id},
         json=newalert)

print(r.status_code, r.text)
curl "https://<your-api-host>/v2/alert/discrete?project_id=4"
    -X POST
    -u john.doe@aedifion.com:mys3cr3tp4ssw0rd
    -H 'Content-Type: application/json'
    -d '{
          "name": "Chiller_01_fault",
          "description": "Alert while the chiller reports one of the fault codes 2, 5 or 7.",
          "dataPointID": "bacnet100-4120-Chiller01-Status",
          "values": [2, 5, 7],
          "level": "crit",
          "negate": false,
          "delay": "5m",
          "notification": {
              "email": {
                  "recipients": ["john.doe@aedifion.com"]
              }
          }
        }'
  1. Point your browser to https:///ui/.
  2. Click "Authorize" on the upper right and provide your login.
  3. From the main tags, select the Alert tag, then the POST /v2/alert/discrete endpoint (green).
  4. Enter the project_id in the query parameter field.
  5. Enter the following JSON example in the new_alert body field:
    {
      "name": "Chiller_01_fault",
      "description": "Alert while the chiller reports one of the fault codes 2, 5 or 7.",
      "dataPointID": "bacnet100-4120-Chiller01-Status",
      "values": [2, 5, 7],
      "level": "crit",
      "negate": false,
      "delay": "5m",
      "notification": {
          "email": {
              "recipients": ["john.doe@aedifion.com"]
          }
      }
    }
    
  6. Click "Try it out!".
  7. Inspect the response body and code.

The response (HTTP 201) confirms the creation:

{
  "id": 9,
  "name": "Chiller_01_fault",
  "description": "Alert while the chiller reports one of the fault codes 2, 5 or 7.",
  "alert_type": "discrete",
  "project_id": 4,
  "status": "Enabled",
  "created": "2024-01-15T11:30:00.000000Z",
  "updated": "2024-01-15T11:30:00.000000Z",
  "dataPointID": "bacnet100-4120-Chiller01-Status",
  "values": [2, 5, 7],
  "level": "crit",
  "negate": false,
  "repeat": "1h",
  "delay": "5m",
  "timezone": "Europe/Berlin",
  "email": "john.doe@aedifion.com",
  "telegram_chatid": "",
  "teams_webhook": "",
  "alarm_dashboard": false,
  "attributes": ""
}

Set "negate": true to invert the condition — for example to alert while a pump status is anything other than the expected "running" code:

{
  "name": "Pump_01_not_running",
  "dataPointID": "bacnet100-4120-Pump01-Status",
  "values": [1],
  "negate": true,
  "level": "warn",
  "notification": {
    "email": {
      "recipients": ["john.doe@aedifion.com"]
    }
  }
}

A rule without a notification channel reaches nobody

notification is optional, and a rule created without it is accepted and runs — it evaluates, changes level, and records alert events, but delivers nothing to anyone. That is occasionally deliberate, for a rule that only feeds the alarm dashboard. If it is not deliberate, it is silent failure of the worst kind, so give every rule at least one channel.

Testing your alert rules

The CO2 alert rule we created first might have been set too defensively and not trigger unless there is a small party going on in your office. To provoke a threshold alert event and verify the rule works, you can create a rule with deliberately low thresholds that will trigger immediately — e.g. "thresholds": {"crit": 200, "order": "asc"} for a CO2 sensor that normally reads above 400 ppm. Remember that a single configured level needs an explicit order, otherwise the request is rejected with HTTP 400. You may also try to provoke some alert events by gathering a few people in your office or by directly breathing into the CO2 sensor. Alert notifications will soon arrive on the channels you configured.

Similarly, you can provoke a throughput alert event by setting very high thresholds, e.g., "crit": 20000, "warn": 50000 and "info": 100000.

Leave out the delay while testing

A delay postpones the first notification by its full duration, which makes a test look like a failure. Omit it until you have confirmed the rule fires, then add it back.

Controlling alert notifications

Every alert rule notifies whenever its severity level changes. Two settings control what happens in between, and both apply to all three alert rule types.

You are told when a condition clears

A notification is sent when the condition clears, not only when it starts. Each notification states which of these happened:

Trend Sent when
Fired The rule reached an alert level for the first time.
Increased The severity rose, e.g. warning → critical.
Decreased The severity fell, e.g. critical → warning.
Unchanged The level has not moved, and repeat elapsed.
Resolved The condition cleared and the rule is back to OK.

So an operator does not have to poll to find out whether a fault went away. repeat: "never" suppresses only the unchanged reminders — the level-change notifications, including the resolving one, are always delivered.

How often an alert repeats

repeat is the minimum interval after which an alert that has not changed level is notified again.

Value Behavior
A duration, e.g. 2h Re-notify every two hours for as long as the alert stays on the same level.
never (or 0s) Never re-notify. You are notified only when the level actually changes.
Omitted Defaults to 1h for threshold and discrete alert rules, 1d for throughput alert rules.

Use "repeat": "never" for one-shot alert rules — conditions you want to know about once, where a repeated reminder would only add noise.

What a notification looks like

An email notification carries the alert level, what triggered it, and where. For the CO2 rule created above, the critical notification reads:

Subject: Alert CO2_Office100 is CRITICAL

  CRITICAL
  Alert "CO2_Office100" fired on level CRITICAL.
  Alert on indoor CO2 level with three severity levels.

  Details
  Type             threshold
  Time             2024-01-15 14:32:05 (Europe/Berlin)
  Project          Office Building Munich
  Datapoint        bacnet100-4120-CO2
  Value            2571
  Condition        value >= 2500
  Delay            5m
  Level            CRITICAL
  Trend            Fired
  Previous level   WARNING
  category         comfort
  team             Operations

The Trend line is the one to read first — it distinguishes a new problem from an escalation, a de-escalation, a periodic reminder, or a resolved condition. When the condition clears you receive the same layout with Alert "CO2_Office100" is back to level OK.

Delay appears only when the rule sets one, Datapoint only when the rule watches a specific datapoint, and each attributes entry becomes its own line — which is what makes them useful for routing and triage by eye. Microsoft Teams and Telegram carry the same fields in their own formatting.

Which timezone timestamps use

Alert notifications render their timestamps in the alert rule's timezone. If you do not set it, the rule uses the project's building timezone and falls back to UTC when that is not configured. The effective value is always returned in the alert rule object, so you can verify which timezone a given rule reports in.

Set it explicitly with an IANA timezone name:

{"timezone": "Europe/Berlin"}

Retrieving a single alert rule

To read one alert rule by its id, call GET /v2/alert/{alert_id}. It returns the same alert rule object as the create, update, enable and disable endpoints — useful for resolving a deep link without paging through the whole list.

alert_id = 6
r = get(f"{api_url}/v2/alert/{alert_id}",
        auth=auth_john)
print(r.status_code, r.text)
curl "https://<your-api-host>/v2/alert/6"
    -X GET
    -u john.doe@aedifion.com:mys3cr3tp4ssw0rd
  1. Point your browser to https:///ui/.
  2. Click "Authorize" on the upper right and provide your login.
  3. From the main tags, select the Alert tag, then the GET /v2/alert/{alert_id} endpoint (blue).
  4. Provide the alert_id.
  5. Click "Try it out!".
  6. Inspect the response body and code.

The response (HTTP 200) is the alert rule object; an unknown id returns HTTP 404.

Listing alert rules

You can list all alert rules using the GET /v2/project/{project_id}/alerts endpoint. The response is paginated and supports filtering, searching, and sorting.

Parameter Datatype Type Required Description Default
project_id integer path yes The numeric id of the project. —
page integer query no Page number. 1
per_page integer query no Items per page (maximum 100). 20
search string query no Filter alert rules by name substring. —
filter string query no Filter by key=value pairs, separated by ;. Keys: alert_type, dataPointID, status. The status filter accepts enabled and disabled (case-insensitive). Filters with the same key are combined with OR, different keys with AND. —
sort_by string query no Sort by field: id, name, alert_type, created, updated, or status. id
sort_order string query no Sort order: asc or desc. asc
r = get(f"{api_url}/v2/project/{project_id}/alerts",
        auth=auth_john,
        params={"per_page": 50})
print(r.status_code, r.text)
curl "https://<your-api-host>/v2/project/4/alerts?per_page=50"
    -X GET
    -u john.doe@aedifion.com:mys3cr3tp4ssw0rd
  1. Point your browser to https:///ui/.
  2. Click "Authorize" on the upper right and provide your login.
  3. From the main tags, select the Project tag, then the GET /v2/project/{project_id}/alerts endpoint (blue).
  4. Provide the project_id and optionally set pagination/filter parameters.
  5. Click "Try it out!".
  6. Inspect the response body and code.

The response is a paginated object containing a list of alert rules and pagination metadata. Among them, we find the alert rules we defined previously. Note that the previously disabled rule has "status": "Disabled" because we paused it earlier.

{
  "items": [
    {
      "id": 6,
      "name": "CO2_Office100",
      "description": "Alert on indoor CO2 level with three severity levels.",
      "alert_type": "threshold",
      "project_id": 4,
      "status": "Disabled",
      "created": "2024-01-15T10:30:00.000000Z",
      "updated": "2024-01-15T10:35:00.000000Z",
      "dataPointID": "bacnet100-4120-CO2",
      "threshold_info": 600,
      "threshold_info_reset": 500,
      "threshold_warn": 1000,
      "threshold_warn_reset": 900,
      "threshold_crit": 2500,
      "threshold_crit_reset": 2000,
      "threshold_order": "asc",
      "repeat": "2h",
      "timezone": "Europe/Berlin",
      "email": "john.doe@aedifion.com",
      "telegram_chatid": "",
      "teams_webhook": "https://example.webhook.office.com/webhookb2/...",
      "alarm_dashboard": false,
      "attributes": {"category": "comfort", "team": "Operations"}
    },
    {
      "id": 7,
      "name": "EON_ERC_Throughput",
      "description": "Alert on project data ingress throughput.",
      "alert_type": "throughput",
      "project_id": 4,
      "status": "Enabled",
      "created": "2024-01-15T11:00:00.000000Z",
      "updated": "2024-01-15T11:00:00.000000Z",
      "dataPointID": "",
      "threshold_info": 50,
      "threshold_info_reset": 60,
      "threshold_warn": 20,
      "threshold_warn_reset": 25,
      "threshold_crit": 0,
      "threshold_crit_reset": 2,
      "threshold_order": "desc",
      "period": "10m",
      "repeat": "1d",
      "timezone": "Europe/Berlin",
      "email": "john.doe@aedifion.com",
      "telegram_chatid": "",
      "teams_webhook": "https://example.webhook.office.com/webhookb2/...",
      "alarm_dashboard": false,
      "attributes": ""
    }
  ],
  "meta": {
    "total_items": 2,
    "items_per_page": 50,
    "current_page": 1,
    "total_pages": 1
  }
}

Legacy alert rules

Alert rules created before February 2024 may have different field formats in the listing response:

  • threshold_ok and threshold_dead may be present with actual values.
  • attributes may be returned as a populated key=value; string (e.g. "category=comfort;team=Operations;") rather than an object. Note that a current rule with no tags also returns a string — an empty one — so only a non-empty string indicates a legacy rule.

Such rules also cannot be retrieved individually or updated — see Modifying alert rules.

You can also filter results, for example to show only threshold alert rules:

r = get(f"{api_url}/v2/project/{project_id}/alerts",
        auth=auth_john,
        params={"filter": "alert_type=threshold"})
print(r.text)
curl "https://<your-api-host>/v2/project/4/alerts?filter=alert_type%3Dthreshold"
    -X GET
    -u john.doe@aedifion.com:mys3cr3tp4ssw0rd

Filters on different keys are combined with AND, so this lists all currently paused throughput alert rules, most recently updated first:

r = get(f"{api_url}/v2/project/{project_id}/alerts",
        auth=auth_john,
        params={"filter": "alert_type=throughput;status=disabled",
                "sort_by": "updated",
                "sort_order": "desc"})
print(r.text)
curl "https://<your-api-host>/v2/project/4/alerts?filter=alert_type%3Dthroughput%3Bstatus%3Ddisabled&sort_by=updated&sort_order=desc"
    -X GET
    -u john.doe@aedifion.com:mys3cr3tp4ssw0rd

Modifying alert rules

Use PATCH /v2/alert/{alert_id} to change an existing alert rule in place. The rule keeps its id and its notification state — no delete-and-recreate needed.

Only the fields you send are changed; everything you omit keeps its current value. An empty payload is a no-op and returns the alert rule unchanged.

The following can be changed: name, description, thresholds (individual levels and resets), repeat, delay, timezone, notification, attributes, a throughput rule's period, and a discrete rule's values, level and negate.

Let's raise the critical threshold of our CO2 alert rule and add a recipient:

alert_id = 6
r = patch(f"{api_url}/v2/alert/{alert_id}",
          auth=auth_john,
          json={
              "thresholds": {"crit": 3000, "crit_reset": 2400},
              "notification": {
                  "email": {
                      "recipients": ["john.doe@aedifion.com", "jane.doe@aedifion.com"]
                  }
              }
          })
print(r.status_code, r.text)
curl "https://<your-api-host>/v2/alert/6"
    -X PATCH
    -u john.doe@aedifion.com:mys3cr3tp4ssw0rd
    -H 'Content-Type: application/json'
    -d '{
          "thresholds": {"crit": 3000, "crit_reset": 2400},
          "notification": {
              "email": {
                  "recipients": ["john.doe@aedifion.com", "jane.doe@aedifion.com"]
              }
          }
        }'
  1. Point your browser to https:///ui/.
  2. Click "Authorize" on the upper right and provide your login.
  3. From the main tags, select the Alert tag, then the PATCH /v2/alert/{alert_id} endpoint (orange).
  4. Provide the alert_id and the fields to update in the update_alert body field.
  5. Click "Try it out!".
  6. Inspect the response body and code.

The response (HTTP 200) is the complete updated alert rule.

How the merge works

Both at the top level and inside the nested objects (thresholds, notification, attributes):

  • A key you omit keeps its current value.
  • A key you provide is added or overwritten.
  • A key you set to null is removed.

Lists are replaced, never appended to. To add a recipient, send the complete list you want:

{"notification": {"email": {"recipients": ["john.doe@aedifion.com", "jane.doe@aedifion.com"]}}}

Sending only the new address would leave you with only that address.

Close to, but not exactly, RFC 7386

The delete-by-null semantics are those of JSON Merge Patch (RFC 7386), and lists are replaced wholesale just as that RFC prescribes. The merge is not recursive to arbitrary depth, though, so do not build an integration on the assumption of full RFC 7386 behaviour. Every object this API actually accepts is at most two levels deep, so the distinction has no practical effect on the payloads shown here.

Removing settings

Set a key to null to delete it. This works for notification channels, severity levels, attributes, and optional top-level fields such as description, repeat, delay and timezone:

{
  "notification": {"email": null},
  "thresholds": {"warn": null, "warn_reset": null},
  "attributes": {"team": null},
  "delay": null
}

Notes on removal:

  • Removing a trigger also drops its paired reset automatically, so {"thresholds": {"warn": null}} is enough — warn_reset will not be left orphaned.
  • At least one severity level must remain; a patch that removes them all is rejected with HTTP 400.
  • Setting repeat or timezone to null resets them to their defaults rather than leaving them unset.
  • An empty object ({}) is a no-op, not a clear — clearing requires an explicit null per key.

What cannot be changed via PATCH

Field Why What to do instead
dataPointID Defines which signal the rule watches. Delete and recreate the rule.
Alert rule type Threshold, throughput and discrete rules are separate resources. Delete and recreate the rule.
thresholds.order The alert direction is baked into the rule. Delete and recreate the rule.
status Enabling and disabling has its own endpoints. See enabling and disabling alert rules.

Fields that belong to another alert rule type are rejected with HTTP 400 — period on a threshold rule, delay on a throughput rule, or values/level/negate on anything but a discrete rule.

Alert rules created before February 2024

Alert rules that predate the current alert templates keep their definition only on the alerting backend, so it cannot be read back or merged. PATCH rejects them with HTTP 400, and GET /v2/alert/{alert_id} answers HTTP 404 — the same status as an unknown id, so the two cases are not distinguishable from the status code alone. They still appear in the listing, which is the reliable way to tell that the id exists. Delete and recreate them; the recreated rule supports the full feature set described here.

Changing the measurement period restarts a throughput alert rule

Patching a throughput rule's period re-binds it in place, which restarts the measurement window. The first window after the change is therefore partial.

Enabling and disabling alert rules

Since the rule might now be triggering notifications frequently, let's take a break and disable it. You can disable an alert rule to temporarily stop it from sending notifications, and enable it again later. There are two separate endpoints for this: POST /v2/alert/{alert_id}/disable and POST /v2/alert/{alert_id}/enable.

Disabling an alert rule

alert_id = 6
r = post(f"{api_url}/v2/alert/{alert_id}/disable",
         auth=auth_john)
print(r.status_code, r.text)
curl "https://<your-api-host>/v2/alert/6/disable"
    -X POST
    -u john.doe@aedifion.com:mys3cr3tp4ssw0rd
  1. Point your browser to https:///ui/.
  2. Click "Authorize" on the upper right and provide your login.
  3. From the main tags, select the Alert tag, then the POST /v2/alert/{alert_id}/disable endpoint.
  4. Provide the alert_id.
  5. Click "Try it out!".
  6. Inspect the response body and code.

The response (HTTP 200) returns the alert rule with its updated status:

{
  "id": 6,
  "name": "CO2_Office100",
  "description": "Alert on indoor CO2 level with three severity levels.",
  "alert_type": "threshold",
  "project_id": 4,
  "status": "Disabled",
  "created": "2024-01-15T10:30:00.000000Z",
  "updated": "2024-01-15T10:35:00.000000Z",
  "dataPointID": "bacnet100-4120-CO2",
  "threshold_info": 600,
  "threshold_info_reset": 500,
  "threshold_warn": 1000,
  "threshold_warn_reset": 900,
  "threshold_crit": 2500,
  "threshold_crit_reset": 2000,
  "threshold_order": "asc",
  "repeat": "2h",
  "timezone": "Europe/Berlin",
  "email": "john.doe@aedifion.com",
  "telegram_chatid": "",
  "teams_webhook": "https://example.webhook.office.com/webhookb2/...",
  "alarm_dashboard": false,
  "attributes": {"category": "comfort", "team": "Operations"}
}

Enabling an alert rule

To re-enable the rule, use the enable endpoint:

alert_id = 6
r = post(f"{api_url}/v2/alert/{alert_id}/enable",
         auth=auth_john)
print(r.status_code, r.text)
curl "https://<your-api-host>/v2/alert/6/enable"
    -X POST
    -u john.doe@aedifion.com:mys3cr3tp4ssw0rd
  1. Point your browser to https:///ui/.
  2. Click "Authorize" on the upper right and provide your login.
  3. From the main tags, select the Alert tag, then the POST /v2/alert/{alert_id}/enable endpoint.
  4. Provide the alert_id.
  5. Click "Try it out!".
  6. Inspect the response body and code.

The response (HTTP 200) returns the alert rule with "status": "Enabled".

Deleting alert rules

Deleting an alert rule is a simple matter of calling DELETE /v2/alert/{alert_id}. The response is HTTP 204 (No Content) with an empty body — per REST semantics, the 204 status itself is the confirmation that the alert rule was deleted. An unknown id returns HTTP 404.

Note that deleting is no longer necessary just to change an alert rule: use PATCH to update one in place, or disable it to stop notifications while keeping its configuration.

As an example, we now delete the threshold alert rule that we have previously created.

alert_id = 6
r = delete(f"{api_url}/v2/alert/{alert_id}",
           auth=auth_john)
print(r.status_code)
curl "https://<your-api-host>/v2/alert/6"
    -X DELETE
    -u john.doe@aedifion.com:mys3cr3tp4ssw0rd
  1. Point your browser to https:///ui/.
  2. Click "Authorize" on the upper right and provide your login.
  3. From the main tags, select the Alert tag, then the DELETE /v2/alert/{alert_id} endpoint (red).
  4. Provide the alert_id.
  5. Click "Try it out!".
  6. Inspect the response code (204 indicates success).

Go ahead and also delete the throughput alert rule, then call GET /v2/project/{project_id}/alerts to verify that both rules are gone.