Shield

Rules: tune, simulate, deploy

A compliance team can change a rule, see what it would have done to the last month of transactions, and put it live — without a code release.

PilotShield is in pilot and enabled per account on request. Without it every Shield endpoint answers 404.

Rules

Each rule has parameters (for example an amount threshold in AZN qəpik: 500000 = 5,000.00 AZN), a base score, a default outcome and a mode: active (affects outcomes), shadow (recorded only) or disabled. A rule that lacks the data it needs does not fire. The sanctions and PEP rules (SAN_01, SAN_02, CMP_01) are always on, in every ruleset; only their name and description can change.

List them with GET /v1/risk/rules; the fields a rule can read and the operators it can use are at GET /v1/risk/schema/events.

Tune → simulate → deploy

1

Simulate the change

Send the change (only the fields you change) and a window of 1–90 days (default 30). Shield re-evaluates every decision in that window from its stored features, twice: with today's rules, and with today's rules plus your change. Nothing changes.
2

Read the comparison

Once Completed: how often the rule fires before and after, outcome counts before and after, the transitions (for example review → clear), up to 25 changed decisions, and caveats. Once-a-month AML rules count condition matches, not firings.
3

Deploy exactly what was simulated

Send the same change with its simulationId, a rationale, the approver and the version it ran against. The API refuses it if the simulation is not completed (SIMULATION_NOT_COMPLETED), ran on another version (SIMULATION_STALE) or simulated a different change (SIMULATION_MISMATCH). The next decision uses the new version.
# 1. Simulate: raise TXN_01's threshold to 8,000 AZN over the last 30 days
curl -X POST https://api.verifex.dev/v1/risk/rules/RULE_GUID/simulate \
  -H "Authorization: Bearer vfx_your_api_key" -H "Content-Type: application/json" \
  -d '{ "params": { "threshold": 800000 }, "days": 30 }'
# → 202 { "simulationId": "sim_…", "status": "Queued", "baseVersion": 1 }

# 2. Poll until "status": "Completed"
curl https://api.verifex.dev/v1/risk/simulations/sim_… \
  -H "Authorization: Bearer vfx_your_api_key"

# 3. Deploy exactly the simulated change
curl -X PATCH https://api.verifex.dev/v1/risk/rules/RULE_GUID \
  -H "Authorization: Bearer vfx_your_api_key" -H "Content-Type: application/json" \
  -d '{ "params": { "threshold": 800000 }, "simulationId": "sim_…",
        "rationale": "Raise the high-value threshold after a 30-day simulation",
        "approvedBy": "Head of Compliance", "expectedVersion": 1 }'

Info

At most 3 simulations per account can be queued or running (429 SIMULATION_LIMIT). The dashboard's rule page does the same three steps with buttons. On the compatible API: POST /api/General/Transaction/Rule/{guid}/Simulate and PUT …/Rule/{guid} with simulationId.

The Parameter Register

Every change is a new version with who made it, who approved it and why (GET /v1/risk/rules/{id}/versions), an audit entry naming the simulation, and a rule.changed webhook. Each decision records the rule versions it used, so an old decision replays with the rules of its day.

Alarm thresholds

GET / PUT /v1/risk/alarm-thresholds with veryLow, low, medium, high, critical (non-decreasing): a decision's alarm is the highest level whose threshold its totalScore reaches; a total of 0 raises none. Compatible API: General/Transaction/RiskThreshold.

MCC and currency risk

Give merchant category codes and currencies a risk level (1 Low, 2 Medium, 3 High); rules read them as mcc_risk_level and currency_risk_level. Native: PUT /v1/risk/mcc-codes and /v1/risk/currency-risk-levels with { items: [...] }. Compatible: SanctionScanner's .xlsx upload (MCC Code, Name, Description, Risk Level). Invalid rows are skipped and reported. No built-in rule uses these: add a rule that does.

Customer risk score

A registered customer has a risk score that rules read as customer_risk_score. Raise or lower it with a reason (POST /v1/risk/customers/{customer}/risk with { delta, reason }); it never goes below 0, and every change is kept. Its level (VeryLow … Critical) comes from the customer risk thresholds.