How to share financial data with an analyst without handing over your customers

August 21, 2026 · accounting · Share
How to share financial data with an analyst without handing over your customers

TL;DR — Quick Answer

An export holds two things: behavior and identity. Every question you have lives in the numbers, and the numbers are impersonal. Replace each text label with a stable token — Germany becomes COUN-000004 in every row — and totals, group-bys and joins all survive untouched. The masked file goes out. The key stays with you.

How to share financial data with an analyst without handing over your customers

You export the quarter, attach the file, start typing the email. Then you scroll left, see the column with customer names in it, and close the window without sending.

The question was a fair one. Margin fell in Q4 while units held, you have looked at it twice, and you want someone who does this for a living to look at it once. What stopped you was not the question. It was four columns you would have to hand to an outsider to get it answered.

So you paste a summary into the email instead.

A summary is an answer, not evidence

Whoever reads that summary — your accountant, an outside analyst, a consultant hired for a month — can agree with you or disagree with you, and that is the entire range of what they can do with it. If the thing you are missing is inside the file — a discount band that behaves differently in one country, a product that only loses money at one price point — then the total you pasted was built by adding it away. Nobody finds it there. Adding it away is what totals are for.

The next idea is to delete the sensitive columns and send what is left. Nothing leaks, which is true and narrow. Strip country, segment and product from a sales export and you have seven hundred rows of arithmetic with nothing to group them by — not data so much as a column of numbers and a shrug.

Then there is the NDA, which is not nothing. It gives you something to point at if the file turns up where it should not. What it does not do is change what sits on the other machine. An NDA governs behavior after the copy exists.

None of these three responses are foolish. They are reasonable answers to a problem that looks binary: the file is either sensitive or it is not, and you either send it or you don't.

The file is not one thing, though. It is two things that arrived in the same envelope.

Two different kinds of column

Open the export and look at the columns as two groups rather than sixteen items.

One group is behavior. Units, price, discount, cost, margin, the dates. Every question you have lives here, and none of it is personal: a margin of 31% is a fact about a transaction, not about a person.

The other group is identity. Customer, country, segment, SKU. These columns do not enter a single calculation. They are addresses. Their whole job is to say which rows belong together.

What makes the file feel unsendable is the second group. What makes it worth sending is the first. And the analysis does not need the labels in group two — it needs those labels to be consistent. Every row that says Germany has to keep saying the same thing as every other row that says Germany, in this file and in the next one. Whether that thing reads "Germany" or "COUN-000004" changes nothing about the arithmetic and everything about what you just emailed.

That is the whole idea: cut the file across the columns rather than down the rows, and replace rather than delete.

How to share financial data with an analyst and keep the names

Here is the check on a public sample workbook — seven hundred rows, sixteen columns, the kind of sales export everyone has seen. Four columns hold text: Segment, Country, Product, Discount Band. The other twelve hold units, prices, dates and money.

Replace every text value with a stable token. Germany becomes COUN-000004 in every row where it appears, in that column and in every column of the same name on every sheet of the workbook. Five countries, five tokens. Nothing else in the workbook is touched.

Now look at what survived. Gross sales across the file: 127,931,598.50 before, 127,931,598.50 after. Profit by country: France 3,781,020.78, and COUN-000001 3,781,020.78. Units, discounts, COGS, dates, month names — identical, because the tool never went near them.

The analyst comes back and says that COUN-000004 gives up its margin in DISC-000001 and nowhere else, and that the effect is seasonal. You read that sentence with the key open next to it and it says Germany, deep discount band, Q4. The finding was reached without knowing it was Germany, because the finding never depended on it. What it depended on was the German rows staying together.

Substitution is the easy half

Filling a column with plausible values is a solved problem; a one-line library call does it. What decides whether the masked copy is worth anything is what survives the substitution, and that list is longer than it looks.

Referential integrity comes first, and it is the one broken by accident. Mask Monday's export in one pass and Tuesday's in another, and Germany gets a different token in each. The files stop joining, and a masked export that cannot be joined to the next one is a dead end.

Cardinality is second. Three payment providers across forty thousand rows have to come out as three providers, not forty thousand unique strings. Get that wrong and the copy describes a business that does not exist.

Duplicates are third, and this is the one that trips up tools written by people who have never reconciled anything. A repeated row looks like dirt. It is frequently the finding — two identical captures from the same provider on the same day are either a genuine double charge or a broken import, and both are things you are paying someone to notice. A masker that deduplicates while it works has destroyed the evidence and left a tidy file behind.

Emptiness is fourth. NULL, an empty string and zero are three different statements — nothing arrived, the field was blank, the value was really zero — and a tool that converts any one of them into another has changed what the column means.

