SMSAPI
— SMS

Send bulk SMS in India via one HTTP API

One HTTP request puts an SMS on its way to any Indian mobile number. Pass your DLT template and principal entity ID, get a delivery receipt back on your webhook, and reconcile every message by ID. The same API sends transactional OTPs and promotional campaigns — you pick the route.

What you can build

— Delivery

Delivery you can see

Every message returns a delivery receipt (DLR) on your webhook, with automatic retries and operator failover. Reconcile by message ID. Delivery rate and median latency: pending verified data.
— Integration

Live in five minutes

One HTTP POST sends your first message. Copy-paste quickstarts in five languages — cURL, Node.js, PHP, Python and Java — with a real request and response, not pseudocode.
— Compliance

DLT-ready by default

Send your principal entity ID and DLT template ID on every request. Both are validated against the TRAI registry before dispatch, so non-compliant sends fail fast instead of being scrubbed downstream.

Send your first SMS in five minutes

Authentication is a bearer token. Every send is a single POST to /v1/sms with your sender header, the route, one or more E.164 numbers, the message body, and the two DLT identifiers India requires.

The response returns a request ID and a per-number message ID. Match that ID against the delivery receipt that arrives on your webhook moments later. There is no SDK to learn first — the JSON below is the whole contract.

Switch route from transactional to promotional to send marketing traffic. The DLT identifiers and sender header change with your registered templates; the call shape does not.

Errors return a non-2xx status with a stable error code — an invalid DLT template, an unregistered header, or a malformed number each carry their own code, so you branch on the code rather than parsing a message. Send an idempotency key with a batch and a retried request returns the original result instead of sending twice.

Each response includes your current rate-limit headers, so a client that reads them can pace itself and back off cleanly instead of being throttled. Limits are per API key and scale with your account.

A single SMS is 160 GSM-7 characters, or 70 when the body contains Unicode. Longer messages are split into concatenated parts, reassembled on the handset, and each part is charged and receipted as one SMS — the API returns the part count so billing is never a surprise.

Before you send live traffic, point a test API key at the same endpoints. Test sends are accepted and receipted without touching the operator network, so you can wire up your webhook handler and reconciliation end to end, then switch to a live key once your DLT header and templates are approved.

Delivery receipts move through a small set of states — submitted, sent, delivered, or failed — and each transition is posted to your webhook with the message ID and a timestamp. A failed receipt carries a reason code, so a number that is on DND, invalid, or out of credit is something you act on rather than guess at.

Two-way SMS works on a long code or a registered keyword on a short code. Inbound messages arrive on your webhook with the sender, the destination, and the body, which is enough to build opt-outs, keyword campaigns, and lightweight support flows without polling.

Throughput scales with your account rather than your code: the same single call that sends one message sends your whole list, and the response returns a message ID for each recipient so nothing is lost in a batch. Pace large jobs with the rate-limit headers and reconcile by request ID.

Campaigns can be queued for a future timestamp in IST and cancelled before they fire — a promotional send scheduled for business hours, a reminder for the morning of an appointment.

See the full quickstart →
curl https://api.smsapi.in/v1/sms \
  -H "Authorization: Bearer $SMSAPI_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "sender": "SMSAPI",
    "route": "transactional",
    "numbers": ["+919876543210"],
    "message": "Your OTP is 481920. Valid for 10 minutes.",
    "dlt_template_id": "1707170000000000000",
    "dlt_entity_id": "1101400000000000000"
  }'

# Response
{
  "request_id": "req_3f9a2b",
  "messages": [
    { "message_id": "sms_9c81a0", "to": "+919876543210", "status": "submitted" }
  ]
}

API request shapes are representative pending the white-label telco API spec (FLAGS_AND_ASSUMPTIONS.md).

What's included

— Reliability

Delivery receipts

Per-message DLRs pushed to your webhook, with retries and operator failover.

— Routing

Transactional & promotional

Separate routes, each with its own sender header and DLT templates.

— Sender ID

Header management

Register and manage 6-character sender headers (e.g. SMSAPI) per route.

— Throughput

Send your whole list in one call

Pass an array of numbers; we fan out and report the status of each one.

— Unicode

Hindi and regional scripts

Full Unicode (UCS-2) for Devanagari and other Indian scripts, 70 characters per part.

— Reporting

Per-message logs

Searchable logs and CSV exports, keyed by request and message ID.

— Security

Key auth and IP allowlist

Rotatable bearer API keys, with optional IP allowlisting.

— Scheduling

Send now or later

Queue a campaign for a future timestamp in IST.

Built for Indian telecom compliance

SMS to Indian numbers is governed by TRAI and delivered through the DLT (Distributed Ledger Technology) framework. Before you can send, your business registers as a principal entity and receives a principal entity ID; each sender header and message template is registered separately and approved.

On every request you pass your principal entity ID and the DLT template ID that matches the message. We validate both against the registry before dispatch, so a mismatched template fails immediately rather than being silently scrubbed by the operator. Promotional traffic additionally respects DND (Do Not Disturb) preferences and time-of-day rules; transactional traffic is exempt.

Sender headers fall into categories that decide what you may send and when: transactional and service-implicit headers carry OTPs and account alerts around the clock, service-explicit headers carry consented service updates, and promotional headers carry marketing within permitted hours. Registering the right category up front avoids template rejections later.

Consent is your responsibility as the sender, and we keep the per-message records you need to evidence it. Our DLT guide covers principal entity registration, header approval, and template categories end to end.

Read the DLT registration guide →

Frequently asked

What is the DLT registration process for a new sender?

Register your business as a principal entity on a TRAI-accredited DLT portal, then register each sender header and message template. You receive a principal entity ID and a template ID for every message type. You pass both on each API request; we validate them before dispatch. Our DLT guide walks through each step.

Which SDK languages do you support?

The API is plain JSON over HTTPS, so any language with an HTTP client works. We publish quickstarts and helper libraries for cURL, Node.js, PHP, Python and Java. The request and response shapes are identical across all of them.

Can I send Unicode SMS in Hindi or regional languages?

Yes. Send the message body as UTF-8 and we encode it as Unicode (UCS-2) automatically. Unicode messages are 70 characters per part rather than 160, and long messages are concatenated. Devanagari and other Indian scripts are supported.

How do delivery webhooks work?

Each message returns a message ID synchronously. When the operator confirms the final state, we POST a delivery receipt to your configured webhook URL with that message ID and the status. Failed deliveries are retried, and you can also poll the message by ID.

What is the difference between the transactional and promotional routes?

Transactional traffic carries OTPs and service alerts to your customers at any hour, on a transactional sender header and template. Promotional traffic carries marketing content, is subject to DND scrubbing and time-of-day rules, and uses a promotional header. You select the route per request.

How is bulk SMS priced?

Pricing is per SMS, with GST shown separately, and rates step down by volume. See the pricing page for current per-message rates by route.

How do I verify a delivery webhook really came from you?

Each webhook POST is signed: a signature header is computed from the payload and your signing secret. Recompute the HMAC on your side and compare before trusting the event, then respond 2xx to acknowledge so retries stop. Reject anything that doesn't match.

— Pricing

Transparent pricing, with GST broken out

Per-SMS credit bundles, from 16.5p/SMS. Base price and 18% GST are shown separately, in rupees.

Trans2K
2,000 SMS · 28p/SMS
₹660.80
₹560 + ₹100.80 GST
Trans10K
10,000 SMS · 20p/SMS
₹2,360
₹2,000 + ₹360 GST
Trans10Lac
10,00,000 SMS · 16.50p/SMS
₹1,94,700
₹1,65,000 + ₹29,700 GST

Start building.