> ## Documentation Index
> Fetch the complete documentation index at: https://docs.senderz.app/llms.txt
> Use this file to discover all available pages before exploring further.

# Flow steps and actions

> Every block you can place in an automation: messages, wait timers, splits, and the data actions that file, tag, notify and call out.

An automation is built from **steps**. The palette holds twelve blocks in three groups, and each one does exactly one thing to the contact who reached it.

Steps stay locked until you have picked a trigger and pressed **Save** in the trigger setup panel. Until then the canvas shows **Select a trigger to start**.

## The palette

| Group        | Blocks                                                                                    |
| ------------ | ----------------------------------------------------------------------------------------- |
| **Messages** | Email, SMS, WhatsApp, Push                                                                |
| **Data**     | Grant points, Update user properties, Update in list, Internal team notification, Webhook |
| **Logic**    | A/B test, Wait, Conditional split                                                         |

<Note>
  Voice calls are not a step you can place in an automation. Voice is still a
  live Senderz channel for one-time passcodes, but it is not in the palette.
  See [Voice](/en/channels/voice).

  **Goal** and **End** are also not blocks you add. The end marker on the
  canvas is drawn for you under every last step and under any branch you have
  not wired up.
</Note>

## Live and draft steps

This is the setting that catches people out, so read it before anything else.

Every **message** step and every **Update in list** step carries a delivery state of **Live** or **Draft**, and every one of them is created as a **Draft**.

A draft step does nothing at send time. The contact reaches it, the step is skipped, and they move on to the next step as if it were not there. No email goes out, no list changes, and nothing appears in your reports.

<Warning>
  A draft step is silent. Nothing in the product tells you afterwards that a
  contact passed through one and got nothing.

  It matters more than it looks, because the default re-entry setting is
  **Enter only once**. If a contact flows past a draft step today, setting that
  step live tomorrow will not send them anything. They have already been
  through, and they cannot be enrolled again.
</Warning>

You set the state on the step itself. Select the step, and the **Delivery** control at the top of the inspector switches between **Live** and **Draft**. On the canvas, each message card shows a Live or Draft badge so you can read the whole automation at a glance.

If you press **Publish** while every message step is still a draft, Senderz offers to set them all live for you in one go, and tells you how many have no content yet and will stay drafts.

## A message step is not required to publish

Since 5 August 2026, an automation does not need a message step at all. An automation that only tags a profile, files someone into a list, notifies your team or calls a webhook is real work, and it publishes on its own.

What is still rejected is an automation that would enrol people and do nothing. Publishing is blocked when **all three** of these are true:

1. The automation has at least one message step.
2. Every one of those message steps is a draft.
3. There is no data action step anywhere in it (Webhook, Update user properties, Update in list, Internal team notification or Grant points).

The message you get is: *Every message step is still a draft, so this automation would send nothing. Set at least one step live before publishing.*

Note what that rule does not cover. Add a single Update in list step and the check passes, even if every message step is still a draft. Wait timers, splits and other logic blocks do not count as work.

<Warning>
  A live automation autosaves with no re-check. If you later flip your last
  live message step back to draft, delete it, or disconnect it, the automation
  keeps enrolling people and stops delivering. The editor shows a red **This
  live automation cannot send** alert when that happens. Nothing else in the
  product will tell you.
</Warning>

## Message steps

Email, SMS, WhatsApp and Push all send through the same delivery pipeline a campaign uses. Suppression, consent, frequency caps, quiet hours, Shabbat and the SMS credit wallet all apply at send time, on every message.

### The email step inspector

The email step has a fixed set of sections, always in this order.

<AccordionGroup>
  <Accordion title="1. Title and Delivery" icon="tag">
    The step's name on the canvas, and the **Live** or **Draft** switch.
  </Accordion>

  <Accordion title="2. Performance" icon="chart-simple">
    A 30-day summary for this one step: open rate, click rate, unsubscribe
    rate, placed orders and revenue, plus how many contacts are waiting at this
    step and how many are about to receive it. It appears once the automation
    is live or paused, and **View details** opens the full report.
  </Accordion>

  <Accordion title="3. Content" icon="pen">
    **Subject**, **Preheader**, **Sender name** and **Sender email**. These
    belong to the step, not to the template.
  </Accordion>

  <Accordion title="4. Template" icon="file-lines">
    Pick a template, see a live preview with a **Mobile** and **Desktop**
    toggle, and press **Edit** to open the builder. The template actions menu
    holds exactly four items: **Preview template**, **Change template**, **Save
    as new template** and **Edit plain text**.
  </Accordion>

  <Accordion title="5. Settings" icon="sliders">
    Exactly two checkboxes on an email step. **Skip recently emailed profiles**
    and **Enable UTM tracking**. Both are covered below.
  </Accordion>

  <Accordion title="6. Additional filters" icon="filter">
    Extra conditions a contact must match before this one message sends.
  </Accordion>
