Mail API Documentation
Self-hosted transactional email service. Send emails via a REST API from your own domain.
Quickstart
- Register โ Create an account op /register
- Add domain โ Add your domain in the dashboard
- Configure DNS โ Add the TXT verification record to your DNS
- Verify โ Click "Verify now" in the dashboard
- Create API key โ Create a key in the dashboard
- Send โ Use the API to send emails
DNS Records
After domain verification, configure these records for optimal deliverability:
| Record | Name | Value |
|---|---|---|
| TXT (SPF) | @ | v=spf1 ip4:13.140.148.113 ~all |
| TXT (DKIM) | mailapi._domainkey | (see dashboard after verification) |
DNS Provider Instructions
Cloudflare: DNS โ Records โ Add Record. Turn proxy (orange cloud) OFF for mail records.
Namecheap: Advanced DNS โ Add New Record โ TXT Record.
TransIP / Strato: DNS settings โ Records โ Add.
API Reference
Send an email. Requires API key in Authorization header.
curl -X POST https://lodata.eu/api/emails/send \
-H "Authorization: Bearer re_xxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: unique-key-123" \
-d '{
"from": "noreply@yourdomain.com",
"to": "customer@example.com",
"subject": "Welcome!",
"html": "Hello
<p>Welcome to our service.</p>",
"text": "Hello, welcome to our service.",
"cc": "cc@example.com",
"bcc": "bcc@example.com",
"reply_to": "support@yourdomain.com"
}'
Required: from, to, subject, html of text
Optional: cc, bcc, reply_to, template_id, variables, attachments, metadata
Headers: Idempotency-Key prevents duplicate sending
Check the status of a sent email.
List of sent emails. Supports ?status=sent&search=klant&limit=50
Event timeline of an email (queued โ sending โ sent โ delivered).
Create a template with Handlebars variables.
Code Examples
Node.js
const resp = await fetch('https://lodata.eu/api/emails/send', {
method: 'POST',
headers: {
'Authorization': 'Bearer re_xxxxxxxxxxxx',
'Content-Type': 'application/json'
},
body: JSON.stringify({
from: 'noreply@yourdomain.com',
to: 'customer@example.com',
subject: 'Welcome!',
html: '<p>Hello!</p>'
})
});
const data = await resp.json();
console.log(data.id, data.status);
Python
import requests
resp = requests.post(
'https://lodata.eu/api/emails/send',
headers={'Authorization': 'Bearer re_xxxxxxxxxxxx'},
json={'from':'noreply@yourdomain.com','to':'customer@example.com','subject':'Test','html':'<p>Hello</p>'}
)
print(resp.json())
SMTP
You can also send via SMTP on port 1587 (localhost only). Authenticate with your API key as password.
Batch Send
Send up to 100 emails in one request. Same fields as /send, in a messages array. Each message is processed independently โ errors in one message do not block the others.
curl -X POST https://lodata.eu/api/emails/batch \
-H "Authorization: Bearer re_xxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"messages": [
{"from":"noreply@yourdomain.com","to":"a@b.com","subject":"Mail 1","html":"One
"},
{"from":"noreply@yourdomain.com","to":"c@d.com","subject":"Mail 2","html":"Twee
"}
]
}'
๐ Tracking โ Open & Click
Optional per email (enabled by default).
| Veld | Werking |
|---|---|
track_opens | Adds invisible tracking pixel. message.opened event on open. |
track_clicks | Rewrites links via the service. message.clicked event bij klik. |
๐ Unsubscribe
Automatic for non-transactional emails. Adds List-Unsubscribe header (RFC 8058) and unsubscribe link in footer.
Use "transactional": true for password resets. Use "unsubscribe": false to disable.
๐ Calendar invites
Send calendar invites as .ics attachment:
"calendar": {
"title": "Teamoverleg",
"start": "2026-06-10T14:00:00Z",
"end": "2026-06-10T15:00:00Z",
"location": "Online",
"attendees": [{"email": "customer@example.com"}]
}
๐ฅ Team & Roles
Invite team members to your tenant with different roles:
| Rol | Rechten |
|---|---|
| Owner | Everything: billing, users, domains, templates, keys, webhooks |
| Admin | Domains, templates, settings, logs |
| Developer | Templates, API-keys, webhooks, logs, send emails |
| Viewer | View logs and statistics only |
๐ Reports
Per receiving provider (gmail.com, outlook.com, etc.): volumes, delivery rates, bounces.
Version history of a template. Each update saves the previous version.
Error Codes
| Code | Meaning |
|---|---|
| 201 | Email accepted and queued |
| 400 | Invalid parameters (wrong email address, missing field) |
| 401 | Invalid or missing API key |
| 403 | API key has no permission / role not allowed |
| 404 | Email, template or webhook not found |
| 409 | Conflict (domain already exists, user already exists) |
| 429 | Rate limit or quota (per minute/hour/day) exceeded |