Skip to content
SMSRay

Send SMS

Send one message to one mobile number. The reply comes back in milliseconds with a messageId; delivery is reported afterwards.

POST/sms/send
https://api.smsray.com/api/sms/v1/sms/send

Queue one SMS to one mobile number, as free text or from an approved template. The cost is reserved from your workspace balance at accept time and the message goes straight into delivery.

Request

Headers

Send an SMS request headers
NameTypeRequiredRules
x-api-keystringrequiredYour secret key, ls_live_ followed by 48 hex characters.
content-typestringrequiredapplication/json
Idempotency-Keystringoptional1–200 printable ASCII characters. Safe retries for 24 h. See Idempotency.

Body parameters (JSON)

Send an SMS body parameters
NameTypeRequiredRules
tostringrequiredRecipient. E.164 is recommended (+9779801234567); the national format is accepted for your workspace's country (for a Nepal workspace 98XXXXXXXX, 97… or 96…, with or without 977). Must match ^\+?\d{7,15}$. See Numbers & countries.
textstringoptionalFree text. Send exactly one of text or templateId. At least 1 character, at most 6 segments (GSM-7: 918 characters, UCS-2: 402 code units). When your workspace requires templates (the default) the text must match one of your approved templates of the same type.
templateIdstringoptionalAn approved template of your workspace. SMSRay renders it with variables. Send exactly one of text or templateId.
variablesobjectoptionalValues for the template's {{variables}}, as strings or numbers. Every variable is required; each value is 1–100 characters with no line break.
typestringoptionaltransactional (default), otp or promotional. Must be one of your workspace's allowedTypes; promotional is available on Enterprise only. With templateId, the template's type is used when omitted.
senderIdstringoptionalStored as from on the message. Not validated in v1 — sender-ID approval is not available yet.

Example request

curl https://api.smsray.com/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": 0.5,
  "encoding": "GSM7",
  "from": "SMSRay"
}

400Validation error

400 application/json
{
  "error": "Invalid request",
  "code": "invalid_request",
  "details": [
    { "path": ["to"], "message": "Required", "code": "invalid_type" }
  ]
}

403No matching template

403 application/json
{
  "error": "This message doesn't match an approved template. Submit the template for approval in your SMSRay dashboard, or send with an approved templateId.",
  "code": "template_required"
}

422Country not supported yet

422 application/json
{
  "error": "We don't deliver to India yet. This workspace can send to: Nepal.",
  "code": "destination_not_supported",
  "details": { "country": "IN", "allowed": ["NP"] }
}

Response fields

Send an SMS response fields
NameTypeRequiredRules
messageIdstring (uuid)requiredUse it with GET /sms/messages/:id and to match webhook events.
statusstringrequiredAlways queued in this reply.
segmentsintegerrequiredHow many SMS parts the text needs.
costnumberrequiredYour rate for type × segments, reserved from the balance.
encodingstringrequiredGSM7 or UCS2.
fromstringrequiredThe sender recorded for the message: your senderId if given, otherwise the default sender.

Errors

Every error uses the same shape: { "error", "code", "details"? }. Branch on code, not on the message.

Send an SMS errors
HTTPcodeWhen
400invalid_requestValidation failed (see details), both or neither of text and templateId were sent, or the text needs more than 6 segments.
400invalid_numberThe number can't receive SMS — for example a landline, or a number that fails its country's mobile rules.
400invalid_variablesWith templateId: a variable is missing, unknown, empty, longer than 100 characters or contains a line break.
402insufficient_balanceYour workspace balance is lower than the cost of this message.
401unauthorizedThe x-api-key header is missing ("Missing x-api-key") or the key is unknown ("Invalid API key").
403client_disabledThe API client that owns this key has been disabled in the dashboard.
403forbiddenThis message type is not allowed on your plan or workspace.
403template_requiredThe text doesn't match an approved template of the same type, or templateId is not an approved template of this workspace.
403workspace_pendingYour workspace has not been activated yet, so it cannot send.
403workspace_suspendedYour workspace is suspended.
409idempotency_conflictThe same Idempotency-Key was used with a different body, or the first request is still running (Retry-After: 1).
422destination_not_supportedA valid number in a country your workspace can't send to yet. details is { country, allowed }; show "We don't deliver to <country> yet".
429rate_limitedYou exceeded your per-client request rate (default 20 requests per second). Honour Retry-After.
503unavailableDelivery is temporarily unavailable. Nothing was charged; retry with backoff.
500server_errorSomething went wrong on our side. The body never contains a stack trace.

Notes

  • The reply always says queued. Follow the message with GET /sms/messages/:id or, better, a message.status webhook. No webhook is sent for the initial queued.
  • Every custom message must use a template approved by SMSRay. Approval protects deliverability and keeps spam off the networks; we aim to review new templates within one business day. OTPs sent with POST /sms/otp/send use SMSRay's built-in template, so OTP works on day one.
  • Messages are delivered over the recipient's mobile network, whichever one they are on, with automatic retries. If delivery finally fails, the message ends as failed and the reserved cost is refunded. undelivered is not refunded.
  • Numbers are stored in E.164, so to in lookups and webhooks is always +<country code><number>.
  • Send an Idempotency-Key on every send so network retries never double-send or double-bill.
  • On a key in test mode the message is accepted and recorded with status test, but never sent and never charged.