POST /invoice/vat-treatment

Answers the question an e-invoicing validator cannot: who charges the VAT on this transaction, under which mechanism, where is it taxed, and what must the invoice say? Post one transaction - the two countries, goods or services, business or consumer customer, the kind of supply, the date, optionally the amount - and get a determination sourced article by article under Directive 2006/112/EC.

An invoice that omits its reverse-charge mention passes every EN 16931 rule and is still refused by the tax authority. That gap is what this endpoint closes: /invoice/validate judges the document, this judges the transaction.

The runtime is pure computation over a committed snapshot - no network call and no secret at request time. See the live /catalog for the authoritative endpoint listing and price.

The customer’s VAT number is an input, taken as declared. This endpoint performs no VIES lookup - zero network by design - so customer_vat_status says what you know, and the response echoes it in data.customer_vat_check together with the request that would check it for real: GET /company/vat, a live VIES lookup. A valid customer VAT number is a substantive condition of the intra-Community exemption (Art. 138(1)(b)) and of the Art. 196 reverse charge: declare it unknown and the exemption falls away, as it should.

x402 golden rule: the agent pays for the answer to its question. A well-formed transaction gets its determination -> 200 - and that includes a motivated undetermined, which is a result, not a failure: an uncovered regime answered with a plausible default would be worse than no answer at all. Only requests the service cannot read - a missing or unknown field, a malformed country code, a date before the rate snapshot - leave the 200 range and are not billed.

Request

POST with a JSON body. Set Content-Type: application/json. Unknown fields are refused (a typo is a 400 naming the field), never ignored.

POST /invoice/vat-treatment
Content-Type: application/json
{
  "supplier_country": "FR",
  "customer_country": "DE",
  "transaction_type": "goods",
  "customer_type": "business",
  "customer_vat_status": "valid",
  "supply_kind": "intra_eu_dispatch",
  "date": "2026-07-01",
  "amount": "12500.00",
  "currency": "EUR"
}
FieldTypeRequiredDescription
supplier_countrystringyesWhere the supplier is established, ISO 3166-1 alpha-2 (EL accepted for GR)
customer_countrystringyesWhere the customer is established, or where the goods arrive
transaction_typestringyesgoods or services
customer_typestringyesbusiness or consumer
supply_kindstringyesOne of eight closed values, below. Never inferred
datestringyesDate VAT becomes chargeable, YYYY-MM-DD. The rate served is the one in force at that date
customer_vat_statusstringno (default unknown)valid, invalid or unknown - declared, never verified here
property_countrystringwith services_land_relatedWhere the immovable property is located
amountstringnoTaxable base, plain decimal string. Supplying it triggers data.computed
currencystringwith amountISO 4217 (XXX and XTS refused - they have no billing use)

Both countries are checked together, so two bad codes come back as two issues in one 400. Territories outside the VAT territory of the Union that ISO can express (IC, EA, AX, the French overseas departments) are third territories; Monaco is FR.

The eight kinds of supply

supply_kind is a closed enumeration and is required: a value outside the list is a 400 naming the admitted ones, never a fallback to general.

supply_kindThe operation declared
generalDomestic supply, goods not dispatched (Art. 31)
intra_eu_dispatchGoods dispatched from one Member State to another (Art. 32, 138, 40)
export_outside_euGoods leaving the Union (Art. 146)
importGoods entering the Union (Art. 60, 201) - not determined, see below
services_b2b_generalServices to a taxable person (Art. 44, 196)
services_b2c_generalServices to a non-taxable person (Art. 45, 59)
services_land_relatedServices connected with immovable property (Art. 47) - add property_country
services_electronic_b2cElectronically supplied services to a consumer (Art. 58)

transaction_type and customer_type must be consistent with supply_kind: services_b2b_general declared with a consumer customer is a motivated refusal (a paid 200, undetermined), never a guess about what you meant.

The five mechanisms

data.mechanism is the verdict, and data.liable says who owes the tax:

