Examples
Eight complete, real-world examples — each showing the actual upstream envelope going in, the node configuration, and the actual output envelope coming out.
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.
{
"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
}
{
"operation": "filter",
"expression": "item.subscriptionStatus === 'active' && item.tier === 'premium'"
}
{
"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]" } }
]
}
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.
{
"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
}
{
"operation": "map",
"expression": "item.orderId"
}
{
"status": "success",
"successCount": 2,
"errorCount": 0,
"errorRecords": [],
"count": 2,
"items": [
{ "json": "ORD-1" },
{ "json": "ORD-2" }
]
}
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.
{
"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
}
{
"operation": "reduce",
"expression": "acc + item.amount",
"initialValue": "0"
}
{
"status": "success",
"successCount": 3,
"errorCount": 0,
"errorRecords": [],
"items": [
{ "json": 425.50 }
]
}
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.
{
"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
}
{
"operation": "sort",
"field": "unitPrice",
"direction": "asc"
}
{
"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 } }
]
}
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.
{
"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
}
{
"operation": "distinct",
"field": "email"
}
{
"status": "success",
"successCount": 2,
"errorCount": 0,
"errorRecords": [],
"count": 2,
"items": [
{ "json": { "name": "Alice", "email": "[email protected]" } },
{ "json": { "name": "Bob", "email": "[email protected]" } }
]
}
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.
{
"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
}
{
"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" } }
]
}
{
"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)."
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.
[
{ "firstName": "Priya", "lastName": "Nair" },
{ "firstName": "Marcus", "lastName": "Lee" }
]
{
"inlineDataSource": "[{\"firstName\":\"Priya\",\"lastName\":\"Nair\"},{\"firstName\":\"Marcus\",\"lastName\":\"Lee\"}]",
"operation": "map",
"expression": "item.firstName + ' ' + item.lastName"
}
{
"status": "success",
"successCount": 2,
"errorCount": 0,
"errorRecords": [],
"count": 2,
"items": [
{ "json": "Priya Nair" },
{ "json": "Marcus Lee" }
]
}
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.
{
"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
}
{
"operation": "map",
"expression": "item.total * 1.08",
"onError": "continue",
"maxErrorsToCollect": 5
}
// 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 ... */
]
}
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.