Rules
Custom rules, the blocklist and the allowlist, and which one wins.
The score decides on its own most of the time. On top of it sit three deterministic overrides, for the cases where you know something the signals cannot see: a customer you trust, a number you have seen defraud you, a bracket of payments you want challenged whatever they score.
All three are Shield Advanced, with one exception: a customer you allowed from the review queue stays allowed on every plan. None of it runs unless your own Shield configuration is on.
The order a decision is settled in
Nothing here replaces the score, everything here acts after it. Reading the sequence once explains every outcome on this page.
| Step | What happens |
|---|---|
| 1 | The signals are collected and the score is computed |
| 2 | A blocklist or sanctions match forces the score to 100 |
| 3 | The score is compared against your thresholds, giving allow, review or block |
| 4 | Your rules are walked in order, and the first matching live rule decides |
| 5 | That rule's action is applied on top of the score decision |
Step 4 is where "first match wins" applies, and only there. Step 2 is why an allow rule cannot rescue a blocklisted customer.
What a rule is made of
namestringrequiredconditionsarrayrequiredactionenumrequiredmodeenumrequireddefault : livepriorityintegeroptionaldefault : ten above your highestenabledbooleanoptionaldefault : trueEvery rule also carries a hit counter and the time it last matched, both updated on every payment it hits, test rules included. That counter is the honest measure of whether a rule is doing anything.
The eight fields
The builder is a closed catalogue. There is no expression language and no access to anything not on this list, including the risk score itself.
| Field | Type | Operators |
|---|---|---|
| Transaction amount | number | gt gte lt lte eq |
| Currency | list | in not.in |
| Payment method | list | in not.in |
| Customer email | text | eq contains matches |
| Customer phone | list | in not.in |
| IP country | list | in not.in |
| First transaction from this customer | boolean | is_true is_false |
| Matches an entry in the blocklist | boolean | is_true |
A few behaviours are worth knowing before you write anything.
The amount is in major units, the same units as the payment, so 50000 is fifty thousand XAF.
Payment method is the channel's type, not its slug: card, mobile_money, wallet, crypto,
ussd, voucher, bnpl, redirect, and three bank types, bank.transfer, bank.debit and
bank.redirect. There is no plain bank: a rule on bank payments lists the bank types it means.
It is the one place in the product where a product-level word is the right answer.
Phone numbers are compared on their digits alone, so +237 6 70 00 00 00 and 237670000000
are the same value. Email comparison is case-insensitive, and so is matches, where * is the
only wildcard and it is anchored at both ends.
First transaction means this customer has never had a live payment succeed with you before. A payment with no customer attached counts as a first.
The four actions
What an action does depends on what the score already decided, which is the part that catches people out.
| Action | Effect |
|---|---|
block | The payment is refused, whatever it scored |
review | The payment is flagged, unless the score already blocked it. A review never rescues a block |
challenge_3ds | 3D Secure is requested on a card payment. The allow, review or block decision is unchanged |
allow | The score decision is dropped and the payment goes through, except against your blocklist or a sanctions match |
Allow is the only action that can undo a decision
And it deliberately cannot undo all of them. A payment matching your blocklist, or a sanctions watchlist, keeps its refusal no matter how many allow rules point at it. An explicit deny always wins over an explicit allow, which is the only arrangement that makes a blocklist worth anything.
challenge_3ds only reaches the issuer through providers that support it. Everywhere else the
provider applies its own 3D Secure policy and the rule changes nothing.
Test mode
A rule in test mode is evaluated on every live payment, the ones a live rule already decided included, counts its hits, and is recorded on the payment as having matched, without ever deciding anything. It is the closest thing Shield has to a dry run, and it is the only one: there is still no sandbox.
The way to use it is to write the rule you are considering in test mode, leave it for a week, and read its hit counter. A rule that would have blocked four hundred payments is a rule you want to know about before it is live.
The blocklist
An entry on the blocklist forces the score to 100, which means a refusal on any threshold you could possibly set. It is the bluntest thing in Shield and the only one that needs no rule.
typeenumrequiredvaluestringrequired+ and its 6 to 15 digits (so +237 670 00 00 00 and 237670000000 are one entry), an IP is one IPv4 or IPv6 address (no range), a country is an ISO 3166-1 alpha-2 code, upper-cased, and a card BIN is 6 to 8 digits, matched against the start of the card. A value that cannot be one of its type is refused with a 422.reasonstringoptionalA country entry is matched against the country of the payer's IP address, not their phone number
and not the currency. Blocking NG stops every payment made from a Nigerian IP, including your own
Nigerian customers paying while they are there.
ip and country entries are matched against the payer's own address. If you charge from your
server with a secret key, send the payer's
Wajub.signals() token with every charge.
The list only applies while it is switched on
A blocklist entry does nothing unless Shield and blocklist_enabled are both on in your
settings, the entries Shield adds after a lost dispute included. Adding an entry from the
Dashboard switches the list on for you, adding one through the API does not.
A card_bin entry matches every card whose number starts with those digits. A match is refused,
or sent to your review queue, where you can refund it and block the payer.
The blocklist is the one part of this page with an API.
https://api.wajub.com/shield/blocklistThe type and the value are required, the reason is yours to fill in and is what the decision records when the entry matches.
curl https://api.wajub.com/shield/blocklist \
-H "Authorization: sk.xxxxxxxxxxxxxxxx…" \
-H "Content-Type: application/json" \
-d '{
"type": "phone",
"value": "+237690000000",
"reason": "confirmed fraud, chargeback March"
}'The full list comes back on every write, so you never need a second call to see the result.
The allowlist
Allowing a customer creates an allow rule that runs before your other rules. The Dashboard writes one for you when you close a review with allow this customer: one rule per identifier, matching the email exactly or the phone digit for digit.
That rule is the one part of this page that works on every plan. Without Shield Advanced it is still read on each payment while every other rule stays dormant, and Shield, lists shows the customers you allowed and removes one in a click. It is how you release a payer Shield refused by mistake.
What counts is narrow on purpose: a live allow rule with a single condition, the email with eq
or the phone with in. With Shield Advanced you can write the same thing by hand, and you should
keep it just as narrow. An allow rule on contains rather than eq would let
[email protected] through along with [email protected], and it is a custom rule like any
other: it stops being read if you leave Shield Advanced.
What a rule cannot do
It cannot see the score. There is no risk score field in the catalogue, so you cannot write "block anything over 60 that is also a first payment". Thresholds are the only lever on the score.
It cannot combine conditions with OR. Every condition in a rule must hold. Two alternatives are two rules.
It cannot read your metadata. Nothing you send on the payment, beyond the amount, the currency, the channel and the customer's email and phone, is visible to a rule.
It cannot lower a payment out of a blocklist. That is step 2 above, and it is settled before rules are read at all.
Related pages