Package Exports
- send16-mail
Readme
send16-mail — Email for developers
The official Node.js SDK for Send16 — transactional and marketing email that just works.
Zero runtime dependencies. ~22 KB on disk, no transitive packages, no supply-chain surface. Works in Node.js 18+, Bun, Deno, Cloudflare Workers, and any other runtime that ships fetch. TypeScript-first.
Install
npm install send16-mailGet your API key
Create a free account and grab a key from Developers → API Keys. Free tier ships 1,000 emails/month.
Quick start
import { Send16 } from 'send16-mail';
const send16 = new Send16('sk_live_your_api_key_here');
const { data, error } = await send16.emails.send({
from: 'Acme <hello@yourdomain.com>',
to: ['user@gmail.com'],
subject: 'Hello from Send16',
html: '<p>Hello world</p>',
});
if (error) console.error('Failed:', error.message);
else console.log('Sent:', data.id);Tasteful HTML in 5 lines — compose()
Don't want to write MJML or React Email? Pass a plain JS object and compose() returns a responsive, mobile-friendly HTML body plus a plain-text fallback. Pure function, runs anywhere, no API call needed for the render itself.
Welcome email
import { compose } from 'send16-mail';
const { html, text } = compose({
product: { name: 'Acme', link: 'https://acme.com' },
body: {
name: 'John',
intro: 'Welcome to Acme — your account is ready.',
action: {
instructions: 'Confirm your email to get started:',
button: { text: 'Confirm email', link: 'https://acme.com/verify?t=abc' },
},
outro: 'Need help? Just reply to this email.',
},
});Password reset
const { html, text } = compose({
product: { name: 'Acme' },
body: {
name: 'John',
intro: 'You requested a password reset for your Acme account.',
action: {
instructions: 'Click the button below to choose a new password:',
button: {
text: 'Reset password',
link: 'https://acme.com/reset?t=abc',
color: '#dc2626',
},
},
outro: 'If you did not request this, you can safely ignore the email.',
},
});Receipt
const { html, text } = compose({
product: { name: 'Acme' },
body: {
name: 'John',
intro: 'Thanks for your purchase! Here is your receipt.',
table: {
data: [
{ Item: 'Pro plan', Quantity: '1', Price: '$29.00' },
{ Item: 'Extra seat', Quantity: '2', Price: '$10.00' },
{ Item: 'Total', Quantity: '', Price: '$39.00' },
],
columns: { customAlignment: { Price: 'right' } },
},
outro: 'Questions about your invoice? Reply and we will help.',
},
});Compose + send in one call
await send16.compose.send({
from: 'Acme <hello@acme.com>',
to: 'user@gmail.com',
subject: 'Welcome!',
product: { name: 'Acme' },
body: { name: 'John', intro: 'Thanks for signing up.' },
});Coming from mailgen?
send16-mail's compose() takes the same { product, body } shape — drop in your existing payload and you'll get HTML out the other side. The difference: we also send the email through a hosted, deliverability-tuned pipeline (DKIM/SPF/DMARC, dedicated IPs, bounce handling, opens/clicks, automations) instead of leaving you to wire up nodemailer + SES yourself.
// Roughly: replace this
const html = mailGenerator.generate({ body: { name, intro, action } });
await transporter.sendMail({ from, to, subject, html });
// …with this
await send16.compose.send({ from, to, subject, product, body: { name, intro, action } });Why send16-mail
- Zero dependencies — 22 KB SDK, no transitives, runs anywhere
fetchexists - Edge-ready — Cloudflare Workers, Vercel Edge, Deno Deploy out of the box
- Resend-compatible API — easy migration from Resend / SendGrid / Postmark / Mailgun
- Self-hosted option — bring your own server if you want full control
- Transactional + marketing — one platform, one SDK
- Free tier — 1,000 emails/month, no credit card
Configuration
const send16 = new Send16('sk_live_your_key', {
baseUrl: 'https://api.send16.com', // default; override for self-hosted
timeout: 30_000, // ms; default 30s
});Emails
Send
const { data, error } = await send16.emails.send({
from: 'Acme <hello@acme.com>',
to: ['user@gmail.com'],
subject: 'Hello',
html: '<p>Hello world</p>',
});All options
await send16.emails.send({
from: 'Acme <hello@acme.com>',
to: ['user@gmail.com'],
cc: ['cc@example.com'],
bcc: ['bcc@example.com'],
replyTo: 'support@acme.com',
subject: 'Invoice #1234',
html: '<p>Your invoice is attached.</p>',
text: 'Your invoice is attached.',
headers: { 'X-Custom-Header': 'value' },
attachments: [
{ filename: 'invoice.pdf', content: '<base64>', contentType: 'application/pdf' },
],
tags: [{ name: 'category', value: 'invoices' }],
scheduledAt: '2026-04-01T09:00:00Z',
});Batch (up to 100)
await send16.emails.batch([
{ from: 'Acme <hi@acme.com>', to: ['a@x.com'], subject: 'Hi A', html: '<p>Hi!</p>' },
{ from: 'Acme <hi@acme.com>', to: ['b@x.com'], subject: 'Hi B', html: '<p>Hi!</p>' },
]);Contacts
await send16.contacts.create({ email: 'user@test.com', firstName: 'John' });
await send16.contacts.list({ page: 1, limit: 50 });
await send16.contacts.update('id', { firstName: 'Jane' });
await send16.contacts.delete('id');Domains
await send16.domains.list();
await send16.domains.verify('domain-id');Render (compile dashboard email content → HTML)
const { data } = await send16.render.run({
content: emailContent, // EmailContent JSON from the Send16 editor
variables: { firstName: 'John' },
});
console.log(data.html); // exact HTML the API will sendEvents (trigger automations)
await send16.events.send({
name: 'signup_completed',
contact: 'user@gmail.com',
payload: { plan: 'pro' },
});Error handling
The SDK never throws. Every method returns { data, error }:
const { data, error } = await send16.emails.send({ /* ... */ });
if (error) {
console.error(error.code); // "HTTP_422" | "TIMEOUT" | "NETWORK_ERROR" | ...
console.error(error.message);
return;
}
console.log(data.id); // non-null when error is nullTypeScript
Full types are bundled. Common imports:
import type {
SendEmailPayload,
SendEmailResponse,
Contact,
Domain,
ComposeInput,
ComposeResult,
} from 'send16-mail';Companion packages
send16-cli—send16command-line tool: send local.tsx/.mjml/.htmlfiles, manage domains/contacts, fire events.send16-editor— embeddable React block editor your users can compose emails in directly inside your app.
Links
- Dashboard — manage your account
- Create Account — get your free API key
- Documentation — API docs and guides
License
MIT