Configuring AutoSend transactional templates for Better Auth OTPs and verification links

When integrating Better Auth with AutoSend for sending OTPs and email verification links, how do we configure template mapping and prevent serverless execution timeouts or timing attacks on Vercel/Cloudflare Workers?

Better Auth provides native hooks (emailVerification, sendResetPassword, emailOTP plugin) where you call AutoSend’s POST /v1/mails/send endpoint.

Complete Better Auth Integration (lib/auth.ts):

import { betterAuth } from "better-auth";
import { emailOTP } from "better-auth/plugins";
import { waitUntil } from "@vercel/functions";

async function sendAutoSendTemplate(to: string, templateId: string, dynamicData: Record<string, any>) {
  await fetch("https://api.autosend.com/v1/mails/send", {
    method: "POST",
    headers: {
      "Authorization": `Bearer ${process.env.AUTOSEND_API_KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      from: { email: "auth@yourdomain.com", name: "Security" },
      to: { email: to },
      templateId,
      dynamicData,
    }),
  });
}

export const auth = betterAuth({
  emailVerification: {
    sendOnSignUp: true,
    sendVerificationEmail: async ({ user, url }) => {
      // Use waitUntil on Vercel/Cloudflare so the function doesn't terminate prematurely
      waitUntil(
        sendAutoSendTemplate(user.email, "tmpl_verify_email", {
          userName: user.name || "there",
          verificationUrl: url,
        })
      );
    },
  },
  plugins: [
    emailOTP({
      sendVerificationOTP: async ({ email, otp, type }) => {
        const templates: Record<string, string> = {
          "sign-in": "tmpl_otp_signin",
          "email-verification": "tmpl_otp_verify",
          "forget-password": "tmpl_otp_reset",
        };
        waitUntil(
          sendAutoSendTemplate(email, templates[type], { otp })
        );
      },
    }),
  ],
});

Relevant Documentation