Getting Started
Modern SMS APIs use RESTful architecture with JSON payloads, making integration straightforward for developers familiar with web APIs. Most Australian SMS providers offer similar API structures, though implementation details vary.
Prerequisites
- SMS provider account with API credentials (API key or OAuth token)
- Development environment with HTTPS support (required for webhooks)
- Basic understanding of HTTP requests and JSON
- Test phone numbers for development and staging environments
Authentication Methods
API Key Authentication
Most common method. Include API key in header:
Authorization: Bearer YOUR_API_KEY
# or
X-API-Key: YOUR_API_KEYOAuth 2.0
Used by some enterprise providers. Requires token refresh mechanism:
POST /oauth/token
Content-Type: application/json
{
"grant_type": "client_credentials",
"client_id": "YOUR_CLIENT_ID",
"client_secret": "YOUR_CLIENT_SECRET"
}REST API Basics
Sending a Simple SMS
Basic POST request to send an SMS:
cURL Example
curl -X POST https://api.provider.com/v1/sms \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"to": "+61412345678",
"from": "YourBrand",
"body": "Your verification code is 123456"
}'Python Example
import requests
def send_sms(to, message):
url = "https://api.provider.com/v1/sms"
headers = {
"Authorization": "Bearer YOUR_API_KEY",
"Content-Type": "application/json"
}
payload = {
"to": to,
"from": "YourBrand",
"body": message
}
response = requests.post(url, json=payload, headers=headers)
if response.status_code == 200:
return response.json()
else:
raise Exception(f"Failed to send SMS: {response.text}")
# Usage
result = send_sms("+61412345678", "Your code is 123456")
print(f"Message ID: {result['message_id']}")Node.js Example
const axios = require('axios');
async function sendSMS(to, message) {
try {
const response = await axios.post(
'https://api.provider.com/v1/sms',
{
to: to,
from: 'YourBrand',
body: message
},
{
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json'
}
}
);
return response.data;
} catch (error) {
console.error('SMS send failed:', error.response.data);
throw error;
}
}
// Usage
sendSMS('+61412345678', 'Your code is 123456')
.then(result => console.log('Message ID:', result.message_id))
.catch(err => console.error(err));API Response Structure
Typical successful response:
{
"message_id": "msg_abc123xyz",
"status": "queued",
"to": "+61412345678",
"from": "YourBrand",
"segments": 1,
"cost": 0.045,
"timestamp": "2025-01-15T10:30:00Z"
}Bulk SMS Sending
Send multiple messages efficiently with batch requests:
{
"messages": [
{
"to": "+61412345678",
"from": "YourBrand",
"body": "Hi John, your order #123 has shipped!"
},
{
"to": "+61498765432",
"from": "YourBrand",
"body": "Hi Sarah, your order #456 has shipped!"
}
]
}⚠️ Rate Limiting
Most providers limit batch size (typically 100-1000 messages per request) and enforce rate limits (e.g., 10 requests per second). Implement exponential backoff when hitting limits.
Webhooks & Delivery Receipts
Webhooks provide real-time updates about message status. Instead of polling the API, your server receives HTTP POST requests when events occur.
Setting Up Webhooks
1. Configure Webhook URL
In your provider dashboard, set webhook URL (must be HTTPS):
https://yourdomain.com/webhooks/sms2. Create Webhook Endpoint
Express.js example:
const express = require('express');
const app = express();
app.post('/webhooks/sms', express.json(), (req, res) => {
const { message_id, status, to, timestamp } = req.body;
console.log(`Message ${message_id} to ${to}: ${status}`);
// Update your database
updateMessageStatus(message_id, status, timestamp);
// Respond with 200 to acknowledge receipt
res.status(200).json({ received: true });
});
app.listen(3000);Webhook Payload Examples
✓ Message Delivered
{
"event": "message.delivered",
"message_id": "msg_abc123",
"status": "delivered",
"to": "+61412345678",
"timestamp": "2025-01-15T10:30:15Z"
}✗ Message Failed
{
"event": "message.failed",
"message_id": "msg_abc124",
"status": "failed",
"to": "+61412345678",
"error_code": "30004",
"error_message": "Invalid phone number",
"timestamp": "2025-01-15T10:30:20Z"
}↩ Reply Received
{
"event": "message.received",
"from": "+61412345678",
"to": "YourBrand",
"body": "STOP",
"timestamp": "2025-01-15T10:31:00Z"
}🔒 Security Best Practices
- Verify webhook signatures to prevent spoofing
- Use HTTPS only (HTTP webhooks are insecure)
- Validate payload structure before processing
- Implement idempotency (handle duplicate webhooks)
- Return 200 status quickly (process async if needed)
Webhook Signature Verification
const crypto = require('crypto');
function verifyWebhookSignature(payload, signature, secret) {
const expectedSignature = crypto
.createHmac('sha256', secret)
.update(JSON.stringify(payload))
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expectedSignature)
);
}
app.post('/webhooks/sms', express.json(), (req, res) => {
const signature = req.headers['x-webhook-signature'];
if (!verifyWebhookSignature(req.body, signature, WEBHOOK_SECRET)) {
return res.status(401).json({ error: 'Invalid signature' });
}
// Process webhook...
});Best Practices
Message Queue Architecture
Don't send SMS synchronously in user-facing requests. Use a queue:
- Add messages to queue (Redis, RabbitMQ, AWS SQS)
- Background workers process queue and call SMS API
- Retry failed messages with exponential backoff
- Track delivery status via webhooks
Phone Number Validation
Validate before sending to avoid wasted costs:
// Use libphonenumber for robust validation
const phoneUtil = require('google-libphonenumber').PhoneNumberUtil.getInstance();
function isValidAustralianMobile(number) {
try {
const phoneNumber = phoneUtil.parse(number, 'AU');
return phoneUtil.isValidNumberForRegion(phoneNumber, 'AU') &&
phoneUtil.getNumberType(phoneNumber) ===
phoneUtil.PhoneNumberType.MOBILE;
} catch (e) {
return false;
}
}Message Templates
Create reusable templates for consistency and compliance:
const templates = {
verification: (code) =>
`Your verification code is ${code}. Valid for 10 minutes. Never share this code.`,
orderShipped: (orderNumber, trackingUrl) =>
`Your order #${orderNumber} has shipped! Track: ${trackingUrl}`,
marketing: (name, offer) =>
`Hi ${name}, ${offer} Reply STOP to unsubscribe.`
};Cost Optimization
- Avoid Unicode when possible: Unicode messages cost 2-3x more (70 chars vs 160 chars per segment)
- Compress messages: Use URL shorteners for links
- Deduplicate recipients: Don't send same message twice to same number
- Respect opt-outs: Maintain unsubscribe list to avoid wasted sends
Testing Strategy
Development Environment
- Use provider sandbox/test mode (no real sends)
- Test with verified phone numbers only
- Mock webhooks for local development
Staging Environment
- Send to internal test numbers only
- Test full webhook flow
- Verify rate limiting behavior
Production Rollout
- Start with small percentage of users
- Monitor delivery rates closely
- Have rollback plan ready
Error Handling
Common HTTP Status Codes
200 OK
Message accepted and queued for delivery
400 Bad Request
Invalid request (missing required fields, invalid phone number format)
401 Unauthorized
Invalid API credentials or expired token
429 Too Many Requests
Rate limit exceeded. Check Retry-After header for wait time
500 Internal Server Error
Provider system error. Implement retry with exponential backoff
Retry Logic Example
async function sendSMSWithRetry(to, message, maxRetries = 3) {
let attempt = 0;
while (attempt < maxRetries) {
try {
const result = await sendSMS(to, message);
return result;
} catch (error) {
attempt++;
// Don't retry client errors (400, 401, 403)
if (error.status >= 400 && error.status < 500) {
throw error;
}
if (attempt >= maxRetries) {
throw new Error(`Failed after ${maxRetries} attempts`);
}
// Exponential backoff: 1s, 2s, 4s
const delay = Math.pow(2, attempt) * 1000;
await new Promise(resolve => setTimeout(resolve, delay));
}
}
}💡 Monitoring Tip
Track error rates by type. A sudden spike in 400 errors might indicate a bug in your phone number validation. High 500 errors suggest provider issues. Set up alerts for delivery rate drops below 95%.
Frequently Asked Questions
What is a REST API for SMS?
A REST API is a modern web service interface that uses HTTP methods (GET, POST, PUT, DELETE) to send and receive SMS messages programmatically. It's the most common API type for SMS providers, using JSON for data exchange.
How do SMS webhooks work?
Webhooks are HTTP callbacks that SMS providers send to your server when events occur (message delivered, failed, or replied). Your server must have a public endpoint to receive these callbacks in real-time.
What are delivery receipts (DLR) and why are they important?
Delivery receipts confirm whether a message was successfully delivered to the recipient. They're crucial for transactional messages (e.g., verification codes) to know if the user received the message and for tracking campaign effectiveness.
Should I use an SDK or call the API directly?
Use official SDKs when available - they handle authentication, error handling, and retries automatically. Direct API calls give more control but require more code. For production applications, SDKs are recommended for reliability.
How do I handle SMS API rate limits?
Implement exponential backoff for retries, queue messages during high-volume periods, batch multiple messages into single API calls when supported, and monitor rate limit headers in API responses.
What's the difference between transactional and marketing SMS APIs?
Transactional APIs send one-off messages (OTPs, alerts, confirmations) with higher priority and no consent required. Marketing APIs handle bulk campaigns, require opt-in consent, and often have different rate limits and pricing.
Continue Learning
SMS Provider Buying Guide →
Learn what to look for when choosing an SMS provider including pricing models, features, and reliability factors.
Legal ComplianceAustralian SMS Compliance Guide →
Essential compliance information for developers: Spam Act 2003, consent requirements, and opt-out mechanisms.
Comparison ToolCompare Provider APIs →
Compare API features, documentation quality, and developer experience across Australian SMS providers.
FeaturesFeatures Comparison →
Detailed comparison of technical features including two-way messaging, webhooks, and delivery receipts.
Ready to Integrate?
Compare API documentation and developer experience across providers to find the best fit for your technical requirements.