// POST /messages
Send a message
Send an SMS to one or many recipients. The request returns immediately; delivery happens in the background so nothing fails at the caller side.
curl -X POST https://sms-api.ekrasunya.com/v1/messages \
-H "X-API-Key: eksms_..." \
-H "Content-Type: application/json" \
-H "Idempotency-Key: order-2048-otp" \
-d '{
"recipients": ["9818000000", "9808000001"],
"text": "Your EK SMS code is 481920",
"senderId": "EKSMS",
"callbackUrl": "https://your-app.com/webhooks/sms"
}'
Request parameters
| Field | Type | Description |
|---|---|---|
| recipients | string[] | Up to 1000 Nepali mobile numbers, 10 digits (e.g. 9818000000). +977 / 977 prefixes are normalized away. Optional if you pass listIds; provide at least one of the two. |
| text | string | Required. The message body, 1-2000 chars. Unicode (Nepali/Devanagari) is supported. |
| senderId | string | Optional, max 11 chars. Falls back to your account default (a shared approved sender ID) when omitted. |
| callbackUrl | string | Optional HTTPS URL. Receives HMAC-signed delivery webhooks for this batch. |
| listIds | string[] | Optional. Saved contact list ids to send to. Members are expanded to recipients at send time and deduped with any recipients. Provide at least one of recipients or listIds. |
| route | string | Optional, A2P (default) or DEVICE. Use DEVICE to send through your own enrolled phones instead of the carrier gateway. See Send from your own device. Implied when deviceId or sendAsUserRef is set. |
| deviceId | string | Optional (device route). UUID of a specific enrolled device to send from. Sets the route to DEVICE. |
| sendAsUserRef | string | Optional (device route), max 128 chars. Send from the device assigned to this platform user reference (e.g. erp-staff-42). Sets the route to DEVICE. |
Headers
| Header | Description |
|---|---|
| X-API-Key | Required. Your API key with the messages:send scope. |
| Idempotency-Key | Recommended. Makes retries exactly-once (see below). |
| Content-Type | application/json |
Response
On success the API returns 202 with the batch summary. The message rows are created and credits debited atomically before the call returns; the actual send happens on a background queue.
{
"status": "success",
"statusCode": 202,
"message": "OK",
"data": {
"batchId": "28750054-c6f9-4ade-9ebd-6f87bd108c09",
"accepted": 2,
"totalCostNpr": 2.8,
"segments": 1,
"encoding": "GSM7",
"status": "QUEUED",
"replayed": false
}
}
Idempotency
Pass a unique Idempotency-Key header to guarantee a message is sent exactly once, even if your request times out and you retry. A replay with the same key returns the original batch with replayed: true and is never charged twice.
Use a natural key
otp-<userId>-<timestamp> or order-<id>-confirm - so a retry of the same business action reuses it automatically.Send from your own device
Besides the carrier gateway (A2P), you can send through your own enrolled Android phones (the DEVICE route). This is the same endpoint and the same API key - you just target a device. Set route to DEVICE, or simply pass deviceId or sendAsUserRef (which imply the device route):
curl -X POST https://sms-api.ekrasunya.com/v1/messages \
-H "X-API-Key: eksms_..." \
-H "Content-Type: application/json" \
-d '{
"recipients": ["9818000000"],
"text": "Sent from your own phone via EK SMS",
"route": "DEVICE"
}'
# Or target a specific device / assigned user instead of route:
# "deviceId": "a1b2c3d4-..." send from this exact phone
# "sendAsUserRef": "erp-staff-42" send from the phone assigned to this user
| To target | Send |
|---|---|
| A specific enrolled phone | deviceId (the device UUID from your dashboard) |
| The phone assigned to one of your users | sendAsUserRef (your own user reference, e.g. erp-staff-42) |
| Any eligible enrolled phone | route: "DEVICE" and let the platform pick |
Device routing must be enabled for your account
NO_ACTIVE_DEVICE (or DEVICE_ENROLLMENT_DISABLED if the account is not enabled); see Errors. Device sends are billed at the device rate, not the A2P rate.Billing & segments
One message segment = one credit, per recipient. Segment count depends on encoding:
| Encoding | Single segment | Per concatenated segment |
|---|---|---|
| GSM-7 | 160 chars | 153 chars |
| Unicode (UCS-2) | 70 chars | 67 chars |
Any character outside the GSM-7 set (including Devanagari) switches the whole message to Unicode. Credits = segments × recipients. The rupee value of a credit is set by your plan and settled at billing time. If a recipient is rejected upstream, its credits are automatically refunded.
Recipients
Message
Next: Delivery & webhooks · Errors