How to Send Transactional SMS in India: Order Updates, Payment Receipts, and Delivery Alerts (2026)
Send transactional SMS API India. Integrate Node.js & Python code for order updates & delivery alerts. Learn DLT requirements vs. DLT-free OTP routing.
Indian consumer businesses run on instant notifications. When a user buys a product, pays a utility bill, or requests a login code, they expect an SMS within seconds. If that message gets delayed or fails, customer support channels overflow and conversion rates drop immediately.
Integrating a transactional sms api india requires more than just calling an endpoint. Indian developers must navigate a complex regulatory framework overseen by the Telecom Regulatory Authority of India (TRAI), manage carrier scrubbing rules, and design resilient fallback systems. This tutorial shows you how to send transactional messages like order updates, payment receipts, and delivery alerts to Indian phone numbers using Node.js and Python, while explaining how to handle the country’s strict Distributed Ledger Technology (DLT) compliance.
Understanding TRAI Rules for Transactional SMS in India
Before writing code, you need to understand how the Indian government categorizes SMS traffic. TRAI mandates that all commercial text messages sent over Indian telecom networks fall into distinct categories. Sending transactional SMS in India requires compliance with these specific definitions.
The first category is Transactional SMS. Under strict TRAI guidelines, transactional messages are limited to transactional banking alerts sent by registered banks. These include OTPs, transaction receipts, and balance alerts. If you are a standard e-commerce company, SaaS application, or logistics platform, your notifications are technically classified as Service Implicit messages.
Service Implicit messages cover order updates, delivery status alerts, appointment reminders, and password resets. In terms of delivery rules, both transactional and service implicit categories behave the same way: they bypass Do-Not-Disturb (DND) registries and are delivered 24/7.
Promotional messages, on the other hand, contain marketing material, discounts, or sales offers. These messages can only be sent between 9:00 AM and 9:00 PM, and they are automatically blocked for any phone number registered on the National Customer Preference Register (NCPR), commonly known as the DND list. If you attempt to send promotional content under a transactional header, telecom operators will block the message and may suspend your sending account.
Setting Up Your Developer Integration
To start sending transactional notifications, you need access to a messaging gateway that connects to Indian carriers like Jio, Airtel, Vi, and BSNL. We will use the StartMessaging API for this integration. The platform provides pre-registered DLT routes by default, allowing you to test integrations immediately without waiting weeks for carrier entity registration.
First, sign up for a developer account at the dashboard. Once registered, generate an API key from the developer settings. Your API key starts with sm_live_ and acts as your authorization token.
Because StartMessaging operates on a pay-as-you-go model, you need to top up your wallet. The billing rate is exactly ₹0.25/OTP for transactional messages sent to Indian numbers. This flat rate covers route optimizations and carrier delivery fees with no monthly maintenance charges.
Node.js Integration for Sending Transactional SMS
We will write a complete Node.js script using the native fetch API to send transactional notifications. This code generates a custom payload containing the recipient’s phone number, a DLT template ID, and the dynamic variables required by the message template.
You must ensure phone numbers are formatted in E.164 standard, starting with the country code +91 for India.
// send-transactional-sms.js
import { randomUUID } from 'crypto';
// The base endpoint for sending transactional notifications
const API_URL = 'https://api.startmessaging.com/otp/send';
const API_KEY = 'sm_live_your_actual_api_key_here'; // Replace with your real API key
async function sendTransactionalAlert(phoneNumber, variables, templateId = null) {
// Use a unique idempotency key to prevent duplicate SMS delivery on network retries
const idempotencyKey = randomUUID();
const payload = {
phoneNumber: phoneNumber,
variables: variables
};
// If you are using your own custom DLT registration, provide the approved Template ID
if (templateId) {
payload.templateId = templateId;
}
try {
const response = await fetch(API_URL, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-API-Key': API_KEY,
'Idempotency-Key': idempotencyKey
},
body: JSON.stringify(payload)
});
const result = await response.json();
if (!response.ok) {
throw new Error(`API error: ${result.message || response.statusText}`);
}
console.log('Transactional SMS queued successfully.');
console.log(`Request ID: ${result.requestId}`);
console.log(`Message ID: ${result.data.messageId}`);
return result.data;
} catch (error) {
console.error('Failed to send transactional SMS:', error.message);
throw error;
}
}
// Example: Sending an order update notification
const customerPhone = '+919876543210';
const orderDetails = {
otp: 'ORD-5521', // The API requires an 'otp' field which can double as your order ID or code
appName: 'ShopKart India'
};
sendTransactionalAlert(customerPhone, orderDetails)
.then(data => console.log('Delivery details:', data))
.catch(err => console.error('Execution failed:', err));
The script above initializes a POST request to the API. We pass the API key in the X-API-Key header. We also attach an Idempotency-Key using a UUID. If a network timeout occurs and your server retries the request, StartMessaging checks the idempotency key and prevents sending a second, duplicate message to the user while ensuring you are only charged once.
Python Integration for Sending Transactional SMS
For Python backends, we will use the requests library to connect to the SMS gateway. This implementation includes standard error handling for network exceptions and processes the JSON response from the API.
You must install the dependency using pip install requests before running this script in your environment.
# send_transactional_sms.py
import uuid
import requests
API_URL = "https://api.startmessaging.com/otp/send"
API_KEY = "sm_live_your_actual_api_key_here" # Replace with your real API key
def send_transactional_alert(phone_number, variables, template_id=None):
# Enforce idempotency on all POST requests to prevent double sending
headers = {
"Content-Type": "application/json",
"X-API-Key": API_KEY,
"Idempotency-Key": str(uuid.uuid4())
}
payload = {
"phoneNumber": phone_number,
"variables": variables
}
# Pass the DLT template ID if using your own custom registration path
if template_id:
payload["templateId"] = template_id
try:
response = requests.post(API_URL, json=payload, headers=headers, timeout=10)
# Raise HTTPError for bad responses (4xx or 5xx)
response.raise_for_status()
result = response.json()
print("Transactional SMS dispatched successfully.")
print(f"Request ID: {result.get('requestId')}")
return result.get("data")
except requests.exceptions.Timeout:
print("Request to StartMessaging timed out. Initiate retry with the same headers.")
raise
except requests.exceptions.RequestException as e:
print(f"Network request failed: {e}")
raise
# Example: Sending a delivery status alert
recipient = "+919876543210"
alert_vars = {
"otp": "DEL-992", # Custom transactional identifiers go into the 'otp' placeholder
"appName": "QuickCart Delhi"
}
try:
sms_data = send_transactional_alert(recipient, alert_vars)
print("Message Status:", sms_data.get("status"))
except Exception as err:
print("Failed to complete sending process:", err)
The Python code handles timeouts by catching requests.exceptions.Timeout explicitly. In high-throughput systems, catching network timeouts allows your application to safely re-queue the job and trigger a retry. By retaining the same Idempotency-Key header during the retry, you ensure that the downstream carriers do not deliver duplicate alerts if the initial request actually reached the gateway.
Navigating the DLT Template Scrubbing Process
Under TRAI’s Telecom Commercial Communications Customer Preference Regulations (TCCCPR), every transactional SMS must pass through carrier-level DLT systems. If you use standard messaging providers, you must register your business entity (PE) on a portal like Jio DLT, Airtel DLT, or Videocon DLT.
The DLT workflow involves registering a Header (the 6-character sender ID, like SHPKRT) and registering Content Templates. A template defines the exact text allowed in the SMS. For example: Your order {#var#} has been shipped. Thank you for shopping with {#var#}.
When your application triggers an SMS API call, telecom operators run the message through a template scrubbing process. The operator check matches the message text against your approved DLT templates. If a variable contains unsupported characters, or if the text deviates from the approved template format, the operator rejects the SMS instantly. This results in a “Template Matching Failed” error.
StartMessaging provides a way to bypass this registration bottleneck. Because the platform maintains pre-approved DLT templates and routing channels, you can send transactional alerts immediately. The API maps your variables into pre-approved layouts, avoiding DLT setup times and template rejections.
Frequently Asked Questions
Q: Do I need my own DLT registration to send transactional SMS in India?
A: If you use a standard raw SMS gateway, yes. You must register your business entity and get templates approved, which takes 2–4 weeks. If you route through StartMessaging, you can use pre-approved DLT channels immediately, eliminating the registration delay.
Q: Can I send transactional and service implicit SMS at night?
A: Yes. Transactional and Service Implicit messages are exempt from the night-time restriction (9:00 PM to 9:00 AM) that applies to promotional campaigns. They are delivered 24/7.
Q: What happens if an SMS fails to deliver due to operator network issues?
A: Telecom carrier outages happen. StartMessaging monitors route quality in real time and automatically redirects failed messages through backup carrier paths (like Airtel or Jio) to ensure delivery rates remain in the 97–99% range.
Q: What is the maximum character limit for an Indian transactional SMS?
A: A standard single SMS contains up to 160 characters. If your message exceeds 160 characters, it is split into multi-part messages. Multi-part messages are charged per segment, so keeping your templates brief helps optimize costs.
Ready to start sending notifications without DLT delays? Sign up for a free developer account at StartMessaging Dashboard and begin testing your Node.js or Python integration immediately.
StartMessaging Team
StartMessaging Team