Skip to content

Repository files navigation

@s-mailer/sdk

Node.js / TypeScript SDK for the S-Mailer API — send messages across SMS, email, WhatsApp and more, list sent/received messages, check your balance, and verify webhooks.

Status: pre-1.0. All resource methods are implemented; the API may still change before 1.0.0.

Requirements

  • Node.js 18+ (uses the global fetch), or a browser with fetch.

Installation

npm install @s-mailer/sdk

Authentication

Every request authenticates with your X-Client-ID / X-Client-Secret pair (from your dashboard).

import { SMailer } from '@s-mailer/sdk';

const mailer = new SMailer({
  clientId: 'CLT-XXXXXXXX',
  clientSecret: 'your-api-secret',
});

Configuration

const mailer = new SMailer({
  clientId: 'CLT-XXXXXXXX',
  clientSecret: 'your-api-secret',
  baseUrl: 'https://api.mailer.smartek.co.mz', // override the API host
  timeout: 30000,                              // per-request timeout in ms (default 30000)
  maxRetries: 2,                               // retry 429/5xx/network (default 2)
});

Retries use an exponential backoff and honour a Retry-After header on 429.

Usage

Send a message

const res = await mailer.messages.send({
  sender: 'sms-co1-xxxxxxxx',
  recipients: [
    '+258841234567',
    { phone: '+258842000001', data: { name: 'Alice' } },
  ],
  contentTemplate: 'Hi ${name}, your code is ${code}.',
  // channel: 'sms', provider: 'sms-co1',   // alternatives to `sender`
  // campaignId: 'promo-2026',
  // webhookUrl: 'https://your-app.com/webhooks/status',
});
// res.message_id, res.total_cost_tokens, ...

List and fetch messages

const sent = await mailer.messages.listOutbound({ status: 'delivered', channel: 'sms', limit: 50 });
const received = await mailer.messages.listInbound({ limit: 50 });
const one = await mailer.messages.get(messageId); // outbound or inbound; check `direction`

Retrigger / delete

await mailer.messages.retrigger(inboundId); // unlock + re-deliver a locked (unpaid) inbound
await mailer.messages.delete(messageId);    // delete an outbound or paid inbound message

Balance, profile, channels

const tokens = await mailer.balance.get();       // number
const profile = await mailer.balance.profile();  // includes webhook_signing_key
const channels = await mailer.channels.list();   // public senders + your private ones (authenticated)

Webhooks

S-Mailer signs every webhook it sends with X-Mailer-Signature: hex(HMAC-SHA256(webhook_signing_key, raw_body)). Your webhook_signing_key comes from mailer.balance.profile(). Verify over the raw request body, before parsing it.

import { webhooks } from '@s-mailer/sdk';

// Express example (raw body required)
app.post('/webhook', express.raw({ type: 'application/json' }), (req, res) => {
  const raw = req.body.toString('utf8');
  const sig = req.header('X-Mailer-Signature') ?? '';

  const event = webhooks.parse(raw, sig, signingKey); // throws on bad signature
  if (event.type === 'inbound' && !event.payment_required) {
    // handle inbound message
  } else if (event.type === 'status') {
    // handle delivery status change
  }
  res.sendStatus(200);
});

WebhookEvent is a discriminated union of InboundEvent (type: 'inbound') and StatusEvent (type: 'status').

Errors

Non-2xx responses reject with a typed error extending SMailerError, carrying the API error code and HTTP statusCode:

Status Error class error
401 AuthenticationError AUTHENTICATION_FAILED
403 ForbiddenError FORBIDDEN
400 BadRequestError / ValidationError BAD_REQUEST / VALIDATION_ERROR
402 InsufficientTokensError INSUFFICIENT_TOKENS
404 NotFoundError NOT_FOUND
429 RateLimitError (retryAfter) RATE_LIMIT_EXCEEDED
5xx ServerError INTERNAL_SERVER_ERROR

License

MIT — see LICENSE.

About

Node.js SDK for the S-Mailer API — send messages, manage webhooks, and more

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages