JavaScript / Node.js SDK
The core ArtaMail SDK for any JavaScript or Node.js environment.
Installation
pnpm add @artatol/artamail-sdkQuick Start
1import { ArtaMail } from '@artatol/artamail-sdk';23const artamail = new ArtaMail({4 apiKey: process.env.ARTAMAIL_API_KEY5});67// Send an email8const result = await artamail.send({9 to: '[email protected]',10 template: 'welcome',11 data: { name: 'John' }12});1314console.log('Email sent:', result.id);15console.log('Test mode:', result.testMode);Configuration
const artamail = new ArtaMail({ // Required apiKey: 'am_live_sk_xxx', // Optional baseUrl: 'https://artamail.artatol.net', // Custom API URL timeout: 30000, // Request timeout (ms) retries: 3 // Retry attempts});| Option | Type | Default | Description |
|---|---|---|---|
apiKey | string | — | Your ArtaMail API key (required) |
baseUrl | string | https://artamail.artatol.net | API base URL |
timeout | number | 30000 | Request timeout in milliseconds |
retries | number | 3 | Number of retry attempts |
Identity variables (auto-injected)
At send time ArtaMail fills brand, legal_entity, legal_address, and legal_detailsfrom Settings → Brand & compliance. Pass in data only to override.
company field and {{company}} template variable are legacy aliases for brand. They still work today but may be removed in a future release.Configure identity in Settings → Brand & compliance. Use {{legal_address}} and {{legal_details}} in template footers for postal address and registration IDs.
Sending Emails
Single Email
const result = await artamail.send({ to: '[email protected]', template: 'welcome', data: { name: 'John', verifyUrl: 'https://example.com/verify/abc123' }, // Optional from: '[email protected]', // Custom sender (must be verified) fromName: 'My App', // Sender display name replyTo: '[email protected]', // Reply-to address priority: 'high', // 'high' | 'normal' | 'low' subtypeSlug: 'product-updates', // operational subtype — enforces consent});Batch Emails
Send up to 1000 emails in a single request:
const result = await artamail.sendBatch({ emails: [ { to: '[email protected]', template: 'notification', data: { message: 'Hello' } }, { to: '[email protected]', template: 'notification', data: { message: 'Hello' } } ]});// Result: { queued: 2, failed: 0, results: [...], testMode: false }Get Email Status
const email = await artamail.getEmail('email-uuid');console.log(email.status); // queued | sending | sent | delivered | bounced | failedconsole.log(email.deliveredAt);console.log(email.openedAt);Contacts
// Create or update contactawait artamail.upsertContact({ email: '[email protected]', name: 'John Doe', locale: 'en', data: { plan: 'premium' }, lists: ['customers'], // segmentation only optInSubtypeSlugs: ['weekly-digest'],});// Get contactconst contact = await artamail.getContact('[email protected]');// Update contactawait artamail.updateContact('[email protected]', { name: 'Jane Doe', data: { plan: 'enterprise' }});// Permanent delete — PII, subscriptions, and list memberships removedawait artamail.deleteContact('[email protected]');deleteContact permanently erases the contact profile, all subscription preferences, and list memberships, and anonymizes stored email content. Cannot be undone — use upsertContactto add them again as a new contact. Org admins can also run erasure from Settings → GDPR & Privacy (POST /api/gdpr/delete), which anonymizes email history even when no contact row exists.
lists are static list slugs (append on upsert). For explicit add/remove with validation errors, use modifyContactLists. Smart-list membership is not returned on contacts — see Contact Lists API.
Contact lists
const lists = await artamail.listContactLists();const vip = await artamail.getContactList('vip');await artamail.createContactList({ name: 'VIP customers', slug: 'vip',});const membership = await artamail.modifyContactLists('[email protected]', { add: ['vip'], remove: ['trial'],});await artamail.addContactToLists('[email protected]', ['newsletter']);Subscriptions & Consent
Grant subtype opt-in, handle double opt-in, and read consent state. See the full guide.
// Opt-in with optional confirm email (when org DOI is enabled)await artamail.optInContact({ email: '[email protected]', optInSubtypeSlugs: ['weekly-digest'], sendConfirmEmail: true,});// Or handle DOI manuallyconst contact = await artamail.upsertContact({ email: '[email protected]', optInSubtypeSlugs: ['weekly-digest'],});if (contact.confirmUrl) { await artamail.sendConsentConfirmEmail({ to: contact.email, confirmUrl: contact.confirmUrl, name: contact.name, });}// Skip double opt-in (import / admin)await artamail.upsertContact({ email: '[email protected]', optInSubtypeSlugs: ['weekly-digest'], doubleOptIn: false,});// List subscription types (includes labelI18n per locale on subtypes)const types = await artamail.listSubscriptionTypes();// Custom preference UI — fetch resolved copy for contact localeconst res = await fetch(`https://artamail.artatol.net/api/u/${token}/data`);const data: import('@artatol/artamail-sdk').PreferencePageData = await res.json();console.log(data.locale, data.copy.title, data.subtypes[0].label);// Read per-subtype consentconst prefs = await artamail.getContactSubscriptionPreferences('[email protected]');Preference page strings are configured in the dashboard and resolved from contacts.locale. See Preferences Data API.
Templates
// List all templatesconst templates = await artamail.listTemplates();for (const template of templates) { console.log(template.slug, template.name); console.log('Variables:', template.variables);}// Get single templateconst template = await artamail.getTemplate('welcome');Sender Addresses
const senders = await artamail.listSenderAddresses();// Find default senderconst defaultSender = senders.find(s => s.isDefault);// Use custom senderawait artamail.send({ to: '[email protected]', template: 'welcome', from: senders[0].email, fromName: senders[0].name});Error Handling
import { ArtaMailError, ValidationError, AuthenticationError, RateLimitError, NotFoundError} from '@artatol/artamail-sdk';try { await artamail.send({ ... });} catch (error) { if (error instanceof ValidationError) { console.error('Invalid input:', error.details); } else if (error instanceof AuthenticationError) { console.error('Invalid API key'); } else if (error instanceof RateLimitError) { console.error('Rate limited, retry after:', error.retryAfter); } else if (error instanceof NotFoundError) { console.error('Resource not found'); }}TypeScript
The SDK is written in TypeScript and provides full type definitions:
import type { ArtaMailConfig, SendEmailOptions, SendEmailResult, BatchEmailOptions, Contact, Template, SenderAddress, SubscriptionType, ContactSubscriptionPreference, OptInContactOptions, SendConsentConfirmEmailOptions} from '@artatol/artamail-sdk';