Design an email once in the builder, then send it from your app whenever you need to: a welcome note, a receipt, a password reset. Your app only references a template ID, so you can change the design anytime without touching code. The Node SDK works today, and a plain HTTP API for other languages is on the way.
Quickstart#
From zero to a sent email in three steps.
In your workspace, open Settings → API keys and create a key. Store it as an environment variable.
emiit delivers through an email service. Here we use Resend, but any of the supported providers works.
npm install @emiit/sdk resendGrab a template ID from the dashboard and send. The full client setup is in the next section.
await emiit.send({
templateId: "tmpl_welcome",
from: "Emiit <[email protected]>",
to: "[email protected]",
subject: "Welcome to Emiit",
data: { name: "Jane" },
});Get your API key#
Open Settings → API keys in your workspace and create a key. It's the only thing you need to start sending, so keep it private and store it as an environment variable.
export EMIIT_API_KEY="emiit_sk_live_..."Send an email#
Pick a template, say who it's for, and emiit builds and sends the email. The Node SDK is ready now; the other languages call the HTTP API that's coming soon.
import { Emiit } from "@emiit/sdk";
import { resend } from "@emiit/sdk/providers";
import { Resend } from "resend";
const emiit = new Emiit({
apiKey: process.env.EMIIT_API_KEY,
provider: resend(new Resend(process.env.RESEND_API_KEY)),
});
await emiit.send({
templateId: "tmpl_welcome",
from: "Emiit <[email protected]>",
to: "[email protected]",
subject: "Welcome to Emiit",
data: { name: "Jane", plan: "Pro" },
});You can send to one person or a whole list, add people on copy, set a reply-to address, or write the preview line. See sending options for everything you can include.
The Node client#
The SDK gives you typed options, readable errors, and no hand-written requests. Add it to your project:
npm install @emiit/sdkThese are the settings you give the client once, when you create it:
| Field | Type | What it does |
|---|---|---|
apiKeyrequired | string | Your emiit API key, from Settings → API keys. |
providerrequired | Provider | The email service that actually sends the mail. |
fromoptional | string | A default sender, used when you don't pass one to send(). |
Set a default from on the client and you can leave it out of every send() call.
Delivery#
emiit renders your template; an email service delivers it. Plug in the one you already use with your own account and keys, so nothing about your sending reputation changes. These are the supported services:
resendnpm i resendnodemailernpm i nodemailer@sendgrid/mailnpm i @sendgrid/mailpostmarknpm i postmark@aws-sdk/client-sesnpm i @aws-sdk/client-sesYou set the service up with your own account details, then hand it to emiit. Here it is with Nodemailer over plain SMTP:
import { Emiit } from "@emiit/sdk";
import { nodemailer } from "@emiit/sdk/providers";
import nm from "nodemailer";
const transport = nm.createTransport({
host: "smtp.emiit.dev",
port: 587,
auth: { user: process.env.SMTP_USER, pass: process.env.SMTP_PASS },
});
const emiit = new Emiit({
apiKey: process.env.EMIIT_API_KEY,
provider: nodemailer(transport),
});Sending options#
Everything you can include when you send an email, whether over the API or the SDK:
| Field | Type | What it does |
|---|---|---|
templateIdrequired | string | The ID of the template you built, shown on its page in the dashboard. |
torequired | string | string[] | One recipient, or a list of them. |
subjectrequired | string | The subject line. It can use variables too, like "Welcome, {{ name }}". |
fromrequired | string | Who the email comes from, like "Emiit <[email protected]>". Optional if you set a default from on the client. |
previewoptional | string | The short line shown next to the subject in the inbox. Optional. |
dataoptional | object | The values that fill in the blanks in your design. |
ccoptional | string | string[] | People to copy on the email. |
bccoptional | string | string[] | People to copy without others seeing them. |
replyTooptional | string | string[] | Where replies should go, if not the sender. |
attachmentsoptional | Attachment[] | Files to send along, such as a PDF receipt. |
tagsoptional | object | Labels you add to track and filter sends in the dashboard. |
Filling in data#
Most emails have parts that change for each person, like a name, an order total, or a list of items. Whatever you pass as data fills in those blanks in your design, matched by name. The subject line can use variables too.
{
"templateId": "tmpl_welcome",
"to": "[email protected]",
"subject": "Welcome, {{ name }}",
"data": {
"name": "Jane",
"plan": "Pro",
"items": [
{ "label": "Unlimited templates" },
{ "label": "Team workspaces" }
]
}
}If a required variable is missing or has the wrong type, the send fails with an invalid_data error that lists exactly which fields to fix, so a broken email never goes out.
Opens & clicks#
Tracking is on by default and needs no setup. Every send is logged per template, links are rewritten to count clicks, and opens are measured automatically. See it all under Analytics in your workspace.
Add tags to a send to label it, so you can tell campaigns apart in the dashboard:
await emiit.send({
templateId: "tmpl_receipt",
to: "[email protected]",
subject: "Your receipt",
tags: { campaign: "q3-launch" },
});Errors#
When an email can't be sent, the SDK throws an EmiitError with a stable code, the HTTP status, and a readable message, so you can show a friendly message or retry.
import { Emiit, EmiitError } from "@emiit/sdk";
try {
await emiit.send({
templateId: "tmpl_welcome",
to: "[email protected]",
subject: "Welcome",
});
} catch (err) {
if (err instanceof EmiitError) {
// e.g. "invalid_data" 422 "Missing or invalid variables: name (string)."
console.error(err.code, err.status, err.message);
}
throw err;
}The codes you might see:
| Code | Status | What it means |
|---|---|---|
missing_api_key | 401 | No API key was sent. Pass it when creating the client, or in the x-api-key header on the HTTP API. |
invalid_api_key | 401 | The key doesn't match any workspace. Check for a typo or a revoked key. |
template_not_found | 404 | No template with that ID exists in your workspace. |
invalid_body | 400 | The request body isn't valid JSON. |
invalid_data | 422 | Required template variables are missing or the wrong type. The fields array lists each one. |
missing_from | 400 | Thrown by the SDK before any request: no from on send() and no default on the client. |
missing_recipient | 400 | Thrown by the SDK before any request: to is empty. |