Values and Templates in Workflows

How a workflow step uses values from the run, like form answers, web requests, and earlier steps, and how to combine them into text and JSON with {{ }}.

Where a run's values are

Everything a workflow run knows is in data. These are the three places you'll use most:

WhatPathExample
Answers from the form that started the rundata.values.<field key>data.values.email
A web request that started the rundata.request.body.<…>data.request.body.order.total
What an earlier step diddata.<step id>.<…>data.card_create.body.id

A step's ID appears under its name in the editor, like card_create. What each step leaves behind is listed on that step's help page. For example, Send a web request leaves status and body.

You'll rarely need to type a path. Click Insert value next to a box to see every value available at that step, by name, and Skidle adds the right path for you.

Templates: fixed text with values in {{ }}

Some boxes use a template: ordinary text or JSON, with {{ }} around the parts that come from the run. The address, headers, and body of a web request are templates.

https://api.example.com/orders/{{ data.request.body.order.id }}

When the workflow runs, each {{ … }} is replaced by its value. Everything outside the braces stays exactly as you wrote it.

Templates in JSON

A JSON template is normal JSON with {{ }} where a value goes:

{
  "email": "{{ data.values.email }}",
  "firstName": "{{ data.values.first_name }}",
  "source": "skidle",
  "quantity": "{{ data.values.qty }}",
  "greeting": "Hi {{ data.values.first_name }}!"
}

Three rules decide what you get:

  1. A value on its own keeps its type. "quantity": "{{ data.values.qty }}" sends a number if the value is a number, and a list if it's a list. The quotes around a lone {{ }} don't turn it into text.
  2. A value inside other text becomes text. "Hi {{ data.values.first_name }}!" sends "Hi Ana!". Quotes and line breaks in the value are escaped for you.
  3. A missing value becomes null.

You can also write a value without quotes: "count": {{ data.values.count }}.

The editor checks templates as you type. It lets you know if the JSON won't be valid once the values are filled in, or if Skidle can't read something inside {{ }}.

Templates in an address

In an address, each value is made safe for a URL. For example, a space becomes %20 and an & becomes %26, so a name like "Ben & Jerry" can't break the address. If the whole address is one value, like {{ data.values.url }}, it's used as is.

Do more than read a value (JSONata)

What goes inside {{ }} is JSONata, a small language for choosing and shaping data. Reading a path is the simplest kind of JSONata. Here are a few other things that are often useful:

ToWriteResult
Combine textdata.values.first_name & " " & data.values.last_nameAna Ruiz
Make text uppercase$uppercase(data.values.first_name)ANA
Clean up an email address$lowercase($trim(data.values.email))ana@example.com
Turn a number into text$string(data.request.body.order.id)"1042"
Turn text into a number$number(data.values.qty) + 14
Round a number$round(data.values.temperature, 0)6
Choose between two valuesdata.values.temperature > 5 ? "Too warm" : "OK"Too warm
Use a default when emptydata.values.notes ? data.values.notes : "No notes"No notes
Get the first item in a listdata.request.body.order.items[0].skuLATTE
Count items$count(data.request.body.order.items)2
Add up a total$sum(data.request.body.order.items.(qty * price))12
List one field from each item$join(data.request.body.order.items.sku, ", ")LATTE, SCONE
Keep only some itemsdata.request.body.order.items[qty > 1].skuLATTE
Get the current time$now()2026-09-24T16:15:12.758Z

Things that often trip people up:

  • Equals is one =, not two: data.values.status = "open". Not equal is !=.
  • Text comparisons are case-sensitive, so $contains(data.values.email, "@example.com") is false for Ana@Example.com. Use $lowercase(…) first.
  • A field key with a dash or space goes in backticks: data.request.body.`first-name` . Insert value does this for you.
  • $exists(x) is true even when x is empty (null). To treat an empty value as missing, use x ? … : ….

For the full language, see jsonata.org.

Secrets in templates

Never put an API key or token in a workflow as plain text. Save it in Account under Secrets, then use {{ secrets.NAME }}, like "Authorization": "Bearer {{ secrets.CRM_KEY }}". See Secrets.