# AML Transaction Monitoring

AML Transaction Monitoring system enables real-time screening of transactions based on configurable rulesets.  
It processes each transaction live, determines whether to approve, decline, or hold it, and can notify AML officers when a ruleset is triggered.  
An internal AI module calculates a transaction risk score based on Verestro’s proprietary specification, but does not influence the decision-making process yet.

# Introduction

Verestro’s AML Transaction Monitoring is a compliance solution that helps businesses detect and prevent suspicious or fraudulent transactions while maintaining full AML compliance.

The system provides **real-time transaction monitoring** based on configurable rulesets and can use **KYC data**, **end user transaction history**, and **transaction details** to support effective risk management.  
Each customer can define **custom AML rulesets** tailored to their specific risk profile and operational needs.

#### Monitor and control all suspicious transactions in one place

- Define custom rulesets that use transaction data, KYC information, and end user transaction history.
- Specify custom actions for your system to execute when a ruleset is triggered; the action logic remains on your side.
- Send notifications automatically when a transaction matches a defined ruleset.

#### Suspicious entity detection

- The AML system lets you define individuals as fraudsters (blacklist) or as suspected of fraud (greylist) using their personal and address data.
- You can create rulesets that detect such entities and trigger appropriate actions.
- This enables fast identification of fraudsters across all your instances.

#### Handle screening results with human expertise

- The AML system can send notifications when a transaction is flagged by a specific ruleset.
- In the current architecture, the system can create an issue in YouTrack — a tool for managing tasks and incidents.
- These notifications allow authorized staff to review and investigate complex cases that require manual expertise.

<p class="callout info">**Note:** Email notifications are also planned for future releases.</p>

#### Empower your AML process with AI assistance

- The AI module currently provides a numerical risk score for each transaction.
- It is based on a predefined technical specification that assigns risk points to specific transaction data.
- We collaborate with AML specialists to continuously improve the AI model.

<p class="callout info">**Note:** Planned improvements include an AI assistant that will suggest AML ruleset and support human expertise in transaction verification and case assessment.</p>

#### How to connect with us?

There are two integration methods available:

1. Plug &amp; Play Package
2. Standalone REST API Integration

