> ## Documentation Index
> Fetch the complete documentation index at: https://docs.orbit.devotel.io/llms.txt
> Use this file to discover all available pages before exploring further.

# The composite pre-send risk verdict: four detectors, one score

> How the SMS-pumping, URL-reputation, Verify Fraud Guard, and Voice Biometrics detectors fold into one 0-100 pre-send verdict — which score wins, how bands map to advisory actions, and why the verdict advises but never enforces.

# The composite pre-send risk verdict

Before you commit an SMS send or a call, you want one answer to "how risky
is this destination?" — not four. Orbit's anti-fraud detectors each answer
that question for their own slice (pumping patterns, link reputation, Verify
channel fraud, voice anti-spoof), with four different response shapes and
four sets of thresholds. `POST /risk/score` fuses them into **one composite
verdict**: a 0–100 score, a coarse band, and an advisory recommendation you
read before your send walks the gating chain.

This page is the concept-level map of that model: what each detector
contributes, how the composite is resolved, what the bands mean, and why the
verdict is read-only by design. Field-level request and response shapes live
in the [Risk API reference](/api-reference/endpoints/risk).

## What a composite pre-send risk verdict is

A composite risk verdict is **one decision artifact per destination**. You
send the destination you are about to text or call, and optionally the
message body and the session scores you already hold; you get back a single
`score` (0 = no observed risk, 100 = worst observed risk), a `band`, a
`recommendation`, and a per-channel `channels` breakdown that shows exactly
which detector drove the verdict. Each destination gets its own verdict —
query per send, not per batch.

Four detector channels fold into the verdict:

| Channel            | Present when                          | What it scores                                                                                       |
| ------------------ | ------------------------------------- | ---------------------------------------------------------------------------------------------------- |
| `sms_pumping`      | Always computed by the endpoint       | Artificial-traffic / SMS-pumping pattern on the destination, from your own recent send traffic.      |
| `url_reputation`   | Computed when you pass `message_body` | Reputation of every URL in the outbound body — the worst URL in the body wins that channel.          |
| `verify_fraud`     | You pass `verify_signal`              | Verify Fraud Guard result from your own OTP send this session (SIM-swap, geo, CAMARA-class signals). |
| `voice_biometrics` | You pass `voice_biometrics_signal`    | Anti-spoof / match verdict from your own Voice Biometrics challenge this session.                    |

## The always-computed detectors

Two channels require nothing from you beyond the destination and body, and
the endpoint runs them on every request:

* **SMS-pumping score.** The artificial-traffic detector aggregates your own
  send history for the destination — velocity and repetition signals the
  endpoint reads from your tenant's traffic — and scores it 0–100. It always
  produces a channel entry, and its dependencies fail **open**: if a signal
  source is unavailable mid-request, that signal degrades to neutral (score
  0 contribution) rather than failing your pre-send check.
* **URL / link reputation.** Pass `message_body` and every URL in it is
  reputation-scanned; the channel score is the worst URL in the body, so one
  bad link in an otherwise clean body still drives the composite. Omit
  `message_body` and the channel is absent — a voice-only caller has no
  body to scan and loses nothing by keeping it out.

Both detectors are the same logic that guards the send path elsewhere —
reused unchanged, so the pre-send verdict agrees with what the platform
already computes.

## The optional pass-through inputs

The other two detectors need inputs the endpoint must never trigger on your
behalf — Verify Fraud Guard runs a paid number-intelligence lookup per send,
and Voice Biometrics needs captured caller audio. So the endpoint does not
run them for you: you have already run them this session, and you pass their
scores in.

* **`verify_signal`.** If you already sent an OTP to this recipient with a
  Fraud Guard policy, the risk score on that `POST /verify/send` response is
  the score you fold in. Omit it when no Verify send ran — the verdict stays
  honest about what the other channels observed, and this channel reports
  `present: false`.
* **`voice_biometrics_signal`.** If you already ran a Voice Biometrics
  challenge for this session (enroll or verify), carry the spoof/match score
  into the composite. Same rule as Verify: omit when no challenge ran.

