> ## Documentation Index
> Fetch the complete documentation index at: https://developers.insuranceboosters.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Variables y contexto

> Cómo pasar datos del trigger y entre pasos con plantillas, output, capture y context.

Antes de ejecutar un paso, la API resuelve las plantillas `{{...}}` dentro de su `input`. El paso `browser.use` también las resuelve dentro de `task`. Así pasas datos del disparo **y entre pasos** sin hardcodearlos.

## Tres formas de pasar datos entre pasos

| Forma                      | Cuándo usarla                                         | Cómo se lee en el siguiente paso                                         |
| -------------------------- | ----------------------------------------------------- | ------------------------------------------------------------------------ |
| `steps.<n>.output`         | Un paso posterior necesita la salida de uno concreto. | `"{{steps.0.output.referencia}}"`                                        |
| `capture` → `context`      | Varios pasos posteriores necesitan el mismo valor.    | `"{{context.accessToken}}"`                                              |
| `input` del siguiente paso | Quieres renombrar o seleccionar solo algunos campos.  | Declara claves en `input` y léelas como `input.<clave>` (en JavaScript). |

Flujo mental:

1. El paso A asigna un resultado (`output` en JavaScript, o la respuesta HTTP).
2. El paso B referencia ese resultado en su `input` con plantillas.
3. Opcionalmente, el paso A usa `capture` para guardar el valor en `context` con un nombre estable.

## Raíces disponibles en plantillas

| Expresión                          | Origen                                               |
| ---------------------------------- | ---------------------------------------------------- |
| `{{trigger.body.<campo>}}`         | Body JSON del webhook (u otro trigger).              |
| `{{trigger.headers.<nombre>}}`     | Headers del disparo, cuando existen.                 |
| `{{trigger.query.<campo>}}`        | Query string del disparo, cuando existe.             |
| `{{context.<clave>}}`              | Valores guardados con `capture` en pasos anteriores. |
| `{{steps.<indice>.output.<ruta>}}` | Salida de un paso previo (índice desde `0`).         |

### Reglas importantes

* Si la plantilla ocupa **todo** el string (`"{{trigger.body.monto}}"`), se conserva el tipo original (número, objeto, etc.).
* Si la plantilla está **dentro** de un texto (`"Hola {{trigger.body.nombre}}"`), el valor se convierte a string.
* Una plantilla sin valor resuelve a string vacío (`""`) cuando está embebida en texto.
* Las plantillas se resuelven en `input`, no dentro del campo `code` de JavaScript. Pasa datos por `input` y léelos como `input.<campo>`.
* En `browser.use`, puedes usar las mismas raíces directamente dentro de `task`.

## Ejemplo completo: JavaScript → HTTP con `steps.N.output`

Webhook de entrada:

```json theme={null}
{
  "referencia": " REC-1001 ",
  "monto": "1250.50"
}
```

Automatización de 2 pasos:

```json theme={null}
{
  "name": "Normalizar y notificar pago",
  "status": "disabled",
  "trigger": { "type": "webhook" },
  "steps": [
    {
      "name": "Normalizar pago",
      "actionKey": "code.javascript",
      "input": {
        "referencia": "{{trigger.body.referencia}}",
        "monto": "{{trigger.body.monto}}"
      },
      "code": "const referencia = String(input.referencia || '').trim();\nconst monto = Number(input.monto);\nif (!referencia) throw new Error('referencia requerida');\nif (!Number.isFinite(monto) || monto <= 0) throw new Error('monto inválido');\noutput = { referencia, monto, moneda: 'MXN' };"
    },
    {
      "name": "Avisar sistema externo",
      "actionKey": "http.request",
      "input": {
        "method": "POST",
        "url": "https://ejemplo.com/hooks/pago",
        "headers": {
          "Content-Type": "application/json",
          "X-Idempotency-Key": "{{steps.0.output.referencia}}"
        },
        "body": {
          "evento": "pago_recibido",
          "referencia": "{{steps.0.output.referencia}}",
          "monto": "{{steps.0.output.monto}}",
          "moneda": "{{steps.0.output.moneda}}"
        }
      }
    }
  ]
}
```

Qué ocurre:

1. El paso `0` recibe el trigger por `input`, limpia datos y deja `output = { referencia, monto, moneda }`.
2. El paso `1` lee esos campos con `{{steps.0.output.*}}` ya resueltos en su `input`.

## Ejemplo completo: JavaScript → JavaScript con `capture` y `context`

Usa `capture` cuando el valor debe reutilizarse en varios pasos o quieres un nombre estable (`context.pago`) en lugar de recordar el índice.

```json theme={null}
{
  "name": "Enriquecer y validar pago",
  "status": "disabled",
  "trigger": { "type": "webhook" },
  "steps": [
    {
      "name": "Normalizar",
      "actionKey": "code.javascript",
      "input": {
        "referencia": "{{trigger.body.referencia}}",
        "monto": "{{trigger.body.monto}}"
      },
      "code": "output = {\n  referencia: String(input.referencia || '').trim(),\n  monto: Number(input.monto)\n};",
      "capture": {
        "pago": {
          "from": "response.body",
          "required": true
        }
      }
    },
    {
      "name": "Validar reglas de negocio",
      "actionKey": "code.javascript",
      "input": {
        "pago": "{{context.pago}}",
        "limite": "{{trigger.body.limite}}"
      },
      "code": "const pago = input.pago || {};\nconst limite = Number(input.limite);\nif (!pago.referencia) throw new Error('falta referencia');\nif (pago.monto > limite) throw new Error('monto excede límite');\noutput = { ok: true, referencia: pago.referencia, monto: pago.monto };"
    },
    {
      "name": "Notificar",
      "actionKey": "http.request",
      "input": {
        "method": "POST",
        "url": "https://ejemplo.com/hooks/pago-validado",
        "headers": { "Content-Type": "application/json" },
        "body": {
          "referencia": "{{context.pago.referencia}}",
          "monto": "{{context.pago.monto}}"
        }
      }
    }
  ]
}
```

