Portal Community
PropertyValue
Directive nameitems
Required isolation levelSafe
ProjectNodeData.Services
Data sourceINodeExecutionData.InputItems
Use caseCollection-level operations that would otherwise require $js

Operations Reference

Path / OperationReturnsExample
$items.countNumberTotal items in input collection
$items.isEmptyBooleantrue if no items
$items.first.fieldAnyField from the first item
$items.last.fieldAnyField from the last item
$items.sum.fieldNameDecimalSum of all items' numeric field
$items.avg.fieldNameDecimalAverage of all items' numeric field
$items.min.fieldNameDecimalMinimum value of a numeric field
$items.max.fieldNameDecimalMaximum value of a numeric field
$items.pluck.fieldNameJSON ArrayArray of a single field from all items
$items.distinct.fieldNameJSON ArrayUnique values of a field across all items
$items.allJSON ArrayFull input collection as JSON
$items.countWhere.field.valueNumberCount of items where field == value
$items.sumWhere.numField.filterField.valueDecimalSum of numField where filterField == value

Complex Scenarios

Scenario 1 — Payroll Batch Totals Summary

After processing a payroll batch, produce summary statistics without JavaScript:

// Email body summary node
Batch Summary — {@ $ctx.today }

Total employees processed : {@ $items.count }
Total gross pay           : {@ $items.sum.grossPay } {@ $ctx.tenant.currency }
Total tax deducted        : {@ $items.sum.taxDeducted } {@ $ctx.tenant.currency }
Total net pay             : {@ $items.sum.netPay } {@ $ctx.tenant.currency }
Average net pay           : {@ $items.avg.netPay } {@ $ctx.tenant.currency }
Highest gross             : {@ $items.max.grossPay }
Lowest gross              : {@ $items.min.grossPay }

Scenario 2 — Guard Against Empty Input

An IfCondition node skips processing when the input collection is empty:

// IfCondition: "Skip if no items"
{@ $items.isEmpty }
// true → skip to summary node
// false → continue to processing loop

// Alternatively: check minimum required count
{@ $js`return context.items.count >= 1` }

Scenario 3 — Extract List of Employee IDs for Audit

Pluck a single field from all items to build a list for an audit trail:

Audit node — all employee IDs processed
{@ $items.pluck.employeeId @json }
[1001, 1002, 1003, 1004, 1005]
Distinct departments in this batch
{@ $items.distinct.department @json }
["Finance","Engineering","HR"]

Scenario 4 — Conditional Count for SLA Alerting

Count how many items match an error condition and alert only when threshold exceeded:

// VariableAssignment: store the failure count
VariableName: "failureCount"
Value: {@ $items.countWhere.status.failed }

// IfCondition: alert if more than 5% failed
{@ $js`
const failed = parseInt(context.vars.failureCount, 10);
const total  = context.items.count;
return total > 0 && (failed / total) > 0.05;
` }

// Alert message
SLA BREACH: {@ $var.failureCount } of {@ $items.count } items failed (threshold: 5%)

Scenario 5 — Sum by Status for Reconciliation Report

Produce a breakdown of amounts by payment status:

// Reconciliation node fields
{
  "processed": {
    "count":  {@ $items.countWhere.status.processed },
    "amount": {@ $items.sumWhere.amount.status.processed }
  },
  "pending": {
    "count":  {@ $items.countWhere.status.pending },
    "amount": {@ $items.sumWhere.amount.status.pending }
  },
  "failed": {
    "count":  {@ $items.countWhere.status.failed },
    "amount": {@ $items.sumWhere.amount.status.failed }
  }
}

Scenario 6 — Pass Entire Collection to an HTTP Endpoint

Send the full input collection as the body of a bulk-insert API call:

HTTP Request body — bulk insert
{@ $items.all @json }
Full JSON array of all input items — ready for a batch API endpoint
// With a wrapper object for an API that expects an envelope:
{
  "batchId":  "{@ $exec.executionId }",
  "count":    {@ $items.count },
  "records":  {@ $items.all @json },
  "tenantId": {@ $ctx.tenant.id }
}

Common Errors

ErrorCauseFix
PathNotFound: sum.fieldNameField doesn't exist or is not numericVerify field name; ensure field contains numeric values; use @default:0
PathNotFound: firstInput collection is emptyGuard with $items.isEmpty check before accessing first/last
ItemsError: ambiguous filtercountWhere path has wrong segment countPath must be exactly $items.countWhere.fieldName.value