Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/czlonkowski/n8n-skills/llms.txt

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

n8n Expression Syntax

All dynamic content in n8n uses double curly braces:
{{expression}}
// ✅ Valid expressions
{{$json.email}}
{{$json.body.name}}
{{$node["HTTP Request"].json.data}}

// ❌ Invalid — missing or wrong braces
$json.email       // treated as literal text
{$json.email}     // single braces — invalid
Webhook data is NOT at the root of $json.Webhook nodes wrap all incoming data under a .body property. Always access webhook fields as {{$json.body.fieldName}}, never {{$json.fieldName}}.
// ❌ WRONG
{{$json.name}}
{{$json.email}}

// ✅ CORRECT
{{$json.body.name}}
{{$json.body.email}}

Core Variables

$json — Current Node Output

Access data from the current node in the workflow:
{{$json.fieldName}}
{{$json['field with spaces']}}
{{$json.nested.property}}
{{$json.items[0].name}}

$node — Reference Other Nodes

Access data from any previous node by name:
{{$node["Node Name"].json.fieldName}}
{{$node["HTTP Request"].json.data}}
{{$node["Webhook"].json.body.email}}
Node names must be in quotes inside brackets. Node names are case-sensitive and must match the exact name in your workflow.

$now — Current Timestamp

Access and format the current date/time using Luxon:
{{$now}}
{{$now.toFormat('yyyy-MM-dd')}}
{{$now.toFormat('HH:mm:ss')}}
{{$now.plus({days: 7})}}

$env — Environment Variables

Access n8n environment variables:
{{$env.API_KEY}}
{{$env.DATABASE_URL}}

Webhook Data Structure

The webhook node wraps all incoming request data:
// Full $json structure from a Webhook node
{
  "headers": {"content-type": "application/json"},
  "params":  {},
  "query":   {},
  "body": {              // ⚠️ User data is HERE
    "name": "John",
    "email": "john@example.com",
    "message": "Hello"
  }
}
In a Slack node text field after a Webhook:
New form submission!

Name: {{$json.body.name}}
Email: {{$json.body.email}}
Message: {{$json.body.message}}

Common Patterns

Nested Fields

// Simple nesting
{{$json.user.email}}

// Array access
{{$json.data[0].name}}
{{$json.items[0].id}}

// Bracket notation for spaces in field names
{{$json['field name']}}
{{$json['user data']['first name']}}

Combining Variables

// Inline concatenation (automatic)
Hello {{$json.body.name}}!

// In URLs
https://api.example.com/users/{{$json.body.user_id}}

// In JSON parameters
{
  "name": "={{$json.body.name}}",
  "email": "={{$json.body.email}}"
}

Multi-Node Data Flow

// Reference previous node by name
{{$node["Webhook"].json.body.order_id}}
{{$node["HTTP Request"].json.data.items[0].name}}

When NOT to Use Expressions

Do not use {{}} expressions inside Code nodes. Code nodes use direct JavaScript/Python — the {{}} syntax is for expression fields in other node types only.
// ❌ WRONG in Code node
const email = '={{$json.email}}';
const name = '{{$json.body.name}}';

// ✅ CORRECT in Code node
const email = $json.email;
const name = $json.body.name;

// Or using the $input API
const email = $input.item.json.email;
const allItems = $input.all();

Data Type Handling

// First item
{{$json.users[0].email}}

// Array length
{{$json.users.length}}

// Last item
{{$json.users[$json.users.length - 1].name}}

// Join all emails
{{$json.users.map(u => u.email).join(', ')}}

Advanced Patterns

Conditional Content

// Ternary operator
{{$json.status === 'active' ? 'Active User' : 'Inactive User'}}

// Default values
{{$json.email || 'no-email@example.com'}}

// Multiple conditions
{{$json.order.total > 100 ? 'Premium Customer' : 'Standard Customer'}}

Date Manipulation

// Add days
{{$now.plus({days: 7}).toFormat('yyyy-MM-dd')}}

// Subtract hours
{{$now.minus({hours: 24}).toISO()}}

// Specific date formatting
{{DateTime.fromISO('2025-12-25').toFormat('MMMM dd, yyyy')}}
// Result: December 25, 2025

String Manipulation

// Substring
{{$json.email.substring(0, 5)}}

