Send SMS
Send one message to one Nepal mobile number. The reply comes back in milliseconds with a messageId; delivery is reported afterwards.
POST
/sms/sendhttps://api.smsray.in/api/sms/v1/sms/sendQueue one SMS to one Nepal mobile number. The cost is reserved from your workspace balance at accept time and the message is dispatched immediately.
Request
Headers
| Name | Type | Required | Rules |
|---|---|---|---|
x-api-key | string | required | Your secret key, ls_live_ followed by 48 hex characters. |
content-type | string | required | application/json |
Idempotency-Key | string | optional | 1–200 printable ASCII characters. Safe retries for 24 h. See Idempotency. |
Body parameters (JSON)
| Name | Type | Required | Rules |
|---|---|---|---|
to | string | required | Recipient. Must match ^\+?\d{7,15}$. Nepal mobile numbers only: 98XXXXXXXX, 97XXXXXXXX, 96XXXXXXXX, optionally prefixed with 977 or +977. |
text | string | required | At least 1 character, at most 6 segments (GSM-7: 918 characters, UCS-2: 402 code units). See Segments & encoding. |
type | string | optional | transactional (default), otp or promotional. Must be one of your workspace's allowedTypes. |
senderId | string | optional | Stored as from on the message. Not validated in v1 — sender-ID approval is not available yet. |
Example request
curl https://api.smsray.in/api/sms/v1/sms/send \
-H "x-api-key: $SMSRAY_API_KEY" \
-H "content-type: application/json" \
-H "Idempotency-Key: order-1042-shipped" \
-d '{ "to": "9779801234567", "text": "Your order #1042 has shipped." }'Response
200
200 application/json
{
"success": true,
"messageId": "2b1f6c1e-8d4f-4c55-9a51-0d2b0b7f3a11",
"status": "queued",
"segments": 1,
"cost": 1.0,
"encoding": "GSM7",
"from": "SMSRay"
}400Validation error
400 application/json
{
"error": "Invalid request",
"code": "invalid_request",
"details": [
{ "path": ["to"], "message": "Required", "code": "invalid_type" }
]
}Response fields
| Name | Type | Required | Rules |
|---|---|---|---|
messageId | string (uuid) | required | Use it with GET /sms/messages/:id and to match webhook events. |
status | string | required | Always queued in this reply. |
segments | integer | required | How many SMS parts the text needs. |
cost | number | required | Your workspace rate for type × segments, reserved from the balance. |
encoding | string | required | GSM7 or UCS2. |
from | string | required | The sender recorded at accept time: your senderId if given, otherwise the default sender. The physical SIM is chosen after accept. |
Errors
Every error uses the same shape: { "error", "code", "details"? }. Branch on code, not on the message.
| HTTP | code | When |
|---|---|---|
| 400 | invalid_request | Validation failed (see details), the text needs more than 6 segments, or the number is not a Nepal mobile ("Only Nepal mobile numbers (96/97/98XXXXXXXX) are supported"). |
| 402 | insufficient_balance | Your workspace balance is lower than the cost of this message. |
| 401 | unauthorized | The x-api-key header is missing ("Missing x-api-key") or the key is unknown ("Invalid API key"). |
| 403 | client_disabled | The API client that owns this key has been disabled in the dashboard. |
| 403 | forbidden | This message type is not allowed for your workspace. |
| 403 | workspace_pending | Your workspace has not been activated by Lacspace yet, so it cannot send. |
| 403 | workspace_suspended | Your workspace is suspended. |
| 409 | idempotency_conflict | The same Idempotency-Key was used with a different body, or the first request is still running (Retry-After: 1). |
| 429 | rate_limited | You exceeded your per-client request rate (default 20 requests per second). Honour Retry-After. |
| 503 | unavailable | No sending route is available right now. Nothing was charged; retry with backoff. |
| 500 | server_error | Something went wrong on our side. The body never contains a stack trace. |
Notes
- The reply always says
queued. Follow the message withGET /sms/messages/:idor, better, amessage.statuswebhook. No webhook is sent for the initialqueued. - Routing picks a SIM on the recipient's own network first, paces each SIM under Android's send limit (30 sends per 30 minutes) and skips SIMs that are stale, failing or out of daily quota. Daily quotas reset on Nepal time.
- If the first SIM fails, the message is retried once on another SIM. If every route fails, the message ends as
failedand the reserved cost is refunded.undeliveredis not refunded. - Send an
Idempotency-Keyon every send so network retries never double-send or double-bill.