De meeste code voor EU-btw begint zo:
const vat = price * (standardRate[country] / 100);
const total = price + vat;
Het werkt voor de eerste verkoop en voor de demo. Het is ook op minstens vijf manieren fout, en die komen later aan het licht, meestal op het slechtst denkbare moment: bij een terugbetaling, een correctie of een controle.
1. Tarieven veranderen, en btw gebruikt het tarief op de datum van de verkoop
Een tabel met de tarieven van vandaag beantwoordt de verkeerde vraag. Btw is verschuldigd tegen het tarief dat gold toen de verkoop plaatsvond.
Tarieven veranderen vaker dan mensen verwachten. Duitsland verlaagde zijn normale tarief voor de tweede helft van 2020 van 19% naar 16%. Finland ging in september 2024 van 24% naar 25,5%. Elke wijziging betekent:
- een terugbetaling voor een verkoop van vóór de wijziging moet het oude tarief gebruiken,
- een verkoop in december die in januari wordt gefactureerd, kan over een wijziging heen vallen,
- een correctie op de aangifte van een eerder kwartaal gebruikt de tarieven van dat kwartaal.
Om het tarief op te zoeken heb je dus een datum nodig: rate(country, date), niet rate(country). Ook historische tariefgegevens moet je controleren: zelfs officiële bronnen vermelden soms onjuiste tarieven uit het verleden.
2. Niet alles valt onder het normale tarief
EU-landen mogen op sommige producten verlaagde tarieven toepassen. Voor digitale verkopers zijn elektronische publicaties de belangrijkste: e-books, digitale kranten en digitale tijdschriften.
| Land | Normaal tarief | E-books |
|---|---|---|
| Duitsland | 19% | 7% |
| Frankrijk | 20% | 5,5% |
| Italië | 22% | 4% |
| Spanje | 21% | 4% |
| Nederland | 21% | 9% |
| Ierland | 23% | 0% |
Verkoop je e-books en vermenigvuldig je met het normale tarief, dan reken je je klanten te veel. Verkoop je e-books en templates en gebruik je voor beide één tarief, dan is een van de twee fout.
3. Zakelijke klanten betalen meestal helemaal geen btw
Is de klant een bedrijf met een geldig btw-nummer in een ander EU-land, dan breng je normaal geen btw in rekening. De klant geeft de btw aan volgens de verleggingsregeling, en je vermeldt de verlegging op je factuur.
De berekening hangt dus af van wie de klant is, en het btw-nummer moet in VIES (de opzoekdienst voor btw-nummers van de EU) worden gecontroleerd voordat je erop vertrouwt. Een nummer dat de klant in een formulier heeft getypt, bewijst niets zolang het niet is gecontroleerd.
4. Waar je gevestigd bent verandert het antwoord
Voor een bedrijf dat in één EU-land gevestigd is, kunnen grensoverschrijdende verkopen van digitale diensten aan consumenten onder € 10.000 per jaar worden belast tegen het tarief van de verkoper zelf. Daarboven geldt het tarief van de klant. De toets kijkt ook naar het vorige jaar.
Voor een bedrijf buiten de EU is er geen drempel: het tarief van de klant geldt vanaf de eerste verkoop.
standardRate[customerCountry] kan dus voor dezelfde verkoop fout zijn voor een kleine EU-verkoper en goed voor een Amerikaanse.
5. Geld als drijvendekommagetal en afronding
0.1 + 0.2 === 0.30000000000000004 // true
Geldbedragen verwerken als binaire drijvendekommagetallen kan precisiefouten veroorzaken, en btw-bedragen moeten op een vastgelegd moment op de cent worden afgerond. Elke factuurregel afronden en dan optellen kan een ander totaal geven dan eerst optellen en dan afronden. Gebruik hele centen of een decimaal type, en kies bewust één afrondingsregel.
Wat de berekening echt nodig heeft
Bij elkaar opgeteld heeft een juiste btw-berekening minstens nodig:
- het land van de klant,
- de datum van de verkoop,
- de productcategorie (normaal, of e-book en vergelijkbaar),
- of de klant een bedrijf is, en zo ja een gecontroleerd btw-nummer,
- waar jij gevestigd bent, en voor een EU-verkoper je grensoverschrijdende verkopen tot nu toe dit jaar en vorig jaar,
- decimaal rekenen met een expliciete afrondingsregel.
Dat is veel meer dan een vermenigvuldiging. Het is de reden dat Duty27 bestaat. Een verzoek ziet er zo uit:
{
"country_code": "DE",
"date": "2020-08-01",
"amount": "100.00",
"amount_type": "NET",
"b2b": false,
"category": "EBOOK"
}
Het antwoord geeft je het tarief dat op die datum gold (rate_percent), het netto-, btw- en brutobedrag als decimale strings, en of de verleggingsregeling van toepassing is. Je kunt een berekening op de homepage uitproberen zonder je aan te melden, en de API-documentatie (in het Engels) behandelt de rest, inclusief zakelijke klanten en de drempel van € 10.000.
Duty27™