<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[VAT Engine Journal]]></title><description><![CDATA[Technical articles on EU VAT APIs, ecommerce integrations, SaaS, security, compliance workflows, and the engineering decisions behind VAT Engine.]]></description><link>https://vat-engine-journal.hashnode.dev</link><image><url>https://cdn.hashnode.com/uploads/logos/6a99b55043444b21ec1f7e0b/59949d06-587b-442d-9a20-8978ffe9e696.png</url><title>VAT Engine Journal</title><link>https://vat-engine-journal.hashnode.dev</link></image><generator>RSS for Node</generator><lastBuildDate>Mon, 07 Sep 2026 04:12:44 GMT</lastBuildDate><atom:link href="https://vat-engine-journal.hashnode.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Why a VAT API Needs More Than a Rate Lookup]]></title><description><![CDATA[When developers first add VAT to an ecommerce or SaaS product, the problem can look surprisingly small:

Find the customer's country.

Look up the VAT rate.

Multiply the price by that percentage.

Do]]></description><link>https://vat-engine-journal.hashnode.dev/why-a-vat-api-needs-more-than-a-rate-lookup</link><guid isPermaLink="true">https://vat-engine-journal.hashnode.dev/why-a-vat-api-needs-more-than-a-rate-lookup</guid><category><![CDATA[api]]></category><category><![CDATA[vat]]></category><category><![CDATA[ecommerce]]></category><category><![CDATA[SaaS]]></category><category><![CDATA[software development]]></category><dc:creator><![CDATA[Vasyl Kyryliuk]]></dc:creator><pubDate>Thu, 03 Sep 2026 23:21:03 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6a99b55043444b21ec1f7e0b/caf2d76e-ed3e-47e0-a9da-a09e4b96d5bb.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>When developers first add VAT to an ecommerce or SaaS product, the problem can look surprisingly small:</p>
<ol>
<li><p>Find the customer's country.</p>
</li>
<li><p>Look up the VAT rate.</p>
</li>
<li><p>Multiply the price by that percentage.</p>
</li>
<li><p>Done.</p>
</li>
</ol>
<p>That works until the first real edge cases arrive.</p>
<p>What product was sold? Was the displayed price VAT-inclusive? Which country actually has taxing rights? Was this transaction created today or six months ago? Is it a refund of an older sale? Which rate was used when the original transaction happened?</p>
<p>At that point, a VAT integration stops being a percentage lookup and starts becoming a data and decision-traceability problem.</p>
<h2>A country does not have one VAT rate</h2>
<p>A basic VAT table might look like this:</p>
<pre><code class="language-json">{
  "DE": 19,
  "FR": 20,
  "IT": 22
}
</code></pre>
<p>Useful, but incomplete.</p>
<p>EU member states can apply standard, reduced, zero, and other rates depending on the type of supply. Books, accommodation, food, pharmaceuticals, and other categories may receive different treatment.</p>
<p>So the more useful question is not:</p>
<blockquote>
<p>What is Germany's VAT rate?</p>
</blockquote>
<p>It is closer to:</p>
<blockquote>
<p>Which VAT rate applies in Germany to this product category for this transaction?</p>
</blockquote>
<p>That means a useful API needs product tax context, not only a country code.</p>
<h2>The transaction date matters</h2>
<p>Using today's rate for every calculation creates another problem.</p>
<p>Imagine processing:</p>
<ul>
<li><p>a refund for an order placed last year,</p>
</li>
<li><p>an imported historical transaction,</p>
</li>
<li><p>an audit of an older sale,</p>
</li>
<li><p>a correction to previously recorded data.</p>
</li>
</ul>
<p>The rate that is active today is not necessarily the rate that was used for the original transaction.</p>
<p>A VAT API therefore benefits from accepting an explicit transaction or supply date:</p>
<pre><code class="language-json">{
  "country": "DE",
  "tax_class": "standard",
  "date": "2026-01-15"
}
</code></pre>
<p>The response can then identify the recorded rate window used for that lookup.</p>
<p>One important distinction: a recorded historical window and a legally verified effective date are not automatically the same thing.</p>
<p>If the underlying source data does not prove legal applicability for a historical period, the API should make that limitation explicit rather than pretending to know more than it does.</p>
<p>Failing clearly is much safer than silently returning a convenient number.</p>
<h2>VAT-inclusive and VAT-exclusive prices are different calculations</h2>
<p>There is also a basic arithmetic distinction that often gets buried inside tax code.</p>
<p>If €100 is VAT-exclusive at 20%, the total is:</p>
<pre><code class="language-text">Net:   €100
VAT:    €20
Gross: €120
</code></pre>
<p>But if €100 already includes 20% VAT, the VAT portion is not €20.</p>
<p>It is:</p>
<pre><code class="language-text">VAT = 100 - (100 / 1.20)
</code></pre>
<p>which is approximately €16.67.</p>
<p>An API should therefore require the caller to make the price basis explicit instead of guessing.</p>
<p>For financial calculations, I also prefer integer minor units rather than floating-point money:</p>
<pre><code class="language-json">{
  "amount": 10000,
  "currency": "EUR",
  "price_includes_vat": true
}
</code></pre>
<p>Here <code>10000</code> represents €100.00.</p>
<p>That avoids a whole class of floating-point rounding problems.</p>
<h2>Returning the correct number is only half the job</h2>
<p>Suppose an API returns this:</p>
<pre><code class="language-json">{
  "vat_rate": 0.19,
  "vat_amount": 1597
}
</code></pre>
<p>Six months later, someone asks:</p>
<blockquote>
<p>Why did this transaction use 19% VAT?</p>
</blockquote>
<p>The number alone cannot answer that.</p>
<p>A more useful calculation record may also retain:</p>
<ul>
<li><p>country,</p>
</li>
<li><p>product tax class,</p>
</li>
<li><p>transaction date,</p>
</li>
<li><p>VAT-inclusive/exclusive basis,</p>
</li>
<li><p>input amount,</p>
</li>
<li><p>rate used,</p>
</li>
<li><p>source/store identity,</p>
</li>
<li><p>calculation timestamp,</p>
</li>
<li><p>relevant rate-data version or provenance where available.</p>
</li>
</ul>
<p>This turns the VAT result from a disposable API response into something that can actually be reviewed later.</p>
<h2>Source identity matters in multi-store commerce</h2>
<p>The problem becomes more visible when a business has several sales channels.</p>
<p>An order might come from:</p>
<ul>
<li><p>Shopify,</p>
</li>
<li><p>a custom checkout,</p>
</li>
<li><p>another marketplace,</p>
</li>
<li><p>an imported CSV,</p>
</li>
<li><p>an internal billing system.</p>
</li>
</ul>
<p>For reporting purposes, simply storing "transaction 12345" may not be enough.</p>
<p>The system also needs to know which source owns that transaction.</p>
<p>That is why I think source profiles are useful as a first-class concept rather than just another string attached to an order.</p>
<p>They make it possible to group and reconcile records without losing where those records originally came from.</p>
<h2>Compliance workflows need committed data</h2>
<p>There is another important boundary between a calculator and a compliance system.</p>
<p>Someone calling a VAT calculator ten times should not automatically create ten filing records.</p>
<p>Reporting workflows need a defined population of committed business transactions, not every exploratory API request ever made.</p>
<p>That separation becomes important for OSS/IOSS preparation, accountant review, exports, and reconciliation.</p>
<p>Calculation and compliance can share the same data model, but they should not be treated as the same action.</p>
<h2>What I am building around these ideas</h2>
<p>These problems are what pushed VAT Engine beyond a simple VAT-rate endpoint.</p>
<p>The current direction combines:</p>
<ul>
<li><p>EU VAT calculation,</p>
</li>
<li><p>TEDB-backed rate data,</p>
</li>
<li><p>product tax classes,</p>
</li>
<li><p>date-aware rate lookup,</p>
</li>
<li><p>transaction records,</p>
</li>
<li><p>source profiles,</p>
</li>
<li><p>SME VAT threshold data,</p>
</li>
<li><p>OSS/IOSS preparation workflows,</p>
</li>
<li><p>ecommerce integrations.</p>
</li>
</ul>
<p>There is still more work to do, particularly around stronger rate provenance, immutable source evidence, and deterministic replay.</p>
<p>The long-term goal is not just to answer:</p>
<blockquote>
<p>What VAT rate should I use?</p>
</blockquote>
<p>It is to make it possible to answer:</p>
<blockquote>
<p>What information produced this VAT result, and can I understand that decision later?</p>
</blockquote>
<p>For financial infrastructure, I think that second question is ultimately the more interesting one.</p>
]]></content:encoded></item></channel></rss>