Quickstart: Node.js
Five minutes from install to a verified send — safely, against the sandbox, before any real email is involved.
Facts verified 2026-07-17 — corrections: hello@emailfast.dev
1. Install
npm install @email-fast/nodejs2. Send
import { EmailFast } from "@email-fast/nodejs";
const ef = new EmailFast({ apiKey: process.env.EMAILFAST_API_KEY, baseUrl: "https://api.emailfast.dev" }); // ef_sandbox_… works everywhere
const { id, status } = await ef.send({
to: "ada@example.com",
subject: "Welcome to the ledger",
html: "<h1>Hi {{name}}</h1><p>Your account is ready.</p>",
data: { name: "Ada" },
idempotency_key: "welcome-ada-1", // retry-safe: same key can never double-send
});
console.log(id, status); // "msg_…", "queued"a 202 from the API means the send is committed to a durable, partitioned outbox before we answer — a crash can't lose it, and a retry with the same idempotency key can't double-send.
3. Watch it happen
const timeline = await ef.getMessage(id);
console.log(timeline.events); // admitted → rendered → (sandbox-)delivered …With a sandbox key the message lands in your hosted capture inbox — same pipeline, nothing sent: sandbox keys (ef_sandbox_…) that run the real pipeline dry: real validation, real rendering, real events, a hosted capture inbox — and no email leaves.
4. Hear about it via webhook
// Your Express handler (raw body needed for signature verification):
import crypto from "node:crypto";
app.post("/hooks/email", express.raw({ type: "application/json" }), (req, res) => {
// x-emailfast-signature: "t=<unix>,v1=<hex>" — HMAC-SHA256 over `<t>.<rawBody>`
const sig = Object.fromEntries(
req.get("x-emailfast-signature").split(",").map((p) => p.split("=")),
);
const expected = crypto
.createHmac("sha256", process.env.EMAILFAST_WEBHOOK_SECRET)
.update(`${sig.t}.${req.body}`)
.digest("hex");
if (!crypto.timingSafeEqual(Buffer.from(sig.v1), Buffer.from(expected))) {
return res.sendStatus(400);
}
const event = JSON.parse(req.body);
// event.type: email.sent | email.bounced | email.opened | …
res.sendStatus(200);
});webhooks signed with timestamped HMAC-SHA256 (Stripe-style t=…,v1=…), with delivery hardened against server-side request forgery. Reject anything older than a few minutes (compare sig.t against the clock) to close the replay window.