Build
Data and expressions
You do not write formulas in a workflow. You pick values from lists, and Filmo stores what you picked as a structured expression. This page explains what the picker offers and how the values behave when the run executes.
Referencing a value
Link to this section: Referencing a valueIn any field that takes a value, «Insert variable» opens a picker with the variables available at that step. A variable belongs to a group:
| Group | Variable | Comes from |
|---|---|---|
| «System» | system_today | The engine, in every run: the date the run was queued. |
| Trigger | trigger_… | The trigger. See the page on triggers for each one's variables. |
| The step's name or description | variables_<step id> | Each step that publishes a value. The key is the id of the step, not a name you typed. |
| Variables | variables_<step id> | The «Set variable» steps, grouped together. The name you give is just a label. |
| Local | $<name>, $value, $this, $first, $second | Only inside a function that loops over a list: the name you give in map, filter, find, every and some; $value and $this in reduce; $first and $second in sort. |
- You drill down into structures: Order > Contact's email. The picker shows the path as a breadcrumb.
- The picker only offers variables whose type fits the field. A variable of the type Unknown fits no typed field.
- A step sees the system variables, the trigger, the steps before it at the same level and the steps of the levels above it.
- Because the key is the step's id, renaming a Set variable step does not break anything, and deleting a step breaks every reference to it. A broken reference is painted red in the editor and blocks switching the workflow live. The server does not check references when you save.
- The editor does not offer values created inside a branch or a loop after it ends, even though they do exist at run time if that branch ran. Compute the value before the composite step if you need it after.
- A «Try» step publishes only its outcome, as «Try result»: «Has failed» (true or false) and «Error message» (text, empty when nothing failed). What the steps inside it created never comes out, because after a failure some of it may not exist. See the Try step.
Kinds of value
Link to this section: Kinds of value| Kind | Example | Notes |
|---|---|---|
| Text | "Order {Order > number} is ready" | Plain text with variables inserted as chips. This is the normal way to build a text. |
| Number | 42 | Whole numbers only where a count of days or laps is asked. |
| True/false | true | Strict: only true or false, never "yes" or 1. |
| Date | 2026-10-15, or an instant | A date with no time, or an instant with a zone. Editors save instants in UTC. |
| List, Object | Built from other values. | |
| Variable | Order > contact's email | A pointer to a value. |
| «Function» | Add days | Only inside a Set variable step. |
A value has a type. The editor knows the type of every variable it offers. You declare types yourself in five places: the body of a webhook, the response of an HTTP request, the data of a signal, and the form of a manual trigger and of a "from another workflow" trigger. The types reference lists the eleven kinds with their operators (text, number, true/false, date, enumeration, record, structure, list, tuple, file and unknown). What each one does when the run checks data against it:
- A number is a JSON number: the text "42" is not one. True/false is strict.
- A date is a day or an instant. You must say which when you declare it; both are accepted at run time, and a declared date defaults to an instant.
- An enumeration holds the option's value, not its label.
- A structure has named fields and every declared field is required; extra fields are ignored. In a list every item is checked; in a tuple only the declared positions are.
- A text can say it is the id of a kind of record; that only helps the picker.
- A file is produced by a step and cannot be written by hand.
- Unknown accepts anything, including a missing or null value, and a variable of that type fits no typed field of the picker.
No optional fields
There is no optional or nullable type. A field you declare is required, and a null or missing value fails the check ("expected a text and received a null"). Declare a field as Unknown to accept anything, including null.
When the data does not match its declared type, the step (or the trigger) fails with the path of the first fields that do not match, for example customer.. A webhook body is validated after Filmo has answered; see the page on incoming webhooks.
Functions
Link to this section: FunctionsFunctions are available in the «Set variable» step. Choose «Function» as the kind of value, pick the function and fill in its arguments, which can be functions themselves. Use the result afterwards as a variable. The data of a Fire a signal step also accepts functions.
The functions come in eight groups: arithmetic, boolean, comparison, text, date, lists, conditional and objects. The functions reference lists each one with its arguments and where it can be used.
Three examples from the engine's own checks:
| Function | Result |
|---|---|
Add days(2026-08-24, 7) | 2026-08-31; with an instant, it keeps the time |
Days between(2026-08-24, 2026-08-31) | 7; the other way round -7 |
Format date(2026-08-24, dd) | 24 |
- Format date uses date-fns letters, such as
dd(not/MM /yyyy DD, which is refused); the month and day names it writes are always in Spanish, whatever language the app is in./MM /YYYY - Starts with, Ends with and Contains are case-sensitive and only accept text. An empty text to look for always matches.
- Arithmetic uses ordinary floating-point numbers, with their usual rounding artifacts. There is no currency type and no number-formatting function. For exact money totals use the Aggregate values step, which sums exactly.
- There is no default-value ("coalesce") function. You can build one with Condition (if, then, else).
Empty values
Link to this section: Empty valuesHow an empty or missing value behaves depends on where it is used. These rules decide most of the failures you will see.
| Where | A value that does not exist | A value that is null |
|---|---|---|
| Inside a text | The whole text becomes empty and the step fails with "the field has no value". There is no partial text. | Prints as an empty string. |
| As a whole field (required) | The step fails, "the field has no value". | The step fails. |
| As a whole field (optional) | Left out, without a word. | Left out, without a word. |
| Zero, false and the empty text | They are real values: 0 prints as "0" and false as "false". | |
| In a condition | See the page on conditions: equal is false, not equal is true, the rest fails. | |
| Set variable | The step fails: a variable cannot hold "nothing". | The same. |
| A step that did not run | Its variables do not exist. A branch that was not taken leaves nothing behind, and there is no "skipped" marker. |
Not the same
A reference whose path goes through a null parent counts as "does not exist" (the whole text fails), while a field that exists and is null counts as "empty" (it prints blank). If a value may be missing, test it with a condition first.
Dates and time zones
Link to this section: Dates and time zonessystem_todayis a date without a time, in the company's time zone. Trigger dates, such astrigger_createdAtandtrigger_scheduledAt, are instants in UTC. Compare like with like.- Add days, Days between and Format date keep the precision of what you give them: a date gives a date, an instant gives an instant. A date with an impossible day, or an instant without a zone, produces no value.
- Operations on instants may use the time zone of the server rather than the company's. Prefer dates without a time, which are exact, when the day matters.
- Change the company's time zone in «Date and formats» («Company time zone») in the business settings.
Checks when you save
Link to this section: Checks when you save- Saving checks the shape of the workflow only: that each field holds a kind of value it accepts, and that the definition is not more than 100 levels deep. A failed check is a 422 that names the path and the first three problems.
- Blank required fields are allowed in a draft. They stop you switching the workflow live.
- Whether a variable exists, whether a function's arguments make sense and whether a value has a value at run time are not checked on the server.
There is no formula bar and no "@" mention: in a text field you type text and insert variables through the picker, nothing else.
Related pages
Link to this section: Related pagesBuild
Conditions and operators
A condition compares one variable with one value. The Condition step sends the run down one of two paths; the Switch step picks the first of several.
Build
Steps
Steps run in order, one after another. Each can read what the trigger and the steps before it produced, and each can publish a value for the steps after it.
Build
HTTP requests
The HTTP step calls a URL from a run: to push a change to your own system, or to read from one. It is deliberately simple, and the simplicity has consequences you should know before you build on it.
Was this page helpful?