---
title: "Introducing Automations"
slug: introducing-automations
description: "Set up lifecycle messages and drip campaigns with triggers, personalization, and real-time observability."
created_at: "2026-04-13"
updated_at: "2026-04-13"
image: https://cdn.resend.com/posts/automations-cover.jpg
humans: ["carolina-josephik", "danilo-campos", "isabella-aquino", "lucas-motta", "vitor-capretz", "zeno-rocha"]
category: "product"
featured: true
---

Resend makes it easy to **send and receive emails**.

Today, we're making it easy to **orchestrate them**.

**Automations** let you build lifecycle sequences triggered by events in your app:

- Onboard new users with timed sequences
- Re-engage users who've gone quiet
- Send trial expiration reminders

<video
  poster="https://cdn.resend.com/posts/automations-video-poster.jpg"
  controls
  preload="metadata"
  className="extraWidth"
>
  <source src="https://cdn.resend.com/posts/introducing-automations.webm" type="video/webm" />
  <source src="https://cdn.resend.com/posts/introducing-automations.mp4" type="video/mp4" />
  <track kind="captions" src="https://cdn.resend.com/posts/introducing-automations.srt" srcLang="en" label="English" />
</video>


Here's how to create and manage Automations.

## 1. Define a trigger

Every Automation starts with an event.
- User signed up
- Order placed
- Trial expired

<video
  autoPlay
  loop
  muted
  playsInline
  className="extraWidth"
>
  <source src="https://cdn.resend.com/posts/introducing-automations-1.webm" type="video/webm" />
  <source src="https://cdn.resend.com/posts/introducing-automations-1.mp4" type="video/mp4" />
</video>

You create these events to fit your own needs. Each event can include an optional schema, so you always know what data is available.

## 2. Personalize each step

Once an event fires, you control what happens next:

- **Time delays**: hold the Automation for a set amount of time
- **Wait for events**: move to the next step after a certain condition is met
- **Conditions**: branch the flow based on contact or event data

Design sequences visually with the drag-and-drop editor, or describe what you want in plain language and let AI build it for you.

<video
  autoPlay
  loop
  muted
  playsInline
  className="extraWidth"
>
  <source src="https://cdn.resend.com/posts/introducing-automations-2.webm" type="video/webm" />
  <source src="https://cdn.resend.com/posts/introducing-automations-2.mp4" type="video/mp4" />
</video>

Conditions support `equals`, `contains`, `greater than`, and `and`/`or` logic. Each email step uses your existing [Templates](/blog/introducing-templates), so copy stays consistent and your team can edit it without touching code.

<video
  autoPlay
  loop
  muted
  playsInline
  className="extraWidth"
>
  <source src="https://cdn.resend.com/posts/introducing-automations-3.webm" type="video/webm" />
  <source src="https://cdn.resend.com/posts/introducing-automations-3.mp4" type="video/mp4" />
</video>

This personalization can be used to:

- Send a welcome email immediately, then a tips email 3 days later
- Branch based on plan and send different content to free vs. paid users
- Wait for a user to complete onboarding before sending the next message

## 3. Go live with confidence

Before going live, fire a test event and watch it flow through each step.

<video
  autoPlay
  loop
  muted
  playsInline
  className="extraWidth"
>
  <source src="https://cdn.resend.com/posts/introducing-automations-4.webm" type="video/webm" />
  <source src="https://cdn.resend.com/posts/introducing-automations-4.mp4" type="video/mp4" />
</video>

When you're ready, publish your automation and start firing events.

<video
  autoPlay
  loop
  muted
  playsInline
  className="extraWidth"
>
  <source src="https://cdn.resend.com/posts/introducing-automations-5.webm" type="video/webm" />
  <source src="https://cdn.resend.com/posts/introducing-automations-5.mp4" type="video/mp4" />
</video>

## 4. Send events from your app

When something happens in your app, fire the event from your application to trigger the Automation.

<CodeTabs codeHeight={280}>

```nodejs
import { Resend } from 'resend';

const resend = new Resend('re_xxxxxxxxx');

const { data, error } = await resend.events.send({
  event: 'user.created',
  email: 'steve.wozniak@gmail.com',
  payload: {
    plan: 'pro',
  },
});
```

```php
$resend = Resend::client('re_xxxxxxxxx');

$resend->events->send([
  'event' => 'user.created',
  'email' => 'steve.wozniak@gmail.com',
  'payload' => ['plan' => 'pro'],
]);
```

```python
import resend

resend.api_key = "re_xxxxxxxxx"

params: resend.Events.SendParams = {
  "event": "user.created",
  "email": "steve.wozniak@gmail.com",
  "payload": {
    "plan": "pro",
  },
}

resend.Events.send(params)
```

```ruby
require "resend"

Resend.api_key = "re_xxxxxxxxx"

params = {
  event: "user.created",
  email: "steve.wozniak@gmail.com",
  payload: {
    plan: "pro",
  },
}

Resend::Events.send(params)
```

```go
package main

import "github.com/resend/resend-go/v3"

func main() {
  client := resend.NewClient("re_xxxxxxxxx")

  params := &resend.SendEventRequest{
    Event: "user.created",
    Email: "steve.wozniak@gmail.com",
    Payload: map[string]any{
      "plan": "pro",
    },
  }

  client.Events.Send(params)
}
```

```rust
use resend_rs::{
  json,
  types::{ContactIdOrEmail, SendEventOptions},
  Resend, Result,
};

#[tokio::main]
async fn main() -> Result<()> {
  let resend = Resend::new("re_xxxxxxxxx");

  let opts = SendEventOptions {
    event: "user.created".to_owned(),
    contact_id_or_email: ContactIdOrEmail::ContactId(
      "7f2e4a3b-dfbc-4e9a-8b2c-5f3a1d6e7c8b".to_owned(),
    ),
    payload: json!({
      "plan": "pro"
    }),
  };

  let opts = SendEventOptions {
    event: "user.created".to_owned(),
    contact_id_or_email: ContactIdOrEmail::Email("steve.wozniak@gmail.com".to_owned()),
    payload: json!({
      "plan": "pro"
    }),
  };

  let _event = resend.events.send(opts).await?;

  Ok(())
}
```

```java
import com.resend.*;

public class Main {
    public static void main(String[] args) {
        Resend resend = new Resend("re_xxxxxxxxx");

        SendEventOptions params = SendEventOptions.builder()
                .event("user.created")
                .email("steve.wozniak@gmail.com")
                .addPayload("plan", "pro")
                .build();

        SendEventResponseSuccess data = resend.events().send(params);
    }
}
```

```dotnet
using Resend;
using System.Text.Json;

IResend resend = ResendClient.Create( "re_xxxxxxxxx" );

var payload = JsonSerializer.SerializeToElement( new { plan = "pro" } );

var resp = await resend.EventSendAsync( new EventSendData()
{
    Event = "user.created",
    Email = "steve.wozniak@gmail.com",
    Payload = payload,
} );
Console.WriteLine( "Event={0}", resp.Content.Event );
```

```curl
curl -X POST 'https://api.resend.com/events/send' \
     -H 'Authorization: Bearer re_xxxxxxxxx' \
     -H 'Content-Type: application/json' \
     -d '{
  "event": "user.created",
  "email": "steve.wozniak@gmail.com",
  "payload": {
    "plan": "pro"
  }
}'
```
</CodeTabs>

As soon as the event is fired, your published Automation runs.

## 5. Full visibility into each run

Once running, the observability panel shows every run in real time: what's in progress, what completed, what failed. Debugging a stuck sequence takes seconds, not hours.

<video
  autoPlay
  loop
  muted
  playsInline
  className="extraWidth"
>
  <source src="https://cdn.resend.com/posts/introducing-automations-6.webm" type="video/webm" />
  <source src="https://cdn.resend.com/posts/introducing-automations-6.mp4" type="video/mp4" />
</video>

You can also [inspect runs programmatically through the API](/docs/api-reference/automations/list-automation-runs).

## Developer-first design

We designed Automations to be developer-first. The entire Automation experience is available via the API or through the Dashboard, to let you build in the way that best fits your team.

You can [create Automations](/docs/api-reference/automations/create-automation), [define Events](/docs/api-reference/events/create-event), and [inspect Runs](/docs/api-reference/automations/list-automation-runs) programmatically using the API, our SDKs, the [MCP Server](/docs/mcp-server), or the [CLI](/docs/cli).

<CodeTabs codeHeight={520}>

```nodejs
import { Resend } from 'resend';

const resend = new Resend('re_xxxxxxxxx');

const { data, error } = await resend.automations.create({
  name: 'Welcome series',
  status: 'disabled',
  steps: [
    {
      key: 'start',
      type: 'trigger',
      config: { eventName: 'user.created' },
    },
    {
      key: 'welcome',
      type: 'send_email',
      config: {
        template: { id: '34a080c9-b17d-4187-ad80-5af20266e535' },
      },
    },
  ],
  connections: [{ from: 'start', to: 'welcome' }],
});
```

```php
$resend = Resend::client('re_xxxxxxxxx');

$resend->automations->create([
  'name' => 'Welcome series',
  'status' => 'disabled',
  'steps' => [
    [
      'key' => 'start',
      'type' => 'trigger',
      'config' => ['event_name' => 'user.created'],
    ],
    [
      'key' => 'welcome',
      'type' => 'send_email',
      'config' => [
        'template' => ['id' => '34a080c9-b17d-4187-ad80-5af20266e535'],
      ],
    ],
  ],
  'connections' => [['from' => 'start', 'to' => 'welcome']],
]);
```

```python
import resend

resend.api_key = "re_xxxxxxxxx"

params: resend.Automations.CreateParams = {
  "name": "Welcome series",
  "status": "disabled",
  "steps": [
    {
      "key": "start",
      "type": "trigger",
      "config": {"event_name": "user.created"},
    },
    {
      "key": "welcome",
      "type": "send_email",
      "config": {
        "template": {"id": "34a080c9-b17d-4187-ad80-5af20266e535"},
      },
    },
  ],
  "connections": [{"from": "start", "to": "welcome"}],
}

resend.Automations.create(params)
```

