Grosend|Docs
Getting Started
  • Introduction
  • Quick Start
Sending
  • SMTP Relay
  • Authentication
Automation
  • Overview
API Reference
  • Overview
  • Send Email
  • Domains
  • Templates
  • API Keys
  • Webhooks
Analytics
  • Tracking
Docs
Getting Started
  • Introduction
  • Quick Start
Sending
  • SMTP Relay
  • Authentication
Automation
  • Overview
API Reference
  • Overview
  • Send Email
  • Domains
  • Templates
  • API Keys
  • Webhooks
Analytics
  • Tracking

Automation

Create multi-step email sequences triggered by contact events. Automate onboarding, re-engagement, transactional workflows, and more — no code required.

How it works

An automation has three parts: a trigger that starts the sequence, a series of steps (each sending an email), and delays between steps. When a contact matches the trigger, they're enrolled and emails are sent on schedule.

1

Trigger

Contact joins a list or a property changes

2

Enroll

Contact enters the automation

3

Step 1

Send first email (immediately or after delay)

4

Delay

Wait (1 hour, 1 day, 1 week...)

5

Step 2

Send next email

6

Complete

All steps sent

Trigger types

Automations start when a contact matches a trigger condition. Three trigger types are supported:

1. List join

Fires when a contact is added to a specific contact list. Use this for welcome sequences, onboarding flows, and campaign-based automations.

Trigger config
{
  "triggerType": "list_join",
  "triggerConfig": {
    "listName": "new-users"
  }
}

2. Property equals

Fires when a contact property matches a specific value. Use this for behavioral triggers like abandoned carts, payment reminders, or inactivity alerts.

Trigger config
{
  "triggerType": "property_equals",
  "triggerConfig": {
    "property": "abandoned_cart",
    "value": "true"
  }
}

3. Property changes

Fires when a contact property changes from one value to another. Use this for status transitions like trial-to-paid, loan approval, or account verification.

Trigger config
{
  "triggerType": "property_changes",
  "triggerConfig": {
    "property": "kyc_status",
    "fromValue": "pending",
    "toValue": "approved"
  }
}

Creating an automation

Create an automation with a trigger and one or more steps. Each step defines an email to send and a delay before sending.

Create automation
curl -X POST https://api.grosend.com/api/v1/automations \
  -H "Authorization: Bearer sv_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Welcome Series",
    "description": "4-day onboarding for new users",
    "triggerType": "list_join",
    "triggerConfig": { "listName": "new-users" },
    "steps": [
      {
        "delayMinutes": 0,
        "subject": "Welcome to {{company}}, {{name}}!",
        "bodyHtml": "<h1>Welcome!</h1><p>We are glad to have you.</p>"
      },
      {
        "delayMinutes": 1440,
        "subject": "Getting started guide",
        "bodyHtml": "<h1>Quick start</h1><p>Here is how to get the most out of Grosend.</p>"
      },
      {
        "delayMinutes": 4320,
        "subject": "Tips for better deliverability",
        "bodyHtml": "<h1>Deliverability tips</h1><p>Follow these best practices.</p>"
      },
      {
        "delayMinutes": 10080,
        "subject": "Need help?",
        "bodyHtml": "<h1>We are here for you</h1><p>Reply to this email anytime.</p>"
      }
    ]
  }'

Response:

201 Created
{
  "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "name": "Welcome Series",
  "description": "4-day onboarding for new users",
  "status": "draft",
  "triggerType": "list_join",
  "triggerConfig": { "listName": "new-users" },
  "totalSent": 0,
  "steps": [
    { "id": "s1...", "position": 0, "delayMinutes": 0, "subject": "Welcome to {{company}}, {{name}}!" },
    { "id": "s2...", "position": 1, "delayMinutes": 1440, "subject": "Getting started guide" },
    { "id": "s3...", "position": 2, "delayMinutes": 4320, "subject": "Tips for better deliverability" },
    { "id": "s4...", "position": 3, "delayMinutes": 10080, "subject": "Need help?" }
  ],
  "createdAt": "2026-01-15T10:30:00Z"
}

Managing steps

Steps are ordered by position (0, 1, 2...). You can add, update, or remove steps at any time while the automation is paused.

Add a step

Add step
curl -X POST https://api.grosend.com/api/v1/automations/{automation-id}/steps \
  -H "Authorization: Bearer sv_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "delayMinutes": 20160,
    "subject": "Final check-in",
    "bodyHtml": "<h1>How is it going?</h1><p>Let us know if you need anything.</p>"
  }'

Update a step

Update step
curl -X PUT https://api.grosend.com/api/v1/automations/{automation-id}/steps \
  -H "Authorization: Bearer sv_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "stepId": "step-id",
    "subject": "Updated subject line",
    "delayMinutes": 7200
  }'

Delete a step

Delete step
curl -X DELETE https://api.grosend.com/api/v1/automations/{automation-id}/steps \
  -H "Authorization: Bearer sv_live_..." \
  -H "Content-Type: application/json" \
  -d '{ "stepId": "step-id" }'
