<?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]]></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.hashnode.dev</link><image><url>https://cdn.hashnode.com/uploads/logos/6a99b55043444b21ec1f7e0b/59949d06-587b-442d-9a20-8978ffe9e696.png</url><title>VAT Engine</title><link>https://vat-engine.hashnode.dev</link></image><generator>RSS for Node</generator><lastBuildDate>Thu, 24 Sep 2026 20:09:18 GMT</lastBuildDate><atom:link href="https://vat-engine.hashnode.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[EU VAT for SaaS & Subscription Billing]]></title><description><![CDATA[Selling SaaS subscriptions across the EU turns VAT into more than a simple percentage calculation.
The billing flow may need to consider the customer's country, product tax treatment, whether the disp]]></description><link>https://vat-engine.hashnode.dev/eu-vat-for-saas-subscription-billing</link><guid isPermaLink="true">https://vat-engine.hashnode.dev/eu-vat-for-saas-subscription-billing</guid><category><![CDATA[SaaS]]></category><category><![CDATA[saas development ]]></category><category><![CDATA[ecommerce]]></category><category><![CDATA[shopify]]></category><category><![CDATA[headless]]></category><category><![CDATA[Headless Commerce]]></category><category><![CDATA[finance]]></category><dc:creator><![CDATA[Vasyl Kyryliuk]]></dc:creator><pubDate>Fri, 18 Sep 2026 17:47:38 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6a99b55043444b21ec1f7e0b/9652745d-55a8-44eb-bcb7-7e67f6f5dfd0.jpg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Selling SaaS subscriptions across the EU turns VAT into more than a simple percentage calculation.</p>
<p>The billing flow may need to consider the customer's country, product tax treatment, whether the displayed price already includes VAT, the transaction date, refunds or corrections, and the information finance teams will need later for reporting.</p>
<p>VAT Engine is designed to keep those pieces connected instead of forcing every SaaS product to maintain its own VAT tables and tax logic.</p>
<h2>EU VAT becomes part of the billing architecture</h2>
<p>A typical SaaS billing system is already responsible for subscriptions, renewals, invoices, payments, cancellations, and refunds.</p>
<p>EU VAT adds another layer of decisions.</p>
<p>For a transaction, your application may need to know:</p>
<ul>
<li><p>which country the sale belongs to</p>
</li>
<li><p>which <a href="https://vat-engine.app/docs/api/tax-classes">tax class</a> applies to the product</p>
</li>
<li><p>which <a href="https://vat-engine.app/docs/api/rates">VAT rate</a> should be used</p>
</li>
<li><p>whether the amount is VAT-inclusive or VAT-exclusive</p>
</li>
<li><p>which transaction date should be considered</p>
</li>
<li><p>and what context should be retained for later review</p>
</li>
</ul>
<p>A billing system that stores only something like `VAT rate: 19%` loses much of the information needed to understand that result later.</p>
<p>VAT Engine separates VAT calculation from the rest of the billing implementation while keeping the relevant transaction context available.</p>
<h2>Calculate VAT from structured transaction data</h2>
<p>A SaaS application can send transaction information to the VAT Engine REST API and receive a structured <a href="https://vat-engine.app/docs/api/calculate">VAT calculation</a> result.</p>
<p>Typical calculation inputs include:</p>
<ul>
<li><p>destination country</p>
</li>
<li><p>product tax class</p>
</li>
<li><p>transaction amount</p>
</li>
<li><p>currency</p>
</li>
<li><p>VAT-inclusive or VAT-exclusive pricing</p>
</li>
<li><p>transaction date</p>
</li>
</ul>
<p>This allows your own application to remain responsible for subscriptions and payments while VAT-specific rate resolution and calculation logic is handled separately.</p>
<p>A simplified flow looks like:</p>
<p><strong>**Customer → SaaS billing flow → VAT Engine → VAT result → Payment → Transaction record**</strong></p>
<p>The API can be used from a custom checkout, subscription backend, billing service, or internal application.</p>
<h2>Handle VAT-inclusive and VAT-exclusive pricing correctly</h2>
<p>The same VAT rate produces different arithmetic depending on how a price is represented.</p>
<p>If a subscription costs €100 before VAT and the applicable rate is 20%, VAT is added to the net amount.</p>
<p>The result is:</p>
<pre><code class="language-plaintext">Net: €100
VAT: €20
Gross: €120
</code></pre>
<p>But if the customer-facing €100 price already includes 20% VAT, the VAT portion is not €20.</p>
<p>It must be extracted from the gross amount.</p>
<p>VAT Engine makes the pricing basis explicit so the calling application does not have to infer whether VAT should be added or extracted.</p>
<p>This can be particularly useful when the same SaaS product serves different customer types, markets, or pricing models.</p>
<h2>Use the transaction date when working with older records</h2>
<p>Subscription systems do not only process transactions created today.</p>
<p>Teams frequently need to work with:</p>
<ul>
<li><p>refunds</p>
</li>
<li><p>corrections</p>
</li>
<li><p>imported historical transactions</p>
</li>
<li><p>billing migrations</p>
</li>
<li><p>reconciliation</p>
</li>
<li><p>audit or accountant reviews</p>
</li>
</ul>
<p>Using today's VAT rate for every historical operation can produce a result that does not match the original transaction.</p>
<p>VAT Engine supports date-aware lookup using recorded rate windows where historical coverage is available.</p>
<p>This means the transaction date can participate in VAT rate resolution instead of the system automatically assuming the currently active rate.</p>
<p>Recorded lookup windows are kept distinct from a guarantee of legally verified historical applicability. Stronger source provenance and deterministic historical replay are areas being developed further.</p>
<h2>Keep enough context to understand the result later</h2>
<p>For financial systems, returning the correct number is only part of the job.</p>
<p>Imagine someone reviews a subscription transaction several months later and asks:</p>
<p><strong>Why was this VAT treatment applied?</strong></p>
<p>A percentage alone does not answer that question.</p>
<p>A useful transaction record can retain context such as:</p>
<ul>
<li><p>country</p>
</li>
<li><p>product tax class</p>
</li>
<li><p>transaction date</p>
</li>
<li><p>original amount</p>
</li>
<li><p>currency</p>
</li>
<li><p>VAT-inclusive or VAT-exclusive pricing basis</p>
</li>
<li><p>VAT result</p>
</li>
<li><p>source identity</p>
</li>
<li><p>calculation timestamps</p>
</li>
<li><p>available rate context</p>
</li>
</ul>
<p>Keeping this information together makes later reconciliation, refunds, reporting, and accountant review easier than reconstructing the original VAT decision from several disconnected systems.</p>
<h2>Support renewals and recurring billing</h2>
<p>Recurring subscription billing creates a new transaction each time a customer renews.</p>
<p>Instead of permanently hard-coding VAT rates into a billing service, the application can resolve VAT using the transaction context relevant to each renewal.</p>
<p>This provides a cleaner separation between:</p>
<ul>
<li><p>subscription logic</p>
</li>
<li><p>payment processing</p>
</li>
<li><p><a href="https://vat-engine.app/docs/api/calculate">VAT calculation</a></p>
</li>
<li><p><a href="https://vat-engine.app/docs/api/transactions">transaction records</a></p>
</li>
<li><p><a href="https://vat-engine.app/docs/api/compliance">compliance preparation</a></p>
</li>
</ul>
<p>It also means VAT-related logic can evolve without requiring every billing workflow to maintain its own copy of tax data.</p>
<h2>Handle refunds and corrections with historical context</h2>
<p>Refunds are one of the places where transaction context becomes particularly important.</p>
<p>A refund issued today may relate to a subscription transaction created months earlier.</p>
<p>The original:</p>
<ul>
<li><p>transaction date</p>
</li>
<li><p>country</p>
</li>
<li><p>product classification</p>
</li>
<li><p>price basis</p>
</li>
<li><p>and recorded VAT context</p>
</li>
</ul>
<p>can all matter when reviewing how the refund should relate to the original sale.</p>
<p>Keeping the original transaction record available is generally more useful than attempting to reconstruct everything from today's configuration.</p>
<h2>Prepare transaction data for OSS workflows</h2>
<p>For B2C SaaS sales across EU countries, VAT calculation is only one part of the operational process.</p>
<p>Finance or accounting teams eventually need an organized set of transactions that can be reviewed by reporting period, country, and source.</p>
<p>VAT Engine provides compliance-oriented workflows around committed transaction records, including support for:</p>
<ul>
<li><p>OSS/IOSS preparation</p>
</li>
<li><p>transaction review</p>
</li>
<li><p>accountant-oriented exports</p>
</li>
<li><p>multi-source reporting</p>
</li>
<li><p>reconciliation</p>
</li>
</ul>
<p>VAT Engine does not submit VAT returns on behalf of the business and does not replace professional tax advice.</p>
<p>The purpose is to make the underlying VAT data easier to organize, inspect, and prepare for downstream compliance work.</p>
<h2>Keep multiple billing sources organized</h2>
<p>As a SaaS business grows, revenue may start arriving through more than one system.</p>
<p>For example:</p>
<ul>
<li><p>the main subscription checkout</p>
</li>
<li><p>an additional storefront</p>
</li>
<li><p>marketplace sales</p>
</li>
<li><p>imported historical billing records</p>
</li>
<li><p>internal payment flows</p>
</li>
<li><p>connected commerce platforms</p>
</li>
</ul>
<p>VAT Engine uses source profiles to keep transactions attributable to the system or sales channel they came from.</p>
<p>That provides a consistent source model for reporting and reconciliation instead of requiring separate tax-data structures for every integration.</p>
<h2>Use SME threshold data alongside VAT workflows</h2>
<p>VAT obligations can also depend on the circumstances of the business itself.</p>
<p>VAT Engine provides <a href="https://vat-engine.app/docs/api/sme-thresholds">EU SME VAT threshold</a> data that can be used alongside other compliance workflows, including values represented in EUR and relevant national currencies where supported.</p>
<p>Keeping threshold information accessible through the same platform reduces the need to maintain another independent dataset inside the application.</p>
<h2>Where VAT Engine fits into a SaaS stack</h2>
<p>VAT Engine is not intended to replace your payment processor or subscription-management platform.</p>
<p>Your existing systems can continue handling:</p>
<ul>
<li><p>subscriptions</p>
</li>
<li><p>payment methods</p>
</li>
<li><p>invoices</p>
</li>
<li><p>payment collection</p>
</li>
<li><p>cancellations</p>
</li>
<li><p>customer accounts</p>
</li>
</ul>
<p>VAT Engine provides the VAT-specific layer around those workflows:</p>
<ul>
<li><p>EU VAT calculation</p>
</li>
<li><p>VAT rate resolution</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><a href="https://vat-engine.app/docs/api/sme-thresholds">SME VAT</a> threshold data</p>
</li>
<li><p><a href="https://vat-engine.app/docs/api/compliance#oss--ioss-tax-registrations">OSS/IOSS</a> preparation workflows</p>
</li>
</ul>
<p>The REST API can be integrated into an existing architecture without requiring VAT Engine to become the system responsible for the entire billing lifecycle.</p>
<h3>Example: a new B2C subscription</h3>
<p>Consider a SaaS customer purchasing a subscription from another EU country.</p>
<p>The billing application collects the required transaction context and sends the relevant data to VAT Engine.</p>
<p>VAT Engine resolves the recorded VAT rate and calculates the VAT amounts.</p>
<p>The billing application can then use the result when presenting or processing the transaction.</p>
<p>After the sale, the transaction context can be retained for reporting and later review.</p>
<h3>Example: a subscription renewal</h3>
<p>When the subscription renews, the billing service creates a new transaction.</p>
<p>The current transaction context can be evaluated again rather than assuming that every renewal must reuse tax data stored when the customer originally subscribed.</p>
<p>This keeps recurring billing logic separate from VAT rate maintenance.</p>
<h3>Example: refunding an older subscription</h3>
<p>A refund may relate to a transaction that occurred during an earlier reporting period.</p>
<p>The original transaction date and recorded VAT context provide a better basis for reviewing the refund than simply applying today's rate.</p>
<p>Date-aware lookup and retained transaction records help support that workflow.</p>
<h3>Example: migrating historical billing data</h3>
<p>A SaaS company moving from another billing architecture may need to import older transactions.</p>
<p>Historical records can be organized using consistent source profiles, tax classes, countries, dates, and recorded VAT context.</p>
<p>That creates a more structured foundation for reconciliation and future reporting.</p>
<h2>Who this use case is for</h2>
<p>VAT Engine can be useful for:</p>
<ul>
<li><p>SaaS businesses selling subscriptions across EU countries</p>
</li>
<li><p>developers building custom subscription billing systems</p>
</li>
<li><p>B2C digital service providers</p>
</li>
<li><p>finance teams preparing OSS data</p>
</li>
<li><p>platforms that need VAT calculation through an API</p>
</li>
<li><p>teams reconciling or migrating historical billing data</p>
</li>
</ul>
<h2>Keep VAT logic outside your billing code</h2>
<p>A SaaS billing system already has enough responsibilities.</p>
<p>Maintaining VAT rates, tax classifications, historical rate context, and compliance-oriented transaction records does not necessarily need to become another permanent part of that codebase.</p>
<p>VAT Engine provides a dedicated EU VAT layer that can be integrated through the API while keeping the transaction context needed for later review.</p>
<p><strong>**VAT Engine is currently available in free alpha. No payment method is required.**</strong></p>
]]></content:encoded></item><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.hashnode.dev/why-a-vat-api-needs-more-than-a-rate-lookup</link><guid isPermaLink="true">https://vat-engine.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/55914f23-9484-4473-bd3c-d18403031f83.jpg" 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 <a href="https://vat-engine.app/docs">VAT API</a> 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><a href="https://vat-engine.app/docs/integrations/shopify">Shopify</a></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 <a href="https://vat-engine.app/docs/api/calculate">calculation</a></p>
</li>
<li><p>TEDB-backed <a href="https://vat-engine.app/docs/api/rates">rate data</a></p>
</li>
<li><p>product <a href="https://vat-engine.app/docs/api/tax-classes">tax classes</a></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><a href="https://vat-engine.app/docs/api/compliance">OSS/IOSS</a> 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>