</AccordionGroup>

Reply-to and unsubscribe-page pickers are no longer in this panel.

### Sender name and address per step

Each message step can carry its own **Sender name** and **Sender email**. When set, they override whatever the template carries. Leave them blank and the template's sender is used.

The sender email still has to be a verified sending address on a verified domain, exactly as it does for a campaign. See [Domains and senders](/en/deliverability/domains).

### Skip recently emailed profiles

Also called smart sending. When it is on, Senderz will not send this message to a contact who already received a message inside your Smart Sending window.

The window itself is a workspace setting, not a per-step one. It lives in **Settings** under **Sending Settings**, and it holds four separate values, each between 1 and 168 hours:

| Window         | Default  |
| -------------- | -------- |
| Email campaign | 16 hours |
| Email flow     | 24 hours |
| SMS campaign   | 24 hours |
| SMS flow       | 24 hours |

The **Adjust the window** link on the step takes you straight there.

On SMS, WhatsApp and push steps the control is expanded. Turning it on reveals two checkboxes, each
showing the window from your settings: **Skip if a campaign was sent in the last N hours** and **Skip
if another flow message was sent in the last N hours**. Tick either or both.

### UTM tracking

**Enable UTM tracking** appends UTM parameters to every link in the message, so clicks show up in your own analytics tool.

On an email step it is a plain on and off. The values default to a source of `senderz`, a medium of `email` and a campaign named after the automation.

On an SMS step you also get **Source**, **Medium** and **Campaign** fields to fill in yourself. Leave one
blank and it falls back to a source of `senderz`, a medium of `sms` and the automation's name.

UTM parameters are applied to email and SMS links only.

### Additional filters and excluded segments

Every message step can carry its own filter on top of the automation's audience. A contact who does not match **skips that one message and carries on**. They are not removed from the automation.

Non-email steps also get an **Exclude segments** picker. Contacts in any of the chosen segments skip that message. See [Segments](/en/audience/segments).

### SMS quiet hours on a step

SMS, WhatsApp and push steps carry a **Respect SMS quiet hours** switch, which is on by default, plus a nested **Respect Shabbat** switch that is also on.

Leaving them on is the normal state and is what the law expects. Turning one off is an explicit override that lets that step send inside the 20:00 to 08:00 window, or during Shabbat.

<Info>
  Email steps have no such switch, because marketing email is exempt from the
  legal Israeli window by product decision. An email step in an automation does
  **not** defer overnight. It still honours your own workspace quiet hours
  setting. See [Quiet hours and
  Shabbat](/en/compliance/quiet-hours).
</Info>

### Merge tags from the triggering event

An automation knows what started it, so message steps can use the event's own data as merge tags. Which ones are available depends on the trigger.

Store events pass through `{{amount}}`, `{{currency}}`, `{{orderId}}`, `{{externalId}}`, `{{recoveryUrl}}` and `{{sourceName}}`. A custom event passes through any property you sent with it.

Order line items are available as a collection for a for-loop, up to 100 items, each exposing `{{item.name}}`, `{{item.sku}}`, `{{item.price}}`, `{{item.quantity}}`, `{{item.productId}}` and `{{item.variantId}}`.

<Info>
  `{{amount}}` is the raw amount from the event in major units, for example
  `249.90`. It is not currency-formatted for you.
</Info>

Six tag names are reserved and event data can never overwrite them: `{{firstName}}`, `{{lastName}}`, `{{email}}`, `{{phone}}`, `{{unsubscribeUrl}}` and `{{converted}}`.

### WhatsApp steps

A WhatsApp step does not use a Senderz template. It sends an approved WhatsApp template from your provider, so the step asks for the template name, a language code, and one parameter per placeholder in that template, in order. Parameters accept merge tags.

WhatsApp runs on a shared business number that our team switches on for your workspace, so the block stays locked until it is enabled for you.

## Timing

### Wait

The Wait block has two modes.

