Skip to main content
AutoSend x Better Auth
This guide shows you how to integrate AutoSend with Better Auth to send authentication emails. Better Auth is a framework-agnostic authentication library for TypeScript that supports email verification, password reset, and OTP-based authentication.

Prerequisites

Installation

Install Better Auth in your project if you haven’t already:
npm install better-auth

Integration

1

Set Environment Variables

Add the required environment variables to your .env file:
.env
AUTOSEND_API_KEY=your_autosend_api_key_here
FROM_EMAIL=[email protected]
FROM_NAME=Your App Name
Get your API key from the API Keys page in your AutoSend dashboard.
2

Create AutoSend Email Helper

Create a helper function to send emails via the AutoSend API using templates:
lib/autosend.ts
const AUTOSEND_API_KEY = process.env.AUTOSEND_API_KEY!;
const FROM_EMAIL = process.env.FROM_EMAIL || "[email protected]";
const FROM_NAME = process.env.FROM_NAME || "Your App";

interface SendEmailOptions {
  to: string;
  templateId: string;
  dynamicData: Record<string, string>;
}

export async function sendEmail({ to, templateId, dynamicData }: SendEmailOptions) {
  const response = await fetch("https://api.autosend.com/v1/mails/send", {
    method: "POST",
    headers: {
      Authorization: `Bearer ${AUTOSEND_API_KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      from: {
        email: FROM_EMAIL,
        name: FROM_NAME,
      },
      to: {
        email: to,
      },
      templateId,
      dynamicData,
    }),
  });

  if (!response.ok) {
    const error = await response.json();
    throw new Error(error.message || "Failed to send email");
  }

  return response.json();
}
3

Create Email Templates

Create email templates in your AutoSend dashboard for each authentication flow:
TemplateSuggested IDVariables
Email verificationtmpl_verify_email{{userName}}, {{verificationUrl}}
Password resettmpl_password_reset{{userName}}, {{resetUrl}}
Sign-in OTPtmpl_otp_signin{{otp}}
Verification OTPtmpl_otp_verify{{otp}}
Password reset OTPtmpl_otp_reset{{otp}}
Learn more about template variables.
4

Configure Better Auth

Wire up your Better Auth configuration to send emails through AutoSend:
lib/auth.ts
import { betterAuth } from "better-auth";
import { emailOTP } from "better-auth/plugins";
import { sendEmail } from "./autosend";

export const auth = betterAuth({
  // ... your database and other configuration

  emailVerification: {
    sendOnSignUp: true,
    sendVerificationEmail: async ({ user, url }) => {
      sendEmail({
        to: user.email,
        templateId: "tmpl_verify_email",
        dynamicData: {
          userName: user.name || "there",
          verificationUrl: url,
        },
      });
    },
  },

  emailAndPassword: {
    enabled: true,
    sendResetPassword: async ({ user, url }) => {
      sendEmail({
        to: user.email,
        templateId: "tmpl_password_reset",
        dynamicData: {
          userName: user.name || "there",
          resetUrl: url,
        },
      });
    },
  },

  plugins: [
    emailOTP({
      sendVerificationOTP: async ({ email, otp, type }) => {
        const templateIds = {
          "sign-in": "tmpl_otp_signin",
          "email-verification": "tmpl_otp_verify",
          "forget-password": "tmpl_otp_reset",
        };

        sendEmail({
          to: email,
          templateId: templateIds[type],
          dynamicData: { otp },
        });
      },
    }),
  ],
});
Don’t await email sending to prevent timing attacks. This ensures response time doesn’t reveal whether an email was sent.
For client-side setup (sending OTPs, verifying codes), see the Better Auth Email OTP documentation.

Serverless Considerations

When running on serverless platforms (Vercel, AWS Lambda, Cloudflare Workers), ensure email sending completes before the function terminates.
Use waitUntil to ensure the email is sent:
import { waitUntil } from '@vercel/functions';
import { sendEmail } from './autosend';

// In your Better Auth config
sendVerificationEmail: async ({ user, url }) => {
  waitUntil(
    sendEmail({
      to: user.email,
      templateId: 'tmpl_verify_email',
      dynamicData: {
        userName: user.name || 'there',
        verificationUrl: url,
      },
    })
  );
};

Troubleshooting

If you receive a “Domain not verified” error, ensure your sending domain is properly configured in AutoSend.Solution: Go to your Domain Settings and complete the DNS verification process.
A 401 error indicates your API key is invalid or missing.Solution:
  1. Check your .env file has the correct AUTOSEND_API_KEY
  2. Verify the key in your API Keys dashboard
  3. Ensure the key hasn’t been revoked
If you’re sending too many emails, you may hit rate limits.Solution: Review the Rate Limits documentation and implement appropriate throttling in your application.
If emails aren’t being delivered:
  1. Check the Email Activity dashboard for delivery status
  2. Verify the recipient email is valid
  3. Check if the email is in Suppressions
  4. Review the Troubleshooting Guide for common issues

Next Steps