Three Reasons for a Zero, and Two Places to Put Them
Zero-rated, exempt and reverse-charged all print as nothing. They differ in who owes the tax and what can be recovered — and a schema with two values for the three does not merely lose a distinction, it invites somebody to invent a third and get charged the standard rate for trying.
On the screen they are identical: a line with a quantity, a price, and nothing in the tax column. Three different legal situations produce that same nil, and the differences between them are not subtle points of interpretation. They change who is liable for the tax, whether the seller can recover the tax on their own costs, and whether the invoice has to carry an extra sentence to be valid at all. A system that stores one of them as another is not being imprecise. It is recording something that did not happen.
Nothing here is tax advice, and this post deliberately does not classify a single real supply. Which state a particular transaction is in is your adviser's determination. What follows is about data modelling — a question you can settle on your own, and one that stops mattering the moment you have settled it.
The three states, and what actually separates them
Zero-rated
A taxable supply, charged at a rate of nought. The transaction is inside the tax system; the rate applied to it happens to be zero. Because it is a taxable supply, the tax the seller paid on their own costs to make it generally remains recoverable. The liability is the seller's and the amount is nil.
Exempt
A supply outside the charge entirely. Not taxed at nought — not taxed. The practical consequence runs in the other direction from the one above: the tax on the seller's own costs attributable to it is generally not recoverable, which means an exempt sale can be more expensive to make than a zero-rated one of the same value. There is no liability and the difference lands on the seller's costs.
Reverse-charged
The one that is structurally unlike the other two, and the reason this post exists. The supply is taxable and the tax is real — it has simply become somebody else's to account for. On a supply to a VAT-registered business in another member state, the buyer accounts for the tax in their own country. The liability exists, it is non-zero, and it belongs to the other party. The nil on the seller's invoice is not the absence of tax. It is the tax being somewhere else.
Which is why only this one has to be announced
A zero-rated line and an exempt line say what they are by being nil. A reverse-charged line cannot, because a reader has no way to tell "no tax was due" from "tax was due and you owe it". So the document has to say so in words — "btw verlegd", or "VAT reverse-charged" — and it has to name the buyer by their VAT identification number, because the sentence is meaningless unless it is clear whose obligation just moved. The reverse charge is the only one of the three states where the invoice is a notification as well as a record.
It is also worth knowing that the mechanism is not only a cross-border one. Some domestic arrangements shift the charge to the customer within the same country — construction subcontracting is the commonly cited case. Read that as a mechanism rather than as a rule you can apply; whether it bites on a particular contract is your adviser's call. What matters here is the shape: a reverse charge is a fact about a transaction, not about a border, so a system that models it as "the international case" has modelled it wrong.
What our own product does, stated exactly
We will use ourselves as the worked example, because it is the schema we can actually show you and because a post on this subject that only criticised other vendors would be worth nothing. Our resolver takes an organization default rate and an item treatment, and it has three branches.
| The treatment stored on the item | The rate the line is charged |
|---|---|
| Blank, or standard | The organization's default rate |
| Zero-rated, or exempt | Zero |
| Any other value at all | The organization's default rate |
Two things follow, and the second is worse than the first. The first is the one you would expect: zero-rated and exempt resolve to the same nil, so once a line is saved the record cannot tell you which was meant. That distinction is not decorative — it is the one that decides recoverability — and a return assembled from these records afterwards is being assembled from information the database threw away.
The second is the interesting one. There is no reverse-charge value at all, and the resolver's third branch means the obvious attempt to add one does something unfortunate.
The branch to sit with
Invent a reverse-charge value of your own and put it in that field — which is the reasonable thing for somebody who understands their own tax position to try — and the line is charged the organization's standard rate. Not an error. Not a zero. Not a warning. The value falls through to the default because the resolver does not recognise it, and the invoice looks entirely normal afterwards. Somebody doing precisely the right thing gets a document charging tax to a customer who owed nothing, and the record they leave behind looks deliberate.
A validation error would be a far smaller problem than a plausible wrong number. Rejecting an unknown value costs somebody thirty seconds. Accepting it and quietly substituting the default costs somebody a customer conversation and a credit note.
Why a missing state is worse than a missing feature
There is a temptation to file all of this under "does not support reverse charge yet", which sounds like a gap on a roadmap. It is not quite that, and the difference is worth being precise about.
A missing feature is something the system cannot do. You find out, you work around it, you move on. A missing state is something the system records incorrectly — and it records it incorrectly at the moment of saving, in a way that cannot be repaired later. If a year of invoices was issued with reverse-charged lines saved as merely zero-rated, no amount of subsequent reporting cleverness can separate them from the genuinely zero-rated ones, because the distinction was never written down. The workaround does not merely inconvenience you now; it degrades the archive.
This is the general form of the thing, and it is worth carrying to every vendor conversation you have: ask what a system stores, not what it displays. A tax status that exists only as a note somebody typed, or only as a report filter applied afterwards, is not stored. It is remembered, by a person, and only until they leave.
What a correct model looks like, in four lines
It is not a large piece of design, which is part of what makes the gap frustrating rather than forgivable.
-
A tax state on the line with more than two values
Standard, zero-rated, exempt and reverse-charged as four distinct stored states, not two outcomes. The states are stable across every VAT jurisdiction on earth, which is why this is a schema decision rather than a country feature.
-
An unrecognised value that fails rather than defaults
Anything the resolver does not know should stop the save. The current behaviour — fall through to the organization default — is the single most dangerous line in this part of our code, because it converts a typo into a plausible invoice.
-
The document wording derived from the state
If a line is reverse-charged, the invoice says so because the line says so — not because somebody remembered to type it into a notes box. The state is the source; the sentence is a rendering of it.
-
The counterparty identifier stored on the transaction
A reverse charge names the other party. That means the buyer's VAT identification number belongs on the invoice, not only on the customer record — which is also the only way a per-customer periodic listing can ever be produced from the data.
Three questions worth asking any vendor
Ask about storage, not about screens
How many distinct tax states can a line be saved in, and what are they called?
What a good answer sounds like
A list of at least four, named, immediately.
What a bad answer is telling you
If the answer is "you can set the rate to zero", the states are being confused with the rate, and the record will not survive the distinction.
If I mark a line exempt today and zero-rated tomorrow, can the records tell me which I did?
What a good answer sounds like
Two distinct stored values, visible on the record afterwards.
What a bad answer is telling you
If both store the same nil, the recoverability question has to be answered outside the system forever. Ours stores the same nil.
What happens if I put a tax treatment the system does not recognise into that field?
What a good answer sounds like
The save fails. Second best is a zero, because a zero is at least visible.
What a bad answer is telling you
If the answer is the default rate, the system will quietly produce wrong tax whenever somebody tries to be more precise than it allows. Ours does exactly this today.
What we would build, and where we stop on purpose
A fourth state, stored; a validation failure instead of a fall-through; the invoice legend rendered from the state rather than typed; and the counterparty identifier on the transaction so a periodic listing becomes possible at all. That sequence is a schema and resolver change rather than a configuration exercise, and it improves every VAT jurisdiction in the product rather than one country — which is the argument for doing it properly rather than for the Netherlands. What we will not do is decide which state a supply belongs in. That determination is your adviser's, they sign it, and a vendor offering a view on it is selling a tax opinion with a software licence attached.
What AWRA OpsHub does today
- An item-level tax treatment that travels with the item onto every document it appears on, rather than being re-decided by whoever is typing.
- A per-line rate column at two decimal places on invoices, quotations and point-of-sale lines.
- Customer-level VAT exemption that is actually applied. A customer marked exempt is not charged — a setting that was stored and inert until 5 August 2026.
- A free-text note that prints on the invoice, which is where a reverse-charge legend can go today, typed by hand.
What it does not do
- A reverse-charge treatment. There is no value to store and therefore no way to distinguish a reverse-charged line from a zero-rated one after the fact.
- A validation failure for unrecognised treatments. Today they fall through to the organization's default rate silently, which is the most consequential item in this list.
- A stored distinction between zero-rated and exempt. Both collapse to the same nil.
- The counterparty VAT number on the transaction. It exists on the customer record and reaches neither the invoice nor the line.
- Any return or listing output, and no Belastingdienst integration of any kind.
Not ours, by choice
- We will not tell you which state a supply is in, including whether a domestic arrangement shifts the charge to your customer. That is your adviser's determination and software offering a view is inviting reliance it cannot carry.
- We will not be your filing agent, even once an integration exists. The obligation is yours and software should make it answerable rather than absorb it.
The four steps above are one project and the order matters — the fourth state is worth little without the validation failure beside it, because a system that accepts anything will keep accepting the old spelling. It is well-scoped, it is not large, and it would improve every VAT market in the product rather than only this one. The precedent that we finish market-specific work of this kind is Kenya: a live tax-authority integration and a maintained statutory payroll engine, both ours and both still maintained. A written specification, a timeline and a price agreed before anything starts, and no dates on a public page.
Worth stating rather than leaving to be inferred: none of this affects a business whose sales are domestic and standard-rated. For them the default does the work correctly and this post describes a problem they do not have. The three states matter exactly when a nil appears on a line, and the reason they matter so much in the Netherlands is that there a nil is the common case rather than the exception.
What is not built for the Netherlands today can still be built for you
Anything described above as not built is a statement about what ships in the standard product today — not a limit on what AWRA OpsHub can do in the Netherlands. Kenya's eTIMS integration and its maintained payroll engine exist because Kenyan clients needed them and commissioned them; neither appeared by itself. The same door is open here. If the buyer's number on the document, and something that checks it is real, a bank or mobile money feed, a statutory return format, a rule your own operation needs that the standard one does not have, or a link to a system you already run is what stands between you and a decision, tell us and we will scope it as a build — written spec, timeline and price — before you commit to anything.
Four builds, and the first one is far smaller than the three behind it
Put the particulars on the printed invoice. Your VAT identification number, your customer's, and their address are all stored today and none of the three reaches the document — so the first build is a template and a query rather than a schema change, and it removes most of the reason a Dutch cross-border invoice would fail on inspection. Then a reverse-charge treatment that survives being saved, with the legend printed from the line's own state instead of typed into a notes box by hand, and a validation failure for treatments the resolver does not recognise rather than the silent fall-through to the standard rate it does today. Then validation of a counterparty VAT number at the point it is entered, against VIES, because the zero rate on an intra-Community supply is conditional on that number being valid and we currently accept any string. Only then a btw-aangifte and an opgaaf ICP assembled from the result — quoted last because an ICP listing is a per-customer total keyed to VAT numbers, and it cannot be built until those numbers are on the transactions in a form a query can read. A Peppol access point for business-to-government invoicing is a separate build and a present one, since that mandate has been live since January 2019.
Banks and payments
SEPA credit transfers and direct debits, iDEAL collection, and bank statement feeds wired into the Payments Register, so money in and out reconciles against the documents that authorised it rather than being re-keyed from a bank screen.
The operational work, which is what most commissions actually are
An extra approval stage in a chain that does not match the standard one, a custom field set on employees or assets that only your sector needs, an expiry that has to block an order rather than send an email, a report your board asks for in a shape nothing produces, or a scanner or weighbridge feeding the goods-in door. These are the commissions we are asked for most often and the smallest ones we quote — and unlike a revenue-authority pipeline, none of them waits on a regulator.
Payroll and statutory returns
A Dutch payroll engine with loonheffing computed on live employee records, pension administration and submission on each pay run. None of it exists today; labour cost attribution to projects and cost centres does.
Systems you already run
The accounting package, CRM, online store or custom database you intend to keep — connected through our API so a fact is entered once and appears everywhere it is needed.
How it works: you describe the requirement, we return a written scope, timeline and cost, and once agreed it is built into your environment and maintained as part of the product. No roadmap slide, and no pretending in a demo that something exists when it does not.
Tell us what you need integratedThe one-line version
Count the distinct tax states your system can save a line in. If the answer is two, it is not that the third is unsupported — it is that the third is being recorded as something it is not, permanently, and the recording happens whether or not anybody notices.
Ask us the three questions
We answered them about our own schema above, which is the only thing that makes them fair to ask of anybody else. Bring an invoice with a nil line on it and we will tell you exactly what our resolver would have stored.
Read the Netherlands page