// Replace
{{$json.message.replace('World', 'n8n')}}

// Split and join
{{$json.tags.split(',').join(', ')}}

Common Mistakes Quick Reference

MistakeFix
$json.field{{$json.field}}
{{$json.field name}}{{$json['field name']}}
{{$node.HTTP Request}}{{$node["HTTP Request"]}}
{{{$json.field}}}{{$json.field}}
{{$json.name}} (from webhook){{$json.body.name}}
'={{$json.email}}' (in Code node)$json.email
{{$json.items.0.name}}{{$json.items[0].name}}
`Hello ${$json.name}` (template literal)Hello {{$json.name}}
{{$node["HTTP Request"].data}}{{$node["HTTP Request"].json.data}}

Complete Error Catalog

Symptom: Field shows literal text like $json.email instead of the actual value.
❌ $json.email
✅ {{$json.email}}
Symptom: Undefined values when accessing webhook data even though the data is being sent.
// Webhook structure:
{
  "headers": {...},
  "params": {},
  "query": {},
  "body": { "name": "John" }  // Data is HERE
}

// Fix:
❌ {{$json.name}}
✅ {{$json.body.name}}
Symptom: Syntax error or undefined when the field definitely exists.
❌ {{$json.first name}}
✅ {{$json['first name']}}

❌ {{$json.user data.email}}
✅ {{$json['user data'].email}}
Symptom: Error like "Cannot read property 'Request' of undefined".
❌ {{$node.HTTP Request.json.data}}
✅ {{$node["HTTP Request"].json.data}}
Symptom: Undefined value even though the node exists and has data.
❌ {{$node["http request"].json.data}}   // lowercase
❌ {{$node["Http Request"].json.data}}   // wrong case
✅ {{$node["HTTP Request"].json.data}}   // exact match
Symptom: Output shows {{value}} instead of the actual value.
❌ {{{$json.field}}}
✅ {{$json.field}}
Symptom: Syntax error or undefined.
❌ {{$json.items.0.name}}
✅ {{$json.items[0].name}}
Symptom: Output shows =john@example.com instead of john@example.com.
// In text fields (no = needed)
Email: ={{$json.email}}
Email: {{$json.email}}

// In JSON mode (= IS needed to set whole value to expression)
{
  "email": "={{$json.body.email}}"
}
Symptom: Undefined value when you know the node has data.
❌ {{$node["HTTP Request"].data}}      // Missing .json
✅ {{$node["HTTP Request"].json.data}}

❌ {{$node["Webhook"].body.email}}     // Missing .json
✅ {{$node["Webhook"].json.body.email}}

Debugging Expressions

1

Open the expression editor

Click the field containing the expression, then click the fx icon to open the expression editor.
2

Check the live preview

The expression editor shows a live preview of the result. Check for values appearing as undefined or error messages highlighted in red.
3

Common error messages

  • “Cannot read property ‘X’ of undefined” → Parent object doesn’t exist; check your data path
  • “X is not a function” → Calling a method on the wrong type; check the variable type
  • Expression shows as literal text → Missing {{ }}; add curly braces
4

Follow the debugging checklist

  1. Is it wrapped in {{ }}?
  2. Is it webhook data? Add .body
  3. Does the field or node name have spaces? Use bracket notation
  4. Does the node name case match exactly?
  5. Is the property path correct? Check the data structure in the editor
  6. Is this inside a Code node? Remove {{ }}

Expression Helper Reference

TypeAvailable Methods
String.toLowerCase(), .toUpperCase(), .trim(), .replace(), .substring(), .split(), .includes()
Array.length, .map(), .filter(), .find(), .join(), .slice(), .reduce()
DateTime (Luxon).toFormat(), .toISO(), .toLocal(), .plus(), .minus(), .set()
Number.toFixed(), .toString(), +, -, *, /, %

Best Practices

Do

  • Always use {{ }} for dynamic content
  • Use bracket notation for field names with spaces
  • Access webhook data from .body
  • Use $node to reference data from earlier nodes
  • Test expressions in the expression editor

Don't

  • Use {{ }} inside Code nodes
  • Forget quotes around node names with spaces
  • Double-wrap with extra {{ }}
  • Assume webhook data is at the root
  • Use expressions in webhook paths or credential fields

Build docs developers (and LLMs) love