Skip to main content

Documentation Index

Fetch the complete documentation index at: https://developer.kodexa.ai/llms.txt

Use this file to discover all available pages before exploring further.

Validation rules and conditional formats are configured on taxons in a data definition. At runtime Kodexa applies those rules to the matching data objects and data attributes in each document. Use validation rules when the document data must satisfy a business rule. Use conditional formatting when reviewers need a visual cue while reviewing data. Both use the same formula language.
You do not add validationRules or conditionalFormats directly to a stored data object or data attribute. You add them to the taxon that models that object or attribute. Kodexa evaluates the rule wherever that taxon appears in document data.

Where Rules Live

Rules can be attached at two levels:
LevelAttach toUse for
Data attributeA field taxon such as invoice_number, due_date, or total_amountRequired fields, field-level ranges, confidence checks, and conditional formatting on a form control
Data objectA group taxon such as invoice, vendor, or line_itemsCross-field checks where the rule describes the whole object
Attribute-level rules are the most common. They bind cleanly to a field in the review UI and can create exceptions against a specific data attribute. Object-level rules are useful when the business rule is about the row or section rather than a single field. For example, an invoice object can validate that subtotal + tax_amount matches total_amount.
Attribute-level rule
taxons:
  - name: invoice
    group: true
    children:
      - name: invoice_number
        label: Invoice Number
        taxonType: STRING
        validationRules:
          - name: Invoice number required
            ruleFormula: "!isblank({invoice_number})"
            messageFormula: '"Invoice number is required"'
            exceptionId: INVOICE_NUMBER_REQUIRED
            overridable: false
Object-level rule
taxons:
  - name: invoice
    group: true
    validationRules:
      - name: Invoice total matches components
        ruleFormula: |
          abs({total_amount} - (
            ifnull({subtotal}, 0) +
            ifnull({tax_amount}, 0) +
            ifnull({shipping_amount}, 0)
          )) < 0.01
        messageFormula: |
          concat(
            "Invoice total does not match the calculated total. Total: ",
            {total_amount}
          )
        exceptionId: INVOICE_TOTAL_MISMATCH
        overridable: true
    children:
      - name: subtotal
        taxonType: CURRENCY
      - name: tax_amount
        taxonType: CURRENCY
      - name: shipping_amount
        taxonType: CURRENCY
      - name: total_amount
        taxonType: CURRENCY

Validation Rules

Validation rules are stored in the validationRules array on a taxon. Each rule evaluates a formula. If the formula returns truthy, the data passes. If it returns falsy or errors, Kodexa treats the rule as failed.
validationRules:
  - id: due-date-after-invoice-date
    name: Due date after invoice date
    description: The payment due date must not be earlier than the invoice date.
    disabled: false
    conditional: true
    conditionalFormula: "!isblank({due_date}) && !isblank({invoice_date})"
    ruleFormula: "isafterdate({due_date}, {invoice_date}) || {due_date} = {invoice_date}"
    messageFormula: '"Due date must be on or after the invoice date"'
    detailFormula: |
      concat("Invoice date: ", {invoice_date}, ". Due date: ", {due_date}, ".")
    exceptionId: DUE_DATE_BEFORE_INVOICE_DATE
    supportArticleId: "9117988"
    overridable: false

Rule Fields

FieldTypeRequiredBehavior
idstringNoStable rule identifier in metadata. Use one when configuration is managed in Git.
namestringRecommendedHuman-readable rule name shown in tooling and useful for derived exception keys.
descriptionstringNoExplains why the rule exists.
disabledbooleanNoWhen true, Kodexa skips the rule.
conditionalbooleanNoWhen true, Kodexa evaluates conditionalFormula before the rule.
conditionalFormulaformula stringRequired when conditional is trueIf the formula is falsy or errors, Kodexa skips ruleFormula.
ruleFormulaformula stringYesMust evaluate truthy for the data to pass. Empty formulas are skipped.
messageFormulaformula stringRecommendedBuilds the message for the exception when the rule fails.
detailFormulaformula stringNoBuilds additional details for the exception.
exceptionIdstringRecommendedStable exception type. If omitted, Kodexa derives a key from the taxon path and rule name.
supportArticleIdstringNoHelp article ID attached to the resulting exception.
overridablebooleanNoControls whether a reviewer can override the exception. Defaults to not overridable when omitted.

