Next.js
Send transactional emails from Next.js in five minutes — no SDK, one fetch.
Send transactional emails from your Next.js app in five minutes. No SDK
required — the whole integration is one fetch.
1. Set up environment variables
Add to .env.local:
EMITD_API_KEY=esk_live_...2. Create a route handler
export async function POST(request: Request) {
const { email, name } = await request.json();
const res = await fetch("https://api.emitd.com/v1/email", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.EMITD_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
from: "hello@yourdomain.com",
to: [email],
subject: `Welcome, ${name}!`,
html_body: `
<h1>Welcome to our app!</h1>
<p>Hi ${name},</p>
<p>Thanks for signing up. We're excited to have you.</p>
`,
tags: { campaign: "welcome" },
}),
});
return Response.json(await res.json());
}Never call emitd from the browser
Keep EMITD_API_KEY in a route handler or server action — the App Router
makes that the default. A key shipped to the client is a leaked key.
3. Use it in a component
"use client";
import { useState } from "react";
export default function Home() {
const [email, setEmail] = useState("");
const [name, setName] = useState("");
const [status, setStatus] = useState("");
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
setStatus("sending...");
const res = await fetch("/api/send-email", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ email, name }),
});
const data = await res.json();
setStatus(data.status === "queued" ? "Sent!" : "Error");
};
return (
<form onSubmit={handleSubmit}>
<input placeholder="Name" value={name} onChange={(e) => setName(e.target.value)} />
<input type="email" placeholder="Email" value={email} onChange={(e) => setEmail(e.target.value)} />
<button type="submit">Send welcome email</button>
<p>{status}</p>
</form>
);
}4. Verify your domain
Before sending from production, verify your domain in the console: add it, publish the DNS records (SPF/DKIM/DMARC), and wait for verification (usually under five minutes). See Sending domains.
5. Test with sandbox recipients
For development, flip test mode on and send to a reserved recipient — no real email leaves the building, every event still fires:
body: JSON.stringify({
from: "hello@yourdomain.com",
to: ["delivered@relay.dev"],
subject: "Test email",
html_body: "<p>This is a test</p>",
test_mode: true,
}),bounced@relay.dev and complained@relay.dev simulate the other outcomes;
inspect results at GET /v1/email/test-events. See
Test mode.
What's next?
- Templates — server-side rendering with
template_alias+template_model - Webhooks — HMAC-signed delivery events
- Idempotency — safe retries with
Idempotency-Key - Scheduling —
scheduled_atin epoch ms