Node.js SDK
The official camelmailer package is TypeScript-first, has zero runtime dependencies, and returns a { data, error } result on every call so nothing throws for a rejected request.
Install
terminal
npm install camelmailer
Requires Node.js 18+ (native fetch). Ships both ESM and CommonJS.
Quickstart
mailer.ts
import { CamelMailer } from 'camelmailer';
const camelmailer = new CamelMailer('cm_xxxx'); // or set CAMELMAILER_API_KEY
const { data, error } = await camelmailer.emails.send({
from: 'billing@acme.com',
to: 'ada@example.com',
subject: 'Your receipt',
html_body: '<p>Thanks for your purchase.</p>',
});
if (error) throw new Error(error.code + ': ' + error.message);
console.log('Queued', data.message_id);Send with a template
Render a stored template against a template_model. Variables use Mustache-style {{ name }} syntax.
template.ts
const { data, error } = await camelmailer.emails.sendWithTemplate({
from: 'hello@acme.com',
to: 'ada@example.com',
template: 'welcome',
template_model: { name: 'Ada', product: 'Acme' },
});Error handling
Nothing throws for request failures. error is a CamelMailerError with a stable code, the API message and an HTTP statusCode. Network failures use the code NetworkError.
errors.ts
const { data, error } = await camelmailer.emails.send({ /* … */ });
if (error) {
switch (error.code) {
case 'ValidationError':
// fix the payload, do not retry
break;
case 'Unauthorized':
// rotate/check the API key
break;
case 'NetworkError':
// instance unreachable — retry with backoff
break;
default:
console.error(error.code, error.message);
}
return;
}Self-hosted instances
The client defaults to https://app.camelmailer.com. Point it at your own instance with the baseUrl option (or the CAMELMAILER_BASE_URL environment variable):
self-hosted.ts
const camelmailer = new CamelMailer('cm_xxxx', {
baseUrl: 'https://mail.example.com',
});Call CamelMailer from server code only (API routes, server actions) so the credential never reaches the browser. Full field reference: Messages API.
