Skip to main content
Package: unosend · Runtime: Node.js 18+ · TypeScript: Full type support included

Installation

npm install unosend

Quick Start

import { Unosend } from 'unosend';

const unosend = new Unosend('un_your_api_key');

const { data, error } = await unosend.emails.send({
  from: 'hello@yourdomain.com',
  to: ['user@example.com'],
  subject: 'Hello from Unosend!',
  html: '<h1>Welcome!</h1><p>Thanks for signing up.</p>'
});

if (error) {
  console.error('Failed to send:', error.message);
  return;
}

console.log('Email sent:', data.id);

Configuration

import { Unosend } from 'unosend';

const unosend = new Unosend('un_your_api_key', {
  baseUrl: 'https://www.unosend.co/api/v1', // default
  timeout: 30000, // request timeout in ms (default: 30s)
});
Never hardcode your API key. Use environment variables: process.env.UNOSEND_API_KEY

Emails

Send an Email

const { data, error } = await unosend.emails.send({
  from: 'John Doe <john@yourdomain.com>',
  to: ['user@example.com'],
  subject: 'Order Confirmation',
  html: '<h1>Order #1234</h1><p>Your order has been confirmed.</p>',
  text: 'Order #1234 - Your order has been confirmed.',
  replyTo: 'support@yourdomain.com',
  cc: ['manager@yourdomain.com'],
  bcc: ['archive@yourdomain.com'],
  tags: [
    { name: 'category', value: 'order' }
  ],
  headers: {
    'X-Entity-Ref-ID': 'order-1234'
  },
  tracking: {
    open: true,
    click: true
  }
});

Send with Attachments

import fs from 'fs';

const { data, error } = await unosend.emails.send({
  from: 'billing@yourdomain.com',
  to: ['customer@example.com'],
  subject: 'Your Invoice',
  html: '<p>Please find your invoice attached.</p>',
  attachments: [
    {
      filename: 'invoice.pdf',
      content: fs.readFileSync('./invoice.pdf').toString('base64'),
      content_type: 'application/pdf'
    }
  ]
});

Send with Templates

const { data, error } = await unosend.emails.send({
  from: 'hello@yourdomain.com',
  to: ['user@example.com'],
  subject: 'Welcome, {{first_name}}!',
  template_id: 'tmpl_abc123',
  template_data: {
    first_name: 'Alice',
    company: 'Acme Inc'
  }
});

Schedule an Email

const { data, error } = await unosend.emails.send({
  from: 'hello@yourdomain.com',
  to: ['user@example.com'],
  subject: 'Scheduled Newsletter',
  html: '<h1>Weekly Digest</h1>',
  scheduled_for: '2026-03-15T09:00:00Z'
});

Send Batch Emails

const { data, error } = await unosend.emails.sendBatch([
  {
    from: 'hello@yourdomain.com',
    to: ['alice@example.com'],
    subject: 'Welcome, Alice!',
    html: '<h1>Welcome!</h1>'
  },
  {
    from: 'hello@yourdomain.com',
    to: ['bob@example.com'],
    subject: 'Welcome, Bob!',
    html: '<h1>Welcome!</h1>'
  }
]);

// data = [{ id: 'email_abc' }, { id: 'email_def' }]

Get Email Details

const { data, error } = await unosend.emails.get('email_abc123');

console.log(data.status);     // 'delivered'
console.log(data.opened_at);  // '2026-02-28T10:30:00Z'
console.log(data.clicked_at); // null

List Emails

const { data, error } = await unosend.emails.list({
  limit: 50,
  status: 'delivered'
});

for (const email of data.data) {
  console.log(`${email.to}${email.status}`);
}

Domains

Add and Verify a Domain

// Create domain
const { data: domain } = await unosend.domains.create({
  domain: 'yourdomain.com'
});

console.log('Add these DNS records:', domain.dns_records);
// [
//   { type: 'TXT', name: 'unosend._domainkey', value: 'v=DKIM1; k=rsa; p=...' },
//   { type: 'MX', name: 'send', value: '10 mail.unosend.co' },
//   { type: 'TXT', name: 'send', value: 'v=spf1 include:_spf.unosend.co ...' }
// ]

// After adding DNS records, verify
const { data: verified } = await unosend.domains.verify(domain.id);
console.log('Verified:', verified.verified); // true

List Domains

const { data } = await unosend.domains.list();

