Skip to main content

Usage & delivery anomaly alert rules

Define org-scoped alert rules that watch the signals that move a CPaaS account: SMS delivery rate, outbound message volume, and spend. When the metric breaks your threshold — or deviates sharply from its own learned baseline — the rule fires an in-app notification the whole team sees in the dashboard’s Notification Center. Rules are read-only over your account. Evaluation aggregates your already-persisted message and billing-ledger rows; the only writes are alert-rule state and the notification it fires. No outbound traffic ever results from a rule. This complements In-dashboard notifications and the Notification Center (the surface rules notify on) and Per-API-key usage budgets and threshold alerts (a browser-local tripwire; everything on this page is org-scoped and shared with your team).

Create and manage rules in the dashboard

Everything the REST surface does is also available from the console at Insights → Usage alert rules (/insights/usage-alert-rules, linked from the Insights hub). Use the console for day-to-day rule management; keep the API for provisioning rules from your infrastructure scripts.

Open the page

From the dashboard sidebar, open Insights, then pick the Usage alert rules tile. The page has three panels: your rules table, the Fired alerts feed, and the create-rule dialog.

Create a rule from the dialog

Click Create rule (on an empty account the empty-state card carries the same button). The dialog asks for:
  • Name — up to 160 characters; the rule fires into the Notification Center titled Usage alert: <name>.
  • Metric — SMS delivery rate, Outbound message volume, or Spend (the same three metrics the API accepts).
  • Trigger — Threshold (compare a fixed bound) or Anomaly (deviate from the metric’s own learned baseline).
  • Condition + Threshold — shown only in Threshold mode: pick the comparator (is below, is at or below, is above, is at or above) and the numeric bound on the metric’s native unit.
  • Window (days) — 1–30, default 7. In Anomaly mode the help line reminds you the comparison is against a learned 28-day baseline.
  • Enabled — toggle the rule on at creation or leave it off as a draft.
Anomaly mode hides the condition/threshold inputs — pass a fixed bound versus baseline deviation, not both. When the metric is Spend in Threshold mode, a suggested throttle preset appears in the dialog: one click fills is above $50/day over a 1-day window, which you can edit before submitting. Notify channels are not a dialog choice — alerting goes through the in-app Notification Center, matching the notify_channels: ["in_app"] restriction the API documents below.

Read the rules table

The table shows one row per rule and mirrors the evaluator-state fields the GET /usage/alert-rules endpoint returns: Timestamps follow the API fields: last_evaluated_at is the last evaluation tick and last_fired_at is the last notification — query them with GET /usage/alert-rules when you need them.

Evaluate now and the fired-alerts feed

The Evaluate now button in the page header runs every enabled rule immediately — the same call as POST /usage/alert-rules/evaluate below — so a scheduled sweep cadence never delays your check. It is disabled while you have no rules. Below the rules table, the Fired alerts section renders the same feed GET /usage/alert-rules/events returns: each entry shows the rule name, the breach sentence (for example “SMS delivery rate is 82.4%, below the 95% threshold over the last 7d.”), the fire time, and a View metric link that follows the event’s deep link — currently the Insights page. The same payload lands in the dashboard Notification Center (the bell), with severity warning; triage, read, and dismiss semantics there are covered in In-dashboard notifications and the Notification Center.

Who can view, who can manage

The console page is open to every member whose key passes the usage:read scope — viewing rules and the fired feed is a read. Creating, toggling, deleting, and running Evaluate now call the write endpoints, which the API restricts to org roles owner, admin, or developer (see Auth requirements below). Recommend developer-or-higher for anyone owning managed rules.

Two worked console flows

(a) Alert me when daily SMS delivery rate drops below 97%. Create rule → Metric: SMS delivery rate → Trigger: Threshold → Condition: is below, Threshold 97 → Window 1 day. A 1-day window is the tightest the console enforces; widen it to 7 (the API example’s cadence below) when a single bad carrier hour should not page you. (b) Alert me when daily spend exceeds its learned baseline. Create rule → Metric: Spend → Trigger: Anomaly. No bound to set — the rule flags the newest complete UTC day when it deviates sharply upward from the learned 28-day baseline. (For a fixed bound instead, Threshold mode on Spend offers the $50/day suggested throttle preset.)

Endpoints

All endpoints share the standard { "data": ..., "meta": ... } envelope and are tenant-scoped. A tenant can hold up to 50 rules.

