Create Campaign
Create a new email campaign. The campaign is created in Draft status and is fully editable until it is sent or scheduled for delivery. Recipients are configured by attaching contact lists and/or tags to the campaign. Use this endpoint to prepare the campaign, then call POST /email/campaigns/:id/send when you are ready to send or schedule.
Common use cases:
- A marketing team preparing a weekly newsletter before scheduling it for Monday morning.
- A SaaS company drafting a product-launch announcement to review before sending.
Endpoint
POST /email/campaigns
Returns: 201 Created
Prerequisites
The from must belong to a verified domain. You can verify your domain in the Arsel Dashboard under Settings > Domains. Domain verification requires adding DNS records (SPF, DKIM, DMARC) to prove ownership. Campaigns from unverified domains will be rejected at send time.
Headers
| Header | Value | Required |
|---|---|---|
Authorization | Bearer <your-api-key> | Yes |
Content-Type | application/json | Yes |
Body Parameters
All parameters are optional. You can create an empty campaign and fill in the details later via PATCH /email/campaigns/:id.
| Parameter | Type | Required | Description |
|---|---|---|---|
name | string | No | Internal name for the campaign. Max 100 characters. |
subject | string | No | Email subject line. Supports {{variables}} from contact properties. |
preheader | string | No | Preview text shown alongside the subject line in email inboxes. |
from_name | string | No | Display name shown alongside the sender address. |
from | string | No | Sender email address. Must belong to a verified domain. |
reply_to | string | No | Reply-to email address. |
template_id | string | No | ID of the email template to use. Create one via POST /templates, copy from the gallery, or use the dashboard. |
list_ids | string[] | No | IDs of contact lists whose contacts should receive the campaign. |
tag_ids | string[] | No | IDs of tags whose tagged contacts should receive the campaign. |
Don't have a template_id yet? Copy any starter design from the gallery in one call: see POST /templates/gallery/:id/copy.
Response
{
"id": "0192a1b2-c3d4-7e5f-9000-abcdef123456"
}
Response Fields
| Field | Type | Description |
|---|---|---|
id | string | Unique campaign ID. Use this with GET /email/campaigns/:id to fetch the full record, or with POST /email/campaigns/:id/send to send or schedule. |
Examples
- cURL
- JavaScript
- Python
- C#
- PHP
curl -X POST "https://api.arsel.sa/v1/email/campaigns" \
-H "Authorization: Bearer be_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"name": "Summer Sale 2026",
"subject": "50% Off Everything!",
"preheader": "Limited time offer",
"from_name": "Acme Store",
"from": "marketing@acme.com",
"reply_to": "support@acme.com",
"template_id": "0192a1b2-aaaa-7bbb-8ccc-dddddddddddd",
"list_ids": ["list-uuid-1"]
}'
const response = await fetch("https://api.arsel.sa/v1/email/campaigns", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: "Bearer be_your_api_key",
},
body: JSON.stringify({
name: "Summer Sale 2026",
subject: "50% Off Everything!",
preheader: "Limited time offer",
from_name: "Acme Store",
from: "marketing@acme.com",
reply_to: "support@acme.com",
template_id: "0192a1b2-aaaa-7bbb-8ccc-dddddddddddd",
list_ids: ["list-uuid-1"],
}),
});
const { id } = await response.json();
console.log(id); // Use this ID for subsequent operations
import requests
response = requests.post(
"https://api.arsel.sa/v1/email/campaigns",
headers={
"Content-Type": "application/json",
"Authorization": "Bearer be_your_api_key",
},
json={
"name": "Summer Sale 2026",
"subject": "50% Off Everything!",
"preheader": "Limited time offer",
"from_name": "Acme Store",
"from": "marketing@acme.com",
"reply_to": "support@acme.com",
"template_id": "0192a1b2-aaaa-7bbb-8ccc-dddddddddddd",
"list_ids": ["list-uuid-1"],
},
)
data = response.json()
print(data["id"])
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer be_your_api_key");
var payload = new
{
name = "Summer Sale 2026",
subject = "50% Off Everything!",
preheader = "Limited time offer",
from_name = "Acme Store",
from = "marketing@acme.com",
reply_to = "support@acme.com",
template_id = "0192a1b2-aaaa-7bbb-8ccc-dddddddddddd",
list_ids = new[] { "list-uuid-1" }
};
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/v1/email/campaigns", content);
var result = await response.Content.ReadAsStringAsync();
// result: {"id":"..."}
Console.WriteLine(result);
<?php
$ch = curl_init("https://api.arsel.sa/v1/email/campaigns");
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([
"name" => "Summer Sale 2026",
"subject" => "50% Off Everything!",
"preheader" => "Limited time offer",
"from_name" => "Acme Store",
"from" => "marketing@acme.com",
"reply_to" => "support@acme.com",
"template_id" => "0192a1b2-aaaa-7bbb-8ccc-dddddddddddd",
"list_ids" => ["list-uuid-1"]
]));
$response = curl_exec($ch);
$data = json_decode($response, true);
echo $data["id"];
curl_close($ch);
Error Responses
- 401 Unauthorized
- 422 Validation Error
{
"status_code": 401,
"name": "unauthorized",
"message": "Invalid or missing API key"
}
{
"status_code": 422,
"name": "validation_error",
"message": "from must be an email"
}
After creating a campaign, you can:
- Update its content with
PATCH /email/campaigns/:id. - Browse all campaigns with
GET /email/campaigns. - Send or schedule it with
POST /email/campaigns/:id/send.