Usage anomalies console — reading the forensics dashboard
Insights → Usage anomalies (/insights/anomalies) is the forensics
surface over the platform’s anomaly ledger — the append-only record its own
detectors (spend spikes, toll-fraud blocks, SIM-swap flags, webhook-delivery
anomalies) write against your account traffic. This guide walks the
dashboard page itself: what each panel answers, how wallet scope differs
from webhook scope, how to read one ledger row, and when to leave the page
for the raw API.
If you want the endpoint-level request/response samples instead, see
Anomaly examples — worked API samples. For the
rule-authoring workflow (thresholds you define yourself, with notifications),
see Usage & delivery anomaly alert rules.
This page is read-only over the detector ledger — you configure nothing here.
What the page surfaces vs the API recipe
The page composes the three public ledger endpoints into one screen. Each panel answers a different triage question, in the order you should ask them:- The summary strip — is anything wrong right now? Four tiles from
GET /insights/anomaly-insights/by-scope: total detections in the window, open anomalies across both scopes, high/critical severity count, and the wallet-vs-webhook split. A healthy account reads zero open and zero high/critical. This is the checklist answer — the same question the by-scope endpoint answers for a poller, without writing a poller. - The per-day trendline — is this a blip or a pattern? From
GET /insights/anomaly-insights/timeseries, the chart stacks wallet against webhook per UTC day across the selected 7 / 30 / 90-day window. One tall spike with empty days on either side is usually a single campaign or one attack burst; a rising staircase is a sustained shift — misconfiguration or ongoing abuse. - The anomaly ledger — which entries exactly? From
GET /insights/anomaly-insights/history, the raw table of every detection in the window, newest first, filtered by scope (All / Wallet / Webhook) and collapsed to ten rows until you expand it. This is the row-level evidence the summary tiles aggregate.
from/to pair).
Reading a detector raise
Every ledger row carries a category, a severity, a scope, a human-readable summary, and the detection time.Scope — where the anomaly lives
- Wallet (spend) — the anomaly sits on a spend-bearing channel (SMS, WhatsApp, email, RCS, voice, AI agents, or an all-channels roll-up). This is your money side: usage or spend on a paid channel behaved abnormally. Treat open wallet anomalies as a billing-risk queue.
- Webhook / inbound — the anomaly is tied to inbound traffic and webhook delivery: your phone numbers, or your webhook endpoints. Inbound anomalies rarely cost you money directly; they signal probing or abuse aimed at your numbers, or delivery problems reaching your endpoints.
Severity — how fast to move
Severity rankslow → medium → high → critical. high and critical are
same-day items; the summary strip counts them separately so you can tell “one
same-day fire” from “a queue of review items” before you open the table.
Category — which detector fired
Categories name the detector family: spend spike, toll-fraud (IRSF) blocked, suspicious campaign send, SIM swap detected, voice deepfake, API key location anomaly, SMS pumping blocked, webhook-delivery anomalies. Where a category has a glossary entry, its name links out to it from the table.Expected resolution path
A detector raise is worked on the Insights → overview Fraud alerts card, which carries the acknowledge / triage controls — the anomalies page is where the raise is read, the overview card is where it is resolved. So the resolution path per row is: read the row here → open the overview card → acknowledge and triage it there → confirm it clears from the open count on this page. Until someone triages it, an entry keeps counting toward “Open anomalies.”Alert rules vs the forensics ledger
Two different surfaces with complementary jobs:- Usage & delivery anomaly alert rules — rules you author: a delivery-rate floor, an outbound-volume ceiling, a spend threshold. When one fires it posts a notification to the Notification Center; the notification deep-links back into Insights.
- This page — the platform’s own detectors, which fire with no configuration. The ledger here is the investigation surface: you come here to reconstruct what happened, in which scope, and how severe, whether or not a rule of yours also fired.
Refresh semantics — the 60-second poll
The page refetches all three feeds every 60 seconds, matched to the API’s 60-second cache TTL on these endpoints. Consequences:- A new detector raise appears on the page within about a minute of landing in the ledger.
- Once you triage a raise on the Fraud alerts card, its open count here clears on the same cadence — expect up to a minute of lag, not a stale number from your session.
- If a raise does not clear within a minute, it was not triaged — go to the overview Fraud alerts card and work it, since resolving from any other surface does not exist.
- Polling pauses in background tabs, so a raise can look “stuck” on an unfocused window; refocus and the next tick reconciles it.
Escalation workflow: from ledger row to support bundle
When a row needs more than a dashboard look, escalate in this order:- Ledger row — note the category, severity, scope, and detection time of the entry that concerns you. The row’s visible fields are everything the platform exposes to a tenant; provider-internal payloads are scrubbed before they reach either the page or the API.
- Raw history endpoint — pull the same window with
GET /insights/anomaly-insights/history?days=<n>&scope=<wallet|webhook>(optionally with an explicitfrom/to) to get the full row set, paged at up to 100 entries per request, or a longer window than the picker offers. The worked API samples include a Node snippet that turns this call into an ops decision pass. - Support bundle — if the escalate-to-support moment arrives, attach the
history response (
dataplus themeta.request_id) for the affected window, name the scope, category, and detection time of the row, and reference the request id. That gives support the exact ledger slice the dashboard rendered, without screenshots.