Expressions & Conditions Guide
This guide walks through common workflow patterns that use expressions and conditions. Each recipe shows the workflow structure, the expression to use, and what the result looks like at runtime.
For the full list of available helpers, see the Expression Reference.
Workflow: API Trigger (GET) → If → Return (200) / Return (400)
Use case: You expose a GET endpoint and want to check whether the caller passed an id query parameter.
- Add an API Trigger node configured for
GET - Connect it to an If node
- Wire the true output to a Return node (success response)
- Wire the false output to another Return node (error response)
input.query.id
That's it. If id is present in the query string, input.query.id returns the value (truthy). If id is missing, it returns None (falsy), and execution takes the false branch.
Set the body to:
{"{{ {\"status\": \"ok\", \"id\": input.query.id} }}"}
Set the status to 400 and the body to:
{"{{ {\"error\": \"Missing required parameter: id\"} }}"}
Dot notation on dictionaries is safe — if a key doesn't exist, it returns None instead of throwing an error. This is a Tensorify feature, not standard Python behavior.
Workflow: Webhook Trigger → Switch → different handlers
Use case: A single webhook endpoint receives events from an external service (e.g., Stripe or GitHub), and you want to route to different actions based on the event type.
- Add a Webhook Trigger node
- Connect it to a Switch node
- Wire each case output to the appropriate handler
input.body.type
Or if the event type is nested:
input.body.event.action
| Case Label | Match Value | Handler |
|------------|------------|---------|
| payment_success | payment_intent.succeeded | Send confirmation email |
| payment_failed | payment_intent.payment_failed | Send alert |
| default | (fallback) | Log and stop |
The Switch node compares the expression result against each case label. The first match wins, or the default branch runs if nothing matches.
Workflow: Webhook → If → Transform / Stop
Use case: A webhook sends a status field that might be a number (200) or a string ("200"). You need to compare it reliably.
Python's == is strictly typed:
"200" == 200 # False — different types!
This can cause unexpected behavior when webhook payloads inconsistently send numbers vs strings.
If condition:
eq(input.body.status, 200)
eq() tries numeric coercion first, then string comparison. It returns True for both "200" and 200.
eq(input.body.count, 0) # True for "0" or 0
eq(input.body.price, 9.99) # True for "9.99" or 9.99
neq(input.body.status, 200) # True if status is NOT 200
When to use eq() vs ==: Use == when you control both sides (e.g., comparing two strings). Use eq() when data comes from webhooks, APIs, or forms where types are unpredictable.
Workflow: Webhook → Transform → HTTP Request
Use case: You receive a webhook from one service and need to reshape the data before sending it to another API.
In the Transform node, use {"{{ }}"} expressions to build a new JSON object:
{
"name": "{"{{ input.body.user.first_name }}"} {"{{ input.body.user.last_name }}"}",
"email": "{"{{ input.body.user.email }}"}",
"source": "webhook",
"received_at": "{"{{ now() }}"}",
"tags": "{"{{ input.body.metadata.tags }}"}"
}
Or use a single expression to build the entire object:
{"{{ pick(input.body, \"email\", \"name\", \"company\") }}"}
Reference the transform output in the next node:
{"{{ transform }}"}
Or cherry-pick fields:
{"{{ to_json(transform) }}"}
Workflow: API Trigger → If → Transform (with dynamic template) → Return
Use case: An API endpoint returns different response shapes depending on whether a detailed query param is passed.
input.query.detailed
{
"id": "{"{{ input.body.id }}"}",
"name": "{"{{ input.body.name }}"}",
"email": "{"{{ input.body.email }}"}",
"created_at": "{"{{ format_date(input.body.created_at, \"%B %d, %Y\") }}"}",
"order_count": "{"{{ length(input.body.orders) }}"}",
"total_spent": "{"{{ sum(pluck(input.body.orders, \"amount\")) }}"}"
}
{
"id": "{"{{ input.body.id }}"}",
"name": "{"{{ input.body.name }}"}"
}
Workflow: Webhook → If → different paths
input.body.email and input.body.name and input.body.age >= 18
This evaluates to True only if email is present AND name is present AND age is at least 18.
input.body.role == "admin" or input.body.role == "owner"
not is_empty(input.body.tags)
If condition — check if list has items:
length(input.body.items) > 0
Transform template:
{"{{ pluck(input.body.users, \"email\") }}"}
Result: ["[email protected]", "[email protected]", ...]
Transform template:
{"{{ [item for item in input.body.orders if item.status == \"completed\"] }}"}
Transform template:
{"{{ sum(pluck(input.body.line_items, \"amount\")) }}"}
{"{{ coalesce(input.body.display_name, input.body.username, \"Anonymous\") }}"}
{"{{ input.body.get(\"timeout\", 30) }}"}
{"{{ safe_get(input, \"body.user.preferences.theme\", \"dark\") }}"}
{"{{ input.body.name if input.body.name else \"Unknown\" }}"}
- If/Switch conditions are bare expressions — don't wrap them in
{"{{ }}"}. Just typeinput.body.status == 200. - Template fields use
{"{{ }}"}— URLs, HTTP bodies, email subjects, Transform object fields. - Dot notation is safe — accessing a missing key returns
None, not an error. - Use
eq()for webhook data — query params and form values often arrive as strings even when they look like numbers. - Chain helpers —
unique(pluck(input.body.orders, "category"))gives you deduplicated categories.
- Expression Reference — full list of all helpers and operators
- If Plugin — boolean condition branching
- Switch Plugin — multi-case routing
- Transform Plugin — data reshaping
- API Trigger Plugin — expose HTTP endpoints
