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

# Wait for Event

> Hold your Automations until a specific event is received.

A wait-until step holds the Automation until a specific event is received.

Unlike a delay, which resumes after a fixed time, this step resumes when something happens in your application.

Common use cases:

* **Payment**: Wait for a payment to succeed before sending a receipt.
* **Adoption**: Wait for a user to complete an action to unlock a feature.
* **Verification**: Wait for the user to verify their email before continuing.

## How it works

> [tab] Using the dashboard
>
> Add a **Wait for event** step and configure the event to wait for.
>
> ![Automation for Event](https://mintcdn.com/resend/xKsnaRV1IW7mxJit/images/automations-wait-until.png?fit=max\&auto=format\&n=xKsnaRV1IW7mxJit\&q=85\&s=76e77ac2bccd32127ebdb3d01baab410)

> [tab] Using the API
>
> Add a `wait_for_event` step to your Automation's `steps` array.
>
> ```ts Node.js {13-20} theme={"theme":{"light":"github-light","dark":"vesper"}}
> import { Resend } from 'resend';
>
> const resend = new Resend('re_xxxxxxxxx');
>
> const { data, error } = await resend.automations.create({
>   name: 'Verification Reminder',
>   steps: [
>     {
>       key: 'start',
>       type: 'trigger',
>       config: { eventName: 'user.created' },
>     },
>     {
>       key: 'verification',
>       type: 'wait_for_event',
>       config: {
>         eventName: 'email.verified',
>         timeout: '1 day',
>       },
>     },
>   ],
>   connections: [{ from: 'start', to: 'verification', type: 'default' }],
> });
> ```
>
> ```php PHP {11-18} theme={"theme":{"light":"github-light","dark":"vesper"}}
> $resend = Resend::client('re_xxxxxxxxx');
>
> $resend->automations->create([
>   'name' => 'Verification Reminder',
>   'steps' => [
>     [
>       'key' => 'start',
>       'type' => 'trigger',
>       'config' => ['event_name' => 'user.created'],
>     ],
>     [
>       'key' => 'verification',
>       'type' => 'wait_for_event',
>       'config' => [
>         'event_name' => 'email.verified',
>         'timeout' => '24 hours',
>       ],
>     ],
>   ],
>   'connections' => [['from' => 'start', 'to' => 'verification', 'type' => 'default']],
> ]);
> ```
>
> ```python Python {13-20} theme={"theme":{"light":"github-light","dark":"vesper"}}
> import resend
>
> resend.api_key = "re_xxxxxxxxx"
>
> params: resend.Automations.CreateParams = {
>   "name": "Verification Reminder",
>   "steps": [
>     {
>       "key": "start",
>       "type": "trigger",
>       "config": {"event_name": "user.created"},
>     },
>     {
>       "key": "verification",
>       "type": "wait_for_event",
>       "config": {
>         "event_name": "email.verified",
>         "timeout": "24 hours",
>       },
>     },
>   ],
>   "connections": [{"from": "start", "to": "verification", "type": "default"}],
> }
>
> resend.Automations.create(params)
> ```
>
> ```ruby Ruby {13-20} theme={"theme":{"light":"github-light","dark":"vesper"}}
> require "resend"
>
> Resend.api_key = "re_xxxxxxxxx"
>
> params = {
>   name: "Verification Reminder",
>   steps: [
>     {
>       key: "start",
>       type: "trigger",
>       config: { event_name: "user.created" },
>     },
>     {
>       key: "verification",
>       type: "wait_for_event",
>       config: {
>         event_name: "email.verified",
>         timeout: "24 hours",
>       },
>     },
>   ],
>   connections: [{ from: "start", to: "verification", type: "default" }],
> }
>
> Resend::Automations.create(params)
> ```
>
> ```go Go {18-25} theme={"theme":{"light":"github-light","dark":"vesper"}}
> package main
>
> import "github.com/resend/resend-go/v4"
>
> func main() {
> 	client := resend.NewClient("re_xxxxxxxxx")
>
> 	params := &resend.CreateAutomationRequest{
> 		Name: "Verification Reminder",
> 		Steps: []resend.AutomationStep{
> 			{
> 				Key:  "start",
> 				Type: resend.AutomationStepTypeTrigger,
> 				Config: map[string]any{
> 					"event_name": "user.created",
> 				},
> 			},
> 			{
> 				Key:  "verification",
> 				Type: resend.AutomationStepTypeWaitForEvent,
> 				Config: map[string]any{
> 					"event_name": "email.verified",
> 					"timeout":    "24 hours",
> 				},
> 			},
> 		},
> 		Connections: []resend.AutomationConnection{
> 			{From: "start", To: "verification", Type: resend.AutomationConnectionTypeDefault},
> 		},
> 	}
>
> 	client.Automations.Create(params)
> }
> ```
>
> ```rust Rust {22-29} theme={"theme":{"light":"github-light","dark":"vesper"}}
> use resend_rs::{
>   types::{
>     AutomationStatus, Connection, ConnectionType, CreateAutomationOptions, Step, TriggerStepConfig,
>     WaitForEventStepConfig,
>   },
>   Resend, Result,
> };
>
> #[tokio::main]
> async fn main() -> Result<()> {
>   let resend = Resend::new("re_xxxxxxxxx");
>
>   let opts = CreateAutomationOptions {
>     name: "Verification Reminder".to_owned(),
>     steps: vec![
>       Step::Trigger {
>         key: "start".to_owned(),
>         config: TriggerStepConfig {
>           event_name: "user.created".to_owned(),
>         },
>       },
>       Step::WaitForEvent {
>         key: "verification".to_owned(),
>         config: WaitForEventStepConfig {
>           event_name: "email.verified".to_owned(),
>           timeout: Some("24 hours".to_owned()),
>           filter_rule: None,
>         },
>       },
>     ],
>     connections: vec![Connection::new("start", "verification").with_type(ConnectionType::Default)],
>     status: AutomationStatus::Disabled,
>   };
>   let _automation = resend.automations.create(opts).await?;
>
>   Ok(())
> }
> ```
>
> ```java Java {20-25} theme={"theme":{"light":"github-light","dark":"vesper"}}
> import com.resend.*;
> import com.resend.core.exception.ResendException;
> import com.resend.services.automations.model.AutomationConnection;
> import com.resend.services.automations.model.AutomationStep;
> import com.resend.services.automations.model.ConnectionType;
> import com.resend.services.automations.model.CreateAutomationOptions;
> import com.resend.services.automations.model.CreateAutomationResponseSuccess;
>
> public class Main {
>     public static void main(String[] args) throws ResendException {
>         Resend resend = new Resend("re_xxxxxxxxx");
>
>         CreateAutomationOptions options = CreateAutomationOptions.builder()
>                 .name("Verification Reminder")
>                 .steps(
>                     AutomationStep.trigger("start")
>                         .eventName("user.created")
>                         .build(),
>                     AutomationStep.waitForEvent("verification")
>                         .eventName("email.verified")
>                         .timeout("1 day")
>                         .build()
>                 )
>                 .connections(
>                     AutomationConnection.builder()
>                         .from("start")
>                         .to("verification")
>                         .type(ConnectionType.DEFAULT)
>                         .build()
>                 )
>                 .build();
>
>         CreateAutomationResponseSuccess data = resend.automations().create(options);
>     }
> }
> ```
>
> ```csharp .NET {7-11,19} theme={"theme":{"light":"github-light","dark":"vesper"}}
> using Resend;
> using System.Text.Json;
>
> IResend resend = ResendClient.Create( "re_xxxxxxxxx" );
>
> var startConfig = JsonSerializer.SerializeToElement( new { event_name = "user.created" } );
> var waitConfig = JsonSerializer.SerializeToElement( new
> {
>     event_name = "email.verified",
>     timeout = "1 day",
> } );
>
> var resp = await resend.AutomationCreateAsync( new AutomationCreateData()
> {
>     Name = "Verification Reminder",
>     Steps = new List<AutomationStepData>
>     {
>         new AutomationStepData { Ref = "start", Type = "trigger", Config = startConfig },
>         new AutomationStepData { Ref = "verification", Type = "wait_for_event", Config = waitConfig },
>     },
>     Connections = new List<AutomationEdge>
>     {
>         new AutomationEdge { From = "start", To = "verification", EdgeType = "default" },
>     },
> } );
> ```
>
> ```bash cURL {10-16} theme={"theme":{"light":"github-light","dark":"vesper"}}
> curl -X POST 'https://api.resend.com/automations' \
>      -H 'Authorization: Bearer re_xxxxxxxxx' \
>      -H 'Content-Type: application/json' \
>      -d '{
>   "name": "Verification Reminder",
>   "steps": [{
>     "key": "start",
>     "type": "trigger",
>     "config": { "event_name": "user.created" }
>   }, {
>     "key": "verification",
>     "type": "wait_for_event",
>     "config": {
>       "event_name": "email.verified"
>     }
>   }],
>   "connections": [
>     { "from": "start", "to": "verification", "type": "default" }
>   ]
> }'
> ```
>
> ```bash CLI theme={"theme":{"light":"github-light","dark":"vesper"}}
> resend automations create --name "Verification Reminder" --file ./automation.json
> ```

## Timeouts

When you set a `timeout`, the step will stop waiting after that duration. This prevents Automations from waiting indefinitely.

When a wait-until step times out, it produces two possible connection types:

| Connection type | When it's used |
| - | - |
| `event_received` | The event arrived before the timeout |
| `timeout` | The timeout elapsed without receiving the event |

You can create different paths depending on whether the user took action within an given time period.

```json {6} theme={"theme":{"light":"github-light","dark":"vesper"}}
{
  "key": "payment",
  "type": "wait_for_event",
  "config": {
    "event_name": "payment.completed",
    "timeout": "3 days"
  }
}
```

> [!NOTE]
>
> The maximum timeout is 30 days.

## Filter rules

Use `filter_rule` to match events that meet only specific criteria. This is useful when the same event name might be sent with different payloads.

`wait_events.*` is not available.

* `field` reads the incoming event (`event.*`) or the Automation's contact (`contact.*`).
* `value` is a fixed value, or it reads the event that triggered the Automation (`event.*`) or the contact (`contact.*`).

See [Configuration](#configuration) for every operator a filter rule supports.

For example, to wait specifically for a successful payment:

```json {6-11} theme={"theme":{"light":"github-light","dark":"vesper"}}
{
  "key": "payment",
  "type": "wait_for_event",
  "config": {
    "event_name": "payment.completed",
    "filter_rule": {
      "type": "rule",
      "field": "event.status",
      "operator": "eq",
      "value": "succeeded"
    }
  }
}
```

### Compare against the triggering event

`field` and `value` can use the same path and still read different payloads. In a `value`, `event.*` is the event that triggered the Automation, not the incoming event.

For example, an Automation triggered by `order.placed` can wait for `order.paid` for the same order:

```json {8-10} theme={"theme":{"light":"github-light","dark":"vesper"}}
{
  "key": "wait_for_payment",
  "type": "wait_for_event",
  "config": {
    "event_name": "order.paid",
    "filter_rule": {
      "type": "rule",
      "field": "event.order_id",
      "operator": "eq",
      "value": { "var": "event.order_id" }
    }
  }
}
```

Here, `field` reads `order_id` from the incoming `order.paid` event, and `value` reads `order_id` from the `order.placed` event that started the Automation. `order.paid` events for other orders don't resume it.

A `value` can also reference the contact, such as `{ "var": "contact.email" }`. Neither `field` nor `value` can reference `wait_events.*`.

## Use the received event in later steps

When the event arrives, steps after the wait can read its payload with `wait_events`. The path is `wait_events.`, then the event name, then the payload field. In `wait_events.order.shipped.tracking_url`, the event name is `order.shipped` and the field is `tracking_url`.

For example, wait for `order.shipped`, then send its tracking link:

```json {6,15-16,23} theme={"theme":{"light":"github-light","dark":"vesper"}}
{
  "steps": [
    {
      "key": "wait_for_shipping",
      "type": "wait_for_event",
      "config": { "event_name": "order.shipped", "timeout": "7 days" }
    },
    {
      "key": "shipping_email",
      "type": "send_email",
      "config": {
        "template": {
          "id": "044db673-fff6-420f-a566-f6aba05d60e7",
          "variables": {
            "carrier": { "var": "wait_events.order.shipped.carrier" },
            "trackingUrl": { "var": "wait_events.order.shipped.tracking_url" }
          }
        }
      }
    }
  ],
  "connections": [
    {
      "from": "wait_for_shipping",
      "to": "shipping_email",
      "type": "event_received"
    }
  ]
}
```

Connect the step to the `event_received` path. On the `timeout` path, the event never arrived, so there's no payload to read.

You can use `wait_events` in [send email](https://resend.com/docs/dashboard/automations/send-email.md#template-variables) variables, [contact update](https://resend.com/docs/dashboard/automations/contact-update.md#dynamic-variables) fields, and [condition](https://resend.com/docs/dashboard/automations/condition.md#compare-against-other-data) rules.

## Configuration

**config.event\_name** `string` *required*

The name of the event to wait for.

**config.timeout** `string`

The maximum time to wait before timing out (e.g. `"3 days"`, `"1 hour"`).
Maximum: 30 days.

**config.filter\_rule** `object`

An optional rule that filters which incoming events resume the step.
`wait_events.` is not available.

**properties**

**type** `string` *required*

The type of filter rule. Possible values:

* `rule`
* `and`
* `or`

**field** `string`

Required when `type` is `rule`. The payload field to evaluate. Use
`event.` for the incoming event or `contact.` for the Automation's contact
(for example, `event.status` or `contact.email`).

**operator** `string`

Required when `type` is `rule`. The comparison operator. Possible values:

* `eq`: equals
* `neq`: not equals
* `gt`: greater than
* `gte`: greater than or equal to
* `lt`: less than
* `lte`: less than or equal to
* `contains`: contains a given value
* `starts_with`: starts with a given value
* `ends_with`: ends with a given value
* `exists`: field exists
* `is_empty`: field is empty

**value** `string | number | boolean | null | object`

Used when `type` is `rule`. The value to compare against. A fixed value,
or a variable reference such as `{ "var": "event.order_id" }`. `event.`
is the event that triggered the Automation. `contact.` is the
Automation's contact. Not required for `exists` and `is_empty`.

**rules** `object[]`

Required when `type` is `and` or `or`. An array of nested filter rules.
Must contain at least one item.

This waits for `order.paid` only when it is the order that started the Automation. `field` reads `order_id` on the incoming event. `value` reads `order_id` on the triggering event.

```json Example {9-11} theme={"theme":{"light":"github-light","dark":"vesper"}}
{
  "key": "wait_for_payment",
  "type": "wait_for_event",
  "config": {
    "event_name": "order.paid",
    "timeout": "3 days",
    "filter_rule": {
      "type": "rule",
      "field": "event.order_id",
      "operator": "eq",
      "value": { "var": "event.order_id" }
    }
  }
}
```
