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
- 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);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