Skip to main content

List Data Policy Rules

List the transformation rules of a data policy: lookups, Lua scripts, computed and conditional fields, all executed in dependency order during resolution.

List the transformation rules of a data policy. Rules are the executable logic of resolution: reference-table lookups (exact and fuzzy), sandboxed Lua scripts, deterministic computations, conditionals, coalescing, and validation checks. The policy compiler orders rules topologically by their field dependencies, so upstream fields always resolve before the rules that read them.

Each rule declares a rule_type, its configuration, and its position (ordinal) in the policy. The compiler validates every rule at compile time: unknown rule types and circular field dependencies are rejected before anything executes against your data.

Rule configuration is where most integration effort goes. A lookup_exact config names the reference table and its search and output columns; lookup_fuzzy adds match tiers and a confidence threshold; a script config carries the Lua source. Reference tables are first-class objects — manage their rows via the reference data endpoints, and a lookup reads the table's current rows at execution time, so updating reference data needs no policy edit.

As with fields, GET /v1/data-policies/{id} is the version-resolved view: it returns the current version's rules with input_field_keys, output_field_key, execution_order, and error_behavior — the compiled ordering a run actually follows — alongside the fields they populate. Use it when you need to reason about what the next resolution will execute rather than browse the rule inventory.

GET/v1/data-policies/{id}/rules

Path parameters

id*uuidData policy UUID.

Response

Response fields

dataarrayArray of rule objects, ordered by ordinal.
data[].idstringRule UUID.
data[].version_idstringThe policy version these rules belong to (the current version, or the newest one when none is current).
data[].field_keystring | nullTarget output field key.
data[].input_field_keysstring[]Field keys the rule reads.
data[].rule_typestringRule type (e.g. select_field, transform, lookup_exact, script).
data[].configobjectRule-type-specific configuration.
data[].ordinalintegerExecution order within the version.
data[].error_behaviorstringWhat a rule failure does to the row: flag, skip, or fail.
data[].provenance_labelstring | nullLabel stamped on values this rule produces.
links.selfstringURL to this rule list.
links.policystringURL to the parent policy.

curl

curl -s https://api.talonic.com/v1/data-policies/p1a2b3c4-e5f6-7890-abcd-ef1234567890/rules \
  -H "Authorization: Bearer tlnc_your_api_key"

Response

{
  "data": [
    {
      "id": "r1a2b3c4-0001",
      "version_id": "v3a2b3c4-0003",
      "field_key": "country_code",
      "input_field_keys": ["country"],
      "rule_type": "lookup_exact",
      "config": {
        "reference_table_id": "country_codes",
        "search_column": "name",
        "output_column": "iso2"
      },
      "ordinal": 1,
      "error_behavior": "flag",
      "provenance_label": null
    },
    {
      "id": "r1a2b3c4-0002",
      "version_id": "v3a2b3c4-0003",
      "field_key": "currency",
      "input_field_keys": ["country_code"],
      "rule_type": "script",
      "config": {
        "script": "if record:get('country_code') == 'US' then return 'USD' end"
      },
      "ordinal": 2,
      "error_behavior": "flag",
      "provenance_label": "Derived currency"
    }
  ],
  "links": {
    "self": "/v1/data-policies/p1a2b3c4-e5f6-7890-abcd-ef1234567890/rules",
    "policy": "/v1/data-policies/p1a2b3c4-e5f6-7890-abcd-ef1234567890",
    "version": "/v1/data-policies/p1a2b3c4-e5f6-7890-abcd-ef1234567890/versions"
  }
}

Errors

Error responses

401unauthorizedMissing or invalid API key.
404not_foundData policy not found or does not belong to your organization.
429rate_limitedToo many requests. Retry after the period indicated in the Retry-After header.
Fuzzy lookups cascade through configurable tiers: exact match after normalization (lowercase + trim) first, then token-based Jaccard matching against the reference table. The rule's error behavior decides what happens when no tier clears the confidence threshold.

Large reference tables in scripts

A script rule normally receives each reference table it uses as a whole. Tables above 20,000 rows or 64 MiB stored never reach the script whole. They are reachable by key only: lookup[name]:exact(col, val) and lookup[name]:where(col, val) each run one tenant-scoped query against the table and return at most 100 rows per call (rows past the cap are dropped and the script log notes the truncation; it is not an error). The result behaves like any other lookup result, so :get(), :row(), :any(), :count(), and further :where clauses work as usual. Keyed matching is exact: case-sensitive and type-sensitive, with a string that parses as a number retried as a number.

Operations that need the whole table, :all(), :fuzzy(), :matches(), and :llm_match(), raise a script error on a large table: reference table '<name>' is keyed-access only (...): :fuzzy() needs the whole table; use :exact(col, val) or :where(col, val). Like any script error, it marks the rule's outputs according to its error_behavior. Rewrite the script to look up by key, or split the reference data into smaller tables if you need fuzzy matching.

Keyed lookup on a large reference table

-- Works on any size of table: one keyed query, at most 100 rows back.
local supplier = lookup["suppliers"]:exact("supplier_id", record.supplier_id)
if supplier:any() then
  record:set("supplier_country", supplier:get("country"))
end

-- Raises on a table over 20,000 rows / 64 MiB:
-- lookup["suppliers"]:fuzzy(...)  -> "... is keyed-access only ..."
A script that uses :fuzzy() or :all() keeps working while its reference table is small and starts failing once the table grows past 20,000 rows or 64 MiB. Prefer :exact() / :where() in scripts that read growing master data.

Frequently asked questions

What rule types are available?+
Data policies support 14 rule types: select_field, transform, auto_transform, lookup_exact, lookup_fuzzy, compute, script (Lua), coalesce, conditional, temp_var, chain, validate, highlight, and bypass. Each rule type has its own configuration schema, validated at compile time.
How does the Lua scripting work?+
script rules execute a sandboxed Lua 5.4 chunk per record. The script reads and writes record values, can match against reference tables via lookup helpers such as :matches(), and can escalate to LLM-powered fuzzy matching via :llm_match(). The returned value lands on the rule's target field.
What happens when a lookup fails to find a match?+
Fuzzy lookups cascade through tiers: string normalization (exact match after lowercasing and trimming), then token-based Jaccard matching with a confidence threshold. If no tier matches, the rule's error_behavior applies: flag the value for review, set it empty, substitute a default, skip, or fail.
Why does my script fail with "keyed-access only"?+
The reference table is over 20,000 rows or 64 MiB, so it is not loaded into the script whole. Use lookup[name]:exact(col, val) or :where(col, val), which return up to 100 matching rows per call; :all(), :fuzzy(), :matches(), and :llm_match() need the whole table and raise.
How is rule execution order decided?+
The compiler orders rules topologically by their input and output field keys, so a rule reading country runs after the rule that produces country. Circular dependencies are rejected at compile time, before the policy executes.