mechanismliableWhat it means for the invoice
standardsupplierThe supplier charges VAT at the rate of the place of supply
reverse_chargecustomerNo VAT charged; the customer self-accounts. The mention is compulsory
exempt_with_creditsupplierExempt with a right to deduct (export). The exemption mention is compulsory
out_of_scopenot_taxable_in_euOutside the territorial scope of the harmonised system
undeterminedundeterminedAn honest refusal, with its rationale - a paid 200

Every verdict carries a rule_id of the form INV-VAT-*. These are Invoket identifiers and are never mixed with the normative BR-* rule ids of /invoice/validate.

200 response - UnifiedResponse

{
  "data": { ... },
  "provenance": {
    "source": "directive-2006-112 + tedb",
    "fetched_at": "2026-07-30T18:08:34Z",
    "freshness": { "kind": "snapshot", "as_of": "2026-07-27T00:00:00Z" }
  }
}
  • provenance.source: directive-2006-112 + tedb - the Directive for the rules, the Commission’s TEDB extract for the rates.
  • freshness.kind: snapshot; as_of dates the committed rate snapshot, not a fetch.

Fields of data

FieldTypeDescription
rule_idstringINV-VAT-* - the rule that decided, stable across calls
rule_summarystringThat rule in one sentence, with its articles
mechanismstringOne of the five above
liablestringsupplier, customer, not_taxable_in_eu or undetermined
place_of_supplyobjectcountry (ISO code, null when it cannot be determined - never guessed) and basis
rateobjectStandard rate of the place of supply at the requested date. Absent when there is no place of supply
required_invoice_mentionsarrayThe wordings to print, each with its basis and, where one exists, its national_basis
legal_basisarrayEvery article the determination rests on, each with a ready-made /legal/eu-act query
computedobjectServed only when amount was supplied and the mechanism is determined
customer_vat_checkobjectstatus (declared_valid, declared_invalid, not_checked) and how_to_verify
rationalestringWhy this is not the nominal case. Present exactly when there is something to explain
caveatsarrayWhat the determination assumes but does not verify (proof of dispatch, product classification…)
notesarrayRemarks on the request itself
limitsarraySix constant sentences on what this endpoint does not cover. Served with every answer

rate

FieldDescription
countryThe place of taxation whose rate is served
kindAlways standard in v1
percentageThe standard rate in force at date, each rate carrying its own validity in the snapshot
reduced_rate_candidatesReduced rates published by that State - candidates only, no product classification here
super_reduced_rate_candidatesSame, for super-reduced rates
has_regional_ratestrue when the State applies territory-specific rates (Corsica, overseas departments, Madeira, the Azores, the Greek islands) that are outside the snapshot

computed - what an agent writes on the invoice

computed.rate_percentage is what the supplier charges - 0 under a reverse charge, an exemption or out of scope - while rate.percentage is the rate of the place of taxation, which the customer self-assesses. An agent filling an invoice reads computed; an agent booking the acquisition reads rate. Amounts are rounded to the cent with the rounding of the EN 16931 engine, restated in computed.rounding.

Example - intra-EU B2B dispatch, reverse charge

A French supplier ships EUR 12,500 of goods to a German business whose VAT number is declared valid. The supply is exempt, the customer self-accounts in Germany, and four mentions are served - the English wording of the Directive and the French domestic wording, for both the reverse charge and the exemption (excerpt: two of the four):

