Skip to main content

Send Email

Queue a transactional email for immediate delivery. Ideal for time-sensitive notifications triggered by user actions:

  • Password resets
  • Welcome messages
  • Order confirmations
  • Two-factor authentication codes

Endpoint

POST /email/send

Returns: 202 Accepted

Prerequisites

Verified Domain Required

The sender address in 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. Emails from unverified domains will be rejected.

Headers

HeaderValueRequired
AuthorizationBearer <your-api-key>Yes
Content-Typeapplication/jsonYes

Body Parameters

ParameterTypeRequiredDescription
fromstringYesSender email address. Must belong to a verified domain.
from_namestringYesDisplay name shown alongside the sender address. Max 256 characters.
tostring[]YesArray of recipient email addresses.
subjectstringYesEmail subject line. Max 998 characters. Supports {{variables}}.
htmlstringConditionalHTML email body. Required if text and template_id are not provided.
textstringConditionalPlain text email body. Required if html and template_id are not provided.
template_idstringConditionalID of a saved template (created via POST /templates or the dashboard). Returns 404 if the template doesn't exist or doesn't belong to your organization.
variablesobjectNoKey-value pairs for {{variable}} replacement in subject, HTML, and text.
reply_tostringNoReply-to email address.
ccstring[]NoCC recipient email addresses.
bccstring[]NoBCC recipient email addresses.
attachmentsobject[]NoFile attachments. See Attachments below.
categorystringNoLabel for grouping emails in analytics. Max 100 characters.
warning

Provide exactly one content source: html, text, or template_id. You may include both html and text together (for multipart emails), but not alongside template_id.

Total Recipients Cap

The combined size of to + cc + bcc must not exceed 50 recipients per message. Requests over this cap are rejected with 400 bad_request (Too many recipients. Maximum 50 allowed, but N provided.). For larger sends, split the request into multiple API calls.

Attachments

Each attachment object has the following fields:

FieldTypeRequiredDescription
filenamestringYesFilename with extension (e.g., invoice.pdf). Max 255 characters.
contentstringYesBase64-encoded file content.
content_typestringNoMIME type. Defaults to application/octet-stream.

Limits: Up to 10 attachments per email, with a combined decoded size of 30 MB. Executable and script MIME types / extensions (e.g. .exe, .bat, .js, .ps1) are rejected.

Template Variables

Use {{variableName}} syntax in your subject, HTML, or text content. Pass values in the variables object:

{
"subject": "Your order {{order_id}} has shipped",
"html": "<p>Hi {{name}}, your order is on its way!</p>",
"variables": {
"name": "Sara",
"order_id": "A-12345"
}
}

Variable replacement is case-sensitive. Unmatched placeholders are left as-is.


Response

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

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

Partial Success Semantics

Recipients go through two validation stages:

  1. Format check (synchronous)to, cc, bcc, and from must be well-formed email addresses. If any address is malformed, the entire request is rejected with 422 validation_error and nothing is sent — matching Amazon SES, which rejects the whole message when a single recipient is invalid.
  2. Deliverability check (asynchronous)after the request is accepted, each address is checked in the background against MX records, domain reachability, disposable-provider lists, and internal suppression lists.

Because the deliverability check runs after the 202 Accepted response, it cannot change the HTTP status. Addresses that fail it are dropped before send and the remaining valid recipients are still delivered. If every recipient fails this stage, no email is sent — but the request has already returned 202, so there is no error response; the outcome is visible only via GET /email/:id and your analytics.

All addresses you submit appear in GET /email/:id under their respective to / cc / bcc arrays, each with its latest per-recipient status. A recipient dropped at the deliverability check never receives tracking events, so it remains in sent status — an address stuck at sent (never advancing to delivered/bounced) indicates it was likely filtered before send.


Examples

Basic Email

curl -X POST "https://api.arsel.sa/v1/email/send" \
-H "Authorization: Bearer be_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"from": "noreply@yourdomain.com",
"from_name": "My App",
"to": ["user@example.com"],
"subject": "Welcome to our platform",
"html": "<h1>Welcome!</h1><p>Thanks for signing up.</p>"
}'

With Template and Variables

curl -X POST "https://api.arsel.sa/v1/email/send" \
-H "Authorization: Bearer be_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"from": "orders@yourdomain.com",
"from_name": "Order Notifications",
"to": ["customer@example.com"],
"subject": "Order {{order_id}} confirmed",
"template_id": "order-confirmation-v2",
"variables": {
"customer_name": "Sara Ahmed",
"order_id": "ORD-98765",
"total": "149.99 SAR"
},
"category": "order-confirmation"
}'

With Attachments

curl -X POST "https://api.arsel.sa/v1/email/send" \
-H "Authorization: Bearer be_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"from": "billing@yourdomain.com",
"from_name": "Billing",
"to": ["customer@example.com"],
"subject": "Your invoice for March 2026",
"html": "<p>Please find your invoice attached.</p>",
"attachments": [
{
"filename": "invoice-march-2026.pdf",
"content": "JVBERi0xLjQK...",
"content_type": "application/pdf"
}
],
"category": "invoices"
}'

Error Responses

{
"status_code": 422,
"name": "validation_error",
"message": "to must be an array, each value in to must be an email"
}