Sending SMS
Learn how to send single and batch SMS messages via the API.
Sending Single Messages
Send a single SMS using the /sms endpoint:
Using TypeScript SDK
import { Transactional } from 'transactional-sdk';
const client = new Transactional({
apiKey: process.env.TRANSACTIONAL_API_KEY,
});
const result = await client.sms.send({
to: '+14155551234',
templateAlias: 'otp-verification',
templateModel: {
code: '123456',
},
tag: 'verification',
metadata: {
userId: 'user_123',
},
});
console.log(result.messageId);Using cURL
curl -X POST https://api.usetransactional.com/v1/sms \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"to": "+14155551234",
"templateAlias": "otp-verification",
"templateModel": {
"code": "123456"
},
"tag": "verification",
"metadata": {
"userId": "user_123"
}
}'Response
{
"to": "+14155551234",
"submittedAt": "2024-01-01T00:00:00.000Z",
"messageId": "sms_abc123",
"errorCode": 0,
"message": "OK"
}Request Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
to | string | Yes | Recipient phone number in E.164 format |
templateAlias | string | One required | Pool template alias or your custom alias |
templateId | number | One required | Pool template ID |
templateModel | object | No | Variables to substitute in template |
tag | string | No | Tag for filtering messages (max 255 chars) |
metadata | object | No | Custom key-value metadata |
Batch Sending
Send up to 500 messages in a single API call:
Using TypeScript SDK
const results = await client.sms.sendBatch([
{
to: '+14155551234',
templateAlias: 'otp-verification',
templateModel: { code: '123456' },
},
{
to: '+14155555678',
templateAlias: 'otp-verification',
templateModel: { code: '789012' },
},
{
to: '+14155559999',
templateAlias: 'order-shipped',
templateModel: { orderId: 'ORD-123' },
},
]);
for (const result of results) {
console.log(`${result.to}: ${result.errorCode === 0 ? 'OK' : result.message}`);
}Using cURL
curl -X POST https://api.usetransactional.com/v1/sms/batch \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '[
{
"to": "+14155551234",
"templateAlias": "otp-verification",
"templateModel": { "code": "123456" }
},
{
"to": "+14155555678",
"templateAlias": "otp-verification",
"templateModel": { "code": "789012" }
}
]'Batch Response
[
{
"to": "+14155551234",
"submittedAt": "2024-01-01T00:00:00.000Z",
"messageId": "sms_abc123",
"errorCode": 0,
"message": "OK"
},
{
"to": "+14155555678",
"submittedAt": "2024-01-01T00:00:00.000Z",
"messageId": "sms_def456",
"errorCode": 0,
"message": "OK"
}
]Partial Failures
In batch sending, some messages may fail while others succeed. Each message in the response array has its own status:
[
{
"to": "+14155551234",
"messageId": "sms_abc123",
"errorCode": 0,
"message": "OK"
},
{
"to": "+14155555678",
"errorCode": 1006,
"message": "Recipient has opted out of SMS messages"
}
]Message Segments
SMS messages are limited by character count:
| Encoding | Characters per Segment |
|---|---|
| GSM-7 (standard) | 160 characters |
| Unicode | 70 characters |
Messages exceeding these limits are split into multiple segments, each billed separately.
Checking Segments
The API response includes segment count:
const message = await client.sms.get('sms_abc123');
console.log('Segments:', message.segments);Unicode Detection
Messages with non-ASCII characters automatically use Unicode encoding:
// GSM-7: 1 segment for 160 chars
await client.sms.send({
to: '+14155551234',
templateAlias: 'simple-alert',
templateModel: { message: 'Hello World' },
});
// Unicode: 1 segment for 70 chars
await client.sms.send({
to: '+14155551234',
templateAlias: 'simple-alert',
templateModel: { message: 'Hello World! ' }, // Emoji triggers Unicode
});Tags and Metadata
Tags
Use tags to categorize messages for filtering and analytics:
await client.sms.send({
to: '+14155551234',
templateAlias: 'otp-verification',
templateModel: { code: '123456' },
tag: 'login-verification',
});
// Later, filter by tag
const messages = await client.sms.list({ tag: 'login-verification' });Metadata
Store custom data with each message:
await client.sms.send({
to: '+14155551234',
templateAlias: 'order-confirmation',
templateModel: { orderId: 'ORD-123' },
metadata: {
userId: 'user_456',
orderId: 'order_789',
source: 'checkout',
},
});Metadata is returned when retrieving message details.
Error Handling
Common Error Codes
| Code | Description |
|---|---|
| 0 | Success |
| 1001 | Invalid phone number format |
| 1002 | Template not found |
| 1003 | Template not approved for organization |
| 1004 | No pool number available for country |
| 1005 | SMS not enabled for organization |
| 1006 | Recipient opted out (suppressed) |
Handling Errors
try {
const result = await client.sms.send({
to: '+14155551234',
templateAlias: 'otp-verification',
templateModel: { code: '123456' },
});
if (result.errorCode !== 0) {
console.error('Send failed:', result.message);
}
} catch (error) {
console.error('API error:', error.message);
}Rate Limits
| Limit Type | Value |
|---|---|
| Single send | 100 requests/second |
| Batch send | 10 requests/second |
| Batch size | 500 messages/request |
Best Practices
1. Use Batch for Multiple Messages
When sending to multiple recipients, use batch API to reduce latency:
// Good - single API call
await client.sms.sendBatch(messages);
// Avoid - multiple API calls
for (const msg of messages) {
await client.sms.send(msg);
}2. Handle Partial Failures
Always check each result in batch responses:
const results = await client.sms.sendBatch(messages);
const failed = results.filter(r => r.errorCode !== 0);
if (failed.length > 0) {
// Log or retry failed messages
}3. Use Meaningful Tags
Tags help with debugging and analytics:
tag: `${featureName}-${environment}` // e.g., "login-otp-production"Next Steps
- Receiving - Handle inbound messages
- Webhooks - Track delivery status
- API Reference - Complete API documentation
On This Page
- Sending Single Messages
- Using TypeScript SDK
- Using cURL
- Response
- Request Parameters
- Batch Sending
- Using TypeScript SDK
- Using cURL
- Batch Response
- Partial Failures
- Message Segments
- Checking Segments
- Unicode Detection
- Tags and Metadata
- Tags
- Metadata
- Error Handling
- Common Error Codes
- Handling Errors
- Rate Limits
- Best Practices
- 1. Use Batch for Multiple Messages
- 2. Handle Partial Failures
- 3. Use Meaningful Tags
- Next Steps