This article collects the most commonly needed, simplest dynamic snippets for system templates (emails, invoices, VoS, job offers).
Before you start: the two rules
- Every snippet goes inside ${ }, using dot notation to drill into a field, e.g. ${booking.customer.name}.
- Always make it null-safe with a fallback. Put a ? before each dot, and end with ?:"" so a missing value shows as blank instead of the word null: ${booking?.customer?.name?:""}
Forgetting the ?:"" fallback is the #1 cause of a template showing null in a live email.
Job / Booking
| Field | Snippet |
| Job ID | ${booking.id?:""} |
| Booking ID (super booking) | ${booking?.superBooking?.id?:""} |
| Service type | ${booking.bookingMode?.name?:""} |
| Language | ${booking.language?.displayName?:""} |
| Job Details | ${booking?.visitDetails?:""} |
| Appointment Details | ${booking?.bookingDetails?:""} |
Customer / Client
| Field | Snippet |
| Customer name | ${booking?.customer?.name?:""} |
| Client name | ${booking?.client?.name?:""} |
| Customer PO | ${booking?.customer?.purchaseOrderNumber?:""} |
| Requested By (name + phone) | ${booking?.requestor?.displayLabel?:""} |
| Requestor email | ${booking?.requestor?.email?:""} |
Location
| Field | Snippet |
| Location (safe default, handles remote jobs) | ${booking?.actualLocationDisplayLabel?:""} |
| Location (short — no address) | ${booking?.actualLocationDisplayLabelConcise?:""} |
| Site / point of contact | ${booking?.siteContact?:""} |
Don't use booking.location.displayLabel — it breaks for remote jobs. Use actualLocationDisplayLabel instead.
Dates & Times
| Field | Snippet |
| Booking date | ${booking?.formatDate(booking?.bookingDate)} |
| Expected start date | ${booking?.formatDate(booking?.expectedStartDate)} |
| Expected start time | ${booking?.formatTime(booking?.expectedStartDate, false)} |
| Expected end (date + time) | ${booking?.formatDateTime(booking.expectedEndDate)} |
| Day of the Week | ${booking?.formatDate(booking.expectedStartDate, "EEEE")} |
Interpreter
| Field | Snippet |
| Name | ${booking?.interpreter?.firstName?:""} ${booking?.interpreter?.lastName?:""} |
| Display name | ${booking?.interpreter?.displayName?:""} |
| Phone | ${booking?.interpreter?.primaryNumber?.displayLabel?:""} |
| ${booking?.interpreter?.primaryEmail?.emailAddress?:""} |
Consumer
| Field | Snippet |
| Name | ${booking?.consumer?.name?:""} |
| Phone | ${booking?.consumer?.phoneNumber?:""} |
| Record number | ${booking?.consumer?.recordNumber?:""} |
Reference Fields
| Field | Snippet |
| Any reference by label | ${booking?.getReference("Job Name")?:""} |
The label inside the quotes must match the configured reference exactly — including case, spacing, and trailing colons. A mismatch shows N/A.
Special Instructions
Three visibility levels exist — match the snippet to who's receiving the email, so internal notes never leak to a customer or interpreter.
| Recipient | Snippet |
| Agency (internal only) | ${booking?.companySpecialInstructions?:""} |
| Customer | ${booking?.customerSpecialInstructions?:""} |
| Interpreter | ${booking?.contactSpecialInstructions?:""} |
Common mistakes to check first
- Shows null → missing the ?:"" fallback at the end of the chain.
- Shows N/A → a reference label doesn't match verbatim (case/spacing).
- Location is blank on a remote job → swap in actualLocationDisplayLabel.
- Wrong Special Instructions showing → check you used the right visibility level for the recipient (agency / customer / interpreter).
Always finish by previewing the template (Template Preview for emails, Financial Review for invoices with a customer override) before saving.