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

# Schedule Email

> Send emails at a specific time without additional complexity.

While some emails need to be delivered as soon as possible, like password resets or magic links, others can be scheduled for a specific time.

Here are some examples of when you might want to schedule an email:

* Send welcome email **5 minutes after** signup
* Trigger a reminder email **24 hours before** an event
* Schedule a weekly digest email for the **next day at 9am PST**

Before, you had to use external services to handle the scheduling logic, but now you can use the new Emailr API to schedule emails.

<Info>Emails can be scheduled up to 30 days in advance.</Info>

There are two ways to schedule an email:

1. [Using natural language](#1-schedule-using-natural-language)
2. [Using date format](#2-schedule-using-date-format)

## 1. Schedule using natural language

You can use the various Emailr SDKs to schedule emails.

The date can be defined using natural language, such as `"in 1 hour"`, `"tomorrow at 9am"`, or `"Friday at 3pm ET"`.

<CodeGroup>
  ```ts Node.js {10} theme={null} theme={null}
  import { Emailr } from 'emailr';

  const emailr = new Emailr('em_xxxxxxxxx');

  await emailr.emails.send({
    from: 'Acme <onboarding@emailr.dev>',
    to: ['delivered@emailr.dev'],
    subject: 'hello world',
    html: '<p>it works!</p>',
    scheduledAt: 'in 1 min',
  });
  ```

  ```php PHP {8} theme={null} theme={null}
  $emailr = Emailr::client('em_xxxxxxxxx');

  $emailr->emails->send([
    'from' => 'Acme <onboarding@emailr.dev>',
    'to' => ['delivered@emailr.dev'],
    'subject' => 'hello world',
    'html' => '<p>it works!</p>',
    'scheduled_at' => 'in 1 min'
  ]);
  ```

  ```python Python {10} theme={null} theme={null}
  import emailr

  emailr.api_key = "em_xxxxxxxxx"

  params: emailr.Emails.SendParams = {
    "from": "Acme <onboarding@emailr.dev>",
    "to": ["delivered@emailr.dev"],
    "subject": "hello world",
    "html": "<p>it works!</p>",
    "scheduled_at": "in 1 min"
  }

  emailr.Emails.send(params)
  ```

  ```rb Ruby {10} theme={null} theme={null}
  require "emailr"

  Emailr.api_key = "em_xxxxxxxxx"

  params = {
    "from": "Acme <onboarding@emailr.dev>",
    "to": ["delivered@emailr.dev"],
    "subject": "hello world",
    "html": "<p>it works!</p>",
    "scheduled_at": "in 1 min"
  }

  Emailr::Emails.send(params)
  ```

  ```go Go {16} theme={null} theme={null}
  import (
  	"fmt"

  	"github.com/emailr/emailr-go/v3"
  )

  func main() {
    ctx := context.TODO()
    client := emailr.NewClient("em_xxxxxxxxx")

    params := &emailr.SendEmailRequest{
      From:        "Acme <onboarding@emailr.dev>",
      To:          []string{"delivered@emailr.dev"},
      Subject:     "hello world",
      Html:        "<p>it works!</p>",
      ScheduledAt: "in 1 min"
    }

    sent, err := client.Emails.SendWithContext(ctx, params)

    if err != nil {
      panic(err)
    }
    fmt.Println(sent.Id)
  }
  ```

  ```rust Rust {14} theme={null} theme={null}
  use emailr_rs::types::CreateEmailBaseOptions;
  use emailr_rs::{Emailr, Result};

  #[tokio::main]
  async fn main() -> Result<()> {
    let emailr = Emailr::new("em_xxxxxxxxx");

    let from = "Acme <onboarding@emailr.dev>";
    let to = ["delivered@emailr.dev"];
    let subject = "hello world";

    let email = CreateEmailBaseOptions::new(from, to, subject)
      .with_html("<p>it works!</p>")
      .with_scheduled_at("in 1 min");

    let _email = emailr.emails.send(email).await?;

    Ok(())
  }
  ```

  ```java Java {12} theme={null} theme={null}
  import com.emailr.*;

  public class Main {
      public static void main(String[] args) {
          Emailr emailr = new Emailr("em_xxxxxxxxx");

          CreateEmailOptions params = CreateEmailOptions.builder()
                  .from("Acme <onboarding@emailr.dev>")
                  .to("delivered@emailr.dev")
                  .subject("hello world")
                  .html("<p>it works!</p>")
                  .scheduledAt("in 1 min")
                  .build();

          CreateEmailResponse data = emailr.emails().send(params);
      }
  }
  ```

  ```csharp .NET {11} theme={null} theme={null}
  using Emailr;

  IEmailr emailr = EmailrClient.Create( "em_xxxxxxxxx" ); // Or from DI

  var resp = await emailr.EmailSendAsync( new EmailMessage()
  {
      From = "Acme <onboarding@emailr.dev>",
      To = "delivered@emailr.dev",
      Subject = "hello world",
      HtmlBody = "<p>it works!</p>",
      MomentSchedule = "in 1 min",
  } );
  Console.WriteLine( "Email Id={0}", resp.Content );
  ```

  ```bash cURL {9} theme={null} theme={null}
  curl -X POST 'https://api.emailr.dev/emails' \
       -H 'Authorization: Bearer em_xxxxxxxxx' \
       -H 'Content-Type: application/json' \
       -d $'{
    "from": "Acme <onboarding@emailr.dev>",
    "to": ["delivered@emailr.dev"],
    "subject": "hello world",
    "html": "<p>it works!</p>",
    "scheduled_at": "in 1 min"
  }'
  ```
</CodeGroup>

## 2. Schedule using date format

You can also use a date in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) format (e.g: `2024-08-05T11:52:01.858Z`).

<CodeGroup>
  ```ts Node.js {5} theme={null} theme={null}
  import { Emailr } from 'emailr';

  const emailr = new Emailr('em_xxxxxxxxx');

  const oneMinuteFromNow = new Date(Date.now() + 1000 * 60).toISOString();

  await emailr.emails.send({
    from: 'Acme <onboarding@emailr.dev>',
    to: ['delivered@emailr.dev'],
    subject: 'hello world',
    html: '<p>it works!</p>',
    scheduledAt: oneMinuteFromNow,
  });
  ```

  ```php PHP {3} theme={null} theme={null}
  $emailr = Emailr::client('em_xxxxxxxxx');

  $oneMinuteFromNow = (new DateTime())->modify('+1 minute')->format(DateTime::ISO8601);

  $emailr->emails->send([
    'from' => 'Acme <onboarding@emailr.dev>',
    'to' => ['delivered@emailr.dev'],
    'subject' => 'hello world',
    'html' => '<p>it works!</p>',
    'scheduled_at' => $oneMinuteFromNow
  ]);
  ```

  ```python Python {6} theme={null} theme={null}
  import emailr
  from datetime import datetime, timedelta

  emailr.api_key = "em_xxxxxxxxx"

  one_minute_from_now = (datetime.now() + timedelta(minutes=1)).isoformat()

  params: emailr.Emails.SendParams = {
    "from": "Acme <onboarding@emailr.dev>",
    "to": ["delivered@emailr.dev"],
    "subject": "hello world",
    "html": "<p>it works!</p>",
    "scheduled_at": one_minute_from_now
  }

  emailr.Emails.send(params)
  ```

  ```rb Ruby {5} theme={null} theme={null}
  require "emailr"

  Emailr.api_key = "em_xxxxxxxxx"

  one_minute_from_now = (Time.now + 1 * 60).strftime("%Y-%m-%dT%H:%M:%S.%L%z")

  params = {
    "from": "Acme <onboarding@emailr.dev>",
    "to": ["delivered@emailr.dev"],
    "subject": "hello world",
    "html": "<p>it works!</p>",
    "scheduled_at": one_minute_from_now
  }

  Emailr::Emails.send(params)
  ```

  ```go Go {12} theme={null} theme={null}
  import (
  	"fmt"

  	"github.com/emailr/emailr-go/v3"
  )

  func main() {
    ctx := context.TODO()
    client := emailr.NewClient("em_xxxxxxxxx")

    oneMinuteFromNow := time.Now().Add(time.Minute * time.Duration(1))
    oneMinuteFromNowISO := oneMinuteFromNow.Format("2006-01-02T15:04:05-0700")

    params := &emailr.SendEmailRequest{
      From:        "Acme <onboarding@emailr.dev>",
      To:          []string{"delivered@emailr.dev"},
      Subject:     "hello world",
      Html:        "<p>it works!</p>",
      ScheduledAt: oneMinuteFromNowISO
    }

    sent, err := client.Emails.SendWithContext(ctx, params)

    if err != nil {
      panic(err)
    }
    fmt.Println(sent.Id)
  }
  ```

  ```rust Rust {12-15} theme={null} theme={null}
  use chrono::{Local, TimeDelta};
  use emailr_rs::types::CreateEmailBaseOptions;
  use emailr_rs::{Emailr, Result};

  #[tokio::main]
  async fn main() -> Result<()> {
    let emailr = Emailr::new("em_xxxxxxxxx");

    let from = "Acme <onboarding@emailr.dev>";
    let to = ["delivered@emailr.dev"];
    let subject = "hello world";
    let one_minute_from_now = Local::now()
      .checked_add_signed(TimeDelta::minutes(1))
      .unwrap()
      .to_rfc3339();

    let email = CreateEmailBaseOptions::new(from, to, subject)
      .with_html("<p>it works!</p>")
      .with_scheduled_at(&one_minute_from_now);

    let _email = emailr.emails.send(email).await?;

    Ok(())
  }
  ```

  ```java Java {7-10} theme={null} theme={null}
  import com.emailr.*;

  public class Main {
      public static void main(String[] args) {
          Emailr emailr = new Emailr("em_xxxxxxxxx");

          String oneMinuteFromNow = Instant
            .now()
            .plus(1, ChronoUnit.MINUTES)
            .toString();

          CreateEmailOptions params = CreateEmailOptions.builder()
                  .from("Acme <onboarding@emailr.dev>")
                  .to("delivered@emailr.dev")
                  .subject("hello world")
                  .html("<p>it works!</p>")
                  .scheduledAt(oneMinuteFromNow)
                  .build();

          CreateEmailResponse data = emailr.emails().send(params);
      }
  }
  ```

  ```csharp .NET {11} theme={null} theme={null}
  using Emailr;

  IEmailr emailr = EmailrClient.Create( "em_xxxxxxxxx" ); // Or from DI

  var resp = await emailr.EmailSendAsync( new EmailMessage()
  {
      From = "Acme <onboarding@emailr.dev>",
      To = "delivered@emailr.dev",
      Subject = "hello world",
      HtmlBody = "<p>it works!</p>",
      MomentSchedule = DateTime.UtcNow.AddMinutes( 1 ),
  } );
  Console.WriteLine( "Email Id={0}", resp.Content );
  ```

  ```bash cURL {9} theme={null} theme={null}
  curl -X POST 'https://api.emailr.dev/emails' \
       -H 'Authorization: Bearer em_xxxxxxxxx' \
       -H 'Content-Type: application/json' \
       -d $'{
    "from": "Acme <onboarding@emailr.dev>",
    "to": ["delivered@emailr.dev"],
    "subject": "hello world",
    "html": "<p>it works!</p>",
    "scheduled_at": "2024-08-20T11:52:01.858Z"
  }'
  ```
</CodeGroup>

## View a scheduled email

Once you schedule an email, you can see the scheduled time in the Emailr dashboard.

<img alt="Video placeholder" src="https://mintcdn.com/emailrdev/tSm2WeCvU8-lHmTx/images/placeholder.svg?fit=max&auto=format&n=tSm2WeCvU8-lHmTx&q=85&s=93891ced94bad8f8c38f90b5be99f73c" width="800" height="450" data-path="images/placeholder.svg" />

## Reschedule an email

After scheduling an email, you might need to update the scheduled time.

You can do so with the following method:

<CodeGroup>
  ```ts Node.js {3} theme={null} theme={null}
  emailr.emails.update({
    id: '49a3999c-0ce1-4ea6-ab68-afcd6dc2e794',
    scheduledAt: 'in 1 min',
  });
  ```

  ```php PHP {2} theme={null} theme={null}
  $emailr->emails->update('49a3999c-0ce1-4ea6-ab68-afcd6dc2e794', [
    'scheduled_at' => 'in 1 min'
  ]);
  ```

  ```python Python {3} theme={null} theme={null}
  update_params: emailr.Emails.UpdateParams = {
    "id": "49a3999c-0ce1-4ea6-ab68-afcd6dc2e794",
    "scheduled_at": "in 1 min"
  }

  emailr.Emails.update(params=update_params)
  ```

  ```rb Ruby {3} theme={null} theme={null}
  update_params = {
    "email_id": "49a3999c-0ce1-4ea6-ab68-afcd6dc2e794",
    "scheduled_at": "in 1 min"
  }

  updated_email = Emailr::Emails.update(update_params)
  ```

  ```go Go {3} theme={null} theme={null}
  updateParams := &emailr.UpdateEmailRequest{
    Id:          "49a3999c-0ce1-4ea6-ab68-afcd6dc2e794",
    ScheduledAt: "in 1 min",
  }

  updatedEmail, err := client.Emails.Update(updateParams)

  if err != nil {
    panic(err)
  }
  fmt.Printf("%v\n", updatedEmail)
  ```

  ```rust Rust {2} theme={null} theme={null}
  let update = UpdateEmailOptions::new()
    .with_scheduled_at("in 1 min");

  let _email = emailr
    .emails
    .update("49a3999c-0ce1-4ea6-ab68-afcd6dc2e794", update)
    .await?;
  ```

  ```java Java {2} theme={null} theme={null}
  UpdateEmailOptions updateParams = UpdateEmailOptions.builder()
    .scheduledAt("in 1 min")
    .build();

  UpdateEmailResponse data = emailr.emails().update("49a3999c-0ce1-4ea6-ab68-afcd6dc2e794", updateParams);
  ```

  ```csharp .NET {7} theme={null} theme={null}
  using Emailr;

  IEmailr emailr = EmailrClient.Create( "em_xxxxxxxxx" ); // Or from DI

  await emailr.EmailRescheduleAsync(
    new Guid( "49a3999c-0ce1-4ea6-ab68-afcd6dc2e794" ),
    "in 1 min"
  );
  ```

  ```bash cURL {5} theme={null} theme={null}
  curl -X PATCH 'https://api.emailr.dev/emails/49a3999c-0ce1-4ea6-ab68-afcd6dc2e794' \
       -H 'Authorization: Bearer em_xxxxxxxxx' \
       -H 'Content-Type: application/json' \
       -d $'{
    "scheduled_at": "in 1 min"
  }'
  ```
</CodeGroup>

You can also reschedule an email directly in the Emailr dashboard.

<img alt="Video placeholder" src="https://mintcdn.com/emailrdev/tSm2WeCvU8-lHmTx/images/placeholder.svg?fit=max&auto=format&n=tSm2WeCvU8-lHmTx&q=85&s=93891ced94bad8f8c38f90b5be99f73c" width="800" height="450" data-path="images/placeholder.svg" />

## Cancel a scheduled email

<Warning>Once an email is canceled, it cannot be rescheduled.</Warning>

If you need to cancel a scheduled email, you can do so with the following code:

<CodeGroup>
  ```ts Node.js theme={null} theme={null}
  emailr.emails.cancel('49a3999c-0ce1-4ea6-ab68-afcd6dc2e794');
  ```

  ```php PHP theme={null} theme={null}
  $emailr->emails->cancel('49a3999c-0ce1-4ea6-ab68-afcd6dc2e794');
  ```

  ```python Python theme={null} theme={null}
  emailr.Emails.cancel(email_id="49a3999c-0ce1-4ea6-ab68-afcd6dc2e794")
  ```

  ```rb Ruby theme={null} theme={null}
  Emailr::Emails.cancel("49a3999c-0ce1-4ea6-ab68-afcd6dc2e794")
  ```

  ```go Go theme={null} theme={null}
  canceled, err := client.Emails.Cancel("49a3999c-0ce1-4ea6-ab68-afcd6dc2e794")
  if err != nil {
    panic(err)
  }
  fmt.Println(canceled.Id)
  ```

  ```rust Rust theme={null} theme={null}
  let _canceled = emailr
    .emails
    .cancel("49a3999c-0ce1-4ea6-ab68-afcd6dc2e794")
    .await?;
  ```

  ```java Java theme={null} theme={null}
  CancelEmailResponse canceled = emailr
      .emails()
      .cancel("49a3999c-0ce1-4ea6-ab68-afcd6dc2e794");
  ```

  ```csharp .NET theme={null} theme={null}
  using Emailr;

  IEmailr emailr = EmailrClient.Create( "em_xxxxxxxxx" ); // Or from DI

  await emailr.EmailCancelAsync( new Guid( "49a3999c-0ce1-4ea6-ab68-afcd6dc2e794" ) );
  ```

  ```bash cURL theme={null} theme={null}
  curl -X POST 'https://api.emailr.dev/emails/49a3999c-0ce1-4ea6-ab68-afcd6dc2e794/cancel' \
       -H 'Authorization: Bearer em_xxxxxxxxx' \
       -H 'Content-Type: application/json'
  ```
</CodeGroup>

You can also cancel a scheduled email in the Emailr dashboard.

<img alt="Video placeholder" src="https://mintcdn.com/emailrdev/tSm2WeCvU8-lHmTx/images/placeholder.svg?fit=max&auto=format&n=tSm2WeCvU8-lHmTx&q=85&s=93891ced94bad8f8c38f90b5be99f73c" width="800" height="450" data-path="images/placeholder.svg" />
