Compliance evidence
Technical guide for DPOs, auditors, and engineers who need to know exactly what Werkmail records and how to get it out. Product thesis: Regulated transactional. Operational controls: Compliance.
What the consent ledger stores per contact
Each ledger event is immutable and append-only. Nothing is overwritten — withdrawals and updates are new events, so the history stays readable in order.
| Field | Meaning |
|---|---|
email / contact_id |
The contact the event belongs to |
channel |
termin, recall, newsletter, transactional, other |
legal_basis |
Simplified GDPR Art. 6 labels: consent, contract, legal_obligation, vital, public_interest, legitimate_interest |
action |
granted, withdrawn, updated, exported, erased, doi_pending, doi_confirmed |
source |
Where the grant came from (form, import, API, preference centre) |
actor_email |
Who performed the change, when there is an operator |
details |
Free-form evidence, including the wording the person saw, IP, and user-agent |
created_at |
Timestamp |
Retention follows the workspace's DSGVO settings; redaction and erase are first-class actions (below). Werkmail does not silently delete ledger history for active contacts.
Pulling an audit export
The workspace audit log is live:
GET /api/practices/{id}/audit
A packaged, DPO-ready audit export is planned — from/to window plus CSV or JSON:
GET /api/practices/{id}/audit-export?from=2026-08-01&to=2026-08-31&format=csv|json
# DPO Audit Export (CSV or JSON)
curl -sS -H "Authorization: Bearer $TOKEN" \
"$BASE/api/practices/$PRACTICE_ID/audit-export?from=2026-08-01&to=2026-08-31&format=csv"
Data Processing Agreement (AVV / DPA)
Werkmail provides a self-service, electronically signable Data Processing Agreement (Art. 28 GDPR) tailored to European compliance:
# Fetch template preview
curl -sS -H "Authorization: Bearer $TOKEN" \
"$BASE/api/practices/$PRACTICE_ID/avv?region=eu-central-1"
# Electronically execute agreement
curl -sS -X POST -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{"signer_name": "Dr. Med. Müller", "signer_title": "Managing Director", "region": "eu-central-1"}' \
"$BASE/api/practices/$PRACTICE_ID/avv/sign"
Consent history and DSAR export
Per-contact consent history is live today:
GET /api/practices/{id}/contacts/{contactID}/consent
A friendlier alias and a DSAR package endpoint are planned:
GET /api/practices/{id}/contacts/{contactID}/consent-history— planned alias of/consentPOST /api/practices/{id}/dsar-export— planned; accepts a contact identifier, runs asynchronously, and fires the workspace webhook when the package is ready
Contact export and erase are live today:
GET /api/practices/{id}/contacts/{contactID}/exportDELETE /api/practices/{id}/contacts/{contactID}
How outgoing/broadcast isolation is enforced
Isolation is not a UI rule — it is wired into the sending infrastructure:
- Each workspace is its own sending tenant on the outbound provider, with its own configuration set and reputation profile. A neighbour's complaints cannot affect your tenant.
outgoing(transactional) andbroadcast(marketing) messages never share the same reputation path inside a tenant.- The content gate — the same one used in compose, batch, and API — rejects marketing-shaped content on transactional routes.
- Werkmail maintains its own suppression store and rate limiter; provider-account suppression lists and account-wide send-rate caps are not the only gates.
Reputation pause: exact thresholds
Werkmail computes rates from its own event log over a rolling window and pauses a tenant when any of these hold:
| Trigger | Condition |
|---|---|
| Bounce rate | ≥ 5% of sends in the window, with at least 20 sends |
| Complaint rate | ≥ 0.1% of sends in the window, with at least 20 sends |
| Absolute complaint spike | ≥ 3 complaints with at least 5 sends in the window |
A per-practice bounce-threshold override can tighten or relax the 5% default. While paused, sends are rejected with a paused result, and an owner must resume the tenant after fixing the list.
Getting notified before a pause
- Webhooks — message events:
message.hard_bounced,message.soft_bounced,message.spam_complaint,message.failed - Slack / Teams alerts:
POST /api/practices/{id}/alerts - The deliverability cockpit shows live bounce and complaint rates before thresholds are hit.
Topic guide: Webhooks API. Reputation guardrails: Compliance.