Consent records
Read, export and retain signed consent decisions and their linked history.
Consent stores each visitor decision as a signed server record. You can review statistics, export records as CSV, or retrieve a decision chain using the record id from a visitor’s cookie.
Records are retained for 1095 days. Their contents and retention can support your records of consent, but do not by themselves establish that you meet a particular legal obligation.
What a record contains
Field | Meaning |
|---|---|
recordId | Identifier of this decision |
necessary, preferences, statistics, marketing | Category flags |
method | explicit, implied or withdrawal |
ver | Decision format version |
utc | Server timestamp of the decision |
region | Two-letter country code, or empty |
page_url | Page origin and path |
stamp | Cryptographic signature over the canonical fields |
providers_rev | Provider-set versions disclosed for the decision |
replaces_id | Previous record in the decision chain, if any |
Records contain no name, email, IP address, visitor id, user agent or device fingerprint.
The stamp
Each product has a signing key. Consent uses it to compute a truncated HMAC-SHA-256 over a canonical set of fields. The stamp can establish whether those fields have changed since signing; it does not attest to fields outside that set.
The page URL keeps no query string
The banner removes the query string and fragment before sending page_url, and the server strips them again before storage. Only origin and path remain, avoiding query parameters such as ?email= or ?token= in the record.
necessary is always true
The API rejects necessary: false, and the database enforces the same rule. The banner’s necessary category cannot be declined.
Withdrawal is a record, not a deletion
Withdrawing creates a record with method: withdrawal and replaces_id pointing to the previous choice. Other choice changes also link to the record they replace, so the chain preserves the decision history.
An unknown replaces_id, or one belonging to another product, is stored as empty. Links cannot cross product boundaries.
Statistics
Use consent_stats_get or the app’s reports tab to read decisions over a window. The response includes:
total: the number of records.accept_all_pct,deny_all_pctandcustom_pct: the percentage in each choice group.by_category: percentages for each optional category.range.fromandrange.to: the exact bounds used by the query.
Supply the window as Nd, such as 30d or 90d. Invalid formats return an error. The server’s default window is 30 days and its default maximum is 365 days.
The optional flags determine the group: all three true means accept_all, all false means deny_all, and a mixture means custom. A withdrawal with all optional flags false therefore counts in deny_all.
Percentages are rounded independently to whole numbers and can sum to 99, 100 or 101. With no records, total and all percentages are zero. Use the returned range.from and range.to for an export that matches the statistics window.
consent_dashboard_stats_get provides the smaller summary used when the dashboard opens.
Recent decisions
consent_dashboard_decisions_list returns up to ten recent decisions, newest first. The server labels each row withdrawal when that is its method; otherwise it uses accept, deny or custom from the flags. The app and MCP receive the same labels.
Export
Both export paths require Admin access. They read the same records:
Path | Result |
|---|---|
GET /consent/dashboard/export | Streaming CSV, using a server-side cursor rather than buffering the full export |
consent_records_export | Inline CSV: 1000 rows by default, at most 10000 |
When more records match than the inline limit allows, it returns truncated: true, the full total_count, and a download_url for the streaming endpoint with the same filters.
The CSV columns are fixed in this order:
decision_id, stamp, necessary, preferences, statistics, marketing,
method, ver, utc, region, page_url, created_at, replaces_idBooleans use true and false, timestamps use ISO-8601, and missing values produce empty cells. Visitor-influenced values beginning with =, +, -, @ or a control character receive a quote prefix to prevent spreadsheet formula execution.
Both paths accept inclusive from and to bounds in strict ISO-8601 format. An inverted range is rejected.
For one visitor’s history, pass the record id from their consent cookie as record_id to the inline export. It follows the decision chain within your product; an id from another product returns an empty chain. This export covers Consent records only. Other information you hold about that person must be handled separately when answering an access request.
A successful export emits consent.records.exported with the actor, surface and row count. A client-aborted download does not emit a successful-export event.
Retention
Item | Lifetime | Effect |
|---|---|---|
Consent cookie | 12 months | Expiry prompts the visitor to choose again |
Consent record | 1095 days from creation | A daily job deletes expired records per product |
Retired signing key | 1125 days from retirement | Keeps signing keys available beyond record retention |
These periods are implemented defaults and are not configurable. The 1095-day record period was chosen for consent accountability; it is not a universal GDPR duration. Your own retention requirements depend on your processing and jurisdiction.
The cleanup job never removes active keys, and the database prevents deletion of a key still referenced by a record.
Erasure
Consent’s erasure operation is product-wide. It deletes the product’s Consent tables in one transaction, following their foreign-key dependencies, with no Consent tombstone. Organization-wide erasure resolves into a request for each product.
End-user erasure cannot select Consent rows by a person’s identity because no such identifier is stored. A visitor can instead locate their decision chain with the record id in their cookie. See Data and privacy for the wider export and erasure model.
Next steps
- The consent tools: check permissions before reading or exporting records.
- Data and privacy: understand other data and retention rules.