Skip to main content

Send SMS

Queue a transactional SMS for immediate delivery to recipients in Saudi Arabia and Egypt.

  • OTP and verification codes
  • Appointment reminders
  • Order status updates
  • Account notifications

Endpoint

POST /sms/send

Returns: 202 Accepted

Prerequisites

Verified Sender Name Required

The from sender name must be registered and approved in the Arsel Dashboard under Settings > SMS Senders. Sender name registration is required by telecom regulators in KSA and Egypt. Messages with unregistered sender names will be rejected.

Headers

HeaderValueRequired
AuthorizationBearer <your-api-key>Yes
Content-Typeapplication/jsonYes
Idempotency-KeyAny unique string, max 256 charsNo — see Idempotency

Body Parameters

ParameterTypeRequiredDescription
fromstringYesRegistered sender name. Alphanumeric, 3-11 characters.
tostring[]YesArray of phone numbers in international format. Max 100 recipients.
contentstringYesMessage body. Supports {{variables}}.
variablesobjectNoKey-value pairs for {{variable}} replacement in content.
categorystringNoLabel for grouping messages in analytics. Max 100 characters.

Phone Number Format

All recipients in a single request must be from the same country. Mixing KSA and Egypt numbers in one request is not allowed.

CountryFormatExample
Saudi Arabia (KSA)+9665XXXXXXXX+966512345678
Egypt+201XXXXXXXXX+201012345678

Character Encoding and Message Parts

SMS messages are automatically split into parts based on content encoding:

EncodingCharactersSingle SMSPer Part (Multi-part)
GSM (Latin, digits, basic symbols)A-Z, 0-9, common punctuation160 characters153 characters
Unicode (Arabic, emoji, special chars)Arabic script, CJK, emoji70 characters67 characters

The encoding is detected automatically based on message content. If any character requires Unicode, the entire message uses Unicode encoding.

A message may run to at most 10 parts — 1,530 GSM characters, or 670 Unicode ones. Longer content is rejected with 400 bad_request.


Response

{
"id": "01957e3a-4b5c-7d8e-9f0a-1b2c3d4e5f6a"
}
FieldTypeDescription
idstringUnique SMS ID. Use this to track delivery status via GET /sms/:id.
tip

The 202 Accepted response means the SMS is queued, not yet delivered. Use GET /sms/:id to track delivery progress.


Idempotency

Sending the same SMS message twice — for example because a network timeout made you retry — could send the SMS twice — and bill you for both. To make a retry safe, send an Idempotency-Key header whose value is unique to that SMS message (for example otp/123):

  • The first request with a given key is processed normally and its response is stored.
  • Any later request with the same key (within 24 hours) is not reprocessed — it returns the original response unchanged, plus an Idempotent-Replayed: true response header. The side effect happens only once.
  • After 24 hours the key expires and may be reused.

The key can be any unique string up to 256 characters. A UUID works, but a value derived from the entity the request is about — like otp/123 — is easier to regenerate identically on a retry. Keys are scoped per endpoint, so the same value can be reused independently across the send-email, send-SMS, and send-event endpoints without colliding.

Reusing a key with a different payload

Reuse a key with a different request body and the request is rejected with 409 invalid_idempotent_request, which protects you from receiving the wrong cached response. Use a fresh key for a genuinely different request.

Idempotency error responses

StatusnameWhen
400invalid_idempotency_keyThe key is empty or longer than 256 characters.
409invalid_idempotent_requestThe key was already used with a different request body.
409concurrent_idempotent_requestsAn earlier request with the same key is still being processed — retry shortly.

Examples

Basic SMS

curl -X POST "https://api.arsel.sa/v1/sms/send" \
-H "Authorization: Bearer be_your_api_key" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: otp/123" \
-d '{
"from": "Arsel",
"to": ["+966512345678"],
"content": "Your verification code is 483920. It expires in 5 minutes."
}'

With Template Variables

curl -X POST "https://api.arsel.sa/v1/sms/send" \
-H "Authorization: Bearer be_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"from": "MyStore",
"to": ["+966512345678", "+966598765432"],
"content": "Hi {{name}}, your order {{order_id}} has been shipped and will arrive by {{date}}.",
"variables": {
"name": "Ahmed",
"order_id": "ORD-12345",
"date": "March 10"
},
"category": "shipping-updates"
}'

Arabic Content (Unicode)

curl -X POST "https://api.arsel.sa/v1/sms/send" \
-H "Authorization: Bearer be_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"from": "Arsel",
"to": ["+966512345678"],
"content": "مرحباً {{name}}، رمز التحقق الخاص بك هو {{code}}. صالح لمدة 5 دقائق.",
"variables": {
"name": "أحمد",
"code": "839201"
}
}'

Error Responses

{
"status_code": 422,
"name": "validation_error",
"message": "All recipients must be from the same country"
}