A pass-through channel you do not supply contributes **nothing** — absence
never invents risk, and a caller holding only one of the four signals still
gets a usable verdict. With no body and no pass-through scores, a clean ask
returns `score: 0` / `band: "low"`.

## How the composite is resolved

```text theme={null}
destination + channel -----------> sms_pumping detector ---------┐
message_body (optional) ---------> url_reputation detector ------┤
verify_signal (pass-through) ------------------------------------┤---> worst present score
voice_biometrics_signal (pass-through) ---------------------------┘      wins → band → advisory recommendation
```

The aggregation rule is **worst present channel wins**: the composite score
is the maximum of the channels that are present for this request — the same
worst-wins rule the URL scan already applies across multiple URLs in one
body. A flagged destination cannot be washed out by clean channels, and a
bad link cannot hide behind a low pumping score. Band cutoffs reuse the
SMS-pumping scorer's thresholds, so `high` means the same thing whether it
came from one channel or from the fused composite.

### Score band → advisory action

| Score  | Band       | Advisory recommendation | How to read it                                                                                                                                  |
| ------ | ---------- | ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
| 0–24   | `low`      | `allow`                 | No channel observed anything — proceed normally.                                                                                                |
| 25–49  | `elevated` | `allow`                 | Something sits above baseline; worth logging or sampling, rarely worth blocking.                                                                |
| 50–79  | `high`     | `review`                | Route to a review queue, step up to a Verified destination you already trust, or delay-and-recheck.                                             |
| 80–100 | `critical` | `block`                 | Skip this send — the worst channel observed a hard fraud pattern, and proceeding burns spend on a pumped destination or pushes a poisoned link. |

The `channels` array tells you *why*: each entry reports `present`, its own
score, and its reason codes — so a critical composite driven by
`url_reputation` (remove the link and retry) is handled differently from one
driven by `sms_pumping` (stop sending to that destination).

## Why the verdict is read-only and advisory

The Risk endpoint sends nothing, routes nothing, and enforces nothing: you
can poll it the entire day and still hold your sends. That is deliberate.
Outbound voice and SMS exit exclusively through the Devotel softswitch with
the platform's send-gating chain attached; a score endpoint that could
silently refuse or reroute your traffic would be a second, hidden class of
gate — one your integration never configured and cannot audit. The verdict
is instead an **input to your decision**: you decide whether the
recommendation skips the send, queues it for review, substitutes a
Verified-channel OTP, or simply gets logged.

## Verdict vs. gate: advice before send, enforcement at send

The composite verdict and the [send-gating chain](/concepts/send-gating-and-quiet-hours)
are complementary, not overlapping:

* **The verdict advises, before send.** Query it ahead of a dispatch (or a
  campaign batch) and translate the recommendation into your own policy —
  skip, review, or proceed. It is a read; the outcome lives in your code.
* **The gates enforce, at send time.** Wallet posture, opt-out and
  suppression lists, quiet hours, frequency caps, and throughput caps admit
  or refuse the actual send — that is where a send is stopped, with a
  documented error or skipped status.

A typical pairing: query `/risk/score` before a high-value send or a
campaign batch, apply your policy to the recommendation, then let the send
walk the gates as it always has. The verdict sharpens what you choose to
send; it never replaces the chain that decides what actually leaves.

## See also

* [Risk API reference](/api-reference/endpoints/risk) — request fields, response shape, and rate limits
* [Send gating and quiet hours](/concepts/send-gating-and-quiet-hours) — the gate chain a send actually walks
* [Verification lifecycle](/concepts/verification-lifecycle) — where the Fraud Guard score you pass in comes from
* [Voice biometrics](/concepts/voice-biometrics) — the anti-spoof challenge behind the biometrics signal
* [Fraud reputation: the shared network feed](/concepts/network-signals-fraud-reputation) — cross-tenant reputation the detectors draw on
