Skip to content

Risk controls

Prepaid credits attract stolen cards. Each brand screens its payments with rules — velocity limits, new-customer limits, blocklists, disposable emails and a risk score — that refuse a payment, ask the bank for 3-D Secure, or hold it for review. Fresh balances can be capped.

Stolen cards are tested on small purchases and cashed out through anything that can be spent at once, and prepaid credits are both. Every brand screens its payments with its own risk rules, on top of your processor's own fraud checks (Stripe Radar stays on). The rules run three times during a checkout and once before every auto-reload:

WhenWhat the rules know
Before the payment intent existsThe email, the IP network and country, the billing country, the customer's history, the amount
Once the card is enteredAlso the card's fingerprint (from the processor) and its country
At confirmationThe same again, so a blocklist entry added in the meantime still holds
Before an auto-reload is chargedThe customer, the saved card, the reload amount (no IP: the charge is off-session)

Each rule that fires has an action:

  • Block: the payment is refused before it reaches the card. The buyer sees "This payment can't be accepted" (risk_payment_declined), never which rule: an answer that names the rule teaches a fraudster how to get around it. An auto-reload is skipped (risk_blocked).
  • Ask for 3-D Secure: the payment intent asks the card's bank to authenticate the customer. Off-session charges can't, so they go through.
  • Hold for review: the payment goes through, and waits in the review queue (below).

The rules and their defaults

The defaults suit prepaid credits. Test and live mode have their own rules (test mode is a parallel world); the counting rules — velocity and the new-customer top-up limits — are on in live mode and off in test mode, where every customer pays with the same few test cards from the developer's own machine. Turn them on in test mode to try them.

RuleDefault
New customers' top-upsAt most 2 top-ups (payments that buy credits, auto-reloads included) in 24 hours; the third is blocked. A customer is new until their first payment is 7 days old.
First top-upAt most 100 EUR, USD, GBP or CHF; more is blocked. Other currencies have no limit until you set one.
First payment3-D Secure.
One IP networkAt most 10 payment attempts and 3 cards an hour from one /24 (IPv4) or /48 (IPv6) network. Private and loopback networks aren't counted.
One cardAt most 5 payment attempts in 24 hours with one card, whoever uses it.
One email domainAt most 10 attempts an hour by new customers of one domain. Large mail providers (gmail.com, outlook.com and others) aren't counted.
Disposable email addressesBlocked. The list of throwaway mail services is a maintained data file.
BlocklistsAlways: emails, card fingerprints, IP ranges and countries you list.
Customer riskA customer whose risk is blocked is refused; elevated (after a lost dispute) adds 40 points.

A payment attempt is counted once, however many times the rules run for it; each card tried counts for the card rules. A window of N hours counts the current clock hour and the N before it, so it looks back at least N hours.

The score

Country mismatches add points: the IP country differs from the billing country (20), the card's country from the billing country (25), the IP country from the card's (15). A new customer adds 10, an elevated one 40. At 20 points the payment asks for 3-D Secure, at 75 it is held for review; a block threshold is off until you set one.

Change any of it in Brand → Risk → Rules, or with PATCH /api/v1/risk/settings. Each rule's action can be any of the three.

Blocklists

Brand → Risk → Blocklists lists the values whose payments are refused:

  • email: an address, in any case;
  • card_fingerprint: the processor's fingerprint of a card number, so the card is refused whatever its expiry or the customer using it (a risk evaluation shows it);
  • ip_range: CIDR such as 203.0.113.0/24. Ownrecord never keeps a full IP address, only its /24 (or /48) network, so a range is at most that narrow;
  • country: matched with the IP country, the billing country and the card's country.

Rejecting a held payment adds the customer's email and card for you.

The review queue

A held payment is recorded, booked and invoiced like any other — the money moved. In the same step:

  • the customer's wallet in the payment's currency is frozen when the payment bought credits, so they can't be spent yet;
  • the customer's risk becomes elevated;
  • your team gets a RISK_REVIEW alert, and your webhook endpoints risk.review.opened. Hold the delivery of your own goods until the review is decided.

In Brand → Risk each review shows why the rules held it — every reason with its points, the countries, the IP network, the card — and two decisions:

  • Approve unfreezes the wallet (unless another review of the customer is pending), puts the customer's risk back and sends risk.review.approved.
  • Refund and block refunds the payment exactly as refunds.create does (a credit note at the original rates; for credits, the unused ones — the hold kept them unspent), puts the customer's email and card on the blocklist, makes the customer's risk blocked and sends risk.review.rejected. The wallet stays frozen.

Support approves; rejecting needs refund rights (support up to its limit, finance above it). Over the API: GET /api/v1/risk/reviews, POST /api/v1/risk/reviews/{id}/approve, POST /api/v1/risk/reviews/{id}/reject.

Why any payment attempt was allowed, asked for 3-D Secure, held or refused is in its risk evaluation: GET /api/v1/risk/evaluations?paymentId=… or ?checkoutSessionId=….

Fresh balances

For high-risk products, cap what can be done with credits bought in the last hours: with wallet.usageCapUntilAgeHours (for example 24) and wallet.usageCap (for example 10 EUR), credits from a payment younger than that can be reserved or spent up to the cap in total; older credits are never capped. Reservations and leases beyond it are refused with wallet_fresh_balance_capped (402) and details.freeAt, when the credits stop being fresh. Off by default.