Evaluation Flow

  1. Kodexa finds the taxon for the changed data object or data attribute.
  2. Disabled rules are skipped.
  3. If conditional is true and conditionalFormula is present, Kodexa evaluates the condition.
  4. If the condition is truthy, Kodexa evaluates ruleFormula.
  5. Truthy results pass. Falsy results fail.
  6. Formula errors are treated as failed validation and marked as evaluation errors so authors can diagnose bad rules.
  7. Failing rules create or reopen data exceptions. Passing rules close matching open exceptions.
Validation formulas are reactive. When a formula references {subtotal}, {tax_amount}, or another attribute, Kodexa tracks that dependency and re-evaluates the affected rule when the referenced value changes.

Required Fields

Use isblank for required field checks. Missing references resolve to null, so isblank handles missing, null, empty-string, and empty-list values.
validationRules:
  - name: Vendor name required
    ruleFormula: "!isblank({vendor_name})"
    messageFormula: '"Vendor name is required"'
    exceptionId: VENDOR_NAME_REQUIRED
    overridable: false

Conditional Rules

Set conditional: true when a rule should apply only for some records.
validationRules:
  - name: PO number required for purchase-order invoices
    conditional: true
    conditionalFormula: "{invoice_type} = 'Purchase Order'"
    ruleFormula: "!isblank({purchase_order_number})"
    messageFormula: '"Purchase order number is required for PO invoices"'
    exceptionId: PO_NUMBER_REQUIRED
    overridable: false
If conditional is omitted or false, Kodexa evaluates ruleFormula regardless of conditionalFormula.

Cross-Field Rules

Attach cross-field rules to the field that should receive the exception, or to the group taxon when the rule describes the full object.
validationRules:
  - name: Line total matches quantity times unit price
    conditional: true
    conditionalFormula: |
      !isblank({quantity}) && !isblank({unit_price}) && !isblank({line_total})
    ruleFormula: "abs({line_total} - ({quantity} * {unit_price})) < 0.01"
    messageFormula: |
      concat("Line total should be ", {quantity} * {unit_price}, " but was ", {line_total})
    exceptionId: LINE_TOTAL_MISMATCH
    overridable: true

Repeating Groups

When a formula references a child path that has multiple data objects, Kodexa returns an array of values. Math functions such as sum, average, min, and max can work across those arrays.
validationRules:
  - name: Invoice total equals line item total
    ruleFormula: "abs({total_amount} - sum({line_items/line_total})) < 0.01"
    messageFormula: |
      concat(
        "Invoice total ",
        {total_amount},
        " does not match line item total ",
        sum({line_items/line_total})
      )
    exceptionId: INVOICE_LINES_DO_NOT_SUM
    overridable: true

Formula Errors

Formula errors are configuration problems. For example, an unknown function, invalid syntax, or unsupported comparison can cause the rule to fail with evaluationErrored.
Avoid
ruleFormula: "NOT_EMPTY({invoice_number})"
Use
ruleFormula: "!isblank({invoice_number})"
The formula language is not SQL, JavaScript, or Excel. Use && and || for logic, = for equality, ! for not, and built-in functions such as isblank, ifnull, datemath, and contains.

Conditional Formatting

Conditional formats are stored in the conditionalFormats array on a taxon. Each format has:
FieldTypeRequiredBehavior
typestringYesFormatter type consumed by the review UI.
conditionformula stringYesFormula that activates the format when truthy.
propertiesobjectNoFormatter-specific properties, usually color or icon.
conditionalFormats:
  - type: backgroundColor
    condition: "isbeforedate({due_date}, datemath('today')) && {status} != 'PAID'"
    properties:
      color: "#FEE2E2"

  - type: textColor
    condition: "isbeforedate({due_date}, datemath('today')) && {status} != 'PAID'"
    properties:
      color: "#991B1B"

  - type: icon
    condition: "{total_amount} > 10000"
    properties:
      icon: alert-circle
      color: "#D97706"

Supported Formatter Types

