Calendar Workflows
Trigger-and-action automations that fire on the booking lifecycle — reminders, reconfirmations, no-show follow-ups, and custom emails or SMS.
A workflow is a small automation tied to one or more booking links. It listens for a lifecycle event (someone books, the meeting starts, a no-show is marked) and fires actions — emails, SMS, or both — with custom copy and variable substitution.
If you're coming from Calendly, this is the direct equivalent of Workflows. If you're starting fresh, think of it as the layer that lets you stop manually emailing prep docs, post-meeting recaps, and "you missed our call" messages.
Screenshot needed — /calendar/workflows builder with trigger picker, step list, and variable autocomplete
When you'd reach for it
- Send a prep doc 2 hours before the call — instead of a stock reminder
- Text the attendee 30 minutes before — Twilio-backed SMS, opt-in tracked
- Ask "are you still attending?" the day before — reconfirmation, dead-meeting cleanup
- Email no-shows a re-book link — once you've marked them no-show
- Notify a different team in Slack — wire it through the email step pointed at a Slack-forwarding address (native Slack actions land in a later release)
- Fire a CRM follow-up sequence after the meeting ends — by chaining to a Sales sequence
The model
Each workflow has:
- One trigger — what kicks it off
- One or more steps — what to do, with optional delays
- A list of booking links it applies to — pick zero (workspace default), one, or many
A booking link can be assigned multiple workflows at once. They all fire independently — there's no priority resolution, no "first matching wins."
Workflows live at /calendar/workflows. They're stored on scheduling_workflows (with scheduling_workflow_steps and scheduling_workflow_event_types for assignments) — sibling to Sales sequences, not part of the generic automations_workflows substrate. The lifecycle-trigger model with event-time-relative delays is too specific to share.
Triggers
Seven trigger points cover the entire booking lifecycle:
| Trigger | When it fires | Common use |
|---|---|---|
| Booked | Right after the booking is confirmed (after payment if paid) | Send prep doc, internal Slack ping |
| Before meeting starts | At a configured offset before starts_at (e.g. 24h, 2h, 30 min) | Reminders, reconfirmation prompt |
| Meeting start | At starts_at exactly | "Joining now" SMS for in-person |
| Rescheduled | When the attendee uses the reschedule token | "Updated time" notice |
| Event end | At ends_at | Post-meeting follow-up, NPS prompt |
| Cancelled | When the attendee or host cancels | "Sorry to miss you, here's a re-book link" |
| No-show marked | When you click No-show on a past meeting | Automatic re-book outreach |
The "before meeting starts" trigger accepts hours and minutes — set 24h for the day before, 30 min for last-call.
Actions
Each step in a workflow does one of two things today:
| Action | What it does |
|---|---|
| Send email | Fully customizable subject + body (plain text or simple markdown). Sender defaults to the workspace's no-reply alias; can be overridden to send from the host's connected Gmail or Outlook (see below). Up to 10 cc recipients per step. |
| Send SMS | Twilio-backed text message. 158-char chunked, STOP/START/HELP keywords auto-handled, opt-in required. See SMS Notifications. |
A step can target the invitee, the host, or a list of explicit email addresses or phone numbers (e.g. an assistant, a Slack-bot inbox, an SMS number routed to PagerDuty). Multiple recipients per step are supported.
Trigger × action matrix
This is the menu of everything you can build today:
| Trigger \ Action | SMS | |
|---|---|---|
| Booked | ✅ Confirmation, prep doc, internal Slack-mailbox ping | ✅ Welcome SMS (opt-in needed) |
| Before meeting starts | ✅ Reminder + reconfirmation button | ✅ Reminder text |
| Meeting start | ✅ "We're starting now" with join link | ✅ "Joining now" SMS |
| Rescheduled | ✅ Updated calendar invite, new prep doc | ✅ Updated time SMS |
| Event end | ✅ Thank-you, NPS link, recap from Notetaker | ✅ Quick poll SMS |
| Cancelled | ✅ Apology + re-book link | ✅ "We missed you" SMS |
| No-show marked | ✅ Re-book outreach | ✅ "We missed you" SMS |
Variables
Workflow message bodies support {{variable}} substitution. Drop them anywhere in the subject or body — they're replaced at send time.
| Variable | Resolves to |
|---|---|
{{invitee_name}} | Attendee's full name |
{{invitee_first_name}} | First name only |
{{invitee_email}} | Attendee's email |
{{host_name}} | Host's name (the assigned host, not the link owner, for round-robin) |
{{host_email}} | Host's email |
{{event_type_name}} | Booking link title |
{{event_start}} | Localized start time (Mon, Jun 9 at 10:00 AM CET) |
{{event_end}} | Localized end time |
{{duration}} | "30 minutes" |
{{meeting_url}} | Zoom / Meet / Teams / Webex / GoTo URL |
{{location}} | Meeting location (custom URL, room name, address) |
{{join_button}} | HTML CTA — turns into a styled button in the email |
{{reschedule_url}} | Token URL for /book/reschedule/<token> |
{{cancel_url}} | Token URL for /book/cancel/<token> |
{{reconfirm_url}} | Token URL for /book/reconfirm/<token> (only meaningful inside a "before start" step that uses reconfirmation mode) |
{{utm_source}} · {{utm_medium}} · {{utm_campaign}} · {{utm_content}} · {{utm_term}} | UTM parameters captured at booking time |
{{answer_<id>}} | Pre-meeting form answer, by field id (e.g. {{answer_company}}) |
{{custom_message}} | The freeform note the host left on the booking link |
{{workspace_name}} | Your workspace's display name |
{{workspace_logo_url}} | URL to your workspace logo, for inline use |
If a variable doesn't resolve (e.g. {{utm_source}} on a booking that didn't carry one), it's stripped silently. There's no fallback syntax today — keep your message bodies graceful when a value is empty.
Reconfirmation flow
A common pattern: text or email an attendee 24 hours out asking "Are you still attending?" with a one-click confirm button. If they don't click, the booking gets quietly cancelled before it pollutes your no-show stats.
To set this up:
- Add a workflow with a Before meeting starts trigger at 24 hours.
- Pick Email or SMS, write your copy, and include
{{reconfirm_url}}as the call-to-action. - Toggle Reconfirmation step on the step. This tells the workflow engine to track whether the URL was actually clicked.
- Configure what happens if not clicked: send an additional reminder, or auto-cancel after a configurable hour offset.
When the attendee clicks {{reconfirm_url}}, the booking row's reconfirmed_at column is set to the click timestamp. You can filter for unconfirmed bookings on the Bookings tab.
No-show follow-up
When you mark a past meeting as No-show on /calendar, the No-show marked trigger fires. Most teams configure one or two steps:
- An apology email with a single-use re-book link (see Single-Use Links)
- An internal SMS to the rep so they know to follow up by hand
Steps under this trigger default to immediate; you can add a delay (e.g. 1 hour) if you want to give the attendee time to reach out first.
Send from your Gmail or Outlook
Email actions default to sending from notifications@workestra.app. To send from the host's connected mailbox instead — so replies land in their inbox and the email comes from a known sender — toggle Send from connected mailbox on the step.
The substrate ships in this release. The OAuth re-consent step (granting gmail.send or Mail.Send to the host's existing connection) is partial — your existing Google or Microsoft connection needs to be re-authorized once for the additional scope. Until that lands, the toggle gracefully falls back to the workspace alias and logs a warning.
Assigning a workflow to booking links
In the workflow editor, the Booking links field is a multi-select chip picker. Pick the links this workflow should apply to. Leaving it empty means the workflow applies to all links in the workspace by default.
Inside /settings/booking-links/<id>, the Workflows tab on the booking link form shows which workflows are wired up. You can attach or detach from either side — the link's tab or the workflow's editor — they write the same scheduling_workflow_event_types join table.
Cloning, editing, deleting
| Action | Effect |
|---|---|
| Clone | Duplicates the workflow with a "(copy)" suffix. Useful for variant A/B copy. |
| Edit | Existing scheduled steps don't retroactively change — already-enqueued reminders run with the old copy. New bookings use the new version. |
| Delete | Soft-deletes the workflow row. Already-enqueued steps still run (so you don't strand a 24h-out reminder mid-flight). New bookings ignore it. |
Reading the audit log
Every workflow step that fires writes a row to the audit log with the booking id, workflow id, step id, recipient, and channel. Surface it on /settings/security/activity filtered by category scheduling, or join from the booking detail to see "what got sent for this meeting."
Read next
- SMS Notifications — Twilio setup, STOP keyword, credit ledger
- Booking Links — assign workflows to specific links
- Reschedule & Cancel — what happens to in-flight workflows when a booking is moved
- AI Notetaker & Recaps — pipe the recap into a post-meeting email step
- CRM Integrations — push booking events into Salesforce or HubSpot from a workflow
Calendar Dashboard
A four-tab command center — overview stats, all your bookings, every event type you've built, and your routing forms.
SMS Notifications
Send booking reminders, reconfirmation prompts, and follow-ups by text — Twilio-backed, with STOP/START/HELP keyword handling and a per-workspace credit ledger.