Where It Runs & Its Limits

Last updated 23 May 2026

Flexie Scripting running inside a sandbox, with access to the current record, __data, and a documented toolkit

The record a script is given

Every place that evaluates Flexie Scripting hands it a record to work on plus the always-available global values. What that record is depends on the context:

Where it runs The record it is given
An email template sent about a contact that contact
An invoice PDF template that invoice
A quote PDF template that quote
A workflow action on a deal that deal
An SMS template the message's recipient record
A snippet the same record as the template that included it

You read that record's fields directly, {{ first_name }}, {{ total_incl_tax }}, with no record. prefix. To work with any other record (a related lead, a recent invoice, the linked account), use a look-up function such as findOne, findMany, or getAccountContacts, and assign the result to a variable of your own.

Built-in related arrays. In a workflow whose record type has standard relations, for example a Deal, which has one linked Account and many linked Contacts, those related records are also exposed automatically as arrays under the plural name: {{ contacts[0].first_name }}, {{ accounts[0].account_name }}. Use [0] to take the first (or only) one.

The __data namespace (inside workflows)

When a script runs inside a workflow, it also has access to everything the workflow has gathered so far, under a single namespace called __data.

This is how data flows from one step to the next. When a workflow is triggered by an incoming signal (an email arrives, a form is submitted, a webhook is received), or when an earlier action stored a value, that information is available to every later step as {{ __data.something }}:

{{ __data.incoming_email.subject }}
{{ __data.incoming_sms.text }}
{{ __data.last_task.due_date }}

The full mechanics of __data, what each trigger provides, and how to store your own values for later steps, are covered in Passing data between steps. For dynamic endpoints, the incoming request body is also exposed this way, see Dynamic Endpoints, Receiving data.

Result limits

To keep templates fast and safe, look-ups that can return many rows are capped at 1,000 results:

If you need totals across more than that, total at the source with findSum, findCount, findMin, findMax (which compute in the database) rather than pulling every row back and adding them up in the template.

query(...) is read-only: only SELECT and WITH are accepted. Anything that would change or remove data (INSERT, UPDATE, DELETE, DROP), and SELECT *, are rejected. You will get an {"error": "…"} result instead.

The safety sandbox

Flexie Scripting runs inside a protected sandbox. This is what keeps it safe to expose in templates and workflow fields. The boundaries:

Only the documented toolkit exists

Only the functions, filters, and tags listed in this section are available. If a script uses anything else, it stops with an error rather than doing something unexpected. The available tags are exactly:

(There is no "include a file," "import," "macro," or similar, those are deliberately not available.)

You read data, you do not call methods on it

Records are provided to your script as plain data, so reading fields works exactly as shown: {{ email }}, {{ total_incl_tax }}, {{ row['some key'] }} (where row is a variable you set from a look-up). What you cannot do is call methods or reach internal properties on objects; the sandbox does not permit it. Everything you need is exposed either as readable record data or as one of the documented functions.

It cannot reach outside Flexie

A script cannot read or write files on the server, run programs, or use anything that has not been deliberately made available. The only ways a script touches the outside world are through the dedicated, controlled functions documented here (for example a webhook is sent by a workflow action, not by the template language itself).

Errors are contained

When a script fails, a bad function name, malformed input, it raises an error in that one place. It does not crash the surrounding page or corrupt data.

Practical implications

Next steps