Skip to content

H. Card and online fraud

Fraud rules are different from money-laundering rules in one important way: speed. Once stolen money has left, it is usually gone. So these rules run in real time, inside the decision API, and can hold, block or ask for extra verification (step_up, such as an OTP) before your system approves the payment.

H1, H2, H3 and H5 ship today in the fraud pack, which runs in the real-time decision API. H4 ships in core and runs post-event.

Real-time rules can return four actions. Picking the right one matters as much as the threshold:

Action What happens Use when
allow Payment goes ahead (the hit is still recorded) You want data without friction, for example while testing
step_up Your system asks the customer for extra proof (OTP, PIN, biometric) The signal is moderate and a genuine customer can easily pass the check
review Payment is held for a person to check The amount is significant and a delay is acceptable
block Payment is refused The signal is strong (for example a confirmed fraud indicator)
ID Rule Mode Status
H1 Card testing: many small auths, few merchants RT Ships (fraud, real-time)
H2 New device + new payee + high value RT Ships (fraud, real-time)
H3 Multiple failed auth/OTP attempts then success RT Ships (fraud, real-time)
H4 High-risk MCC RT/PE Ships (core, post-event)
H5 Account takeover: profile change then payout RT Ships (fraud, real-time)
GB3 Cheque credits withdrawn in cash PE Ships (gh-bank, post-event)
GB4 Large instant transfer to a new payee PE Ships (gh-bank, post-event)

What it looks for: many small authorisations on a card in a short time, at only a few merchants. Criminals who buy stolen card numbers test which ones work with tiny payments before using the good ones for large purchases.

Example

With max_small_auths 5, small_amount GHS 10 and window 30 minutes:

  • ✅ Fires: seven authorisations of GHS 1–5 at the same online merchant within ten minutes.
  • ❌ Does not fire: three small payments for transport and snacks during the day.

Parameters

Parameter Meaning How to tune
max_small_auths Small authorisations allowed in the window Low — genuine customers rarely make many tiny payments in minutes
small_amount What counts as “small” Around the size of typical test payments
window The period Minutes to an hour

False positives: subscription services that verify a card with tiny charges. They usually appear once or twice, not repeatedly.

Data it needs: card or account identifier, amount, merchant, authorisation timestamps.


What it looks for: three risk signals at once — a payment from a device never seen for this customer, to a payee they have never paid, for a large amount. Any one is common; all three together is the classic account-takeover pattern.

Example

With threshold_amount GHS 3,000:

  • ✅ Fires: a customer’s account logs in from a new phone and sends GHS 8,000 to a wallet they have never paid before.
  • ❌ Does not fire: a new phone, paying a regular recipient.
  • ❌ Does not fire: the usual phone, paying a new recipient GHS 8,000.

Parameters

Parameter Meaning How to tune
threshold_amount Amount that makes the combination high-risk Lower for retail customers

False positives: customers who have just bought a new phone and pay someone new the same day. A step_up action handles this well.

Data it needs: device_fingerprint and a counterparty on each transaction, and enough history for SpeculaPro to know the customer’s usual devices and payees. On the first day you send data, every device and payee is new; see What “new” means.


What it looks for: several failed login, PIN or OTP attempts followed by a success — a sign that someone was guessing, or that a fraudster finally obtained the code (often by tricking the customer over the phone).

Example

With max_failures 3 and window 15 minutes:

  • ✅ Fires: four wrong OTP entries, then a correct one, then a transfer — all within ten minutes.
  • ❌ Does not fire: one typo, then success.

Parameters

Parameter Meaning How to tune
max_failures Failed attempts before a success counts as suspicious 3–5
window The period Minutes

Data it needs: otp_failed and pin_failed account events, sent as they happen, with the same customer references as your transactions.


What it looks for: card payments at merchants in high-risk merchant category codes (MCCs) — categories such as gambling, money transfer or crypto exchanges — above a threshold.

Example

With a high-risk MCC list and threshold_amount GHS 2,000:

  • ✅ Fires: a GHS 5,000 card payment to an online gambling merchant.
  • ❌ Does not fire: a GHS 5,000 payment at a supermarket.

Parameters

Parameter Meaning How to tune
MCC list Which merchant categories count as high-risk (a tenant list) Based on your risk appetite and scheme guidance
threshold_amount Amount above which the rule fires Can be low; these categories carry inherent risk

Mode: real-time or post-event.

Data it needs: the merchant category code on card transactions.


H5 Account takeover: profile change then payout

Section titled “H5 Account takeover: profile change then payout”

What it looks for: a change to the account’s contact details or credentials (email, phone number, password) followed soon after by a payout. Fraudsters who take over an account change the contact details first, so the real owner stops getting alerts.

Example

With window_hours 24:

  • ✅ Fires: the email address is changed at 20:10; a GHS 7,500 transfer to a new payee is attempted at 20:25.
  • ❌ Does not fire: a password change, then no unusual payments for two days.

Parameters

Parameter Meaning How to tune
window_hours How long after a profile change payouts are watched 24–72 hours

False positives: customers who update their details and then make a normal payment. A step_up through the old, trusted contact channel is the safest response.

Data it needs: profile-change account events (phone_change, email_change, password_reset and so on), sent as they happen.


What it looks for: cheques paid into an account, and most of the value taken out in cash within two days. That is the shape of cheque fraud and kiting: get the cash out before the cheque can be returned unpaid.

Example

With the defaults (min_cheques 20,000, ratio 0.7):

  • ✅ Fires: cheques of GHS 18,000 and GHS 12,000 are credited on Monday; on Tuesday the customer withdraws GHS 25,000 in cash, which is 83% of the GHS 30,000 credited.
  • ❌ Does not fire: the same cheques, then card payments and transfers over the following weeks.

Parameters

Parameter Meaning How to tune
min_cheques Cheque credits in the last 48 hours, at least (base currency)
ratio The cash withdrawal as a share of those cheque credits 0.5–0.9 are typical values to test

Mode and pack: post-event, in gh-bank 1.0.0. Post-event means it alerts after the withdrawal; it can’t stop it.

False positives: businesses that deposit customer cheques and withdraw cash for wages. Check the customer’s declared activity, and use a suppression for a known pattern.

Data it needs: cheque credits sent with channel: cheque and direction in, and the withdrawal with type withdrawal or cash_out.


What it looks for: a large instant transfer to someone the customer has never paid. It is the shape of authorised push-payment scams and impersonation fraud, where a customer is persuaded to send money themselves and it is gone in seconds.

Example

With the default threshold of 20,000:

  • ✅ Fires: a customer sends GHS 45,000 by GIP to an account they have never paid, after a call from someone claiming to be the bank’s fraud team.
  • ❌ Does not fire: GHS 45,000 by GIP to the customer’s own landlord, paid every month.

Parameters

Parameter Meaning How to tune
threshold Amount at or above (base currency)

Mode and pack: post-event, in gh-bank 1.0.0. Because it is post-event, it alerts after the money has gone, so analysts can contact the customer and try a recall. To stop such payments before they leave, a similar check can run as a real-time rule in the decision API: see H2.

False positives: first payments to a new supplier, a car dealer or a school. A call to the customer usually settles it.

Data it needs: channel: instant_payment on GIP transfers, and the counterparty on each, so SpeculaPro can tell whether the customer has paid them before.