@smsgist/node
v1.1.0
Published
Official Node.js SDK for the SMSGist messaging platform
Downloads
210
Maintainers
Readme
@smsgist/node
Official Node.js SDK for the SMSGist messaging platform.
- TypeScript-first — full type definitions included
- Zero dependencies — only Node.js built-ins (
crypto,https) - Dual format — works with both
require()andimport - Node >= 18 — uses built-in
cryptofor AES-256-CBC authentication
Installation
npm install @smsgist/nodeQuick Start
import { SMSGist } from '@smsgist/node';
const client = new SMSGist({
clientId: process.env.SMSGIST_CLIENT_ID,
clientSecret: process.env.SMSGIST_CLIENT_SECRET,
appKey: process.env.SMSGIST_APP_KEY,
});
// Send SMS
const res = await client.sms.send({
senderId: 'MyApp',
recipients: ['+233245972246'],
message: 'Hello from SMSGist!',
});
console.log(res.messageId, res.status);Configuration
Create a client by passing config directly or using environment variables:
const client = new SMSGist({
clientId: 'your-client-id', // or SMSGIST_CLIENT_ID env var
clientSecret: 'your-client-secret', // or SMSGIST_CLIENT_SECRET env var
appKey: 'your-32-byte-app-key', // or SMSGIST_APP_KEY env var (16, 24, or 32 bytes)
baseUri: 'https://api.smsgist.com', // or SMSGIST_URI env var
timeout: 30000, // HTTP timeout in ms (default: 30s)
mode: 'live', // 'live' | 'test' | 'dryrun'
testPhone: '+233200000000', // redirect SMS in test/dryrun mode
testEmail: '[email protected]', // redirect emails in test/dryrun mode
});With environment variables only:
const client = new SMSGist(); // reads from SMSGIST_CLIENT_ID, SMSGIST_CLIENT_SECRET, SMSGIST_APP_KEYSMS
Send SMS
const res = await client.sms.send({
senderId: 'MyApp',
recipients: ['+233245972246', '+233201234567'],
message: 'Hello!',
idempotencyKey: 'unique-key-123', // optional: prevent duplicate sends
});
console.log(res.messageId); // "9b1deb4d-3b7d-..."
console.log(res.status); // "queued"
console.log(res.recipientsCount); // 2
console.log(res.totalCost); // 0.06Send OTP
const res = await client.sms.sendOtp({
recipients: ['+233245972246'],
message: 'Your verification code is 482916',
senderId: 'MyApp',
});const res = await client.email.send({
from: 'My App',
recipients: ['[email protected]'],
subject: 'Welcome!',
message: '<h1>Hello</h1><p>Welcome to our platform.</p>',
contentType: 'html', // 'html' (default) or 'text'
replyTo: '[email protected]',
noTracking: true,
attachments: [
{ filename: 'invoice.pdf', data: base64EncodedData },
],
});contentType defaults to 'html' when omitted (backward compatible). Pass
'text' to send a plain-text body. Set route: 'otp' to deliver via the
high-priority OTP queue.
Message Operations
// Get delivery status
const status = await client.messages.getStatus('message-id');
console.log(status.delivered, status.pending, status.failed);
// Retry a failed message
const res = await client.messages.retry('message-id');Credit Balance
const balance = await client.credits.getBalance();
console.log(balance.available, balance.reserved, balance.currency); // 150.50 10.00 "GHS"Fluent Builder API
An alternative chainable API that mirrors the Go and PHP SDKs:
// SMS
const res = await client.send('sms')
.to('+233245972246')
.from('MyApp')
.message('Hello!')
.idempotencyKey('msg-001')
.exec();
// SMS with OTP priority
const res = await client.send('sms')
.to('+233245972246')
.from('MyApp')
.messageOtp('Your code is 123456')
.exec();
// Email
const res = await client.send('email')
.to('[email protected]')
.from('My App')
.subject('Welcome')
.message('<h1>Hello</h1>')
.replyTo('[email protected]')
.noTracking()
.exec();Email content types
For email, prefer the explicit body helpers over the bare .message() —
they set the content_type the server uses to render the message:
// HTML email (content_type: 'html')
await client.send('email').to('[email protected]').subject('Hi')
.messageHtml('<h1>Hello</h1>').exec();
// HTML OTP email — routed to the high-priority OTP queue (route: 'otp')
await client.send('email').to('[email protected]').subject('Your code')
.messageHtmlOtp('<p>Your code is <b>482916</b></p>').exec();
// Plain-text email (content_type: 'text')
await client.send('email').to('[email protected]').subject('Hi')
.messagePlainText('Hello in plain text').exec();
// Plain-text OTP email (content_type: 'text', route: 'otp')
await client.send('email').to('[email protected]').subject('Your code')
.messagePlainTextOtp('Your code is 482916').exec();| Method | content_type | route |
| --- | --- | --- |
| messageHtml(body) | html | — |
| messageHtmlOtp(body) | html | otp |
| messagePlainText(body) | text | — |
| messagePlainTextOtp(body) | text | otp |
The legacy .message() / .messageOtp() helpers still work for email and
default content_type to html; .messageOtp() also routes via otp. These
helpers add no content_type for SMS.
Webhooks
Verify and parse incoming webhook payloads:
import { Webhook, Events } from '@smsgist/node';
// Verify signature (HMAC-SHA256 + 5-min replay protection)
const isValid = Webhook.verifySignature({
body: rawBody,
signature: req.headers['x-smsgist-signature'],
timestamp: req.headers['x-smsgist-timestamp'],
secret: 'your-webhook-secret',
});
if (isValid) {
const event = Webhook.parse(rawBody);
switch (event.event) {
case Events.MESSAGE_DELIVERED:
console.log(`Delivered to ${event.recipient}`);
break;
case Events.MESSAGE_FAILED:
console.log(`Failed: ${event.status}`);
break;
}
}Express Example
import express from 'express';
import { Webhook, Events } from '@smsgist/node';
const app = express();
app.use(express.raw({ type: 'application/json' }));
app.post('/webhooks/smsgist', (req, res) => {
const body = req.body.toString();
const isValid = Webhook.verifySignature({
body,
signature: req.headers['x-smsgist-signature'] as string,
timestamp: req.headers['x-smsgist-timestamp'] as string,
secret: process.env.SMSGIST_WEBHOOK_SECRET!,
});
if (!isValid) {
return res.status(401).send('Invalid signature');
}
const event = Webhook.parse(body);
console.log('Webhook:', event.event, event.messageId);
res.status(200).send('OK');
});Error Handling
import { SMSGist, ApiError, ValidationError, AuthenticationError } from '@smsgist/node';
try {
await client.sms.send({ recipients: [], message: '' });
} catch (err) {
if (err instanceof ValidationError) {
console.log('Validation:', err.message);
} else if (err instanceof ApiError) {
console.log('API error:', err.statusCode, err.responseBody);
} else if (err instanceof AuthenticationError) {
console.log('Auth error:', err.message);
}
}Modes
import { SMSGist, Mode } from '@smsgist/node';
// Test mode — redirects all messages to testPhone/testEmail
const testClient = new SMSGist({
...config,
mode: Mode.Test,
testPhone: '+233200000000',
testEmail: '[email protected]',
});
// DryRun mode — logs messages, returns mock response
const dryClient = new SMSGist({
...config,
mode: Mode.DryRun,
});CommonJS
const { SMSGist } = require('@smsgist/node');
const client = new SMSGist({
clientId: process.env.SMSGIST_CLIENT_ID,
clientSecret: process.env.SMSGIST_CLIENT_SECRET,
appKey: process.env.SMSGIST_APP_KEY,
});License
MIT