{
  "data": {
    "rule_id": "INV-VAT-D01",
    "rule_summary": "Intra-EU B2B dispatch with a proven VAT number: exempt supply, customer self-accounts in the Member State of arrival (Art. 138, 40, 200)",
    "liable": "customer",
    "mechanism": "reverse_charge",
    "place_of_supply": {
      "country": "DE",
      "basis": {
        "celex": "32006L0112",
        "article": "40",
        "title": "Place of an intra-Community acquisition of goods: where dispatch ends",
        "query": "/legal/eu-act?celex=32006L0112&article=40"
      }
    },
    "rate": {
      "country": "DE",
      "kind": "standard",
      "percentage": "19",
      "reduced_rate_candidates": ["7"],
      "super_reduced_rate_candidates": [],
      "has_regional_rates": false
    },
    "required_invoice_mentions": [
      {
        "text": "Reverse charge",
        "language": "en",
        "basis": [
          { "celex": "32006L0112", "article": "226", "title": "Compulsory particulars on invoices", "query": "/legal/eu-act?celex=32006L0112&article=226" }
        ]
      },
      {
        "text": "Exonération de TVA, article 262 ter I du CGI",
        "language": "fr",
        "basis": [
          { "celex": "32006L0112", "article": "138", "title": "Exemption of intra-Community supplies of goods", "query": "/legal/eu-act?celex=32006L0112&article=138" },
          { "celex": "32006L0112", "article": "226", "title": "Compulsory particulars on invoices", "query": "/legal/eu-act?celex=32006L0112&article=226" }
        ],
        "national_basis": { "jurisdiction": "FR", "reference": "CGI, art. 262 ter I" }
      }
    ],
    "computed": {
      "currency": "EUR",
      "taxable_amount": "12500.00",
      "rate_percentage": "0",
      "vat_amount": "0.00",
      "total_amount": "12500.00",
      "rounding": "rounded to 2 decimals with fn:round(x*100) div 100, the rounding of the EN 16931 engine (the minor unit of every Member State currency is the hundredth)",
      "note": "The supplier charges no VAT: the customer accounts for it under the reverse charge, so the invoice total carries no VAT and must bear the mention above."
    },
    "customer_vat_check": {
      "status": "declared_valid",
      "how_to_verify": "GET /company/vat?vat_number=<the customer's VAT number, e.g. DE…> (company_grid, live VIES lookup)"
    },
    "caveats": [
      "The rate returned is the one the customer self-assesses in the Member State of arrival; the supplier invoices no VAT.",
      "The exemption is conditional on evidence that the goods left the Member State of dispatch (Art. 138(1), 131) and on filing a recapitulative statement: neither is checked here."
    ]
  }
}

All examples on this page are real service responses, abridged: the constant limits[], the full legal_basis[] and the remaining caveats[] are served in full by the endpoint.

The two rates in that answer say different things: rate.percentage is 19 % (what the German customer self-assesses), computed.rate_percentage is 0 (what the French supplier charges). Pass this determination to /invoice/generate through its vat_treatment field and the mention is written into the invoice for you.

Example - the same supply, without a proven VAT number

Same transaction, customer_vat_status left at unknown. The exemption falls away and the French supplier charges French VAT - and the response says why, in rationale:

{
  "data": {
    "rule_id": "INV-VAT-D02",
    "rule_summary": "Intra-EU B2B dispatch without a proven VAT number: no exemption, the supplier charges its own VAT (Art. 138(1)(b))",
    "liable": "supplier",
    "mechanism": "standard",
    "place_of_supply": { "country": "FR", "basis": { "celex": "32006L0112", "article": "32", "title": "Place of supply of goods dispatched or transported", "query": "/legal/eu-act?celex=32006L0112&article=32" } },
    "rate": {
      "country": "FR",
      "kind": "standard",
      "percentage": "20",
      "reduced_rate_candidates": ["5.5", "10"],
      "super_reduced_rate_candidates": ["2.1"],
      "has_regional_rates": true
    },
    "required_invoice_mentions": [],
    "rationale": "A VAT identification number of the customer, issued by another Member State and valid at the time of the supply, is a substantive condition of the exemption (Art. 138(1)(b)). It is declared as invalid or unknown here, so the exemption is not granted and the supply is taxed in the Member State of dispatch.",
    "computed": {
      "currency": "EUR",
      "taxable_amount": "12500.00",
      "rate_percentage": "20",
      "vat_amount": "2500.00",
      "total_amount": "15000.00",
      "note": "VAT is charged by the supplier at the standard rate of the place of supply."
    },
    "customer_vat_check": {
      "status": "not_checked",
      "how_to_verify": "GET /company/vat?vat_number=<the customer's VAT number, e.g. DE…> (company_grid, live VIES lookup)"
    }
  }
}

