Get Campaign Stats
Retrieve delivery, engagement and conversion stats for an email 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 /email/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": "email_campaign_stats",
"campaign_id": "0192a1b2-c3d4-7e5f-9000-abcdef123456",
"sent": 12040,
"delivered": 11800,
"failed": 12,
"bounced": 228,
"hard_bounced": 90,
"soft_bounced": 120,
"validator_rejected": 18,
"opens": 6100,
"unique_opens": 4720,
"clicks": 980,
"unique_clicks": 610,
"unsubscribed": 31,
"complained": 2,
"delivery_rate": 0.9801,
"open_rate": 0.4,
"click_rate": 0.0517,
"bounce_rate": 0.0189,
"unsubscribe_rate": 0.0026,
"complaint_rate": 0.0002,
"smart_sending": { "enabled": true, "skipped": 140 },
"links": [
{ "url": "https://example.com/sale", "clicks": 311 },
{ "url": "https://example.com/new", "clicks": 97 }
],
"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 |
|---|---|---|
sent | number | Emails sent |
delivered | number | Accepted by the receiving server |
failed | number | Never accepted by the mail provider |
bounced | number | hard_bounced + soft_bounced + validator_rejected |
hard_bounced | number | Permanent bounces |
soft_bounced | number | Temporary bounces |
validator_rejected | number | Addresses rejected by email validation before sending |
opens | number | Total opens |
unique_opens | number | Contacts who opened |
clicks | number | Total clicks |
unique_clicks | number | Contacts who clicked |
unsubscribed | number | Unsubscribes |
complained | number | Spam complaints |
delivery_rate | number | null | delivered / sent |
open_rate | number | null | unique_opens / delivered |
click_rate | number | null | unique_clicks / delivered |
bounce_rate | number | null | bounced / sent |
unsubscribe_rate | number | null | unsubscribed / delivered |
complaint_rate | number | null | complained / 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 |
links | array | { url, clicks } per link, most clicked first. Unsubscribe links are excluded. |
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/email/campaigns/0192a1b2-c3d4-7e5f-9000-abcdef123456/stats" \
-H "Authorization: Bearer $ARSEL_API_KEY"
const response = await fetch("https://api.arsel.sa/v1/email/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/email/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/email/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/email/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"
}