Analytics
Deliverability and risk-tolerance reporting for your numbers. **Scope** — Reports are organization-scoped: any API key in the organization returns the whole organization's scorable fleet, regardless of which numbers a particular key is attached to. **Eligibility** — Risk scoring is available for dedicated numbers (Dedicated Commercial or Dedicated Enterprise) and inbound numbers (Inbound Basic); shared and trial numbers return `403 dedicated_plan_required`. Those are the only lines whose per-number usage is meaningful to score. **What the score means** — Each number gets a `risk_score` from 0 (lowest risk) to 100 (highest), mapped to a `risk_level`: `low` (0-29, healthy), `medium` (30-59, monitor), `high` (60-100, likely to be filtered/suspended by carriers). The score is the clamped sum of ten additive risk factors (see `RiskFactors`); positive factor scores raise risk, negative scores (bonuses) lower it. High **inbound** volume and engagement lower risk; high **outbound** volume, bursts, low reply rates, and templated content raise it. Risk is attributed to what a number does rather than to the traffic it receives, so `newConversationBursts` counts only the conversations the number itself opened — on every line type, a rush of customers texting in is never read as a blast. **Inbound lines are scored differently** — Inbound numbers are reply-only, so the factors that assume cold outreach are re-scoped for them: `outboundConversations` and `inboundPercentage` report `status: "not_applicable"` with a score of 0 (they are structurally fixed on a reply-only line), `inboundConversations` earns no volume bonus, and `inboundMsgCount` uses a relaxed threshold worth fewer points. The remaining factors — reply rate, total contacts, message balance, message bursts, and message similarity — are scored identically to dedicated lines. Each report entry carries a `line_type` so you can tell which profile was applied. **How it's computed** — Fully real-time: every request recomputes from Postgres over the requested window (there is no cache on the report endpoints). The metric fan-out is collapsed into a handful of org-wide `GROUP BY allocation_id` queries that run on a single database connection, so cost is roughly independent of fleet size. Conversation-initiation signals read the `channel_thread_stats` rollup (one row per conversation, holding its earliest message + direction); engagement, contacts, and bursts scan the windowed `messages`; message similarity derives a SimHash per outbound message at read time. **Window** — Defaults to the trailing 30 days; override with `days` or an explicit `from`/`to` epoch-ms range (see the per-endpoint query params).