TypePropertiesResult
backgroundColorcolorApplies a background color to the attribute control.
textColorcolorApplies a text color to the attribute control.
outlineColorcolorApplies a colored outline around the attribute control.
iconicon, colorDisplays a review icon for the attribute.
Conditional formatting is attribute-oriented. Add conditionalFormats to the field taxon whose control should be styled.
Attribute styling
taxons:
  - name: invoice
    group: true
    children:
      - name: total_amount
        label: Total Amount
        taxonType: CURRENCY
        conditionalFormats:
          - type: backgroundColor
            condition: "{total_amount} > 10000"
            properties:
              color: "#FEF3C7"
          - type: icon
            condition: "{total_amount} > 10000"
            properties:
              icon: alert-circle-outline
              color: "#92400E"
Older examples may use formula, backgroundColor, textColor, or icon at the top level of a conditional format. The current Kodexa document runtime evaluates condition and returns active { type, properties } records, so new configuration should use the canonical shape shown above.

How Conditional Formats Recalculate

Kodexa builds a dependency graph from every condition. When any referenced value changes, the affected conditional formats are evaluated for that data object.
  • A truthy condition activates the format.
  • A falsy condition deactivates the format.
  • An empty condition is skipped.
  • A condition that errors is treated as inactive.
  • Kodexa caches active/inactive state and emits conditional format change events only when the state changes.

Formula Language

Validation rules and conditional formats use Kodexa’s KEXL formula language. The same syntax is used by formula taxons and other data-definition features.

Literals

123
123.45
"Invoice total is required"
'PAID'
true
false
null
[1, 2, 3]
Strings can be single-quoted or double-quoted. Use backslash escapes such as \", \', \n, and \t, or double the quote character inside the same quote style.

Attribute References

Use curly braces to read values from the current data object or related data objects.
{invoice_number}              // Attribute on the current data object
{line_items/line_total}       // Child data object path, often returns an array
{../invoice_number}           // Attribute on the parent data object
{../../customer_name}         // Attribute two levels up
{./status}                    // Explicit self-relative attribute reference
References are case-insensitive when matching existing attributes. The formula service also understands taxon externalName mappings, so generated data can use external names without changing the underlying taxon names.

Operators

OperatorUse
+, -, *, /Arithmetic
^Power
&String concatenation
=Equality
!=Inequality
<, <=, >, >=Ordered comparison
&&Logical and, short-circuits
``Logical or, short-circuits
!Logical not
[]Array index access
()Grouping
({subtotal} + {tax_amount}) = {total_amount}
!isblank({invoice_number}) && {total_amount} > 0
concat("Invoice ", {invoice_number}) & " is ready"
Use = for equality. Do not use ==. Use && and ||; uppercase AND and OR are not formula operators.

Truthy and Falsy Values

Kodexa uses truthiness when deciding whether a validation passes or a conditional format is active.
ValueTruthiness
truetruthy
falsefalsy
Non-zero numbertruthy
Zerofalsy
Non-empty stringtruthy
Empty stringfalsy
Non-empty arraytruthy
Empty arrayfalsy
nullfalsy

Function Reference

