Mail API Docs

Mail API Documentation

Self-hosted transactional email service. Send emails via a REST API from your own domain.

Quickstart

  1. Register โ€” Create an account op /register
  2. Add domain โ€” Add your domain in the dashboard
  3. Configure DNS โ€” Add the TXT verification record to your DNS
  4. Verify โ€” Click "Verify now" in the dashboard
  5. Create API key โ€” Create a key in the dashboard
  6. Send โ€” Use the API to send emails

DNS Records

After domain verification, configure these records for optimal deliverability:

RecordNameValue
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

POST/api/emails/send

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

GET/api/emails/:id

Check the status of a sent email.

GET/api/emails

List of sent emails. Supports ?status=sent&search=klant&limit=50

GET/api/emails/:id/events

Event timeline of an email (queued โ†’ sending โ†’ sent โ†’ delivered).

POST/api/templates

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

POST/api/emails/batch

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).

VeldWerking
track_opensAdds invisible tracking pixel. message.opened event on open.
track_clicksRewrites 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:

RolRechten
OwnerEverything: billing, users, domains, templates, keys, webhooks
AdminDomains, templates, settings, logs
DeveloperTemplates, API-keys, webhooks, logs, send emails
ViewerView logs and statistics only

๐Ÿ“ˆ Reports

GET/api/reports/providers

Per receiving provider (gmail.com, outlook.com, etc.): volumes, delivery rates, bounces.

GET/api/templates/:id/versions

Version history of a template. Each update saves the previous version.

Error Codes

CodeMeaning
201Email accepted and queued
400Invalid parameters (wrong email address, missing field)
401Invalid or missing API key
403API key has no permission / role not allowed
404Email, template or webhook not found
409Conflict (domain already exists, user already exists)
429Rate limit or quota (per minute/hour/day) exceeded