And the outliers stay. Refunds, reversals, negative lines, the single order forty times larger than its neighbors: not noise to be cleaned up before an outsider sees it. Usually the reason someone is looking — a refund landing two months after the sale is its own kind of problem, and it is invisible in a file that has been tidied.

The disguise has to look like a disguise

The obvious improvement is to make the substitutes realistic. Rather than CUST-000007, write "Initech Inc". The file stays pleasant to read, the analyst is not squinting at codes, and everything above stays true.

That improvement is the one thing you must not do.

A realistic fake is indistinguishable from a real value that got through. "John Smith" sitting in a masked column might be a substitution, or it might be the one row the tool skipped because of a trailing space, and there is no way to tell by looking. To be confident the file was clean you would have to verify the tool rather than the output — trusting a promise instead of checking a fact, which is the exact position you were trying to get out of when you closed the email window.

Ugly sequential tokens make the check take half a minute. Scroll the column. Anything not shaped like CUST-000123 is a leak, and it is visible from across the room.

The numbering is shuffled deliberately for the same reason. In the workbook above, Canada appears in the very first data row and got COUN-000002; France, which shows up later, got COUN-000001. Handing numbers out in order of appearance would quietly encode who came first, and sorting them by volume would encode who is biggest. The token is meant to carry nothing at all.

Where this stops working

Three limits, and the first is not a detail.

This is pseudonymization, not anonymization, and the words are not interchangeable. Pseudonymization replaces identifiers with stable substitutes and leaves the rest of the record intact. Anonymization would mean the record can no longer be tied back to anyone at all — a far stronger claim, and not one this makes. The amounts, the dates and the number of distinct values are all real, so someone who already holds the same records from another source — a public registry, a leaked database, an invoice they were sent — could line them up and work back toward identities. Without such a source there is nothing to match the numbers against. What the masking removes is the accidental case: the customer list that lands in someone's inbox and stays there for years. It is a way to send data to a party you have already chosen to work with, and a bad way to publish.

Second, the key. You now hold a file mapping every token to its real value, and it is the most sensitive object in the exercise. The risk did not vanish; it changed shape. That is a far better problem to have: one file, in one place you control, instead of copies you cannot reach.

Third, mask only what is genuinely an address. If the analyst needs to know it is Germany because a VAT rate, a currency or a seasonal pattern depends on it, then Country is doing analytical work, and masking it removes the answer along with the risk. That is a column-by-column judgment about your own data — which is also why a tool that guesses meaning from column headings would be worse than one that refuses to. A heading can say anything. Only you know what is actually in the column.

What we ask for, and what we will not take

This is how our own intake works, so the abstract version has a concrete one.

We ask for two things: exports, and a description of what is in them. The exports can be masked before they ever leave your machine. The description is the part people do not expect — which column holds the payout id, which figure is gross and which is net, what those status values mean in that particular system. We ask you to name your own structure instead of inferring it, because inference produces confident mistakes, and confident mistakes in financial data are expensive to find later.

What we do not ask for: access to your store, your bank or your accounting system. And the key. We hold no lookup dictionary, we do not ask for one, and we will not accept one if it is offered — the moment it sits on our machine, every sentence above stops being true.

There are things we deliberately do not promise, too. We do not encrypt anything on your behalf, we do not provide a GDPR opinion, and we do not claim the masked file is anonymous. The limit is the one described above, and it is the only one we know of.

We built the tool that does the masking because we needed it. It runs in the browser and nothing is uploaded: no server, no third-party domain, and once the engine has loaded you can disconnect from the network and watch it keep working. That last part matters more than any assurance we could write, because "we can't see your data" is a claim, while an empty Network tab is a measurement. It is at anonymizer.alsok.org, the source is on GitHub under Apache-2.0, and it works the same whether or not you ever talk to us.

Underneath all of it is a distinction that turns up everywhere in financial architecture once you start looking: whoever holds the dictionary owns the data, and computation does not require ownership. A model can be built, checked and argued over on tokens. The moment identity is genuinely required arrives much later and much less often than everyone assumes, and it is usually a moment you can attend yourself.

An NDA is a promise about what someone will do with your numbers. A key you never sent is a fact about what they can.

(Figures above come from a public sample workbook, processed exactly as described.)

Start with the gap

Before rebuilding anything, find out what the difference between your sales and your bank deposits is actually made of. Send one month of payout data and get it broken back apart, line by line.

Payout Gap Report →

Exports only. No access to your store, your bank or your accounting system.

Published: August 21, 2026 · Back to Insights

Share