Use this file to discover all available pages before exploring further.
penscript expressions are evaluated in real time. They can be embedded within forms, case templates, automations, notifications, and API calls. Every expression receives a scope — the set of variables and data available at evaluation time — and returns a result.This page is a tour of the language. It introduces the two expression modes, shows how operators compose, and walks through the major categories of what penscript can express.
Variable references and simple logic embedded inside strings. Lightweight, readable, and ideal for labels, notifications, and short conditions.
"Hello {user.given_name}, your case #{case.reference} is {status}."// Scope: { "user": { "given_name": "Marie" }, "case": { "reference": "2024-0847" }, "status": "active" }// → "Hello Marie, your case #2024-0847 is active."
Inline expressions also support pipes, comparisons, and ternaries:
"{data.birthdate | age >= 18 ? 'Adult' : 'Minor'}"// → "Adult" or "Minor"
Both modes can be mixed freely. A JSON operator can contain inline expressions in its arguments, and inline expressions can reference values computed by operators elsewhere in the configuration.
The real power of penscript comes from composing operators — nesting them to express complex logic in a single, declarative structure.Consider this: you want to display a formatted message that changes based on the number of documents a contact has uploaded.
Reading from the inside out: :count counts the documents, :cmp compares the count, and :if picks the right message. Each operator does one thing, and composition builds the behavior.Or, using :case for cleaner multi-branch logic:
Route a notification based on a contact’s language:
{ ":case": "{contacts.main.language}", ":when": [ ["fr", "Votre dossier a été mis à jour."], ["nl", "Uw dossier is bijgewerkt."], ["de", "Ihre Akte wurde aktualisiert."] ], ":else": "Your case has been updated."}
Combine multiple conditions to determine eligibility:
Each condition is a separate operator. The :if evaluates all of them — if they all pass, the :then branch is returned.→ Full reference: Logic & comparisons
This creates a set of form fields for each child — dynamically. If the user enters 3, three sets of fields appear. The {@index} and {@position} variables track where you are in the loop. The :with operator creates a local pos variable (1-based) for display labels.Filter a list to find only completed items:
The :i18n operator reads the active locale from the scope and returns the matching translation. Variables inside translations are resolved normally.→ Full reference: Internationalization
Define local variables, build reusable expression templates, and pipe values through transformation chains.Define intermediate values for a complex calculation:
The :raw operator captures the expression without evaluating it. :eval evaluates it later, in a scope where the variables have values.→ Full reference: Dynamic evaluation & scope
These capabilities are designed to be combined. A single penscript configuration might use conditions to control which form elements appear, calculations to compute a premium, loops to generate dynamic fields, date arithmetic to set deadlines, and internationalization to serve it all in the contact’s language.Here’s a realistic fragment from a case automation — automatically moving a case to “Ready for Review” when all required documents are uploaded and the contact is an adult:
Reading this: the first condition checks the contact’s age. The second iterates over the list of required document types and, for each one, checks whether any uploaded document matches that type. If both conditions pass, the case moves to “Ready for Review.”This is a single JSON object. No procedural code, no external scripts — just declarative logic that Penbox evaluates in real time.
penscript expressions appear throughout the platform:
Form templates — element visibility, validation, default values, computed fields, conditional steps
Case templates — data schema defaults, status transition conditions, step visibility rules
Automations — trigger conditions, status transitions, post-automation payloads
Notifications — dynamic content in emails and SMS (subject lines, body text, conditional sections)
Document generation — variable injection into Word and PDF templates
API payloads — outbound data sent by post-automations to external systems
The visual editor handles configuration for most of these. penscript lets you go further — adding logic, conditions, and dynamic behavior that the visual editor doesn’t expose.