Skip to main content

SMS-pumping (AIT) protection: read the risk score before you send

SMS-pumping — also called artificial-inflation of traffic (AIT) — is the fraud pattern where an attacker (or a complicit premium-rate number owner) drives fake traffic to destination numbers that pay out on inbound SMS. The attacker converts stolen signup forms, bot-driven OTP requests, or compromised senders into messages to IRSF (International Revenue Share Fraud) ranges and premium-rate destinations; the platform bills every accepted leg, and the fraudster pockets the carrier payout. Orbit ships three API surfaces that expose this pattern to you before and after it costs money. This guide explains what each surface computes, how to read the score, and where to wire it into a send path. Every surface below is advisory and read-only. None of them sends, routes, blocks, or modifies any outbound message — outbound traffic exits only through the Devotel softswitch, exactly as before. The platform computes the verdict; the decision to act on it — allow, review, or refuse a send — is always the tenant’s.

1. What SMS-pumping actually looks like

A pumping attack inflates your SMS spend in two recognisable shapes:
  • Premium-rate / IRSF destinations. Traffic drifts to numbers on revenue-share ranges (historically Cuba, Somalia, Sierra Leone-class corridors). Each accepted message bills at several times a normal rate.
  • OTP-completion collapse on Verify. Bots request real SMS OTPs but never enter a code. Verify’s per-destination conversion (verified ÷ sent) falls far below your tenant baseline while carrier spend keeps accruing.
Both shapes are detectable from signals your tenant already accrues: destination-prefix prefixes, send velocity, delivery conversion, geographic spread, and — for Verify — OTP completion rates. The three surfaces below package those signals into scores you can query and act on.

2. The three surfaces

A fourth Verify-specific detector, GET /api/v1/verify/conversion-anomaly, flags destinations whose OTP completion rate is far below your tenant baseline and reports the estimated spend at risk — run it periodically as the detection side of the same posture.

3. Reading the score

All scoring surfaces return the same three top-level fields:
  • score — a composite risk score from 0 (clean) to 100 (certain block).
  • band — a coarse label derived from the score: below 25 low, 25+ elevated, 50+ high, 80+ critical.
  • recommendation — the mapped advisory action: allow, review, or block.
The same cut-offs apply in both the standalone SMS-pumping scorer and the composite verdict, so a high band means the same thing on POST /messages/risk-signals and on POST /risk/score. The composite verdict also returns a per-channel breakdownsms_pumping, url_reputation, verify_fraud, voice_biometrics — naming which detector(s) fired and their individual scores. The composite is the maximum of the present channels (worst present channel), chosen deliberately: a message that reviews on any single channel gets flagged rather than averaged back to low, and a destination with no signal at all returns a clean score of 0 rather than a misleading average. The standalone SMS-pumping score returns a factors array instead — one entry per signal that contributed, with a machine-readable code, the points it added, and a human-readable detail. The per-factor breakdown sums (before the 100 cap) into the composite score, so the verdict is never a black box.

4. Advisory, not enforcing

These surfaces score; they do not enforce. POST /risk/score, POST /messages/risk-signals, and the Verify analytics endpoints never send, route, block, or modify an outbound message. The Devotel softswitch remains the sole outbound path for every channel. Whether a given score means “send anyway”, “queue for review”, or “refuse the destination” is a decision your own campaign or send code makes. The recommendation field is a suggested action — nothing more.
Tenants that want the platform’s built-in enforcement layer on top can configure Fraud Shield on the messaging side (GET / PUT /api/v1/messages/fraud-shield, then POST /api/v1/messages/fraud-shield/evaluate to turn a score into a terminal allow/review/block decision against your own thresholds and country lists) and the Fraud Guard on the Verify side (which can refuse an OTP pre-send). Those are separate, tenant-owned configurations; this guide covers only the always-on scoring surfaces.

5. Worked examples

Composite verdict: POST /api/v1/risk/score

Query the fused verdict for a destination before a send. Supply channel so the correct velocity aggregate drives the SMS-pumping leg, and optionally the message body so URLs inside it are reputation-scanned.
A flagged response looks like:
If you already run a Verify Fraud Guard evaluation or a Voice Biometrics challenge for this session, pass their scores through as verify_signal / voice_biometrics_signal so the composite folds them into the same verdict instead of you reconciling four independently-banded results.

Per-factor breakdown: POST /api/v1/messages/risk-signals

When the composite flags a destination, the standalone scorer tells you exactly which signals fired:
Each factor is an additive weight capped at 100 in total: tenant outbound blocklist (100), NANP +1 555-NXX test range (90), known IRSF / premium-rate prefix (85), send-velocity spike (up to 40, ratio-scaled against your velocity window), 24h geo-spread anomaly (25), and low delivery-conversion rate (up to 30, only when at least 20 terminal sends back the rate). A missing signal — for example, no delivery history yet — contributes nothing rather than inventing or absolving risk.

Historical posture: GET /api/v1/verify/fraud-analytics

Aggregate what the fraud-event ledger already caught over a window (1–90 days, default 30):
The response carries blocked and step-up totals, per-channel and per-reason breakdowns, a per-day time series for charting, and an estimated blocked-spend-saved figure. Pair it with GET /api/v1/verify/conversion-anomaly (same window_days query) to see unblocked AIT suspects — destinations converting far below your baseline — and download GET /api/v1/verify/conversion-anomaly/evidence-export.csv when you need an RFC-4180 evidence pack for a carrier chargeback dispute.

6. Webhooks and the fraud-event ledger

Two streams make the posture observable after the fact:
  • verification.fraud_blocked — emitted when the pre-send Fraud Guard refuses an OTP send. The payload carries the channel, destination, the computed risk_score, and the machine-readable fraud_reasons (for example ["risk_block", "roaming"]). Pre-send refusals are deliberately not reported as verification.failed — no verification row exists, so there is no phantom failure. See the webhook events reference for the full payload shape and the companion verification.fraud_step_up event.
  • The fraud-event ledger — every block and step-up verdict persists to a per-tenant ledger. GET /api/v1/verify/fraud-analytics (above) is the reporting surface over it: per-channel and per-reason totals, a per-day series, and the cumulative estimated spend saved by the blocked events.

7. Wire it into the send path

Query before committing spend, not after. The cheapest integration point is the campaign or send orchestration code that already validates a recipient:
The composite endpoint is rate-limited to 120 requests/minute per tenant, so for high-volume campaign sends score the campaign’s distinct destination prefixes first and only escalate full destination-level checks on suspicious prefixes. Cache verdicts by destination for the duration of a campaign — a destination’s score does not change meaningfully inside a send window. For ongoing hygiene, schedule GET /api/v1/verify/fraud-analytics daily and GET /api/v1/verify/conversion-anomaly weekly; when the anomaly report flags a new destination, feed it back into your send-side policy (or your outbound blocklist, which the scorer itself reads) so the next send to that destination scores critical immediately.

What’s next