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
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
| Header | Value | Required |
|---|---|---|
Authorization | Bearer <your-api-key> | Yes |
Content-Type | application/json | Yes |
Body Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
from | string | Yes | Registered sender name. Alphanumeric, 3-11 characters. |
to | string[] | Yes | Array of phone numbers in international format. |
content | string | Yes | Message body. Supports {{variables}}. |
variables | object | No | Key-value pairs for {{variable}} replacement in content. |
category | string | No | Label 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.
| Country | Format | Example |
|---|---|---|
| Saudi Arabia (KSA) | +9665XXXXXXXX | +966512345678 |
| Egypt | +201XXXXXXXXX | +201012345678 |
Character Encoding and Message Parts
SMS messages are automatically split into parts based on content encoding:
| Encoding | Characters | Single SMS | Per Part (Multi-part) |
|---|---|---|---|
| GSM (Latin, digits, basic symbols) | A-Z, 0-9, common punctuation | 160 characters | 153 characters |
| Unicode (Arabic, emoji, special chars) | Arabic script, CJK, emoji | 70 characters | 67 characters |
The encoding is detected automatically based on message content. If any character requires Unicode, the entire message uses Unicode encoding.
Response
{
"id": "01957e3a-4b5c-7d8e-9f0a-1b2c3d4e5f6a",
"to": ["+966512345678"],
"from": "Arsel",
"queued_recipients": 1,
"invalid_recipients": 0,
"created_at": "2026-03-08T12:00:00.000Z"
}
| Field | Type | Description |
|---|---|---|
id | string | Unique SMS ID. Use this to check delivery status. |
to | string[] | Recipient phone numbers |
from | string | Sender name |
queued_recipients | number | Number of recipients successfully queued |
invalid_recipients | number | Number of invalid phone numbers skipped |
created_at | string | ISO 8601 timestamp |
Check invalid_recipients in the response. Invalid phone numbers are silently skipped and not queued for delivery.
Examples
Basic SMS
- cURL
- JavaScript
- Python
- C#
- PHP
curl -X POST "https://api.arsel.sa/api/v1/sms/send" \
-H "Authorization: Bearer be_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"from": "Arsel",
"to": ["+966512345678"],
"content": "Your verification code is 483920. It expires in 5 minutes."
}'
const response = await fetch("https://api.arsel.sa/api/v1/sms/send", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: "Bearer be_your_api_key",
},
body: JSON.stringify({
from: "Arsel",
to: ["+966512345678"],
content: "Your verification code is 483920. It expires in 5 minutes.",
}),
});
const data = await response.json();
console.log(`Queued: ${data.queued_recipients}, Invalid: ${data.invalid_recipients}`);
import requests
response = requests.post(
"https://api.arsel.sa/api/v1/sms/send",
headers={
"Content-Type": "application/json",
"Authorization": "Bearer be_your_api_key",
},
json={
"from": "Arsel",
"to": ["+966512345678"],
"content": "Your verification code is 483920. It expires in 5 minutes.",
},
)
data = response.json()
print(f"Queued: {data['queued_recipients']}, Invalid: {data['invalid_recipients']}")
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer be_your_api_key");
var payload = new
{
from = "Arsel",
to = new[] { "+966512345678" },
content = "Your verification code is 483920. It expires in 5 minutes."
};
var json = System.Text.Json.JsonSerializer.Serialize(payload);
var content = new StringContent(json, System.Text.Encoding.UTF8, "application/json");
var response = await client.PostAsync("https://api.arsel.sa/api/v1/sms/send", content);
Console.WriteLine(await response.Content.ReadAsStringAsync());
<?php
$ch = curl_init("https://api.arsel.sa/api/v1/sms/send");
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Content-Type: application/json",
"Authorization: Bearer be_your_api_key"
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([
"from" => "Arsel",
"to" => ["+966512345678"],
"content" => "Your verification code is 483920. It expires in 5 minutes."
]));
$response = curl_exec($ch);
echo $response;
curl_close($ch);
With Template Variables
- cURL
- JavaScript
- Python
- C#
- PHP
curl -X POST "https://api.arsel.sa/api/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"
}'
const response = await fetch("https://api.arsel.sa/api/v1/sms/send", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: "Bearer be_your_api_key",
},
body: JSON.stringify({
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",
}),
});
console.log(await response.json());
import requests
response = requests.post(
"https://api.arsel.sa/api/v1/sms/send",
headers={
"Content-Type": "application/json",
"Authorization": "Bearer be_your_api_key",
},
json={
"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",
},
)
print(response.json())
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer be_your_api_key");
var payload = new
{
from = "MyStore",
to = new[] { "+966512345678", "+966598765432" },
content = "Hi {{name}}, your order {{order_id}} has been shipped and will arrive by {{date}}.",
variables = new
{
name = "Ahmed",
order_id = "ORD-12345",
date = "March 10"
},
category = "shipping-updates"
};
var json = System.Text.Json.JsonSerializer.Serialize(payload);
var content = new StringContent(json, System.Text.Encoding.UTF8, "application/json");
var response = await client.PostAsync("https://api.arsel.sa/api/v1/sms/send", content);
Console.WriteLine(await response.Content.ReadAsStringAsync());
<?php
$ch = curl_init("https://api.arsel.sa/api/v1/sms/send");
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Content-Type: application/json",
"Authorization: Bearer be_your_api_key"
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([
"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"
]));
$response = curl_exec($ch);
echo $response;
curl_close($ch);
Arabic Content (Unicode)
- cURL
- JavaScript
- Python
- C#
- PHP
curl -X POST "https://api.arsel.sa/api/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"
}
}'
const response = await fetch("https://api.arsel.sa/api/v1/sms/send", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: "Bearer be_your_api_key",
},
body: JSON.stringify({
from: "Arsel",
to: ["+966512345678"],
content: "مرحباً {{name}}، رمز التحقق الخاص بك هو {{code}}. صالح لمدة 5 دقائق.",
variables: {
name: "أحمد",
code: "839201",
},
}),
});
console.log(await response.json());
import requests
response = requests.post(
"https://api.arsel.sa/api/v1/sms/send",
headers={
"Content-Type": "application/json",
"Authorization": "Bearer be_your_api_key",
},
json={
"from": "Arsel",
"to": ["+966512345678"],
"content": "مرحباً {{name}}، رمز التحقق الخاص بك هو {{code}}. صالح لمدة 5 دقائق.",
"variables": {
"name": "أحمد",
"code": "839201",
},
},
)
print(response.json())
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer be_your_api_key");
var payload = new
{
from = "Arsel",
to = new[] { "+966512345678" },
content = "مرحباً {{name}}، رمز التحقق الخاص بك هو {{code}}. صالح لمدة 5 دقائق.",
variables = new
{
name = "أحمد",
code = "839201"
}
};
var json = System.Text.Json.JsonSerializer.Serialize(payload);
var content = new StringContent(json, System.Text.Encoding.UTF8, "application/json");
var response = await client.PostAsync("https://api.arsel.sa/api/v1/sms/send", content);
Console.WriteLine(await response.Content.ReadAsStringAsync());
<?php
$ch = curl_init("https://api.arsel.sa/api/v1/sms/send");
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Content-Type: application/json",
"Authorization: Bearer be_your_api_key"
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([
"from" => "Arsel",
"to" => ["+966512345678"],
"content" => "مرحباً {{name}}، رمز التحقق الخاص بك هو {{code}}. صالح لمدة 5 دقائق.",
"variables" => [
"name" => "أحمد",
"code" => "839201"
]
]));
$response = curl_exec($ch);
echo $response;
curl_close($ch);
Error Responses
- 422 Validation Error
- 401 Unauthorized
- 429 Rate Limited
{
"status_code": 422,
"name": "validation_error",
"message": "All recipients must be from the same country"
}
{
"status_code": 401,
"name": "unauthorized",
"message": "Invalid or missing API key"
}
{
"status_code": 429,
"name": "rate_limit_exceeded",
"message": "Too many requests. Please retry after the period indicated in the retry-after header."
}