Auth requirements

  • Reads (GET ..., GET .../events) — a valid API key/JWT whose scopes include usage:read.
  • Writes and evaluate-now (POST, PATCH, DELETE, POST .../evaluate) — additionally require an org role of owner, admin, or developer. The audit log records create/update/delete with the acting user.

Rule shapes

Each rule targets one metric, using one of two modes.

Metrics

Delivery rate and volume are computed over your outbound messages with the same status filters the dashboard’s delivery KPI card uses, and spend is aggregated from wallet-ledger debits excluding admin adjustments — so an alert fires on exactly the numbers the dashboard shows.

Threshold mode (default)

Compares the metric’s value over a trailing window against a fixed number.
  • comparator: one of gt, gte, lt, lte
    • lt / lte — “must stay above X” (e.g. delivery rate below 95%)
    • gt / gte — “must stay below X” (e.g. volume above 10k/day, spend above $100)
  • threshold: a finite number on the metric’s native unit
  • window_days: the trailing window the threshold aggregates over, 1–30 (default 7)
A threshold rule cannot exist without both a comparator and a threshold — create and update both reject it (422).

Anomaly mode

Compares the newest complete UTC day against a learned 28-day baseline using a z-score classifier. You set no threshold — “unusual for your account” is the trigger. For delivery rate it detects a downward drop; for volume and spend, an upward spike (the metric on volume/spend rules is inverted internally so a spike registers the same way). Anomaly rules must not carry comparator/threshold at create time (they are ignored); pass only mode: "anomaly" plus window_days, cooldown_hours, notify_channels, enabled.

Field reference (create / update body)

notify_channels currently accepts only in_app. Alerts surface through the existing dashboard notification channel (the bell / Notification Center); email or webhook fan-out is not yet on this surface.

The fired event lifecycle

A scheduler-driven sweep continuously evaluates every tenant that has at least one rule, and POST /usage/alert-rules/evaluate runs the same evaluation on demand for your tenant. On every evaluation tick, each enabled rule updates its runtime fields (last_evaluated_at, last_status, last_value) — even in a breach. An event is appended to your fired-alert feed (max 50, newest first) and a notification pushed only when:
  • the rule’s status transitions into breached, or
  • it stays in breach and the cooldown_hours re-notify window (default 24h) has elapsed since the last notification.
While the rule stays in breach but inside the cooldown, state still updates but no new event/notification is emitted — the same signal does not re-page you for 24 hours. A metric that cannot be resolved (no data in the window, or a provisioning gap) is reported as insufficient_data and never fires a false alert.

Event payload

Each entry in GET /usage/alert-rules/events: Poll GET /usage/alert-rules/events to consume alerts from an API integration, or open the Notification Center in the dashboard.

Where alerts land in the dashboard

A firing rule reuses the in-app notification channel: it appears in the bell dropdown and the Notification Center with severity warning, titled Usage alert: <your rule name>, with the threshold/anomaly sentence as the body and a deep link to the Insights page. See In-dashboard notifications and the Notification Center for triage/read/dismiss semantics.

Example: delivery-failure-rate alert

Create a rule that fires when SMS delivery rate over the trailing week falls below 95%, and re-fires at most once a day while it stays breached:
Response (201):
Evaluate now (optional — the scheduler sweep also evaluates it on its own cadence):
Then read the fired feed:
A mode: “anomaly” variant — pick up when the newest day’s delivery rate deviates sharply from the learned 28-day baseline, without fixing a threshold:

Troubleshooting

422 says “comparator is required for a threshold rule”. Pass both comparator and threshold whenever the rule is threshold mode (create, and any update on a threshold rule; mode defaults to threshold). A rule’s last_status reads insufficient_data. The metric could not be resolved in the window — usually zero outbound messages (or wallet debits, for spend rules) in the window. Evaluation reports no value rather than firing on a fabricated 0%. The rule fires fewer notifications than expected. That is cooldown semantics: while a rule stays in breach, it re-notifies only once per cooldown_hours (default 24h, up to 720). Evaluation itself is either the scheduler sweep or a manual tick — the POST /usage/alert-rules/evaluate row in the Endpoints table above — during which a breach in cooldown updates the rules table’s status and current value without emitting another event. You want email or webhook instead of the dashboard notification. The only configured channel today is the dashboard notification (notify_channels: ["in_app"]). Poll the fired-event feed to integrate alerts into your own systems.