SMS API Reference: Endpoints, Parameters and Status Codes
Every endpoint, field, reply and status code for our SMS APIs on one page. Use it alongside the getting-started guide when you build, test or debug an integration with the v2 REST, URL or XML API.

Send SMS with POST /api/v2/sms/send, passing sender_id, recipient and message as JSON with your API key as a Bearer token. A 200 reply returns a message_id with status queued. Delivery reports are pushed to your webhook URL or read from the status endpoint. Older software can use the URL API at /httpapi/send, which replies in plain text.
Endpoints
Base host https://whitelabled.securesmsc.com. The v2 REST API takes JSON and a Bearer key. The URL and XML APIs suit older software that can only call a link.
| Method | Path | What it does |
|---|---|---|
POST | /api/v2/sms/send | Send one SMS |
POST | /api/v2/sms/send-bulk | Send one message to 1 to 1,000 numbers |
POST | /api/v2/sms/schedule | Schedule one SMS (scheduled_at required) |
GET | /api/v2/sms/status/{id} | Status of a message, by message ID or broadcast ID |
GET | /api/v2/balance | Your SMS credit balance |
GET | /api/v2/sender-ids | Your approved sender IDs and DLT header IDs |
GET | /api/v2/templates | Your approved templates and DLT template IDs |
GET, POST | /httpapi/send | URL-style send for Tally, ERPs and plug-ins (plain-text reply) |
POST | /xmlapi/send | Many numbers and messages in one XML post |
GET | /api/smsdlr | Status of one number in a broadcast (plain text) |
GET | /api/getcredits | Credit balance as plain text |
POST /api/v2/sms/send parameters
| Field | Required | Meaning |
|---|---|---|
sender_id | Yes | Your approved sender ID, up to 11 characters, such as ACMEIN. |
recipient | Yes | One mobile number: 10 digits, or with country code such as 919812345678. send-bulk takes recipients, an array of up to 1,000. |
message | Yes | Up to 1,600 characters. For India it must match an approved DLT template. |
route | No | transactional (default) or promotional. |
dlt_entity_id | No | Your DLT entity ID. Defaults to the one saved on your sender ID or account. |
dlt_template_id | No | The DLT template ID. If you leave it out, the message is matched against your approved templates. |
schedule_at | No | A future date and time to send. scheduled_at on the /schedule endpoint. |
timezone | No | Timezone for the schedule time. Default Asia/Kolkata (IST). |
unicode | No | true for Tamil, Hindi or emoji text. Unicode is also detected automatically. |
flash | No | true for a flash SMS, where the route supports it. |
Responses
# 200 OK {"success": true, "message": "SMS queued successfully", "data": {"message_id": "48213907", "queue_id": "48213907", "status": "queued"}} # 422 Unprocessable {"success": false, "error": "Validation failed", "message": "Invalid request parameters", "errors": {"recipient": ["The recipient format is invalid."]}}
HTTP status codes
| Status | Meaning |
|---|---|
200 | Accepted. data.message_id and status queued. |
400 | Invalid sender ID, or dispatch failed, for example insufficient credits. |
401 | Missing, invalid, disabled or expired API key, or inactive account. |
403 | Request from an IP address not allowed for this key, or read access not enabled for GET calls. |
422 | Validation failed, or TEMPLATE_MISMATCH: the text does not match an approved DLT template. |
429 | Rate limit reached. Wait for the Retry-After seconds, then retry. |
500 | Server error. Retry with back-off. |
URL API: /httpapi/send
GET or POST. The reply is plain text: a broadcast ID on success, or a negative code.
| Parameter | Meaning |
|---|---|
api_key | Your API key. username and password also work. |
sender_id | Approved 6-character header, such as KOVAIM, without prefix or suffix. |
phonenumber | One or more numbers, comma-separated. On routes T and P the last 10 digits are used. |
message | Plain English text that matches your DLT template. |
text | Use in place of message for Unicode text such as Tamil or Hindi. |
route | T for service and transactional, P for promotional. |
flash | 1 for a flash SMS. |
schedule | Send later: YYYY-MM-DD HH:MM:SS in IST. |
| Reply | Meaning |
|---|---|
-5 | Missing or invalid mobile number |
-6 | Missing message |
-7 | Invalid API key or login |
-10 | Invalid sender ID |
-12 | Not enough credits |
-17 | Invalid route |
-18 | Route T used with the promotional sender |
-19 | Route P used without the promotional sender |
-20 | International SMS not enabled on the account |
-40 | Unicode text sent in message. Use text instead |
-41 | The route cannot carry this message |
XML API: POST /xmlapi/send
<root>
<username>acme</username>
<password>YOUR_PASSWORD</password>
<senderid>ACMEIN</senderid>
<messages>
<message number="9812345678" text="Dear Priya, your order KM2431 has shipped. - Kovai Mart"/>
<message number="9898012345" text="Dear Arun, your order KM2432 has shipped. - Kovai Mart"/>
</messages>
</root>Delivery report push
GET https://your-server.example/dlr?messageid=1042_9f3c27d1e8a54b6f_1761972245&status=delivered&number=9812345678&date=2026-11-01+10:24:05
Delivery status values
| Group | Values you may see | What to do |
|---|---|---|
Delivered | DELIVRD, delivered | Final. The handset received the SMS. |
Failed | failed, UNDELIV, REJECTD, EXPIRED, NUMBER NOT VALID, NUMBER IS BLOCKED, PROMO NOT ALLOWED | Final. Not delivered. Check the number, the template or DND status. |
Pending | Submitted to SMSC, Scheduled | Not final yet. A delivered or failed status follows. |
Three ways in
JSON REST for new code, a URL API for plug-ins and an XML API for batches.
DLT fields built in
Pass dlt_template_id, or let the platform match your approved templates.
Push or pull reports
Get delivery status at your webhook, or ask for it by message ID.
Clear failure codes
Each rejection has a status or code that tells you exactly what to fix.
Which API should you use?
Use the v2 REST API for anything new. It takes JSON, returns JSON with clear HTTP status codes, supports scheduling and bulk sends of up to 1,000 numbers per call, and gives you endpoints for balance, sender IDs and templates.
Use the URL API at /httpapi/send when the software you connect can only call a web link, as many Tally SMS modules, ERPs and older plug-ins do. You put the key, sender, number and text in the URL, and the reply is plain text: a broadcast ID or a negative code.
The XML API suits systems that already produce XML. One post can carry many numbers, each with its own text.
Authentication and keeping your key safe
Create an API key in the panel and send it as a Bearer token in the Authorization header. The URL API takes it as the api_key parameter. Keep the key on your server. Never put it in a browser page or a mobile app, where anyone can read it.
In the v2 API, a key is tied to the server IP addresses allowed to use it. The first server that calls with a new key is added automatically, and calls from other addresses get HTTP 403. If you send from more than one server, move servers or call from a cloud service such as Salesforce, ask us to add the address or range.
Read endpoints such as balance, status, sender IDs and templates use GET, which is switched off on a new key. Ask our team to enable read access for your key when you need it.
How DLT matching works in the API
Every SMS to an Indian number must match a template approved on the DLT portal. In the v2 API you can pass dlt_template_id and dlt_entity_id with each message. If you leave them out, the platform uses the entity saved on your sender ID and compares your text with your approved templates.
When the text does not match any approved template, the v2 API replies with HTTP 422 and TEMPLATE_MISMATCH. Fix the wording so only the {#var#} parts change, or register a new template. In the URL API the message is not sent and its report shows PROMO NOT ALLOWED.
Delivery reports and message IDs
Set a delivery report URL on the Webhooks page of the panel. When a number reaches a final status, we call your URL once with the broadcast ID, status, number and send time. You can also ask for a status at any time with GET /api/v2/sms/status/{id}, which accepts a message ID or a broadcast ID.
The single-send reply gives you a message_id, while a bulk send also returns a broadcast_id. Pushed reports carry the broadcast ID, so for single sends, match pushed reports on the number and send time, or check the status endpoint with your message_id.
Limits, retries and errors
Each key has a per-minute and a per-day request limit, which we set to suit your traffic. Every reply carries X-RateLimit headers showing your limit and what remains. If you hit it, you get HTTP 429 with a Retry-After header. Wait that long, then retry. For campaigns, use send-bulk instead of one call per number.
Retry only temporary failures, such as timeouts, 429 and 500 replies, with a wait that grows each time. Do not retry 400, 401, 403 or 422 replies. They will fail again until you fix the key, sender, IP address, template or credit balance.
How it works
Create a key
Generate an API key in the panel and store it on your server only.
Check your sender
Call the sender ID and template endpoints, or copy the IDs from the panel.
Send a test
Send to your own number and confirm the 200 reply and the message_id.
Wire up reports
Set your delivery report URL and log every status against the message.
Frequently asked questions
Where do I get my SMS API key?
Log in to the panel and open the API settings page to create a key. You can create a new key and retire the old one at any time. Send it as a Bearer token for the v2 API or as api_key for the URL API. Keep it on your server and never in front-end code.
Why does my new server get HTTP 403?
In the v2 API, each key is tied to the IP addresses allowed to use it. The first server that uses a new key is added automatically, and other addresses are refused with 403. Ask our support team to add your new server's public IP address to the key, then try again. GET calls also return 403 until read access is enabled.
What does TEMPLATE_MISMATCH mean?
Your message text does not match any DLT template approved for that sender. Only the {#var#} parts of a template may change. Check spaces, punctuation and the brand name at the end against the approved text, or pass the exact dlt_template_id. If the wording is new, register it as a template first.
Is there an OTP generate and verify API?
No. Your app creates the code, stores it with an expiry time and checks what the user enters. You send the code through the SMS API like any other message, using an approved OTP template on a service route. Our OTP security guide covers expiry, retry limits and SMS pumping protection.
What is the difference between message_id and broadcast ID?
The v2 send reply returns a message_id for the queued SMS. A broadcast ID identifies a send request and is what the URL API returns and what pushed delivery reports carry. The status endpoint accepts either. For bulk sends, the reply includes the broadcast_id, so you can match pushed reports directly.
Which delivery statuses are final?
Delivered and failed statuses are final, such as delivered, DELIVRD, UNDELIV, REJECTD, EXPIRED, NUMBER NOT VALID and NUMBER IS BLOCKED. Statuses such as Submitted to SMSC and Scheduled mean the SMS is still on its way, so wait for a final status before you act on it.
Get your API key
Create an account, add your DLT details and send your first test SMS from code.