<Tabs>
  <Tab title="Wait a while">
    Hold the contact for an **Amount** of **Minutes**, **Hours** or **Days**.
    The default is 24 hours.

    Two optional extras stack on top:

    * **Also wait until a time** holds the contact past the delay until a set
      hour and minute. You choose whether that clock is the **Recipient
      timezone** or the **Account timezone**.
    * **Also wait until certain days** only releases the contact on the
      weekdays you tick.

    Combine them to say "wait 3 days, then release at 09:00 on a weekday".
  </Tab>

  <Tab title="Wait for event">
    Hold the contact until a chosen event happens, or until a maximum wait
    elapses. The default is 7 days.

    This mode creates **two branches**, labelled **Event happened** and **Time
    expired**. Both have to be wired up before the automation can publish.
  </Tab>
</Tabs>

A contact parked in a wait is not frozen out of everything. Your exit rules are still swept while they wait, so someone who becomes eligible to leave does so without sitting out the rest of the timer.

## Logic

### Conditional split

A conditional split evaluates a filter against the contact and sends them down one of two branches: **Yes** for a match, **No** for everyone else.

The branch is chosen by the connector you dragged from, not by the order you drew the edges in. The Yes handle always carries matches and the No handle always carries the rest, whichever one you wired first.

<Warning>
  A half-wired split stops the contact. If you connect only the **Yes** branch,
  a contact who does not match reaches the end of their journey rather than
  quietly continuing down the branch you did draw. Wire both outcomes unless
  stopping is what you want.
</Warning>

Use one split inside one automation rather than duplicating the whole automation per segment.

### A/B test

An A/B test splits traffic between **Path A** and **Path B**.

* **Split** is the percentage sent down Path A, between 10 and 90.
* **Goal metric** is one of Open rate, Click rate, Conversion (Placed Order), Revenue per recipient, or a Custom event you name.
* **Duration (hours)** and **Minimum sample**. You need at least one of the two.
* **Automatically promote winner** moves future traffic to the significant winner. The change is versioned and reversible.

The assignment is stable per contact. Once someone is put on Path A they stay on Path A for that journey, even if the step runs again.

Both branches have to be connected before the automation can publish.

## Data actions

### Update in list

Adds a contact to lists, removes them from lists, or both in the same step.

* **Lists to add** and **Lists to remove** are separate pickers. A list chosen on one side is disabled on the other.
* A contact already on a list you are adding is skipped, and so is a contact who is not on a list you are removing.
* This step carries the same **Status** of Live or Draft as a message step, and it starts as a **Draft**.

<Note>
  This block works on **lists only**, never on segments. A list is something you
  put people on and take them off by hand. A segment is calculated from its own
  definition, so there is nothing for an automation to change. If you want an
  automation to move people between audiences, use lists.
</Note>

A list cannot be both added and removed in the same step. The picker greys out the conflict, and publishing is blocked if one slips through.

### Update user properties

Sets contact properties when the contact reaches this step.

Pick a property, then type the value. The value box is typed to the property, and it validates before you save:

| Property type            | What is accepted                                                           |
| ------------------------ | -------------------------------------------------------------------------- |
| Number or currency       | A number. Otherwise: *Enter a number.*                                     |
| URL                      | An http or https address with a real host. Otherwise: *Enter a valid URL.* |
| Coordinate               | A value between -180 and 180                                               |
| Boolean                  | Yes or No                                                                  |
| Text and everything else | Free text                                                                  |

You can set any custom property, plus these built-in fields: first name, last name, timezone, language, locale and country. Computed fields are not offered, because Senderz calculates them for you and would overwrite whatever you set on the next run.

If a property was deleted from your account after you built the step, the row shows it as *no longer available* with a prompt to pick another or remove it, rather than failing quietly.

### Internal team notification

Posts an alert to your team, not to the contact.

* **Message** is the alert text. It appears in the in-app notification bell, linking back to the automation.
* **Also send an email** additionally emails the alert to the addresses you list in **Recipient emails**, comma separated.

Leave the message blank and the step does nothing.

### Webhook

Posts the contact to a **POST URL** of your choosing when they reach this step.

<Warning>
  The address has to be a public HTTPS address on the default port. Internal,
  private and loopback addresses are rejected, because this step sends contact
  details to whatever answers.

  The check runs when you save, again when you publish, and again immediately
  before each call, since an address that resolved publicly last week can point
  somewhere else today.
</Warning>

If you want richer delivery, retries and signatures, use [outbound webhooks](/en/integrations/webhooks-outbound) instead.

### Grant points

Adds or removes loyalty points through a connected loyalty app.

* **Loyalty app** is Rivo or Yotpo Loyalty and Referrals. Only apps connected to this workspace appear.
* **Points adjustment** takes a positive number to grant points or a negative number to take them away.
* **Customer history title** is the label the customer sees against the adjustment.
* **Send email from Senderz only** stops Rivo sending its own parallel points email. For Yotpo, disable the matching notification in Yotpo itself.

