Quickstarts
Send with Better Auth emails
Send your first email from Better Auth emails.
Prerequisites
You need a running installation, a verified sending domain, and an API key with sending or full access. Set OPENSEND_API_KEY and OPENSEND_BASE_URL on the server. The base URL is your installation’s API origin (the public Convex HTTP origin), such as https://api.example.com, without an /api suffix.
Install
bash
pnpm add @opensendcc/sdkSend
typescript
import { betterAuth } from "better-auth";
import { Opensend } from "@opensendcc/sdk";
const opensend = new Opensend(process.env.OPENSEND_API_KEY!, {
baseUrl: process.env.OPENSEND_BASE_URL!, // https://api.example.com
});
// Merge these email hooks into your existing Better Auth configuration.
export const auth = betterAuth({
emailAndPassword: {
enabled: true,
sendResetPassword: async ({ user, url }) => {
const { error } = await opensend.emails.send({
from: "Acme <hello@example.com>", to: user.email,
subject: "Reset your password", text: `Reset your password: ${url}`,
});
if (error) throw new Error(error.message);
},
},
emailVerification: {
sendVerificationEmail: async ({ user, url }) => {
const { error } = await opensend.emails.send({
from: "Acme <hello@example.com>", to: user.email,
subject: "Verify your email", text: `Verify your email: ${url}`,
});
if (error) throw new Error(error.message);
},
},
});Try it
Trigger a verification or password reset in your app. Open Emails in Opensend to inspect the message. An ID means the email entered the durable queue; it does not prove inbox delivery. Inspect delivery events and failures there.
Keep the key on the server. SES sandbox restrictions still apply. The HTTP equivalent is:
bash
curl "$OPENSEND_BASE_URL/emails" \
-H "Authorization: Bearer $OPENSEND_API_KEY" \
-H "Content-Type: application/json" \
-d '{"from":"Acme <hello@example.com>","to":["you@example.net"],"subject":"Hello from Opensend","html":"<p>Your first email is on its way.</p>"}'