Batch Messaging
Send SMS messages to multiple recipients efficiently.
Overview
The batch messaging feature allows you to send the same or different messages to multiple recipients in a single API call.
Basic Usage
typescript
import { MsGineClient } from '@msgine/sdk'
const client = new MsGineClient({
apiToken: process.env.MSGINE_API_TOKEN!
})
const messages = [
{ to: '+256701521269', message: 'Hello Alice!' },
{ to: '+256701521270', message: 'Hello Bob!' },
{ to: '+256701521271', message: 'Hello Charlie!' }
]
const results = await client.sendSmsBatch(messages)
results.forEach((result, index) => {
console.log(`Message ${index + 1}:`, result.id, result.status)
})Response
The sendSmsBatch method returns an array of SendSmsResponse objects:
typescript
[
{
id: "msg_1234567890",
status: "pending",
to: ["+256701521269"],
content: "Hello Alice!",
cost: 0.05,
currency: "USD",
createdAt: "2024-01-15T10:30:00Z"
},
{
id: "msg_1234567891",
status: "pending",
to: ["+256701521270"],
content: "Hello Bob!",
cost: 0.05,
currency: "USD",
createdAt: "2024-01-15T10:30:01Z"
},
{
id: "msg_1234567892",
status: "pending",
to: ["+256701521271"],
content: "Hello Charlie!",
cost: 0.05,
currency: "USD",
createdAt: "2024-01-15T10:30:02Z"
}
]Examples
Send Same Message to Multiple Recipients
typescript
async function notifyUsers(phoneNumbers: string[], message: string) {
const messages = phoneNumbers.map(to => ({
to,
message
}))
const results = await client.sendSmsBatch(messages)
const successful = results.filter(r => r.status !== 'failed').length
const failed = results.filter(r => r.status === 'failed').length
console.log(`✅ Sent: ${successful}, ❌ Failed: ${failed}`)
return results
}
await notifyUsers(
['+256701521269', '+256701521270', '+256701521271'],
'System maintenance tonight at 10 PM'
)Send Personalized Messages
typescript
interface User {
phone: string
name: string
code: string
}
async function sendVerificationCodes(users: User[]) {
const messages = users.map(user => ({
to: user.phone,
message: `Hi ${user.name}, your code is ${user.code}`
}))
const results = await client.sendSmsBatch(messages)
return results.map((result, index) => ({
user: users[index],
messageId: result.id,
status: result.status
}))
}
const users = [
{ phone: '+256701521269', name: 'Alice', code: '123456' },
{ phone: '+256701521270', name: 'Bob', code: '789012' }
]
const sent = await sendVerificationCodes(users)Batch with Error Handling
typescript
import { MsGineError, MsGineValidationError } from '@msgine/sdk'
async function sendBatchSafely(messages: Array<{ to: string; message: string }>) {
try {
const results = await client.sendSmsBatch(messages)
const summary = {
total: results.length,
pending: results.filter(r => r.status === 'pending').length,
sent: results.filter(r => r.status === 'sent').length,
failed: results.filter(r => r.status === 'failed').length,
totalCost: results.reduce((sum, r) => sum + r.cost, 0)
}
return { success: true, results, summary }
} catch (error) {
if (error instanceof MsGineValidationError) {
console.error('Validation failed:', error.errors.issues)
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' }
}
}Limits
Batch Size
- Maximum: 1000 messages per batch
- Recommended: 100-500 messages per batch for optimal performance
For larger campaigns, split into multiple batches:
typescript
async function sendLargeCampaign(messages: Array<{ to: string; message: string }>) {
const BATCH_SIZE = 500
const results = []
for (let i = 0; i < messages.length; i += BATCH_SIZE) {
const batch = messages.slice(i, i + BATCH_SIZE)
const batchResults = await client.sendSmsBatch(batch)
results.push(...batchResults)
console.log(`Sent batch ${i / BATCH_SIZE + 1}/${Math.ceil(messages.length / BATCH_SIZE)}`)
// Optional: Add delay between batches to avoid rate limits
if (i + BATCH_SIZE < messages.length) {
await new Promise(resolve => setTimeout(resolve, 1000))
}
}
return results
}Best Practices
1. Validate All Recipients
Validate phone numbers before sending:
typescript
function validateBatch(messages: Array<{ to: string; message: string }>) {
const e164Regex = /^\+[1-9]\d{1,14}$/
return messages.filter(msg => {
if (!e164Regex.test(msg.to)) {
console.warn(`Invalid phone number: ${msg.to}`)
return false
}
if (!msg.message || msg.message.length === 0) {
console.warn(`Empty message for: ${msg.to}`)
return false
}
return true
})
}
const validMessages = validateBatch(messages)
const results = await client.sendSmsBatch(validMessages)2. Monitor Results
Track successful and failed messages:
typescript
const results = await client.sendSmsBatch(messages)
const failed = results.filter(r => r.status === 'failed')
if (failed.length > 0) {
console.error(`${failed.length} messages failed`)
// Retry failed messages or log for review
}3. Implement Retry Logic
Retry failed messages:
typescript
async function sendWithRetry(messages: Array<{ to: string; message: string }>, maxRetries = 3) {
let results = await client.sendSmsBatch(messages)
let retries = 0
while (retries < maxRetries) {
const failed = results.filter(r => r.status === 'failed')
if (failed.length === 0) break
console.log(`Retrying ${failed.length} failed messages (attempt ${retries + 1})`)
// Extract original messages for failed results
const retryMessages = failed.map(result => {
const index = results.indexOf(result)
return messages[index]
})
const retryResults = await client.sendSmsBatch(retryMessages)
// Update results
retryResults.forEach((retryResult, i) => {
const originalIndex = results.findIndex(r => r.id === failed[i].id)
results[originalIndex] = retryResult
})
retries++
}
return results
}4. Calculate Costs
Estimate and track costs:
typescript
const results = await client.sendSmsBatch(messages)
const totalCost = results.reduce((sum, result) => sum + result.cost, 0)
const currency = results[0]?.currency || 'USD'
console.log(`Total cost: ${totalCost.toFixed(2)} ${currency}`)5. Use Batching for Large Lists
Split large recipient lists:
typescript
async function* sendInBatches(
messages: Array<{ to: string; message: string }>,
batchSize = 100
) {
for (let i = 0; i < messages.length; i += batchSize) {
const batch = messages.slice(i, i + batchSize)
const results = await client.sendSmsBatch(batch)
yield results
}
}
// Usage
for await (const batchResults of sendInBatches(largeMessageList)) {
console.log(`Batch sent: ${batchResults.length} messages`)
}Performance Considerations
Parallel Processing
For very large campaigns, consider parallel processing:
typescript
async function sendParallel(
messages: Array<{ to: string; message: string }>,
batchSize = 100,
parallelBatches = 3
) {
const batches = []
for (let i = 0; i < messages.length; i += batchSize) {
batches.push(messages.slice(i, i + batchSize))
}
const results = []
for (let i = 0; i < batches.length; i += parallelBatches) {
const parallelPromises = batches
.slice(i, i + parallelBatches)
.map(batch => client.sendSmsBatch(batch))
const batchResults = await Promise.all(parallelPromises)
results.push(...batchResults.flat())
}
return results
}Rate Limits
Be mindful of rate limits when sending large batches. The SDK will handle retries automatically, but it's better to pace your requests.
Next Steps
- Error Handling - Handle errors in batch operations
- Best Practices - Optimization tips
- API Reference - Complete API documentation