simplysend
v6.0.0
Published
Official Node.js SDK for Simply Send - Send transactional and marketing emails
Maintainers
Readme
Features
- Strict Separation of Concerns: Exposes three dedicated client classes for Transactional API, Marketing API, and Web Setup API.
- Lightweight & Dependency-free: Uses native
fetch(requires Node.js 22+). No heavy dependencies. - Dual module support: Pre-built ESM (ES Modules) and CJS (CommonJS) formats.
- Strongly Typed: Full TypeScript support with detailed interfaces.
- Smart Attachments: Pass raw Node.js
Bufferobjects, and the SDK will automatically base64-encode them for you.
Installation
npm install simplysendWhat's New in v6
v6 aligns the Web Setup SDK with the current WAPI contract and adds typed helpers for domain features.
- Create domains with
POST. - Partially update domain groups, contacts, subscription groups, templates, compliance templates, and webhooks with
PATCH. - Configure and verify click tracking and inbound email with
client.domainshelpers.
Migrating from v5
This is a breaking WAPI change. Upgrade the SDK and deploy the corresponding Web Setup API changes together:
npm install simplysend@^6.0.0If you call WAPI directly rather than through this SDK, update the following request methods:
| Operation | v5 and earlier | v6 |
| --- | --- | --- |
| Create domain | PUT /web-setup/domains | POST /web-setup/domains |
| Update a domain group | PUT | PATCH |
| Update a contact | PUT | PATCH |
| Update a subscription group or subscription | PUT | PATCH |
| Update a template, compliance template, or webhook | PUT | PATCH |
The existing SDK method names are unchanged. Update the package version; the SDK sends the correct v6 method automatically.
await client.domains.configureClickTracking(domainId, true);
await client.domains.verifyClickTracking(domainId);
await client.domains.configureInboundEmail(domainId, {
enabled: true,
inboxSubdomain: 'inbound',
});
await client.domains.verifyInboundEmail(domainId);Client Initialization
To connect to SimplySend, you will initialize the specialized client class corresponding to the API features you need. Each constructor requires your Account ID and the respective API Key (retrieved from the Settings page in your SimplySend Dashboard).
1. SimplySendTransactionalClient
Used to send transactional emails (OTPs, receipts, alerts).
import { SimplySendTransactionalClient } from 'simplysend';
const client = new SimplySendTransactionalClient({
accountId: 'ss_acc_123456',
apiKey: 'ss_api_key_abcdef'
});2. SimplySendMarketingClient
Used to send newsletters or marketing campaigns.
import { SimplySendMarketingClient } from 'simplysend';
const client = new SimplySendMarketingClient({
accountId: 'ss_acc_123456',
apiKey: 'ss_api_key_abcdef'
});3. SimplySendWebSetupClient
Used for resource management (domains, templates, subscribers, webhooks).
import { SimplySendWebSetupClient } from 'simplysend';
const client = new SimplySendWebSetupClient({
accountId: 'ss_acc_123456',
apiKey: 'ss_api_key_abcdef'
});Usage Examples
1. Send a Transactional Email
import { SimplySendTransactionalClient, SendTransactionalEmailResponse } from 'simplysend';
const client = new SimplySendTransactionalClient({
accountId: 'ss_acc_123',
apiKey: 'ss_api_key_abc'
});
try {
const response: SendTransactionalEmailResponse = await client.email.send({
from: 'Acme Welcome Team <[email protected]>', // Verified domain email with display name
to: '[email protected]', // Valid email or "Display Name <[email protected]>"
cc: '[email protected]', // Optional: CC recipient(s)
bcc: '[email protected]', // Optional: BCC recipient(s)
// Note: BCC is mutually exclusive with TO and CC. Use either TO/CC or BCC, not both.
subject: 'Welcome!', // UTF-8 text, max 998 chars per line
html: '<h1>Hello, World!</h1><p>Thank you for signing up.</p>', // Combined attachments: max 2MB
text: 'Hello, World! Thank you for signing up.', // Optional: Plain text version for accessibility
replyTo: '[email protected]', // Optional: "Display Name <[email protected]>" or "[email protected]>"
enableClickTracking: true, // Optional: Boolean for link tracking
enableOpenTracking: true, // Optional: Boolean for open tracking
attachments: [
{
name: 'invoice.pdf', // File name with extension
contentType: 'application/pdf', // MIME type (PDF, PNG, JPG, CSV, DOCX)
content: Buffer.from('PDF content here...'), // Automatically encoded to base64 by SDK
}
]
});
console.log('Transactional email sent. Message ID:', response.data?.messageId);
} catch (error) {
console.error('Failed to send email:', error.message);
}2. Send a Marketing Email
import { SimplySendMarketingClient, SendMarketingEmailResponse } from 'simplysend';
const client = new SimplySendMarketingClient({
accountId: 'ss_acc_123',
apiKey: 'ss_api_key_xyz'
});
try {
const response: SendMarketingEmailResponse = await client.email.send({
from: '[email protected]',
to: '[email protected]',
// Note: BCC and CC are not supported for marketing emails. Use the "to" field only.
subject: 'June Newsletter',
html: '<h1>Our monthly updates</h1><p>Here is what is new...</p>{{company_address_html}}{{unsubscribe_email_html}}',
subscriptionGroupId: 'sub_group_123', // Required
campaignId: 'camp_abc_456', // Optional campaign tracking
enableClickTracking: true,
enableOpenTracking: true,
});
console.log('Marketing email sent. Message ID:', response.data?.messageId);
} catch (error) {
console.error('Failed to send marketing email:', error.message);
}3. Manage Web Setup Resources (Domains, Contacts, Subscription Groups, Subscribers)
import { SimplySendWebSetupClient } from 'simplysend';
const client = new SimplySendWebSetupClient({
accountId: 'ss_acc_123',
apiKey: 'ss_api_key_789'
});
// 1. Add a domain to verify
const newDomain = await client.domains.create({
domain: 'mycompany.com',
useCaseId: 'tx-us-east-1'
});
console.log('Verification records:', newDomain.dnsRecords);
// Publish those records, then verify the domain. If the apex already has an SPF
// TXT from Google Workspace, Microsoft 365, or another provider, merge Simply Send
// into that record — do not add a second v=spf1 TXT.
// https://simplysend.email/docs/guide/domain-verification/spf
// https://simplysend.email/blog/setup-spf-record
// Optional domain features are configured through the Web Setup API:
// PATCH /web-setup/domains/{domainId}/features/click-tracking
// PATCH /web-setup/domains/{domainId}/features/inbound-email
// POST /web-setup/domains/{domainId}/features/{feature}/verify
// Each operation has its own API reference page. See:
// https://simplysend.email/docs/api/domains/click-tracking/configure
// https://simplysend.email/docs/api/domains/click-tracking/verify
// https://simplysend.email/docs/api/domains/inbound-email/configure
// https://simplysend.email/docs/api/domains/inbound-email/verify
// Update a domain group:
// PATCH /web-setup/domain-groups/{groupId}
// https://simplysend.email/docs/api/domain-groups/update
// 2. Create a Contact profile globally in the Contacts Directory
// Note: Contacts must exist globally before they can be subscribed to groups.
const contactResponse = await client.contacts.createContact({
email: '[email protected]',
firstName: 'Alice',
lastName: 'Smith',
phone: '+1234567890',
globalStatus: 'active',
consentMethod: 'single_opt_in',
consentDetails: 'User checked physical agreement box during customer onboarding'
});
console.log('Contact created:', contactResponse.data.contact);
// 3. Create a Subscription Group (audience list)
const groupResponse = await client.contacts.createSubscriberGroup({
name: 'Newsletter List',
description: 'Monthly updates newsletter list'
});
const subscriptionGroupId = groupResponse.data.group.subscriptionGroupId!;
console.log('Group created:', groupResponse.data.group);
// 4. Subscribe the contact to the group list
const subscriptionResponse = await client.contacts.addSubscriber(subscriptionGroupId, {
email: '[email protected]',
isActive: true,
consentMethod: 'single_opt_in',
consentDetails: 'Footer newsletter subscription form'
});
console.log('Subscribed to group:', subscriptionResponse.data.subscriber);
// 5. Register a Webhook to subscribe to inbound email received events
const newWebhook = await client.webhooks.create({
url: 'https://your-server.com/webhooks/simply-send',
events: ['email_received'],
description: 'Webhook to receive inbound support emails'
});
console.log('Webhook created successfully with ID:', newWebhook.webhookId);Client Configurations
When initializing, each client class expects exactly the same configuration properties:
| Property | Type | Required | Description |
| :--- | :--- | :--- | :--- |
| accountId | string | Yes | Your unique SimplySend Account ID, found on the Account page of the SimplySend website. |
| apiKey | string | Yes | The SimplySend API Key for authentication, found on the API Keys page of the SimplySend website. |
Error Handling
The SDK exposes descriptive error classes to help you debug integration issues:
import { SimplySendTransactionalClient, SimplySendHttpError, SimplySendValidationError } from 'simplysend';
try {
// 1. Instantiation validation (throws locally)
const client = new SimplySendTransactionalClient({
accountId: '', // Throws validation error locally
apiKey: 'ss_api_key_...'
});
// 2. Request parameter validation (throws locally)
await client.email.send({
from: '[email protected]',
to: '', // Throws validation error locally
subject: 'Hello',
html: '...'
});
} catch (error) {
if (error instanceof SimplySendValidationError) {
// Local validation failed (field check did not hit the network)
console.error('Validation failed on field:', error.field); // e.g. "accountId", "to"
console.error('Message:', error.message);
} else if (error instanceof SimplySendHttpError) {
// API server responded with a non-2xx status code
console.error('HTTP Status:', error.statusCode); // e.g. 403, 400
console.error('Error Code:', error.reasonCode); // e.g. "ACCOUNT_SUSPENDED"
console.error('Message:', error.message);
} else {
// Generic connection/network failure
console.error('Network/Request Error:', error.message);
}
}BCC Usage
The SDK supports BCC (Blind Carbon Copy) for transactional emails. BCC recipients are hidden from other recipients.
BCC-only Send
To send a BCC-only email (no visible TO or CC recipients), provide only the bcc field:
const response = await client.email.send({
from: '[email protected]',
bcc: '[email protected]',
subject: 'Subject',
html: '<p>Email content</p>'
});BCC with TO/CC
The SDK enforces that BCC is mutually exclusive with TO and CC. You cannot use BCC together with TO or CC - the SDK will throw a validation error:
// This will throw a SimplySendValidationError
await client.email.send({
from: '[email protected]',
to: '[email protected]',
bcc: '[email protected]', // ❌ Error: BCC cannot be used with TO
subject: 'Subject',
html: '<p>Email content</p>'
});Multiple BCC Recipients
You can pass an array of BCC recipients:
const response = await client.email.send({
from: '[email protected]',
bcc: ['[email protected]', '[email protected]'],
subject: 'Subject',
html: '<p>Email content</p>'
});Marketing Email Limitations
Marketing emails have different requirements than transactional emails for compliance reasons:
No BCC or CC Support
Marketing emails do not support BCC or CC recipients. This is because:
- BCC addresses cannot be tracked for unsubscribes
- Consent verification requires visible recipient information
- RFC 8058 compliance requires clear unsubscribe mechanisms
Always use the to field for marketing emails:
// ✅ Correct - Marketing email with TO only
await marketingClient.email.send({
from: '[email protected]',
to: '[email protected]',
subject: 'Newsletter',
html: '<p>Content</p>',
subscriptionGroupId: 'group_123'
});
// ❌ Error - BCC not supported for marketing emails
await marketingClient.email.send({
from: '[email protected]',
bcc: '[email protected]', // Will throw validation error
subject: 'Newsletter',
html: '<p>Content</p>',
subscriptionGroupId: 'group_123'
});Domain authentication
Before sending, publish the DNS records returned by domains.create and verify the domain in the dashboard. A domain may have only one SPF TXT record. If Google Workspace, Microsoft 365, or another provider already published SPF, merge Simply Send into that record — do not add a second v=spf1 line.
License
MIT
