Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.anyreach.ai/llms.txt

Use this file to discover all available pages before exploring further.

JSONata is a small query language for JSON. This page is a list of patterns you’ll reach for often. For the full spec, see jsonata.org. The patterns below are the ones that cover ~90% of workflow use.

Reference fields

WantJSONata
Top-level input field{{ email }}
Nested input field{{ contact.email }}
Step output field{{ `Lookup contact`.body.id }}
Top-level by full path{{ ctx.input.email }}
Backticks are required when a step name contains spaces or special characters.

Comparisons and logic

{{ score > 50 }}
{{ tier = 'gold' }}              // single =, not ==
{{ tier in ['gold', 'platinum'] }}
{{ score > 50 and tier = 'gold' }}
{{ found = false or status_code != 200 }}
{{ not (tier = 'free') }}

Defaults and null-checks

{{ name ? name : 'friend' }}                     // ternary
{{ $exists(name) ? name : 'unknown' }}           // explicit existence
{{ contact.email ?? 'no-reply@example.com' }}    // null-coalesce

String operations

{{ first_name & ' ' & last_name }}               // concat
{{ $uppercase(name) }}
{{ $lowercase(email) }}
{{ $trim(' hello ') }}
{{ $contains(message, 'urgent') }}
{{ $substring(phone, 0, 3) }}
{{ $replace(phone, '-', '') }}

Number operations

{{ price * 1.08 }}                                // tax
{{ $round(price * quantity, 2) }}
{{ $floor(score) }}
{{ $abs(delta) }}
{{ $sum(items.price) }}                           // aggregate
{{ $count(items) }}
{{ $average(scores) }}

Array operations

// indexing
{{ contacts[0] }}
{{ contacts[-1] }}                                // last element

// filter
{{ contacts[tier = 'gold'] }}                     // all gold contacts
{{ contacts[score > 50][0] }}                     // first high-scoring

// map (project a field)
{{ contacts.email }}                              // ['a@b', 'c@d']
{{ contacts.{ "id": id, "label": name } }}        // reshape each item

// boolean over array
{{ $count(contacts[tier = 'gold']) > 0 }}         // any gold?
{{ $count(contacts[tier = 'gold']) = $count(contacts) }}  // all gold?

// concat / flatten
{{ list_a & list_b }}                             // arrays merge with &? — use [list_a, list_b].**
{{ $each(contacts, function($v) { $v.email }) }}

Object operations

{{ $keys(contact) }}                              // ['id', 'email', ...]
{{ $merge([contact, {"verified": true}]) }}       // shallow merge
{{ contact.{ "name": $.name, "tier": $.tier } }}  // pick fields

Conditionals

{{ score > 50 ? 'qualified' : 'not qualified' }}

// chained
{{ score > 90 ? 'a' : (score > 70 ? 'b' : (score > 50 ? 'c' : 'fail')) }}

// switch-style
{{ {
  "high":   score > 80,
  "medium": score > 50 and score <= 80,
  "low":    score <= 50
}[$$ = true] }}                                   // returns the matching key

Date operations

{{ $now() }}                                      // current ISO timestamp
{{ $millis() }}                                   // current epoch ms
{{ $fromMillis(ms) }}
{{ $toMillis(iso_string) }}
For richer date math, do it in a Code step instead.

Common workflow snippets

Build a Slack mention

"text": "{{ '<@' & user_id & '> new lead from ' & $.name }}"

Extract domain from email

"domain": "{{ $substringAfter(email, '@') }}"

First non-null

"phone": "{{ contact.mobile ?? contact.work ?? contact.home }}"

Pick by enum

"slack_channel": "{{ {
  'billing': 'C_BILLING',
  'support': 'C_SUPPORT',
  'sales':   'C_SALES'
}[intent] }}"

Sum with filter

"qualified_revenue": "{{ $sum(leads[score > 50].arr) }}"

Debugging tips

When an expression isn’t producing what you expect:
  1. Inspect ctx at the failing step. Open the run trace, click the step before the failing one, and copy the visible ctx.
  2. Test the expression manually. Paste ctx and the expression into try.jsonata.org — same engine.
  3. Add a Code step temporarily that just returns the raw value, so you can see what JSONata sees.
  4. Check for backticks around step names with spaces (most common bug).