Real-time decisions
In short
Section titled “In short”Most of SpeculaPro looks at payments after they happen: transactions arrive, rules run, and suspicious activity becomes an alert for your compliance team. That is post-event monitoring, and it is what anti-money-laundering work needs.
Fraud is different. Once a fraudster has emptied a wallet, an alert an hour later is too late. A real-time decision lets your payment system ask SpeculaPro “is this payment safe?” before the money moves, and act on the answer while the customer is still on the payment screen.
| Post-event monitoring | Real-time decision | |
|---|---|---|
| When | After the payment, seconds to minutes later | Before the payment completes, within a time budget you set |
| Sent with | POST /api/v1/ingest/transactions (or a file import) |
POST /api/v1/decisions |
| Rules that run | Your post-event rules | Your real-time rules, then your post-event rules afterwards |
| What you get back | accepted |
An answer: allow, step_up, review or block, with the reasons |
| What it raises | AML alerts | Fraud alerts, as well as any AML alerts |
A payment sent for a decision is also recorded and monitored like any other transaction, so you never send it twice.
The four answers
Section titled “The four answers”| Answer | On screen | What it means | What your payment system typically does |
|---|---|---|---|
allow |
Allowed | Nothing that needs action | Let the payment go through |
step_up |
Step-up | Possibly not the real customer | Challenge them (a one-time code, PIN, 3-D Secure or biometrics) and let it through only if they pass |
review |
Held for review | Suspicious enough for a person to look at | Hold the payment until your fraud team decides |
block |
Blocked | Very likely fraud | Decline it |
The answers are listed weakest to strongest. SpeculaPro never moves money and never contacts the customer: your system acts on the answer. Decide what it does for each one before you go live.
How SpeculaPro works out the answer
Section titled “How SpeculaPro works out the answer”Every payment is checked against your workspace’s real-time rules: rules marked Real-time on
the Rules page, in their live slot. Each rule that fires has an action (block, review,
step_up, allow, tag or score_only) and a score from 0 to 100.
- The strongest action wins.
blockbeatsreview, which beatsstep_up. If no rule asks for one of them, the answer isallow. - An
allowrule waives a review or a step-up, never a block. Anallowrule says “this is known to be fine”, for example a trusted beneficiary. It can’t override a rule that blocks. - Scores combine like independent chances. Two rules scoring 50 make 75, not 100, and the total
never passes 100. Rules set to
tagorscore_onlyadd to the score without changing the answer by themselves;allowrules don’t add to it. - Your score thresholds can raise the answer. If your workspace’s
decision policy sets a block or
review score, a payment whose combined score reaches it is at least blocked or reviewed,
whatever the individual actions say. An
allowrule waives the review threshold, but not the block threshold.
When the answer isn’t simply the strongest rule’s action, the response’s note says why, for
example an allow rule waived review or combined score 82.0 reached the block threshold 80.
- Sanctions screening can raise the answer once more. See Sanctions screening below.
Shadow rules run too, but never change the answer: what they would have done is recorded so you can compare before switching them on. See Shadow mode.
Worked example
Section titled “Worked example”Ama sends GHS 2,400 from her wallet. Her SIM card was replaced yesterday.
| Rule that fired | Action | Score |
|---|---|---|
Payout soon after a SIM swap (gh.sim_swap_payout) |
block |
85 |
The answer is block, with a score of 85 and one reason: SIM swapped 48 hours or less before this
payout of GHS 2,400. Ama’s wallet provider declines the payment and asks her to visit a branch.
Sanctions screening
Section titled “Sanctions screening”Screening checks your customers and counterparties against sanctions lists in the background, and your reviewers decide each potential match. A real-time decision reads the result for both sides of the payment, the customer and the counterparty, and applies your workspace’s screening policy after the rules. A counterparty with no stored screening result, which is the case for the first payment to them, has its name checked against your sanctions lists inside the decision: see A counterparty seen for the first time.
| What screening knows about the customer or counterparty | Setting | Default answer |
|---|---|---|
| A reviewer confirmed a sanctions match, and the Sanctioned designation it set is still in force | Confirmed sanctions match | block |
| A potential sanctions match is open: nobody has decided it yet (a decision waiting for a second person counts as open). This includes a match the decision has just found itself, for a counterparty with no stored result | Open potential match | review |
Each setting can be Block, Review or Leave it to the rules. Set them under Settings → Workspace → Decision policy.
Things to know:
- It only ever raises the answer. A payment the rules already block stays blocked.
- No
allowrule waives it. A trusted-beneficiary rule can’t let a payment to a confirmed sanctions match through. - The note says why, for example the counterparty is a confirmed sanctions match: the
screening policy blocks or the customer has an open potential sanctions match: the screening
policy sends for review. It adds no reason and no score:
reasonsstill lists only rules. - Only sanctions matches count. A PEP or adverse-media match doesn’t change the answer here. Once confirmed, it sets a designation that your designation rules read.
- A confirmed match stops counting when its designation is revoked or expires.
- A reviewer’s decision takes up to about 30 seconds to reach decisions, because customer and
counterparty details are cached for that long (the operator’s
SP_DECISION_PROFILE_TTL). - Only a counterparty with nothing stored is screened on the spot. For everyone else the decision reads the matches already recorded. See A counterparty seen for the first time.
- A degraded decision still applies confirmed matches. When the checks can’t finish in time,
the failure policy below answers, raised to your Confirmed sanctions match setting if the
customer or the counterparty is a confirmed sanctions match. So failing open doesn’t let that
payment through. A degraded decision reads nothing new, so each decision process keeps your
workspace’s confirmed sanctions matches in memory and re-reads them every few seconds. What
remains:
- A match confirmed, or a designation revoked, in the last few seconds may not be in that
copy yet (it is re-read at half the operator’s
SP_DECISION_STATE_TTL, 5 seconds by default). If the database can’t be reached, the copy stays as it last was. - The copy holds 100,000 parties per workspace. A workspace with more confirmed sanctions matches than that is covered during an outage only for the most recently confirmed 100,000; the rest still block when the checks finish. The operator sees an error in the log and a metric that counts such workspaces.
- A decision process that has just started has no copy for your workspace until it has loaded your rules once. If it can’t, the failure policy answers alone.
- Open potential matches are never applied to a degraded decision. That includes a match found by screening a new counterparty’s name inside the decision: a decision that couldn’t finish its checks may not have screened the name at all.
- A match confirmed, or a designation revoked, in the last few seconds may not be in that
copy yet (it is re-read at half the operator’s
Rules can also read the same state as customer.screening_match and
counterparty.screening_match (none, open or confirmed), in real-time rules only. See the
CEL reference.
A counterparty seen for the first time
Section titled “A counterparty seen for the first time”The first payment to a new counterparty arrives before the background screening has seen them: their record is written after the decision, and the worker screens it some seconds later. So that this payment isn’t decided blind, the decision screens the counterparty’s name itself.
| When | Only when nothing is stored for the counterparty: the worker hasn’t screened them and no match is on record. A counterparty the worker has screened, or whose match a reviewer cleared or confirmed, is never screened again by a decision |
| Who | The counterparty only: the payee of an outgoing payment, the payer of an incoming one. The payment must carry their name; a counterparty sent without a name isn’t screened here. The customer is never screened inside a decision: a customer is known by ID and is screened when their record arrives |
| Against what | The lists your workspace screens against under Settings → Screening, with the same matching and the same threshold as the background screening. It runs in the decision process’s memory: no database query and no network call |
| Not | Screening providers. They are remote services and are never called from a decision. The worker calls them when it screens the counterparty afterwards |
| What a match does | A potential match against a sanctions list counts as an open match: your Open potential match setting applies (review by default) and counterparty.screening_match reads open. A match against a list of another kind, such as a watch list of your own, doesn’t change the answer |
| What is recorded | The match goes to the Screening queue for a reviewer, written just after the answer is returned. It is the same potential match the worker would have raised, and it is raised once: several decisions at the same moment, and the worker’s own screening a little later, all land on the same match |
Nothing here needs switching on. It follows your screening settings: with screening off for the workspace, or Counterparties unticked, no name is screened inside a decision.
Things to know:
- Later payments to the same counterparty read the stored match, like any other open match, until a reviewer decides it.
- Changed lists and settings reach decisions within about a minute. Each decision process keeps your workspace’s screening settings and the list index in memory and refreshes them in the background.
- A decision process that has no list loaded screens nothing. That is the case when the
installation has not fetched or imported any list yet, and on a self-hosted installation whose
operator has switched screening off (
SP_SCREENING_ENABLED=false). - If the match can’t be written (the database is unreachable, or the queue of matches waiting to be written is full), the answer to the payment is unaffected and the worker records the match when it screens the counterparty.
When the checks can’t finish in time
Section titled “When the checks can’t finish in time”Each workspace sets a time budget, 150 milliseconds unless you change it. If the checks can’t
finish inside it, because part of the system is slow, unavailable or overloaded, SpeculaPro
doesn’t keep your customer waiting. It answers with your failure policy instead and marks the
answer degraded:
| Policy | Answer | What happens next |
|---|---|---|
| Fail open (the default) | allow, or what your Confirmed sanctions match setting says (block by default) when a party is already known to be a confirmed sanctions match |
The payment goes through unless it was raised. A fraud alert is raised so someone checks it afterwards |
| Fail closed | review |
The payment is held for your team. A fraud alert is raised so someone reviews it and releases or declines it in your own systems |
In the alert, either kind appears as the hit Decided without real-time checks (degraded), rule key
system.degraded_decision, and its explanation says which policy answered. When a known confirmed
sanctions match raised the answer, the decision’s note says so, for example checks didn’t finish
(timeout); fail-open policy applied; the counterparty is a confirmed sanctions match: the screening
policy blocks.
Choose the policy deliberately, with your risk committee: see Workspace settings: decision policy.
Fraud alerts
Section titled “Fraud alerts”Rules don’t only answer: they also leave evidence.
- Each real-time rule that fires is recorded as a hit, like a post-event rule’s hit, with its explanation and the feature values it saw.
- Hits from rules whose action is
block,revieworstep_upraise a fraud alert on the customer (or the account or counterparty the rule is about). So does every degraded answer, fail-open or fail-closed. - Fraud alerts are kept apart from AML alerts: a customer can have one open fraud alert and one
open AML alert at the same time. Both appear in the same alert queue,
where a fraud alert carries a FRAUD tag, and its Rules list names the real-time rules,
such as
fraud.card_testing. - Cases are kept apart in the same way. If the customer already has an active fraud case, new fraud alerts join it; they never join an AML case, and AML alerts never join a fraud case.
After its real-time check, the payment also goes through your post-event rules like any other transaction, so a decided payment can raise an AML alert as well.
Where to see decisions
Section titled “Where to see decisions”- The Decisions page lists every decision, with its reasons, and lets you record what really happened. See The Decisions page.
- The Command center shows a summary strip of the last 24 hours. See Command center: real-time decisions.
- Each real-time rule’s page shows how often it fired and how its hits were labelled. See Feedback and fraud labels.