The block is locked until a loyalty app is connected. See [Integrations](/en/integrations/overview).

## Steps that need setting up first

Four blocks are locked in the palette until a prerequisite is in place. Clicking a locked block explains why and, where you can fix it yourself, links you there.

| Block        | Requirement                | Where to fix it                                                                 |
| ------------ | -------------------------- | ------------------------------------------------------------------------------- |
| SMS          | An approved sender ID      | Settings, **SMS Sender names**. See [Sender IDs](/en/deliverability/sender-ids) |
| Grant points | A connected loyalty app    | [Integrations](/en/integrations/overview)                                       |
| WhatsApp     | Enabled for your workspace | Contact support                                                                 |
| Push         | Enabled for your workspace | Contact support                                                                 |

WhatsApp and push run on shared infrastructure that our team provisions, so there is no self-serve screen for them. The dialog says so rather than sending you somewhere useless.

While Senderz is still checking, nothing is locked. A block is only greyed out once we know for certain the prerequisite is missing.

## Working on the canvas

<Steps>
  <Step title="Add a step">
    Drag a block from the palette onto the canvas, press the **+** on a
    connector to splice a step between two existing ones, or click the
    connector under a step and pick from the menu. Dropping a block shows an
    insertion indicator so you can see where it will land.
  </Step>

  <Step title="Connect two steps">
    Drag from a step's bottom connector onto another step. Valid landing spots
    highlight as you drag.

    A step can only lead to one next step, and a path cannot loop back on
    itself. An invalid target is refused with *These steps can't be connected*
    rather than being silently accepted.
  </Step>

  <Step title="Rewire or detach">
    Drag the arrow head of an existing connection onto a different step to
    rewire it. Drop it on empty canvas to detach it. The end the connection
    leaves from does not move.
  </Step>

  <Step title="Duplicate">
    Use **Duplicate** on the step's menu. The copy is inserted directly after
    the original with all of its settings, and it becomes the selected step so
    you can edit it straight away.
  </Step>

  <Step title="Tidy up">
    **Tidy** in the header re-lays out the whole canvas. **Undo** and **Redo**
    sit next to it and cover every edit.
  </Step>
</Steps>

Each step's menu also holds **Edit**, **Edit template** on a message step, and **Delete**.

### The end marker

Senderz draws an end marker under every last step, and under every branch handle you have not wired yet. That is how you spot a half-wired conditional split at a glance.

It is drawn for you. There is nothing to place and nothing to delete. If you open an older automation that had a stored end block in it, it is removed on open and the connections are joined across it.

## Publish checks that come from your steps

Most publish failures point at a specific step. These are the ones to know:

| What is wrong                                               | What to do                                       |
| ----------------------------------------------------------- | ------------------------------------------------ |
| A step is not reachable from the trigger                    | Reconnect it, or delete it                       |
| Every message step is a draft, with no data action anywhere | Set at least one message step live               |
| A live email, SMS or push step has no template              | Choose a template, or set the step back to draft |
| A live email step has an invalid reply-to address           | Fix the address                                  |
| A live WhatsApp step has no template name                   | Enter the approved template name                 |
| An A/B test has fewer than two branches                     | Connect both paths                               |
| An A/B test has no goal                                     | Choose a goal metric                             |
| An A/B test split is outside 10 to 90                       | Move the slider back in range                    |
| An A/B test has no duration and no minimum sample           | Set one of the two                               |
| An Update in list step adds and removes the same list       | Remove the list from one side                    |
| A wait-for-event step has no event                          | Choose the event to wait for                     |
| A wait-for-event step is missing a branch                   | Connect both the event and the timeout paths     |
| A webhook points at a non-public address                    | Use a public HTTPS address on the default port   |

A single contact's journey through an automation is capped at 200 steps. The canvas already refuses to
let a path loop back on itself, so this is a backstop rather than something you will meet in normal use.
A contact who does hit it stops there.

## Related

<CardGroup cols={2}>
  <Card title="Automations overview" icon="bolt" href="/en/messaging/flows">
    What an automation is, how to create one, and the draft, live and paused
    lifecycle.
  </Card>

  <Card title="Templates and content" icon="file-lines" href="/en/messaging/templates">
    The email builder, SMS and push templates, and merge tags.
  </Card>

  <Card title="Segments" icon="filter" href="/en/audience/segments">
    Building the audiences you filter a step against.
  </Card>

  <Card title="Quiet hours and Shabbat" icon="moon" href="/en/compliance/quiet-hours">
    Which channels defer, and which are exempt.
  </Card>
</CardGroup>
