The Email API sends HTML email through an SMTP sender connected to your account, to one recipient or to a list. Every send goes through POST /email/email-service/send and returns a batch ID.
Before you send#
Your SMTP sender (and, if you want replies and bounces read, its IMAP mailbox) is set up with our team during onboarding. Each sender has an ID, smtpId, that you pass on every send.
Check your sending domain before you go live. These calls validate the records that receiving servers look at:
| Method | Path | Checks |
|---|---|---|
| GET | /email/email-service/validate/domain/{EMAIL_DOMAIN} |
Domain |
| GET | /email/email-service/validate/spf/{EMAIL_DOMAIN} |
SPF record |
| GET | /email/email-service/validate/dmarc/{EMAIL_DOMAIN} |
DMARC record |
cURL
curl https://api.broadnet.me/email/email-service/validate/spf/omnidemo.example \
-H "Authorization: Bearer $BROADNET_TOKEN"Send an email#
cURL
curl -X POST https://api.broadnet.me/email/email-service/send \
-H "Authorization: Bearer $BROADNET_TOKEN" \
-F smtpId=16 \
-F campaignName=order-confirmations \
-F "subject=Your OmniDemo order 8842" \
-F "body=<p>Hi Sara,</p><p>Your order 8842 is confirmed.</p>" \
-F recipients=sara@example.com \
-F scheduled=falseNode.js
const form = new FormData();
form.append("smtpId", "16");
form.append("campaignName", "order-confirmations");
form.append("subject", "Your OmniDemo order 8842");
form.append("body", "<p>Hi Sara,</p><p>Your order 8842 is confirmed.</p>");
form.append("recipients", "sara@example.com");
form.append("scheduled", "false");
const res = await fetch("https://api.broadnet.me/email/email-service/send", {
method: "POST",
headers: { Authorization: `Bearer ${process.env.BROADNET_TOKEN}` },
body: form,
});
const batchId = await res.text(); // 19-digit batch IDPython
import os
import requests
fields = {
"smtpId": "16",
"campaignName": "order-confirmations",
"subject": "Your OmniDemo order 8842",
"body": "<p>Hi Sara,</p><p>Your order 8842 is confirmed.</p>",
"recipients": "sara@example.com",
"scheduled": "false",
}
r = requests.post(
"https://api.broadnet.me/email/email-service/send",
headers={"Authorization": f"Bearer {os.environ['BROADNET_TOKEN']}"},
files={k: (None, v) for k, v in fields.items()},
timeout=30,
)
batch_id = r.text # 19-digit batch IDPHP
<?php
$ch = curl_init("https://api.broadnet.me/email/email-service/send");
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ["Authorization: Bearer " . getenv("BROADNET_TOKEN")],
CURLOPT_POSTFIELDS => [
"smtpId" => "16",
"campaignName" => "order-confirmations",
"subject" => "Your OmniDemo order 8842",
"body" => "<p>Hi Sara,</p><p>Your order 8842 is confirmed.</p>",
"recipients" => "sara@example.com",
"scheduled" => "false",
],
]);
$batchId = curl_exec($ch);
curl_close($ch);A successful call returns 200 with a plain 19-digit batch ID. If no recipient address is valid, the call fails with 400 ("No Valid Recipient Found"); individual invalid addresses in a list are skipped.
Request fields#
| Field | Type | Required | Description |
|---|---|---|---|
smtpId |
integer | Yes | The ID of your connected SMTP sender. |
subject |
string | Yes, unless templateId |
Subject line. |
body |
string | Yes, unless templateId |
HTML body. |
recipients |
string | Yes, or recipientsFile |
Addresses separated by commas, semicolons, new lines or tabs. |
recipientsFile |
file | Yes, or recipients |
CSV, TXT or Excel file of recipients (with per-row values for personalised templates). |
fromAddress, fromName |
string | No | Sender address and display name, within what your SMTP sender allows. |
ccRecipients, bccRecipients |
string (JSON array) | No | For example ["finance@example.com"]. |
attachmentList |
file | No | One or more attachments. |
templateId |
string | No | Send a saved template instead of subject and body. |
sharedParams |
string (JSON) | No | Template values shared by every recipient. |
campaignName |
string | No | Your label; defaults to the template name. |
allowDuplicates |
boolean | No | false collapses duplicate addresses into one. |
delay |
number | No | Seconds between emails. |
scheduled |
boolean | No | false sends now; true schedules. |
scheduleTime, gmt |
string | When scheduled | For example 2026-11-01 09:00:00 and GMT+04:00. |
recurrence, repeatCount, recurrenceEndTime |
string | No | Recurring sends, for example DAILY. |
Send a saved template#
cURL
curl -X POST https://api.broadnet.me/email/email-service/send \
-H "Authorization: Bearer $BROADNET_TOKEN" \
-F smtpId=16 \
-F templateId=11 \
-F recipients=sara@example.com \
-F 'sharedParams={"companyName":"OmniDemo","offerCode":"SAVE20"}' \
-F scheduled=falseTemplates are managed with POST /email-templates/save, PUT /email-templates/update, GET /email-templates/getAll and GET /email-templates/grouped-by-category. Reusable layout frames are managed under /frame-templates.
Sandbox test send#
POST /email/email-sandbox/sendTestEmail sends one test email to check your SMTP setup before a campaign:
cURL
curl -X POST https://api.broadnet.me/email/email-sandbox/sendTestEmail \
-H "Authorization: Bearer $BROADNET_TOKEN" \
-F smtpId=16 \
-F recipient=you@example.com \
-F "subject=Sandbox test" \
-F "body=<p>SMTP smoke test</p>"Batches and bounces#
| Method | Path | Description |
|---|---|---|
| GET | /email/email-service/all-bulk |
List batches, with page, size, status, campaignName and date filters. |
| GET | /email/email-service/edit?batch_Id=… |
Batch details. |
| GET | /email/email-service/pause?batch_Id=… |
Pause a batch. |
| GET | /email/email-service/resume?batch_Id=… |
Resume a batch. |
| DELETE | /email/email-service/abort?batch_Id=… |
Abort a batch. |
| POST | /email/email-service/bounce/scan |
Scan the mailbox for bounce messages. |
| POST | /email/email-service/bounce/monitor/start |
Start continuous bounce monitoring. |
| POST | /email/email-service/bounce/monitor/stop |
Stop bounce monitoring. |
Remove addresses that hard-bounce from your lists to protect your sender reputation.
Next steps#
- Webhooks: track delivery events.
- Push notifications: reach app users directly.
- Errors and limits: retries and rate limits.
Ready to send your first message?
Request test credentials. An engineer sets up your account, and test sends go to your own verified numbers.
Request test access