Overview
The rule expression engine evaluates bracket functions and field placeholders in eADM. Expressions appear in:
Consumer: Rulesets (Regelsett) | Typical use: Filter users, departments, groups; gate message flows, sync steps, permissions
Consumer: Message templates | Typical use: Dynamic recipient, subject, body (HTML)
Consumer: Export templates / sync template flow lines | Typical use: Target attribute mapping
Consumer: Customer setup | Typical use: Username expression, auto-group naming, position filter
Consumer: Form templates | Typical use: Form field bindings
Consumer: Expression builder | Typical use: Preview against a test user, department, or group
How evaluation works
-
The engine scans the expression for
[...]tokens. -
[ARRAYFOREACH...]runs first — before the innermost-first pass — so template placeholders???and???ibind per pipe-separated element. -
Otherwise it resolves the innermost bracket pair first.
-
Each function returns a plain text result that replaces the bracket.
-
When no functions remain, remaining
[FieldName]tokens are replaced from the current object (and optional history row in message flows). -
Unrecognised field names stay as literal
[FieldName]in the output.
Pipe-separated lists (|) are used for multi-value data — especially HR positions on a user.
Dummy data used in examples below
Unless stated otherwise, examples assume customer Eksempel kommune with:
Object: User Kari Nordmann | Key values: GivenName=Kari, Surname=Nordmann, DisplayName=Kari Nordmann, UserName=kari.nordmann, Email=kari.nordmann@eksempel.kommune.no, Start=01.04.2026 00:00:00, Department=IT og digitalisering, DepartmentNumber=100
Object: User positions (pipe-aligned) | Key values: APositionCodeId=POS-01|POS-02, AUnitId=IT-100|HR-200, APositionCodeName=Utvikler|HR-rådgiver, APrimaryPosition=true|false, APositionPercentage=100.0|20.0
Object: Department IT (type 2) | Key values: Id=2100, SourceId=IT-100, DepartmentNumber=100, OrgUnitnr=IT-100, ParentDepartmentNumber=0
Object: Department HR (child of IT) | Key values: Id=2101, SourceId=HR-200, ParentDepartmentNumber=100
Object: System role (permission) | Key values: Id=501, Name=Bruker Fagsystem X, linked to system id=12
Object: Permission on Kari | Key values: SystemRoleId=501, ManagerOf=2100, Comment=Automatisk tildelt, ExpiryDate=empty
Object type ids (for lookups): User=1, Department=2, Group=3, API user=14.
Syntax conventions
-
Functions:
[NAME;arg1;arg2;...]— arguments separated by semicolon (;). -
Fields:
[FieldName]— value from current object (case-insensitive). -
Nested expressions: inner brackets resolved before outer.
-
List separator: pipe character
|(vertical bar) between values — e.g.POS-01|POS-02. Never type a backslash;|appears only as markdown escaping in source files, not in expressions. -
Dates in fields are often stored as
dd.MM.yyyy HH:mm:ss; imports may useyyyy-MM-ddand other common formats.
Query mini-language
Used inside [FOREACH], [IFTHENELSE], and advanced [OBJECT...] filters.
Token: = | Meaning: Equal
Token: >, < | Meaning: Greater / less than
Token: ! | Meaning: Not equal
Token: * | Meaning: Pattern match (like)
Token: # | Meaning: Value in list
Token: & | Meaning: AND next condition
Token: | | Meaning: OR next condition
Prefix related data with object., system., systemrole., objectpermission., etc.
Nesting
Inner field first, then outer function
Step: 1 | Expression fragment: [start] | Resolves to: 01.04.2026 00:00:00
Step: 2 | Expression fragment: [SUBSTRING;0;10;01.04.2026 00:00:00] | Resolves to: 01.04.2026
Blocked if inner field missing: [SUBSTRING;0;10;[UnknownField]] stays unchanged when UnknownField is not on the object.
Typical permission chain (read inside-out):
[REFERENCE;DisplayName;UserId;1;[REFERENCE;Manager;Id;2;[OBJECTPERMISSION;ManagerOf;SystemRoleId;501]]]
-
Permission → department id
2100 -
Department → manager user id
-
User → manager display name
[ARRAYFOREACH...] is different: it expands a pipe-separated list before inner functions in the template run. Use ??? for the current element and ???i for its 0-based index. Nesting [ARRAYFOREACH...] inside another [ARRAYFOREACH...] is not supported — use [ARRAYJOIN] / [ARRAYPREFIX] or sibling calls instead.
Access levels
Role: Super manager | What it affects: Expression builder preview
Role: Company administrator | What it affects: Full function list in builder; [APITOKEN...], [SYNCSTEPPARAMETER...] in preview
Role: Organization administrator | What it affects: Expressions touching protected fields in preview
Role: Super administrator | What it affects: [UPDATE...], [DECRYPT...], [ENCRYPT...] — omitted from this guide
Automation (sync, messages, exports) evaluates expressions with server privileges. A function that works in production may still be blocked in the expression builder for your role.
Field placeholders
Not functions — replaced from the current object (or history row in event-driven message flows).
Example: Template Hello [GivenName] [Surname] on Kari Nordmann → Hello Kari Nordmann
Placeholder: [GivenName], [Surname], [DisplayName] | Typical source: Person name
Placeholder: [UserName], [Email], [Upn], [Mail] | Typical source: Account / mail
Placeholder: [Department], [DepartmentNumber] | Typical source: Primary department
Placeholder: [Start] | Typical source: Employment start datetime
Placeholder: [Manager] | Typical source: Manager reference from HR
Placeholder: [APositionCodeId], [AUnitId], [APositionCodeName] | Typical source: Multi-position (pipe-separated)
History-only (message flows after sync): [OldValue], [NewValue], [EntryType], [AttributeName], [Comment].
Function reference with examples
Each entry lists parameters, a worked example with dummy data, and expected output.
Date and time
[NÅ] / [NOW]
Returns server date and time.
Parameter: (none) | Purpose: Current moment
Parameter: +N / -N suffix | Purpose: Add or subtract N days
Expression: [NÅ] | Assumed server date: 17.06.2026 14:30:00 | Output: 17.06.2026 14:30:00
Expression: [NOW+7] | Assumed server date: 17.06.2026 | Output: 24.06.2026 14:30:00 (same time, +7 days)
Use: Permission start display, relative deadlines in templates.
[DATEFORMAT;date;format]
Reformats a date string.
Parameter: date | Purpose: Input date, or pipe-separated dates
Parameter: format | Purpose: Output pattern (e.g. yyyy-MM-dd, dd/MM/yyyy)
Expression: [DATEFORMAT;01.04.2026 00:00:00;yyyy-MM-dd] | Input (after field resolve): — | Output: 2026-04-01
Expression: [DATEFORMAT;01.04.2026 00:00:00|15.06.2026 00:00:00;yyyy-MM-dd] | Input (after field resolve): two dates | Output: 2026-04-01|2026-06-15
Use: Export formats, ISO dates in API payloads.
[DATEDIFF;date1;date2;unit]
Numeric difference between two dates.
Parameter: date1 | Purpose: Later or primary date
Parameter: date2 | Purpose: Earlier or reference date
Parameter: unit | Purpose: d days (default), y years, m months, h hours, mi minutes, s seconds
Expression: [DATEDIFF;17.06.2026 00:00:00;01.04.2026 00:00:00;d] | Output: 77 | Meaning: 77 days between start and today
Expression: [DATEDIFF;17.06.2026 00:00:00;01.04.2026 00:00:00;y] | Output: 0 | Meaning: Same calendar year in this example
Use: Tenure checks in rulesets, "days until start" in messages.
[DAYOFYEAR;date]
Parameter: date | Purpose: Date to evaluate
Expression: [DAYOFYEAR;01.04.2026 00:00:00] | Output: 91
Use: Seasonal rules, fiscal period tricks.
String manipulation
[SUBSTRING;start;length;text]
Parameter: start | Purpose: 0-based start index
Parameter: length | Purpose: Number of characters to take
Parameter: text | Purpose: Source string (often a nested field)
Expression: [SUBSTRING;0;10;01.04.2026 00:00:00] | Resolved text: — | Output: 01.04.2026
Expression: [SUBSTRING;0;4;POS-01] | Resolved text: — | Output: POS-0
Use: Date-only from datetime in welcome mails: [SUBSTRING;0;10;[Start]] → 01.04.2026.
[SPLIT;text;delimiter;index]
Parameter: text | Purpose: String to split
Parameter: delimiter | Purpose: Separator (e.g. |, ;, space)
Parameter: index | Purpose: 0-based piece index, or last / last-1
Expression: [SPLIT;Kari|Nordmann;|;0] | Output: Kari
Expression: [SPLIT;POS-01|POS-02;|;last] | Output: POS-02
Use: Salutation from combined name field; pick last position code.
[REPLACE;text;find;replace]
Parameter: text | Purpose: Original string
Parameter: find | Purpose: Substring(s) to replace; pipe = multiple; ^x = only at start; x^ = only at end
Parameter: replace | Purpose: Replacement text
Expression: [REPLACE;kari.nordmann;.;-] | Output: kari-nordmann
Expression: [REPLACE;+4712345678;+47|;;] | Output: 12345678
Use: Normalise phone numbers, swap separators in usernames.
[REPLACELIST;text;fromChars;toChars]
Character-by-character map (both char lists must be same length).
Parameter: text | Purpose: Input
Parameter: fromChars | Purpose: Characters to map from
Parameter: toChars | Purpose: Characters to map to
Expression: [REPLACELIST;abcåøæ;åøæaoe] | Output: abcaoe
Use: Legacy character set fixes in imports.
[RTRIM;text;chars] / [LTRIM;text;chars]
Parameter: text | Purpose: Input; if it contains |, each segment is trimmed
Parameter: chars | Purpose: Character(s) to strip from end (RTRIM) or start (LTRIM)
Expression: [RTRIM;POS-01|POS-02|;] | Output: POS-01|POS-02 (trailing empty segment removed)
Expression: [LTRIM;; Kari; ] | Output: Kari
Use: Clean pipe lists after [ARRAYDIFF].
[RPAD;text;padChar;totalLength] / [LPAD;text;padChar;totalLength]
Parameter: text | Purpose: Value to pad
Parameter: padChar | Purpose: Fill character
Parameter: totalLength | Purpose: Target width
Expression: [RPAD;42;0;5] | Output: 42000
Expression: [LPAD;7;0;4] | Output: 0007
Use: Fixed-width employee numbers in file exports.
[RIGHT;length;text]
Parameter: length | Purpose: How many characters from the right
Parameter: text | Purpose: Source
Expression: [RIGHT;4;12345678] | Output: 5678
Use: Last digits of national id in test environments.
[INITIALS;text;startWord;endWord]
Parameter: text | Purpose: Full name or phrase
Parameter: startWord | Purpose: Word index to start (0-based)
Parameter: endWord | Purpose: Word index to end, or last / last-1
Expression: [INITIALS;Kari Marie Nordmann;0;last] | Output: K M N (letters plus spaces as produced)
Expression: [INITIALS;Kari Marie Nordmann;1;1] | Output: M
Use: Short codes in group names or mail aliases.
[PRETTIFY;text]
Title-cases after space or hyphen.
Expression: [PRETTIFY;kari nordmann] | Output: Kari Nordmann
Expression: [PRETTIFY;it-og-digitalisering] | Output: It-Og-Digitalisering
Use: Display names in messages when HR sends uppercase.
[LOWER;text] / [UPPER;text]
Expression: [LOWER;Kari.Nordmann@Eksempel.Kommune.NO] | Output: kari.nordmann@eksempel.kommune.no
Expression: [UPPER;avdeling-it] | Output: AVDELING-IT
Use: Normalise before [CLEAN] in username rules.
[CLEAN;text] / [STRICTCLEAN;text] / [CNCLEAN;text]
Strip or replace characters unsafe for usernames, strict ids, or AD common names (CN).
Expression: [CLEAN;Kari Åse Nordmann!] | Typical output: kariasenordmann (non-letters removed, lowercased style) | Use: Username / uid
Expression: [CNCLEAN;Kari (test) Nordmann] | Typical output: CN-safe form for AD | Use: Group or user CN
Exact output depends on customer character rules; test in expression builder.
[GETKEYVALUE;key;delimiter;metadata]
Reads key
pairs inside a pipe-separated metadata string.
Parameter: key | Purpose: Key to find
Parameter: delimiter | Purpose: Separator between key and value (often = or :)
Parameter: metadata | Purpose: Pipe-separated list of key-value tokens
Expression: [GETKEYVALUE;cost;=;cost=IT|site=Oslo] | metadata value: — | Output: IT
Use: Custom import metadata on extension attributes.
Logic and control flow
[IFTHENELSE;query;thenValue;elseValue]
Parameter: query | Purpose: Condition on current object (e.g. ObjectTypeId=1)
Parameter: thenValue | Purpose: Returned if query matches
Parameter: elseValue | Purpose: Returned if not
Context: User Kari (type 1) | Expression: [IFTHENELSE;ObjectTypeId=1;Ansatt;Ikke ansatt] | Output: Ansatt
Context: Department IT (type 2) | Expression: same | Output: Ikke ansatt
Use: Single template for mixed object types.
[IFEMPTYUSE;primary;fallback;reversed]
Parameter: primary | Purpose: Value to test
Parameter: fallback | Purpose: Used when primary is empty (default)
Parameter: reversed | Purpose: Optional true: use fallback when primary is not empty
Expression: [IFEMPTYUSE;;Permanent tilgang] | Kari's permission expiry: empty | Output: Permanent tilgang
Expression: [IFEMPTYUSE;15.12.2026;Permanent tilgang] | Kari's permission expiry: 15.12.2026 | Output: 15.12.2026
Expression: [IFEMPTYUSE;[Manager];;true] | Kari's permission expiry: Manager=empty | Output: `` (empty — reversed: fallback only when manager exists)
Use: Default text for missing expiry, manager, or comment.
[EXISTS;value;resultIfNonEmpty]
Parameter: value | Purpose: Tested string
Parameter: resultIfNonEmpty | Purpose: Returned only if value is non-empty
Expression: [EXISTS;ola.hansen;has-manager] | Kari Manager field: ola.hansen | Output: has-manager
Expression: [EXISTS;;has-manager] | Kari Manager field: empty | Output: `` (empty)
Use: Gate nested lookups — only run [REFERENCE...] when [Manager] is set.
[TRANSFORM;input;mapping...]
Parameter: input | Purpose: Value to map
Parameter: key|value pairs | Purpose: Match input to output
Parameter: *|default | Purpose: Wildcard if no key matches
Expression: [TRANSFORM;F;M|Mann;F|Kvinne;*|Ukjent] | [Sex] = F: — | Output: Kvinne
Expression: [TRANSFORM;X;M|Mann;F|Kvinne;*|Ukjent] | [Sex] = F: — | Output: Ukjent
Use: HR codes → display text in messages.
[CONTAINS;valueList;targetList;ifYes;ifNo]
Parameter: valueList | Purpose: Pipe-separated needles
Parameter: targetList | Purpose: Pipe-separated haystack
Parameter: ifYes / ifNo | Purpose: Strings returned on match / no match
Expression: [CONTAINS;IT-100|FIN-300;HR-200|IT-100|SALG-400;ja;nei] | Output: ja (IT-100 found in target)
Expression: [CONTAINS;FIN-300;HR-200|IT-100;ja;nei] | Output: nei
Use: Ruleset-style branching inside a template.
Array (pipe-separated) operations
Lists look like A|B|C. Many HR position fields use this shape.
[COUNT;ignored;list]
Parameter: ignored | Purpose: Placeholder (unused)
Parameter: list | Purpose: Pipe-separated values
Expression: [COUNT;x;POS-01|POS-02|] | Output: 2 (empty trailing segments may affect count — test with your data)
Use: "How many positions does this user have?"
[ARRAYAPPEND;list1;list2]
Expression: [ARRAYAPPEND;POS-01|;POS-02|POS-03|] | Output: POS-01|POS-02|POS-03|
Use: Merge role lists from two permission queries.
[ARRAYUNIQUE;list]
Expression: [ARRAYUNIQUE;A|B|A|C|] | Output: A|B|C|
Use: Deduplicate department ids before export.
[ARRAYFILTER;list;allowed]
Keeps only items that appear in allowed.
Expression: [ARRAYFILTER;POS-01|POS-02|POS-99;POS-01|POS-02|] | Output: POS-01|POS-02|
Use: Whitelist position types for a message.
[ARRAYDIFF;current;previous]
Items in current not in previous.
Context: New position added | current: POS-01|POS-02| | previous: POS-01| | Output: POS-02|
Context: No change | current: POS-01| | previous: POS-01| | Output: ``
Use: Detect new position in message flow (pair with [LASTVALUE;APositionCodeId]). Warning: unreliable if several positions change in one import.
[ARRAYJOIN;list1;list2]
Zips two lists by index.
Expression: [ARRAYJOIN;Utvikler|HR-rådgiver;100%|20%] | Output: Utvikler100%|HR-rådgiver20%
Use: Combine parallel columns for CSV-style export lines.
[ARRAYFOREACH;array;template] / [ARRAYFOREACH;array;separator;template]
Iterates over a pipe-separated list. For each non-empty element, substitutes ??? with the element and ???i with its 0-based index in the template, evaluates nested [...] in the template, then joins results.
Parameter: array | Purpose: Pipe-separated list (often a field like [APositionCodeName])
Parameter: separator | Purpose: Optional join string between iterations (default |)
Parameter: template | Purpose: Text or nested expression; ??? = current item, ???i = index
Expression: [ARRAYFOREACH;[APositionCodeName];Stilling: ???] | Kari APositionCodeName: Utvikler|HR-rådgiver | Output: Stilling: Utvikler|Stilling: HR-rådgiver
Expression: [ARRAYFOREACH;[APositionCodeId];, ;DEPT-???] | Kari APositionCodeName: POS-01|POS-02 | Output: DEPT-POS-01, DEPT-POS-02
Expression: [ARRAYFOREACH;[APositionCodeId];[SUBSTRING;0;4;???]] | Kari APositionCodeName: POS-01|POS-02 | Output: POS-|POS-
Expression: [ARRAYFOREACH;[APositionCodeName];???i:???] | Kari APositionCodeName: Utvikler|HR-rådgiver | Output: 0:Utvikler|1:HR-rådgiver
Empty pipe segments are skipped (same convention as [ARRAYUNIQUE] / [ARRAYPREFIX]).
Not supported: [ARRAYFOREACH...] nested inside another [ARRAYFOREACH...] — expression evaluation fails. Use two sibling calls or [ARRAYJOIN] instead.
Use: Format each position as its own line in a message; prefix each unit id for export.
[ARRAYPREFIX;list;mode;text]
Parameter: list | Purpose: Pipe-separated items
Parameter: mode | Purpose: 1 = prefix each item with text; other = suffix
Parameter: text | Purpose: Prefix or suffix string
Expression: [ARRAYPREFIX;IT-100|HR-200;1;DEPT-] | Output: DEPT-IT-100|DEPT-HR-200|
Use: Namespace external ids.
[ARRAYTRIM;list;delimiter;maxCount]
Expression: [ARRAYTRIM;A|B|C|D;|;2] | Output: A|B
Use: Only first N positions in a summary mail.
[PRUNEARRAY;list;regex;reverse]
Parameter: list | Purpose: Pipe-separated items
Parameter: regex | Purpose: .NET regular expression
Parameter: reverse | Purpose: true = keep non-matching items instead
Expression: [PRUNEARRAY;POS-01|TEMP-99|POS-02;^TEMP;false] | Output: POS-01|POS-02
Expression: [PRUNEARRAY;POS-01|TEMP-99;^TEMP;true] | Output: TEMP-99
Use: Drop temporary position codes from export.
[UNION;headers;list1;list2;...]
Merges parallel lists row-wise into spaced/pipe combined rows.
Expression: [UNION;Role|Dept;Admin|User;IT|HR] | Conceptual output: Role Admin Dept IT|User HR (pattern: concatenate columns per index)
Use: Multi-column text blocks in reports.
Random, hash, uniqueness
[RND;min;max]
Parameter: min | Purpose: Minimum integer (inclusive)
Parameter: max | Purpose: Maximum integer (exclusive in practice — test your range)
Expression: [RND;1000;9999] | Example output: 4521 (varies each run)
Use: Ticket numbers in test templates.
[STRRND;minLen;maxLen;chars]
Parameter: minLen / maxLen | Purpose: Length range
Parameter: chars | Purpose: Allowed character set (empty = alphanumeric default)
Expression: [STRRND;8;8;abcdefghjkmnpqrstuvwxyz] | Example output: kthqwrnb (varies)
Use: One-time codes when password rule is not used.
[PASSWORD;ruleId]
Parameter: ruleId | Purpose: Id of password generation rule configured in eADM
Expression: [PASSWORD;3] | Output: e.g. Xk9#mP2$vL (follows rule 3 complexity; varies)
Use: Initial password in welcome message — handle securely.
[HASH;text]
Expression: [HASH;kari.nordmann@eksempel.kommune.no] | Output (example): 32-character MD5 hex string (fixed for same input)
Use: Opaque tokens in links (not for security-critical hashing alone).
[UNIQUE;base;fieldName;replacement]
Ensures base does not already exist in fieldName on another object; appends 2, 3, … or inserts before replacement.
Parameter: base | Purpose: Proposed username or email
Parameter: fieldName | Purpose: Field to check uniqueness against (e.g. UserName)
Parameter: replacement | Purpose: Optional suffix marker to replace with number
Scenario: kari.nordmann free | Expression: [UNIQUE;kari.nordmann;UserName;.] | Output: kari.nordmann
Scenario: kari.nordmann taken | Expression: same | Output: kari.nordmann2 or kari2.nordmann depending on replacement
Use: Customer setup username expression together with [CLEAN] / [LOWER].
Database lookup and relations
These read live eADM data for the customer. Ids must exist in your environment.
[REFERENCE;returnField;whereField;objectTypeId;searchValue;exactMatch]
Parameter: returnField | Purpose: Field(s) to return from matched object (§ joins multiple fields)
Parameter: whereField | Purpose: Field to match on
Parameter: objectTypeId | Purpose: 1 user, 2 department, 3 group
Parameter: searchValue | Purpose: Value to find
Parameter: exactMatch | Purpose: true exact; false pattern
Expression: [REFERENCE;OrgUnitnr;Id;2;2100] | Dummy match: Dept id 2100 = IT | Output: IT-100
Expression: [REFERENCE;DisplayName;UserId;1;ola.hansen] | Dummy match: Manager user | Output: Ola Hansen
Use: Department number from permission ManagerOf id:
[REFERENCE;OrgUnitnr;Id;2;2100]
[OBJECTPERMISSION;returnField;whereField;filterValue;exactMatch;aggregate]
Reads permissions on the current user.
Parameter: returnField | Purpose: Permission field (Comment, ManagerOf, ExpiryDate, SystemRoleId, …)
Parameter: whereField | Purpose: Field to filter on
Parameter: filterValue | Purpose: Match value, or * for all
Parameter: exactMatch | Purpose: String match mode
Parameter: aggregate | Purpose: true = all matches joined with |; false = first only
Expression: [OBJECTPERMISSION;Comment;SystemRoleId;501;true;false] | Output (Kari): Automatisk tildelt
Expression: [OBJECTPERMISSION;ManagerOf;SystemRoleId;501;true;false] | Output (Kari): 2100
Shorthand for role name:
Expression: [OBJECTPERMISSION.SYSTEMROLE;Name;SystemRoleId;501] | Output: Bruker Fagsystem X
[OBJECTHISTORIES;returnField;whereField;filterValue;exactMatch;aggregate]
Reads object history on current user (audit trail from sync/UI).
Example filter: Last permission add | Expression: [OBJECTHISTORIES;Comment;EntryType;AddPermission;false;false] | Typical output: Tildelt av admin
Use: "Who assigned this permission?" in message flows (often nested in [SPLIT] / [REFERENCE]).
[FOREACH;collection;query;returnFields;headers;format]
Parameter: collection | Purpose: object, objectpermission, objecthistory, …
Parameter: query | Purpose: Filter (company scope added automatically)
Parameter: returnFields | Purpose: Comma-separated fields, optionally object.Field
Parameter: headers | Purpose: Column titles for csv/html
Parameter: format | Purpose: csv, html, json, xml, eadm
Example (conceptual): All users with role 501, CSV:
[FOREACH;objectpermission;SystemRoleId=501;object.DisplayName,object.Email;Name,Email;csv]
Output (dummy):
Name,Email
Kari Nordmann,kari.nordmann@eksempel.kommune.no
Ola Hansen,ola.hansen@eksempel.kommune.no
Use: Manager report embedded in email body.
[DESCENDANTS;rootId;returnField;parentKey;foreignKey]
Parameter: rootId | Purpose: Department object id to start from
Parameter: returnField | Purpose: Field to collect from each node
Parameter: parentKey | Purpose: Child field pointing to parent (e.g. DepartmentNumber)
Parameter: foreignKey | Purpose: Parent identifier field (e.g. ParentDepartmentNumber)
Start: IT id 2100 | Tree: IT → HR | Expression: [DESCENDANTS;2100;SourceId;DepartmentNumber;ParentDepartmentNumber] | Output: IT-100,HR-200
Use: All sub-departments for scope on a manager permission.
[SYSTEM;type;id;field]
Parameter: type | Purpose: system, systemrole, or systemroles
Parameter: id | Purpose: Numeric id or *
Parameter: field | Purpose: Field name(s) to return
Expression: [SYSTEM;systemrole;501;Name] | Output (dummy): Bruker Fagsystem X
Expression: [SYSTEM;system;12;Name] | Output (dummy): Fagsystem X
Use: System owner contact in admin notification.
[SELECTION;rulesetId;returnField]
Parameter: rulesetId | Purpose: Ruleset to evaluate per object
Parameter: returnField | Purpose: Field from each object that matches
Expression: [SELECTION;1001;Email] | Output (dummy): kari.nordmann@eksempel.kommune.no|ola.hansen@eksempel.kommune.no|
Use: Mailing list of everyone matching "New starters" ruleset.
[AVAILABLESYSTEM;field] / [AVAILABLEROLE;systemId;field]
Returns pipe-separated values for systems or roles that pass their Available for ruleset on the current user.
Expression: [AVAILABLESYSTEM;Name] | Meaning: Names of systems Kari may receive permissions for
Expression: [AVAILABLEROLE;12;Name] | Meaning: Role names on system 12 she may be assigned
Use: Dynamic pick lists in forms or messages.
[AVAILABLEDEPARTMENTS;fields;targetUserId]
Parameter: fields | Purpose: Comma-separated department fields
Parameter: targetUserId | Purpose: User to evaluate; empty = current object
Use: List departments a manager may administer (from ManagerOf, unit ids, mega.eadm.no roles).
[DATAOWNER;returnField]
Follows data-owner relation on object; returns field from owner.
Expression: [DATAOWNER;Name] | Output (if owner group name stored): IT dataeiere
[ANTECEDANTS.SYSTEMROLE;roleId;departmentId;returnField]
Managers holding roleId on ancestor departments of departmentId.
Expression: [ANTECEDANTS.SYSTEMROLE;501;2101;Email] | Output (dummy): it-leder@eksempel.kommune.no,
Use: Escalation mail when HR child dept has no local approver.
[COUNTEMPLOYEE] / [COUNTMEMBERS]
Evaluated on department or group object respectively.
Object: Department IT | Expression: [COUNTEMPLOYEE] | Output (dummy): 47
Object: Group "Prosjekt Alfa" | Expression: [COUNTMEMBERS] | Output (dummy): 12
[GETLASTSYNCID]
Expression: [GETLASTSYNCID] | Output (dummy): 88421 (latest import file id for company)
Use: Troubleshooting footers in admin mails.
[LASTVALUE;attributeName]
Previous value of field from last import HR history, else current field.
Context: Before sync Kari had one position | Expression: [LASTVALUE;APositionCodeId] | Output: POS-01|
Context: After adding POS-02 | Expression: [APositionCodeId] | Output: POS-01|POS-02|
Pair with [ARRAYDIFF;[APositionCodeId];[LASTVALUE;APositionCodeId]] → POS-02|.
Positions (multi-position HR)
Position fields share index across pipes: index 0 = first position, 1 = second.
[POSITION;returnField;whereField;matchValue]
Parameter: returnField | Purpose: Position field to return (e.g. APositionCodeName)
Parameter: whereField | Purpose: Field to match (e.g. AUnitId)
Parameter: matchValue | Purpose: Unit or code to find
Expression: [POSITION;APositionCodeName;AUnitId;IT-100] | Output: Utvikler
Expression: [POSITION;APositionCodeName;AUnitId;HR-200] | Output: HR-rådgiver
[POSITIONS;returnField;whereField;matchValue]
Same as [POSITION] but returns aligned pipe string across all positions (empty slot where no match).
Expression: [POSITIONS;APositionCodeName;AUnitId;IT-100] | Output: Utvikler| (second position empty at same index pattern)
[GROUPPRIMARYPOSITION;returnField]
Picks primary position: highest APositionPercentage, tie-break by earliest APositionStartDate.
Kari positions: 100% IT, 20% HR | Expression: [GROUPPRIMARYPOSITION;APositionCodeName] | Output: Utvikler
[ACTIVEPOSITIONCOUNT;asOfDate]
Expression: [ACTIVEPOSITIONCOUNT;17.06.2026 00:00:00] | Output: 2 (both positions active on that date)
Messaging and integration
[COUNTMESSAGESENT;messageId;fromDate]
Parameter: messageId | Purpose: Message template id (optional if flow provides context)
Parameter: fromDate | Purpose: Only count sends after this date (optional)
Expression: [COUNTMESSAGESENT;1936;01.06.2026 00:00:00] | Output (dummy): 1
Use: "Already notified?" guard in follow-up flow.
[SYSTEMOWNER]
Requires history row from permission change (Add/Edit/Delete permission).
Context: Permission on role 501 added | Output (dummy): fagsystem-eier@eksempel.kommune.no
Use: CC system owner when automated permission is granted.
[SYNCSTEPPARAMETER;key;companySyncStepId]
Parameter: key | Purpose: Parameter name on sync step
Parameter: companySyncStepId | Purpose: Customer sync step instance id
Expression: [SYNCSTEPPARAMETER;ApiBaseUrl;42] | Output: https://api.example.invalid/hr
Access: Company administrator in expression builder preview.
[APITOKEN;apiUsername]
Parameter: apiUsername | Purpose: API user login name (object type 14)
Expression: [APITOKEN;sync.service] | Output: Opaque session token string (varies)
Access: Company administrator in preview. Use only in secured server-side flows.
HTML helpers (message templates)
[HTMLLISTMEMBEROF;displayField]
On a group member user: lists parent groups.
Expression: [HTMLLISTMEMBEROF;Name] | Output:
Prosjekt AlfaIT-utviklere
[HTMLLISTARRAY;list]
Expression: [HTMLLISTARRAY;Utvikler|HR-rådgiver] | Output:
UtviklerHR-rådgiver
Form template controls
Used in form templates, not standard rulesets.
Function: [INPUTBOX;fieldId;label;default;value] | Purpose: Text input bound to form field id
Function: [CHECKBOX;...] | Purpose: Boolean input
Function: [LISTBOX;...] | Purpose: Dropdown (five parameters)
Function: [RADIO;...] | Purpose: Radio group
Function: [DATEBOX;...] | Purpose: Date picker
Function: [AREABOX;...] | Purpose: Multi-line text
Function: [BUTTON;...] | Purpose: Action button
Example pattern: [INPUTBOX;1042;Avdeling;IT-100;] renders input labelled "Avdeling" defaulting to IT-100.
Markers [NOTIFY...], [HIDDEN...], [SERVERFUNCTION...] are form behaviour hooks, not data functions.
End-to-end scenarios (dummy data)
Welcome mail — start date only
Ny ansatt [DisplayName] starter [SUBSTRING;0;10;[Start]].
Output: Ny ansatt Kari Nordmann starter 01.04.2026.
Permission expiry line
Gyldig til: [IFEMPTYUSE;[OBJECTPERMISSION;ExpiryDate;SystemRoleId;501];Permanent tilgang]
Output: Gyldig til: Permanent tilgang
Manager missing — escalate to parent dept manager
[IFEMPTYUSE;
[EXISTS;[Manager];];
[REFERENCE;Email;UserId;1;[REFERENCE;Manager;Id;2;[REFERENCE;ParentDepartmentNumber;DepartmentNumber;2;[DepartmentNumber]]]]]
Kari Manager: empty | Output: ola.hansen@eksempel.kommune.no (parent dept manager email)
Kari Manager: set | Output: empty (EXISTS branch — adjust template logic if you need manager email when present)
Adjust IFEMPTYUSE/EXISTS pairing to match your template intent; test in expression builder.
New position only — message recipient
After sync adds POS-02:
[REFERENCE;Email;UserId;1;[POSITION;APositionManager;AUnitId;[RTRIM;[ARRAYDIFF;[APositionCodeId];[LASTVALUE;APositionCodeId]];|]]]
Output: Manager email for the new position's unit (dummy: ny-leder@eksempel.kommune.no).
Auto security group name (customer setup)
SG-[Department]-[CLEAN;[OrgUnitnr]]
Output: SG-IT og digitalisering-IT-100 (exact CLEAN output may vary).
Export mapping — samAccountName
[UserName]
Output: kari.nordmann
Ruleset — user has role on system
Rule attribute expression:
[OBJECTPERMISSION.SYSTEMROLE;Name;SystemRoleId;501]
Resolved value: Bruker Fagsystem X — compare with operator Er lik / membership operators.
Expression builder
Item: Where | Detail: Header icon expression builder, message template editors, some eHub screens
Item: Function list | Detail: All object fields for selected type plus standard functions
Item: Preview | Detail: Pick test user/department/group; requires super manager
Item: Rulesets | Detail: Automation → Rulesets — minimum super manager
Troubleshooting
Symptom: Literal [FUNCTION...] in output | Likely cause: Inner field empty or typo | Action: Fix nesting; verify field names on object
Symptom: Expression evaluation error | Likely cause: Nested [ARRAYFOREACH...] | Action: Split into sibling calls or use [ARRAYJOIN]
Symptom: Empty string | Likely cause: No matching id / permission | Action: Confirm system role id and system id in system access
Symptom: Wrong position in mail | Likely cause: Several positions changed at once | Action: Do not rely on ARRAYDIFF/LASTVALUE alone
Symptom: Preview blocked | Likely cause: Role or protected field | Action: Elevate role or simplify test expression
Symptom: Works in builder, not in message | Likely cause: Event flow needs object history from sync | Action: Run import; check entry type in history
Quick index
Category: Date/time | Functions: NÅ, NOW, DATEFORMAT, DATEDIFF, DAYOFYEAR
Category: String | Functions: SUBSTRING, SPLIT, REPLACE, REPLACELIST, RTRIM, LTRIM, RPAD, LPAD, RIGHT, INITIALS, PRETTIFY, LOWER, UPPER, CLEAN, STRICTCLEAN, CNCLEAN, GETKEYVALUE
Category: Logic | Functions: IFTHENELSE, IFEMPTYUSE, EXISTS, TRANSFORM, CONTAINS
Category: Arrays | Functions: COUNT, ARRAYAPPEND, ARRAYUNIQUE, ARRAYFILTER, ARRAYDIFF, ARRAYJOIN, ARRAYFOREACH, ARRAYPREFIX, ARRAYTRIM, PRUNEARRAY, UNION
Category: Security | Functions: HASH, PASSWORD, UNIQUE, RND, STRRND
Category: Lookup | Functions: REFERENCE, OBJECTPERMISSION, OBJECTHISTORIES, FOREACH, DESCENDANTS, SYSTEM, SELECTION, AVAILABLESYSTEM, AVAILABLEROLE, AVAILABLEDEPARTMENTS, DATAOWNER, ANTECEDANTS.SYSTEMROLE, COUNTEMPLOYEE, COUNTMEMBERS, GETLASTSYNCID, LASTVALUE
Category: Positions | Functions: POSITION, POSITIONS, GROUPPRIMARYPOSITION, ACTIVEPOSITIONCOUNT
Category: Messaging | Functions: COUNTMESSAGESENT, SYSTEMOWNER, SYNCSTEPPARAMETER, APITOKEN
Category: HTML | Functions: HTMLLISTMEMBEROF, HTMLLISTARRAY
Category: Forms | Functions: INPUTBOX, CHECKBOX, BUTTON, LISTBOX, RADIO, DATEBOX, AREABOX
AI assistant notes
-
Prefer
[DisplayName]-style fields before wrapping in functions. -
Ask where the expression lives: ruleset vs message vs export vs customer setup.
-
Replace dummy ids (
501,2100) with the customer's real system role and department ids from system access. -
Position filter on import excludes matches; sync step ruleset includes matches.
-
Event message flows need object history from a sync run.
-
Build nested examples inside-out — except
[ARRAYFOREACH...], which binds???per element before template functions run. -
Do not nest
[ARRAYFOREACH...]; use sibling calls or[ARRAYJOIN]. -
Terms: ruleset (Regelsett), message flow (meldingsflyt), system access (systemtilgang), permission (tilgang), object history (objekthistorikk).