Skip to content

Privacy

What happens to a file you open here, what is measured, and what is not. Written to be checkable rather than reassuring.

The browser tools: your document never leaves your device

Every tool on this site reads files in your browser. When you drop a file on a tool, it is read with the browser's File API and parsed with the browser's own XML parser, inside the tab. No tool on this site has an upload step, and no code that runs in your browser has a path that sends document content anywhere.

There is one part of this project where that is deliberately not the case, and it is not a tool on this site: the Validation API, a separate product where a developer uploads a document on purpose, from their own server. It is described below, along with the developer account that goes with it. Nothing you do on these pages goes near either.

This is a claim you can check rather than take on trust. Open your browser's developer tools, switch to the network panel, and load an invoice into the UBL viewer or the CII viewer. No request is made. The only request any tool makes is a GET for this site's own sample documents, and only when you press the sample button.

The validators are the one nuance, and it is visible in the same network panel: the UBL validator and the France validator download their schema and rule files from this site's own origin in order to run them in your browser. Those requests are for fixed, versioned artefact paths — the same ones for everybody — and nothing in them is derived from your document. Your document is still never transmitted.

PDFs work the same way. The Factur-X viewer and the Factur-X validator parse the file with a local copy of PDF.js in a worker, with PDF JavaScript and evaluation disabled and the worker served from this origin. Opening a PDF here generates no network request derived from its contents: no remote font, no external image, no URL built from anything inside the document.

What is not stored

  • No file storage, anywhere. No document is written to disk on any server — not one you open in a browser tool, which never reaches a server at all, and not one you send to the API, which is held in memory and discarded. There is no object storage behind this site and no database column a document could go into.
  • No account for using the tools. The browser tools have no sign-up, no login and no session. Nothing links one visit to another. A developer account exists only if you deliberately create one for the API, and it has no bearing on how the tools behave.
  • No persistence in your browser. Documents are held in memory for as long as the page is open. Closing or reloading the tab discards them.
  • No invoice content in logs. Parse failures are reported to you in the page. Document content is never written to a console or a log, by the tools or by the API.

Contact form

The contact page carries a form, and it is the one place on this site where you deliberately send information to us. It is worth separating clearly from everything above, because the two work in opposite ways.

What is collected
The name, email address, category, subject and message you type into the form. Nothing else: there is no attachment field, no file upload, and no device or browser fingerprinting attached to the submission.
Why
To read your message and reply to it. Your address is used for that and for nothing else — no mailing list, no newsletter, no onward sharing, no advertising.
Who is involved in delivering it
The message travels from your browser to this site's server, which passes it to the mail infrastructure of the site's host, Hostinger, which delivers it to the project's mailbox — a Google (Gmail) account. Google therefore receives contact messages, because that is where the destination mailbox is. Google receives no invoice, no document and nothing derived from one: documents never enter this path at all.
How long it is kept
Contact correspondence is reviewed and deleted after about 12 months, unless it needs keeping longer to continue an active conversation, to meet a legal obligation, or to deal with a dispute. This is a policy about the destination mailbox: this application stores nothing, has no database behind the form, and keeps no copy of a message after handing it to the mail system.
What the application itself records
Whether a send succeeded or failed, as a single log line naming neither you nor your message. Your name, address, subject and message body are never written to a log.

Please do not paste invoice or document contents into a contact message. A message is ordinary email and travels through the mail systems described above; the tools on this site are built precisely so that your documents do not.

Validation API

Separate from everything above, and the opposite way round: the Validation API is a server-side interface for developers, and using it means sending us a document on purpose.

We are saying so here rather than quietly extending the sentence at the top of this page, because "your document never leaves your device" is a promise about the browser tools and it would stop being true if it were stretched to cover an API whose entire purpose is to receive documents. The promise about the tools is unchanged. The API has its own, and it is this:

  • Held in memory, never written down. An uploaded document is processed in memory and no temporary file is written at any point — not to a temporary directory, not under a random name, not at all. There is therefore nothing to delete afterwards, and nothing a crash or a timeout can leave behind.
  • Not retained. No document storage, no validation history, no findings database. The result is returned to the caller and the processing state is discarded.
  • Not logged. Operational logs record a request identifier, the public prefix of the API key, which target ran, the size in bytes, how long it took, the HTTP status and how many findings there were. They never record document content, a filename, an invoice number, a party name, a VAT identifier, an amount, the text of a finding, or a hash of the document.
  • Counted, not profiled. Per-day counts of requests and bytes are kept against each API key, and a per-day count of admitted validations against each account, so that a quota can be enforced and usage shown back to you. Every number would be identical if you had validated an empty file.
  • Not measured by analytics. No Google Analytics event is emitted for an API request, and nothing derived from an uploaded document reaches any analytics system.

