English
English
English
English
Expressions are how you compute values inside a spec. Anywhere an operation expects a value — an external_id, a condition for if_else, the items to loop over in for_each — you reach for an expression. They're the spec language's verbs for getting values, the way operations are its verbs for doing things.
Most expressions take other expressions as arguments — that's how you build up a value step by step (e.g. an if_else's condition might be an equals whose left side is a var reference and right side is a literal).
This page covers all of them, grouped by what they're for:
literal, varand, or, not, equals, equals_one_off, greater_than, is_null, is_empty, existsconcat, implode_with_spaces, string_between, string_contains, string_replacesum, multiply, divide, minimumparse_datetime, parse_timestamp, datetime_differenceThese two are the foundation: every other expression eventually bottoms out in a literal value or a variable lookup.
Use this when you want to put a fixed value directly into the spec — a string like "Deal | won", a number like 1.21, a hard-coded ID. The Spec Builder accepts whatever type you type in.
valueoptionalanyThe literal value. Strings, numbers, and booleans are all accepted.
Use this to read the value of a variable currently in scope — a field on the source model, an enrichment, a constant, the result of an earlier return_as, or the iteration item inside a for_each body. Variable picker autocompletes from the scope panel.
varrequiredvariable pathThe dotted path to the variable. Examples: source_model.id, event.ghl_opportunity.assignedTo, agent_external_identity.id.
Boolean expressions used in if_else conditions and combined with and / or / not to express richer conditions.
Use this when several conditions all need to be true. Short-circuits — stops checking the rest as soon as one argument is false.
argumentsrequiredlist of booleansThe conditions to evaluate. Returns true only if every one is true.
Use this when at least one of several conditions needs to be true. Short-circuits — stops checking the rest as soon as one argument is true.
argumentsrequiredlist of booleansThe conditions to evaluate. Returns true if at least one is true.
Use this to flip a boolean — useful for "if X is not true, then..." conditions.
expressionrequiredbooleanThe boolean to negate.
Use this to compare two values for equality. Works for strings, numbers, and other comparable values; comparisons are loose (string "5" and number 5 are equal).
leftrequiredanyrightrequiredanyUse this when you want to check whether a value matches any of several alternatives — like a multi-way equality check without writing a chain of or + equals.
needlerequiredanyThe value you're looking for.
haystackrequiredlistThe values to check against. Returns true if needle matches any of them.
A note on the name
The identifier is equals_one_off (with the extra "f"). It's a typo from when the expression was first added, but specs in production already use it under that name, so renaming would break them. The label in the inspector reads "Equals One Of" — that's how it's pronounced.
Use this to check whether one number is strictly greater than another. For "greater than or equal," combine with equals using or.
leftrequirednumberrightrequirednumberUse this to check whether a variable's value is null — typically as a guard before reading a field that the source might not always populate.
varrequiredvariable pathThe variable to check. Returns true if its value is null.
Use this to check whether a variable is "empty" in the everyday sense — null, empty string, zero, empty array. Useful for guarding a branch that should only run when there's actually a value to act on.
varrequiredvariable pathThe variable to check. Returns true if its value is null, empty, or zero.
Use this to check whether a variable is even in scope at this point in the spec — different from is_null, which assumes the variable exists and asks whether its value is null. Useful when an enrichment is optional and you need to skip the branch entirely if the field wasn't loaded.
varrequiredvariable pathThe variable to check. Returns true if a variable with this path is currently in scope.
Example: matching a custom field by ID and value
Inside a for_each over a contact's custom fields, you want to react only when one specific field has a specific value. The condition uses and to combine two equals comparisons:
equals(field.id, "XlG7djKG0BdlUx2njBZa")equals(field.value, "Ja")Wrapped in an if_else, this gives you a single branch that runs only when the named custom field is set to "Ja" — used in the GHL stage-change processor to detect Setter-handled deals.
For building IDs, types, and any text the spec needs to compose from pieces.
Use this when you want to glue several values together end to end into a single string — typically for building composite IDs that look like <a> | <b> or <prefix><value>. If you want a separator, include it as one of the arguments (a literal " | " is the standard).
argumentsrequiredlist of strings or numbersThe values to join, in order. They're concatenated with no separator.
Use this when you want to glue several values together with single spaces between them — useful for building human-readable strings like a person's full name from first + last. Empty/null arguments get skipped, so you don't end up with double spaces or trailing whitespace.
argumentsrequiredlist of strings or numbersThe values to join. Joined with a single space; nulls and empty strings are dropped.
Use this to extract the text between two markers in a string. Useful for parsing a value out of a free-form string the source delivers — for example pulling an order number out of "Order #1234 confirmed".
subjectrequiredstringThe string to search in.
fromrequiredstringThe marker the wanted text starts after.
torequiredstringThe marker the wanted text ends before.
If either marker isn't found in the subject, the expression returns null.
Use this to check whether a string contains another string anywhere inside it. Case-insensitive.
subjectrequiredstringThe string to search in.
searchrequiredstringThe substring to look for.
Use this to replace every occurrence of one substring with another — or to strip a substring entirely by leaving the replacement empty. Used in the production specs to clean up source data, like stripping quotes from a date string before parsing it.
subjectrequiredstringThe string to operate on.
searchrequiredstringThe substring to find.
replaceoptionalstringThe replacement. If left empty, every match of search is removed.
Example: stripping multiple characters
Source data sometimes arrives with stray quotes around values — "'2026-01-15'" instead of 2026-01-15. Two string_replace calls nested together (one stripping ', one stripping ") clean it up before parsing:
string_replace has subject = an inner string_replacestring_replace has subject = payload.Date, search = ', replace = empty", replace = emptyThe result lands in a define_variable named date, which the rest of the spec then uses freely. Pattern from the Google Ad Spend processor.
Arithmetic for sums, totals, and conversions.
Use this to add numbers together. Common case: accumulating a running total inside a for_each loop, with the previous total and the new value as arguments.
argumentsrequiredlist of numbersThe numbers to add. Empty list returns 0.
Use this to multiply numbers together. Common case: applying a VAT factor to a unit price × quantity (multiply(1.21, line.price, line.quantity)).
argumentsrequiredlist of numbersThe numbers to multiply. Empty list returns null.
Use this to divide one number by another — for example computing an average, or converting between units. Returns null if the denominator is 0 (or if either side is missing) so you don't get an error mid-spec.
numeratorrequirednumberdenominatorrequirednumberUse this to take the smaller of several numbers. The production specs use this as a cap — for example, capping a sale's total value at 1 000 000 to keep one outlier from skewing every chart.
argumentsrequiredlist of numbersThe numbers to compare. Returns the smallest.
Example: line totals with VAT
A line on an order has a quantity and a price, both excluding VAT. The line's contribution to the running total is computed with one multiply:
1.21 (literal), line.quantity, line.priceThe result is the VAT-inclusive line total. Wrapping that whole expression in a sum together with the running total gives you the new running total — that's the inner accumulation step in the Troublefree offer processor.
Source systems hand you dates as strings or numeric timestamps. These expressions turn them into proper datetime values that operations like upsert_activity and if_else (with a greater_than) can work with.
Use this when your source field is a date or datetime string — anything Carbon can parse, like "2026-01-15T14:32:00Z", "2026-01-15", or "15-01-2026 14:32". The result lands in your tenant's timezone.
datetimerequiredstringThe string to parse.
If the string is just a date with no time, the time defaults to 06:00 (so daily activities don't all stack on midnight, which causes off-by-one display issues in Amsterdam time).
Use this when your source field is a numeric Unix timestamp — typically the case with APIs that return milliseconds since epoch (GoHighLevel, for example). Auto-detects whether the value is in seconds, milliseconds, or microseconds.
timestamprequiredstring or numberThe Unix timestamp. Whatever unit it's in, this expression figures it out.
Use this to compute the time between two datetimes. Returns the difference in seconds — multiply if you need a different unit.
startrequireddatetimeendrequireddatetimeReturns 0 if either side is null.