Building SMS Notifications into Your App: A Developer's Guide
By: Jayson Presto
Published: February 06, 2026
Learn how to integrate SMS notifications into your application using IPROG SMS. Complete guide with code examples in Ruby, PHP, Python, JavaScript, and more.
Building SMS Notifications into Your App: A Developer's Guide
SMS notifications are one of the most effective ways to reach users directly. With a 98% open rate and near-instant delivery, SMS is perfect for critical alerts, OTP codes, appointment reminders, and transactional notifications. In this comprehensive guide, we'll walk you through integrating SMS notifications into your application using IPROG SMS.
Why SMS Notifications?
Before diving into the technical details, let's understand why SMS notifications are essential for modern applications:
- High Open Rates: SMS messages have a 98% open rate compared to 20-30% for email
- Instant Delivery: Messages are typically delivered within seconds
- Universal Reach: Works on all mobile devices, even basic feature phones
- User Trust: Users expect important notifications via SMS
- No App Required: Works without users installing your app
Getting Started with IPROG SMS
Prerequisites
Before you begin, you'll need:
- An IPROG SMS account (sign up at iprogsms.com)
- SMS credits loaded into your account
- Your API token (found in your account dashboard)
- Basic knowledge of HTTP requests and your preferred programming language
Getting Your API Token
Your API token is your authentication key for all API requests. Here's how to get it:
- Log in to your IPROG SMS account
- Navigate to your account settings or dashboard
- Find your API token (it will look like: abc123def456...)
- Keep this token secure and never commit it to version control
Security Best Practice: Store your API token as an environment variable, not in your source code.
API Endpoints Overview
IPROG SMS provides several endpoints for different use cases:
Core SMS Endpoints
- POST /api/v1/sms_messages - Send a single SMS message
- POST /api/v1/sms_messages/send_bulk - Send SMS to multiple recipients
- GET /api/v1/sms_messages/status - Check the status of a sent message
- GET /api/v1/accounts/sms_credits - Check your account balance
Built-in Feature Endpoints
- POST /api/v1/otp/send_otp - Send OTP (One-Time Password) with automatic generation and expiration
- POST /api/v1/otp/verify_otp - Verify an OTP code
- POST /api/v1/message-reminders - Schedule SMS reminders for future delivery
- GET /api/v1/message-reminders/:id - View a scheduled reminder
- PATCH /api/v1/message-reminders/:id - Update a scheduled reminder
- DELETE /api/v1/message-reminders/:id - Delete a scheduled reminder
Base URL: https://iprogsms.com
Sending Your First SMS
Single SMS Request
The simplest way to send an SMS is using a POST request to the /api/v1/sms_messages endpoint. Here's what you need:
- api_token: Your API authentication token
- phone_number: Recipient's phone number (Philippines format: 639171234567)
- message: The SMS message content
Phone Number Format
Phone numbers must be in international format without the plus sign:
- ✅ Correct: 639171234567
- ❌ Wrong: +639171234567
- ❌ Wrong: 09171234567
- ❌ Wrong: 9171234567
The format is: 63 (country code) + 9 (mobile prefix) + 10-digit number
Code Examples
Ruby Example
require 'net/http'
require 'uri'
require 'json'
# Define the API endpoint
uri = URI('https://iprogsms.com/api/v1/sms_messages')
# Set up the HTTP request
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
request = Net::HTTP::Post.new(uri.path, { 'Content-Type' => 'application/json' })
# Request body
request.body = {
api_token: ENV['IPROG_SMS_API_TOKEN'],
phone_number: '639171071234',
message: 'Hello! This is a test message from IPROG SMS.'
}.to_json
# Send the request
response = http.request(request)
puts JSON.parse(response.body)
PHP Example
<?php
$url = 'https://iprogsms.com/api/v1/sms_messages/';
$data = [
'api_token' => getenv('IPROG_SMS_API_TOKEN'),
'message' => 'Hello! This is a test message from IPROG SMS.',
'phone_number' => '639171071234'
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Content-Type: application/x-www-form-urlencoded'
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
echo $response;
?>
Python Example
import requests
import os
url = 'https://iprogsms.com/api/v1/sms_messages'
data = {
'api_token': os.getenv('IPROG_SMS_API_TOKEN'),
'phone_number': '639171071234',
'message': 'Hello! This is a test message from IPROG SMS.'
}
response = requests.post(url, json=data)
print(response.json())
JavaScript/Node.js Example
const axios = require('axios');
const sendSMS = async () => {
try {
const response = await axios.post(
'https://iprogsms.com/api/v1/sms_messages',
{
api_token: process.env.IPROG_SMS_API_TOKEN,
phone_number: '639171071234',
message: 'Hello! This is a test message from IPROG SMS.'
},
{
headers: {
'Content-Type': 'application/json'
}
}
);
console.log('Success:', response.data);
} catch (error) {
console.error('Error:', error.response?.data || error.message);
}
};
sendSMS();
cURL Example
curl -X POST "https://iprogsms.com/api/v1/sms_messages" -H "Content-Type: application/json" -d '{
"api_token": "your_api_token_here",
"phone_number": "639171071234",
"message": "Hello! This is a test message from IPROG SMS."
}'
Understanding the Response
When you send an SMS, you'll receive a JSON response. Here's what a successful response looks like:
{
"status": 200,
"message": "SMS successfully queued for delivery.",
"message_id": "iSms-abc123",
"message_status_link": "https://iprogsms.com/api/v1/sms_messages/status?api_token=12345&message_id=iSms-abc123",
"message_status_request_mode": "GET",
"sms_rate": 1
}
Response Fields:
- status: HTTP status code (200 = success)
- message: Human-readable status message
- message_id: Unique identifier for tracking this message
- message_status_link: URL to check message status
- sms_rate: Number of SMS credits used. Messages are split into multiple parts based on character encoding:
- GSM-7 (standard characters): 160 characters per SMS (153 characters per segment for multi-part messages)
- Unicode (emojis & special characters): 70 characters per SMS (67 characters per segment for multi-part messages). Using emojis reduces the character count per SMS segment.
Error Handling
It's crucial to handle errors gracefully in your application. Here are common error responses and how to handle them:
Invalid API Token
{
"status": 500,
"message": "Invalid api token or no load balance"
}
Solution: Verify your API token is correct and your account has sufficient SMS credits.
Missing Required Parameters
{
"status": 500,
"message": "API Token, phone number and message are required."
}
Solution: Ensure all required parameters (api_token, phone_number, message) are included in your request.
Rate Limit Exceeded
Note: Rate limiting is currently applied to the web interface (sending SMS through the website), not the API endpoints. API users can send messages without rate limit restrictions.
If you're using the web interface and encounter rate limit errors, you'll see a message like:
{
"status": 500,
"message": "You've hit the limit of 3 requests per minute. For unlimited access, explore our pricing plans."
}
For API users: You don't need to worry about rate limits when using the API. However, it's still good practice to implement request throttling in your application to avoid overwhelming your system or the SMS service.
Error Handling Example (Python)
import requests
import os
import time
def send_sms_with_retry(phone_number, message, max_retries=3):
url = 'https://iprogsms.com/api/v1/sms_messages'
api_token = os.getenv('IPROG_SMS_API_TOKEN')
data = {
'api_token': api_token,
'phone_number': phone_number,
'message': message
}
for attempt in range(max_retries):
try:
response = requests.post(url, json=data, timeout=10)
result = response.json()
if result.get('status') == 200:
return {
'success': True,
'message_id': result.get('message_id'),
'data': result
}
else:
# Check if it's a rate limit error
if 'limit' in result.get('message', '').lower():
wait_time = (attempt + 1) * 2 # Exponential backoff
print(f"Rate limit hit. Waiting {wait_time} seconds...")
time.sleep(wait_time)
continue
return {
'success': False,
'error': result.get('message', 'Unknown error')
}
except requests.exceptions.Timeout:
print(f"Request timeout. Attempt {attempt + 1}/{max_retries}")
if attempt < max_retries - 1:
time.sleep(2)
continue
except requests.exceptions.RequestException as e:
return {
'success': False,
'error': f'Network error: {str(e)}'
}
return {
'success': False,
'error': 'Max retries exceeded'
}
# Usage
result = send_sms_with_retry('639171071234', 'Test message')
if result['success']:
print(f"Message sent! ID: {result['message_id']}")
else:
print(f"Failed: {result['error']}")
Sending Bulk SMS
For sending SMS to multiple recipients, use the bulk endpoint. This is more efficient than sending individual requests.
Bulk SMS Request
POST /api/v1/sms_messages/send_bulk
Parameters:
- api_token: Your API token
- phone_number: Comma-separated list of phone numbers (e.g., 639171234567,639171234568,639171234569)
- message: The message to send to all recipients
Bulk SMS Example (Python)
import requests
import os
def send_bulk_sms(phone_numbers, message):
url = 'https://iprogsms.com/api/v1/sms_messages/send_bulk'
# Convert list to comma-separated string
phone_numbers_str = ','.join(phone_numbers)
data = {
'api_token': os.getenv('IPROG_SMS_API_TOKEN'),
'phone_number': phone_numbers_str,
'message': message
}
response = requests.post(url, json=data)
return response.json()
# Usage
recipients = [
'639171234567',
'639171234568',
'639171234569'
]
result = send_bulk_sms(recipients, 'Bulk message to all recipients')
print(result)
Bulk Response:
{
"status": 200,
"message": "Your bulk SMS messages have been successfully added to the queue...",
"message_ids": "iSms-abc123,iSms-def456,iSms-ghi789",
"sms_rates": "1,1,1",
"message_status_link": "https://iprogsms.com/api/v1/sms_messages/status?...",
"message_status_request_mode": "GET"
}
Checking Message Status
After sending an SMS, you can check its delivery status using the message_id returned in the response.
Status Endpoint
GET /api/v1/sms_messages/status?api_token=YOUR_TOKEN&message_id=MESSAGE_ID
Status Check Example (Python)
import requests
import os
import time
def check_message_status(message_id):
url = 'https://iprogsms.com/api/v1/sms_messages/status'
params = {
'api_token': os.getenv('IPROG_SMS_API_TOKEN'),
'message_id': message_id
}
response = requests.get(url, params=params)
return response.json()
# Usage
message_id = 'iSms-abc123' # From the send response
status = check_message_status(message_id)
print(f"Status: {status.get('message_status')}")
print(f"SMS Count: {status.get('sms_count')}")
Possible Status Values:
- pending: Message is queued and waiting to be sent
- completed: Message was successfully delivered
- failed: Message delivery failed
Checking Account Balance
Before sending messages, it's good practice to check your account balance to ensure you have sufficient credits.
Balance Check Endpoint
GET /api/v1/accounts/sms_credits?api_token=YOUR_TOKEN
Balance Check Example (Python)
import requests
import os
def check_balance():
url = 'https://iprogsms.com/api/v1/accounts/sms_credits'
params = {
'api_token': os.getenv('IPROG_SMS_API_TOKEN')
}
response = requests.get(url, params=params)
result = response.json()
if result.get('status') == 'success':
balance = result.get('data', {}).get('load_balance', 0)
print(f"Current balance: {balance} SMS credits")
return balance
else:
print(f"Error: {result.get('message')}")
return None
# Usage
balance = check_balance()
if balance and balance < 10:
print("Warning: Low balance! Consider topping up.")
Best Practices
1. Store Credentials Securely
Never hardcode your API token. Use environment variables or a secure configuration management system:
# .env file (never commit this!)
IPROG_SMS_API_TOKEN=your_actual_token_here
# In your code
import os
api_token = os.getenv('IPROG_SMS_API_TOKEN')
2. Validate Phone Numbers
Always validate phone numbers before sending:
import re
def validate_philippine_phone(phone_number):
# Remove any spaces, dashes, or plus signs
cleaned = re.sub(r'[ -+]', '', phone_number)
# Check if it starts with 63 and has 12 digits total
pattern = r'^63[9]d{9}$'
return bool(re.match(pattern, cleaned))
# Usage
phone = '639171234567'
if validate_philippine_phone(phone):
# Send SMS
pass
else:
print("Invalid phone number format")
3. Implement Retry Logic
Network issues can cause temporary failures. Implement retry logic with exponential backoff:
import time
import random
def send_with_retry(url, data, max_retries=3):
for attempt in range(max_retries):
try:
response = requests.post(url, json=data, timeout=10)
if response.status_code == 200:
return response.json()
except requests.exceptions.RequestException:
if attempt < max_retries - 1:
# Exponential backoff with jitter
wait_time = (2 ** attempt) + random.uniform(0, 1)
time.sleep(wait_time)
else:
raise
return None
4. Handle Message Length
SMS messages have different character limits based on encoding:
- GSM-7 (standard characters): 160 characters per SMS, 153 characters per segment for multi-part messages
- Unicode (emojis & special characters): 70 characters per SMS, 67 characters per segment for multi-part messages
Important: Using emojis or special Unicode characters reduces the character count per SMS segment from 153 to 67 characters, which means your message will use more SMS credits.
import re
def calculate_sms_count(message):
# Check if message contains Unicode characters (emojis, special chars)
has_unicode = bool(re.search(r'[^-]', message))
if has_unicode:
# Unicode encoding: 70 chars per SMS, 67 per segment for multi-part
if len(message) <= 70:
return 1
else:
return 1 + ((len(message) - 70) // 67) + (1 if (len(message) - 70) % 67 > 0 else 0)
else:
# GSM-7 encoding: 160 chars per SMS, 153 per segment for multi-part
if len(message) <= 160:
return 1
else:
return 1 + ((len(message) - 160) // 153) + (1 if (len(message) - 160) % 153 > 0 else 0)
# Usage
message1 = "Your standard message here..." # GSM-7
message2 = "Your message with emoji 🎉 here..." # Unicode
sms_count1 = calculate_sms_count(message1)
sms_count2 = calculate_sms_count(message2)
print(f"Standard message: {sms_count1} SMS credit(s)")
print(f"Message with emoji: {sms_count2} SMS credit(s)")
5. Use Queues for High Volume
For high-volume sending, implement a queue system to avoid rate limits:
from queue import Queue
import threading
sms_queue = Queue()
def sms_worker():
while True:
item = sms_queue.get()
if item is None:
break
phone_number, message = item
send_sms(phone_number, message)
sms_queue.task_done()
time.sleep(1) # Rate limiting
# Start worker threads
for _ in range(3): # 3 concurrent workers
threading.Thread(target=sms_worker, daemon=True).start()
# Add messages to queue
sms_queue.put(('639171234567', 'Message 1'))
sms_queue.put(('639171234568', 'Message 2'))
6. Log All SMS Activity
Keep logs of all SMS sent for debugging and auditing:
import logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
def send_sms_with_logging(phone_number, message):
try:
result = send_sms(phone_number, message)
logger.info(f"SMS sent successfully. ID: {result.get('message_id')}, To: {phone_number}")
return result
except Exception as e:
logger.error(f"Failed to send SMS to {phone_number}: {str(e)}")
raise
Common Use Cases
1. OTP (One-Time Password) Verification
IPROG SMS provides a built-in OTP API that handles OTP generation, sending, and verification automatically. This is much easier than implementing it manually!
Send OTP
Use the dedicated OTP endpoint to send a verification code:
POST /api/v1/otp/send_otp
Parameters:
- api_token: Your API token
- phone_number: Recipient's phone number
- message: (optional) Custom message. Use :otp placeholder for the code. Default: "Your OTP code is :otp. It is valid for 5 minutes. Do not share this code with anyone."
- code_length: (optional) Length of OTP code (default: 6)
Example (Python):
import requests
import os
def send_otp(phone_number, custom_message=None):
url = 'https://iprogsms.com/api/v1/otp/send_otp'
data = {
'api_token': os.getenv('IPROG_SMS_API_TOKEN'),
'phone_number': phone_number
}
if custom_message:
data['message'] = custom_message
response = requests.post(url, json=data)
return response.json()
# Usage
result = send_otp('639171234567')
if result.get('status') == 'success':
print(f"OTP sent! Code: {result['data']['otp_code']}")
print(f"Expires at: {result['data']['otp_code_expires_at']}")
Verify OTP
Verify the OTP code entered by the user:
POST /api/v1/otp/verify_otp
Parameters:
- api_token: Your API token
- phone_number: Recipient's phone number
- otp: The OTP code to verify
Example (Python):
def verify_otp(phone_number, otp_code):
url = 'https://iprogsms.com/api/v1/otp/verify_otp'
data = {
'api_token': os.getenv('IPROG_SMS_API_TOKEN'),
'phone_number': phone_number,
'otp': otp_code
}
response = requests.post(url, json=data)
return response.json()
# Usage
result = verify_otp('639171234567', '123456')
if result.get('status') == 'success':
print("OTP verified successfully!")
else:
print(f"Verification failed: {result.get('message')}")
Benefits of using the built-in OTP API:
- Automatic OTP generation (6 digits by default, configurable)
- Built-in expiration handling (5 minutes default)
- Automatic SMS sending with proper formatting
- Secure verification with expiration checks
- No need to store OTPs in your database
2. Scheduled Message Reminders
IPROG SMS provides a built-in reminder API that automatically sends SMS messages at scheduled times. No need to set up cron jobs or task schedulers!
Create a Reminder
Schedule a message to be sent at a specific date and time:
POST /api/v1/message-reminders
Parameters:
- api_token: Your API token
- phone_number: Recipient's phone number
- message: The message to send
- scheduled_at: Date and time in format: YYYY-MM-DDTHH:MM (e.g., 2024-02-15T14:30)
Example (Python):
from datetime import datetime, timedelta
def create_reminder(phone_number, message, scheduled_at):
url = 'https://iprogsms.com/api/v1/message-reminders'
data = {
'api_token': os.getenv('IPROG_SMS_API_TOKEN'),
'phone_number': phone_number,
'message': message,
'scheduled_at': scheduled_at.strftime('%Y-%m-%dT%H:%M')
}
response = requests.post(url, json=data)
return response.json()
# Schedule reminder 24 hours before appointment
appointment = datetime(2024, 2, 15, 14, 30)
reminder_time = appointment - timedelta(hours=24)
result = create_reminder(
'639171234567',
'Reminder: You have an appointment tomorrow at 2:30 PM.',
reminder_time
)
if result.get('status') == 'success':
print(f"Reminder scheduled: {result['message']}")
Update or Delete Reminders
You can also update or delete scheduled reminders:
- GET /api/v1/message-reminders/:id - View a reminder
- PATCH /api/v1/message-reminders/:id - Update a reminder
- DELETE /api/v1/message-reminders/:id - Delete a reminder
Benefits of using the built-in Reminder API:
- No need to set up cron jobs or task schedulers
- Automatic message sending at scheduled times
- Easy to update or cancel reminders
- Reliable delivery without managing background jobs
3. Transactional Notifications
def send_transaction_notification(phone_number, transaction_type, amount, reference):
if transaction_type == 'payment_received':
message = f"Payment of ₱{amount:,.2f} received. Reference: {reference}"
elif transaction_type == 'order_shipped':
message = f"Your order {reference} has been shipped!"
else:
message = f"Transaction update: {transaction_type}. Reference: {reference}"
return send_sms(phone_number, message)
Rate Limits and Quotas
Important: Rate limiting is currently only applied to the web interface (sending SMS through the website), not to API endpoints. API users can send messages without rate limit restrictions.
Web Interface Rate Limits
If you're using the web interface to send SMS, you may encounter rate limits:
- Per-minute limit: 3 requests per minute for non-premium accounts
- Daily limit: Varies based on account type (typically 20-1000 messages per day)
API Usage
API endpoints do not have rate limits enforced. However, we still recommend:
- Implementing request throttling in your application to avoid overwhelming your system
- Using bulk sending endpoints when sending to multiple recipients (more efficient than individual requests)
- Monitoring your API usage and account balance
- Implementing proper error handling and retry logic
Testing Your Integration
Before going live, thoroughly test your SMS integration:
- Test with your own phone number first
- Test error scenarios: Invalid tokens, insufficient balance, invalid phone numbers
- Test rate limiting: Send multiple messages quickly to see how your app handles limits
- Test message length: Try messages of different lengths (short, exactly 160 chars, long multi-part)
- Monitor delivery: Check message status to ensure delivery
Troubleshooting
Messages Not Sending
- Check your API token is correct
- Verify you have sufficient SMS credits
- Ensure phone numbers are in correct format (639XXXXXXXXX)
- Check for rate limit errors
- Review error messages in API responses
Messages Delayed
- SMS delivery is typically instant but can take up to a few minutes during peak times
- Check message status using the status endpoint
- Verify the recipient's phone is powered on and has signal
High Failure Rate
- Verify phone number formats are correct
- Check if recipient numbers are valid and active
- Review message content for any restricted content
- Contact support if issues persist
Conclusion
Integrating SMS notifications into your application is straightforward with IPROG SMS. By following this guide, you should be able to:
- Send single and bulk SMS messages
- Check message delivery status
- Handle errors gracefully
- Implement best practices for production use
Remember to always:
- Keep your API token secure
- Validate phone numbers before sending
- Implement proper error handling and retry logic
- Monitor your SMS usage and account balance
- Test thoroughly before deploying to production
For additional support, documentation, and code examples, visit our website or check out our code examples.
Happy coding! 🚀