The full developer documentation is published on this site: what the report contains, what the limits are, and what a validation result does and does not establish.

Developer accounts

A developer account is the one place on this site where an identity is held. You create one deliberately, in order to use the API; nothing about the browser tools creates one, and nothing you do with the tools is visible from one.

What follows is the complete list of what an account stores. It is written out rather than summarised because "account data" is a phrase that could mean anything.

You
Your email address, stored once in a normalised form — trimmed and lower-cased — because two copies of an address are two things that can disagree about who an account belongs to. Your password as a scrypt hash, never as the password. Whether the address has been confirmed, and when. Whether the account is active or suspended. When it was created and last changed.
Your account
An account name, which starts as something derived from your address and which you may change. Its entitlement — which beta allowance applies — and its status. A membership row joining you to it.
Your projects
The name you gave each project, its status, when it was created, and which account owns it. A project name is free text you chose and is visible only to you; it is not a place to put personal data or customer names.
Your API keys
The public prefix, which is not a secret and appears in operational logs. The secret half as a SHA-256 digest, never in a recoverable form — a dump of this table is not a set of working credentials. Whether the key is active or revoked, which targets it may use, its rate limit, when it was created, when it was last used and when it was revoked.
Your sessions and links
For each signed-in session: a SHA-256 digest of the session token — never the token — with when it was created, last seen, expires and was revoked. For each verification or password-reset link: a SHA-256 digest of the token, what it is for, when it expires and whether it has been used. Nothing here can be turned back into a working credential.
What you agreed to
Which agreement, which version of it, and when you accepted it — for the Terms of Use, the Developer and API Terms and this privacy policy. A version string rather than a tick, so that "what did they actually agree to" has an answer that survives the page being edited.
Usage
Per API key and per UTC day: how many requests were made, how many produced a report, how many did not, and how many bytes were uploaded. Per account and per UTC day: how many validations were admitted against the daily allowance. Counts and dates. Nothing about any document.

Why it is held. To operate the account you asked for — to sign you in, to authenticate your API calls, to enforce the allowance, to show you your own usage, and to keep a record of the terms you accepted. There is no profiling, no advertising use, no sharing and no onward transfer.

How long. For as long as the account exists. What survives closing it is set out below.

Email. Verification and password-reset messages are sent from no-reply@edocumenttools.com through the mail infrastructure of this site's host, Hostinger, to the address you registered. That address is used for those messages and for nothing else: no newsletter, no product mail, no marketing. There is nothing to unsubscribe from.

Anti-abuse check (Cloudflare Turnstile)

Four forms can be protected against automated abuse by Cloudflare Turnstile, a service of Cloudflare, Inc.: developer sign-up, forgotten password, resending a verification email, and the contact form. When the check is switched on for this site, those four forms show it; no other page and none of the browser tools load it, and signing in, resetting a password and closing an account never use it.

What your browser does
It loads the check from challenges.cloudflare.com and communicates with Cloudflare so that Cloudflare can tell a person from an automated program. Cloudflare then gives the page a short-lived, single-use token, which is sent with your form.
What this site's server does
Before handling the form, it sends that token to Cloudflare to verify it. It does not send your IP address with it. If the check cannot be completed, the form is not processed.
What Cloudflare processes
According to Cloudflare's Turnstile privacy addendum, signals from your browser such as your IP address, TLS fingerprint, user agent, and the site key and origin of this page, for the purpose of detecting and blocking bots — not, it says, to identify, profile or target individuals. Cloudflare's documentation also states that Turnstile does not access, store or transmit form entries or other page inputs. What Cloudflare stores in your browser for the check is governed by its policy, not this one.
What this site keeps
Nothing from the check. The token is not stored or logged; the log records only whether the check passed and, if not, a fixed reason such as "expired".

Cookies and browser storage