for (const domain of data.data) {
  console.log(`${domain.domain} — verified: ${domain.verified}`);
}

Contacts & Audiences

Create an Audience

const { data: audience } = await unosend.audiences.create({
  name: 'Newsletter Subscribers'
});

Add a Contact

const { data: contact } = await unosend.contacts.create(audience.id, {
  email: 'user@example.com',
  first_name: 'Alice',
  last_name: 'Smith',
  metadata: {
    plan: 'pro',
    signed_up: '2026-01-15'
  }
});

List Contacts

const { data } = await unosend.contacts.list(audience.id, {
  limit: 100
});

console.log(`Total: ${data.total} contacts`);

SMS

Send an SMS

const { data, error } = await unosend.sms.send({
  to: '+14155551234',
  message: 'Your verification code is 384729. Expires in 10 minutes.'
});

console.log('SMS sent:', data.id);
console.log('Cost:', data.cost); // '$0.016'

Send Batch SMS

const { data, error } = await unosend.sms.sendBatch({
  messages: [
    { to: '+14155551234', message: 'Your code is 123456' },
    { to: '+447700900123', message: 'Your code is 654321' }
  ]
});

WhatsApp

Send a Template Message

const { data, error } = await unosend.whatsapp.send({
  to: '+919876543210',
  type: 'template',
  template: 'order_update',
  language: 'en',
  variables: ['Alice', 'ORD-1234']
});

Send a Chat Message

const { data, error } = await unosend.whatsapp.send({
  to: '+919876543210',
  type: 'chat',
  message: 'Your order has shipped! Track at: https://track.example.com/1234'
});

Webhooks

Create a Webhook

const { data: webhook } = await unosend.webhooks.create({
  url: 'https://yourapp.com/api/unosend-webhook',
  events: ['email.delivered', 'email.bounced', 'email.opened', 'email.clicked']
});

console.log('Signing secret:', webhook.signing_secret);

Validation

Validate an Email

const { data } = await unosend.validation.validateEmail({
  email: 'user@example.com'
});

console.log(data.valid);        // true
console.log(data.disposable);   // false
console.log(data.has_mx);       // true
console.log(data.confidence);   // 95

Error Handling

The SDK returns { data, error } on every call. Errors have a consistent shape:
const { data, error } = await unosend.emails.send({
  from: 'hello@yourdomain.com',
  to: ['user@example.com'],
  subject: 'Hello',
  html: '<h1>Hello</h1>'
});

if (error) {
  switch (error.statusCode) {
    case 401:
      console.error('Invalid API key');
      break;
    case 422:
      console.error('Validation error:', error.message);
      break;
    case 429:
      console.error('Rate limited. Retry after:', error.retryAfter, 'seconds');
      break;
    default:
      console.error('Error:', error.message);
  }
  return;
}

console.log('Sent:', data.id);

Framework Examples

Next.js (App Router)

// app/api/send/route.ts
import { Unosend } from 'unosend';
import { NextResponse } from 'next/server';

const unosend = new Unosend(process.env.UNOSEND_API_KEY!);

export async function POST(request: Request) {
  const { email, name } = await request.json();

  const { data, error } = await unosend.emails.send({
    from: 'welcome@yourdomain.com',
    to: [email],
    subject: `Welcome, ${name}!`,
    html: `<h1>Welcome, ${name}!</h1><p>Thanks for joining.</p>`
  });

  if (error) {
    return NextResponse.json({ error: error.message }, { status: 500 });
  }

  return NextResponse.json({ id: data.id });
}

Express.js

import express from 'express';
import { Unosend } from 'unosend';

const app = express();
const unosend = new Unosend(process.env.UNOSEND_API_KEY!);

app.post('/send-email', async (req, res) => {
  const { data, error } = await unosend.emails.send({
    from: 'hello@yourdomain.com',
    to: [req.body.email],
    subject: req.body.subject,
    html: req.body.html
  });

  if (error) return res.status(500).json({ error: error.message });
  res.json({ id: data.id });
});

app.listen(3000);

TypeScript Types

The SDK exports all types for full IntelliSense support:
import type {
  SendEmailRequest,
  SendEmailResponse,
  Email,
  Domain,
  Contact,
  Audience,
  Webhook,
  SmsMessage,
  WhatsAppMessage,
  ValidationResult,
  UnosendError
} from 'unosend';

Environment Variables

.env
UNOSEND_API_KEY=un_your_api_key

Full API Reference

See all available endpoints and parameters