A list is a set of values that your decision flows check while they run, such as known fraud emails, blocked devices, mule accounts, trusted customers, or companies to which you will not lend. People can add and remove entries at any time, and the decision flow sees each change on the next request without a new release. The rule "decline when the email is on the fraud list" belongs to the flow and is versioned with it, while the people or values on the list are data.
Lists appear on the Data sources page as their own type. The entries are stored in your own database, in the list store connected under data destinations, and only the execution node in your region reads them. Throughout the portal, values are masked to show the first character and last two characters. The masking preserves an email's domain.
Contents
- Kinds of list
- Creating a list
- Lists of several fields
- Adding entries
- Testing and erasing a value
- Checking a list in a decision flow
- Adding to a list from a flow or a case
- Backtests see the list as it was
- Expiry, history and retention
- Writing entries from your own systems
Kinds of list
| Kind | Typical use |
|---|---|
| Block list | Confirmed fraud, mule accounts, chargebacks |
| Allow list | Known good customers or devices that skip a check |
| Watch list | Values under investigation that should send an application to review |
| List | Any other reference set, such as partner merchants or staff accounts |
The kind serves as a label for people and for the AI assistant. The engine handles every kind in the same way; the rules in your flow determine what a hit means, whether the result causes a decline, a referral, or a skipped check.
Creating a list
- Open Data sources, open the menu next to the new button, and choose List.
- Give the list a Title and an Identifier.
- Pick the Kind and the Value type.
- Optionally set a Default expiry, such as
90d, to give every new entry an expiry date. If you leave it empty, entries remain until someone removes them. - Optionally set History retention (days) to specify how long removed and expired entries remain before permanent deletion. If you leave it empty, the history remains forever.
- Save. You can drop a CSV file on the form before saving, and it uploads as soon as the list exists.
The value type determines how values are compared. Each type is normalised before storage and lookup, so the same value written in two ways still matches:
| Value type | Matches |
|---|---|
| Text | Case and repeated spaces ignored |
| Case ignored | |
| Phone number | Digits only, with a leading + or 00 read as the country prefix |
| IBAN and Account number | Spaces and dashes ignored, upper case |
| Device id | Exactly as written |
| Domain | The domain and every parent domain, so an entry evil.cz matches mail.evil.cz |
| Prefix (BIN, phone prefix) | Any value that starts with the entry, so 411111 matches a card starting with those digits |
| Person or company name | Accents and word order ignored, so "Novák, Jan" matches "JAN NOVAK" |
| Date | 1980-01-05, 5.1.1980 and 05/01/1980 are the same date |
The value type cannot change while the list contains entries.
Lists of several fields
Choose Several fields as the value type when an entry represents a person or company rather than a single value. The Fields editor opens with two presets, Company by registry and Person, and you can adjust either preset.
Each field has a name, a value type, and a role:
- Identity fields collectively identify one entry. For a company, these are country, registry, and company number, so the same company number in the Dubai registry and the Sharjah registry represents two different companies.
- An Identifier matches independently, such as a phone number, email, or ID card number.
- An Attribute stays with the entry and is returned when there is a hit, but is never used for matching, such as a company name or director.
An entry requires every identity field or at least one identifier.
Adding entries
Below the list settings, you can add one entry at a time with a reason and an optional expiry. A list of several fields displays one input for each field.
To add many entries at once, drop a CSV, TSV, or text file on the upload area:
- For a list of one value, the first column contains the value and the second, optional column contains the reason. A header row is detected and skipped.
- For a list of several fields, the first row must name the columns with the field names, along with an optional
reasoncolumn. Columns with other names are ignored.
Each file becomes one upload, with counts for entries that were added, already existed on the list, or were invalid. Undo removes everything that upload added.
Testing and erasing a value
Test a value tells you whether a value is currently on the list, which entry matched, and, for a list of several fields, which fields matched.
After a test, Erase with history deletes every entry for that exact value in this list, including entries that were removed or expired. Use this when someone asks to have their data deleted. The action cannot be undone, and the audit log records how many entries were erased, never the value itself.
Checking a list in a decision flow
Add a data source step to your flow and choose the list. The step has these parameters:
| Parameter | What to set |
|---|---|
value | The attribute to check, such as $.applicant.email. An array checks every element. A list of several fields has one parameter per field instead. |
output_path | Where the result is written, such as $.checks.fraud_emails. Use a different path for each check. |
max_entry_age | Optional. A duration such as 90d; older entries are ignored. |
mode | Leave empty to check. add adds the value instead, see below. |
reason | Used only in add mode. |
The step writes this result at output_path:
| Field | Meaning |
|---|---|
hit | true when a value is on the list, false when it is not, empty when the check could not run |
match_count | How many entries matched |
matches | Each matching entry with its reason, age in days and attributes |
__list_status | ok, unavailable when the list store could not be reached, or no_input when the value was empty |
A list of several fields adds identity_hit, fields_hit with one true or false per identity and identifier, full_hit when one entry matched everything the request sent, and max_fields_matched. Your rules can therefore treat an identity match as a decline and a shared phone number as a referral, for example.
Always add a rule for __list_status equal to unavailable. If the list store cannot be reached, hit is empty, so a flow that reads only hit treats the value as absent from the list. The release warns you when no step reads the status.
Adding to a list from a flow or a case
Set mode to add, and the step adds the value to the list instead of checking it, together with the reason you provide. Place the step after the decision has already been made, such as after a rule confirms fraud, so the next application with the same device is declined.
The value is written after the response has returned to the caller, so writing it never slows the decision. The entry records the request as its source. Test runs in the portal and backtests never write; instead, they show the status not_written.
A case procedure can perform the same action. Point a data source procedure at the list, map value to the case data, and set mode to add. The entry records the case as its source. An analyst who confirms fraud in a case can put the value on the block list from the case. The analyst does not need to open the list page.
Backtests see the list as it was
A backtest replays past requests. For each request, it uses the list as it stood when that request arrived, so an entry counts only from the moment it was added until it was removed or expired. A fraudster added in August does not make the March results look better than they were. Requests from an uploaded file have no arrival time and are checked against the list as it is now.
Test runs and backtests check lists even when calls to external data sources are switched off, because a list is read from your own store.
Expiry, history and retention
An entry stops matching when it expires or is removed. Expired and removed entries remain in the table as history, and the status filter in the entries grid lets you view them. Change expiry moves an entry's expiry date, and you can restore a removed entry.
When History retention (days) is set, a daily job deletes history older than that number of days. Entries that are still live are never touched.
Writing entries from your own systems
Your list store is a table in your own database, decisimo_list_entry unless you named it otherwise, and your systems can insert entries directly, for example from a chargeback feed.
Insert one row per entry:
| Column | Value |
|---|---|
tenant_id | Your tenant number |
list_id | The list's number, shown in the address of the list page |
value | The value as written. For a list of several fields, any label you like |
record | For a list of several fields only: {"v": {"country": "AE", "registry": "Dubai", "company_number": "12345"}, "a": {"company_name": "Desert Holdings"}} with the entered values under v and attributes under a |
reason | Optional |
source | direct |
dtime_expires | Optional expiry |
Leave match_key empty. Within a minute, Decisimo normalises the row in the same way as an entry added in the portal, after which it matches. A row whose value is invalid for the list's value type is removed with the reason invalid, while a value already on the list is removed with the reason duplicate. Until normalisation is complete, the row never matches, so a direct entry cannot match the wrong value.
INSERT INTO decisimo_list_entry (tenant_id, list_id, value, reason, source)
VALUES (171, 1015201, 'jan.novak@example.org', 'chargeback 2026-09', 'direct');