Get Campaign Stats
Retrieve delivery, click and conversion stats for an SMS campaign.
Totals are lifetime. Unique counts can lag event counts by up to 15 minutes. Before the campaign is sent, counts are 0 and rates are null.
Endpoint
GET /sms/campaigns/:id/stats
Returns: 200 OK
Headers
| Header | Value | Required |
|---|---|---|
Authorization | Bearer <your-api-key> | Yes |
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id | string | Yes | The campaign ID. |
Response
{
"object": "sms_campaign_stats",
"campaign_id": "0192a1b2-c3d4-7e5f-9000-abcdef123456",
"recipients": 5200,
"sent": 5180,
"delivered": 4960,
"undelivered": 110,
"failed": 4,
"blocked": 6,
"rejected": 3,
"expired": 21,
"unknown": 9,
"pending": 71,
"clicks": 402,
"unique_clicks": 371,
"bot_clicks": 58,
"delivery_rate": 0.9575,
"click_rate": 0.0748,
"smart_sending": { "enabled": false, "skipped": 0 },
"conversions": {
"enabled": true,
"tracking_since": "2026-09-01T00:00:00.000Z",
"total": 42,
"revenue": [{ "currency": "SAR", "amount": 18350 }],
"by_event": [
{
"event_id": "0192a1b2-eeee-7fff-8000-111111111111",
"event_name": "order_completed",
"tracks_revenue": true,
"conversions": 42,
"revenue": [{ "currency": "SAR", "amount": 18350 }]
}
]
}
}
Response fields
| Field | Type | Description |
|---|---|---|
recipients | number | Contacts sent to. Before sending, the current audience size. |
sent | number | Accepted by the SMS provider |
delivered | number | Confirmed delivered to the handset |
undelivered | number | Delivery failed (phone off, invalid number, do-not-disturb) |
failed | number | Never accepted by the SMS provider |
blocked | number | Blocked by the carrier or a regulatory filter |
rejected | number | Rejected before a delivery attempt |
expired | number | Delivery window expired |
unknown | number | Receipts with a status the provider did not name |
pending | number | Accepted, no final receipt yet |
clicks | number | Total clicks, link scanners excluded |
unique_clicks | number | Contacts who clicked |
bot_clicks | number | Link-scanner clicks. Not counted in clicks. |
delivery_rate | number | null | delivered / sent |
click_rate | number | null | unique_clicks / delivered |
smart_sending.enabled | boolean | Smart Sending was on when the campaign was sent |
smart_sending.skipped | number | Recipients skipped because they had reached the sending cap |
conversions.enabled | boolean | false when the organization has no conversion events |
conversions.tracking_since | string | null | When the first conversion event was enabled (ISO 8601) |
conversions.total | number | Conversions attributed to the campaign |
conversions.revenue | array | Attributed revenue as { currency, amount }, one entry per currency |
conversions.by_event | array | The same breakdown per conversion event |
Rates are fractions from 0 to 1, rounded to four decimals, and null when the denominator is 0.
Examples
- cURL
- JavaScript
- Python
- C#
- PHP
curl "https://api.arsel.sa/v1/sms/campaigns/0192a1b2-c3d4-7e5f-9000-abcdef123456/stats" \
-H "Authorization: Bearer $ARSEL_API_KEY"
const response = await fetch("https://api.arsel.sa/v1/sms/campaigns/0192a1b2-c3d4-7e5f-9000-abcdef123456/stats", {
headers: {
Authorization: `Bearer ${process.env.ARSEL_API_KEY}`,
},
});
const data = await response.json();
if (!response.ok) {
throw new Error(`${data.name}: ${data.message}`);
}
console.log(data);
import os
import requests
response = requests.get(
"https://api.arsel.sa/v1/sms/campaigns/0192a1b2-c3d4-7e5f-9000-abcdef123456/stats",
headers={"Authorization": f"Bearer {os.environ['ARSEL_API_KEY']}"},
)
response.raise_for_status()
print(response.json())
using System.Net.Http.Headers;
var client = new HttpClient(); // share one instance across requests
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(
"Bearer", Environment.GetEnvironmentVariable("ARSEL_API_KEY"));
var response = await client.GetAsync("https://api.arsel.sa/v1/sms/campaigns/0192a1b2-c3d4-7e5f-9000-abcdef123456/stats");
var body = await response.Content.ReadAsStringAsync();
if (!response.IsSuccessStatusCode)
throw new HttpRequestException($"{(int)response.StatusCode}: {body}");
Console.WriteLine(body);
<?php
$ch = curl_init("https://api.arsel.sa/v1/sms/campaigns/0192a1b2-c3d4-7e5f-9000-abcdef123456/stats");
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
"Authorization: Bearer " . getenv("ARSEL_API_KEY"),
],
]);
$data = json_decode(curl_exec($ch), true);
if (curl_getinfo($ch, CURLINFO_HTTP_CODE) >= 400) {
throw new Exception("{$data['name']}: {$data['message']}");
}
print_r($data);
Error Responses
- 404 Not Found
- 401 Unauthorized
{
"status_code": 404,
"name": "not_found",
"message": "Campaign not found or access denied"
}
{
"status_code": 401,
"name": "unauthorized",
"message": "Invalid API Key"
}