SMS SDK Reference
Complete reference for @wraps.dev/sms TypeScript SDK.
A TypeScript-first SDK for sending SMS through your Wraps-deployed AWS End User Messaging infrastructure. Simple, type-safe, and intuitive API.
npm install @wraps.dev/sms
import { WrapsSMS } from '@wraps.dev/sms';const sms = new WrapsSMS();const result = await sms.send({ to: '+14155551234', message: 'Your verification code is 123456',});console.log(result.messageId);Create a new WrapsSMS client. The SDK automatically detects AWS credentials from your environment (OIDC, IAM roles, or environment variables).
new WrapsSMS(config?: WrapsSMSConfig)region (optional): AWS region where your infrastructure is deployed. Auto-detected if not provided.credentials (optional): AWS credentials object. Auto-detected if not provided.roleArn (optional): IAM role ARN for OIDC authentication (Vercel, EKS, GitHub Actions).Example with Options
const sms = new WrapsSMS({ region: 'us-west-2', credentials: { accessKeyId: process.env.AWS_ACCESS_KEY_ID, secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY, },});OIDC Authentication
// OIDC authentication (Vercel, EKS, GitHub Actions)const sms = new WrapsSMS({ roleArn: process.env.AWS_ROLE_ARN,});Send a single SMS message through your Wraps infrastructure.
sms.send(options: SendOptions): Promise<SendResult>| Parameter | Type | Description |
|---|---|---|
to | string | Recipient phone number (E.164 format) |
message | string | Message body |
messageType | string | TRANSACTIONAL or PROMOTIONAL (optional) |
from | string | Override sender phone number (optional) |
context | Record<string, string> | Custom metadata (optional) |
dryRun | boolean | Validate without sending (optional) |
const result = await sms.send({ to: '+14155551234', // Required: E.164 format message: 'Hello!', // Required: Message body messageType: 'TRANSACTIONAL', // Optional: TRANSACTIONAL or PROMOTIONAL from: '+18005551234', // Optional: Override sender context: { userId: '123' }, // Optional: Custom metadata dryRun: true, // Optional: Validate without sending});// Resultconsole.log(result.messageId); // 'msg-abc123'console.log(result.status); // 'QUEUED'console.log(result.segments); // 1Send SMS messages to multiple recipients efficiently.
sms.sendBatch(options: BatchOptions): Promise<BatchResult>const result = await sms.sendBatch({ messages: [ { to: '+14155551234', message: 'Your order shipped!' }, { to: '+14155555678', message: 'Your order shipped!' }, ], messageType: 'TRANSACTIONAL',});// Resultconsole.log(`Sent: ${result.queued}, Failed: ${result.failed}`);// Check individual resultsresult.results.forEach((r) => { if (r.status === 'QUEUED') { console.log(`Sent to ${r.to}: ${r.messageId}`); } else { console.log(`Failed to send to ${r.to}: ${r.error}`); }});List and manage phone numbers in your AWS account.
const numbers = await sms.numbers.list();// Resultnumbers.forEach((n) => { console.log(n.phoneNumber); // '+18005551234' console.log(n.numberType); // 'TOLL_FREE' console.log(n.messageType); // 'TRANSACTIONAL' console.log(n.twoWayEnabled); // false});Get details for a specific phone number by ID.
const number = await sms.numbers.get('phone-number-id');// Returnsconsole.log(number.phoneNumberId); // 'phone-number-id'console.log(number.phoneNumber); // '+18005551234'console.log(number.numberType); // 'TOLL_FREE'console.log(number.messageType); // 'TRANSACTIONAL'console.log(number.twoWayEnabled); // falseManage opt-out lists for compliance with messaging regulations.
Check Opt-Out Status
// Check if a number has opted outconst isOptedOut = await sms.optOuts.check('+14155551234');if (isOptedOut) { console.log('User has opted out');}Manage Opt-Outs
// Add a phone number to the opt-out listawait sms.optOuts.add('+14155551234');// Remove a phone number from the opt-out listawait sms.optOuts.remove('+14155551234');// List all opted-out numbersconst optedOut = await sms.optOuts.list();optedOut.forEach((entry) => { console.log(`${entry.phoneNumber} opted out at ${entry.optedOutAt}`);});List all opted-out phone numbers with pagination support.
const result = await sms.optOuts.list({ limit: 20 });result.entries.forEach((entry) => { console.log(`${entry.phoneNumber} opted out at ${entry.optedOutAt}`);});// Paginateif (result.nextToken) { const nextPage = await sms.optOuts.list({ limit: 20, nextToken: result.nextToken, });}The SDK throws typed errors for different failure scenarios.
| Error | Description |
|---|---|
ValidationError | Invalid input parameters (includes field property) |
OptedOutError | Recipient has opted out (includes phoneNumber property) |
SMSError | AWS service error (includes code, retryable properties) |
RateLimitError | Rate limit exceeded |
import { WrapsSMS, SMSError, ValidationError, OptedOutError } from '@wraps.dev/sms';try { await sms.send({ to: '+14155551234', message: 'Hello!' });} catch (error) { if (error instanceof ValidationError) { console.log('Invalid input:', error.field); } else if (error instanceof OptedOutError) { console.log('User opted out:', error.phoneNumber); } else if (error instanceof SMSError) { console.log('AWS error:', error.code, error.message); if (error.retryable) { // Safe to retry } }}Thrown when AWS rate limits are exceeded. Includes a retryAfter property indicating how many seconds to wait before retrying.
import { RateLimitError } from '@wraps.dev/sms';try { await sms.send({ to: '+14155551234', message: 'Hello!' });} catch (error) { if (error instanceof RateLimitError) { console.log('Rate limited, retry after:', error.retryAfter, 'seconds'); console.log('Message:', error.message); }}Helper functions for common SMS operations.
import { calculateSegments, validatePhoneNumber } from '@wraps.dev/sms';// Calculate SMS segmentscalculateSegments('Hello!'); // 1calculateSegments('a'.repeat(200)); // 2calculateSegments('Hello emojis!'); // 1 (Unicode)// Validate phone numbersvalidatePhoneNumber('+14155551234', 'to'); // OKvalidatePhoneNumber('4155551234', 'to'); // Throws ValidationErrorUtility function to sanitize phone numbers into E.164 format by removing formatting characters.
import { sanitizePhoneNumber } from '@wraps.dev/sms';sanitizePhoneNumber('(415) 555-1234'); // '+14155551234'sanitizePhoneNumber('+1-415-555-1234'); // '+14155551234'Remove all SMS infrastructure including phone numbers and opt-out lists. This action is irreversible.
// Remove all SMS infrastructure (phone numbers, opt-out lists)await sms.destroy();| Type | Use Case | Best Practices |
|---|---|---|
TRANSACTIONAL | OTP, alerts, notifications | Time-sensitive, user-initiated |
PROMOTIONAL | Marketing, promotions | Requires explicit consent |
The SDK is written in TypeScript and provides full type safety out of the box.
import { WrapsSMS, SendOptions, SendResult } from '@wraps.dev/sms';const sms = new WrapsSMS();// TypeScript will validate all parametersconst options: SendOptions = { to: '+14155551234', message: 'Hello!', messageType: 'TRANSACTIONAL',};const result: SendResult = await sms.send(options);AWS End User Messaging charges per message segment:
| Component | Cost (US) |
|---|---|
| Toll-free number | $2/month |
| Outbound SMS | ~$0.00849/segment |
| Carrier fees | ~$0.003-0.006/segment |
Sequential Batch Processing
Batch sends are processed sequentially (not in parallel) to respect AWS rate limits. Each message is sent one at a time.
Default Message Type: TRANSACTIONAL
The default messageType is TRANSACTIONAL. Set to PROMOTIONAL for marketing messages.
Check out the package on npm for the latest version and changelog.
View PackageExplore the source code, report issues, or contribute.
View Source