invalid and unknown are treated identically: the Directive does not distinguish “we checked and it is wrong” from “we did not check”. Both make the exemption fall away. The way out is not a flag - it is GET /company/vat, which asks VIES.

Example - undetermined, a result rather than a failure

An importation. The determination is refused, the refusal is motivated, and the answer is a paid 200:

{
  "data": {
    "rule_id": "INV-VAT-I01",
    "rule_summary": "Import of goods into the Union: customs procedure, out of v1 scope (Art. 60, 201)",
    "liable": "undetermined",
    "mechanism": "undetermined",
    "place_of_supply": { "country": null },
    "required_invoice_mentions": [],
    "legal_basis": [
      { "celex": "32006L0112", "article": "60", "title": "Place of importation of goods", "query": "/legal/eu-act?celex=32006L0112&article=60" },
      { "celex": "32006L0112", "article": "201", "title": "VAT on importation is payable by the person designated as liable", "query": "/legal/eu-act?celex=32006L0112&article=201" }
    ],
    "rationale": "VAT on importation is due in the Member State where the goods enter the Union (Art. 60), which is not derivable from the countries of the parties. Import VAT and customs regimes are outside the scope of this service.",
    "caveats": [
      "Import VAT is assessed under customs procedures, and who pays it depends on the customs status of the parties, on the incoterms and on national deferment or reverse-charge schemes (Art. 201)."
    ]
  }
}

Note what is not there: no rate, no computed, and place_of_supply.country is null rather than the country of one of the parties. An undetermined verdict never leaks a plausible-looking number.

Other real undetermined answers, each with its own rationale: a services_land_related supply without property_country (INV-VAT-L01); the same supply with it, because who accounts for the tax on immovable property is not harmonised - Art. 194 leaves it to each Member State (INV-VAT-L03); a services_b2b_general claimed for a consumer (INV-VAT-S06); a B2C service to a customer outside the Union, where Art. 59 moves only a closed list of services (INV-VAT-C02).

Example - export outside the Union

{
  "data": {
    "rule_id": "INV-VAT-X01",
    "rule_summary": "Export of goods out of the Union: exempt with credit (Art. 146)",
    "liable": "supplier",
    "mechanism": "exempt_with_credit",
    "place_of_supply": { "country": "FR", "basis": { "celex": "32006L0112", "article": "32", "title": "Place of supply of goods dispatched or transported", "query": "/legal/eu-act?celex=32006L0112&article=32" } },
    "required_invoice_mentions": [
      { "text": "VAT exempt export of goods - Article 146 of Directive 2006/112/EC", "language": "en", "basis": [ { "celex": "32006L0112", "article": "146", "title": "Exemption of exports of goods outside the Union", "query": "/legal/eu-act?celex=32006L0112&article=146" } ] },
      { "text": "Exonération de TVA, article 262 I du CGI", "language": "fr", "basis": [ { "celex": "32006L0112", "article": "146", "title": "Exemption of exports of goods outside the Union", "query": "/legal/eu-act?celex=32006L0112&article=146" } ], "national_basis": { "jurisdiction": "FR", "reference": "CGI, art. 262 I" } }
    ],
    "computed": {
      "currency": "EUR",
      "taxable_amount": "5000.00",
      "rate_percentage": "0",
      "vat_amount": "0.00",
      "total_amount": "5000.00",
      "note": "The supply is exempt with a right to deduct: no VAT is charged, and the invoice must bear the exemption mention above."
    },
    "caveats": [
      "The exemption is conditional on proof that the goods left the Union (Art. 146(1), 131): customs evidence is not checked here.",
      "Import VAT and duties in the country of destination are outside the scope of this service."
    ]
  }
}

A supply where both parties sit outside the VAT territory of the Union comes back as out_of_scope (INV-VAT-G05), with liable not_taxable_in_eu - and a rationale pointing at export_outside_eu or import if goods actually cross that border.

What this endpoint will not do

