Skip to content

Email Automations

An automation is a sequence of emails sent to a recipient over time, triggered by an event. Think: “when someone signs up, send a welcome email immediately, then a tips email 2 days later, then an upgrade prompt 7 days later.”

Trigger fires (webhook POST)
┌─────────────────────────────────────────────┐
│ Automation Run │
│ recipient: alice@example.com │
│ merge data: {name: "Alice", plan: "pro"} │
│ │
│ Step 0 (0s delay): "Welcome, Alice!" ──► sent
│ Step 1 (2d delay): "Getting started" ──► scheduled
│ Step 2 (5d delay): "Go pro?" ──► queued
│ │
│ Status: running | Current step: 1 │
└─────────────────────────────────────────────┘

Each step has a delay, a subject template, and a body template. Forge’s scheduler picks up due runs every 5 seconds and sends the next step.

TriggerHow it firesBest for
WebhookYour app POSTs to a unique webhook URLUser signups, purchases, form submissions
ManualYou add recipients from the dashboardTesting, one-off sequences
ScheduledCron-based recurring triggerWeekly digests, renewal reminders

Go to System Settings → Email → AutomationsCreate Automation.

Name: User Onboarding
Trigger Type: Webhook
Webhook Slug: user-onboarding (auto-generated from name)

Each step defines when and what to send:

Step 1
Delay: 0 seconds (immediate)
Subject: Welcome to {{app_name}}, {{name}}!
Text: Hey {{name}},\n\nThanks for joining the {{plan}} plan!
HTML: <h1>Welcome {{name}}!</h1><p>Thanks for joining <strong>{{plan}}</strong>.</p>
Step 2
Delay: 2 days
Subject: Getting started tips for {{name}}
Text: Hey {{name}},\n\nHere are 3 tips to get the most out of {{app_name}}...
Step 3
Delay: 5 days
Subject: Ready to upgrade, {{name}}?
Text: Hey {{name}},\n\nYou've been on the {{plan}} plan for a week...

Change status from Draft to Active. The webhook URL is now live.

POST /api/v1/email/automations/webhook/user-onboarding
Content-Type: application/json
{
"email": "alice@example.com",
"name": "Alice",
"app_name": "My SaaS",
"plan": "pro"
}

Response (202):

{
"run_id": "run_a1b2c3d4",
"automation_id": "auto_xyz",
"status": "running"
}

All fields except email become merge variables available in your templates.

Use {{variable_name}} in subject and body templates. Supports dot-path for nested JSON:

{{name}} → "Alice"
{{plan}} → "pro"
{{metadata.company}} → "Acme Inc"

Missing variables render as empty string. No conditional logic ({{#if}}) in the current version.

The Runs tab for each automation shows:

  • Recipient email
  • Current step number
  • Status (running, completed, paused, failed)
  • Started at / completed at
  • Next send scheduled time

You can pause individual runs (they stop at the current step) or resume them. Completed runs are retained for the log retention period.

LimitValue
Max automations per identity10
Max steps per automation20
Max concurrent runs per identity50
Scheduler tick interval5 seconds (configurable)

Trigger: Your signup endpoint calls the webhook after creating the user.

# In your signup handler:
await httpx.post(
"https://forge.yourdomain.com/api/v1/email/automations/webhook/welcome",
json={
"email": user.email,
"name": user.name,
"plan": user.plan,
"app_name": "My SaaS"
}
)

Steps configured in Forge:

StepDelaySubject
00sWelcome to My SaaS, {{name}}!
12 days3 tips to get started
25 daysYour first week recap
314 daysReady to upgrade from {{plan}}?

Result: Alice gets 4 emails over 2 weeks, each personalized with her name and plan, without any scheduling code in your application.