No.
BP-AT-001
Scale
1 : 1
Date
2026-05-25
Rev.
A
Werkstatt 4notify · Data protectionReleased
Blueprint BP-AT-001 of BP-AT-008 · Data protection
SMSEmailWhatsAppWebhook

GDPR-compliant consent management with audit trail

Double opt-in, withdrawal handling and an audit log fit for the Austrian DPA

§ AThe problem

Many platforms store consent as a single boolean column — `marketing_opt_in = true`. That predates the GDPR and won't survive a complaint today: the Austrian DPA requires consent to be demonstrable in detail (exact wording, date, channel) — and withdrawal must take effect within 30 days, be documented and confirmed back to the data subject. Without that, you risk formal warnings; repeat findings draw fines of up to 4% of global annual turnover or EUR 20 m.

§ BMain view

The Austrian Data Protection Act (DSG, BGBl. I 165/1999) supplements the GDPR with national specifics — the Datenschutzbehörde (DPA) in Vienna publishes annual guidance interpretations. For notifications this means: consent must be informed, freely given, specific to a purpose and demonstrable, and withdrawal must be as easy as granting it. 4notify implements this as a consent ledger: every opt-in is stored with timestamp, IP, user-agent, the exact wording the user saw and the channel scope. The ledger is append-only and exportable as CSV for DPA requests.

§ CParts list
ChannelPrimary providerFallback
Consent-FormHosted form @ 4notifyEmbed (JS widget)
Double-Opt-in E-Mail4notify Mail (DKIM/DMARC)Mailgun EU
Audit-LedgerPostgres append-onlyS3 EU-Central WORM
Widerruf-LinkSigned HMAC-token URLInbound STOP keyword
DSB-ExportAsync CSV jobJSON API (Pagination)
§ DTolerances
Double opt-in window
72hours
Withdrawal effective in
30days (GDPR)
Audit log retention
7years
DPA request export
≤ 30days (GDPR Art. 12)
Withdrawal confirmation
≤ 24hours
§ ENormative references
DSGVO Art. 6 (1) (a)

Processing is lawful only if the data subject has given consent. For SMS/email direct marketing, consent is the only viable legal basis — Art. 6(1)(f) legitimate interest rarely survives a marketing-channel balancing test.

DSGVO Art. 7 (1)

Where processing is based on consent, the controller must be able to demonstrate consent. The proof must be reconstructible by content and date — a boolean flag isn't enough.

DSGVO Art. 13

Information duty: at collection time, identity of controller, purposes, legal basis, recipients, storage duration and data-subject rights must be disclosed. The exact wording shown is archived in the consent ledger.

DSG § 1 (Verfassungsbestimmung)

The Austrian DSG raises data protection to constitutional rank — the DPA tends to interpret it more strictly than other EU supervisory authorities, particularly the granularity requirement for bundled consents.

§ FBuild steps

Lock the consent wording in the ledger

Before consent is collected in production, the exact wording is locked as a versioned template in the ledger. Every later opt-in references this version — even when the frontend changes later, the historical proof stays consistent.

Double opt-in via email with a signed token

After the first click, an HMAC-signed confirmation link is sent to the supplied email address. Only after the user clicks does the ledger flip the consent to `active`. The token is valid for 72 hours — afterwards consent silently lapses.

Ledger as an append-only table

Instead of UPDATEs, every state change is written as a new row (granted, confirmed, withdrawn, expired). The full history stays forensically reconstructible — essential when DPA complaints look back years.

Withdrawal via link + SMS STOP + API

Every send carries a signed withdrawal link in the footer (email) or a STOP hint (SMS). Inbound STOP messages are delivered back by the gateway as MO webhooks and simultaneously written to the ledger as a new row.

DPA export as an async CSV job

On DPA request, the full history for a data subject is exported as CSV (with timestamp, IP, user-agent, text version, channel scope). The job runs async, generates a signed S3 URL and stays retrievable for 7 days.

§ GTest procedure

Test procedure: (1) Create an entry with a test email — verify the ledger row was written with status `pending`. (2) Receive the confirmation email, click the link — confirm a new row with status `confirmed` and the same consent_id exists. (3) Click the withdrawal link — new row with `withdrawn`. (4) Send a test SMS to a test number, reply STOP, verify the MO handler inserts a `withdrawn` row with channel `sms`. (5) Call the DPA-export endpoint, download the CSV, verify all four rows with correct timestamps.

§ HCode
bash
curl -X POST https://api.4notify.net/v1/consent/grant \
  -H "Authorization: Bearer $API_KEY' \
  -H "Content-Type: application/json' \
  -d '{
    "email': '[email protected]",
    "phone': '+436641234567",
    "wording_id': 'consent_v3_at",
    "purposes': ['transactional", "appointment_reminder"],
    "channels': ['sms", "email"],
    "client_ip': '85.127.0.1",
    "user_agent': 'Mozilla/5.0 ...",
    "consent_type': 'double_opt_in"
  }'
§ ISample message
SMS

WienerHandwerk: confirm your newsletter sign-up by replying YES to this number. Reply STOP to opt out. Privacy: 4notify.net/datenschutz

§ JCommissioning checklist
  • Lock the consent wording as a versioned template (e.g. consent_v3_at)
  • Double opt-in email signed with DKIM and DMARC
  • Ledger table set up as append-only (Postgres trigger or application layer)
  • Withdrawal link signed with HMAC, valid for 30 days
  • Inbound STOP webhook active for every SMS sender ID
  • DPA-export endpoint with async job + signed S3 URL implemented
  • Retention policy: audit log kept for at least 7 years, auto-deleted afterwards
What 4notify does differently

Instead of a boolean `opt_in = true` flag, 4notify maintains an append-only audit ledger — every consent, confirmation and withdrawal stays forensically reconstructible, years back.

§ KFAQ
How does the Austrian DPA interpretation differ from Germany's BfDI?

The DPA is stricter on granularity: bundled consents (e.g. ’marketing + profiling + third-party sharing’ in one checkbox) are consistently treated as invalid, where the German BfDI sometimes allows leeway. One checkbox per purpose is the safe choice.

Does withdrawal really need to take effect in 30 days?

GDPR Art. 12(3) requires a response to data-subject rights within 30 days. For a pure withdrawal of consent the DPA expects effectively immediate effect — the 30-day window is meant for access and erasure requests that require effort.

What happens if a customer orders again after withdrawing consent?

Transactional messages (order confirmation, shipment status) stay covered by legitimate interest Art. 6(1)(f) — withdrawal applies only to marketing purposes. The ledger separates `transactional` and `marketing` as distinct purpose_ids.

Open a free account

14 days, no card. German-language support.

§ LOther blueprints