# How Risk Scoring Works

> Understand how Fidro calculates a 0–100 risk score from multiple fraud signals.

**Category:** core-concepts | **Last updated:** March 14, 2026

---

Every validation request returns a `risk_score` between 0 and 100. This score is calculated by running multiple independent checks, each contributing a weighted score based on how strongly the signal indicates fraud.

## The scoring model

Fidro runs up to 23 checks per request across five categories:

### Email checks
| Check | What it detects | Weight |
|-------|----------------|--------|
| Disposable email | Throwaway inbox services (Mailinator, Guerrilla Mail, etc.) | Medium |
| Invalid email | Invalid format, missing MX records | High |
| Custom blocklist (email) | Matches your account's email blocklist entries | Critical |

### IP checks
| Check | What it detects | Weight |
|-------|----------------|--------|
| VPN | Commercial VPN services | Medium |
| Proxy | Open proxies and anonymous relays | Medium |
| Tor | Tor exit nodes | High |
| Bad ISP | Hosting providers and suspicious ISPs | Low |
| Bad IP reputation | IPs on known abuse lists | High |
| Custom blocklist (IP) | Matches your account's IP blocklist entries | Critical |
| Geolocation mismatch | IP country differs from billing/expected country | Medium |

### Stripe card & payment checks
These run automatically on chargeback prevention — no extra integration needed.

| Check | What it detects | Weight |
|-------|----------------|--------|
| Prepaid card | Prepaid/virtual cards (2–4x higher chargeback rates) | Medium |
| AVS mismatch | Address verification failed (address or postal code) | Medium |
| CVC failure | Card security code check failed | High |
| Stripe Radar flag | Stripe's own risk assessment flagged the transaction | High |
| Card/IP country mismatch | Card issuing country differs from IP geolocation | Medium |
| Billing/card country mismatch | Billing address country differs from card country | High |
| High-value transaction | Amount exceeds $500 (severity scales with amount) | Medium |
| Transaction velocity | 3+ transactions from same email/IP in 60 minutes | Medium |
| New customer | No previous transactions from this email | Low |

### Optional merchant metadata checks
These only run when you pass additional metadata on your Stripe PaymentIntent. See [Passing Customer Metadata](/docs/guides/passing-metadata-to-stripe) for setup.

| Check | What it detects | Weight |
|-------|----------------|--------|
| New account | Customer account created less than 30 minutes ago | Medium |
| No phone number | Customer has no phone on file (only scored when you send other metadata) | Low |
| Device velocity | Same device fingerprint used across 3+ different emails in 24 hours | Medium |
| Short session | Checkout completed in under 30 seconds (bot/automation signal) | Medium |

## How scores combine

Each failed check adds points to the score. Checks are weighted by fraud correlation and adjusted by severity — a Tor exit node is a stronger fraud signal than a missing phone number.

The final score is capped at 100. Multiple moderate signals can combine to push a user into the "review" or "refund" range even if no single check is alarming on its own.

## Score ranges and recommendations

| Score | Recommendation | Meaning |
|-------|---------------|---------|
| 0–40 | `allow` | Low risk — proceed normally |
| 41–70 | `review` | Medium risk — flag for manual review or add friction |
| 71–100 | `refund` | High risk — auto-refund if enabled, or reject |

These thresholds are configurable in your [chargeback settings](/app/settings/account) if you're on the Pro plan.

## Reading check results

The `data.checks` array in the response shows exactly which checks ran and what they found:

```json
{
  "risk_score": 72,
  "recommendation": "refund",
  "data": {
    "checks": [
      {
        "name": "disposable_email",
        "passed": false,
        "score": 25,
        "detail": "Domain mailinator.com is a known disposable email provider"
      },
      {
        "name": "prepaid_card",
        "passed": false,
        "score": 30,
        "detail": "Prepaid card detected"
      },
      {
        "name": "avs_mismatch",
        "passed": false,
        "score": 35,
        "detail": "Address verification failed"
      }
    ]
  }
}
```

Use these details to build custom logic — for example, you might allow prepaid cards but always block disposable emails combined with AVS failures.

## Tips for tuning

- **Start with defaults.** The built-in thresholds are calibrated across thousands of real-world fraud patterns.
- **Monitor your review queue.** If you're reviewing too many legitimate users, consider raising your review threshold.
- **Use blocklists.** If you see repeat offenders, add them to your [custom blocklist](/docs/guides/managing-blocklists) for instant blocking on future attempts.
- **Pass optional metadata.** Adding account age, order count, and device fingerprint data gives Fidro significantly more signal for chargeback scoring.