Notas:

* En un paso JavaScript, `capture.from = "response.body"` apunta al valor de `output`.
* En el paso 1, `input.pago` llega como objeto porque la plantilla ocupa todo el string.
* El paso 2 también puede leer `{{context.pago.referencia}}` sin depender del índice del paso.

## Ejemplo: HTTP → JavaScript → HTTP

```json theme={null}
{
  "name": "Token, transformar y consultar",
  "status": "disabled",
  "trigger": { "type": "webhook" },
  "steps": [
    {
      "name": "Obtener token",
      "actionKey": "http.request",
      "input": {
        "method": "POST",
        "url": "https://ejemplo.com/oauth/token",
        "headers": { "Content-Type": "application/json" },
        "body": {
          "clientId": "{{trigger.body.clientId}}",
          "clientSecret": "{{trigger.body.clientSecret}}"
        }
      },
      "capture": {
        "accessToken": {
          "from": "response.body",
          "path": "access_token",
          "required": true
        }
      }
    },
    {
      "name": "Armar consulta",
      "actionKey": "code.javascript",
      "input": {
        "polizaId": "{{trigger.body.polizaId}}",
        "token": "{{context.accessToken}}"
      },
      "code": "output = {\n  path: `/polizas/${encodeURIComponent(String(input.polizaId))}`,\n  authorization: `Bearer ${input.token}`\n};",
      "capture": {
        "consulta": {
          "from": "response.body",
          "required": true
        }
      }
    },
    {
      "name": "Consultar póliza",
      "actionKey": "http.request",
      "input": {
        "method": "GET",
        "url": "https://ejemplo.com{{context.consulta.path}}",
        "headers": {
          "Authorization": "{{context.consulta.authorization}}"
        }
      }
    }
  ]
}
```

## `capture`: contrato

```json theme={null}
"capture": {
  "accessToken": {
    "from": "response.body",
    "path": "token",
    "required": true
  }
}
```

| Campo      | Descripción                                                                                     |
| ---------- | ----------------------------------------------------------------------------------------------- |
| `from`     | `response.body`, `response.headers` o `response.status`.                                        |
| `path`     | Ruta con puntos dentro de esa fuente (opcional). Si omites `path`, capturas el objeto completo. |
| `required` | Si es `true` y falta el valor, el paso falla.                                                   |
| `maxBytes` | Tope opcional del valor capturado.                                                              |

## Buen ejemplo vs mal ejemplo

### Bien: pasar salida del paso 0 al paso 1

```json theme={null}
{
  "steps": [
    {
      "name": "Preparar",
      "actionKey": "code.javascript",
      "input": { "nombre": "{{trigger.body.nombre}}" },
      "code": "output = { nombre: String(input.nombre || '').trim() };"
    },
    {
      "name": "Enviar",
      "actionKey": "http.request",
      "input": {
        "method": "POST",
        "url": "https://ejemplo.com/hooks/hola",
        "headers": { "Content-Type": "application/json" },
        "body": { "nombre": "{{steps.0.output.nombre}}" }
      }
    }
  ]
}
```

### Mal: asumir variables globales entre pasos

```json theme={null}
{
  "steps": [
    {
      "actionKey": "code.javascript",
      "code": "nombreNormalizado = 'María'; output = { ok: true };"
    },
    {
      "actionKey": "code.javascript",
      "code": "output = { nombre: nombreNormalizado };"
    }
  ]
}
```

Cada paso corre aislado. El segundo no ve `nombreNormalizado`. Debes publicar el valor en `output` (y leerlo con `steps.0.output` o `capture`/`context`).

### Mal: plantilla dentro de `code`

```json theme={null}
{
  "actionKey": "code.javascript",
  "code": "output = { referencia: '{{trigger.body.referencia}}' };"
}
```

Esto **no** interpola el trigger. Declara `"referencia": "{{trigger.body.referencia}}"` en `input` y usa `input.referencia`.

### Mal: índice de paso incorrecto

Si insertas un paso al inicio, los índices cambian. `{{steps.1.output.x}}` puede dejar de apuntar al paso que creías. Para valores reutilizados, prefiera `capture` + `{{context.x}}`.

## Triggers de contacto o tablero

Si el disparo viene de un contacto o registro, usa la bolsa `values`:

| Trigger                                          | Ruta típica                                 |
| ------------------------------------------------ | ------------------------------------------- |
| Registro creado (`database_record_created`)      | `{{trigger.body.record.values.<fieldId>}}`  |
| Registro actualizado (`database_record_updated`) | `{{trigger.body.record.values.<fieldId>}}`  |
| Contacto creado/actualizado                      | `{{trigger.body.contact.values.<fieldId>}}` |

Metadatos del sobre (por ejemplo `trigger.body.record.id`) viven fuera de `values`.

Por ejemplo, este `input` entrega a un paso HTTP el registro y dos de sus campos:

```json theme={null}
{
  "recordId": "{{trigger.body.record.id}}",
  "estado": "{{trigger.body.record.values.estado}}",
  "responsable": "{{trigger.body.record.values.responsable}}"
}
```

## Relacionado

* [Tipos de paso](/automatizaciones/tipos-de-paso)
* [Paso JavaScript](/automatizaciones/paso-javascript)
* [Paso HTTP](/automatizaciones/paso-http)
* [Crear automatización](/automatizaciones/crear-automatizacion)
