Skip to content

Sending SMS

Learn how to send SMS messages using the MsGine SDK.

Basic Usage

Send a simple SMS message:

typescript
import { MsGineClient } from '@msgine/sdk';

const client = new MsGineClient({
  apiKey: process.env.MSGINE_API_KEY!,
})

const result = await client.sms.send({
  to: '+256701521269',
  message: 'Hello from MsGine!'
})

console.log('Message sent:', result.id)

Parameters

to (required)

Type: string | string[]

The recipient's phone number(s) in E.164 format.

typescript
// Single recipient
await client.sms.send({
  to: '+256701521269',  // ✅ Correct
  message: 'Hello!'
})

// Multiple recipients
await client.sms.send({
  to: ['+256701521269', '+256701234567'],
  message: 'Hello!'
})

// ❌ Incorrect formats:
// to: '0701521269'     // Missing country code
// to: '256701521269'   // Missing + prefix

message (required)

Type: string (max 1000 characters)

The message content to send.

typescript
await client.sms.send({
  to: '+256701521269',
  message: 'Your verification code is 123456'
})

Message Length

  • Standard SMS: Up to 160 characters per part
  • Unicode/Emoji: Up to 70 characters per part
  • Maximum: 1000 characters total

from (optional)

Type: string (max 11 characters)

Custom sender ID displayed to recipients.

typescript
await client.sms.send({
  to: '+256701521269',
  from: 'MyApp',
  message: 'Hello from MyApp!'
})

callbackUrl (optional)

Type: string

Webhook URL to receive delivery status updates.

typescript
await client.sms.send({
  to: '+256701521269',
  message: 'Hello!',
  callbackUrl: 'https://your-app.com/webhooks/msgine'
})

Response

The sms.send() method returns a promise that resolves to a SendSmsResponse:

typescript
{
  id: "msg_1234567890",           // Unique message identifier
  sid: "SM1234567890",            // Provider-specific ID
  channel: "sms",                 // Message channel
  to: ["+256701521269"],          // Recipients
  from: "MsGine",                 // Sender ID
  content: "Hello from MsGine!",  // Message content
  status: "pending",              // Message status
  cost: 30,                       // Cost in UGX
  currency: "UGX",                // Currency
  createdAt: "2024-01-15T10:30:00Z",
  updatedAt: "2024-01-15T10:30:01Z"
}

Message Statuses

StatusDescription
pendingMessage is queued for delivery
sentMessage has been sent to the carrier
deliveredMessage was successfully delivered
failedMessage delivery failed

Examples

Send a Verification Code

typescript
async function sendVerificationCode(phoneNumber: string, code: string) {
  const result = await client.sms.send({
    to: phoneNumber,
    message: `Your verification code is ${code}. Valid for 10 minutes.`
  })

  return result.id
}

const messageId = await sendVerificationCode('+256701521269', '123456')

Send a Notification

typescript
async function sendNotification(phoneNumber: string, message: string) {
  try {
    const result = await client.sms.send({
      to: phoneNumber,
      message
    })

    if (result.status === 'pending' || result.status === 'sent') {
      console.log('✅ Notification sent successfully')
      return true
    }

    return false
  } catch (error) {
    console.error('❌ Failed to send notification:', error)
    return false
  }
}

Send with Error Handling

typescript
import { MsGineClient, MsGineError, MsGineValidationError } from '@msgine/sdk'

async function sendSmsWithErrorHandling(to: string, message: string) {
  try {
    const result = await client.sms.send({ to, message })
    return { success: true, data: result }
  } catch (error) {
    if (error instanceof MsGineValidationError) {
      // Input failed validation before reaching the API
      console.error('Validation failed:', error.message)
      if (error.field) console.error('Field:', error.field)
      return { success: false, error: 'Invalid input' }
    }

    if (error instanceof MsGineError) {
      // API returned an error
      console.error('API error:', error.message)
      console.error('Status:', error.statusCode)
      return { success: false, error: error.message }
    }

    // Handle unexpected errors
    console.error('Unexpected error:', error)
    return { success: false, error: 'Unknown error' }
  }
}

Phone Number Formatting

E.164 Format

All phone numbers must be in E.164 format:

+[country code][subscriber number]

Examples:

typescript
'+256701521269'  // Uganda
'+1555123456'    // United States
'+447911123456'  // United Kingdom
'+33123456789'   // France

Common Mistakes

typescript
// ❌ Missing country code
to: '0701521269'

// ❌ Missing + prefix
to: '256701521269'

// ❌ Contains spaces or hyphens
to: '+256 70 152 1269'
to: '+256-70-152-1269'

// ✅ Correct format
to: '+256701521269'

Message Content

Character Limits

  • Standard SMS: 160 characters per part
  • Unicode/Emoji: 70 characters per part
  • Maximum: 1000 characters

Long Messages

Messages longer than 160 characters are automatically split into parts:

typescript
await client.sms.send({
  to: '+256701521269',
  message: 'This is a longer message that will be split...'
})
// Charged per part — check the `cost` field in the response

Best Practices

1. Validate Phone Numbers

Always validate phone numbers before sending:

typescript
function isValidE164(phoneNumber: string): boolean {
  const e164Regex = /^\+[1-9]\d{1,14}$/
  return e164Regex.test(phoneNumber)
}

if (isValidE164(phoneNumber)) {
  await client.sms.send({ to: phoneNumber, message })
}

2. Handle Errors Gracefully

Always wrap API calls in try-catch:

typescript
try {
  const result = await client.sms.send({ to, message })
  // Handle success
} catch (error) {
  // Handle error
}

3. Keep Messages Concise

Shorter messages are:

  • Cheaper (one part vs multiple)
  • Faster to read
  • More likely to be read completely
typescript
// ✅ Good: Concise and clear
"Your code: 123456. Valid for 10 min."

// ❌ Too verbose
"Hello! Thank you for using our service. Your verification code is 123456. Please note that this code will expire in 10 minutes from now."

4. Use Environment Variables

Never hardcode sensitive data:

typescript
// ✅ Good
const client = new MsGineClient({
  apiKey: process.env.MSGINE_API_KEY!,
})

// ❌ Bad
const client = new MsGineClient({
  apiKey: 'sk_live_1234567890'
})

Next Steps

Released under the MIT License.