Package Exports
- @sendmailos/sdk
- @sendmailos/sdk/react
Readme
@sendmailos/sdk
Official JavaScript/TypeScript SDK for SendMailOS email API.
Installation
npm install @sendmailos/sdk
# or
yarn add @sendmailos/sdk
# or
pnpm add @sendmailos/sdkQuick Start
import { SendMailOS } from '@sendmailos/sdk';
const client = new SendMailOS('sk_live_your_api_key');
// Send a transactional email
await client.emails.send({
to: 'user@example.com',
fromName: 'Your Company',
fromEmail: 'hello@yourcompany.com',
subject: 'Welcome!',
html: '<h1>Hello!</h1><p>Welcome to our platform.</p>'
});Features
- Type-safe: Full TypeScript support with exported types
- Lightweight: Zero dependencies for core SDK
- Industry Templates: 50+ pre-built templates for different industries
- Agency Workspaces: Manage multiple clients from one account
- Pixel Tracking: Track website visitors and link to email campaigns
- React Components: Pre-built components and hooks
- Webhook Verification: Secure signature verification utilities
- Error Handling: Custom error classes for different scenarios
API Reference
Emails
// Send transactional email
await client.emails.send({
to: 'user@example.com',
subject: 'Hello!',
html: '<h1>Welcome!</h1>',
fromName: 'Acme',
fromEmail: 'hello@acme.com',
});
// Send with template
await client.emails.sendTemplate({
to: 'user@example.com',
templateId: 'tmpl_welcome',
variables: { firstName: 'John' }
});Subscribers
// Create subscriber
const { subscriber } = await client.subscribers.create({
email: 'user@example.com',
firstName: 'John',
tags: ['newsletter', 'premium']
});
// List subscribers
const { subscribers, total } = await client.subscribers.list({
limit: 50,
offset: 0
});Campaigns
// Send campaign
await client.campaigns.send({
name: 'Weekly Newsletter',
subject: 'What\'s new this week',
fromName: 'Company Newsletter',
fromEmail: 'news@company.com',
html: '<h1>Hello {{first_name}}!</h1>',
tags: ['newsletter'] // Filter by subscriber tags
});Domains
// Add sending domain
const { domain } = await client.domains.create({
domain: 'yourcompany.com'
});
console.log('DNS Records to add:', domain.dnsRecords);Organization & Industries
Set your industry during onboarding to get pre-built templates and workflows.
import { SendMailOS, INDUSTRIES } from '@sendmailos/sdk';
const client = new SendMailOS('sk_live_...');
// Get current organization
const org = await client.organization.get();
// Set industries (multi-select)
await client.organization.setIndustries(['ecommerce', 'saas']);
// Convert to agency account (enables workspaces)
await client.organization.convertToAgency();
// Available industries (50+)
console.log(INDUSTRIES);
// { hotels: 'Hotels & Hospitality', restaurants: 'Restaurants & Food Service', ... }Supported Industries
Hotels, Restaurants, Gyms, Travel Agencies, Real Estate, Schools, E-commerce, Dentists, Car Dealerships, Events, Beauty Salons, Law Firms, Non-Profits, SaaS, Recruitment, Insurance, Online Courses, Municipalities, Personal Trainers, Influencers, Doctors/Clinics, Nightclubs, Coworking, Wedding Planners, Art Galleries, Car Rentals, Podcasters, Consultants, Bakeries, Veterinarians, Airbnb Hosts, Accountants, Developers, Musicians, Spas, Bookstores, Cleaning Services, Churches, Graphic Designers, Coffee Shops, Florists, Political Campaigns, Libraries, Taxis/Limos, Home Inspectors, Photographers, Universities, Fashion, Nutritionists, Startups
Agency Workspaces
Agencies can manage multiple clients from one account, each with isolated data.
// Convert to agency account first
await client.organization.convertToAgency();
// Create client workspaces
const pizzaPlace = await client.workspaces.create({
name: 'Pizza Palace',
industry: 'restaurants',
import_templates: true // Auto-import restaurant templates
});
const gym = await client.workspaces.create({
name: 'FitLife Gym',
industry: 'gyms',
import_templates: true
});
// List all clients
const { workspaces } = await client.workspaces.list();
for (const ws of workspaces) {
console.log(`${ws.name}: ${ws.stats?.subscribers} subscribers`);
}
// Get detailed stats
const details = await client.workspaces.get(pizzaPlace.id);
console.log(details.stats);
// { total_subscribers: 1200, active_subscribers: 1150, total_campaigns: 24, ... }
// Invite client to view reports
await client.workspaces.inviteClient(pizzaPlace.id, 'owner@pizzapalace.com');Pixel Tracking
Track website visitors and connect their behavior to email campaigns.
Basic Setup
import { SendmailPixel } from '@sendmailos/sdk';
const pixel = new SendmailPixel({
token: 'pk_live_your_public_key',
debug: false // Set true for console logging
});
pixel.init();Track Events
// Track custom events
pixel.track('button_clicked', { button_id: 'cta-signup' });
// Track page views (called automatically on init)
pixel.pageView();
// Identify a visitor by email
pixel.identify('user@example.com', {
first_name: 'John',
plan: 'premium'
});Privacy Controls
// Opt out of tracking (e.g., user declines cookies)
pixel.optOut();
// Opt back in
pixel.optIn();
// Check opt-out status
if (pixel.isOptedOut()) {
console.log('Tracking disabled');
}
// Reset identity (e.g., on logout)
pixel.reset();Global smp() Function
For script tag usage, use createGlobalPixel to set up a global smp() function:
import { createGlobalPixel } from '@sendmailos/sdk';
createGlobalPixel({ token: 'pk_live_...' });
// Now use anywhere:
smp('track', 'event_name', { property: 'value' });
smp('identify', 'user@example.com');
smp('optOut');
smp('optIn');React Pixel Hooks
import { usePixel, usePageTracking, useIdentifyOnLogin } from '@sendmailos/sdk/react';
// Basic usage
function MyComponent() {
const { track, identify, optOut } = usePixel('pk_live_...');
return (
<button onClick={() => track('button_clicked', { id: 'cta' })}>
Click Me
</button>
);
}
// Auto page tracking (Next.js App Router)
function Layout({ children }) {
const pathname = usePathname();
usePageTracking('pk_live_...', pathname);
return <>{children}</>;
}
// Auto identify on login
function App() {
const { user } = useAuth();
useIdentifyOnLogin('pk_live_...', user?.email, {
first_name: user?.firstName,
plan: user?.plan
});
return <Main />;
}Data Attributes
Track clicks without JavaScript using HTML data attributes:
<button data-smp-track="signup_clicked">Sign Up</button>
<button
data-smp-track="button_clicked"
data-smp-track-button-id="cta-main"
data-smp-track-variant="blue"
>
Get Started
</button>React Integration
import { SendMailOSProvider, SubscribeForm } from '@sendmailos/sdk/react';
function App() {
return (
<SendMailOSProvider publicKey="pk_live_...">
<SubscribeForm
tags={['newsletter']}
onSuccess={() => console.log('Subscribed!')}
buttonText="Join Newsletter"
/>
</SendMailOSProvider>
);
}Custom Form with Hook
import { useSubscribe } from '@sendmailos/sdk/react';
function CustomForm() {
const { subscribe, isLoading, error, isSuccess } = useSubscribe();
const [email, setEmail] = useState('');
const handleSubmit = async (e) => {
e.preventDefault();
await subscribe({ email, tags: ['newsletter'] });
};
if (isSuccess) return <p>Thanks for subscribing!</p>;
return (
<form onSubmit={handleSubmit}>
<input
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
/>
<button disabled={isLoading}>
{isLoading ? 'Subscribing...' : 'Subscribe'}
</button>
{error && <p>{error.message}</p>}
</form>
);
}Webhook Verification
import { verifyWebhookSignature } from '@sendmailos/sdk';
app.post('/webhooks', (req, res) => {
const isValid = verifyWebhookSignature({
payload: JSON.stringify(req.body),
signature: req.headers['x-sendmailos-signature'],
timestamp: req.headers['x-sendmailos-timestamp'],
secret: process.env.WEBHOOK_SECRET
});
if (!isValid) {
return res.status(401).json({ error: 'Invalid signature' });
}
// Process webhook event
const event = req.body;
console.log('Event:', event.type);
res.status(200).json({ received: true });
});Error Handling
import { SendMailOS, SendMailOSError, RateLimitError } from '@sendmailos/sdk';
try {
await client.emails.send({ ... });
} catch (error) {
if (error instanceof RateLimitError) {
console.log(`Rate limited. Retry after ${error.retryAfter}s`);
} else if (error instanceof SendMailOSError) {
console.log(`Error: ${error.message} (${error.code})`);
}
}Security
- Never expose secret keys (
sk_*) in client-side code - Use public keys (
pk_*) for React components - Verify webhook signatures to prevent spoofing
- Use environment variables for API keys
License
MIT