Personalization

If you want to customize the output of the Ntropy API you can do so by defining a ruleset through the personalization API in /v3/rules/.

A ruleset is a set of rules that change some of the fields returned by the enrichment API, such as entity attributes or adding and removing labels. If not specified otherwise, rules are applied to all transactions. Rulesets are unique per API key.

In order to apply them to a subset of transactions, you can filter by the values that transaction fields of this set would have. To apply to consumer or business transactions you could use account_holder_type. To have more fine-grained control and apply it to specific account holders or subsets thereof please see this example.

Rules

There are two types of rules: actions and conditionals. Actions are used to change the fields of transactions. Conditionals, execute actions depending on a boolean expression. To replace the logo of a website, we could use:

1from ntropy_sdk import SDK
2
3sdk = SDK("cd1H...Wmhl")
4rules = [
5 {
6 "if": {
7 "==": [
8 {"get": "website"},
9 "ntropy.com"
10 ]
11 },
12 "then": [
13 {"set": "logo", "to": "https://logos.ntropy.com/ntropy.com"}
14 ],
15 }
16]
17
18sdk.rules.replace(rules)

Please refer to our examples section for more examples on how to override labels in the enrichment result or how to segment rules by account holders or by subsets of their accounts.

Uploading and modifying rulesets

Rulesets are type checked when modified. They can be uploaded, replacing all of the existing ones via POST request to /v3/rules/replace. and retrieved by a GET request to the /v3/rules. Only one ruleset is allowed per API key.

To add rules to a ruleset, you can do it via a POST request to /v3/rules. Deleting and replacing individual rules can be done via DELETE /v3/rules/{id}. and PATCH /v3/rules/{id}. respectively.

There is a size limit of 200,000 bytes for API key rulesets which is enough for approximately 8000 basic rules.

Rule Specification

Actions

There are 3 types of actions a rule can perform. They take expressions as arguments and can set general properties, modify labels and modify mccs.

Set property

1{"set": "property", "to": expression}

Modify labels

You can add labels, remove labels, or replace all the labels. These expect strings.

1{"set_labels": [string...]}
2{"add_label": string}
3{"remove_label": string}

Modify MCCs

Similarly, you can add, removes, or replace all the MCCs. These expect numbers.

1{"set_mcc": [number...]}
2{"add_mcc": number}
3{"remove_mcc": number}

Conditionals

Execute a set of actions if condition is true. A condition is an expression that evaluates to a boolean.

1{"if": condition, "then": [rules...]}
2{"if": condition, "then": [rules...], "else": [rules...]}

Note that conditionals support the specification of rules in the then clause. This means that nested conditionals are supported. Building on the previous example:

1from ntropy_sdk import SDK
2
3sdk = SDK("cd1H...Wmhl")
4rules = [
5 {
6 "if": {
7 "==": [
8 {"get": "website"},
9 "ntropy.com"
10 ]
11 },
12 "then": [
13 {
14 "if": {
15 "==": [
16 {"get": "website"},
17 "api.ntropy.com"
18 ]
19 },
20 "then": [
21 {"set": "logo", "to": "https://logos.ntropy.com/api.ntropy.com"}
22 ],
23 "else": [
24 {"set": "logo", "to": "https://logos.ntropy.com/ntropy.com"}
25 ]
26 }
27 ],
28 }
29]
30sdk.rules.replace(rules)

Expressions

Expressions can have one of three types: number, boolean, or string. null is not an allowed value. All numbers are interpreted as floats.

Expressions can be literals, transformations or operators.

Transformations

There are currently 7 transformations supported:

transformationargsdescription
getread-propertyreturn the value of the transaction property. it needs to be a readable property.
is_substring[expression, expression]takes two strings and returns a boolean, indicating whether the 2nd argument is a substring of the 1st.
starts_with[expression, expression]takes two strings and returns a boolean, indicating whether the 2nd argument is a prefix of the 1st.
ends_with[expression, expression]takes two strings and returns a boolean, indicating whether the 2nd argument is a suffix of the 1st.
to_lowerexpressiontakes a string converts it to lowercase.
to_upperexpressiontakes a string converts it to uppercase.
has_labelexpressiontakes a string and returns a boolean

Operators

Operators evaluate to a boolean literal and take an arbitrary number of arguments and are evaluated as ((arg1 <op> arg2) <op> arg3) <op> ...:

1{"!": expression} // logical not, accepts a boolean
2{"&&": [expressions...]} // logical and, accepts a list of booleans
3{"||": [expressions...]} // logical or, accepts a list of booleans
4{"==": [expressions...]} // equals, accepts a list of expressions of the same type
5{"+": [expressions...]} // accepts a list of numbers
6{"*": [expressions...]} // accepts a list of numbers
7{"/": [expressions...]} // accepts a list of numbers
8{"-": [expressions...]} // accepts a list of of numbers
9{"//": [expressions...]} // integer division, accepts a list of numbers
10{"<": [expression, expression]} // accepts two numbers
11{"<=": [expression, expression]} // accepts two numbers
12{">": [expression, expression]} // accepts two numbers
13{">=": [expression, expression]} // accepts two numbers

Properties

Each property corresponds to an enrichment transaction field of the same name. write and read indicate whether the property is writable and/or readable.

nametypewriteread
logostring
websitestring
merchantstring
merchant_idstring
locationstring
personstring
transaction_typestring
descriptionstring
amountnumber
entry_typestring (“incoming” or “outgoing”)
account_holder_typestring
account_holder_idstring
account_holder_namestring

Examples

Adding income label to interest payments

1from ntropy_sdk import SDK
2sdk = SDK("cd1H...Wmhl")
3
4rules = [
5 {
6 "if": {
7 "||": [
8 {"has_label": "interest"},
9 {"is_substring": [{"to_lower": {"get": "description"}}, "interest"]},
10 ]
11 },
12 "then": [{"add_label": "income"}],
13 }
14]
15sdk.rules.replace(rules)

Account holder rule segmentation

For further control over the subset of transactions rules apply to, if you only want to apply a set of rules to an account holder ntropy, you can use the property account_holder_id to do so:

1from ntropy_sdk import SDK
2sdk = SDK("cd1H...Wmhl")
3
4rules = [
5 {
6 "if": {
7 "==": [
8 {"get": "account_holder_id"},
9 "ntropy"
10 ]
11 },
12 "then": ...
13 }
14]
15sdk.rules.replace(rules)

Taking this a step further, there are some use-cases where instead of applying rules to specific account holders, you may want to apply it to all future account holders that follow a specific pattern.

This could simplify the management of rules and account holder management on your side. To this end, you can use a combination of starts_with and account_holder_id. For example, if for every account under the account holder ntropy we want to apply a set of rules, we could adopt the naming convention of ntropy_<specific_id> and set rules of this form:

1from ntropy_sdk import SDK
2sdk = SDK("cd1H...Wmhl")
3
4rules = [
5 {
6 "if": {
7 "starts_with": [
8 {"get": "account_holder_id"},
9 "ntropy_"
10 ]
11 },
12 "then": ...
13 }
14]
15
16sdk.rules.replace(rules)