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

# Risk decisions

> How Clausum scores transactions and what each decision means.

Every call to `POST /api/v1/assess` returns a `risk_score` from **0 to 100** and a `decision`. The score is the sum of the weights of the signals that fired, capped at 100.

## Decisions

| Decision    | Typical score     | Recommended action                                |
| ----------- | ----------------- | ------------------------------------------------- |
| `approve`   | low               | Proceed with the transaction.                     |
| `review`    | moderate          | Allow, but queue for manual review or monitoring. |
| `challenge` | elevated          | Require step-up verification (3DS, OTP, KYC).     |
| `decline`   | high / hard block | Block the transaction.                            |

Thresholds between these bands are **configurable per organization** in the dashboard, so you can tune Clausum to your risk appetite without code changes.

<Note>
  A hard block (for example an email on a `block`-severity blocklist, or an amount over your configured maximum) forces `decline` with a `risk_score` of 100 and populates `blocked_by` with the reason.
</Note>

## Response shape

```json theme={null}
{
  "decision": "challenge",
  "risk_score": 55,
  "signals": ["high_velocity", "disposable_email"],
  "signal_details": [
    { "code": "high_velocity", "weight": 35, "description": "6 transactions in the last hour" },
    { "code": "disposable_email", "weight": 20, "description": "Disposable email detected" }
  ],
  "session_id": "ps_1716998400000_a1b2c3d4e",
  "blocked_by": null,
  "latency_ms": 48
}
```

* **`signals`** — short codes of every signal that contributed.
* **`signal_details`** — the weight and human-readable description for each.
* **`session_id`** — persist this to correlate with later reports and webhooks.
* **`blocked_by`** — non-null only when the transaction was hard-blocked.

## Signal categories

<AccordionGroup>
  <Accordion title="Blocklist matches" icon="ban">
    Email, email domain, IP, IP range, device fingerprint, card BIN, card hash, country, phone, or customer id present on your blocklists. `block` severity hard-declines; `flag` and `review` add weight.
  </Accordion>

  <Accordion title="Email signals" icon="envelope">
    Disposable email providers and suspicious TLDs (`.xyz`, `.top`, `.click`, …).
  </Accordion>

  <Accordion title="Behavioral signals" icon="hand-pointer">
    Very short sessions, no mouse movement, copy-pasted fields, and bot-like patterns — most reliable when paired with the [browser SDK](/guides/browser-sdk).
  </Accordion>

  <Accordion title="Amount signals" icon="money-bill">
    Configurable min/max limits and statistical outliers compared to your recent transaction history.
  </Accordion>

  <Accordion title="Velocity signals" icon="gauge-high">
    Repeated transactions from the same email or device within a short window.
  </Accordion>

  <Accordion title="Payer history" icon="clock-rotate-left">
    Prior confirmed fraud associated with the email carries a heavy penalty.
  </Accordion>

  <Accordion title="Custom rules" icon="sliders">
    Organization-defined rules can add or subtract score, or force a specific decision. Triggered rules appear in `rules_applied`.
  </Accordion>
</AccordionGroup>

## Enforcing decisions

```ts theme={null}
function enforce(assessment) {
  switch (assessment.decision) {
    case "approve":   return proceed()
    case "review":    return proceed({ flagForReview: true })
    case "challenge": return requireStepUp()        // 3DS / OTP
    case "decline":   return block(assessment.blocked_by)
  }
}
```

<Tip>
  Log `session_id`, `risk_score`, and `signals` alongside your order records. They are invaluable when investigating disputes and when calling [`report-fraud`](/guides/report-fraud) later.
</Tip>