Details of both integration options can be found in the following section: [Quick start guide | Verestro Developer Zone](https://developer.verestro.com/books/aml-transaction-monitoring/page/quick-start-guide).

# Overview

This document provides a high-level overview of the functionalities offered by the AML Transaction Monitoring service.  
AML Transaction Monitoring allows you to define rulesets that process transactions in real time.  
This document explains in detail how to construct AML rulesets and describes the available conditions that can be used within those rulesets.  
Other configurable system elements required for a complete AML Transaction Monitoring setup are also described.

## Architecture

### C4 Context diagram

[![12.png](https://developer.verestro.com/uploads/images/gallery/2025-11/scaled-1680-/12.png)](https://developer.verestro.com/uploads/images/gallery/2025-11/12.png)

## Ruleset configuration elements

Elements used to configure the logic for transaction processing are:

<table border="1" id="bkmrk-element-name-element" style="border-collapse: collapse; width: 100%; height: 249.193px;"><tbody><tr style="height: 49.1927px;"><td bgcolor="#1C1E3F" style="width: 20%; height: 49.1927px;"><span style="color: #ecf0f1;">**Element name**</span></td><td bgcolor="#1C1E3F" style="width: 80%; height: 49.1927px;"><span style="color: #ecf0f1;">**Element description**</span></td></tr><tr style="height: 40px;"><td style="width: 20%; height: 40px;"><span style="color: rgb(68, 68, 68);">**Ruleset**</span></td><td style="width: 80%; height: 40px;"><span style="color: rgb(68, 68, 68); background-color: rgb(255, 255, 255);"><span style="color: rgb(68, 68, 68); background-color: rgb(255, 255, 255);">A set of conditions evaluated during transaction processing, and instructions that the system considers when returning the transaction outcome.</span></span></td></tr><tr style="height: 60px;"><td style="width: 20%; height: 60px;"><span style="color: rgb(68, 68, 68);">**Action**</span></td><td style="width: 80%; height: 60px;"><span style="color: rgb(68, 68, 68); background-color: rgb(255, 255, 255);">Returned by the engine when processing a transaction; actions are interpreted and handled by the service requesting AML verification.</span></td></tr><tr style="height: 40px;"><td style="width: 20%; height: 40px;"><span style="color: rgb(68, 68, 68);">**Value set**</span></td><td style="width: 80%; height: 40px;"><span style="color: rgb(68, 68, 68); background-color: rgb(255, 255, 255);">Helper variables that let you define sets of data, such as a list of high-risk countries.</span></td></tr></tbody></table>

The following sections describe each of these elements in detail.

### Ruleset

A ruleset defines a set of conditions to check during transaction monitoring and the outcomes to apply when a transaction matches those conditions.  
When a transaction is processed, all enabled rulesets are applied to see if the transaction matches their criteria.

Each ruleset consists of:

- a ruleset name,
- logic conditions checked by the processing engine,
- a trigger that defines the outcome when the ruleset is matched.

#### Condition types

Conditions define what the ruleset checks when the AML engine processes a transaction. Each ruleset can contain one or more conditions, combined with logical operators (`AND` / `OR`). The engine evaluates these conditions and returns a single decision for the transaction. The following types of conditions are supported:

<table border="1" id="bkmrk-condition-name-condi" style="border-collapse: collapse; width: 100%;"><tbody><tr><td bgcolor="#1C1E3F" style="width: 26.9338%;"><span style="color: #ecf0f1;">**Condition name**</span></td><td bgcolor="#1C1E3F" style="width: 73.0662%;"><span style="color: #ecf0f1;">**Condition description**</span></td></tr><tr><td><span style="color: rgb(68, 68, 68);">**AND / OR**</span></td><td><span style="color: rgb(68, 68, 68);">Group multiple conditions:  
`AND` means all conditions must be true,   
`OR` means at least one must be true.</span></td></tr><tr><td><span style="color: rgb(68, 68, 68);">**request\_property\_check**</span></td><td><span style="color: rgb(68, 68, 68);">Compares a specific field from the transaction request (for example, amount, currency or transaction country) to a value or list of values.</span></td></tr><tr><td><span style="color: rgb(68, 68, 68);">**kyc\_property\_check**</span></td><td><span style="color: rgb(68, 68, 68);">Compares a property from the end user’s KYC record, such as risk level or nationality, to a value or list of values.</span></td></tr><tr><td><span style="color: rgb(68, 68, 68);">**transaction\_volume\_check**</span></td><td><span style="color: rgb(68, 68, 68);">Evaluates the cumulative transaction volume over a defined period and scope (e.g. by end user, card, balance or corporation) and can be grouped by merchant or country.</span></td></tr><tr><td><span style="color: rgb(68, 68, 68);">**transaction\_quantity\_check**</span></td><td><span style="color: rgb(68, 68, 68);">Evaluates the number of transactions over a defined period and scope, also grouped by merchant or country.</span></td></tr><tr><td><span style="color: rgb(68, 68, 68);">**blacklist\_check**</span></td><td><span style="color: rgb(68, 68, 68);">Checks whether certain end user or transaction values (e.g. PESEL, IBAN, name) match entries in a predefined blacklist.</span></td></tr><tr><td><span style="color: rgb(68, 68, 68);">**greylist\_check**</span></td><td><span style="color: rgb(68, 68, 68);">Similar to `blacklist_check`, but matches data against a greylist of entities that are considered suspicious but not definitively fraudulent.</span></td></tr><tr><td><span style="color: rgb(68, 68, 68);">**compare\_with\_last\_transaction**</span></td><td><span style="color: rgb(68, 68, 68);">Compares fields from the current transaction with those from the last transaction within a specified time window (e.g. 5 minutes) and context (card, balance or balance owner).</span></td></tr></tbody></table>

Each condition uses comparators (e.g. `=`, `!=`, `>`, `>=`, `<`, `<=`, `IN`, `NIN`, `CONTAINS`) to compare values. You can also refer to predefined *value sets* when supplying a list of values (for example, a set of high‑risk countries).

<p class="callout info">**Info:** We continuously develop new condition types to address all business needs related to AML transaction monitoring.</p>

<p class="callout success">**Tip:** In order to set up AML rulesets, check out **[Technical Documentation – AML Ruleset Definition Language](https://developer.verestro.com/books/aml-transaction-monitoring/page/technical-documentation-aml-ruleset-definition-language "Technical documentation - DSL schema documentation for transaction rules")**</p>

#### Trigger types

A trigger defines the outcome when a ruleset is matched during transaction processing.  
You can combine actions and alerts with a decision in a single trigger block.  
There are three trigger types:

<table border="1" id="bkmrk-trigger-type-trigger" style="border-collapse: collapse; width: 100%; height: 186.375px;"><tbody><tr style="height: 29.7969px;"><td bgcolor="#1C1E3F" style="width: 18.631%; height: 29.7969px;"><span style="color: #ecf0f1;">**Trigger type**</span></td><td bgcolor="#1C1E3F" style="width: 81.4882%; height: 29.7969px;"><span style="color: #ecf0f1;">**Trigger description**</span></td></tr><tr style="height: 46.5938px;"><td style="height: 46.5938px;"><span style="color: rgb(68, 68, 68);">**Decision (required)**</span></td><td style="height: 46.5938px;"><span style="color: rgb(68, 68, 68);">The main result of single ruleset processing. You set it to one of: `APPROVED`, `DECLINED`, or `ON_HOLD`. Only one decision is returned for the whole transaction, even if multiple rulesets match.</span></td></tr><tr style="height: 63.3906px;"><td style="height: 63.3906px;"><span style="color: rgb(68, 68, 68);">**Actions (optional)**</span></td><td style="height: 63.3906px;"><span style="color: rgb(68, 68, 68);">Actions are instructions returned by the engine and executed by the requesting system. Example action: block an end user.  
Actions must be defined in advance in your system or via API.</span></td></tr><tr style="height: 46.5938px;"><td style="height: 46.5938px;"><span style="color: rgb(68, 68, 68);">**Alert (optional)**</span></td><td style="height: 46.5938px;"><span style="color: rgb(68, 68, 68);">Alerts are notifications sent to selected channels (for example: `YouTrack ticket`) when a ruleset is matched. You can use alerts to inform AML officers about suspicious activity.</span></td></tr></tbody></table>

### Action

An action is an instruction returned by the AML engine when a ruleset is triggered.  
Actions define additional operations that should be performed by the system requesting AML verification.

Examples of actions:

- Block an end user
- Block an account

Actions are optional and must be defined in advance via GUI or via API.

<p class="callout warning">**Warning:** The AML system only allows you to define and return actions when processing a transaction. The logic for executing each action is the responsibility of the system that receives the action from the AML engine. </p>

<p class="callout warning">**Warning:** Before using actions in AML rulesets, make sure they are defined in the system.</p>

### Value set

A value set is a helper list you can use in AML rulesets to simplify configuration and maintenance.  
Value sets let you store reusable sets of values, such as lists of high-risk countries, transaction types, or merchants.  
You can reference a value set in any ruleset condition, instead of listing all the values every time.

Examples of value sets:

- List of high-risk countries
- List of blocked merchants
- List of suspicious transaction types

Value sets are optional. You define them in the [administration panel](https://developer.verestro.com/books/administration-panel) or via API, and update them as your risk policies change.

<p class="callout warning">**Warning:** Before using value set in AML rulesets, make sure they are defined in the system.</p>

## Watchlist management

The AML system supports two types of watchlists for identifying suspicious end users.

1. **Blacklist** – designed to store end users confirmed or proven to be involved in fraudulent activity.
2. **Greylist** – designed to store end users suspected of fraudulent behavior but not yet confirmed.

Managing watchlists involves adding end users by their personal and address data. End users can also be removed from a list at any time.  
Entries on these lists are automatically verified when the `blacklist_check` or `greylist_check` condition is used in AML rulesets.

#### Purpose and benefits

1. **Cross-instance fraud detection** - with properly defined AML rulesets, the system can identify and block a known fraudulent end user across all BIN sponsor instances. This is possible because verification relies on personal and address data instead of instance-specific end user identifiers.
2. **Monitoring suspicious end users** - using greylists, AML operators can add end users suspected of fraudulent activity and monitor their presence across different instances. Configured AML rulesets can trigger an alert when a transaction involves an end user found on the greylist.

## Alerts

When defining an AML ruleset, the operator configures how alerts related to that ruleset should be sent. The system sends an alert according to the defined alert configuration when a transaction matches the AML ruleset.

#### Alert configuration

Each AML ruleset can define how alerts are sent when triggered.  
The alert configuration includes following key parameters:

<table border="1" id="bkmrk-alert-parameters" style="border-collapse: collapse; width: 100%;"><tbody><tr><td bgcolor="#1C1E3F" style="width: 25%;"><span style="color: #ecf0f1;">**Alert parameter**</span></td><td bgcolor="#1C1E3F" style="width: 75%;"><span style="color: #ecf0f1;">**Alert parameter description**</span></td></tr><tr><td><span style="color: rgb(68, 68, 68);">**channel**</span></td><td><span style="color: rgb(68, 68, 68);">Defines where the alert should be sent. Currently, the supported channel is `YOUTRACK_TICKET`, which creates a new issue in the predefined YouTrack project.</span></td></tr><tr><td><span style="color: rgb(68, 68, 68);">**cooldown\_period**</span></td><td><span style="color: rgb(68, 68, 68);">Defines the minimum time (in seconds) between two identical alerts generated by the same ruleset for the same end user or corporation. This prevents multiple alerts of the same type from being created within a short time window.</span></td></tr></tbody></table>

These parameters are defined inside the `alert` block of the AML ruleset configuration.

<p class="callout info">**Info:** We plan to extend the alerting mechanism in the future by adding new alert channels, such as <span style="text-decoration: underline;">email notifications</span> sent to the person/people responsible for manual AML case review when required.</p>

## AI risk scoring

Each verified transaction is also analyzed by a machine learning–based system that calculates the probability of fraud.  
The result is a numerical score ranging from **0 to 100.**

- 0 means the transaction is considered completely safe
- **100** represents the highest possible fraud probability assigned by the system

<p class="callout warning">**Warning:** At this stage, the AI score is not used in any way when making AML decisions about a transaction.  
All decisions are made solely based on the outcomes of individual AML rulesets that process the transaction.</p>

## Transaction evaluation process

<article class="text-token-text-primary w-full focus:outline-none [--shadow-height:45px] has-data-writing-block:pointer-events-none has-data-writing-block:-mt-(--shadow-height) has-data-writing-block:pt-(--shadow-height) [&:has([data-writing-block])>*]:pointer-events-auto [content-visibility:auto] supports-[content-visibility:auto]:[contain-intrinsic-size:auto_100lvh] scroll-mt-[calc(var(--header-height)+min(200px,max(70px,20svh)))]" data-scroll-anchor="true" data-testid="conversation-turn-48" data-turn="assistant" data-turn-id="request-WEB:184a7657-2740-4a97-9982-07b6b86720dd-76" dir="auto" id="bkmrk-to-enable-the-system" tabindex="-1">To enable the system to check transactions against AML rulesets, the rulesets must first be defined.  
This can be done through the graphical interface available in the [**Administration Panel**](https://developer.verestro.com/books/administration-panel).

Once the rulesets are configured, the transaction processing system must start calling the AML service using the `aml-verify` endpoint.  
When the AML system receives a request on this endpoint, it begins evaluating the transaction against all rulesets defined in the system.

As a result of this evaluation, the system returns:

<div class="text-base my-auto mx-auto pb-10 [--thread-content-margin:--spacing(4)] thread-sm:[--thread-content-margin:--spacing(6)] thread-lg:[--thread-content-margin:--spacing(16)] px-(--thread-content-margin)"><div class="[--thread-content-max-width:40rem] thread-lg:[--thread-content-max-width:48rem] mx-auto max-w-(--thread-content-max-width) flex-1 group/turn-messages focus-visible:outline-hidden relative flex w-full min-w-0 flex-col agent-turn" tabindex="-1"><div class="flex max-w-full flex-col grow"><div class="min-h-8 text-message relative flex w-full flex-col items-end gap-2 text-start break-words whitespace-normal [.text-message+&]:mt-1" data-message-author-role="assistant" data-message-id="94640577-56b3-4bf4-b64f-e0ff4c76c083" data-message-model-slug="gpt-5" dir="auto"><div class="flex w-full flex-col gap-1 empty:hidden first:pt-[1px]"><div class="markdown prose dark:prose-invert w-full break-words dark markdown-new-styling">- **verificationId** – a unique identifier of the verification entity,
- **result** – a single decision for the transaction,
- **actions** – an array of actions returned by the matching rulesets.

</div></div></div></div></div></div>The AML system always returns all actions triggered by the rulesets, but only one final decision.

<p class="callout warning">**Warning: decision return logic** If all rulesets return `APPROVED`, the final result is `APPROVED`.  
If at least one ruleset returns `DECLINED`, the final result is `DECLINED`.  
If no ruleset returns `DECLINED` but at least one returns `ON_HOLD`, the final result is `ON_HOLD`.</p>

</article>

# Quick start guide

To start using Verestro AML Transaction Monitoring, select one of the following integration methods:

##### **Option 1 – Plug &amp; play package**

Get started instantly by choosing the **[Antaca](https://developer.verestro.com/books/card-issuing-and-core-banking) + AML Transaction Monitoring + [Administration Panel](https://developer.verestro.com/books/administration-panel) bundle**.  
No development or integration is needed — just define your AML rulesets in the [Verestro Administration Panel](https://developer.verestro.com/books/administration-panel), and the system will handle all transaction monitoring automatically.

<p class="callout success">**Advantages:** - No integration or development required  
- Fastest time-to-market  
- All modules work out-of-the-box  
- Centralized management via [Administration Panel](https://developer.verestro.com/books/administration-panel)  
- Technical support included  
</p>

##### **Option 2 – Standalone REST API integration**

Integrate AML Transaction Monitoring as a standalone service via REST API.  
This requires connecting your systems to our REST API, including KYC, KYB, and transaction history modules.  
We provide sandbox access, documentation, and support for rulesets setup and testing.

<p class="callout info">**Important:** This option requires your technical team to manage API integration and maintain connections with external data sources.   
</p>

<p class="callout warning">**Warning:** This option may require additional development on Verestro’s side regarding integration with KYC, KYB, and transaction history modules, depending on your setup and business requirements.</p>

# Technical Documentation – AML Ruleset Definition Language

# **DSL Schema Documentation for Transaction Rulesets**

## **Overview**

This DSL (Domain-Specific Language) defines ruleset-based conditions for handling transactions. The rulesets specify conditions under which transactions should be blocked, allowed, or flagged. The schema enables defining logical conditions using `AND`, `OR`, `request_property_check`, `transactions_volume_check`, `transactions_quantity_check`, `blacklist_check`, `greylist_check`, `kyc_property_check` and `compare_with_last_transaction`statements, along with customizable triggers and actions.

---

## **Schema Structure**

```yaml
conditions:
  AND | OR: # Logical operator grouping conditions
    - request_property_check: # Check type
        property: <string>  # The property to check (e.g., "transactionData.acquirerCountry")
        comparator: <string>  # enums: "IN", "NOT_IN", "=", "!=", ">", ">=", "<", "<=", "CONTAINS"
        value: <string | list | variable>  # Expected value or variable reference, eg: string: "123", list: "value1, value2, value3" or variable (`{{ vars.UHRC_COUNTRIES }}`)
        treat_missing_value_as: <boolean>  # optional, How to handle missing fields (default: false)
    - transactions_volume_check:
        scope: <string> # enums: CORPORATION, USER, CARD, BALANCE
        by: <string> # optional, enums: MERCHANT, COUNTRY, grouping parameter
        period: <string> # 1d -> 1 day, 1M -> one month etc.
        amount: <number> # cumulative amount for given scope/by and period, as minor > 50000
        currency: <string> # country currency codes e.g. PLN, USD, AOA
        currencyAggregation: <string> # enums: SAME_CURRENCY_ONLY, CONVERT_TO_CURRENCY
        filters: # optional
          - field: <string>> #enum: type, subtype, transactionData.merchantName, transactionData.mcc, transactionData.countryCode, transactionData.contrahentName, transactionData.captureMode
            comparator: <string>  # enums: "IN", "NOT_IN", "=", "!="
            value: ATM # <string | list | variable>
    - transactions_quantity_check:
        scope: BALANCE # enums: CORPORATION, USER, CARD, BALANCE
        by: COUNTRY # optional, enums: MERCHANT, COUNTRY, grouping parameter
        period: <string> # 1d -> 1 day, 1M -> one month etc.
        quantity: 5 # transactions count for given scope/by and period, > 5
        filters: # optional
          - field: <string>> #enum: type, subType, transactionData.merchantName, transactionData.mcc, transactionData.countryCode, transactionData.contrahentName, transactionData.captureMode
            comparator: <string>  # enums: "IN", "NOT_IN", "=", "!="
            value: ATM # <string | list | variable>
    - kyc_property_check:
        property: <string>
        comparator: <string> # enums: "IN", "NOT_IN", "=", "!=", ">", ">=", "<", "<=", "CONTAINS"
        value: <string | list | variable>
        treat_missing_value_as: <boolean>  # optional, How to handle missing fields (default: false)
    - blacklist_check:
        properties:
          - property: <string> # blacklist record property
            kyc_value: <string> # user's KYC record property to evaluate
          - property: <string> # blacklist record property
            request_value: <string> # aml-verify request property to evaluate
    - greylist_check:
        properties:
          - property: <string> # greylist record property
            kyc_value: <string> # user's KYC record property to evaluate
          - property: <string> # greylist record property
            request_value: <string> # aml-verify request property to evaluate
    - compare_with_last_transaction:
        options:
          within_seconds: <number> # time in seconds
          subType: list<string> # types of transactions will be searched for in the transaction history, e.g. ["ATM_WITHDRAWAL", "PURCHASE"]
          context: <string> # enums: CARD, BALANCE, BALANCE_OWNER
          captureMode: list<string> # Payment channel/method (e.g. CONTACT, CONTACTLESS, ECOMMERCE, CLOUD, MONEYSEND, etc.)
        property: <string> # The property to check in history transaction (e.g., "transactionData.acquirerCountry")
        comparator: <string> # enums: "IN", "NOT_IN", "=", "!=", ">", ">=", "<", "<=", "CONTAINS"
        request_property: <string> # The property to check in request (e.g., "transactionData.acquirerCountry")
        treat_missing_value_as: <boolean> # optional, How to handle missing fields (default: false)

    - AND | OR:
        - request_property_check: null
          field: <string>
        #...
trigger:
  decision: <string>  # enum ( APPROVED, DECLINED)
  actions:
    <group>: # Action group
      - name: <string> # Action name (e.g. block_resource)
        properties:
          <key>: <value> # Action properties (e.g. reason: fraud_suspected, resource_type: user)
  alert:
    channels: <string> # enum: YOUTRACK_TICKET, USER_PUSH_NOTIFICATION, USER_EMAIL_NOTIFICATION
    cooldown_period: <string> # optional, 1d -> 1 day, 1M -> one month etc.
  balance_owner_notifications:
    - type: <string> # enum: SMS, EMAIL
      template_name: <string> # notification template name
      cooldown_period: <string> # optional, 1d -> 1 day, 1M -> one month etc.

```

---

## **Field Descriptions**

### **Top-Level Fields**

<table id="bkmrk-field-type-descripti"><thead><tr><th>Field</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td>`conditions`</td><td>`Object`</td><td>Defines logical conditions using `AND` / `OR`.</td></tr><tr><td>`trigger`</td><td>`Object`</td><td>Specifies what happens when the conditions are met.</td></tr></tbody></table>

### **Condition Fields**

<table id="bkmrk-field-type-descripti-1"><thead><tr><th>Field</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td>`AND` / `OR`</td><td>`List`</td><td>Groups multiple conditions where all (`AND`) or at least one (`OR`) must be met.</td></tr><tr><td>`request_property_check`</td><td>`Object`</td><td>Specifies a [request property](#bkmrk-request-property-che) condition check.</td></tr><tr><td>`kyc_property_check`</td><td>`Object`</td><td>Specifies a [kyc value](#bkmrk-kyc-check) check.</td></tr><tr><td>`transactions_volume_check`</td><td>`Object`</td><td>Specifies a [transactions volume](#bkmrk-transactions-volume) check.</td></tr><tr><td>`transactions_quantity_check`</td><td>`Object`</td><td>Specifies a [transactions quantity](#bkmrk-transactions-quantit) check.</td></tr><tr><td>`blacklist_check`</td><td>`Object`</td><td>Specifies a [blacklist](#bkmrk-blacklist-and-greyli) check.</td></tr><tr><td>`greylist_check`</td><td>`Object`</td><td>Specifies a [greylist](#bkmrk-blacklist-and-greyli) check.</td></tr><tr><td>`compare_with_last_transaction`</td><td>`Object`</td><td>Specifies a [last transaction](#bkmrk-last-transaction-che) check.</td></tr></tbody></table>

### **Common check fields**

<table id="bkmrk-field-type-descripti-2"><thead><tr><th>Field</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td>`comparator`</td><td>`String`</td><td>Comparison operator, enums: `IN`, `NOT_IN`, `=`, `!=`, `>`, `>=`, `<`, `<=`, `CONTAINS`, in case of date comparison uses ISO-8601 format for parsing date).</td></tr><tr><td>`property`</td><td>`String`</td><td>The data field to evaluate (e.g., `transactionData.acquirerCountry`).</td></tr><tr><td>`value`</td><td>`String`/`List`</td><td>The expected value in the form of:   
 string `value`  
 list `value1, value2, value3`  
 or a reference to a variable called "Value set" `{{ vars.UHRC_COUNTRIES }}`. Reference variables must be defined in API or front end administration panel. Only defined reference variables are allowed.</td></tr><tr><td>`treat_missing_value_as`</td><td>`Boolean`</td><td>Determines handling of missing fields (default `false`).</td></tr></tbody></table>

### **Comparators**

Comparators are used to compare the value of a property with a given value.

<table id="bkmrk-comparator-accepted-"><thead><tr><th>Comparator</th><th>Accepted value type</th><th>Description</th></tr></thead><tbody><tr><td>`=`</td><td>`String`</td><td>Property value equals the given value string (case-insensitive).</td></tr><tr><td>`!=`</td><td>`String`</td><td>Property value does not equals the given value string (case-insensitive).</td></tr><tr><td>`>`</td><td>`String`</td><td>Property value is greater than the given value string (case-insensitive).</td></tr><tr><td>`>=`</td><td>`String`</td><td>Property value is greater than or equal the given value string (case-insensitive).</td></tr><tr><td>`<`</td><td>`String`</td><td>Property value is less than the given value string (case-insensitive).</td></tr><tr><td>`<=`</td><td>`String`</td><td>Property value is less than or equal the given value string (case-insensitive).</td></tr><tr><td>`IN`</td><td>`List`</td><td>Property value matches any of the strings in the given value list (case-sensitive).</td></tr><tr><td>`NOT_IN`</td><td>`List`</td><td>Property value matches none of the strings in the given value list (case-sensitive).</td></tr><tr><td>`CONTAINS`</td><td>`String/List`</td><td>Property value contains the given value string, or any string from the provided value list (case-insensitive)</td></tr><tr><td>`NOT_CONTAINS`</td><td>`String/List`</td><td>Property value does not contain the given value string, nor any string from the provided value list (case-insensitive)</td></tr></tbody></table>

### **Request property check**

<table id="bkmrk-field-type-descripti-3"><thead><tr><th>Field</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td>`property`</td><td>`String`</td><td>See [property](#bkmrk-common-check-fields).</td></tr><tr><td>`comparator`</td><td>`String`</td><td>See [comparator](#bkmrk-comparators).</td></tr><tr><td>`value`</td><td>`String`/`List`</td><td>See [value](#bkmrk-common-check-fields).</td></tr><tr><td>`treat_missing_value_as`</td><td>`Boolean`</td><td>See [treat\_missing\_value\_as](#bkmrk-common-check-fields).</td></tr></tbody></table>

### **Kyc check**

<table id="bkmrk-field-type-descripti-4"><thead><tr><th>Field</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td>`property`</td><td>`String`</td><td>The Kyc property to evaluate (e.g., `riskLvl`).</td></tr><tr><td>`comparator`</td><td></td><td>See [comparator](#bkmrk-common-check-fields).</td></tr><tr><td>`value`</td><td></td><td>See [value](#bkmrk-common-check-fields).</td></tr><tr><td>`treat_missing_value_as`</td><td></td><td>See [treat\_missing\_value\_as](#bkmrk-common-check-fields).</td></tr></tbody></table>

### **Transactions volume check**

<table id="bkmrk-field-type-descripti-5"><thead><tr><th>Field</th><th>Type</th><th>Description</th><th>AML-Verify request mapping</th></tr></thead><tbody><tr><td>`scope`</td><td>`String`</td><td>Defines the level at which the transaction volume is calculated. It determines whose transaction volume is being measured.  
enums: `CORPORATION`, `USER`, `CARD`, `BALANCE`</td><td>`CORPORATION` → `balance.ownerId` (if balance.owner == CORPORATION)  
`USER` → `balance.ownerId` (if balance.owner == USER)  
`CARD` → `resourceId` (if resource == CARD)  
`BALANCE` → `balance.id`</td></tr><tr><td>`by`</td><td>`String`</td><td>Specifies the parameter used to group transaction volume within the selected scope.  
enums: `MERCHANT`, `COUNTRY`</td><td>`MERCHANT` → `transactionData.merchantIdentifier`  
`COUNTRY` → `transactionData.acquirerCountry`</td></tr><tr><td>`period`</td><td>`String`</td><td>The time interval over which to aggregate transaction volume. See [periods](#bkmrk-periods)</td><td>-</td></tr><tr><td>`amount`</td><td>`Number`</td><td>Cumulative amount.</td><td>-</td></tr><tr><td>`currency`</td><td>`String`</td><td>Cumulative amount currency.</td><td>-</td></tr><tr><td>`currencyAggregation`</td><td>`String`</td><td>Defines how transactions in different currencies are aggregated.</td><td>-</td></tr><tr><td>`filters`</td><td>`List`</td><td>See [transaction filters](#bkmrk-transaction-check-fi).</td><td>-</td></tr></tbody></table>

### **Transactions quantity check**

<table id="bkmrk-field-type-descripti-6"><thead><tr><th>Field</th><th>Type</th><th>Description</th><th>AML-Verify request mapping</th></tr></thead><tbody><tr><td>`scope`</td><td>`String`</td><td>Defines the level at which the transaction quantity is calculated. It determines whose transaction quantity is being measured.  
enums: `CORPORATION`, `USER`, `CARD`, `BALANCE`</td><td>`CORPORATION` → `balance.ownerId` (if balance.owner == CORPORATION)  
`USER` → `balance.ownerId` (if balance.owner == USER)  
`CARD` → `resourceId` (if resource == CARD)  
`BALANCE` → `balance.id`</td></tr><tr><td>`by`</td><td>`String`</td><td>Specifies the parameter used to group transaction quantity within the selected scope.  
enums: `MERCHANT`, `COUNTRY`</td><td>`MERCHANT` → `transactionData.merchantIdentifier`  
`COUNTRY` → `transactionData.acquirerCountry`</td></tr><tr><td>`period`</td><td>`String`</td><td>The time interval over which to count transactions. See [periods](#bkmrk-periods)</td><td>-</td></tr><tr><td>`quantity`</td><td>`Number`</td><td>Transactions count.</td><td>-</td></tr><tr><td>`filters`</td><td>`List`</td><td>See [transaction filters](#bkmrk-transaction-check-fi).</td><td>-</td></tr></tbody></table>

### **Blacklist and greylist check**

<table id="bkmrk-field-type-descripti-7"><thead><tr><th>Field</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td>`property`</td><td>`String`</td><td>The property from the blacklist/greylist record to be checked (e.g., `name`, `pesel`).</td></tr><tr><td>`kyc_value`</td><td>`String`</td><td>The user's KYC field that will be compared against the `property`. (e.g. `firstName`,`lastName`)</td></tr><tr><td>`request_value`</td><td>`String`</td><td>The request field (from `aml-verify` body) that will be compared against the `property`.</td></tr></tbody></table>

### **Last transaction check**

<table id="bkmrk-field-type-descripti-8"><thead><tr><th>Field</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td>`options.within_seconds`</td><td>`String`</td><td>Time in seconds to search transaction history from.</td></tr><tr><td>`options.subType`</td><td>`List<String>`</td><td>Last transaction subType, e.g. `ATM_WITHDRAWAL, PURCHASE`</td></tr><tr><td>`options.context`</td><td>`String`</td><td>Last transaction context, enums: `CARD, BALANCE, BALANCE_OWNER`</td></tr><tr><td>`options.captureMode`</td><td>`List<String>`|`null`</td><td>Last transaction captureMode, will be matched with event's `transactionData.channel`</td></tr><tr><td>`property`</td><td>`String`</td><td>The property to check in history transaction (e.g., `transactionData.acquirerCountry`).</td></tr><tr><td>`comparator`</td><td>`String`</td><td>See [comparator](#bkmrk-common-check-fields).</td></tr><tr><td>`request_property`</td><td>`String`</td><td>The property to check in request (e.g., `transactionData.acquirerCountry`).</td></tr><tr><td>`treat_missing_value_as`</td><td>`String`</td><td>See [treat\_missing\_value\_as](#bkmrk-common-check-fields).</td></tr></tbody></table>

### **Allowed values for fields inside ruleset parameters**

<table id="bkmrk-ruleset-check-type-a"><thead><tr><th>Ruleset check type</th><th>Allowed value</th></tr></thead><tbody><tr><td>Request property check `property`</td><td>transactionId, balance.owner, balance.ownerId, resourceId, externalReferenceTransactionId, resource, type, subType, amount, currency, originalAmount, originalCurrency, status, description, transactionDate, tenantId, transactionData.mcc, transactionData.merchantIdentifier, transactionData.merchantName, transactionData.captureMode, transactionData.lastFourDigits, transactionData.acquirerCountry, transactionData.mdesDigitizedWalletId, transactionData.cashbackPosCurrencyCode, transactionData.cashbackPosAmount, transactionData.lastFourDpan, transactionData.adjustmentReasonDescription, transactionData.retrievalReferenceNumber, transactionData.contrahentName, transactionData.contrahentIban, transactionData.contrahentBic, customData.\*</td></tr><tr><td>Kyc check `property`</td><td>status, tenantId, customerId, dcUserId, verificationId, firstName, lastName, birthDate, nationality, riskLvl, createdAt, usaResident, taxResident, sourceOfFunds, pesel, country, city, identityCardNo, documents</td></tr><tr><td>Blacklist / greylist check `property`</td><td>userId, tenantId, name, surname, fullName, birthDate, pesel, documentNumber, documentType, addressCountry, addressCity, iban</td></tr><tr><td>Last transaction check `property`</td><td>transactionId, eventTimestamp, tenantId, type, subType, amount, currency, status, description, card.cardOwner, card.cardOwnerId, balance.balanceOwner, balance.balanceOwnerId, transactionDate, createdAt, clearedAt, externalTransactionId, externalReferenceTransactionId, transactionData.lastFourDigits, transactionData.mcc, transactionData.merchantName, transactionData.channel, transactionData.countryCode, transactionData.originalAmount, transactionData.originalCurrency, transactionData.walletReference, transactionData.contrahentName, transactionData.contrahentBic, transactionData.merchantId</td></tr></tbody></table>

### **Trigger Fields**

<table id="bkmrk-field-type-descripti-9"><thead><tr><th>Field</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td>`decision`</td><td>`String`</td><td>The decision taken if the ruleset is triggered (`DECLINED`, `ON_HOLD`, `APPROVED`).</td></tr><tr><td>`actions`</td><td>`List`</td><td>A list of actions executed when the ruleset is triggered. Actions and their properties must be defined in API. Only defined in API actions are allowed</td></tr><tr><td>`alert`</td><td>`Object`</td><td>Definition of alerts that should be sent to internal channels (e.g. YouTrack).</td></tr><tr><td>`balance_owner_notifications`</td><td>`List`</td><td>A list of direct notifications sent to the balance owner when the ruleset is triggered. See [balance owner notification fields](#bkmrk-balance-owner-notifi).</td></tr></tbody></table>

### **Alert Fields**

<table id="bkmrk-field-type-descripti-10"><thead><tr><th>Field</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td>`channels`</td><td>`List`</td><td>List of channels where send alert. Possible values: `YOUTRACK_TICKET, USER_PUSH_NOTIFICATION, USER_EMAIL_NOTIFICATION`</td></tr><tr><td>`cooldown_period`</td><td>`String`</td><td>How long the sending of a repeated alert is suspended for a given (USER + TENANT) or (CORPORATION + TENANT). See [periods](#bkmrk-periods)</td></tr></tbody></table>

### **Balance Owner Notification Fields**

<table id="bkmrk-field-type-descripti-11"><thead><tr><th>Field</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td>`type`</td><td>`String`</td><td>Notification channel type. Possible values: `SMS`, `EMAIL`</td></tr><tr><td>`template_name`</td><td>`String`</td><td>Name of the notification template to use.</td></tr><tr><td>`cooldown_period`</td><td>`String`</td><td>Optional. How long sending of a repeated notification is suspended for a given balance owner. See [periods](#bkmrk-periods)</td></tr></tbody></table>

### **Transaction check filters**

`[0-*]` filters to narrow the transaction history search.

Each filter consists of:

<table id="bkmrk-field-type-descripti-12"><thead><tr><th>Field</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td>`field`</td><td>`String`</td><td>Filter field by. Possible values: `type, subType, transactionData.mcc, transactionData.countryCode, transactionData.merchantName, transactionData.contrahentName, transactionData.captureMode`</td></tr><tr><td>`comparator`</td><td>`String`</td><td>See [comparator](#bkmrk-common-check-fields).</td></tr><tr><td>`value`</td><td>`String`/`List<String>`</td><td>See [value](#bkmrk-common-check-fields).</td></tr></tbody></table>

#### **Periods**

Allowed period values:

<table id="bkmrk-unit-variants-chrono"><thead><tr><th>Unit variants</th><th>ChronoUnit</th></tr></thead><tbody><tr><td>Y, y, yr, year, years</td><td>YEARS</td></tr><tr><td>M, m, mo, mon, month, months</td><td>MONTHS</td></tr><tr><td>w, week, weeks</td><td>WEEKS</td></tr><tr><td>d, day, days</td><td>DAYS</td></tr><tr><td>h, hr, hour, hours</td><td>HOURS</td></tr><tr><td>min, mins, minute, minutes</td><td>MINUTES</td></tr></tbody></table>

Additional literal values:

- `previous_month` – allowed only for **check period** (used by `TransactionsVolumeCheck` and `TransactionsQuantityCheck`); represents the full previous calendar month.

---

## **Key Aspects**

### Ruleset

The rulesets specify conditions under which transactions should be blocked, allowed, or flagged. If a ruleset's conditions are true, its actions are executed.

### Conditions

Conditions are the core of each ruleset. They can be simple or complex, using logical operators to combine multiple checks. Conditions are evaluated using the logical operators specified.

### Actions

Actions are executed when a ruleset's conditions are met. These can include any number of predefined actions, such as blocking a card or notifying a user. Actions are executed in the order they appear in the list. If multiple rulesets match with the transaction and contain an action, it will only be returned and executed once.

### Decision

If all rulesets return `APPROVED`, the final result = `APPROVED`. If at least one ruleset returns `DECLINED`, the final result = `DECLINED`. If no rulesets return `DECLINED` but at least one ruleset returns `ON_HOLD`, the final result = `ON_HOLD`.

---

## **Example Rulesets**

### **Example 1: Blocking Transactions from UHRC Countries for every Partner**

### **Ruleset description**

This ruleset blocks any transaction where the acquirer country belongs to the UHRC (Unusual High-Risk Countries) list. It enforces a global AML policy and applies to all partners. Any transaction coming from high-risk jurisdictions is automatically declined and reported through an alert.

```yaml
conditions:
  AND:
    - request_property_check:
        property: transactionData.acquirerCountry
        comparator: IN
        value: {{ vars.UHRC_COUNTRIES }}
        treat_missing_value_as: false
trigger:
  decision: DECLINED
  alert:
    channels: [ YOUTRACK_TICKET ]

```

---

### **Example 2: Additional Tenant and User ID Constraints**

### **Ruleset description**

This ruleset blocks UHRC transactions specifically for the Acme tenant. It excludes internal or system accounts based on ownerId. When triggered, the user is also blocked at the Antaca level. It represents a stricter, tenant-specific AML policy tailored for Acme.

```yaml
conditions:
  AND:
    - request_property_check:
        property: transactionData.acquirerCountry
        comparator: IN
        value: {{ vars.UHRC_COUNTRIES }}
    - request_property_check:
        property: tenantId
        comparator: =
        value: Acme
    - request_property_check:
        property: balance.ownerId
        comparator: NOT_IN
        value: [ 1,2,3 ]
trigger:
  decision: DECLINED
  actions:
    antaca:
      - name: block_resource
        properties:
          reason: fraud_suspected
          resource_type: user

```

---

### **Example 3: Structuring pattern in high-risk merchant categories**

### **Ruleset description**

This ruleset detects potential structuring (smurfing) behavior. If many small transactions or a high cumulative transaction amount occurs in high-risk MCC categories within one day, an alert is generated. Transactions are approved to avoid blocking—but the AML team is notified for review.

```yaml
conditions:
  OR:
    - transactions_volume_check:
        scope: BALANCE
        by: MERCHANT
        period: "1d"
        amount: 1500000
        currency: PLN
        filters:
          - field: transactionData.mcc
            comparator: IN
            value: {{ vars.HIGH_RISK_MCC }}
          - field: type
            comparator: "="
            value: "DEBIT"
    - transactions_quantity_check:
        scope: BALANCE
        by: MERCHANT
        period: "1d"
        quantity: 10
        filters:
          - field: transactionData.mcc
            comparator: IN
            value: {{ vars.HIGH_RISK_MCC }}
          - field: type
            comparator: "="
            value: "DEBIT"
trigger:
  decision: APPROVED
  alert:
    channels: [ YOUTRACK_TICKET ]
    cooldown_period: "1d"

```

---

### **Example 4: High KYC risk level or high risk nationality alert**

### **Ruleset description**

This ruleset identifies users with a high KYC risk level or with a nationality belonging to a high-risk jurisdiction. It does not block transactions but produces an alert to highlight increased AML exposure and enable continuous monitoring of risky users.

```yaml
conditions:
  OR:
    - kyc_property_check:
        property: riskLvl
        comparator: =
        value: HIGH
    - kyc_property_check:
        property: nationality
        comparator: IN
        value: {{ vars.UHRC_COUNTRIES }}
        treat_missing_value_as: true
trigger:
  decision: APPROVED
  alert:
    channels:
      - YOUTRACK_TICKET

```

---

### **Example 5: Blacklist match on personal or national identifiers**

### **Ruleset description**

This ruleset checks if the user matches any record in the blacklist based on personal identifiers such as PESEL, name, surname, nationality, date of birth, or counterparty IBAN. If a match occurs, the transaction is declined and the user is blocked. This ensures that individuals previously flagged for fraud or AML reasons cannot transact further.

```yaml
conditions:
  OR:
    - blacklist_check:
        properties:
          - property: pesel
            kyc_value: pesel
    - blacklist_check:
        properties:
          - property: iban
            request_value: transactionData.contrahentIban
    - blacklist_check:
        properties:
          - property: name
            kyc_value: firstName
          - property: surname
            kyc_value: lastName
          - property: addressCountry
            kyc_value: nationality
          - property: birthDate
            kyc_value: birthDate
trigger:
  decision: DECLINED
  actions:
    antaca:
      - name: block_resource
        properties:
          reason: fraud_suspected
          resource_type: user

```

---

### **Example 6: Rapid cross-border card transaction on terminal or ATM detection**

### **Ruleset description**

This ruleset detects impossible or highly suspicious card activity across borders. If two transactions occur within 300 seconds but originate from two different countries, the system assumes the card may be compromised. The transaction is declined and an alert is raised, as physical cross-border movement is not feasible in such a short time.

```yaml
conditions:
  AND:
    - request_property_check:
        property: subType
        comparator: IN
        value: [ PURCHASE, ATM_WITHDRAWAL ]
    - request_property_check:
        property: transactionData.captureMode
        comparator: IN
        value: [ MAG, EMV, NFC ]
    - compare_with_last_transaction:
        options:
          within_seconds: 300
          subType: [ PURCHASE, ATM_WITHDRAWAL ]
          context: CARD
          captureMode: [ CONTACT, CONTACTLESS ]
        property: transactionData.countryCode
        comparator: "="
        request_property: transactionData.countryCode
        treat_missing_value_as: false
trigger:
  decision: DECLINED
  alert:
    channels: [ YOUTRACK_TICKET ]

```

### **Example 7: Unusual debit transaction with balance owner notifications**

### **Ruleset description**

This ruleset detects unusual debit transactions in gambling and casino-related merchant categories and notifies the balance owner directly via SMS and EMAIL in addition to raising an internal alert. The MCC codes associated with gambling are defined as a variable (`GAMBLING_MCC`). Both notifications have an optional cooldown period to avoid spamming the user and use a predefined template.

```yaml
conditions:
  AND:
    - request_property_check:
        property: type
        comparator: =
        value: DEBIT
    - request_property_check:
        property: transactionData.mcc
        comparator: IN
        value: {{ vars.GAMBLING_MCC }}
trigger:
  decision: DECLINED
  alert:
    channels:
      - YOUTRACK_TICKET
    cooldown_period: 1d
  balance_owner_notifications:
    - type: SMS
      template_name: unusual_transaction_detected
      cooldown_period: 1d
    - type: EMAIL
      template_name: unusual_transaction_detected
      cooldown_period: 1d

```

### **Example 8: Monthly turnover threshold without extended verification**

### **Ruleset description**

This ruleset detects when a user without extended KYC verification exceeds the defined monthly turnover threshold in EUR or PLN. When triggered, the system declines further transactions and requires the user to complete extended verification.

```yaml
conditions:
  AND:
    - kyc_property_check:
        property: kycLevel
        comparator: "!="
        value: EXTENDED
        treat_missing_value_as: true
    - OR:
        - transactions_volume_check:
            scope: USER
            period: "1M"
            amount: 1000000
            currency: EUR
        - transactions_volume_check:
            scope: USER
            period: "1M"
            amount: 4300000
            currency: PLN
trigger:
  decision: DECLINED
  actions:
    antaca:
      - name: extended_verification_required
        properties:
          reason: monthly_turnover_exceeded
          resource_type: user

```

---

## **Tools**

- [kaml](https://github.com/charleskorn/kaml)
- [yamlkt](https://github.com/Him188/yamlkt)
- [jackson yaml](https://github.com/FasterXML/jackson-dataformats-text)

# Technical documentation - AML Core API

AML Core is the main processing engine responsible for real-time verification of incoming transactions against active AML rulesets.  
It provides a REST API that external systems can call to evaluate transactions.  
The service applies configured logic and returns a decision (`APPROVED`, `DECLINED`, or `ON_HOLD`) along with any defined actions to be executed.

<p class="callout info">Integration with this API is not required when the client uses **[Verestro’s Antaca](https://developer.verestro.com/books/card-issuing-and-core-banking)** system, which is already natively integrated with AML Core.</p>

<p class="callout success">When purchasing the full **[Administration Panel](https://developer.verestro.com/books/administration-panel) + [Antaca](https://developer.verestro.com/books/card-issuing-and-core-banking)+ AML Transaction Monitoring** package, the only required client action is defining AML ruleset through the Administration Panel.</p>

@swagger="https://s3.verestro.com/falcon-documentation-public/AML/aml-core-openapi.json"

# Technical documentation - AML Configuration API

AML Config is the configuration module that enables management of AML rulesets, actions, and value sets through an administrative panel.  
It exposes a REST API for defining, activating, and updating AML configuration used by the AML Core service.

<p class="callout info">Integration with this API is not required when the client uses [**Verestro’s Administration Panel**](https://developer.verestro.com/books/administration-panel), which is already fully integrated with AML Config.</p>

<p class="callout success">When purchasing the full **[Administration Panel](https://developer.verestro.com/books/administration-panel) + [Antaca](https://developer.verestro.com/books/card-issuing-and-core-banking)+ AML Transaction Monitoring** package, the only required client action is defining AML rulesets through the Administration Panel.</p>

@swagger="https://aml-config.verestro.dev/api-docs"

# Administration panel documentation - user interface manual

A detailed manual for AML Transaction Monitoring administration panel operators, covering all main interface areas and typical operator workflows.

[ 👉 Open Operator Interface Manual ](https://developer.verestro.com/books/administration-panel/page/aml-management-administration-panel-overview)