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

# Risk Scoring

> How Didit scores every transaction: rule contributions, thresholds, and status mapping (APPROVED, IN_REVIEW, DECLINED). Pay-per-call $0.02 per transaction.

Every transaction gets a **score** — an integer that summarizes its risk. The score drives the transaction's status (`APPROVED`, `IN_REVIEW`, `DECLINED`) and the decision whether to create an alert, open a case, or require user remediation.

## The formula

```
score = Σ(score_delta of every matched rule)
```

* Base score: 0.
* Each matched rule contributes its configured `score_delta` (typically 25–35).
* A transaction with no matching rules scores 0.

## Thresholds and statuses

Score thresholds are configured per application at *Transactions → Settings*.

| Setting                             | Default | Meaning                                                                                          |
| ----------------------------------- | ------- | ------------------------------------------------------------------------------------------------ |
| `preferred_review_score_threshold`  | 60      | Scores ≥ this go to `IN_REVIEW`                                                                  |
| `preferred_decline_score_threshold` | 85      | Scores ≥ this go to `DECLINED`. The maximum slider value (`500`) means "never decline by score". |

Status assignment:

```
if decline_threshold < 500 and score >= decline_threshold: status = DECLINED
else if score >= review_threshold: status = IN_REVIEW
else: status = APPROVED
```

Individual rule actions can override this — e.g. a rule with `action: change_status → DECLINED` will decline regardless of score.

## Rule contributions — worked example

Suppose these rules fire on a single transaction:

| Rule                                | `score_delta` |
| ----------------------------------- | ------------- |
| High-value outbound (>\$10,000)     | 30            |
| High-risk jurisdiction counterparty | 35            |
| Structuring pattern detected        | 35            |

Total score = 30 + 35 + 35 = **100**.

With default thresholds (60 review, 85 decline), this transaction is `DECLINED`.

## Action overrides

Rules can also directly set the status, bypassing score thresholds:

| Rule action                     | Effect                                                                                                                                                                                                                    |
| ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `change_status → DECLINED`      | Transaction declined regardless of score                                                                                                                                                                                  |
| `change_status → IN_REVIEW`     | Transaction goes to review regardless of score                                                                                                                                                                            |
| `change_status → AWAITING_USER` | Transaction waits for user remediation - the workflow on the rule action; library rules fall back to your settings choice, then your Biometric Authentication workflow (stored face required), then your default workflow |
| `add_score(n)`                  | Only contributes to the score; no forced status                                                                                                                                                                           |
| `add_tags([...])`               | Attaches tags for console filtering; no score effect                                                                                                                                                                      |
| `add_to_list(...)`              | Adds an identifier to a blocklist                                                                                                                                                                                         |

A single rule can have multiple actions — e.g. `add_score(35)` + `add_tags(["structuring"])` + `add_note("Auto-tagged by structuring preset")`.

## Why scores beat hard rules

A pure threshold (e.g. "decline every transaction over \$100k") triggers both legitimate high-value transactions and real risk. Combining several moderate `score_delta` rules and a review/decline threshold gives you:

* **Layered scoring** — no single rule causes a decline; multiple signals have to agree.
* **Tunable sensitivity** — raise or lower thresholds without touching rule definitions.
* **Ordering of gravity** — a transaction with score 65 goes to review (worth a look); score 90 goes to decline (serious).

## Configuring thresholds

From *Transactions → Settings*:

* **Review threshold**: raise if your review queue is flooded; lower to catch more edge cases.
* **Decline threshold**: raise to reduce false-positive declines; lower to lean toward aggressive blocking. Set it to the maximum value (`500`) to route high scores to review instead of auto-declining.

Changes apply to **new** transactions only — historical transactions retain their evaluation-time status.

## Test mode for rules

Rules can run in `TEST` mode:

* Rule evaluates against transactions but does not contribute to the score or status.
* `TransactionRuleRun` records are created with `is_test = true`.
* Lets you validate a rule's selectivity without risking production declines.

Switch to `ACTIVE` once you're happy with the selectivity.

## Severity and legacy fields

The `severity` field on Transaction and TransactionAlert is nullable and legacy. New rule evaluations don't set it. Use `score` as the primary risk signal.

## Inspecting scores

### Via API

Every transaction response includes `score`, `rules_evaluated_count`, `rules_matched_count`, and a `rule_runs[]` array:

```json theme={null}
{
  "txn_id": "tx-0002",
  "status": "IN_REVIEW",
  "score": 65,
  "rules_evaluated_count": 18,
  "rules_matched_count": 2,
  "rule_runs": [
    {
      "rule_name": "High-value outbound",
      "matched": true,
      "score_delta": 30,
      "severity": null,
      "status_target": null
    },
    {
      "rule_name": "High-risk jurisdiction counterparty",
      "matched": true,
      "score_delta": 35,
      "action_summary": { "add_tags": ["high_risk_country"] }
    }
  ]
}
```

### In the console

On the transaction detail page, the **Score** tab shows a breakdown of each matched rule's contribution and the final status mapping. Hover over the score badge for the threshold values used at evaluation time.

## Next steps

<CardGroup cols={3}>
  <Card title="Rules" icon="scale-balanced" href="/transaction-monitoring/rules">
    Rule anatomy and evaluation.
  </Card>

  <Card title="Alerts" icon="bell" href="/transaction-monitoring/alerts">
    What happens when a rule fires.
  </Card>

  <Card title="Settings" icon="gear" href="/transaction-monitoring/settings">
    Configure thresholds.
  </Card>
</CardGroup>
