Skip to main content

Anomaly detection — reading usage & delivery anomalies across Insights

Orbit runs automatic detectors against your own account traffic that flag behaviour deviating from its normal pattern — a spend spike, a toll-fraud attempt, a SIM-swap on your verification traffic, an API key calling home from an unexpected country. Every detection lands in a single append-only ledger. This guide shows you where anomalies surface across Insights, how to read the ledger, and what to do about what you find. If you are looking for the rule-authoring workflow instead (threshold and anomaly rules you define yourself), see Usage & delivery anomaly alert rules. This page covers the platform’s own detectors — which fire with no configuration at all.

What gets observed

Every detection creates one ledger entry with a category, a severity, a status, and a scope. It is classified into one of two scopes:
  • Wallet — anomalies on the spend-bearing channels: SMS, WhatsApp, email, RCS, voice, AI agents, or an “all channels” roll-up. This is your money-side scope. An alert here means usage or spend on a paid channel behaved abnormally.
  • Webhook — anomalies tied to inbound traffic and webhook delivery: phone numbers, webhook endpoint delivery. Inbound anomalies rarely cost you money directly; they signal probing or abuse pointed at your numbers.
The detector categories you will see in the ledger: Severity ranks low → medium → high → critical: high and critical demand same-day action; everything else queues for review. The ledger is read-only automatic detection. Entries are still acknowledged and triaged from the Fraud alerts card on your Insights overview; Usage & delivery anomaly alert rules is where you add your own threshold-and-anomaly rules on top (delivery rate, outbound volume, spend) with notifications you control.

Surfaces consuming anomaly detection

Four places in the dashboard read anomaly detection:
  1. Insights → Usage anomalies (/insights/anomalies) — the forensics surface this guide walks through: per-scope totals, a per-day trendline, and the raw ledger table.
  2. Insights → overview Fraud alerts card (/insights) — your live open alerts with the acknowledge/triage controls. This is where an anomaly gets worked; the anomalies page is where it gets read.
  3. Insights → Usage alert rules and KPI Alerts — the self-serve layer. Rules you author post their breach notifications to the Notification Center, not into the detector ledger.
  4. Fired-alert deep links — when one of your alert rules fires, its notification deep-links into the Insights page, so the detour from notification to the ledger view is one click.
All three ledger endpoints are tenant-scoped and return the standard { "data": ..., "meta": ... } envelope: All three accept a days window (default 30, maximum 365) or an explicit from/to ISO datetime pair, plus scope=wallet|webhook; /history additionally takes limit.

Reading the Usage anomalies page

Open Insights → Usage anomalies. Three components answer three questions, in this order:
  1. The summary stripis anything wrong right now? Per scope (wallet, webhook) you get the window total, the open count, the high-or-critical count, and the latest detection timestamp, plus the all-scopes total. Start here: a healthy account shows zero open and zero high/critical in both scopes.
  2. The per-day trendlineis this a blip or a pattern? The chart stacks wallet against webhook per UTC day. A single tall spike with empty days either side is usually one campaign or one attack burst; a rising staircase is a sustained shift — misconfiguration or ongoing abuse.
  3. The ledger tablewhich entries exactly? Every detection, newest first, with category, severity, status, scope, channel, and detection time, paged at up to 100 rows per request. Entries carry only scrubbed fields a tenant should see — provider-internal payloads never render.
Scope the whole page with the wallet / webhook filter, and widen the window with days or from/to when you need more than the default 30 days.

Worked example: a spend spike end to end

A runtime monitoring pulse goes off overnight. Here is the operator pass, top to bottom:
  1. Summary strip: wallet scope shows total: 6, open: 2, high_or_critical: 1; webhook scope is flat at zero. The problem is on a spend-bearing channel, not inbound.
  2. Trendline: wallet buckets hold at 0–1 per day for three weeks, then jump to 6 on a single day. A burst, not a drift — something happened on that day.
  3. Ledger table: the day’s entries read Spend spike (severity high, channel sms) and Toll-fraud (IRSF) blocked (severity critical). The toll-fraud detector already blocked the worst of it; the spend-spike entry quantifies what got through before the block engaged.
  4. Act on it in place: switch to the Insights → overview Fraud alerts card to acknowledge the critical entry so the rest of the team sees it is being handled.
  5. Prevent the repeat: open Insights → Usage alert rules and add a threshold rule — for example spend, comparator: gt, threshold: 100, window_days: 1, with in-app notification — so the next overnight spike pages the team at $100 instead of after the fact.

API usage

Same pass over the API — wallet scope, last 7 days:
Then the trendline and the rows behind it:
If truncated is non-null, the window held more ledger rows than the bounded scan reads — narrow the window or page /history instead of relying on the by-scope totals for that window.

Scopes and access

  • Ledger endpoints require an API key or JWT with the analytics read scope — the same posture as the other Insights read surfaces.
  • The Insights → Usage anomalies page is open to any member who can read Insights; risk and spend visibility should not be gated to finance roles.
  • Acknowledge / dismiss / resolve actions from the Fraud alerts card follow your team’s compliance permissioning, as on the anti-fraud surfaces.

Troubleshooting

The page is empty but you expected alerts. Widen the window above the default 30 days, and clear the scope filter back to all scopes. Detectors only write an entry when behaviour actually deviates — a quiet ledger on a healthy account is the correct state, not a broken one. A category you do not recognize appears. Categories ship ahead of their labels occasionally; the ledger falls back to a Title Case rendering of the detector name. The irsf_blocked and spend_velocity_anomaly categories have dedicated glossary explainers linked from the dashboard card (“Learn more”). By-scope total disagrees with your own count. You are counting a different window: by-scope and timeseries always resolve either days or an explicit from/to into UTC days. Pass the same window to /history and compare against data.total. An alert fired but nothing is in the ledger. Your own alert rules fire to the Notification Center — they are a separate system from the automatic detectors and never write to the anomaly ledger.

See also