This site's own cookies are two, they are set only when you sign in to a developer account, and there are no others. Reading the tools, the reference pages and this one sets no cookie: your analytics choice is kept in this browser's localStorage rather than in a cookie, and Google sets cookies of its own only if you allow analytics. On the four forms that use the anti-abuse check, what Cloudflare stores for it is described in its section above.

Strictly necessary, for signing in

Two cookies, both set only after you sign in, and both required for the dashboard to work at all. They are strictly necessary in the sense the ePrivacy rules use: without them there is no way to stay signed in and no way to defend a form submission, so they do not depend on an analytics choice and are not covered by the consent banner. They carry nothing about you and nothing that can identify you outside this site.

__Host-edt_session
Your session. A random value whose digest identifies the session row on the server; the value itself is not stored anywhere but in this cookie. HttpOnly so no script can read it, Secure, SameSite=Lax, Path=/, and with no Domain attribute — which is what the __Host- prefix enforces, so no other host under this domain can set one. It lasts as long as the session and is cleared when you sign out.
__Host-edt_csrf
A random seed the server uses to derive the token that proves a form submission came from a page of this site rather than from somewhere else. Same attributes, also HttpOnly: no script reads it, including ours.

Over plain HTTP — which is a local development checkout, never this site — the __Host- prefix cannot be used, because it requires Secure. The names lose the prefix there and nothing else changes.

Your analytics choice, and Google's cookies

Your choice is stored in this browser's localStorage, and Google's own cookies are set only if you allow analytics. Both are described in the next section. It is a separate question with a separate answer: refusing analytics has no effect on being able to sign in, and the two cookies above are set whatever you answered.

Analytics

No analytics is running at present, and none can run without your agreement. The site supports optional Google Analytics 4, and it is switched off in this build: no measurement property is configured, so nothing is loaded whatever you choose. This section describes what happens when it is switched on, so that it is written down before it runs rather than after.

If analytics is enabled, you will be asked once. Until you answer, and permanently if you answer no, no request is made to Google at all — not to googletagmanager.com, not to google-analytics.com, not to analytics.google.com, and not as a cookieless ping. The Google tag is not loaded into the page until you allow it. This is Google's Basic Consent Mode; the Advanced mode, which sends signals even when consent is refused, is deliberately not used here.

If you allow it, what is sent is which page you looked at, its title, and standard information your browser sends with any web request, such as your approximate location and device type. Google acts as an external analytics provider for that data and processes it under its own terms.

Your documents are never sent to Google Analytics. That is not a policy statement, it is a property of the code: the only function in this application that can send an analytics event accepts a page path with the query string and fragment stripped, a page title, and a closed list of parameters taken from the site's own public route definitions. There is no method that would accept a document value, so none can be passed to one.

Specifically, none of the following is ever sent: invoice numbers, company or person names, VAT identifiers, bank details, amounts, raw XML, validation findings, or filenames — filenames routinely contain customer names and invoice numbers, so they are treated as sensitive. Nothing you type into the contact form is sent to analytics either.

Advertising features stay off when you accept analytics. Google Signals, ad personalisation, remarketing and user identifiers are all disabled, and accepting analytics does not enable advertising storage of any kind.

Cookies and storage

Your choice is stored in this browser under the name edocumenttools_analytics_consent_v1. It holds one word, granted or denied, and nothing else — no identifier and nothing about you. It never leaves your device. The name carries a version so that if the policy materially changes, the old answer stops being recognised and you are asked again rather than having a previous yes reinterpreted.

If you allow analytics, Google sets its own cookies on this domain, typically _ga and a _ga_ cookie naming the data stream. Their lifetimes are Google's to set and are documented by Google rather than restated here, where they could quietly become wrong.

Changing your mind

Use Privacy settings at the foot of any page. Choosing to reject stops any further measurement immediately and removes the Google analytics cookies this site is able to remove from its own domain. What it cannot do is reach back into Google's systems: data already transmitted while consent was in force has already been received, and no button on this site can delete it. Google's own controls are the route for that.

Advertising

No advertising is served at present. No ad or consent script is loaded, and the site's Content-Security-Policy currently permits no third-party script origin at all — which is a check you can run yourself on the response headers rather than a claim you have to accept.

