The tax engine

Every order,
classified correctly.

This is the part nobody else does properly. The engine reads the ship-to country, the buyer, and the value, resolves the place of supply, commits to exactly one of four schemes, and applies the destination rate — before the customer ever pays.

Decimal-exact money, pure functions, every classification audit-logged.

ORDER #1042VATFlow
Ship toGB United Kingdom
BuyerB2C
NetGBP 48.00
Classified✓ resolved
Place of supplyGB
SchemeUK domestic
Rate20%
VATGBP 9.60
TotalGBP 57.60
01Four schemes

One treatment per order — never a guess.

There are only four ways a cross-border fashion order can be taxed. The engine picks one, applies it, and shows its working on the invoice. No order falls between the cracks.

20%UK_DOMESTIC

UK domestic

Goods shipped to a UK address are standard-rated at 20% and rolled straight into your UK MTD return. Place of supply resolves to GB and stays there.

OSSEU_OSS

EU One Stop Shop

B2C sales across all 27 member states are charged at the destination country’s rate — 19% to Germany, 21% to the Netherlands, 23% to Ireland — then reported on a single quarterly OSS return filed in your home state.

≤ €150EU_IOSS

Import OSS (IOSS)

Low-value goods (≤ €150) imported into the EU from outside it. VAT is collected at checkout and the parcel ships Delivered Duty Paid — the customer never gets a surprise bill at the door.

0%B2B_REVERSE

B2B reverse charge

When a buyer supplies a valid EU VAT number, VAT shifts to them under the reverse-charge mechanism. We validate the number, charge 0%, and keep the audit trail that proves it.

02Place of supply

The first question is always: whose rules apply?

Place of supply is the country whose VAT rules govern a transaction. It is not the same as the ship-to address — buyer type and goods origin can move it. The engine resolves it from four inputs, then everything else follows.

SHIP_TO

Ship-to country

The destination address — GB, DE, FR, US — read off the order at checkout.

BUYER

Buyer type

Consumer or business. A validated VAT number flips a sale into reverse charge.

VALUE

Goods value

The €150 import threshold decides whether IOSS applies to a parcel from outside the EU.

ORIGIN

Goods origin

Where the goods dispatch from sets whether this is a domestic, distance, or import sale.

Show your working

A classification you can read line by line.

The engine never hands you a total and asks you to trust it. Pass an order in and it returns the decision in full — the place of supply it resolved, the scheme it chose, the rate it pulled, and the VAT it settled. Every figure is a Decimal128 string, never a float.

  • Pure function — no database, no network, fully deterministic.
  • Same inputs always produce the same audited output.
  • Validated VAT number short-circuits to reverse charge at 0%.
classify(order)
input
  shipTo       "DE"
  buyer        "consumer"
  vatNumber    null
  net          "20.25"   // EUR, Decimal128

resolve
  placeOfSupply  "DE"
  scheme         "EU_OSS"
  rate           "0.19"  // VATRate[DE] from JSON

settle  (Big.js)
  vat            "3.85"
  total          "24.10"
  invoice        "/v1/invoices/inv_8f2a.pdf"
  audit          logged  ✓
Rules as data

Tax rules are data, not code.

Country VAT rates live in a VATRate collection seeded from a JSON file. When a rate changes or a country joins, we add rows — we don’t deploy code. The engine stays pure and the rates stay current.

That separation is why classification is the most-tested code in the product and the rate table is the easiest thing to keep right.

vat-rates.seed.json
[
  { "country": "GB", "rate": "0.20", "scheme": "UK_DOMESTIC" },
  { "country": "DE", "rate": "0.19", "scheme": "EU_OSS" },
  { "country": "NL", "rate": "0.21", "scheme": "EU_OSS" },
  { "country": "IE", "rate": "0.23", "scheme": "EU_OSS" },
  { "country": "FR", "rate": "0.20", "scheme": "EU_OSS" }
  // adding a country = adding a row
]
GBDENLIEFRESIT+22

Reverse charge, only when it’s real.

A B2B sale is only zero-rated if the buyer’s VAT number is valid. The engine checks the number before it commits to reverse charge — an invalid or missing number falls back to OSS at the destination rate, and the decision is logged either way.

FR 40 303 265 045valid · reverse charge · 0%
FR 00 000 000 000invalid · OSS · 20%

Numbers shown are illustrative. The mechanism is the point: valid wins zero-rating, anything else is charged.

03The paperwork

Compliant documents fall out of the decision.

The classification isn’t just a number — it’s the source of the invoice. Generate a PDF for every order and a matching credit note for every return, all in the same audit trail.

Compliant invoices

Every order generates a PDF invoice that shows its working — place of supply, scheme, rate, net, VAT, total — with your VAT registration numbers and the legend the treatment requires.

Credit notes on return

A return issues a matching credit note that reverses exactly what the invoice charged, links back to the original, and lands in the same audit trail.

04Filing

From settled VAT to a filed return.

Classification feeds the ledger; the ledger feeds the return. Both filings the platform owes are produced from the same audited figures — no spreadsheet, no copy-paste.

  1. 01

    EU OSS — quarterly

    Every B2C EU sale for the quarter is aggregated by destination country and exported as an OSS return — a single XML file you submit in your home member state, covering all 27.

    EXPORT · OSS · XML
  2. 02

    UK MTD — digital

    UK domestic VAT is filed to HMRC under Making Tax Digital — submitted via API from MTD-compatible software, never re-keyed into a portal.

    SUBMIT · HMRC · MTD
05Why you can trust it

Correctness isn’t a feature. It’s the architecture.

VAT is legally risky, so the engine is built to be provably right and provably auditable — not just usually accurate.

Decimal-exact money

Every money field is MongoDB Decimal128 and every calculation runs through Big.js. No JavaScript floats touch a VAT figure — ever. 19% of EUR 20.25 is EUR 3.85, not 3.8474999999.

Pure, isolated engine

Classification lives in one place — pure functions, no database, no network. It is the most-tested code in the product, and it is tested first because it is the legally-risky core.

Immutable audit log

Every state change — classification, invoice, credit note, return — writes a who / what / before / after / at entry to an append-only AuditLog. Nothing is silently rewritten.

Periodic reconciliation

A scheduled job re-checks settled VAT against the source orders, so drift surfaces before a filing deadline — not after HMRC asks.

The legally-risky core, done right

Watch your first order classify itself.

Import a catalogue, place a test order to Germany, and read the decision the engine makes — place of supply, scheme, rate, VAT — before you commit a single real sale.