Skip to content

Lists in rules

Some rules check a transaction against a list you maintain: high-risk countries, high-risk merchant categories, blocked wallets. The rule’s logic stays the same; you change what’s on the list. A rule reads a list as lists.<key>, for example lists.high_risk_countries.

Rule List key Holds Format of each entry
core.high_risk_jurisdiction (E1) high_risk_countries Countries you treat as high risk Two-letter ISO country code in capitals, such as IR
core.high_risk_mcc (H4) high_risk_mcc Merchant category codes you treat as high risk Four-digit code, such as 7995
fraud.deny_listed_counterparty (F4, real-time) blocked_countries Countries payments must not go to: the rule blocks them Two-letter ISO country code in capitals
fraud.deny_listed_counterparty (F4, real-time) blocked_mcc Merchant categories whose payments are blocked Four-digit code
ghb.correspondent_high_risk (GB5) high_risk_correspondents Correspondent banks you rated high risk in due diligence Item type text: the counterparty’s provider as your transactions carry it, such as a SWIFT BIC. Matched ignoring capitals (since gh-bank 1.1.0)
gh.border_region (E4), optional high_risk_regions Extra towns, districts or regions you treat as high risk, on top of the rule’s own regions parameter Item type text: the area’s name. Matched ignoring case

Entries must match exactly what your transactions carry: country codes are always two capital letters and MCCs are four digits. Correspondent and region names are matched ignoring capitals.

The other 50 shipped rules don’t use lists.

  • lists.<key> is a list of strings: the current entries. Entries with an expiry date in the past are left out.

  • A list the rule names but your workspace hasn’t created yet reads as an empty list, so the rule simply doesn’t fire on it; it doesn’t error. SpeculaPro spots the lists a rule reads when the key is written out, either as lists.my_key or as lists["my_key"]. A key worked out while the rule runs, such as lists[params.list_name], isn’t spotted, and a missing list named that way makes the rule error instead. The shipped rules also guard with has(), which is harmless and keeps them correct on older versions:

    has(lists.high_risk_countries) && txn.counterparty_country in lists.high_risk_countries
  • List changes reach the running post-event rules within about 15 seconds, and real-time decisions within about 10 seconds.

The simplest way is the Lists panel on the Rules page, described step by step in Managing lists. You need lists.manage (in the built-in roles, the MLRO / Compliance officer); anyone with rules.view can read lists. Values are cleaned up as they are added: country codes are upper-cased and must be two letters, merchant category codes must be four digits, and duplicates are skipped.

To script it instead, use the Lists API. Sign in with curl first, as described in Rules API: before you start.

  1. Create the list. The key is what rules read (lists.high_risk_countries), so use the key the rule expects (see the table above):

    Terminal window
    curl -s -b ~/.sp-cookies -H 'Content-Type: application/json' -d '{
    "key": "high_risk_countries",
    "name": "High-risk countries",
    "kind": "reference",
    "item_type": "country",
    "description": "FATF high-risk and increased-monitoring jurisdictions, approved by MLRO 2026-10-09"
    }' "$SP/api/v1/lists"

    201 with the new list’s id. A key that already exists returns 409.

  2. Add the entries, with a note saying where they come from:

    Terminal window
    # The entries below are an EXAMPLE. Use the MLRO's approved list, based on current FATF publications.
    curl -s -b ~/.sp-cookies -H 'Content-Type: application/json' -d '{
    "values": ["KP", "IR", "MM"],
    "note": "FATF list, October 2026 review"
    }' "$SP/api/v1/lists/high_risk_countries/items"
    { "added": 3 }

    Up to 1,000 values per call. Values already on the list are skipped, so added counts only new ones. Country codes are upper-cased for you (ir becomes IR) and must be two letters; merchant category codes must be four digits. If any value is invalid, none are added and the error names the bad value.

  3. Check the result:

    Terminal window
    curl -s -b ~/.sp-cookies "$SP/api/v1/lists"
    curl -s -b ~/.sp-cookies "$SP/api/v1/lists/high_risk_countries/items"

    The first lists every list with items, its number of current entries, and used_by, the rules that read it. used_by shows only rules that are running, so it stays empty until a rule that reads the list is switched on. The second lists the entries, each with its note, who added it and when.

  4. To remove an entry, give its value exactly as it is stored (IR, not ir):

    Terminal window
    curl -s -b ~/.sp-cookies -X DELETE "$SP/api/v1/lists/high_risk_countries/items?value=IR"

    204 when removed, 404 if the value isn’t on the list.

Field Meaning
key What rules read: lists.<key>. 2 to 64 lowercase letters, digits and _
kind allow, deny or reference
item_type country, mcc, customer, account, counterparty, device, ip or text
values The entries, in exactly the format the rule compares against

Every change is recorded in the audit log: list.create, list.add_items (with the values, the note and any end date), list.remove_item, list.item_expiry, list.update and list.delete. That record answers the examiner’s question of why a country was or wasn’t on the list on a given date. See Lists for what each kind of list is for.

  • Review on a timetable. FATF updates its lists several times a year. Put a review in the compliance calendar and record each one.
  • Use expires_at for temporary entries, so they don’t linger after the reason has passed.
  • Never delete history you may need. Instead of removing an entry, set its expires_at to now. The entry stops counting but stays on record.