A JSON API for sending transactional email. One endpoint to send, full delivery feedback per recipient, and guided domain verification. All requests are authenticated with your API key.
| Base URL | https://api.digitmailer.co.za |
| Authentication | Header Authorization: Bearer dm_<your key> on every request. Create keys in your dashboard. |
| Content type | application/json |
| Errors | All errors return {"error":{"code":"...","message":"..."}} |
curl -X POST https://api.digitmailer.co.za/v1/messages \
-H "Authorization: Bearer dm_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"from": "Billing <billing@yourdomain.co.za>",
"to": ["customer@example.com"],
"subject": "Your invoice INV-1042",
"html": "<p>Please find your invoice attached.</p>",
"text": "Please find your invoice attached.",
"attachments": [
{"filename": "INV-1042.pdf", "content_type": "application/pdf", "content_b64": "JVBERi0x..."}
],
"idempotency_key": "inv-1042-first-send"
}'
Response 202:
{"id": "0d9c1c6e-8f2a-4c1e-9c1a-2b7e8f0a1d42", "status": "queued"}
from domain must be verified and active on your account (see Domains below).html, text, or both — at least one is required.idempotency_key (or an Idempotency-Key header) makes retries safe: a repeated call returns the original id with "duplicate": true."suppressed" array.{
"id": "0d9c1c6e-...",
"status": "accepted",
"recipients": [
{"addr": "customer@example.com", "status": "delivered",
"detail": "250 2.0.0 OK", "updated_at": "2026-08-20T21:41:43Z"}
],
"opened": true, "open_count": 2, "first_opened_at": "2026-08-20T21:44:01Z",
"events": [
{"event": "queued", "at": "..."},
{"event": "smtp_accepted", "detail": "5E77444DB7", "at": "..."},
{"event": "delivered", "detail": "customer@example.com: 250 2.0.0 OK", "at": "..."},
{"event": "opened", "at": "..."}
]
}
status is the pipeline state: queued → sending → accepted (handed to the mail server) or failed.status: pending, delivered, deferred (temporary failure, retrying), bounced (rejected — detail carries the receiving server's reply), or complained (recipient reported it as spam).Register the domain you send from, publish the DNS records we return, then verify. Sending is enabled the moment your DKIM record is live. The dashboard wizard does the same thing visually.
# Register — returns the DNS records to publish (DKIM required; SPF + DMARC recommended)
curl -X POST https://api.digitmailer.co.za/v1/domains \
-H "Authorization: Bearer dm_YOUR_KEY" -H "Content-Type: application/json" \
-d '{"domain": "yourdomain.co.za"}'
# Check DNS and activate
curl -X POST https://api.digitmailer.co.za/v1/domains/yourdomain.co.za/verify \
-H "Authorization: Bearer dm_YOUR_KEY"
# List / inspect / remove
GET /v1/domains
GET /v1/domains/{domain}
DELETE /v1/domains/{domain}
pending_dns → active; a domain whose DKIM record disappears is suspended and reactivates automatically when the record returns.{"month": 202608, "accepted": 12480, "delivered_to_postfix": 12401, "failed": 12,
"plan": {"code": "starter", "name": "Starter", "included_emails": 50000, "overage_policy": "block"},
"remaining": 37520}
| Option | Default | Effect |
|---|---|---|
| Track opens | on | Embeds a read pixel in HTML mail; opens appear on the message as opened/open_count. |
| Unsubscribe link | off | Appends an unsubscribe link to the email and emits one-click List-Unsubscribe headers (single-recipient messages). Recipients who unsubscribe are added to your suppression list automatically. Recommended for marketing/bulk mail; leave off for transactional mail like invoices and password resets. |
Tip: create separate keys for transactional and marketing traffic so each gets the right behavior.
Addresses that report your mail as spam or hard-bounce (user unknown) are suppressed automatically and skipped on future sends — this protects your sender reputation.
GET /v1/suppressions # list: addr, reason (complaint|hard_bounce|unsubscribe|manual), detail
DELETE /v1/suppressions/{addr} # remove an address (use with care)
| Code | Meaning |
|---|---|
| 202 | Message accepted and queued. |
| 400 | Invalid request — or all_recipients_suppressed. |
| 401 | Missing or invalid API key. |
| 402 | Monthly quota exhausted on a hard-capped plan. |
| 403 | Sender domain not verified/active, or account suspended. |
| 413 | Message exceeds the 20 MB size limit. |
| 429 | Rate limit exceeded — honour the Retry-After header. |
Questions or missing features? Contact us — the API is versioned under /v1 and breaking changes will only ever ship under a new version prefix.