On this page
Before you start
Indian telecom regulations (TRAI TCCCPR 2018) require every business SMS to be registered on a DLT platform. Messages that don't match your DLT registration are blocked by the operator, even if the API call succeeds. Complete these steps before you integrate:
- Create a SpringEdge account. Sign up to get access to the SMS panel, your API key and your SMS service URL.
- Register your business (Principal Entity) on DLT. You'll receive a 19-digit Entity ID. See the DLT entity registration guide.
- Register your Sender ID (header). A 6-character header, such as
SEDEMO, approved on DLT. See the DLT Sender ID guide. - Get your message templates approved. Every message you send must match an approved DLT content template, with only the variable parts changed. See the DLT template approval guide.
- Share your DLT details with SpringEdge. Send us your Entity ID, headers and template IDs so we can link them to your account and complete the PE–TM chain.
Not sure where you stand? The DLT information hub explains the whole process, and DLT troubleshooting covers the most common reasons messages are rejected.
Base URL & API key
Every request in this documentation starts with <SMS_SERVICE_URL>. This is your account's SMS service URL, shared with you after sign-up. Replace the placeholder with that URL, including https://.
<SMS_SERVICE_URL>/api/web/send/
Requests are authenticated with the apikey parameter. Generate your API key from your SMS account. For extra protection, your API key can be restricted to accept requests only from specific IP addresses. Ask support to enable IP whitelisting.
Keep your API key secret. Call the API only from your server. Never call it from front-end code such as JavaScript, jQuery or HTML forms, where the key would be visible to anyone.
Request basics
- Methods: every endpoint accepts HTTP
GETorPOST. We recommendPOSTfor larger payloads and better security. - Encoding: send parameters form-encoded (like an HTML form submission). All values must be URL-encoded, especially the
messagetext. - Parameter names are case-sensitive. Use
apikey, notAPIKey. - HTTPS: both HTTP and HTTPS are supported. Use HTTPS so your API key and message content are encrypted in transit.
- Response format: plain text by default. Add
format=jsonorformat=xmlto any request to change it. See response formats. - Rate limit: a maximum of 10 requests per second per IP address. Flooding the API, for example from an unthrottled loop, can get your IP address temporarily blocked.
- Retries: if an operator network is down, our gateway keeps retrying your message for up to six hours before marking it failed.
- Duplicates are not filtered. The same number, sender and message submitted twice will be sent twice, so make sure your code doesn't resubmit on retries.
Send SMS
Sends a transactional (service) SMS to a mobile number. On success the API returns a message ID. Store it so you can match delivery reports to the message later.
<SMS_SERVICE_URL>/api/web/send/
Parameters
| Parameter | Required | Description |
|---|---|---|
apikey |
Yes | API key generated from your SMS account. |
sender |
Yes | Approved Sender ID (header) assigned to your account, e.g. SEDEMO. |
to |
Yes | Recipient's 10-digit mobile number. The 91 or +91 prefix is optional. |
message |
Yes | SMS text, URL-encoded. Must match one of your DLT-approved templates. |
format |
No | json or xml. Plain text if omitted. |
unicode |
No | Set to 1 to send a Unicode SMS, for example Hindi or Tamil text. |
promo |
No | Set to 1 to send a promotional SMS. |
callbackurl |
No | Your webhook URL for real-time delivery reports. |
label |
No | Your own reference ID for this message, returned in the delivery report webhook. |
Sample request
curl -X POST "<SMS_SERVICE_URL>/api/web/send/" \
--data-urlencode "apikey=YOUR_API_KEY" \
--data-urlencode "sender=SEDEMO" \
--data-urlencode "to=9900XXXXXX" \
--data-urlencode "message=Hello, This is a test message from spring edge" \
--data-urlencode "format=json"<SMS_SERVICE_URL>/api/web/send/?apikey=YOUR_API_KEY&sender=SEDEMO&to=9900XXXXXX&message=Hello%2C+This+is+a+test+message+from+spring+edge&format=json<?php
$params = [
'apikey' => 'YOUR_API_KEY',
'sender' => 'SEDEMO',
'to' => '9900XXXXXX',
'message' => 'Hello, This is a test message from spring edge',
'format' => 'json',
];
$ch = curl_init('<SMS_SERVICE_URL>/api/web/send/');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => http_build_query($params),
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
]);
$response = curl_exec($ch);
curl_close($ch);
$result = json_decode($response, true);
echo $result['MessageIDs'];import requests
response = requests.post(
"<SMS_SERVICE_URL>/api/web/send/",
data={
"apikey": "YOUR_API_KEY",
"sender": "SEDEMO",
"to": "9900XXXXXX",
"message": "Hello, This is a test message from spring edge",
"format": "json",
},
timeout=30,
)
print(response.json())// Node.js 18+ (built-in fetch)
const params = new URLSearchParams({
apikey: 'YOUR_API_KEY',
sender: 'SEDEMO',
to: '9900XXXXXX',
message: 'Hello, This is a test message from spring edge',
format: 'json',
});
const response = await fetch('<SMS_SERVICE_URL>/api/web/send/', {
method: 'POST',
body: params,
});
console.log(await response.json());Sample response
{
"groupID": 61,
"MessageIDs": "61-1",
"status": "AWAITED-DLR"
}<xml>
<groupID>62</groupID>
<MessageIDs>62-1</MessageIDs>
<status>AWAITED-DLR</status>
</xml>AWAITED-DLR means the message was accepted and handed to the operator (SMSC), and is waiting for a delivery report. Use MessageIDs to check the status of a single message and groupID to check the whole request.
Send Unicode SMS
To send messages in regional languages such as Hindi, Kannada or Tamil, add unicode=1 to the send request and pass the message text in that language. Unicode messages carry fewer characters per SMS. See message length.
<SMS_SERVICE_URL>/api/web/send/?unicode=1
| Parameter | Required | Description |
|---|---|---|
apikey |
Yes | API key generated from your SMS account. |
to |
Yes | Recipient's mobile number, with or without 91 / +91. |
sender |
Yes | Approved Sender ID (header). |
message |
Yes | The text, written in the language you want to send, URL-encoded. |
unicode |
Yes | Must be 1. |
Sample request
curl -X POST "<SMS_SERVICE_URL>/api/web/send/" \
--data-urlencode "apikey=YOUR_API_KEY" \
--data-urlencode "sender=SEDEMO" \
--data-urlencode "to=9900XXXXXX" \
--data-urlencode "message=नमस्ते, स्प्रिंग एज की ओर से यह एक परीक्षण संदेश है" \
--data-urlencode "unicode=1" \
--data-urlencode "format=json"
Sample response
{
"groupID": 1234,
"messages": [
{
"id": "1234-1",
"mobile": "9900xxxxxx",
"status": "AWAITED_DLR"
}
]
}<xml>
<groupID>1234</groupID>
<messages>
<sms>
<id>1234-1</id>
<mobile>9900xxxxxx</mobile>
<status>AWAITED_DLR</status>
</sms>
</messages>
</xml>Send promotional SMS
To send a promotional (marketing) message, add promo=1 to the send request. Promotional SMS use a numeric header, are delivered only to numbers not registered on DND for that category, and can only be sent during the permitted hours (9 AM to 9 PM). Read transactional vs promotional SMS for the differences.
<SMS_SERVICE_URL>/api/web/send/?promo=1
| Parameter | Required | Description |
|---|---|---|
apikey |
Yes | API key generated from your SMS account. |
to |
Yes | Recipient's mobile number, with or without 91 / +91. |
sender |
Yes | Approved promotional Sender ID (header). |
message |
Yes | The text to send, URL-encoded. |
promo |
Yes | Must be 1. |
Sample request
curl -X POST "<SMS_SERVICE_URL>/api/web/send/" \
--data-urlencode "apikey=YOUR_API_KEY" \
--data-urlencode "sender=XXXXXX" \
--data-urlencode "to=9900XXXXXX" \
--data-urlencode "message=Your promotional message text" \
--data-urlencode "promo=1" \
--data-urlencode "format=json"
Sample response
{
"groupID": 1234,
"messages": [
{
"id": "1234-1",
"mobile": "9900xxxxxx",
"status": "AWAITED_DLR"
}
]
}<xml>
<groupID>1234</groupID>
<messages>
<sms>
<id>1234-1</id>
<mobile>9900xxxxxx</mobile>
<status>AWAITED_DLR</status>
</sms>
</messages>
</xml>Response formats
By default the API responds in plain text. Add format=json or format=xml to any request to get a structured response that is easier to parse:
<SMS_SERVICE_URL>/api/web/send/?apikey=YOUR_API_KEY&sender=XXXXXX&to=9900xxxxxx&message=TEST&format=json
<SMS_SERVICE_URL>/api/web/send/?apikey=YOUR_API_KEY&sender=XXXXXX&to=9900xxxxxx&message=TEST&format=xml
Error codes
If a request can't be processed, the API returns one of the following messages instead of a message ID:
| Response | Meaning | How to fix |
|---|---|---|
Invalid Input Data |
A required parameter or its value is missing. | Check that apikey, sender, to and message are all present and spelled in lowercase. |
Account Inactive. Please contact Support |
Your SMS account is inactive or deactivated. | Contact support. |
Invalid Mobile Numbers |
The mobile number is invalid or has fewer than 10 digits. | Send a valid 10-digit Indian mobile number. |
Invalid Sender ID |
The Sender ID (header) is not applied for or not yet approved on your account. | Use an approved header. See the Sender ID guide. |
Insufficient Credits |
Your SMS account is out of credits. | Recharge your account. |
Invalid Message GID |
The message group ID is invalid. | Use the groupID returned by the send API. |
Invalid Schedule Date and Time! |
The schedule time is invalid. | Correct the time value. |
Invalid Schedule Date! |
The schedule date is invalid. | Correct the date value. |
Delivery report webhook (push)
Instead of polling for delivery status, you can have SpringEdge notify your server the moment a message's status changes. Add two extra parameters to your send SMS request:
| Parameter | Required | Description |
|---|---|---|
callbackurl |
Yes | The URL on your server that should receive the delivery report, URL-encoded. It must be reachable from the internet. |
label |
Yes | Your own reference for the message, such as an order or message ID from your system. It is sent back to you with the delivery report so you can match it. |
Sample request
curl -X POST "<SMS_SERVICE_URL>/api/web/send/" \
--data-urlencode "apikey=YOUR_API_KEY" \
--data-urlencode "sender=SEDEMO" \
--data-urlencode "to=9900XXXXXX" \
--data-urlencode "message=Test message" \
--data-urlencode "format=json" \
--data-urlencode "callbackurl=https://yourdomain.com/receivestatus/" \
--data-urlencode "label=ORDER-10245"
What your server receives
When the operator reports the final status, SpringEdge calls your callbackurl with these parameters:
https://yourdomain.com/receivestatus/?label=ORDER-10245&recipient=9900XXXXXX&status=DELIVRD
| Parameter | Description |
|---|---|
label |
The label you sent with the message. |
recipient |
The destination mobile number. |
status |
Delivery status: DELIVRD (delivered), UNDLIVRD (not delivered) or FAILED. |
Sample webhook handler
<?php
// receivestatus/index.php - stores the delivery status sent by SpringEdge
$label = $_REQUEST['label'] ?? '';
$recipient = $_REQUEST['recipient'] ?? '';
$status = $_REQUEST['status'] ?? '';
if ($label !== '') {
$pdo = new PDO('mysql:host=localhost;dbname=app', 'user', 'password');
$stmt = $pdo->prepare('UPDATE sms_log SET status = ?, recipient = ? WHERE label = ?');
$stmt->execute([$status, $recipient, $label]);
}
http_response_code(200);
echo 'OK';
Tip: Use a unique label for every message, respond quickly with HTTP 200, and do any heavy processing after responding.
Single message status (pull)
Fetch the current delivery status of one message using the message ID returned when it was sent.
<SMS_SERVICE_URL>/api/status/message?apikey=YOUR_API_KEY&messageid=MESSAGE_ID
| Parameter | Required | Description |
|---|---|---|
apikey |
Yes | API key generated from your SMS account. |
messageid |
Yes | The message ID returned by the send API, e.g. 363-1. |
format |
No | json or xml. |
Sample response
{
"id": "363-1",
"Recipient": "+919900xxxxxx",
"status": "AWAITED-DLR"
}<xml>
<id>363-1</id>
<Recipient>+919900xxxxxx</Recipient>
<status>AWAITED-DLR</status>
</xml>| Response | Meaning |
|---|---|
SUBMITTED / DELIVRD / UNDELIVRD / REJECTED |
The current delivery status of the message. |
Invalid Input Data |
A required value is missing. |
Account Inactive. Please Contact Support |
Your SMS account is inactive or deactivated. |
Invalid Message ID |
The message ID does not exist. |
Group status (pull)
Fetch the delivery status of every message in one send request using its group ID.
<SMS_SERVICE_URL>/status/group?apikey=YOUR_API_KEY&messagegid=GROUP_ID
| Parameter | Required | Description |
|---|---|---|
apikey |
Yes | API key generated from your SMS account. |
messagegid |
Yes | The groupID returned by the send API. |
format |
No | json or xml. |
Sample response
{
"ID": "363-1",
"Recipient": "+919900xxxxxx",
"StatusDetails": "AWAITED-DLR",
"UpdatedTime": "2013-06-17 14:40:59"
}<xml>
<sms>
<ID>363-1</ID>
<Recipient>+919900xxxxxx</Recipient>
<StatusDetails>AWAITED-DLR</StatusDetails>
<UpdatedTime>2013-06-17 14:40:59</UpdatedTime>
</sms>
</xml>| Response | Meaning |
|---|---|
Submitted / Delivered / Undelivered / Rejected |
The current delivery status of each message. |
Invalid Input Data |
A required value is missing. |
Account Inactive. Please contact support |
Your SMS account is inactive or deactivated. |
Invalid Message GID |
The group ID is invalid. |
Check credit balance
Returns the number of SMS credits available in your account. Useful for low-balance alerts in your application.
<SMS_SERVICE_URL>/api/status/credit?apikey=YOUR_API_KEY
Sample response
{"Credits": "485000"}<xml>
<Credits>485000</Credits>
</xml>| Response | Meaning |
|---|---|
Your available credits is <VALUE> |
The number of credits available in your account (plain-text response). |
Invalid Input Data |
A value in the URL is missing. |
Account Inactive . Please contact support |
Your account is inactive or deactivated. |
Message length & encoding
Credits are charged per SMS part. Longer messages are automatically split into parts and joined back together on the recipient's phone. Each part loses a few characters to the header (UDH) that links the parts together.
| SMS parts | English (GSM 03.38) | Unicode (Hindi, Tamil, etc.) |
|---|---|---|
| 1 | 160 characters | 70 characters |
| 2 | 306 characters (2 × 153) | 134 characters (2 × 67) |
| 3 | 459 characters (3 × 153) | 201 characters (3 × 67) |
| n | n × 153 characters | n × 67 characters |
| Maximum | 2,000 characters | 1,000 characters |
GSM 03.38 (standard) characters
Messages that use only the standard GSM character set (English letters, digits and common symbols) get 160 characters per SMS:
@ £ $ ¥ è é ù ì ò Ç Ø ø Å å Δ _ Φ Γ Λ Ω Π Ψ Σ Θ Ξ Æ æ ß É ! " # ¤ % & ' ( ) * + , - . /
0 1 2 3 4 5 6 7 8 9 : ; < = > ? ¡ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
Ä Ö Ñ Ü § ¿ a b c d e f g h i j k l m n o p q r s t u v w x y z ä ö ñ ü à
These extended characters count as two characters each: ^ { } \ [ ] ~ | €. Any character outside the GSM set, such as emojis or regional scripts, switches the whole message to Unicode, which has a limit of 70 characters per SMS.
Mobile numbers & sender ID
Mobile number format
Send valid 10-digit Indian mobile numbers starting with 6, 7, 8 or 9, for example 9XXXXXXXXX. The 91 or +91 country code prefix is optional.
Sender ID (header)
Every SMS carries a header that appears as the sender name on the recipient's phone. You can use any header approved for your account. Headers are 6 characters long:
- Transactional / service messages: alphabetic header, e.g.
SEDEMO. - Promotional messages: numeric header.
Read the DLT Sender ID guide to register a new header.
Help & support
Need your <SMS_SERVICE_URL>, IP whitelisting, higher throughput or help with an integration? Email contact@springedge.com or contact us.
Looking for ready-made code? See the Postman collection, PHP, Python, Java and Node.js integration guides, or browse plugins and add-ons.
