Skip to content

EU VAT rate feed

EU VAT rate feed

The engine can source live EU member-state VAT rates from a real, public, permissively-licensed dataset instead of the shipped static snapshot. This page documents exactly which dataset, under what license, and how it is wired.

The dataset

Name ibericode/vat-rates — "Community maintained resource for VAT rates of EU member states"
URL (canonical) https://raw.githubusercontent.com/ibericode/vat-rates/master/vat-rates.json
Repository https://github.com/ibericode/vat-rates
License MIT (permissive) — see the repository's LICENSE
Provenance A community-maintained fork of adamcooke/vat-rates; a compilation of EU VAT rates, not the EU Commission TEDB itself
Coverage The 27 EU member states plus the UK (28 country entries)
Adapter IbericodeVatRateSource

Honest provenance. This is a community compilation, not a primary tax authority. The maintainers state plainly that they "cannot be held responsible for its accuracy or completeness." Treat it as a good, refreshable default — pin/mirror a copy and re-verify against each member state's own guidance before relying on it for filing. For a primary source, enable the live EU Commission TEDB feed instead (tax.tedb.live) — it needs no API key, and it is the tax authority's own database rather than a compilation of it. See rate sources.

Dataset shape

Schema version: 4. Each country maps to a list of rate periods (newest last), keyed by effective_from (YYYY-MM-DD, with 0000-01-01 as the open-ended base):

{
  "details": "https://github.com/ibericode/vat-rates",
  "version": 4,
  "items": {
    "DK": [ { "effective_from": "0000-01-01", "rates": { "standard": 25 } } ],
    "FR": [
      { "effective_from": "2014-01-01",
        "rates": { "super_reduced": 2.1, "reduced1": 5.5, "reduced2": 10, "standard": 20 },
        "exceptions": [ { "name": "Guadeloupe", "postcode": "971\\d{2,}", "standard": 8.5 } ] }
    ]
  }
}
  • The adapter selects the period in force at the assessment date ($at, or now) and resolves the standard rate authoritatively.
  • The dataset carries reduced tiers (reduced, reduced1, reduced2, super_reduced, parking, press_publications) but does not map them to product categories. The adapter therefore resolves the standard rate by default and only returns a reduced tier when an operator supplies an authoritative category → tier map — the package never guesses which tier a category belongs to. (EU e-services are generally standard-rated; e-books and similar reduced cases need an explicit mapping.)
  • Territorial exceptions (Canary Islands, French overseas départements, …) are postcode-scoped and not applied at country granularity.

How it is wired

Disabled by default — the static snapshot stays the zero-config default. Enable the feed and the provider composes ChainTaxRateSource(EU feed → static snapshot): the feed is authoritative, the shipped static rates are the fallback (deny-by-default is preserved — if neither has a rate, the engine denies).

TAX_EU_VAT_FEED=true
# Optional: override the URL to a pinned mirror or a TEDB export.
# TAX_EU_VAT_URL=https://your-mirror.example/vat-rates.json

A URL source is wrapped in CachingTaxRateSource automatically (one request per lookup otherwise); a local file path is read directly. The config URL is config-driven end-to-end — see config/tax.php and rate sources.