Skip to content

Fraud & Risk Rules

Swft leverages Stripe Radar’s risk scoring on every card transaction. You set thresholds; Swft auto-blocks high-risk orders, flags elevated-risk orders for manual review, and surfaces every score on your Sessions and Fraud dashboard pages.

When a card payment is processed, Stripe Radar scores the transaction 0–100 (higher = riskier) and assigns a risk level (normal, elevated, highest). Optionally Radar also names the rule that triggered the flag (e.g. “IP is anonymous proxy”, “Card has been used by many emails”).

You configure two thresholds:

ThresholdEffect
Block scoreOrders scoring ≥ this fail payment with a generic decline. Default 75.
Review scoreOrders scoring ≥ this complete payment but are flagged amber in your dashboard. Default 50.

The shopper never sees that an order was flagged or blocked for fraud — blocked orders just see a standard “Your card was declined” message.

Swft Dashboard → Fraud & Risk.

SettingWhat it does
Enable fraud blockingMaster toggle. When off, no orders are blocked regardless of score.
Block score0–100. Orders ≥ this score are blocked.
Review score0–100. Orders ≥ this score are flagged but completed.

Sensible starting points: Block ≥ 75, Review ≥ 50. Tighten the block score to 65 if you’re seeing chargebacks; loosen to 85 if legitimate customers are being declined.

The Fraud page shows:

  • KPIs — blocked count, review count, fraud rate, total scored orders.
  • Flagged orders — every order with radar.level = 'elevated' or 'highest', with the score, rule name, customer, and amount. Click through to the session detail.
  • Blocked orders — every payment intent declined for risk. Helpful for spotting patterns (e.g. the same IP / card BIN repeatedly).

On payment_intent.succeeded and payment_intent.payment_failed, the Swft webhook fetches the underlying Stripe Charge (stripe.charges.retrieve(charge_id)) and reads charge.outcome:

  • outcome.risk_score → number 0–100
  • outcome.risk_level → string 'normal' | 'elevated' | 'highest'
  • outcome.rule.predicate → the Radar rule that triggered, if any

The result is written to session_data.radar on the checkout_sessions row. The Fraud page filters sessions by radar.level to populate its lists.

For blocked orders, Radar declines the PaymentIntent at Stripe’s level before it confirms — Swft just records the declined attempt and surfaces it in the Blocked list.

  • Radar runs after payment is attempted, not before. Blocking happens at confirm-time, so the shopper sees a declined message. You can’t pre-filter carts based on risk.
  • Rule names are Stripe-internal codes. When Radar shows “Rule X triggered”, consult the Stripe Radar dashboard for the human-readable name of that rule. Custom rules you create in Stripe will appear by their custom name.
  • Historical orders have no radar data. Orders placed before you enabled the integration show in the dashboard. There’s no backfill.
  • Radar only applies to card payments. PayPal, Klyme (Open Banking), and other gateways have their own fraud screens — Swft surfaces nothing for those.
  • Your Stripe Radar plan matters. Stripe’s free Radar layer is rule-based and rough. Radar for Fraud Teams ($0.07/transaction) is the full ML-driven scoring and what most of this page assumes.
  1. Start with the defaults (block 75, review 50).
  2. Watch the Fraud page for two weeks.
  3. If you’re getting chargebacks despite the scores being low, your Stripe Radar plan may be too basic — upgrade.
  4. If your review queue is too noisy, raise the review threshold to 60 or 65.
  5. If legitimate customers are getting blocked, raise the block threshold to 80 or 85.

If you have a high-risk vertical (digital goods, downloads, high AOV), consider running an external fraud screen (Signifyd, Sift) on top of Radar — Swft will preserve the Radar data either way.