Deleting a step automatically reorders the remaining steps. Step positions are recalculated sequentially (0, 1, 2...).

Activation and pausing

Automations start in draft status. Activate to start enrolling contacts. Pause to stop new enrollments.

Activation lifecycle
# Activate
curl -X POST https://api.grosend.com/api/v1/automations/{id}/activate \
  -H "Authorization: Bearer sv_live_..."

# Response
{ "id": "...", "status": "active" }

# Pause
curl -X POST https://api.grosend.com/api/v1/automations/{id}/pause \
  -H "Authorization: Bearer sv_live_..."

# Response
{ "id": "...", "status": "paused" }
draft→active(POST /activate)
active→paused(POST /pause)
paused→active(POST /activate)
Pausing does not cancel already-enqueued emails. Contacts currently waiting for a delayed step will still receive their next email. Pausing only prevents new enrollments.

Enrollments

An enrollment tracks a contact's progress through an automation. Each contact can only be enrolled once per automation. Enrollments are created automatically by the trigger engine — you cannot create them via API.

Enrollment statuses

activeContact is progressing through steps
completedAll steps have been sent
exitedContact left (deleted or unsubscribed)

List enrollments

List enrollments
curl https://api.grosend.com/api/v1/automations/{id}/enrollments \
  -H "Authorization: Bearer sv_live_..."
Response
{
  "data": [
    {
      "id": "enrollment-uuid",
      "contact": {
        "id": "contact-uuid",
        "email": "user@example.com",
        "name": "Jane Doe"
      },
      "currentStep": 2,
      "status": "active",
      "enrolledAt": "2026-01-15T10:30:00Z",
      "completedAt": null,
      "exitReason": null
    }
  ],
  "total": 42
}

Filter by status:

Filtering
# Active enrollments only
curl "https://api.grosend.com/api/v1/automations/{id}/enrollments?status=active" \
  -H "Authorization: Bearer sv_live_..."

# Paginated
curl "https://api.grosend.com/api/v1/automations/{id}/enrollments?limit=25&offset=50" \
  -H "Authorization: Bearer sv_live_..."

Template variables

Use {{variable_name}} syntax in your email subjects and bodies. Variables are rendered when the email is sent.

Built-in variables

{{name}}Contact name (falls back to "there")
{{email}}Contact email address
{{company}}Your company name (from env)
{{list_name}}Name of the list that triggered enrollment

Contact properties

All string-valued contact properties are automatically available as template variables. For example, if a contact has {"plan": "pro", "company": "Acme"}, you can use {{plan}} and {{company}} in your emails.

Example with variables
{
  "subject": "{{name}}, your {{plan}} plan is ready",
  "bodyHtml": "<h1>Hi {{name}}</h1><p>Your {{plan}} plan with {{company}} is now active.</p>"
}

Pre-built scenarios

Grosend ships with 43 pre-built automation scenarios across 7 industries. Each includes pre-written email copy, optimal delay timing, and appropriate trigger configuration.

List scenarios
curl https://api.grosend.com/api/v1/automations/scenarios
Response (summary)
{
  "data": [
    {
      "id": "saas-welcome-series",
      "name": "Welcome Series",
      "description": "4-step onboarding for new SaaS users",
      "industry": "SaaS",
      "triggerType": "list_join",
      "stepCount": 4
    },
    {
      "id": "ecommerce-abandoned-cart",
      "name": "Abandoned Cart",
      "description": "Recover lost sales with timed reminders",
      "industry": "E-commerce",
      "triggerType": "property_equals",
      "stepCount": 3
    }
  ]
}

Scenarios by industry

Fintech12 scenarios

KYC Onboarding · Payment Reminders · Transaction Alerts · Card Activation · Re-engagement

SaaS7 scenarios

Welcome Series · Trial-to-Paid · Feature Adoption · Churn Prevention · Inactivity Re-engagement

E-commerce7 scenarios

Abandoned Cart · Browse Abandonment · Post-Purchase · Replenishment · Win-Back

Healthcare5 scenarios

Appointment Scheduling · Patient Onboarding · Post-Visit Follow-up · Wellness Series

EdTech4 scenarios

Course Enrollment · Course Completion · Webinar Sequence · Student Re-engagement

Real Estate4 scenarios

Lead Follow-up · Listing Alert · Post-Tour · Transaction Update

B2B/Agency4 scenarios

Proposal Follow-up · Client Onboarding · Quarterly Review · Referral Request

Example: Abandoned cart recovery

A complete walkthrough of building an abandoned cart automation from scratch.

Step 1: Set up the trigger

When your app detects an abandoned cart, set a property on the contact:

Set contact property
curl -X PATCH https://api.grosend.com/api/v1/contacts/{contact-id} \
  -H "Authorization: Bearer sv_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "properties": {
      "abandoned_cart": "true",
      "cart_url": "https://yourapp.com/cart/abc123",
      "cart_total": "₦89,000"
    }
  }'

Step 2: Create the automation

