# Automations

> E-mail flows for SaaS and apps (onboarding, trial ending, failed payments, re-engagement, abandoned checkout) driven by your events and contacts, and recovery flows for connected stores, with goals, conversions and revenue. Scale plan.

Source: https://docs.pidgely.com/guides/automations/

Automations send a sequence of e-mails when something happens, stop as soon as the person does what the e-mails ask for, and show what they brought back. There are two kinds:

- **Organization automations**, for SaaS products and apps: they start from the [events](https://docs.pidgely.com/guides/events/) your product sends (`user_signed_up`, `payment_failed`…), from new contacts, from a date on the contact (`trial_ends_at`) or from inactivity. No store needed.
- **Store automations**: recovery flows of a [connected store](https://docs.pidgely.com/guides/stores/) (abandoned cart, unpaid Pix/boleto, post-purchase, win-back).

Both are on the **Scale** plan (and custom plans). In the dashboard they are under **Marketing → Automations**: the gallery has two groups, **For SaaS and apps** and **For stores**. Pick a preset, review the e-mails in the visual builder, and activate it.

## For SaaS and apps

### Presets

Each preset comes with its steps, its goal and e-mails designed with your [brand](https://docs.pidgely.com/guides/templates/#the-brand-page) in English, Portuguese (Brazil) and Spanish.

| Preset | Starts when | Default steps | Goal (ends the flow) |
|---|---|---|---|
| **Welcome / onboarding** (Boas-vindas) | The `user_signed_up` event (or, if you switch the trigger, any new contact) | welcome e-mail · wait 2 days → a tip · wait 3 days → a check-in | `activated` |
| **Trial ending** (Teste grátis acabando) | 3 days before the contact's `trial_ends_at` date, at 9h | e-mail "3 days left" · wait 2 days → e-mail "last day" | `subscription_started` (revenue from `amount`) |
| **Failed payment** (Pagamento falhou) | The `payment_failed` event | e-mail now · wait 3 days → e-mail · wait 4 days → e-mail (day 7) | `payment_succeeded` (revenue from `amount`) |
| **Re-engagement** (Reengajamento) | 14 days without a `login` event | e-mail · wait 4 days → e-mail | `login` |
| **Abandoned checkout** (Checkout abandonado) | The `checkout_started` event | wait up to 1 hour for `subscription_started` (exit if it happens) → e-mail · wait 1 day → e-mail | `subscription_started` (revenue from `amount`) |

Event names are only defaults: change the trigger, the goal and the waits to match the events your product already sends.

### Triggers

| Trigger | Options | Starts a flow when |
|---|---|---|
| **Custom event** (`event`) | `event_name` | Your product sends that [event](https://docs.pidgely.com/guides/events/) for a contact. |
| **Contact added** (`contact_added`) | `segment_id` (optional), `sources` (optional) | A contact is created, from any source (dashboard, import, API, store, [captured from your e-mails](https://docs.pidgely.com/guides/contacts/#automatic-contacts-from-your-e-mails), event) or only the `sources` you pick; or, with `segment_id`, when a contact is added to that segment. |
| **Contact date** (`contact_date`) | `property`, `offset_seconds`, `send_hour`, `yearly` | A date on the contact is reached, before or after: `trial_ends_at` with an offset of −3 days, `renewal_at` −7 days, `birthday` with `yearly` on. Dates without a time (`2026-11-05`) fire at `send_hour` (default 9h) in the automation's time zone; dates with a time (`2026-11-05T14:30:00Z`) fire at that moment plus the offset. |
| **Inactivity** (`inactivity`) | `event_name` (empty = any event), `inactive_days` (1 to 365) | A contact sent no such event for that many days since their last one. |

Notes:

- Date properties are plain contact properties (`YYYY-MM-DD` or RFC 3339) set through the [contacts API](https://docs.pidgely.com/guides/contacts/), the dashboard, or the `contact.properties` of an [event](https://docs.pidgely.com/guides/events/). When the date changes, the new date counts. Activating a date automation never mails dates that already passed.
- Date and inactivity triggers are checked by a periodic sweep over indexed tables (every few minutes), so a flow can start a few minutes after the exact time.
- Events older than 24 hours (`occurred_at`) are recorded but start no flow, so importing history does not mail anyone.
- A contact is in an automation at most once at a time. When the flow ends, the next trigger can start it again (a second `payment_failed` next month starts the failed-payment flow again).

### Entry filters

Only contacts that match the **filter** enter: in a segment (`segment_id`), and/or with properties that match (`eq`, `neq`, `exists`, `not_exists`), all conditions together. For example, the trial-ending flow only for `plan` `eq` `pro`. Contacts that do not match are not enrolled; changing the filter applies to new enrollments.

### Steps

Up to 20 steps:

- **Wait**: a duration, from 5 minutes to 90 days.
- **E-mail**: a builder template, an optional subject and an optional sender.
- **Wait for event** (`wait_event`): waits up to a duration (5 minutes to 30 days) for an event of the contact. If the event happens, the flow either **continues** right away or **exits** (`event_received`); when the time runs out, it either **continues** or **exits** (`timeout`). The abandoned-checkout preset waits an hour for `subscription_started` and exits if it arrives; otherwise it goes on to the reminder.

This is a linear flow with early exits, not a branching tree: each wait-for-event chooses between going on and leaving. Two different follow-ups (one for people who did something and one for those who did not) are two automations with different triggers or filters.

### Goals, exit events and conversions

- The **goal** is an event (`subscription_started`, `payment_succeeded`, `activated`…). When the contact sends it, the flow ends (`goal`) and, if they received an e-mail of the automation within the [attribution window](#settings), it counts as a **conversion**. Set `value_property` (for example `amount`) and its value is added up as **revenue**: send it in major units (`49.90`), shown in the automation's `settings.currency` (BRL by default).
- **Exit events** end the flow without counting as a conversion (`exit_event`), for example `account_deleted`.
- Each enrollment converts at most once, credited to the last e-mail it received.

The automation page shows conversions and revenue whether they come from a goal event or from store orders.

## For stores

These run on a [connected store](https://docs.pidgely.com/guides/stores/) and start from its events.

| Preset | Starts when | Default steps | Stops when (goal) |
|---|---|---|---|
| **Abandoned cart** (Carrinho abandonado) | A checkout with an e-mail is left idle for an hour (`checkout.abandoned`) | wait 1 h → e-mail · wait 23 h → e-mail · wait 48 h → e-mail with an optional coupon | The checkout is recovered or completed, or the customer places any order in the store |
| **Unpaid Pix/boleto** (Pix/Boleto não pago) | An order is placed with payment pending and a Pix or boleto payment method | wait 30 min → e-mail with the payment link · wait 24 h → e-mail | The order is paid or cancelled |
| **Post-purchase** (Pós-compra) | The order is delivered (`order.delivered`); for stores whose platform never reports deliveries, 7 days after payment | wait 1 day → thank-you e-mail · wait 6 days → review request | The order is cancelled or refunded |
| **Win-back** (Reconquista) | The customer's last paid order is 90 days old (checked daily) | e-mail · wait 7 days → e-mail | The customer places a new order |

Without a connected store, these presets show **Connect a store** in the gallery; the SaaS presets work right away.

Pix and boleto are recognised from the payment method each platform reports, whatever the gateway: `pix`, `Pix`, `mercado_pago_pix`, `PIX via Mercado Pago`, `boleto`, `Boleto Bancário`, `ticket` (Mercado Pago), `Bank Invoice` (VTEX) and so on. The trigger options set which of the two the payment flow covers, the delivery fallback (1 to 60 days) and the win-back inactivity (14 to 730 days).

Before **every** e-mail of a store automation, Pidgely checks the goal again against the store's current data: a checkout that was recovered, an order that was paid, a customer who already bought. Store events stop flows the moment they arrive, and this check catches anything a platform reported late. The exit reasons `order_placed`, `checkout_recovered`, `checkout_completed` and `paid` are goals.

An order counts as recovered revenue when the customer received an automation e-mail in the attribution window before placing it. Each order counts **once**, credited to the **last** automation e-mail the customer received. For **Unpaid Pix/boleto**, what counts is the payment of that very order. Amounts are in the store's currency. The store page has a summary card of its automations for the last 30 days.

Store automations can also use wait-for-event steps, exit events and entry filters, with the [events](https://docs.pidgely.com/guides/events/) your systems send for the same addresses.

## Settings

- **Quiet hours**: no e-mails between 22h and 8h by default; an e-mail due in that window waits until 8h. Hours are in the automation's time zone: for store automations the **store's** (from its currency: BRL São Paulo, ARS Buenos Aires, MXN Mexico City…), for organization automations the time zone of the browser that created it (São Paulo when unknown). Set another IANA time zone, change the hours or turn them off.
- **Frequency cap** (on by default): at most one automation e-mail per person every 24 hours, across all your automations. A second e-mail waits until the 24 hours have passed.
- **Attribution window**: conversions up to 7 days (1 to 30) after an automation e-mail count.
- **Sender** (organization automations): the default `From` of the e-mails. Each e-mail can override it; without either, the template's sender is used. Store automations use the store's sender address.
- **Currency** (organization automations): the currency of the goal revenue.

The enrollments table shows the step each person is on (and the event a wait-for-event step is waiting for) and why each one left: `goal`, `exit_event`, `event_received`, `timeout`, `unsubscribed`, `suppressed`, `expired`, `deleted`, `failed`, plus the store reasons (`order_placed`, `checkout_recovered`, `checkout_completed`, `paid`, `cancelled`, `refunded`, `store_disconnected`). Editing the steps of an active automation applies from each person's next step on.

## Consent and unsubscribes

Automations are **marketing** e-mail. They:

- skip contacts who unsubscribed and addresses on your [suppression list](https://docs.pidgely.com/guides/suppressions/) (bounces, complaints, unsubscribes, manual entries); the person leaves the flow (`unsubscribed` or `suppressed`);
- carry the one-click unsubscribe link in the footer and the `List-Unsubscribe` and `List-Unsubscribe-Post` headers, exactly like [broadcasts](https://docs.pidgely.com/guides/broadcasts/). Unsubscribing from an automation e-mail unsubscribes the address from your marketing e-mail, and every automation drops it before its next e-mail.

Your transactional e-mails (password resets, receipts, login codes sent through the API, store [order e-mails](https://docs.pidgely.com/guides/order-emails/)) do not depend on automations and keep going to people who unsubscribed from marketing, unless the address is suppressed.

**Unpaid Pix/boleto**, **Post-purchase**, **Failed payment** and **Trial ending** are close to transactional, but they are still treated as marketing for unsubscribe purposes: the person did not request them, and Gmail and Yahoo expect one-click unsubscribe on lifecycle mail.

## E-mails, templates and variables

Creating an automation creates one [builder template](https://docs.pidgely.com/guides/templates/) per e-mail, with your **brand** (logo, colors, fonts, footer address and social links). Store automations use the store's language as the base language; SaaS presets use the language you work in (the dashboard's), with variants in the other two. Click an e-mail in the flow to open it in the visual builder; the automation sends the **published** version, in the contact's `language` [property](https://docs.pidgely.com/guides/contacts/) when it has a variant (else the base language). Automation templates do not count toward the [template limit](https://docs.pidgely.com/guides/templates/#template-limits).

Variables of organization automations (the builder's **Insert variable** menu lists them):

| Variable | Value |
|---|---|
| `{{{contact.first_name}}}`, `{{{contact.last_name}}}`, `{{{contact.email}}}` | The contact, read when the e-mail is sent. |
| `{{{contact.<property>}}}` | Any contact property: `{{{contact.plan}}}`, `{{{contact.trial_ends_at}}}`. |
| `{{{event.name}}}`, `{{{event.<property>}}}` | The event that started the flow: `{{{event.plan}}}`, `{{{event.amount}}}`, `{{{event.payment_url}}}`. |
| `{{{COMPANY_NAME}}}`, `{{{COMPANY_URL}}}` | Your brand's name and website. |
| `{{{FIRST_NAME}}}`, `{{{LAST_NAME}}}`, `{{{EMAIL}}}`, `{{{UNSUBSCRIBE_URL}}}` | As in [broadcasts](https://docs.pidgely.com/guides/broadcasts/). |

Fallbacks work as everywhere: `{{{contact.first_name|there}}}`. A missing value without a fallback renders empty.

Variables of store automations: `STORE_NAME`, `STORE_URL`, `CUSTOMER_FIRST_NAME`, `CUSTOMER_NAME`, `CUSTOMER_EMAIL`, `CART_RECOVERY_URL` (the platform's link that restores the cart), `CART_TOTAL`, `ORDER_NUMBER`, `ORDER_TOTAL`, `ORDER_DATE`, `ORDER_STATUS_URL`, `ORDER_PAYMENT_URL` (the order page, where Pix and boleto can be paid), `PAYMENT_METHOD`, `COUPON_CODE`, and the **Cart items** and **Order items** blocks. When a step has no coupon code, blocks that mention `{{{COUPON_CODE}}}` are left out of that e-mail.

Links are tracked like any other e-mail when [click tracking](https://docs.pidgely.com/guides/tracking/) is on for the sending domain; opens and clicks per step come from those events. Every automation e-mail also appears in **Emails**, tagged `automation` and `automation_step`, so you can filter [metrics](https://docs.pidgely.com/guides/metrics/) by them.

## Stats

The automation page shows, for the whole flow and per step: people enrolled, e-mails sent, unique opens and clicks, exits by goal, conversions and revenue, with a daily chart.

## Plans, pausing and deleting

Automations run on **Scale** and custom plans. On other plans the automations page shows the presets locked, and the API answers `403 plan_required` (`field: "automations"`). [Events](https://docs.pidgely.com/guides/events/) and [automatic contacts](https://docs.pidgely.com/guides/contacts/#automatic-contacts-from-your-e-mails) work on every plan, so your history is ready when you upgrade. If an organization moves to a plan without automations, its active automations are **paused** (`status_reason: "plan"`), never sending in the meantime; activate them again after upgrading.

**Pause** stops new enrollments and holds the people in the flow. **Activate** resumes them where they were; an e-mail that became more than three days late while paused is dropped (`expired`), so nobody gets a stale reminder. Activating needs a sender on a verified domain for every e-mail. **Delete** ends the flow for everyone in it; its templates stay in Templates.

## From the API

The same features are available to full access API keys ([API reference](https://docs.pidgely.com/api-reference/automations/list/)). Create the trial-ending automation (no store):

```bash tab="cURL"
curl -X POST 'https://api.pidgely.com/automations' \
  -H "Authorization: Bearer $PIDGELY_API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{
  "preset": "trial_ending",
  "locale": "pt-BR",
  "timezone": "America/Sao_Paulo"
}'
```

It starts as a `draft`. Adjust it: here, only contacts on the `pro` plan, the default sender, and the goal with its revenue property:

```bash tab="cURL"
curl -X PATCH 'https://api.pidgely.com/automations/0199e3d1-4a5b-7c6d-8e9f-0a1b2c3d4e51' \
  -H "Authorization: Bearer $PIDGELY_API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{
  "filter": {
    "segment_id": null,
    "properties": [
      {
        "key": "plan",
        "op": "eq",
        "value": "pro"
      }
    ]
  },
  "goal": {
    "event_name": "subscription_started",
    "value_property": "amount"
  },
  "settings": {
    "quiet_hours": {
      "enabled": true,
      "start": 22,
      "end": 8,
      "timezone": "America/Sao_Paulo"
    },
    "frequency_cap": true,
    "attribution_days": 7,
    "from": "Fexxo <oi@fexxo.com.br>",
    "currency": "BRL"
  }
}'
```

```bash tab="cURL"
curl -X POST 'https://api.pidgely.com/automations/0199e3d1-4a5b-7c6d-8e9f-0a1b2c3d4e51/activate' \
  -H "Authorization: Bearer $PIDGELY_API_KEY"
```

For a store automation, pass the store:

```bash tab="cURL"
curl -X POST 'https://api.pidgely.com/automations' \
  -H "Authorization: Bearer $PIDGELY_API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{
  "preset": "cart_abandoned",
  "store_id": "0199e0f2-1a2b-7c3d-9e4f-5a6b7c8d9e01"
}'
```

Read the results:

```bash tab="cURL"
curl -X GET 'https://api.pidgely.com/automations/0199e3d1-4a5b-7c6d-8e9f-0a1b2c3d4e51/stats?days=30' \
  -H "Authorization: Bearer $PIDGELY_API_KEY"
```
