Skip to content
Docs
flero.ai

Common expression patterns

Battle-tested recipes for things you'll write often. Copy, adjust, ship.


1. Pull a webhook field into an HTTP body

{
  "user_id": "{{ $trigger.body.userId }}",
  "amount":   {{ $trigger.body.amount }}
}

Note the quotes: user_id is a string (use quotes), amount is a number (no quotes, the expression resolves to the raw number).


2. Build a URL with path params

https://{{ $env.API_HOST }}/users/{{ $trigger.body.userId }}/orders

Use $env for the base URL so it varies per environment without changing the workflow.


3. Compose a Slack-style message

:tada: Order {{ $trigger.body.orderId }} from *{{ $trigger.body.customerName }}* — total ${{ $trigger.body.amount }}

Mix literal text and expressions freely. Slack-style markdown (*bold*, _italic_, code ) is just literal characters from Flero's perspective.


4. Date for a filename

report-{{ $node["DateTime: now"].json.dateString }}.pdf

Use the DateTime Operations node to produce the date string in the format you want, then reference it.


5. Conditional content via an If

Flero doesn't have a ternary inside {{ }}. Use an If node to branch and assemble two different downstream nodes.

For minor conditional content inside a single string, use a Code node:

// Code node
return {
  greeting: `Hello, ${input.firstName || "there"}!`
};

Then reference {{ $node["Greeting"].json.greeting }} downstream.


6. Join an array into a CSV string

[Loop over items] → [Set: csvRow = "{{ $input.id }},{{ $input.name }},{{ $input.total }}"]
                  → [Done] → [Data Transform: join all rows with "\n"]

The Text Processing node has a join operation that does this in one step.


7. Cap a value with min / max

{{ $trigger.body.amount }}     // if you trust the upstream

If you need to clamp, use a Data Transform with calculate, or a Code node:

return { capped: Math.min(input.amount, 10000) };

8. Default for a missing field

[Data Transform: map { name: $input.name }]   // fails if name is missing

Better, explicit default via a Data Transform map:

Operations:
  - map:
      name: {{ $input.name }}
  - map:
      name: {{ $input.name }}   # overwrites only if previous step was null

The cleanest pattern is still a small Code node:

return { name: input.name ?? "Anonymous" };

9. Reference a deeply nested field with a long path

{{ $node["GraphQL Response"].json.data.user.organization.subscription.plan.tier }}

Long paths are normal. Break into multiple Set checkpoints if you reference the same subtree several times:

[Set: subscription = $node["GraphQL Response"].json.data.user.organization.subscription]
[Downstream: {{ $node["Set: subscription"].json.plan.tier }}]

10. Use a field from each Loop iteration

// Inside the Loop body — references the current item
{{ $input.email }}

// Equivalent
{{ $node["Loop"].json.email }}

$input is more concise inside loops. Use whichever reads better in context.


11. Webhook signature verification

[Webhook Trigger: secret = $env.STRIPE_WEBHOOK_SECRET]

[If: $trigger.headers["stripe-signature"] isNotEmpty]
   true → continue
   false → [Terminal: status = failed, message = "missing signature"]

For deeper validation (compute HMAC, compare to header), use an Encryption/Hashing node with the hmac operation.


12. Idempotency via Cache Storage

[Webhook Trigger]

[Cache: exists?  key = "webhook:{{ $trigger.body.id }}"]

[If: exists isTrue]
   true → [Terminal: skip, duplicate]
   false → [Cache: set, key = same, value = 1, ttl = 86400] → [continue]

Prevents the same webhook delivery from doing the real work twice.



Found something out of date? This page lives in the Flero docs content set.