Explained

Use variables in workflows

Insert details like the client's name, appointment time or salon address into workflow steps, and format them with helpers.

5 min readRole: Super Administrator or higherAutomationsUpdated October 25, 2026
Open in the app

Variables fill in real details when a workflow runs, like the client's first name or the appointment's start time. You can use them in any text field of a step: recipients, subjects, message content, conditions, URLs and request bodies.

A variable is an expression between double curly braces, like {{ $event.data.object.client.firstName }}. When the run reaches the step, Softalon replaces it with the value. Anything inside the braces works like a small piece of JavaScript.

Insert a variable

Click Insert Variable next to a field. The Select Variable dialog opens with Suggested Variables for that field. Click View All Variables to browse everything, or search by name. Pick a group to go deeper, then pick a value.

In fields like Recipient, the dialog only shows values that fit, for example email addresses for an email.

Below the text, a Preview shows how the message looks with example values.

Variable groups

What you can pick depends on the trigger and on the step before the current one.

GroupWhat it holdsExample
EventDetails of the event that started the run: its type, the time it happened and its data.{{ $event.timestamp }}
The trigger's record, for example Appointment or ClientThe record the event is about, with its related records.{{ $event.data.object.status }}
Previous record, for example Previous AppointmentThe values before the change, on update triggers.{{ $event.data.previousAttributes.status }}
Previous NodeThe result of the last step that sent something or called another system.{{ $previousNode.sent }}
RequestThe request that started a Webhook workflow.{{ $request.body.phoneNumber }}
OtherYour salon's details: Salon, Timezone, Week Starts On, Time Format, Date Format, Contact Details and Social Media.{{ $salon.name }}

Other is available in every workflow. Event and the record groups aren't available for Webhook and Manual workflows, because no event starts them.

For an appointment trigger, the appointment comes with its Client, Member, Service and Location. For example:

  • {{ $event.data.object.client.firstName }}: the client's first name
  • {{ $event.data.object.member.firstName }}: the team member's first name
  • {{ $event.data.object.service.name }}: the service name

Softalon loads related records, like the client or the service, when a step uses them as a plain variable, such as {{ $event.data.object.client.emailAddress }}. If you only use a related record inside a function or a comparison, also use it as a plain variable somewhere in the workflow. Otherwise its values may come out empty.

Previous values

On Updated triggers and other triggers that react to a change, $event.data.previousAttributes holds the old values of the fields that changed. Fields that didn't change aren't in it. For example, on Rescheduled, {{ $event.data.previousAttributes.startAt }} is the old start time.

Format dates, money and addresses

Date, amount and location variables offer formatted versions in the picker. You can also write them yourself:

HelperWhat it returnsExample
DateThe date in your salon's date format.{{ date($event.data.object.startAt) }}
TimeThe time in your salon's 12-hour or 24-hour format.{{ time($event.data.object.startAt) }}
Date & TimeBoth.{{ datetime($event.data.object.startAt) }}
YearOnly the year.{{ year($event.data.object.startAt) }}
Currency FormattedAn amount in your salon's currency format.{{ currency($event.data.object.total) }}
Duration FormattedA number of minutes as a readable duration.{{ duration(90) }}
AddressA location's address on one line.{{ address($event.data.object.location) }}
Directions LinkA Google Maps link to a location.{{ directionsLink($event.data.object.location) }}

Dates and times use your salon's time zone. In a message to the trigger's client who booked from another time zone, they use the client's time zone.

actionLink creates a short link that lets a client act on an appointment or invoice without signing in. Pass the record's ID and the action:

  • {{ actionLink($event.data.object.id, "confirm") }}
  • {{ actionLink($event.data.object.id, "reschedule") }}
  • {{ actionLink($event.data.object.id, "cancel") }}
  • {{ actionLink($event.data.object.id, "review") }}

See Send a client a confirm, reschedule or review link for what each link does.

Expressions

Because the inside of the braces is JavaScript, you can do small transformations, like {{ $event.data.object.client.firstName.toUpperCase() }} or {{ $event.data.object.notes || "No notes" }}.

Some code isn't allowed for safety, such as defining functions, assigning values or reaching system objects. If you use it, the workflow can't be saved.

If an expression fails when the workflow runs, it's replaced with empty text and the run continues.

Common questions

The record may not have that value, like a client without a last name. Also check that related records are used as a plain variable somewhere in the workflow.