Portal Community

Example 1 — Filter: Active Premium Subscriptions (from a CRM query node)

A CRM query node returns every customer. Keep only those with an active subscription and premium tier before sending renewal reminders.

Upstream input (CRM query node's output)
{
  "timestamp": "2026-07-24T10:00:02.1102003Z",
  "triggerTime": "2026-07-24T10:00:00.0000000Z",
  "resource": "crm-query",
  "operation": "get-all-customers",
  "status": "success",
  "portName": "main",
  "items": [
    { "json": { "customerId": "C-001", "subscriptionStatus": "active",   "tier": "premium", "customerEmail": "[email protected]" } },
    { "json": { "customerId": "C-002", "subscriptionStatus": "expired",  "tier": "premium", "customerEmail": "[email protected]" } },
    { "json": { "customerId": "C-003", "subscriptionStatus": "active",   "tier": "basic",   "customerEmail": "[email protected]" } },
    { "json": { "customerId": "C-004", "subscriptionStatus": "active",   "tier": "premium", "customerEmail": "[email protected]" } }
  ],
  "success": true
}
CollectionOperation configuration
{
  "operation": "filter",
  "expression": "item.subscriptionStatus === 'active' && item.tier === 'premium'"
}
Output
{
  "status": "success",
  "successCount": 2,
  "errorCount": 0,
  "errorRecords": [],
  "count": 2,
  "items": [
    { "json": { "customerId": "C-001", "subscriptionStatus": "active", "tier": "premium", "customerEmail": "[email protected]" } },
    { "json": { "customerId": "C-004", "subscriptionStatus": "active", "tier": "premium", "customerEmail": "[email protected]" } }
  ]
}
Outcome: items holds only the two matching customers. successCount (2) tells a downstream node how many renewal emails to send; an empty result (successCount: 0) can be handled by a conditional branch to skip the email loop entirely.

Example 2 — Map: Extract Order IDs (from a database query node)

A Loop node needs a plain array of IDs to iterate over, but the source data is full order objects from a database query.

Upstream input (SQL query node's output)
{
  "timestamp": "2026-07-24T10:05:31.0021044Z",
  "triggerTime": "2026-07-24T10:05:30.0000000Z",
  "resource": "sql-query",
  "operation": "select",
  "status": "success",
  "portName": "main",
  "items": [
    { "json": { "orderId": "ORD-1", "total": 100 } },
    { "json": { "orderId": "ORD-2", "total": 200 } }
  ],
  "success": true
}
CollectionOperation configuration
{
  "operation": "map",
  "expression": "item.orderId"
}
Output
{
  "status": "success",
  "successCount": 2,
  "errorCount": 0,
  "errorRecords": [],
  "count": 2,
  "items": [
    { "json": "ORD-1" },
    { "json": "ORD-2" }
  ]
}
Outcome: A downstream Loop node iterates over output.ExtractOrderIds.items, reading each entry's .json as a plain order ID string.

Example 3 — Reduce: Sum Invoice Line Item Totals (from an upstream mapping step)

After DataMapping normalizes a multi-line invoice, calculate the grand total by reducing the line items to a single numeric sum.

Upstream input
{
  "timestamp": "2026-07-24T10:10:00.0000000Z",
  "triggerTime": "2026-07-24T10:10:00.0000000Z",
  "resource": "data-mapping",
  "operation": "data-mapping",
  "status": "success",
  "portName": "main",
  "items": [
    { "json": { "amount": 100 } },
    { "json": { "amount": 250.50 } },
    { "json": { "amount": 75 } }
  ],
  "success": true
}
CollectionOperation configuration
{
  "operation": "reduce",
  "expression": "acc + item.amount",
  "initialValue": "0"
}
Output — single item, no "count" field for scalar operations
{
  "status": "success",
  "successCount": 3,
  "errorCount": 0,
  "errorRecords": [],
  "items": [
    { "json": 425.50 }
  ]
}
Outcome: items[0].json is 425.50. Store it in a variable for the PDF invoice template and the payment node.

Example 4 — Sort: Products by Price, Ascending (from a product catalog API)

A product recommendation workflow needs cheapest-first ordering for in-stock products.

Upstream input (HTTP Request node's output)
{
  "timestamp": "2026-07-24T10:15:09.0031120Z",
  "triggerTime": "2026-07-24T10:15:08.0000000Z",
  "resource": "http-request",
  "operation": "GET",
  "status": "success",
  "portName": "main",
  "items": [
    { "json": { "sku": "P-30", "unitPrice": 45.00 } },
    { "json": { "sku": "P-10", "unitPrice": 12.99 } },
    { "json": { "sku": "P-20", "unitPrice": 27.50 } }
  ],
  "success": true
}
CollectionOperation configuration
{
  "operation": "sort",
  "field": "unitPrice",
  "direction": "asc"
}
Output
{
  "status": "success",
  "successCount": 3,
  "errorCount": 0,
  "errorRecords": [],
  "count": 3,
  "items": [
    { "json": { "sku": "P-10", "unitPrice": 12.99 } },
    { "json": { "sku": "P-20", "unitPrice": 27.50 } },
    { "json": { "sku": "P-30", "unitPrice": 45.00 } }
  ]
}
Outcome: The Loop node that follows renders product cards from lowest to highest unitPrice.

Example 5 — Distinct: Deduplicate a Contact List by Email (from a merged-source node)

A mailing list assembled from multiple sources may contain duplicate contacts. Deduplicate on the email field so each recipient gets only one message.

Upstream input
{
  "timestamp": "2026-07-24T10:20:44.0000000Z",
  "triggerTime": "2026-07-24T10:20:44.0000000Z",
  "resource": "collection-operation",
  "operation": "map",
  "status": "success",
  "portName": "main",
  "items": [
    { "json": { "name": "Alice",       "email": "[email protected]" } },
    { "json": { "name": "Alice Smith", "email": "[email protected]" } },
    { "json": { "name": "Bob",         "email": "[email protected]" } }
  ],
  "success": true
}
CollectionOperation configuration
{
  "operation": "distinct",
  "field": "email"
}
Output
{
  "status": "success",
  "successCount": 2,
  "errorCount": 0,
  "errorRecords": [],
  "count": 2,
  "items": [
    { "json": { "name": "Alice", "email": "[email protected]" } },
    { "json": { "name": "Bob",   "email": "[email protected]" } }
  ]
}
Outcome: The first occurrence for each unique email is kept ("Alice", not "Alice Smith"). The downstream email dispatch loop receives a clean, deduplicated list.

Example 6 — Error Handling: Continue vs. Error, with a Deliberately Bad Field (from a partially-dirty import)

A bulk import contains a handful of malformed records — here, one record has status as null instead of a string, which throws when the expression calls .toLowerCase() on it. This example shows the same input under both onError modes.

Upstream input (file-import node's output, 5 records, 1 malformed)
{
  "timestamp": "2026-07-24T10:25:00.0000000Z",
  "triggerTime": "2026-07-24T10:25:00.0000000Z",
  "resource": "file-import",
  "operation": "csv-import",
  "status": "success",
  "portName": "main",
  "items": [
    { "json": { "id": "R-1", "status": "Active" } },
    { "json": { "id": "R-2", "status": "Active" } },
    { "json": { "id": "R-3", "status": null } },
    { "json": { "id": "R-4", "status": "Inactive" } },
    { "json": { "id": "R-5", "status": "Active" } }
  ],
  "success": true
}
Configuration A — onError: "continue" (default): bad record skipped, node still succeeds
{
  "operation": "filter",
  "expression": "item.status.toLowerCase() === 'active'",
  "onError": "continue"
}
{
  "status": "success",
  "successCount": 3,
  "errorCount": 1,
  "errorRecords": [
    { "item": { "id": "R-3", "status": null }, "error": "Cannot read properties of null (reading 'toLowerCase')" }
  ],
  "count": 3,
  "items": [
    { "json": { "id": "R-1", "status": "Active" } },
    { "json": { "id": "R-2", "status": "Active" } },
    { "json": { "id": "R-5", "status": "Active" } }
  ]
}
Configuration B — onError: "error" with maxErrorCount: 0: the same single bad record now fails the whole node
{
  "operation": "filter",
  "expression": "item.status.toLowerCase() === 'active'",
  "onError": "error",
  "maxErrorCount": 0
}
// Routed to the error port:
// "Operation 'filter' had 1 item error(s), exceeding maxErrorCount (0)."
Outcome: Same input, same expression, same single bad record — but the node's behavior is entirely controlled by onError. Under "continue" (the default), one broken record never blocks the other four from being processed; errorCount/errorRecords tell you exactly what and why. Under "error" with the default maxErrorCount: 0, any single failure fails the node — appropriate when partial results are unacceptable.

Example 7 — inlineDataSource: Manually-Entered Test Data (no upstream node at all)

Test a map operation without wiring up a real upstream node. Type a plain JSON array directly into inlineDataSource — no envelope required; the node normalizes it automatically.

inlineDataSource (exactly what you type — a plain array, no envelope)
[
  { "firstName": "Priya", "lastName": "Nair" },
  { "firstName": "Marcus", "lastName": "Lee" }
]
CollectionOperation configuration
{
  "inlineDataSource": "[{\"firstName\":\"Priya\",\"lastName\":\"Nair\"},{\"firstName\":\"Marcus\",\"lastName\":\"Lee\"}]",
  "operation": "map",
  "expression": "item.firstName + ' ' + item.lastName"
}
Output (normalized into the standard envelope automatically)
{
  "status": "success",
  "successCount": 2,
  "errorCount": 0,
  "errorRecords": [],
  "count": 2,
  "items": [
    { "json": "Priya Nair" },
    { "json": "Marcus Lee" }
  ]
}
Outcome: What you typed as inline test data was a plain array — the node built the items/json envelope around each mapped result, not you.

Example 8 — Circuit Breaker: maxErrorsToCollect Stops a Systemically Broken Expression Early

A collection of 1,000 records references a field that was renamed upstream — every single item will fail the same way. Without a cap, the operation burns through all 1,000 failures before reporting anything. With maxErrorsToCollect, it stops as soon as the pattern is clear.

Upstream input (abbreviated — imagine 1,000 records, all missing the renamed field)
{
  "timestamp": "2026-07-24T10:35:00.0000000Z",
  "triggerTime": "2026-07-24T10:35:00.0000000Z",
  "resource": "sql-query",
  "operation": "select",
  "status": "success",
  "portName": "main",
  "items": [
    { "json": { "orderId": "ORD-0001", "orderTotal": 120 } },
    { "json": { "orderId": "ORD-0002", "orderTotal": 88 } }
    /* ... 998 more records, all shaped the same way ... */
  ],
  "success": true
}
CollectionOperation configuration — expression references the old field name "total", not "orderTotal"
{
  "operation": "map",
  "expression": "item.total * 1.08",
  "onError": "continue",
  "maxErrorsToCollect": 5
}
Output — stops after 5 failures instead of processing all 1,000
// Routed to the error port:
// "Operation 'map' stopped after 5 item error(s) reached maxErrorsToCollect (5)."
{
  "status": "error",
  "successCount": 0,
  "errorCount": 5,
  "errorRecords": [
    { "item": { "orderId": "ORD-0001", "orderTotal": 120 }, "error": "Map expression produced NaN (likely a non-numeric or missing field used in an arithmetic expression)." },
    { "item": { "orderId": "ORD-0002", "orderTotal": 88 },  "error": "Map expression produced NaN (likely a non-numeric or missing field used in an arithmetic expression)." }
    /* ... 3 more identical failures, then the circuit breaker stopped the loop ... */
  ]
}
Outcome: item.total is undefined on every record (the field is actually named orderTotal), so undefined * 1.08 is NaN on every item — a systemic bug, not a few bad rows. maxErrorsToCollect: 5 catches this after 5 failures instead of grinding through all 1,000, and — notably — this circuit-break fails the node even though onError was left at the default "continue": the safety cap always overrides onError because the operation genuinely didn't finish.