```ruby
require "resend"

Resend.api_key = "re_xxxxxxxxx"

params = {
  name: "Welcome series",
  status: "disabled",
  steps: [
    {
      key: "start",
      type: "trigger",
      config: { event_name: "user.created" },
    },
    {
      key: "welcome",
      type: "send_email",
      config: {
        template: { id: "34a080c9-b17d-4187-ad80-5af20266e535" },
      },
    },
  ],
  connections: [{ from: "start", to: "welcome" }],
}

Resend::Automations.create(params)
```

```go
package main

import "github.com/resend/resend-go/v3"

func main() {
  client := resend.NewClient("re_xxxxxxxxx")

  params := &resend.CreateAutomationRequest{
    Name:   "Welcome series",
    Status: resend.AutomationStatusDisabled,
    Steps: []resend.AutomationStep{
      {
        Key:  "start",
        Type: resend.AutomationStepTypeTrigger,
        Config: map[string]any{
          "event_name": "user.created",
        },
      },
      {
        Key:  "welcome",
        Type: resend.AutomationStepTypeSendEmail,
        Config: map[string]any{
          "template": map[string]any{
            "id": "34a080c9-b17d-4187-ad80-5af20266e535",
          },
        },
      },
    },
    Connections: []resend.AutomationConnection{
      {From: "start", To: "welcome"},
    },
  }

  client.Automations.Create(params)
}
```

```rust
use resend_rs::{
  types::{
    AutomationStatus, AutomationTemplate, Connection, CreateAutomationOptions, SendEmailStepConfig,
    Step, TriggerStepConfig,
  },
  Resend, Result,
};

#[tokio::main]
async fn main() -> Result<()> {
  let resend = Resend::new("re_xxxxxxxxx");

  let opts = CreateAutomationOptions {
    name: "Welcome series".to_owned(),
    status: AutomationStatus::Disabled,
    steps: vec![
      Step::Trigger {
        key: "start".to_owned(),
        config: TriggerStepConfig {
          event_name: "user.created".to_owned(),
        },
      },
      Step::SendEmail {
        key: "welcome".to_owned(),
        config: SendEmailStepConfig::new(AutomationTemplate::new(
          "34a080c9-b17d-4187-ad80-5af20266e535",
        )),
      },
    ],
    connections: vec![Connection::new("start", "welcome")],
  };
  let _automation = resend.automations.create(opts).await?;

  Ok(())
}
```

```java
import com.resend.*;

public class Main {
    public static void main(String[] args) {
        Resend resend = new Resend("re_xxxxxxxxx");

        CreateAutomationOptions options = CreateAutomationOptions.builder()
                .name("Welcome series")
                .status(AutomationStatus.DISABLED)
                .steps(
                    AutomationStep.trigger("start")
                        .eventName("user.created")
                        .build(),
                    AutomationStep.sendEmail("welcome")
                        .template("34a080c9-b17d-4187-ad80-5af20266e535")
                        .build()
                )
                .connections(
                    AutomationConnection.builder()
                        .from("start")
                        .to("welcome")
                        .build()
                )
                .build();

        CreateAutomationResponseSuccess response = resend.automations().create(options);
    }
}
```

```dotnet
using Resend;
using System.Text.Json;

IResend resend = ResendClient.Create( "re_xxxxxxxxx" );

var startConfig = JsonSerializer.SerializeToElement( new { event_name = "user.created" } );
var welcomeConfig = JsonSerializer.SerializeToElement( new { template = new { id = "34a080c9-b17d-4187-ad80-5af20266e535" } } );

var resp = await resend.AutomationCreateAsync( new AutomationCreateData()
{
    Name = "Welcome series",
    Status = "disabled",
    Steps = new List<AutomationStepData>
    {
        new AutomationStepData { Ref = "start", Type = "trigger", Config = startConfig },
        new AutomationStepData { Ref = "welcome", Type = "send_email", Config = welcomeConfig },
    },
    Connections = new List<AutomationEdge>
    {
        new AutomationEdge { From = "start", To = "welcome" },
    },
} );
Console.WriteLine( "AutomationId={0}", resp.Content );
```

```curl
curl -X POST 'https://api.resend.com/automations' \
     -H 'Authorization: Bearer re_xxxxxxxxx' \
     -H 'Content-Type: application/json' \
     -d '{
  "name": "Welcome series",
  "steps": [
    {
      "key": "start",
      "type": "trigger",
      "config": { "event_name": "user.created" }
    },
    {
      "key": "welcome",
      "type": "send_email",
      "config": {
        "template": { "id": "34a080c9-b17d-4187-ad80-5af20266e535" }
      }
    }
  ],
  "connections": [
    { "from": "start", "to": "welcome" }
  ]
}'
```

</CodeTabs>

## Get started today

Automations unlock entirely new ways to engage your audience by building lifecycle sequences triggered by events in your own app.

You can get started with **10,000 Automation Runs for free**, and scale as you need. See [Pricing](/pricing#automations) for all the details.

Visit the [Automations page](/docs/dashboard/automations/introduction) or read the [API docs](/docs/api-reference/automations/create-automation) to build your first Automation.
