Sintaxis básica: {{ }}
Cualquier campo de un nodo puede estar en modo Fixed (texto fijo, tal cual lo escribís) o en modo Expression (un valor calculado en el momento). Activás el modo expresión con el ícono de la fórmula (fx) al lado del campo, y todo lo que escribas entre doble llave {{ }} se evalúa como JavaScript.
// Modo Fixed: texto literal, tal cual lo escribís
Hola Ana
// Modo Expression: activás el ícono fx y escribís entre doble llave
{{ $json.nombre }}
// Para lógica más larga, envolvés todo en una función autoejecutada (IIFE)
{{ (() => {
const nombre = $json.nombre || "sin nombre";
return nombre.toUpperCase();
})() }}
Al activar el modo expresión se abre un editor con vista previa en vivo: mientras escribís, te muestra el resultado calculado con los datos reales del ítem actual. Podés arrastrar un campo directamente desde el panel INPUT del nodo hacia el campo de expresión, y n8n te arma la referencia ($json.campo) automáticamente.
Variables integradas
Estas son las variables que vas a usar todo el tiempo dentro de una expresión. Todas están disponibles sin necesidad de importar nada.
| Variable | Qué devuelve | Ejemplo |
|---|---|---|
$json | Los datos JSON del ítem que se está procesando ahora mismo | {{ $json.email }} |
$binary | Los datos binarios (archivos adjuntos) del ítem actual | {{ $binary.data.fileName }} |
$itemIndex | La posición del ítem actual dentro de la lista que está corriendo el nodo | {{ $itemIndex }} |
$now | La fecha y hora actual, como objeto Luxon DateTime | {{ $now.toFormat('dd/MM/yyyy') }} |
$today | La medianoche de hoy, como objeto Luxon DateTime | {{ $today.toISO() }} |
$execution | Metadata de la ejecución actual: id, mode, resumeUrl | {{ $execution.id }} |
$workflow | Información del workflow actual: id, name, active | {{ $workflow.name }} |
$vars | Variables de entorno o de instancia, definidas en n8n | {{ $vars.apiUrl }} |
$env | Variables de entorno del sistema (si el admin las habilitó) | {{ $env.NODE_ENV }} |
$prevNode | Información sobre el nodo del que vinieron los datos de entrada | {{ $prevNode.name }} |
$runIndex | El índice de la ejecución actual del nodo, para nodos que corren más de una vez | {{ $runIndex }} |
$input | Los datos de entrada del nodo actual: .all(), .first(), .last(), .item | {{ $input.first().json.email }} |
$items() | Forma antigua de acceder a los ítems de un nodo. Preferí $input o $('Nombre') | {{ $items()[0].json }} |
$('Nombre del nodo') | Accede a los datos de otro nodo por su nombre: .item, .all(), .first(), .last(), .params | {{ $('Webhook').item.json.email }} |
Acceso a datos de otros nodos
Por defecto, $json solo te da el ítem que está procesando el nodo actual. Para leer un campo de un nodo anterior en la cadena, usás la sintaxis moderna con el nombre del nodo entre paréntesis y comillas:
// Sintaxis moderna (la recomendada)
{{ $('Webhook').item.json.email }}
// Todos los ítems de ese nodo, o solo el primero / el último
{{ $('Google Sheets').all() }}
{{ $('Google Sheets').first().json.nombre }}
// Sintaxis antigua: todavía funciona, pero está en desuso
{{ $node["Webhook"].json.email }}
Cuando usás .item sobre otro nodo, n8n no te devuelve "cualquier" ítem de ese nodo: te devuelve el ítem vinculado ("paired item"), es decir, el ítem específico de ese nodo anterior que dio origen al ítem que se está procesando ahora. n8n sigue ese hilo por vos automáticamente, incluso si en el medio hubo nodos que combinaron, filtraron o reordenaron ítems. Si esa cadena se rompe (por ejemplo, en un nodo Code mal escrito), vas a ver el error "Referenced node is not part of the input data".
Fechas con Luxon
$now y $today no son strings: son objetos Luxon DateTime, la librería de fechas que usa n8n por dentro. Eso te da métodos con nombre en vez de tener que hacer matemática de milisegundos.
// Formatear
{{ $now.toFormat('dd/MM/yyyy') }} // 22/08/2026
// Sumar y restar tiempo (formato objeto, funciona en cualquier lado)
{{ $now.plus({ days: 7 }) }}
{{ $now.minus({ hours: 2 }) }}
// ISO 8601, útil para mandarle una fecha a una API
{{ $now.toISO() }}
// Diferencia entre dos fechas, en la unidad que pidas
{{ $now.diffTo('2026-12-31', 'days') }}
{{ $json.fecha.toDateTime().diffToNow('hours') }}
n8n agrega un atajo propio para sumar/restar fechas con dos argumentos, $now.plus(7, 'days'), que funciona en los campos de expresión. Dentro del nodo Code ese atajo no existe: ahí Luxon corre "nativo" y solo acepta el formato objeto, $now.plus({ days: 7 }). Si escribís código que después vas a copiar a un nodo Code, usá siempre el formato objeto.
Transformación de datos: funciones integradas
Además de los métodos nativos de JavaScript (.toUpperCase(), .slice(), .map(), etc.), n8n agrega sus propios métodos sobre strings, arrays y objetos, pensados para tareas comunes de automatización. Se usan igual que cualquier método: encadenados con un punto.
Sobre strings
{{ "ana@ejemplo.com".isEmail() }} // true
{{ "quick brown $FOX".toSnakeCase() }} // "quick_brown_fox"
{{ "ana@ejemplo.com".extractDomain() }} // "ejemplo.com"
{{ "*bold*, [link]()".removeMarkdown() }} // "bold, link"
Sobre arrays
{{ [4,8,15].sum() }} // 27
{{ [4,8,15].average() }} // 9
{{ ["a","a","b"].unique() }} // ["a", "b"]
{{ [1,2,3,4].chunk(2) }} // [[1,2],[3,4]]
Sobre objetos y números
{{ $json.keys() }} // ["nombre", "email", "plan"]
{{ $json.values() }} // ["Ana", "ana@ejemplo.com", "pro"]
{{ ({}).isEmpty() }} // true
Estos son helpers propios de n8n que se suman a los métodos nativos del lenguaje, no los reemplazan. "hola".toUpperCase() sigue funcionando igual que siempre; "hola".toSnakeCase() es un extra que solo existe adentro de una expresión de n8n (o del nodo Code).
Ejemplos prácticos
Casos que vas a repetir en casi cualquier workflow:
// Armar un saludo con el nombre del ítem actual
{{ "Hola, " + $json.nombre + "!" }}
// Valor por defecto si el campo no vino (operador ??)
{{ $json.telefono ?? "sin teléfono" }}
// Condicional ternario
{{ $json.monto > 10000 ? "premium" : "estándar" }}
// Formatear una fecha que viene en el ítem
{{ $json.fechaAlta.toDateTime().toFormat('dd/MM/yyyy') }}
// Unir un array de tags en un solo string
{{ $json.tags.join(", ") }}
// Campo anidado, con optional chaining por si no existe
{{ $json.direccion?.ciudad ?? "sin ciudad" }}
Errores comunes
- Campo que no existe:
$json.campodevuelveundefinedsi el campo no está en ese ítem, y una operación sobreundefined(como.toUpperCase()) tira error. Usá?.o??para protegerte. - Comillas mal puestas: mezclar comillas simples y dobles sin cerrar, o usar comillas curvas ("smart quotes") pegadas de Word en vez de comillas rectas.
- Olvidarse la doble llave: escribir
$json.emailsin{{ }}hace que n8n lo trate como texto literal, no como expresión. - Confundir Fixed con Expression: si el campo está en modo Fixed,
{{ $json.email }}se guarda tal cual, como texto, y nunca se evalúa. - Nombre de nodo mal escrito:
$('Webhok')en vez de$('Webhook')— tiene que coincidir exactamente, mayúsculas incluidas, con el nombre que aparece en el canvas.
Si necesitás repasar cómo fluyen los ítems entre nodos y qué son los datos fijados, volvé a la Sección 05 · Anatomía de un workflow. Y si lo que buscás es escribir lógica más larga que una sola expresión, esa es tarea del nodo Code, que se ve en la Sección 06 · Nodos esenciales y lógica.