This site may carry advertising in future, because it is free to use and has running costs. If that happens, three things will be true, and they are stated here now so they can be held against the site later:

  • Advertising will never see a document. Not its bytes, not its filename, not a party name, a VAT identifier, an IBAN, an amount, an invoice number or a validation finding. Ad slots live in the page shell, above and below the tool, and no document-derived value is ever written into the URL, the page title, a meta tag or a DOM attribute an ad script could read. That boundary is enforced by tests in this project's source, not by intention.
  • Consent will come first where it is required. Personalised advertising will not be served to visitors in the EEA, the UK or Switzerland before a consent choice has been collected through a certified consent management platform.
  • This page will say so. Advertising cookies and storage, and the ad provider's own identity and policies, will be described here before any of it runs — not in the same release that turns it on.

Advertising, if it arrives, is a property of the page shell. It is separate from document processing, which stays entirely in your browser either way.

Hostile documents

Because invoices arrive from third parties, documents are screened before parsing. A document declaring a DOCTYPE or XML entities is refused outright, which closes off XML external entity attacks and entity-expansion attacks. No external resource is ever fetched on behalf of a document: an xml-stylesheet instruction is reported and ignored, never followed.

Invoice values are rendered as text. Nothing from a document is assigned to innerHTML, so markup inside an invoice — a <script> element in a note field, for example — is displayed as characters and cannot execute.

Hosting and server logs

The site is served as prerendered static pages by a Node process. Like any web server, the host records ordinary request metadata — IP address, timestamp, requested path, user agent — for operational purposes. That is a record of pages requested, not of file content: a document you open in a tool on this site never reaches the server, so there is nothing of it to record.

The same process also serves the validation API described above, where a caller does send a document on purpose. That is the one path on which a document reaches this server, it is never taken by anything on these pages, and what the API records is set out in its own section.

Third-party content

The site loads no external fonts, no trackers and no third-party content, with two exceptions, each described above and each loaded only when switched on: Google Analytics, only after you consent to it, and the Cloudflare Turnstile check, only on the four forms it protects. Everything else it serves comes from its own origin.

Closing a developer account

The account page closes an account, and it is worth being exact about what that does, because "delete my account" and what a database can honestly do are not always the same thing.

What happens immediately, in one transaction:

  • Every API key is revoked. Anything using one stops authenticating on its next request.
  • Every project is suspended, and the name you gave it is replaced with a generated one.
  • Every project is archived, so none of them appears anywhere in the dashboard again.
  • Every session is revoked and every outstanding verification or reset link is consumed. You are signed out everywhere.
  • Your email address is replaced with a non-routable placeholder and your password hash with one that can never match. The account name becomes "Closed account". Your real address is released and can be registered again.

What is kept, and why:

  • Per-day counts of requests and bytes. These are operational totals for a shared service — how much work it did, on which day — and they are what the allowance was enforced against. After closure nothing attached to them identifies you: the address is gone, the password is unusable, the account name is generic and the project names have been replaced. What remains is a number against a date.
  • The record of what you accepted. Which agreement, which version, and when. That record exists to answer a question about consent, and deleting it would destroy the evidence of the thing it documents.
  • Ordinary server logs, on the host's usual rotation, as for any visitor.

This is not the same as erasing every row, and this page does not claim that it is. If you want the retained rows removed as well, ask through the contact form and say so; it is a manual operation and it will be done.

Your rights

Data protection law gives you rights over personal data held about you — access, a copy, correction, erasure, objection, and portability. There are three kinds of personal data connected with this site, and they are very different in size:

  • A developer account, if you created one. The complete contents are listed above. You can see and change most of it yourself on the account page, and close the account there. For anything the dashboard does not do — a copy of everything held, or erasure of what closing leaves behind — ask through the contact form from the registered address.
  • Contact messages you have sent. A message you sent through the contact form exists in a mailbox, with your name and address on it. That is personal data, it is held, and you have rights over it. Ask through the contact form and it will be found and deleted.
  • Ordinary request metadata in the host's server logs — IP address, timestamp, requested path, user agent — as described above. It is not linked to any identity by this site.

There is nothing else, and in particular there is no document. A file you open in a tool is never received; a file you send to the API is discarded when the report is returned. There is no copy of one to access, correct or erase.

If you use only the browser tools, the first two do not exist either: there is no account, no identifier and no profile of you.

Getting in touch about this page

Questions about this page, a request about your own data, or a discrepancy between what it says and what the site does are all worth raising through the contact form. The claims here are meant to be exact, and an inaccurate privacy page is a defect like any other.

See also the terms of use, the disclaimer and the legal notice.