Function Reference
Last updated 23 May 2026

Functions are called by name with parentheses: {{ functionName(arg1, arg2) }}. Arguments shown with = value are optional and have that default.
1. Looking up records
These functions read data from across your Flexie account, so a template can show related information, a contact's invoices, an account's contacts, totals, counts.
| Function | What it does | Example |
|---|---|---|
| findOne(type, field, value, …) | Fetch a single record matching all the field/value pairs you give (joined with AND). Returns an empty result if none found. | {{ findOne("lead", "email", "john@example.com") }} |
| findMany(type, field, value, orderBy='id', dir='ASC', limit=1000) | Fetch many records matching one field, optionally sorted and capped. | {{ findMany("invoice", "status", "finalized", "date_added", "DESC", 50) }} |
| findCount(type, field, value, …) | Count records matching all field/value pairs. | {{ findCount("deal", "stage_id", 5, "owner_id", 3) }} |
| findSum(type, column, field, value, …) | Add up a numeric column across matching records. | {{ findSum("invoice", "total_incl_tax", "contact_id", 42, "status", "finalized") }} |
| findMin(type, column, field, value, …) | Smallest value of a column across matching records. | {{ findMin("deal", "amount", "stage_id", 5) }} |
| findMax(type, column, field, value, …) | Largest value of a column across matching records. | {{ findMax("deal", "amount", "is_won", 1) }} |
| findByPhoneNumber(type, phoneField, number) | Find a record by a phone number held in a specific field. | {{ findByPhoneNumber("contact", "phone", "+155501234") }} |
| getSmartListRecords(type, listAlias) | All records belonging to a saved smart list. | {{ getSmartListRecords("lead", "high_value") }} |
| getOrganization(idOrVat) | Look up an organisation by its id or VAT number. | {{ getOrganization("DE123456789") }} |
| getUserById(userId) | Fetch a user (name, email, phone, profile image, etc.). | {{ getUserById(5).full_name }} |
| getAccountContacts(accountId) | All contacts linked to an account. | {{ getAccountContacts(42) }} |
| findDeals(type, entityId) | All deals linked to a contact, account, or lead. | {{ findDeals("contact", 42) }} |
| findCases(type, entityId) | All cases linked to a record. | {{ findCases("account", 10) }} |
| findDealsValue(type, stage='*', pipeline='*', entityId) | Total deal value for a record, optionally filtered by stage (pending/won/lost/*) and pipeline. | {{ findDealsValue("contact", "won", "*", 42) }} |
Result limits. Look-ups that can return many rows are capped at 1,000 results to keep templates fast. Filter tightly and sort, rather than pulling everything.
Ready-made statistics
These return a small bundle of figures in one call, handy for customer summaries.
| Function | Returns |
|---|---|
| getDealStats(type, entityId) | total, active, won, lost |
| getInvoiceStats(type, entityId) | invoice_total, credit_memo_total, draft, sent, canceled, won, finalized, pending, active |
| getCaseStats(type, entityId) | total, open, pending, solved, closed |
In an account-context template, the account's own id is read at the top level:
This account has {{ getDealStats("account", id).won }} won deals
worth {{ findDealsValue("account", "won", "*", id) | number_format(2) }}.
Advanced: direct queries
For administrators and power users who need data the helpers above do not cover:
| Function | What it does |
|---|---|
| query(sql) | Run a read-only data query and get the rows back. Only retrieval is allowed (SELECT and WITH only, no INSERT, UPDATE, DELETE, DROP, and no SELECT *). Results are capped at 1,000 rows. Returns the rows, or {"error": "…"} if the query is rejected. |
{% set rows = query("SELECT id, email FROM leads WHERE status = 1 LIMIT 10") %}
Matching leads: {{ rows | length }}
2. Numbers and maths
| Function | What it does | Example → result |
|---|---|---|
| add(a, b, …) | Add all arguments. | {{ add(10, 5, 3) }} → 18 |
| subtract(a, b) | a minus b. | {{ subtract(100, 30) }} → 70 |
| multiply(a, b, …) | Multiply all arguments. | {{ multiply(5, 4, 2) }} → 40 |
| divide(a, b) | a divided by b (empty if dividing by zero). | {{ divide(100, 4) }} → 25 |
| round(n, places=0, mode="ROUND_HALF_UP") | Round to a number of decimal places. | {{ round(3.14159, 2) }} → 3.14 |
| squareRoot(n) | Square root. | {{ squareRoot(16) }} → 4 |
| cubeRoot(n) | Cube root. | {{ cubeRoot(27) }} → 3 |
| max(a, b, …) | Largest of the given values (also works on a list). | {{ max(1, 3, 2) }} → 3 |
| min(a, b, …) | Smallest of the given values (also works on a list). | {{ min(1, 3, 2) }} → 1 |
| random(…) | A random value: random() (a number), random(5) (0 to 5), random(["a","b"]) (a random item), random("ABC") (a random character). | {{ random(["a","b","c"]) }} |
| range(from, to, step=1) | A sequence of numbers, handy in a loop. | {% for i in range(1, 5) %}…{% endfor %} |
| numberFormat(n, decimals=0, style="none", round="ROUND_HALF_EVEN") | Format with grouping. style is ",|." (1,234.56), ". | ," (1.234,56), or none. |
| reverseFormattedNumber(text, style=",|.") | Turn a formatted string back into a number you can calculate with. | {{ reverseFormattedNumber("1.234,56", ".|,") }} → 1234.56 |
| formatCurrency(amount, symbol="$", decimals=2, style=",|.", position="before") | Format a money amount with a currency symbol. | {{ formatCurrency(1234.5, "€", 2, ".|,", "after") }} → 1.234,50€ |
Why
reverseFormattedNumbermatters. Once a number has thousands separators it is text, not a number,"1,200" + 50will not behave. Reverse it first, do the maths, then format the result.
For totals across a list of records (sumField, avgField, minField, maxField) see Filters & collections.
3. Dates and time
| Function | What it does | Example |
|---|---|---|
| now(format="Y-m-d H:i:s", tz="UTC") | The current date and time. | {{ now("Y-m-d") }} |
| date(value, format="Y-m-d H:i:s", toTz="UTC", fromTz="UTC") | Reformat a date and optionally convert its timezone. | {{ date(date_added, "M j, Y") }} |
| dateAdd(date, amount, unit="days", format="Y-m-d H:i:s") | Add time to a date. Units: years, months, weeks, days, hours, minutes, seconds. | {{ dateAdd(due_date, 30, "days") }} |
| dateSubtract(date, amount, unit="days", format=…) | Subtract time from a date. | {{ dateSubtract(now(), 1, "months") }} |
| dateDiff(date1, date2, unit="days") | Signed difference between two dates. | {{ dateDiff(date_added, now()) }} |
| daysBetween(date1, date2) | Whole days between two dates (always positive). | {{ daysBetween(due_date, now()) }} |
Format codes are the common date pieces: Y 4-digit year, m month number, d day, H hour (24h), i minutes, s seconds, M short month name, j day without leading zero, l weekday name. Example: "l, j M Y" → Tuesday, 3 Jun 2025.
{# Current record = the invoice #}
{% if daysBetween(due_date, now()) > 0 and status != "paid" %}
This invoice is {{ daysBetween(due_date, now()) }} days overdue.
{% endif %}
4. Working with text
| Function | What it does | Example → result |
|---|---|---|
| truncate(text, length=100, suffix="…") | Shorten text, adding a suffix. | {{ truncate(subject, 30) }} |
| padString(value, length, char=" ", side="left") | Pad to a fixed width. | {{ padString(42, 6, "0") }} → 000042 |
| startsWith(text, prefix) | True if text begins with the prefix. | {{ startsWith(phone, "+44") }} |
| endsWith(text, suffix) | True if text ends with the suffix. | {{ endsWith(file, ".pdf") }} |
| wordCount(text) | Number of words. | {{ wordCount(note.body) }} |
| toAlphanumeric(text) | Strip everything except letters and numbers. | {{ toAlphanumeric("AB-12/3") }} → AB123 |
| htmlToText(html) | Convert HTML into clean plain text (great for turning an email body into SMS). | {{ htmlToText(email.html) }} |
| findAndReplace(html, start, end, replacement) | Replace whatever sits between two markers. | {{ findAndReplace(body, "", "", newPart) }} |
| urlEncode(text) | Make text safe to drop into a URL. | {{ urlEncode(email) }} |
| md5(text) | An MD5 fingerprint of the text. | {{ md5(email) }} |
| base64encode(text) / base64decode(text) | Encode or decode text in base64. | {{ base64encode(payload) }} |
For pattern-based find-and-replace and slug-making, see the regex_replace and slugify filters in Filters & collections.
Pulling things out of text
| Function | What it does |
|---|---|
| verifyEmail(text) | 1 if it looks like a valid email address, else 0. |
| extractEmails(text) | All email addresses found in a block of text. |
| extractPhoneNumbers(text) | All phone numbers found in text. |
| extractWebsiteLinks(text) | All web links found in text. |
{% set found = extractEmails(email.text) %}
{% if found | length > 0 %}Reply-to candidate: {{ found[0] }}{% endif %}
5. Tags
Flexie stores tags as a single pipe-separated string (vip|renewal). These helpers make working with them safe.
| Function | What it does | Example → result |
|---|---|---|
| addTag(tags, newTag) | Append a tag. | {{ addTag("red|blue", "green") }} → red |
| removeTag(tags, tag) | Remove a tag (case-insensitive). | {{ removeTag("red|blue", "BLUE") }} → red |
| matchAnyTag(tagsA, tagsB) | 1 if the two sets share at least one tag. | {{ matchAnyTag(tags, "vip|gold") }} |
| matchAllTags(tagsA, tagsB) | 1 if the two sets are identical. | {{ matchAllTags(tags, "vip|gold") }} |
6. JSON and structured data
When a value holds JSON (for example data received from another system), these turn it into something you can read.
| Function | What it does |
|---|---|
| jsonDecode(text, associative=true) | Turn a JSON string into data you can read with dots or brackets. |
| jsonPath(data, expression) | Pull a nested value out using a path like $.order.items[0].sku. |
| isCollection(value) | True if the value is a list or array. |
{% set order = jsonDecode(__data.webhook_body) %}
First item: {{ jsonPath(order, "$.items[0].name") }}
There is also a json_decode and json_path filter form, see Filters & collections.
7. Unique values and sequence numbers
| Function | What it does |
|---|---|
| uuid() | A random globally-unique identifier. |
| uniqueId() | A shorter unique id. |
| incrementAndGetSequenceNumber(type, field, matchField, matchValue) | Safely bump a counter column by one and return the new value, the reliable way to generate gap-free invoice or order numbers, even under load. |
Invoice no. {{ incrementAndGetSequenceNumber("invoice", "sequence_no", "year", "2026") }}
8. Links, attachments, and QR codes
| Function | What it does |
|---|---|
| getAttachments(type, id, name="*", firstOnly=false) | Attachment details for a record (optionally filtered by filename). |
| getAttachmentsPath(type, id, name="*", firstOnly=true) | Direct download URLs for attachments. |
| addAttachments(type, id, name="*", …) | Ready-made HTML links to attachments. |
| getFormAttachments(payload) | Attachments from a form submission. |
| publicAttachmentLink(type, id, userId=null) | A secure public link to an attachment that needs no login. |
| qrCode(text, border=0, width=140, height=140, bg="#FFFFFF", fg="#333333") | A QR code image (SVG) for any text or URL. |
Scan to pay: {{ qrCode("https://pay.example.com/invoice/" ~ id, 2, 200, 200) }}
9. Security helpers (advanced)
For building authenticated links and signed payloads when integrating with other systems. These are administrator-level tools.
| Function | What it does |
|---|---|
| encrypt(text) / decrypt(text) | Encrypt or decrypt with your account's secret key. |
| signUrl(url, expiryHours) | Produce a tamper-proof, time-limited link. |
| hashHmac(algorithm, data, secret) | An HMAC signature (e.g. sha256) for verifying payloads. |
| jwtEncode(payload, key, alg="HS256") / jwtDecode(token, secret) | Build or read a JSON Web Token. |
10. Utility
| Function | What it does |
|---|---|
| coalesce(a, b, c, …) | The first value that is not empty, a clean way to provide fallbacks. |
| contains(haystack, needle) | True if text contains a substring, or a list contains a value. |
| getQueryString(name) | Read a value from the current URL's query string. |
| memoryGet(key) | Read a value from short-lived shared memory (set elsewhere by a workflow's "Memory Set" action). Read-only here. |
| getAiChatHistory(key="") | Retrieve stored AI conversation history. |
| dump(value) | Print a value's full contents, for debugging a template only. |
Hello {{ coalesce(first_name, "there") }}!
Some specialised functions also exist for fiscal or regulatory document signing and for streaming external data files. These are configured by administrators for specific integrations and are outside everyday use.
Next steps
- Filters & collections: transforming values with
| filtersand working across lists of records. - Recipes: these functions combined into real solutions.