The six sentences below travel in data.limits with every answer. They are the contract, not small print.

  • The one-stop-shop schemes (OSS, IOSS) and the distance-selling thresholds of Art. 33 and 59c are not applied: a supply that falls under them is returned as undetermined, never guessed.
  • Import VAT and customs procedures (Art. 60, 201) are not determined: the person liable is designated by the Member State of importation.
  • The margin schemes (second-hand goods, works of art, travel agents) and the special scheme for investment gold are not applied.
  • Chain and triangular transactions involving more than the two parties declared are not judged, and no transport ascription is made.
  • No product classification: the rate served is the standard rate of the place of supply, reduced rates being candidates only (Annex III and national nomenclatures).
  • The verdict is rendered on the data declared in the request: no registry or VIES lookup happens here - counterparty checks are /company/resolve and /company/vat.

It is a determination, not tax advice, and it does not file anything: no VAT return, no recapitulative statement, no Intrastat.

Coverage of the rate snapshot

Rates come from a committed snapshot of the Commission’s TEDB covering 2016-01-01 onwards, each rate carrying its own validity, so a date in 2019 gets the rate that was in force in 2019. A date before the snapshot is a 400 date_out_of_range naming the covered window - a rate is never extrapolated backwards. The snapshot date is in every response (provenance.freshness.as_of).

Errors

Typed 4xx responses are not billed. Faults of the body are accumulated: one 400 lists every actionable issue at once, in issues[].

Statuscodeissues[].codeCase
400INVALID_INPUT-Body is not readable JSON, an unknown field, or a supply_kind / transaction_type / customer_type / customer_vat_status outside its enumeration - the admitted values are named
400INVALID_INVOICE_INPUTmissing_fieldA required field is absent (including currency when amount is given)
400INVALID_INVOICE_INPUTinvalid_countryNot an ISO 3166-1 alpha-2 code
400INVALID_INVOICE_INPUTinvalid_dateNot a real calendar date in YYYY-MM-DD form
400INVALID_INVOICE_INPUTdate_out_of_rangeDate before the rate snapshot
400INVALID_INVOICE_INPUTinvalid_decimalamount is not a plain decimal (scientific notation is refused)
400INVALID_INVOICE_INPUTinvalid_currencyXXX or XTS - ISO 4217 codes with no billing use
500INTERNAL-Internal error (detail logged, not exposed)
{
  "code": "INVALID_INVOICE_INPUT",
  "error": "invoice input is invalid: 2 actionable issue(s) listed in issues[]",
  "issues": [
    { "code": "invalid_country", "message": "supplier_country must be an ISO 3166-1 alpha-2 country code, got \"FRA\"", "path": "supplier_country" },
    { "code": "invalid_country", "message": "customer_country must be an ISO 3166-1 alpha-2 country code, got \"DEU\"", "path": "customer_country" }
  ]
}
{
  "code": "INVALID_INVOICE_INPUT",
  "error": "invoice input is invalid: 1 actionable issue(s) listed in issues[]",
  "issues": [
    { "code": "date_out_of_range", "message": "date 2010-01-01 predates the VAT rate snapshot, which covers 2016-01-01 onwards (rates in force before that date are not known to the service)", "path": "date" }
  ]
}

Every refusal names what is admitted, so a second call can succeed.

Attribution

The rules are those of Council Directive 2006/112/EC on the common system of value added tax, as published on EUR-Lex; the articles cited are queryable through GET /legal/eu-act. The rates come from a committed extract of the European Commission’s Taxes in Europe Database (TEDB). National invoice wordings cite their own domestic basis in national_basis.

See also

  • POST /invoice/vat-treatment/batch - the same determination on up to 200 transactions, in one settlement.
  • POST /invoice/generate - pass this determination as vat_treatment and the compulsory mention is written into the invoice.
  • POST /invoice/validate - the EN 16931 verdict on a document, plus the vat_consistency block that flags an invoice contradicting its own VAT logic.
  • GET /company/vat - the live VIES check this endpoint deliberately does not perform.
  • GET /legal/eu-act - the text of the articles cited in legal_basis, at a date.
  • For agents - discovery surfaces, the live /catalog and how settlement works.