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

# Workflows

> Steps, delays, and triggering a workflow for a subscriber.

A workflow is a sequence of emails that goes out automatically to one person, such as a welcome email now and a follow-up two days later. Each step is an email or a webhook, with an optional wait before it.

You describe a workflow as JSON:

```json theme={null}
{
  "key": "trial",
  "name": "Trial onboarding",
  "description": "Nudges people through their trial",
  "type": "automation",
  "steps": [
    {
      "type": "email",
      "subject": "Your trial has started",
      "body": "<p>Hey {{ subscriber.firstName | default: \"there\" }}, you have 14 days of Pro.</p>"
    },
    {
      "type": "email",
      "delayMs": 259200000,
      "subject": "Three things to try",
      "body": "<ul><li>…</li></ul>"
    }
  ],
  "triggers": [{ "source": "stripe", "event": "trial_started" }],
  "exitConditions": [{ "source": "stripe", "event": "trial_converted" }]
}
```

| Field | Description |
| - | - |
| `key` | Stable identifier you trigger the workflow by, such as `welcome`. Unique within the environment. |
| `name`, `description` | For you and your agent. |
| `type` | `automation` (triggered per subscriber, the default) or `broadcast` (sent to everyone). This only organises your workflows; either type can be used either way. |
| `steps` | 1 to 50 email or webhook steps. |
| `triggers`, `exitConditions` | Events from connected integrations that start or stop the workflow. See [Stripe triggers](https://docs.subscriber.dev/integrations/stripe.md). |

## Creating a workflow

Write the JSON yourself, or let your agent or the TUI build it for you.

Or ask [your agent](https://docs.subscriber.dev/mcp.md): "Create a trial onboarding workflow: an email when the trial starts, three tips three days later, and stop it when they convert." It writes the steps and templates for you.

> [tab] CLI
>
> ```bash theme={null}
> subscriber workflows create --file trial.json
> subscriber workflows update <workflowId> --file trial.json
> ```

> [tab] TUI
>
> Open **Workflows** and press `n`. On a workflow, press `e` to edit it or `g` to edit its triggers and exit conditions.

> [tab] API
>
> ```bash theme={null}
> curl -X POST https://api.subscriber.dev/workflows \
>   -H "x-api-key: $KEY" -H "content-type: application/json" \
>   -d @trial.json
> ```

### Sender

Every email in a workflow comes from the same sender. Set `channels.email.fromName` and `channels.email.replyTo` on the workflow to override your email integration's, for example onboarding from "Jane at Acme" and billing from "Acme Billing". The from address always comes from the integration, because providers only send from domains you've verified.

```json theme={null}
{
  "key": "trial-onboarding",
  "name": "Trial onboarding",
  "channels": {
    "email": { "fromName": "Jane at Acme", "replyTo": "jane@acme.com" }
  },
  "steps": [ … ]
}
```

In an update, each channel you include replaces that channel's settings, and channels you leave out don't change. Set `channels.email` to `null` to go back to the integration's.

## Steps

A step is one thing the workflow does: send an email or call a URL.

### Email

Sends an email to the subscriber.

| Field | Description |
| - | - |
| `subject` | Up to 500 characters. Supports templates. |
| `body` | HTML or plain text. Supports templates. |
| `layout` | `default` or `none`. See [Layouts](https://docs.subscriber.dev/templates.md#layouts). |
| `previewText` | Optional short summary inboxes show next to the subject. Supports templates. Default layout only. |
| `delayMs` | How long to wait after the previous step, or after the trigger for the first step. Defaults to `0`. |

[Opted-out subscribers](https://docs.subscriber.dev/subscribers.md#opting-in-and-out) are never emailed. Every email includes one-click unsubscribe headers, which Gmail and Yahoo require from bulk senders.

### Webhook

Posts JSON to an HTTPS URL, for example to tell your team in Slack or Discord when someone signs up.

```json theme={null}
{
  "type": "webhook",
  "url": "https://discord.com/api/webhooks/…",
  "body": "{\"content\": {{ subscriber.email | append: \" just signed up\" | json }}}"
}
```

`body` is rendered as a [template](https://docs.subscriber.dev/templates.md) and sent as-is with `Content-Type: application/json`. Wrap values in the `json` filter so the result stays valid JSON.

### Delays

A delay is how long to wait before a step. `delayMs` is in milliseconds:

| Delay | `delayMs` |
| - | - |
| 1 hour | `3600000` |
| 1 day | `86400000` |
| 3 days | `259200000` |
| 1 week | `604800000` |

Delays add up: a step with a one-day delay after a step with a two-day delay sends three days after the trigger.

## Editing emails in the browser

The email editor lets you tweak the copy your agent wrote, preview it with your own details filled in, and send yourself a test. Type `/` to add a heading, button, image, video, list or divider, and `{{` to add a variable such as the subscriber's first name.

Drop or paste an image straight into the email to upload it, up to 5 MB. Click an image to set its alt text, link, size and alignment. Email apps can't play video, so a video shows its thumbnail with a play button, linked to the video. Paste a YouTube, Vimeo or Loom link. Agents can do the same with `subscriber uploads image` and `subscriber uploads video`, or the `upload_image` and `add_video` MCP tools.

```bash theme={null}
subscriber workflows edit <workflowId>
```

This opens the editor in your browser. Your agent can also give you the link: every workflow has an `editUrl`.

Emails with a custom template (`"layout": "none"` or a full HTML document) open as HTML instead, so the editor never changes your markup. Saving replaces the workflow's steps, the same as an update; runs already in progress keep the version they started with.

## Triggering a workflow

Triggering a workflow starts it for one subscriber. Workflows run for one subscriber at a time. Usually your app triggers them, but you can also trigger them by hand:

> [tab] CLI
>
> ```bash theme={null}
> subscriber workflows trigger welcome --email jane@acme.com --payload '{"plan": "pro"}'
> ```

> [tab] TUI
>
> Open **Workflows**, choose the workflow, press `t` and enter the subscriber's email.

> [tab] API
>
> ```bash theme={null}
> curl -X POST https://api.subscriber.dev/workflows/trigger \
>   -H "x-api-key: $KEY" -H "content-type: application/json" \
>   -d '{"key": "welcome", "subscriber": {"email": "jane@acme.com"}, "payload": {"plan": "pro"}}'
> ```

Identify the subscriber by `email`, `externalId` or `publicId`. They have to exist already.

If the workflow is paused, the trigger returns `{"triggered": false, "reason": "workflow_paused"}` and nothing sends.

To start workflows automatically from events in your other tools, see [Stripe triggers](https://docs.subscriber.dev/integrations/stripe.md). To send a workflow to everyone at once, see [Broadcasts](https://docs.subscriber.dev/broadcasts.md).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.