Transform — Declaratively reshape data into a new value

Reshapes data into a new structure without writing Python code. Use it to extract fields, rename keys, merge values from multiple upstream nodes, or build exactly the payload shape a downstream node expects.

When to Use

Use Transform when:

  • You need to rename or restructure the output of a trigger or action before passing it downstream
  • You want to combine fields from multiple upstream nodes into one object
  • You need to flatten nested data or create a new shape from existing values
  • You want to pick, pluck, or merge fields using expression helpers

For more complex logic (loops, conditionals, calculations), use Code instead.

Inputs

HandleTypeDescription
inputanyThe upstream value to transform. Optional — you can also reference any upstream variable via template bindings in the template setting.

Output

HandleTypeDescription
resultanyThe transformed output value.

The result is accessed in downstream nodes as {{ transform.* }}. When the output is a single object, reference fields directly (e.g., {{ transform.customerId }}). When the output is a scalar or array, use {{ transform }} or {{ transform.result }} depending on shape.

Settings

SettingTypeDefaultDescription
modeenumobjectTransformation strategy. object — build a new object from a JSON template. expression — evaluate a single expression and return its result.
templatecode editor (JSON)Defines how to build the output from the input using template expression bindings. Required.

Object mode

In object mode, the template is a JSON object where values use {{ }} bindings:

{
  "userId": "{{ webhook.body.data.object.customer }}",
  "amount": "{{ webhook.body.data.object.amount_received }}",
  "currency": "{{ webhook.body.data.object.currency }}",
  "eventType": "{{ webhook.body.type }}"
}

When an entire value is a single {{ }} expression, the original type is preserved (number, list, dict). When mixed with surrounding text, the result is a string.

Expression mode

In expression mode, the template is a single expression that returns a value directly:

{{ webhook.body.data.object.customer }}

Use expression mode with helpers like pick(), pluck(), or merge() for more powerful transformations:

{{ pick(input.body, "name", "email", "company") }}
{{ pluck(input.body.users, "email") }}
{{ merge(input.body.defaults, input.body.overrides) }}

See the Expression Reference for the full list of helpers.

Example

Canvas

Extract and rename fields from a Stripe payment_intent.succeeded event:

Webhook → Transform → HTTP Request

Transform settings:

  • Mode: object
  • Template:
    {
      "customerId": "{{ webhook.body.data.object.customer }}",
      "amountCents": "{{ webhook.body.data.object.amount_received }}",
      "currency": "{{ webhook.body.data.object.currency }}",
      "paymentId": "{{ webhook.body.data.object.id }}"
    }
    

The downstream HTTP Request node can reference {{ transform.customerId }} directly without navigating the full Stripe payload.

TSL

import webhook from @tensorify/webhook-trigger:4.0.0
import transform from @tensorify/transform:3.0.0
import http_request from @tensorify/http-request:3.0.0

node trigger @tensorify/webhook-trigger:4.0.0 {
    path = "/stripe"
    method = "POST"
    provider = "stripe"
}

node format @tensorify/transform:3.0.0 {
    mode = "object"
    template = "{\"customerId\": \"{{ webhook.body.data.object.customer }}\", \"amountCents\": \"{{ webhook.body.data.object.amount_received }}\", \"currency\": \"{{ webhook.body.data.object.currency }}\"}"
}

node notify @tensorify/http-request:3.0.0 {
    method = "POST"
    url = "https://api.example.com/payments"
}

trigger.payload -> format.input
format.result -> notify.body

Error Handling

Transform has a hidden On Error control output branch. Enable it via the "Error output handle" toggle at the bottom of the settings panel, or connect an edge to error in TSL (which enables it automatically).

The error branch fires when:

  • The template setting is empty or missing
  • The template produces invalid JSON after binding resolution (object mode)
  • An expression fails to evaluate (expression mode or invalid helper usage)

When the error branch executes, downstream nodes can access the error details via {{ <nodeId>__error }}:

FieldTypeDescription
errorstringHuman-readable error message describing what failed
nodeIdstringThe ID of the node that failed

If the error branch is not connected, template errors halt execution on that path.

Connect the error output to a fallback action or Stop node when malformed upstream data is possible.

TSL with error branch

import transform from @tensorify/transform:3.0.0
import stop from @tensorify/stop:3.0.0

node format @tensorify/transform:3.0.0 {
    mode = "object"
    template = "{\"email\": \"{{ webhook.body.email }}\"}"
}

node halt @tensorify/stop:3.0.0

format.error -> halt.input

Common Gotchas

  • Missing fields evaluate to null: If a referenced variable does not exist, the binding evaluates to null. Use If to guard against missing fields, or connect the error branch for unexpected template failures.
  • No array looping: Transform does not loop over arrays natively. For list mapping, use expression mode with a list comprehension (e.g., {{ [item.name for item in input.body.items] }}) or use Code.
  • Template is required: An empty template always fails. Provide a valid JSON template (object mode) or expression (expression mode).
  • JSON validity in object mode: After bindings resolve, the template must be valid JSON. A trailing comma or unquoted string will trigger the error branch.

See Also

  • Expression Reference — full list of helpers (pick, pluck, merge, coalesce, etc.)
  • Code — transform with Python logic
  • HTTP Request — send transformed payloads to APIs
  • If — branch based on transformed values
On this page