Overview

Sometimes rather than sending a welcome email to new users immediately, it’s nice to delay it.

(Some email APIs support this out of the box, but for the sake of this example, let’s assume they don’t.)

We’re going to use Resend as our email API, because we’re big fans!

Getting your Resend API key

Before we can set up our scheduled email, you’ll need an API key from Resend.

Sign up for a free account here: https://resend.com/signup

Scheduling your welcome email

Once we have our Resend API key, we can send a POST request to https://api.resend.com/emails with the following email parameters:

const email = {
  // If you want to send from your own domain, you'll have to verify
  // your domain in the Resend dashboard: https://resend.com/domains
  from: "Example <welcome@resend.dev>",
  // The email address of the user that just signed up:
  to: user.email,
  subject: "Welcome to Example Inc!",
  html:
    "<p>Thanks for signing up!</p>" +
    "<p>Check out our docs to get started: https://docs.example.com</p>" +
    "<p>Best,<br />Alex</p>",
};

Here’s how it might look in the code after a new user signs up for an account:

import Scheduler from "@booper/scheduler";

const BOOPER_API_KEY = process.env.BOOPER_API_KEY;
const RESEND_API_KEY = process.env.RESEND_API_KEY;

const scheduler = new Scheduler({ apiKey: BOOPER_API_KEY });

async function register(user) {
  // ...
  // handle user registration logic
  // ...

  await scheduler.jobs.create({
    method: "post",
    url: "https://api.resend.com/emails",
    headers: {
      Authorization: `Bearer ${RESEND_API_KEY}`,
    },
    body: {
      from: "Example <welcome@resend.dev>",
      to: user.email,
      subject: "Welcome to Example Inc!",
      html:
        "<p>Thanks for signing up!</p>" +
        "<p>Check out our docs to get started: https://docs.example.com</p>" +
        "<p>Best,<br />Alex</p>",
    },
    schedule_in: [45, "minutes"],
    idempotency_key: `${user.email}:welcome`,
  });
}

Don’t forget to pass in your RESEND_API_KEY in the Authorization header

This will schedule an email to be sent to user.email in 45 minutes after signing up.

Optional: Ensuring idempotency

Booper also features an option to ensure idempotency, meaning we can set a key that is used to enforce uniqueness.

In other words, if we want to send an email to Jane and make sure it’s only sent once, we could set the idempotency_key to some combination of Jane’s unique ID with the name of the email template (e.g. jane.welcome) to force any future scheduled emails with the same idempotency_key to be ignored.