Create abandoned cart automation
curl -X POST https://api.grosend.com/api/v1/automations \
  -H "Authorization: Bearer sv_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Abandoned Cart Recovery",
    "triggerType": "property_equals",
    "triggerConfig": {
      "property": "abandoned_cart",
      "value": "true"
    },
    "steps": [
      {
        "delayMinutes": 60,
        "subject": "You left something in your cart",
        "bodyHtml": "<h1>Complete your order</h1><p>You have items waiting. Your cart total: {{cart_total}}</p><p><a href=\"{{cart_url}}\">Complete checkout →</a></p>"
      },
      {
        "delayMinutes": 1440,
        "subject": "Still thinking about it?",
        "bodyHtml": "<h1>Your cart is waiting</h1><p>Complete your order before your items sell out.</p><p><a href=\"{{cart_url}}\">Return to cart →</a></p>"
      },
      {
        "delayMinutes": 4320,
        "subject": "Last chance — 10% off your cart",
        "bodyHtml": "<h1>Here is 10% off</h1><p>Use code SAVE10 at checkout. Your cart: {{cart_total}}</p><p><a href=\"{{cart_url}}\">Claim discount →</a></p>"
      }
    ]
  }'

Step 3: Activate

Activate
curl -X POST https://api.grosend.com/api/v1/automations/{id}/activate \
  -H "Authorization: Bearer sv_live_..."

Now whenever a contact has abandoned_cart = "true", they'll receive a 3-email sequence: reminder at 1 hour, nudge at 1 day, and discount at 3 days.

Example: Welcome series with templates

Use email templates with your automations for consistent branding across steps.

Using templates in automations
# First, create a template
curl -X POST https://api.grosend.com/api/v1/templates \
  -H "Authorization: Bearer sv_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Welcome Email",
    "subject": "Welcome to {{company}}!",
    "htmlBody": "<h1>Welcome, {{name}}!</h1><p>Thanks for joining. Here is how to get started.</p>"
  }'

# Then reference it in your automation step
curl -X POST https://api.grosend.com/api/v1/automations/{id}/steps \
  -H "Authorization: Bearer sv_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "delayMinutes": 0,
    "templateId": "template-uuid"
  }'
When a step has a templateId, the template's subject and body are used instead of the step's inline subject/bodyHtml. Template variables are still rendered.

Delay reference

Delays are specified in minutes. Common durations:

0 minImmediately
60 min1 hour
120 min2 hours
1440 min1 day
2880 min2 days
4320 min3 days
7200 min5 days
10080 min1 week
14400 min10 days
20160 min2 weeks
30240 min3 weeks
43200 min1 month

Webhook events

Emails sent by automations fire the same webhook events as regular emails. Each automation email includes an automation_id tag for filtering.

Webhook payload with automation tag
{
  "id": "evt_1750000000000",
  "type": "email.delivered",
  "created_at": "2026-01-15T10:35:00Z",
  "data": {
    "email_id": "email-uuid",
    "from": "hello@yourapp.com",
    "to": "user@example.com",
    "subject": "Welcome to Acme!",
    "tags": [{ "name": "automation_id", "value": "automation-uuid" }]
  }
}

API reference

GET/api/v1/automationsList all automations
POST/api/v1/automationsCreate automation
GET/api/v1/automations/:idGet automation details
PUT/api/v1/automations/:idUpdate automation
DELETE/api/v1/automations/:idDelete automation
POST/api/v1/automations/:id/activateActivate automation
POST/api/v1/automations/:id/pausePause automation
GET/api/v1/automations/:id/stepsList steps
POST/api/v1/automations/:id/stepsAdd step
PUT/api/v1/automations/:id/stepsUpdate step
DELETE/api/v1/automations/:id/stepsDelete step
GET/api/v1/automations/:id/enrollmentsList enrollments
GET/api/v1/automations/scenariosList pre-built scenarios

Get automation with enrollment stats

Get automation
curl https://api.grosend.com/api/v1/automations/{id} \
  -H "Authorization: Bearer sv_live_..."
Response
{
  "id": "...",
  "name": "Welcome Series",
  "status": "active",
  "triggerType": "list_join",
  "triggerConfig": { "listName": "new-users" },
  "totalSent": 142,
  "steps": [
    { "id": "s1", "position": 0, "delayMinutes": 0, "subject": "Welcome!", "totalSent": 142 },
    { "id": "s2", "position": 1, "delayMinutes": 1440, "subject": "Getting started", "totalSent": 98 },
    { "id": "s3", "position": 2, "delayMinutes": 4320, "subject": "Tips", "totalSent": 67 },
    { "id": "s4", "position": 3, "delayMinutes": 10080, "subject": "Need help?", "totalSent": 31 }
  ],
  "enrollmentStats": {
    "total": 142,
    "active": 31,
    "completed": 111,
    "exited": 0
  }
}
The enrollmentStats.totalSent decreasing across steps shows drop-off. Use this to identify where contacts disengage.

Error handling

400Missing required fields (name, triggerType, triggerConfig)
400Already active / Not active (activate/pause)
400Add at least one step before activating
401Invalid or missing API key
404Automation not found