Skip to content

Batch Messaging

Send the same message to multiple recipients in a single API call.

Overview

The MsGine SDK supports sending to multiple recipients by passing an array to the to parameter of client.sms.send(). A single API call handles all recipients — no looping required.

Basic Usage

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

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

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

console.log('Message ID:', result.id);
console.log('Recipients:', result.to.length);
console.log('Status:', result.status);
console.log('Cost:', result.cost, result.currency);

Response

typescript
{
  id: "msg_1234567890",
  channel: "sms",
  to: ["+256701521269", "+256701521270", "+256701521271"],
  from: "MsGine",
  content: "Hello from MsGine!",
  status: "pending",
  cost: 90,         // 30 UGX × 3 recipients
  currency: "UGX",
  createdAt: "2024-01-15T10:30:00Z"
}

Examples

Broadcast Notification

typescript
async function notify(phones: string[], message: string) {
  const result = await client.sms.send({ to: phones, message });
  console.log(`Sent to ${result.to.length} recipients. Cost: ${result.cost} ${result.currency}`);
  return result;
}

await notify(
  ['+256701521269', '+256701521270', '+256701521271'],
  'System maintenance tonight at 10 PM'
);

With Error Handling

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

async function broadcastSafely(phones: string[], message: string) {
  try {
    const result = await client.sms.send({ to: phones, message });
    return { success: true, messageId: result.id, cost: result.cost };
  } catch (error) {
    if (error instanceof MsGineValidationError) {
      console.error('Validation failed:', error.message);
      if (error.field) console.error('Field:', error.field);
      return { success: false, error: 'Invalid input' };
    }

    if (error instanceof MsGineError) {
      console.error('API error:', error.message);
      return { success: false, error: error.message };
    }

    return { success: false, error: 'Unknown error' };
  }
}

Personalized Messages

To send a different message to each recipient, make separate calls:

typescript
interface User {
  phone: string;
  name: string;
  code: string;
}

async function sendVerificationCodes(users: User[]) {
  const results = await Promise.all(
    users.map(user =>
      client.sms.send({
        to: user.phone,
        message: `Hi ${user.name}, your code is ${user.code}. Expires in 10 minutes.`,
      })
    )
  );

  return results.map((result, i) => ({
    user: users[i],
    messageId: result.id,
    status: result.status,
  }));
}

const users = [
  { phone: '+256701521269', name: 'Alice', code: '123456' },
  { phone: '+256701521270', name: 'Bob', code: '789012' },
];

await sendVerificationCodes(users);

Large Recipient Lists

For very large lists, send in chunks to stay within rate limits:

typescript
async function sendInChunks(phones: string[], message: string, chunkSize = 100) {
  const results = [];

  for (let i = 0; i < phones.length; i += chunkSize) {
    const chunk = phones.slice(i, i + chunkSize);
    const result = await client.sms.send({ to: chunk, message });
    results.push(result);

    console.log(`Sent chunk ${Math.floor(i / chunkSize) + 1}/${Math.ceil(phones.length / chunkSize)}`);

    // Pace requests to avoid rate limits
    if (i + chunkSize < phones.length) {
      await new Promise(resolve => setTimeout(resolve, 1000));
    }
  }

  return results;
}

Best Practices

Validate Phone Numbers First

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

const validPhones = phones.filter(p => {
  if (!isValidE164(p)) {
    console.warn(`Skipping invalid number: ${p}`);
    return false;
  }
  return true;
});

if (validPhones.length > 0) {
  await client.sms.send({ to: validPhones, message });
}

Track Costs

typescript
const result = await client.sms.send({ to: phones, message });
console.log(`Total cost: ${result.cost} ${result.currency}`);

Rate Limits

The API allows 100 requests per minute per API key. For high-volume campaigns, pace your requests or contact support for increased limits.

Next Steps

Released under the MIT License.