Werkmail Docs
Contents

API

Send API

Set BASE=https://werkmail.eu. Authenticate with a session, team, or project bearer.

Single send

POST /api/practices/{id}/send202

bash
curl -sS -X POST "$BASE/api/practices/$PRACTICE_ID/send" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: order-123" \
  -d '{
    "from": "Praxis <noreply@your-domain.example>",
    "to": ["you@example.com"],
    "reply_to": ["praxis@example.com"],
    "subject": "Hello from Werkmail",
    "text": "Plain text body",
    "html": "<p>HTML body</p>",
    "tag": "appointment",
    "route": "outgoing",
    "message_kind": "transactional",
    "metadata": {"patient_id": "42"}
  }'

Response:

json
{ "message_id": "uuid", "id": "uuid", "status": "queued" }

Blocked content returns 4xx with code content_blocked, content_reasons, and scanner.

Fields

Field Type Notes
from string Optional; defaults to the tenant From
to string or string[] Required
cc, bcc, reply_to string or string[] Optional
subject string Required
text / text_body string One of text or html required
html / html_body string
route string Slug or UUID; default outgoing
message_kind string termin, recall, doi, transactional, newsletter, custom, …
tag string First tag; used in filters
tags string[] Normalized case-insensitive unique
metadata object String values; echoed on webhooks
headers object Extra MIME headers (restricted set)
attachments array See Sending
settings.track_opens bool Override route default
settings.track_clicks bool Override route default
calendar object ICS invite (summary, starts_at, …)
idempotency_key string Same as the header

Recipient cap: 50 (to+cc+bcc). Dedup across buckets.

Batch

POST /api/practices/{id}/send/batch — JSON array, max 500.

bash
curl -sS -X POST "$BASE/api/practices/$PRACTICE_ID/send/batch" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '[
    {"to":"a@example.com","subject":"One","text":"hi","idempotency_key":"order-1","tags":["orders"]},
    {"to":"b@example.com","subject":"Two","text":"hi","idempotency_key":"order-2","tag":"receipt"}
  ]'

Bulk (templated)

POST /api/practices/{id}/send/bulk and POST /api/emails/send-bulk (flat; pass project_id).

Placeholders use {{variable}}. Each recipient is rendered locally and sent through the shared pipeline. Response is a per-recipient results[] array.

bash
curl -sS -X POST "$BASE/api/emails/send-bulk" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: campaign-2026-03-20" \
  -d '{
    "project_id": "'"$PRACTICE_ID"'",
    "template": {
      "subject": "Hello {{name}}",
      "html": "<p>Hi {{name}}, your code is {{code}}.</p>"
    },
    "recipients": [
      {"email":"a@example.com","data":{"name":"Ada","code":"42"}},
      {"email":"b@example.com","data":{"name":"Grace","code":"7"}}
    ]
  }'

Defaults: message_kind=newsletter, route broadcast. List-Unsubscribe is always injected.

Score (dry-run)

POST /api/practices/{id}/send/score — same body as send, no delivery.

Returns score, grade, inbox_risk, would_block, reasons, warnings, scanner, recommendations, and broadcast/Impressum eligibility when the route is marketing.

Test send

POST /api/practices/{id}/send-test

json
{ "kind": "quality", "to": "you@example.com" }

kind: quality | success | bounce | complaint | ooto

success / bounce / complaint / ooto target the mailbox simulator. quality sends a placement-oriented sample to the address you provide (allowlisted in safe mode).

View this page as Markdown · llms.txt · full corpus