# Records and proof

What is stored about each response and how to find it.

We record every response a visitor gives the banner: an anonymous ID, the time, the choice for each category, the banner version, the country, where the visitor was (the country, or in the US and Canada the state or province, such as `US-CA`), the version of the rules in force, and the browser type. We don't record IP addresses. These records are what you show if a regulator or a visitor asks for proof.

## The Responses tab

Each site in the dashboard has a **Responses** tab. It shows:

- How many responses came in over the last 30 days, split into Accepted all, Chose some and Rejected all.
- The same numbers by place, on a map that draws each US state separately or as a table. Click a place to see its latest responses.
- Browser opt-outs (Global Privacy Control), counted separately.
- The latest responses, described in plain words. We keep every choice a visitor makes, so a later change shows as **Changed** and turning something off shows as **Withdrew consent**.
- An ID for every response. The table shows the first 8 characters, and clicking copies the full ID. **Find by ID** accepts either. A developer can get a visitor's own ID in their browser with `cmp.getConsentId()`.
- **Download consent log**, which exports everything as a CSV file for proof. For each response, the `event` column says what it meant compared with the visitor's previous response: first choice, changed, withdrew consent or GPC opt-out. For US visitors who opted out of the sale or sharing of their data, it also includes the record California's regulations (§7101) ask for: the request, how it was made (GPC signal or the site's privacy choices) and the response, in `optout_request`, `optout_method` and `optout_response`. `event_id` identifies each response, and `id` identifies the visitor and is the same on all their responses. On sites with ad networks (IAB TCF) turned on, `tc_string` holds the TC string ad partners were given after the choice and `ac_string` holds Google's Additional Consent string; both are empty for every other response, and both are part of the response's fingerprint when present.

## What they saw

Every time your banner is published, we keep an exact copy of it, including the wording in every language, the colours, the layout and the links. Each copy is identified by a fingerprint of its content, so any later change to it would show. Each response records which copy the visitor saw, the version of the banner code, where the visitor was and the rules in force.

We also take screenshots of every published version, on desktop and on a phone. They are drawn from that copy by the same code that renders the live banner. The fingerprints of each pair of screenshots are timestamped by independent timestamp authorities, following CNIL's advice to keep timestamped screenshots of each version. Open **What they saw** to see them.

Click **What they saw** on any response to see the banner redrawn exactly as that visitor saw it, in their language and with those details.

## Tamper-evident

Every night we seal the previous day. Each response gets a fingerprint (a SHA-256 hash of its fields). Your site's fingerprints are combined into one site fingerprint, and the fingerprints of all sites are combined into one for the day. Each day is then chained to the day before, so no past day can be rewritten without breaking every day after it. We publish the sealed days, as hashes only, at [cdn.flatconsent.com/proof](https://cdn.flatconsent.com/proof). This follows the French regulator CNIL's recommendation to publish a timestamped hash as proof.

Two independent timestamp authorities, DigiCert and Sectigo, also timestamp each day's chained fingerprint under the RFC 3161 standard. Their signed tokens prove that the day existed in that form by the signed time, without relying on us or our clock. We publish the tokens with each day.

You can check your own records without trusting us. Download your consent log (each response's fingerprint is in the `leaf` column) and run:

```bash
curl -O https://flatconsent.com/verify-proof.mjs
node verify-proof.mjs responses.csv YOUR_SITE_ID 2026-09-22
```

The script recomputes every fingerprint from the data, rebuilds your site's fingerprint for that day, finds it in what we published, and checks the day's timestamps with OpenSSL, which is installed on macOS and most Linux systems.

## Proof of consent, signed

For any response, open **What they saw** and download its **proof of consent**, either as a one-page PDF for people or as JSON for machines. It states what the visitor chose and what that meant (first choice, change, withdrawal or US opt-out), where they were and which rules were in force, exactly which banner they saw, and where the response sits in the sealed and timestamped records. Flat Consent signs it with Ed25519, and our public key is at [cdn.flatconsent.com/proof/key](https://cdn.flatconsent.com/proof/key).

You can also get the consent log export signed: after **Download consent log**, choose **Signature for this file**. The signature states the file's SHA-256 hash, how many responses it holds and its cut-off time. You can check either kind of signature without trusting us:

```bash
node verify-proof.mjs --signed responses-example.com-1790000000000.csv responses-example.com-1790000000000.csv.sig.json
node verify-proof.mjs --proof proof-example.com-1a2b3c4d.json
```

## Change history

We record every change to a site's settings: who made it, whether it came through the dashboard, an API key or our own site check, and each setting's value before and after. Open **Change history** at the bottom of the Banner tab.

## How long records are kept

Under **Keeping records** on the Responses tab, choose 1, 2, 3 or 5 years. The default is 2 years, which covers California's requirement to keep opt-out records for 24 months. Older responses are deleted automatically each night, and each cleanup is logged.

**Hold** stops all deletion until you turn it off, for example during a complaint or an investigation.

If a cleanup would delete far more than on a usual night (after you shorten the period, for example), it waits a week first. Everyone on your account gets an email saying how many responses will be deleted, from before which date and on which day, with a link to download them first. The same notice shows under **Keeping records** until then. Choosing a longer period or turning on Hold during that week cancels the cleanup.

## Who accessed the records

The Responses tab lists everyone who viewed, looked up, downloaded or deleted responses, with the time and whether they used the dashboard or an API key. Viewing is logged once an hour per person, and downloads, proofs and deletions are logged every time.

## Deleting a visitor's responses on request

If a visitor asks for their data to be deleted, find their response by ID, open **What they saw** and choose **Delete this visitor's responses**. This permanently removes every response with their ID. We keep only a note that responses were deleted on request, along with each one's fingerprint, so days that were already sealed still verify.
