Docs

The emiit SDK

Send the templates you design in emiit from your own app.

Quickstart#

Three steps to your first email.

1
Create an API key

In your workspace, open Settings → API keys and create a key. Store it as an environment variable.

2
Install the SDK and a provider

emiit delivers through an email service. Here we use Resend, but any of the supported providers works.

Terminal
npm install @emiit/sdk resend
3
Send your first email

Grab a template ID from the dashboard and send. The full client setup is in the next section.

JavaScript
await emiit.send({
  templateId: "tmpl_welcome",
  from: "Emiit <hello@emiit.dev>",
  to: "timi@emiit.dev",
  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.

Terminal
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. Use the Node SDK, or call the HTTP API from anything else.

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 <hello@emiit.dev>",
  to: "timi@emiit.dev",
  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:

Terminal
npm install @emiit/sdk

These are the settings you give the client once, when you create it:

FieldTypeWhat it does
apiKeyrequiredstringYour emiit API key, from Settings → API keys.
provideroptionalProviderThe email service that delivers the mail. Leave it out to send with emiit, from a domain you verified.
fromoptionalstringA 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:

Resendresend
npm i resend
Nodemailernodemailer
npm i nodemailer
SendGrid@sendgrid/mail
npm i @sendgrid/mail
Postmarkpostmark
npm i postmark
AWS SES@aws-sdk/client-ses
npm i @aws-sdk/client-ses

You set the service up with your own account details, then hand it to emiit. Here it is with Nodemailer over plain SMTP:

JavaScript
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 with emiit

Prefer not to bring a provider? Leave provider out and emiit delivers the mail itself. First connect the domain you want to send from:

1
Add your domain

Open Settings → Domains and add it. You'll get three DKIM CNAME records and a starter DMARC record.

2
Add the DNS records

Copy them into your DNS provider, then hit Check. Verification is usually minutes, though DNS can take up to 72 hours to propagate.

3
Send from any address on it

Once the domain reads verified, every address on it works as a from, subdomains included.

JavaScript
import { Emiit } from "@emiit/sdk";

const emiit = new Emiit({ apiKey: process.env.EMIIT_API_KEY });

await emiit.send({
  templateId: "tmpl_welcome",
  from: "Emiit <hello@emiit.dev>",
  to: "timi@emiit.dev",
  subject: "Welcome to Emiit",
  data: { name: "Jane" },
});
A send from an unverified domain fails with domain_not_verified rather than being delivered unsigned. Attachments still need a provider.

Want to try it before touching DNS? Send from welcome@emiit.dev today. It needs no setup, but it only delivers to the email addresses of your workspace's members, so it's for testing rather than real traffic. Anything else comes back as recipient_not_allowed.

Sending options#

Everything you can include when you send an email, whether over the API or the SDK:

FieldTypeWhat it does
templateIdrequiredstringThe ID of the template you built, shown on its page in the dashboard.
torequiredstring | string[]One recipient, or a list of them.
subjectrequiredstringThe subject line. It can use variables too, like "Welcome, {{ name }}".
fromrequiredstringWho the email comes from, like "Emiit <hello@emiit.dev>". Optional if you set a default from on the client.
previewoptionalstringThe short line shown next to the subject in the inbox. Optional.
dataoptionalobjectThe values that fill in the blanks in your design.
ccoptionalstring | string[]People to copy on the email.
bccoptionalstring | string[]People to copy without others seeing them.
replyTooptionalstring | string[]Where replies should go, if not the sender.
attachmentsoptionalAttachment[]Files to send along, such as a PDF receipt.
tagsoptionalobjectLabels you add to track and filter sends in the dashboard.
unsubscribeoptionalbooleanAdds a one-click unsubscribe link to the inbox UI, as Gmail and Yahoo require for bulk mail. Needs exactly one to and no cc or bcc. Leave it off for receipts and password resets.

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.

JavaScript
{
  "templateId": "tmpl_welcome",
  "to": "timi@emiit.dev",
  "subject": "Welcome, {{ name }}",
  "data": {
    "name": "Jane",
    "plan": "Pro",
    "items": [
      { "label": "Unlimited templates" },
      { "label": "Priority support" }
    ]
  }
}

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:

JavaScript
await emiit.send({
  templateId: "tmpl_receipt",
  to: "timi@emiit.dev",
  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.

JavaScript
import { Emiit, EmiitError } from "@emiit/sdk";

try {
  await emiit.send({
    templateId: "tmpl_welcome",
    to: "timi@emiit.dev",
    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:

CodeStatusWhat it means
missing_api_key401No API key was sent. Pass it when creating the client, or in the x-api-key header on the HTTP API.
invalid_api_key401The key doesn't match any workspace. Check for a typo or a revoked key.
template_not_found404No template with that ID exists in your workspace.
invalid_body400The request body isn't valid JSON.
invalid_data422Required template variables are missing or the wrong type. The fields array lists each one.
missing_from400Thrown by the SDK before any request: no from on send() and no default on the client.
missing_recipient400Thrown by the SDK before any request: to is empty.
domain_not_verified403Sending with emiit from a domain your workspace hasn't verified. Add it under Settings → Domains.
recipient_not_allowed403The shared test sender only delivers to your workspace members' own addresses. Verify a domain to reach anyone else.
recipient_suppressed422Every to address previously bounced, reported spam, or unsubscribed. When only some are, the rest still send and the response lists the skipped ones in suppressed.
unsubscribe_needs_single_recipient400unsubscribe was set on a send with more than one recipient. The link unsubscribes one person, so send to each separately.
sending_paused403Sending is paused because the bounce or complaint rate got too high. The message says which.
rate_limited429More than 10 requests in one second from the same API key. Wait a moment and retry.
daily_limit_reached429The workspace has sent 200 emails today. Each recipient counts as one. The limit resets at 00:00 UTC.
send_failed502Delivery rejected the message. Retry later, and check the from address if it keeps happening.