Function names are case-insensitive, but examples should use lower-case names for consistency.
FunctionExampleNotes
sumsum({line_items/line_total})Adds numeric values. Arrays are summed.
averageaverage({scores/value})Mean of numeric values. Returns zero when there are no numeric values.
minmin({line_items/amount})Lowest numeric value.
maxmax({line_items/amount})Highest numeric value.
absabs({expected} - {actual})Absolute value. Arrays are summed first.
ceilceil({amount})Round toward positive infinity.
floorfloor({amount})Round toward negative infinity.
roundround({amount})Round to nearest integer.
stddeviationstddeviation(1, 2, 3)Standard deviation.
decimalplacesdecimalplaces({amount}, 2, "round_half_up")Decimal rounding. Default mode is floor.
concatconcat("PO ", {purchase_order_number})Converts arguments to strings and joins them.
substringsubstring({code}, 0, 3)String slice using start and end indexes.
lowercaselowercase({vendor_name})Returns lower-case string values.
uppercaseuppercase({vendor_name})Returns upper-case string values.
trimtrim({vendor_name})Trims whitespace.
replacereplace({phone}, "-", "")Replaces all occurrences.
splitsplit({csv_value}, ",")Returns an array.
strlenstrlen({invoice_number})Length of string value.
lengthlength({line_items/line_total})Length of string, array, map, or object representation.
lenlen({line_items/line_total})Alias for length.
ifif({amount} > 0, "debit", "credit")Conditional result. Arguments are evaluated before the function runs.
ifnullifnull({tax_amount}, 0)Returns fallback for null or empty arrays.
sumifssumifs({amounts}, {types}, "freight")Sums values where criteria match.
countifscountifs({statuses}, {statuses}, "open")Counts values where criteria match.
isnullisnull({field})True for null or empty arrays.
isblankisblank({field})True for null, empty arrays, or whitespace-only strings.
containscontains({description}, "freight")Substring check.
startswithstartswith({code}, "INV")Prefix check.
endswithendswith({code}, "-US")Suffix check.
datemathdatemath({invoice_date}, "days", 30)Adds days, weeks, months, or years. datemath("today") returns today’s date.
isdateisdate({invoice_date})True when the value can be parsed as a date.
isbeforedateisbeforedate({invoice_date}, {due_date})Date comparison, ignoring time.
isafterdateisafterdate({due_date}, {invoice_date})Date comparison, ignoring time.
daysbetweendaysbetween({invoice_date}, {due_date})Full days between two dates.
weeksbetweenweeksbetween({start_date}, {end_date})Full weeks between two dates.
monthsbetweenmonthsbetween({start_date}, {end_date})Month difference between two dates.
validatedatevalidatedate({invoice_date})True when the date parses.
formatdateformatdate({invoice_date}, "yyyy-MM-dd")Formats a date using Java date-pattern syntax.
regexregex({invoice_number}, "^[A-Z0-9-]+$")Go regular expression match.
matchesmatches({invoice_number}, "^[A-Z0-9-]+$")Alias for regex.
confidenceconfidence("invoice_number")Reads confidence for an attribute on the current data object.
countcount(1, 2, 3)Counts function arguments.
selectioncontainsselectioncontains({available_codes}, {code})Checks string values or { label, value } option objects.
getvaluegetvalue("../invoice_number")Resolves a path supplied as a string.
servicebridgecallservicebridgecall("VendorLookup", "lookup", "name", {vendor_name})Calls a configured Service Bridge when available in the runtime.

Eager and Short-Circuit Evaluation

Function arguments are evaluated before the function runs. That means if does not protect an invalid branch from being evaluated.
Avoid
if({denominator} = 0, 0, {numerator} / {denominator})
Use logical operators when you need short-circuit behavior.
Use
{denominator} != 0 && ({numerator} / {denominator}) > 10

Common Formula Patterns

Required value
!isblank({invoice_number})
Optional date ordering
isblank({due_date}) || isblank({invoice_date}) || isafterdate({due_date}, {invoice_date}) || {due_date} = {invoice_date}
Numeric tolerance
abs({expected_total} - {actual_total}) < 0.01
Date window
!isblank({due_date}) &&
isafterdate({due_date}, datemath("today", "days", -1)) &&
isbeforedate({due_date}, datemath("today", "days", 31))
Selection-like text
{status} = "Approved" || {status} = "Approved with Conditions"
Dynamic path
getvalue("../" & {field_name}) = "Complete"
  1. Put field-level validation and formatting on the field taxon.
  2. Put object-level validation on the group taxon.
  3. Use stable exceptionId values for customer-facing exceptions.
  4. Use conditional: true only when the rule has a real gating condition.
  5. Write formulas with explicit braces around every data reference.
  6. Prefer isblank, ifnull, abs, datemath, and date comparison functions over hand-rolled string checks.
  7. Keep conditional formatting visual and non-blocking; use validation rules for business conditions that must be resolved.

Data Definitions Guide

Start with the overall data definition model.

Event-Based Scripting

Use scripts when a rule needs side effects or procedural logic.

Selection Option Formulas

Compute dropdown options dynamically from document context.

Formula Reference

See the broader formula guide and examples.