Fraud Prevention
Signal-based risk scoring on every order, monitor/enforce modes, review queue with customisable customer comms, alerts to Slack/Discord/Teams/Telegram, daily threat feeds — chargebacks stopped before fulfilment.
What it does
Built for production from day one.
Every placed order is risk-scored server-side the moment it lands — no storefront integration required. Weighted signals (order velocity per IP and per canonical email identity, disposable email domains, block/allow lists with CIDR range matching, high-risk countries, failed-payment patterns, plus-addressing abuse, first-order value) roll up to a 0-100 score. Your per-channel thresholds decide what happens: log it, hold it for review, or hold it and tell the customer it is being verified. Digital-goods aware: fulfilment (licence keys, downloads) waits for approval, so one reviewer click is the difference between a sale and a chargeback.
Server-side enforcement
Assessment runs on OrderPlacedEvent inside Vendure — fraudsters can't bypass it by skipping your storefront JS. No checkout integration needed.
Weighted signal scoring
Velocity (IP/hour, IP/day, email/day, daily value), order value ceilings, disposable emails, list hits, high-risk countries, failed payments, identity fan-out (many emails from one IP = card testing), VPN/proxy/datacentre IPs, IP vs billing-country mismatch, MX-less email domains. Every weight overridable per channel.
Monitor → enforce rollout
Start in monitor mode: everything is scored and logged, nothing is held. Watch the Activity tab, tune thresholds, then flip to enforce.
Manual review queue
Held orders wait for a human. Approve releases fulfilment; reject cancels — and each can be done silently (no customer email) or, on reject, with a one-click silent blocklist of the email + IP so the fraudster is turned away next time and never tipped off. Alerts fan out to Slack, Discord, Microsoft Teams, Telegram and an HMAC-signed webhook; a per-channel auto-approve timer means nothing strands over a weekend. Full audit trail on every decision.
Fulfilment hold hook
One-line host integration: ask pendingOrderIds() before releasing licence keys or shipping. Approval is the gate, not an afterthought.
Daily threat feeds
FireHOL Level 1, Spamhaus DROP (CIDR ranges matched properly), Tor exit nodes and ~3,500 disposable-email domains — synced nightly into your blocklist.
Email canonicalisation
[email protected], [email protected] and [email protected] all count as ONE identity for velocity — the plus-addressing trick stops working.
Trust works both ways
Returning customers earn NEGATIVE points — a real repeat buyer rarely trips a hold. Allowlisted identities (test accounts, key B2B customers, office IPs) skip every check entirely.
Customer messages in your voice
Every gating outcome — held, approved, rejected — is a per-channel editable template with variables, live preview and thoughtful defaults: a held order reads as 'a quick security check' with a stated turnaround, never an accusation, and rejections carry a refund timeline plus a human-appeal path. Each shows a default / customised badge; reset any selection or all of them in one click. You choose when — and whether — customers are told: never, block-level only, or always.
"What-if" simulator
Run a hypothetical order (email, IP, value, country) against live data and see the exact signal-by-signal score breakdown — without logging or holding anything.
Multi-tab admin dashboard
Overview KPIs + daily chart, Rules, Review queue with count badge, Lists, Simulate, customer Lookup dossier (orders, spend, failed payments, case history, one-click allow/block), filterable Activity log with CSV export, Settings. WCAG AA in light and dark themes.
Install
Three steps, five minutes.
Add the package
Or run the one-line installer that does steps 1–3 for you:
Prefer to do it by hand?
Register it
In your vendure-config.ts:
Run the migration
The plugin adds its own table(s). Generate + run the migration like any other:
That's it. The admin UI tab appears immediately. Without a licence key the plugin runs in a degraded evaluation mode — fine for trying things out. Buy a key →
HTTP endpoints
Every route exposed.
/fraud-prevention/checkPublic: storefront pre-check (rate limited, minimal shape)/fraud-prevention/configAdmin: per-channel config/fraud-prevention/configAdmin: save config/fraud-prevention/statsAdmin: KPIs + daily series + top IPs/fraud-prevention/casesAdmin: review queue/fraud-prevention/cases/:id/approveAdmin: release + notify customer/fraud-prevention/cases/:id/rejectAdmin: cancel + notify customer/fraud-prevention/simulateAdmin: dry-run with full signal breakdown/fraud-prevention/logAdmin: filterable audit log/fraud-prevention/lists/syncAdmin: threat-feed sync (licensed)FAQ
Common questions.
How do I get a licence key?
Buy here — Stripe Checkout, monthly or lifetime. You'll receive the JWT key by email; set it as HULO_LICENCE_KEY_FRAUD_PREVENTION in your .env.
Does it work without a key?
Yes — the plugin boots in a degraded "evaluation" mode. You can install, configure, and inspect the admin UI before committing.
Where is data stored?
In your Vendure database. The plugin adds its own tables via a migration — your data never leaves your server.
Will it survive a Vendure upgrade?
Tested against Vendure >=3.5.0 <4.0.0 — 3.5, 3.6 and 3.7 are all covered by CI. A boot-time compatibility check emits a non-fatal warning if @vendure/core is outside that range, so upgrades to a future 3.x are safe to try. The 4.0 line will be tested and re-declared once its changelog lands.