> ## Documentation Index
> Fetch the complete documentation index at: https://docs.cube.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Alerts

> Notify only when a number crosses a threshold, changes by a percentage, or falls outside its normal range, on a dashboard delivery or a scheduled task.

An alert is a condition on something that already runs on a schedule. Without
one, every run notifies; with one, each run checks a number first, and people
hear about it only when that number meets the condition you set — for example,
when the orders count goes above 1,000, when revenue drops by 10% or more from
the previous month, or when this week's sign-ups look unusual.

Two things can carry a condition, and both choose it the same way, with a
**How** choice of **Every time** or **Alert on condition**:

| Carrier | What it checks | What happens when the condition starts to hold |
| - | - | - |
| A [dashboard delivery][ref-deliveries] | A value on one chart or KPI of the published dashboard | The delivery's notification goes out. A dashboard delivery with a condition is called an **alert**. |
| A [scheduled task][ref-scheduled-tasks] | A measure of the data model | The agent runs the task's instructions and notifies its recipients. See [Conditional tasks][ref-conditional-tasks]. |

Both use the same [rules](#rule-types), the same words for them, and the same
[notify-once behaviour](#when-an-alert-notifies), and both offer the same two
actions to run them by hand: **Send now** and **Check condition** (see
[Sending now or checking the condition](#sending-now-or-checking-the-condition)).
This page describes alerts on dashboards in full; the
[Conditional tasks][ref-conditional-tasks] section of the Scheduled Tasks page
covers what is specific to tasks.

> [!NOTE]
>
> Alerts on dashboards are available wherever \[dashboard
> deliveries]\[ref-deliveries] are: on [Premium and Enterprise
> plans](https://cube.dev/pricing), for users with at least the
> \[Explorer]\[ref-roles] role and Edit or Manage permission on the workbook. A
> condition on a scheduled task takes the same permissions as the task itself.

## Rule types

A condition reads one number and compares it in one of three ways. The words
are the same on a dashboard delivery and on a scheduled task:

| Rule | Its options | Holds when |
| - | - | - |
| **is above or below** | **is above**, **is below**, **is equal to**, and a **Value** | The number compares with the value as the option says. |
| **changes by** | **increases by ≥**, **decreases by ≥**, **changes by ≥** (in either direction), and a **Percent** | The number moved by at least that percentage since the one it is compared with. |
| **is unusual** | None | The number falls outside the normal range of the earlier ones: their median ± 3 × the median absolute deviation. |

**is equal to** holds when the number equals the value to within one part in a
billion, so the rounding noise of a computed value doesn't stop it.

Wherever a condition is listed, it is summarized in the same words, for example
"Revenue is above 1,000 in the last complete month", "Revenue increases by ≥
10 % vs the previous month", or "Revenue is unusual for a month".

## Creating an alert on a dashboard

1. Open the [sidebar][ref-accessing] of a published dashboard and click
   **Create schedule**, or edit an existing schedule.
2. In the **Alert condition** card, set **How** to **Alert on condition**. The
   card shows its fields.
3. In **Chart**, pick the chart or KPI to watch. The list holds every chart and
   KPI widget on the published dashboard, including those inside grid, stack,
   and tabs containers. A chart that can't carry an alert is listed but
   disabled; hover it to see why (see
   [Which charts support which rule](#which-charts-support-which-rule)).
4. In **Measure**, pick the value to read. The chart's first measure is
   selected for you. **Measure** and **Condition** stay disabled until you pick
   a chart.
5. Under **Condition**, choose the [rule type](#rule-types) and fill in its
   fields.
6. Click **Add notification** and tick **Email** with recipients picked,
   **Slack** with at least one channel picked, or both. An alert needs someone
   to notify, so **Save** stays disabled until it has one.
7. Click **Save**. The dialog's title reads **Create alert**, and the toast
   "Alert created".

While something is missing, the dialog footer says what it is — for example,
"Enter the value to compare with." or "An alert needs a notification: add
recipients or a Slack channel."

On a dashboard with no charts, the card reads "This dashboard has no charts to
check." and the footer reads "This dashboard has no charts to check. Choose
“Every time” to save."

You can also create an alert from the [Refreshes, deliveries and
alerts][ref-all-schedules] tab of the **Scheduled** page. Its **Create
schedule** dialog shows the **How** choice from the start, disabled with "Select
a dashboard to add an alert condition." until you pick a **Dashboard**. After
that, it works as it does in the sidebar.

### From a chart's menu

To watch a particular chart, open that chart or KPI's menu (`⋮`) on the
published dashboard and choose **Create alert**. The **Create alert** dialog
opens with **How** already on **Alert on condition**, that chart in **Chart**,
and its first measure in **Measure**; continue from step 5 of the list above.
Everything outside the card starts as it does for **Create schedule** in the
sidebar. When you save, the dialog closes with "Alert created", and the new
alert is listed in the [sidebar][ref-accessing].

**Create alert** is offered only to people with Edit or Manage permission on the
workbook, and never on an [embedded dashboard][ref-embedding], published or in
[Creator Mode][ref-creator-mode]. On a plan without dashboard deliveries (see
the note at the top of this page), it is still listed, but pressing it opens
the **Dashboard deliveries** upgrade dialog instead of **Create alert**.

In the [dashboard builder][ref-workbooks], a chart's menu offers **Create
alert** too. An alert reads the published dashboard, so the item is enabled
only on a chart that is in the published version. On a chart added since the
last publish, or on every chart of a dashboard that has never been published,
it is disabled, and hovering it shows "Publish the dashboard to create an alert
on this chart." Once you publish, the item is enabled.

If the chart can't carry an alert — it is split by a dimension, or Cube can't
read its query — the dialog still opens on it, disables every rule type, shows
the reason under them, and keeps **Save** disabled with, for example, "This
chart has no single value to check. Choose another chart." Pick another chart
in **Chart** to continue.

## How a dashboard alert reads its chart

### is above or below

On a chart with a time dimension, the value is the last complete period's; on
a chart or KPI without one, its single value.

### changes by

On a chart with a time dimension, it compares the chart's last complete period
with the period before it, and the condition's summary names that period, for
example "vs the previous month". On a chart or KPI without one, it compares the
value read now with the value the previous check read, and the summary reads
"vs the previous check" (see
[Comparing with previous checks](#comparing-with-previous-checks)).

When the previous period's or previous check's value is 0 there is no
percentage to compute, so the check can't run and nothing is sent.

### is unusual

On a chart with a time dimension, the condition is met when the last complete
period falls outside the normal range of the periods before it. On a chart or
KPI without one, it is met when the value read now falls outside the normal
range of the values the alert read on its earlier checks. If every earlier
value is the same, the range is that value alone, and any other value is
outside it.

The rule needs at least 8 earlier values: complete periods before the latest
one, or earlier checks on a chart without a time dimension. Until it has them,
the check can't run and nothing is sent.

### Which charts support which rule

The dialog offers a chart and a rule type only where the chart has the value it
reads, and says why when it doesn't:

* A chart or KPI **without a time dimension** supports every rule type.
  **changes by** and **is unusual** compare its value with the values the alert
  read on its previous checks, and the dialog says so under the condition:
  "Compares with the values this alert read on its previous checks."
* A chart **split by a dimension** besides its time dimension — a bar chart by
  category, or a line chart with one line per status — has no single value to
  check, so it is disabled in the **Chart** list. Its tooltip says why, for
  example "“Orders by month and status” is split by Status, so it has no single
  value to check. Pick a KPI or a chart without a breakdown." A chart with
  several measures and no breakdown is fine: you pick one measure.
* A chart whose query Cube can't read, such as a Python analysis or a chart
  built from SQL, is disabled in the **Chart** list too.

If the chart an alert already watches can no longer carry one — for example, it
is now split by a dimension — **Edit** keeps that chart in **Chart**, disables
every rule type, and shows the reason under them.

## What a dashboard alert checks

**The data the notification shows.** The alert reads the chart with the
schedule's [control values][ref-control-values], and with the dashboard's
published default for every control the schedule leaves on **Use default** —
the same data the notification's screenshot shows. For example, if the
dashboard's Status filter defaults to completed orders and the schedule sets it
to **Clear**, the alert reads the orders of every status. The dialog, every
alert email, and every Slack message say so: "Checked with the dashboard's
default filters and this schedule's saved filters." If you republish the
dashboard or change a default, the next check uses the new version.

**The last complete period.** On a chart with a time dimension, every rule reads
the last *complete* period: the period still in progress, and any later periods
the data holds, are skipped. A monthly chart checked on September 15 reads
August. Periods follow the granularity the chart is drawn with, so a
[time granularity switcher][ref-time-granularity] that changes it changes the
period the alert reads. On a chart without a time dimension, the alert reads its
single value, and **changes by** and **is unusual** compare it with the values
the alert read on its previous checks.

**The owner's access.** The check runs once per run, with the data access of
the alert's owner, the person who created it.

## Comparing with previous checks

A chart or KPI without a time dimension has no earlier periods to compare with,
so a **changes by** or **is unusual** alert on it remembers the value it reads
on each check and compares the next value with those:

* **changes by** compares with the value the previous check read. The
  schedule's frequency sets what "previous" means: on a daily schedule, a check
  compares with yesterday's.
* **is unusual** compares with the normal range of the values the earlier
  checks read, once there are at least 8 of them.

The alert remembers the values of its last 30 checks. **is above or below**
alerts, and alerts on a chart with a time dimension, remember nothing.

The first check of a **changes by** alert has nothing to compare with: it
remembers its value and sends nothing. Its card reads "Last check: less than a
minute ago, could not check", and hovering the line shows "could not check.
There is no earlier check to compare with yet. Nothing sent." On an **is
unusual** alert's first check the hover reads "Needs 8 earlier checks, has 0.",
and each later check counts up until there are 8. Only the alert's owner sees
the count; anyone else reads "Needs 8 earlier checks."

**Check condition** is a check like any other: it compares with the remembered
values and adds its own, so the next scheduled run compares with it. Pressing it
twice gives the second press a previous check. **Send now** reads nothing and
remembers nothing.

A check remembers nothing when it can't read a number (for example, the chart
returned no rows or is now split by a dimension), or when it found the condition
met but its notification reached no one. The next check then compares with the
same earlier value.

The remembered values are kept when you change the schedule's frequency, time,
timezone, recipients, or Slack channels, and when you turn the schedule off and
on again. They are discarded, and the alert starts over from its first check,
when you change the alert's chart, measure, rule type, direction, or percentage,
or the schedule's [control values][ref-control-values]. Republishing the
dashboard keeps them, as long as the new version applies the schedule's [added
controls][ref-added-controls] as the previous one did: if you change the chart's
filters and republish, the next check compares the new value with the values
read before the change.

## When an alert notifies

An alert notifies when its condition **starts** to hold, and again only after it
has stopped holding and then starts again. While the condition keeps holding,
later runs send nothing, so a value that stays above its threshold for a week
sends one notification, not seven. There is no notification when the condition
stops holding. This is the same on a dashboard alert and on a
[conditional task][ref-conditional-tasks].

On a dashboard alert, a notification counts as sent when it reaches at least
one person or Slack channel. One that reaches no one — for example, when the
only recipient is a group with no members and every Slack post fails — doesn't
count: the next run that finds the condition met tries again.

The alert starts fresh — as if its condition had never held, with its card
back to "Last check: not run yet" — when you turn the schedule off, edit the
alert's condition, or change the schedule's
[control values][ref-control-values]: the next check notifies if the condition
holds on what it now reads. A republish that changes how the schedule's [added
controls][ref-added-controls] apply starts it fresh the same way, at the next
run, which notifies if the condition holds. Changing only the schedule's time
keeps the history. A check that can't run leaves the history as it was. Turning
the schedule off doesn't discard the values an alert on a chart without a time
dimension remembers (see
[Comparing with previous checks](#comparing-with-previous-checks)).

A run whose alert does not fire is a plain refresh: no screenshot is generated,
no [AI summary][ref-ai-summary] is written, and nothing is sent.

## Sending now or checking the condition

Both carriers of a condition offer two actions, on the sidebar card and the
list's row menu of a dashboard alert, and on the page and the list's row menu
of a conditional task:

* **Send now** sends to everyone now, without checking the condition. On a
  dashboard alert, it sends the dashboard as a plain dashboard delivery would,
  without the alert's findings; on a task, it runs the agent and notifies the
  task's recipients. Either way, the condition's state and **Last check** stay
  as they were.
* **Check condition** checks the condition now, exactly as a scheduled run
  would, and notifies only if the condition starts to hold. Pressing it twice
  while the condition holds notifies once. Its result shows in the **Last
  check**; after it, leave the sidebar or the task page open: the result
  appears by itself, with no reload. A run can take a few minutes.

**Run now** takes the place of **Send now** on something that notifies nobody:
a [refresh][ref-deliveries], or a scheduled task that notifies no one. Like
**Send now**, it runs without checking any condition.

## The notification

A fired alert sends the schedule's usual notification — the dashboard link and
screenshot, and the [AI summary][ref-ai-summary] if it is turned on — led by
what the alert found:

* **Email** — the subject is `Alert: <chart> on <dashboard>`. The message names
  the condition, the chart, and the value read: the period it read, plus the
  previous period and the change for **changes by**, or the normal range for
  **is unusual**. On a chart without a time dimension, it names the previous
  check's time and value instead of the previous period, or the normal range of
  the earlier checks, and adds "Compared with the values this alert read on its
  previous checks."
* **Slack** — every picked channel gets a message that opens with the same
  `Alert: <chart> on <dashboard>` line, followed by what the alert read, for
  example "Count increased by 2.5% from 157 in 2026-08 to 161 in 2026-09 (alert
  at 1% or more)." On a chart without a time dimension it reads, for example,
  "Count decreased by 50%: it was 20,003, from 40,000 at the previous check
  (2026-10-17 04:56 UTC) (alert at 10% or more)." and adds the same sentence as
  the email.

Both state that the check used the dashboard's default filters and the
schedule's saved filters, and that you will be notified again only after the
condition stops holding.

> [!NOTE]
>
> Because the check runs with the owner's access, the values it read appear only
> in the owner's email and in the Slack messages. Every other email recipient
> gets the condition and the chart, a note that the values are not shown because
> the check ran with the owner's access, and a screenshot of the dashboard with
> their own access.

## Following an alert in the sidebar

In the sidebar, an alert carries an **Alert** badge beside its schedule and a
summary of its rule, for example "Condition: Count is above 1,000 · Orders
count". A **changes by** rule ends with the period it compares, for example "vs
the previous month", or "vs the previous check" on a chart without a time
dimension, and an **is unusual** rule on such a chart reads, for example,
"Count is unusual vs its earlier checks". On the [Refreshes, deliveries and
alerts][ref-all-schedules] tab, the same summary, without "Condition:", fills
the **Condition** column.

The card's last line shows the last check. Before the first one it reads "Last
check: not run yet"; afterwards it says how long ago the check ran, what it
read, and what came of it, for example "Last check: 3 minutes ago, Count
increased by 2.7%, notified". What it read depends on the rule:

* **is above or below** — the value, for example "Count was 20,003".
* **changes by** — the change, for example "Count increased by 2.7%" or "Count
  decreased by 4%".
* **is unusual** — "Count outside its normal range" or "Count within its normal
  range".

What came of it is one of these:

| Outcome | Meaning |
| - | - |
| notified | The condition started to hold and the notification was sent. |
| still met, not notified again | The condition was already holding at the previous check. |
| met, nothing sent | The condition started to hold, but the notification reached no one. |
| not met | Nothing was sent. |
| could not check | The check couldn't run. Nothing was sent. |

How long ago is given in its largest unit, as for the next run: "less than a
minute ago", "3 minutes ago", "1 hour ago", or "2 days ago".

Hovering the line shows it whole and, under it, the whole check: when it ran, in
your timezone and naming it, the value it read, and, for **changes by**, the
previous period and the change, for example "Last check Oct 17, 2026, 3:08 AM
GMT+1: Count 339 (2026-09). Previous: 330 (2026-08), +2.7%. Condition not met."
For **is unusual**, it names the normal range, for example "Normal range: 8 –
14." On a chart without a time dimension, it names the previous check instead,
for example "Count 20,003. Previous check Oct 19, 2026, 3:04 PM GMT+1: 40,000,
-50%.", or "Normal range of the earlier checks: 8 – 14." For a check that
couldn't run, it says why. The **Last check** column of the [Refreshes,
deliveries and alerts][ref-all-schedules] tab shows the same line, without
"Last check:", and the same text on hover.

The values are shown only to the alert's owner. Anyone else sees how long ago
the check ran and what came of it, for example "Last check: 1 minute ago, still
met, not notified again", and on hover "values not shown, as it ran with the
access of the delivery's owner."

### When a check can't run

A check that can't run sends nothing and doesn't change whether the alert
counts as holding. On a chart without a time dimension, it still remembers the
value it read, if it read one. Hovering the last-check line shows why, for
example:

* The chart is no longer on the dashboard, or the measure is no longer in its
  query.
* The chart is now split by a dimension.
* The chart returned no rows, or there is no complete period yet.
* An **is unusual** rule has too few complete periods, or a **changes by**
  rule's previous period was 0.
* On a chart without a time dimension, a **changes by** rule has no earlier
  check yet or its previous check read 0, or an **is unusual** rule has fewer
  than 8 earlier checks.

When the chart or measure is gone, **Edit** shows the alert with the missing
field flagged, for example "Count is no longer in “Orders by month”. Pick
another measure."

## Editing, duplicating, and deleting

Edit an alert to change or remove its condition: set **How** to **Every time**
and save to make it a plain dashboard delivery again. [Duplicating a
schedule][ref-duplicate] copies its condition, and deleting a schedule deletes
its condition.

If alerts are turned off for your account, schedules keep their conditions but
send nothing while they do. Editing such a schedule shows only the **Alert
condition** switch in place of the **How** choice; turn it off and save to
remove the condition. When alerts are turned back on, they resume where they
left off.

## Managing alerts from chat

You can also ask the agent in [Analytics Chat][ref-chat] to add, change, or
remove a dashboard's alert, or to list the alerts on a dashboard, in plain
language — for example, *"email me when the Orders KPI on the Sales dashboard
drops 10% from one check to the next, every day at 9"* or *"what alerts are on
the Sales dashboard?"* The agent never makes an alert on a chart of a published
dashboard into a [scheduled task][ref-scheduled-tasks] with a condition: the
alert belongs to a dashboard delivery of that dashboard. See [Managing
schedules from chat][ref-chat-schedules].

## Managing alerts through the API

The [Platform API][ref-api-update] sets an alert through a notification's
`alert` field. An alert needs notifications switched on and at least one
recipient, so create the notification, add its recipients, and then update it
with `alert`. Setting `alert` to `null` removes the alert and keeps the
notification.

[ref-accessing]: https://docs.cube.dev/docs/explore-analyze/dashboard-deliveries.md#accessing-scheduled-refreshes

[ref-ai-summary]: https://docs.cube.dev/docs/explore-analyze/dashboard-deliveries.md#ai-summary

[ref-api-update]: https://docs.cube.dev/api-reference/notifications/update-a-scheduled-notification.md

[ref-chat]: https://docs.cube.dev/docs/explore-analyze/analytics-chat.md

[ref-chat-schedules]: https://docs.cube.dev/docs/explore-analyze/dashboard-deliveries.md#managing-schedules-from-chat

[ref-all-schedules]: https://docs.cube.dev/docs/explore-analyze/dashboard-deliveries.md#viewing-all-scheduled-refreshes

[ref-conditional-tasks]: https://docs.cube.dev/docs/explore-analyze/scheduled-tasks.md#conditional-tasks

[ref-control-values]: https://docs.cube.dev/docs/explore-analyze/dashboard-deliveries.md#control-values

[ref-added-controls]: https://docs.cube.dev/docs/explore-analyze/dashboard-deliveries.md#added-controls

[ref-creator-mode]: https://docs.cube.dev/embedding/iframe/creator-mode.md

[ref-deliveries]: https://docs.cube.dev/docs/explore-analyze/dashboard-deliveries.md

[ref-duplicate]: https://docs.cube.dev/docs/explore-analyze/dashboard-deliveries.md#duplicating-a-schedule

[ref-embedding]: https://docs.cube.dev/embedding/iframe/dashboards.md

[ref-roles]: https://docs.cube.dev/admin/users-and-permissions/roles-and-permissions.md

[ref-scheduled-tasks]: https://docs.cube.dev/docs/explore-analyze/scheduled-tasks.md

[ref-time-granularity]: https://docs.cube.dev/docs/explore-analyze/dashboards/widgets/controls.md#time-granularity-switcher

[ref-workbooks]: https://docs.cube.dev/docs/explore-analyze/workbooks


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.