Blog · Engineering

Cryptographic audit-proof. How we make withdrawals court-ready.

Imagine your shop gets a cease-and-desist because a customer claims they withdrew and you never responded. You need evidence that holds up in court. Not a log file you could have edited yourself. Not a screenshot that can be faked. Something that is mathematics instead of trust.

The problem: trust doesn't scale

A withdrawal is a legally binding act. Whoever claims to have withdrawn needs proof. Whoever claims to have received a withdrawal does too. In the classic setup you store the entries in your database, plus a log file, and hope nobody claims you changed something.

The problem: the operator of the database, that is us, could in theory edit everything after the fact. A lawyer who doubts your evidence has an easy time. “How do we know this database record really dates from the moment it arrived?”

The solution in one sentence

Every withdrawal gets a fingerprint. At the end of the day we combine all fingerprints into a tree. We publish the root of that tree. Anyone can later check whether their withdrawal really was in the tree, without getting access to the other withdrawals.

Whoever doesn't read the rest of this article has grasped the essentials.

The fingerprint: SHA-256

SHA-256 is a cryptographic hash function. You throw in any amount of text, you get 64 characters out. These 64 characters are unique to the text. Change a single comma and the entire hash changes. It is practically impossible to find two different texts that produce the same hash.

Every withdrawal with us is serialized into a defined text block on arrival: name, contact, order reference, free text, timestamp down to the millisecond, shop ID. This block is run through SHA-256. Result: a 64-character hash.

The hash is like a sealed-envelope receipt. If we later show the contents and someone recomputes the hash, it has to match exactly again. If a single character differs, for example because we shortened the name afterwards, the hash no longer matches. Tampering becomes visible.

The tree: Merkle tree

One hash per withdrawal is good, but not enough yet. We would have to publish each hash individually to make them verifiable. That would be a data-protection nightmare, because the hashes plus the information “this hash was on the server at time X” would allow conclusions to be drawn.

Merkle trees solve this elegantly. You take two hashes, combine them and hash the result again. You take this new hash pair together with the next pair, until a single hash remains at the end: the root of the tree.

Withdrawal A → hash_A ─┬───── hash_AB ─┬──────────┐
Withdrawal B → hash_B ─┘              │             │
                                         │             Root
Withdrawal C → hash_C ─┬───── hash_CD ─┘
Withdrawal D → hash_D ─┘

The root is only exactly the same if every single withdrawal underneath it is unchanged. A single altered letter in a single withdrawal would flip its hash, then the pair hash above it, then the next one, all the way up to the root. The root would no longer match.

The notary analogy

Picture a notary. Every day at midnight they collect all withdrawals of the day, write them into a book, seal the book and put it in a vault. The next morning they publish a short code on a billboard in front of their house that only matches this book.

If someone later comes and claims their withdrawal is in the book, the notary can show them: “Yes, look, here on page 47, line 12. The code on the billboard matches this book exactly. If I had changed anything, the code would no longer match, and everyone would see that on the billboard.”

The book is the database. The seal is the SHA-256 hash. The billboard is our public endpoint. The code is the Merkle root.

The public root: /proof

Every day at midnight we compute the Merkle tree of all withdrawals received that day. We write the root into a public endpoint at /proof/root/YYYY-MM-DD.

Every shop owner gets a proof_token for each withdrawal. That is the complete path through the tree, from their own withdrawal up to the root. With this token any third party, a judge too, the customer themselves too, can verify authenticity.

GET /proof/{token}

Response 200:
{
  "revocationHash": "9f86d081884c7d659a2feaa0c55ad015...",
  "merkleProof": ["a3f5...", "b2e8...", "c1d4..."],
  "merkleRoot": "5d41402abc4b2a76b9719d911017c592...",
  "publishedAt": "2026-04-13T00:00:00Z",
  "verifiable": true
}

Whoever wants to check the logic takes the revocationHash, combines it according to the rules of Merkle trees with the elements from merkleProof, and should end up with exactly the merkleRoot. This can be recomputed in any programming language in ten lines of code.

Data protection: why this stays GDPR-compatible

The clever part of the Merkle tree is that the root allows no conclusions about individual withdrawals. We publish neither the names, nor the e-mails, nor even the individual hashes. Only the root and, per withdrawal, the individual path proof.

The path proof goes only to whoever knows the proof_token. And only the shop owner, the customer, and whoever is handed the token by one of the two get it. There is no public list.

This means the construction satisfies two seemingly contradictory requirements at once: public verifiability and GDPR-compliant data protection of the individual transactions.

Why this holds up in court

A judge does not need to understand how SHA-256 works to accept an expert opinion based on SHA-256. The function has been standardized since 2001, is used worldwide by banks, governments and blockchains, and is cryptographically unbroken.

What matters is that the Merkle root was published at a moment when nobody could still influence it after the fact. That is why the midnight write, and why the immutable storage. Whoever claims we added a record afterwards would have to explain how we simultaneously changed the root that had already become public the next day. That explanation does not exist as long as SHA-256 is not broken.

In practice: what you see in the dashboard

In the dashboard every withdrawal gets a link to /proof/{token}. You can pass this link to a lawyer or check it yourself. In any possible legal dispute this is your technically neutral verification, independent of us.

And because we ourselves cannot intervene in the tree without destroying the public root, we too are bound by the proof. This is not a marketing promise but a structural limit of the system.

Why other providers don't have this

Most withdrawal-button providers simply write the entry into their database and rely on backups plus a clear conscience. That is enough until the first dispute escalates. Then you stand there with a database row that a technical expert classifies as manipulable in ten seconds.

We chose the extra effort because the obligation under EU Directive (EU) 2023/2673 (Article 11a of the Consumer Rights Directive), applicable across the EU from 19 June 2026, is too new to rely on habit. The first court decisions are still to come. When they come, you want to be on the side that has the mathematics.

Details on the implementation in our guide or on the product page.

Court-ready, without you having to do anything

WiderrufButton archives every withdrawal in a cryptographically verifiable way. You get the proof, we keep the book.

Start free now

14 days free · No credit card required