VIES is the EU's live VAT-validation gateway; PrestaShop's native VAT field is stored but never checked against it. The reverse-charge rules below reflect EU VAT as it stands in 2026; your tax authority and accountant remain responsible for whether a given sale is exempt. Paths cover PrestaShop 1.7, 8 and 9.
Here is the situation a VAT-registered B2B customer in another EU country expects when they land on your PrestaShop store: they type their VAT number, the price drops to net, and the invoice they download says "reverse charge" instead of charging them tax they would only have to claim back. Get that right and you have a frictionless cross-border B2B sale. Get it wrong. Charge VAT you shouldn't have, or exempt a number that turns out invalid, and you are either losing the customer or carrying the tax liability yourself. This guide is specifically about automating the verification: how PrestaShop checks a VAT number against the EU's VIES system, where that check actually happens in the code, and how to turn a valid number into an exempt order without manual work.
This is one piece of a larger B2B setup. Deciding which customers see net prices, how the tax display itself switches, and how you vet a trade applicant in the first place are their own jobs, covered in the siblings linked throughout. Here we own one question: making the VAT exemption fire automatically and correctly.
The rule you are automating: intra-EU reverse charge
The tax logic is narrow and worth stating precisely, because the automation is only as good as the conditions it checks. When a VAT-registered business sells goods or services to a VAT-registered business in a different EU member state, the seller does not charge VAT. The buyer self-assesses it on their own return, the "reverse charge", which spares them reclaiming foreign VAT. For the exemption to be legitimate, all of the following must hold:
- Both parties are VAT-registered businesses.
- They are in different EU member states (a German seller and a German B2B buyer still pay German VAT).
- The buyer's VAT number is valid, confirmed against VIES, not just well-formatted.
- The supply genuinely crosses the border.
Miss any one of these and normal VAT applies. That is exactly why a format check ("does it look like a French number?") is not enough on its own, and why the automation has to talk to VIES.
VIES: the only authoritative check
VIES (VAT Information Exchange System) is the European Commission's official service for confirming that a VAT number is real and active. You send it a country code plus a number; it answers valid or invalid, and, depending on the member state, returns the registered company name and address. There is no substitute. A regex that confirms the number has the right length and country prefix tells you nothing about whether the number is actually registered, which is the only thing that matters for an exemption you may have to defend in an audit.
The practical catch is reliability. VIES is a real-time gateway to individual national tax databases, so it goes down for maintenance, individual member states drop offline, and responses can lag. So what does that mean for your checkout? Your automation must never let a VIES timeout block a sale. The correct behaviour when VIES is unreachable is to accept the order, charge VAT as normal (the safe default), and flag the order for manual review or a re-check, not to hang the customer on a spinning validator. An exemption you can apply retroactively after a successful re-check is recoverable; an abandoned cart is not.
VIES exposes a SOAP web service, which is the endpoint any PrestaShop VAT-validation module calls under the hood. A bare-bones PHP call looks like this. Useful to know exactly what a module is doing on your behalf, and what a timeout actually means:
// VIES SOAP check – country code + number, returned valid/invalid (+name/address where the state shares it).
// Wrap in try/catch: a SoapFault here = VIES unreachable, NOT an invalid number.
try {
$client = new SoapClient(
'https://ec.europa.eu/taxation_customs/vies/services/checkVatService.wsdl',
array('connection_timeout' => 10) // never hang the checkout on a slow gateway
);
$res = $client->checkVat(array(
'countryCode' => 'FR', // ISO country code (use XI for Northern Ireland)
'vatNumber' => '12345678901', // digits only, no country prefix
));
// $res->valid === true|false; $res->name / $res->address where the member state returns them.
} catch (SoapFault $e) {
// VIES down or timed out -> take the order WITH VAT, flag for manual re-check. Do not block.
}
Note the two distinct failure modes: $res->valid === false means VIES answered and the number is not registered (reject the exemption); a SoapFault means VIES didn't answer at all (charge VAT, flag, re-check later). Conflating them is the classic bug. A government outage should never look like an invalid customer.
What PrestaShop does natively, and where it stops
PrestaShop ships more of this than most merchants realise, but it stops short of the full automation. The native pieces:
- A VAT number field on addresses. The vat_number field lives on the Address object (stored in the ps_address table; you'll see it on the address form at checkout and when editing an address under Customers → Addresses). Whether it appears is governed per country by International → Locations → Countries → [country] → "Do you need a tax identification number?", and the company/VAT fields are surfaced by enabling B2B mode (below). There is no separate global "show VAT field" toggle.
- A "B2B mode" switch. Shop Parameters → Customer Settings → Enable B2B mode (the PS_B2B_ENABLE configuration value) exposes company/VAT fields and B2B-oriented customer data.
- Tax comes from tax rules and addresses, not from a VIES check. This is the crucial limitation. PrestaShop charges tax based on the tax rules attached to products together with the customer's address (country/state/zone). Not on a live VIES check, and not on group membership. A customer group controls the price display method (tax-included vs tax-excluded display) and reductions, but it does not natively zero out the VAT charged. The native vat_number field is stored and printed on the invoice, and core may apply basic field validation, but it should not be treated as authoritative VAT validation: PrestaShop core does not call VIES and does not automatically zero out tax because a number was entered.
In other words, out of the box you can collect a VAT number and you can build a customer group that shows net prices, but there is no native "tax-exempt group" that removes VAT. Groups are useful for net/gross display and pricing visibility; the actual VAT exemption needs correct tax-rule and address logic, or a module/custom tax manager. The bridge between "this number is valid at VIES" and "therefore this customer is exempt" is the part you have to add. How a net-pricing group is built and how prices flip to net for it is sibling territory: see net prices vs gross prices: tax display switching for the display mechanics and customer groups in PrestaShop for the group setup itself.
Where the exemption actually fires in PrestaShop

To automate this cleanly, it helps to know which lever moves the tax. There are two honest routes, and they behave differently:
| Mechanism | How tax is removed | When it applies | Trade-off |
|---|---|---|---|
| Net-pricing customer group | The group's price_display_method controls only tax-included vs tax-excluded display. Set it to tax-excluded so the customer sees net prices. The actual tax rate charged still comes from each product's tax rule plus the address (country/state/zone) rules, not from the group | The customer sees net prices store-wide the moment they're in the group | Net display is tied to group membership, but display is not exemption: the group does not zero the VAT charged, so the legal 0% still has to come from tax/address logic |
| Address-level tax exemption | The Tax / TaxManager layer resolves the rate per the delivery address country and tax rules group. Native PrestaShop does not automatically treat a valid intra-EU VAT number as a reverse-charge trigger; module/custom logic has to validate the VAT number and either alter the tax calculation or select an appropriate tax-rule path that yields 0% | Per order, based on the address used at checkout | Closer to the real legal rule (it's the cross-border supply that matters), but needs custom logic to read VIES and adjust the cart's tax |
Under the hood the tax is computed through PrestaShop's TaxManagerFactory / TaxCalculator when a cart total is built, reading the tax rules group on each product and the customer's address zone. An automation either (a) moves a VIES-verified customer into a net-pricing group and applies a compliant 0% tax path for that order, or (b) hooks the cart/order tax resolution directly. The key thing to keep straight is that the group only changes the net/gross display. Riding PrestaShop's own pricing engine for the display is robust (no forked tax math, no surprises at invoice time, survives upgrades), but the legal 0% VAT still has to be applied through tax logic keyed to the delivery/invoice address, the seller's country, VAT validation and the supply rules. So the verification step has to encode "valid VIES number AND different member state" before it both promotes the customer for net display and triggers the exemption.
The automated flow, end to end
A properly automated tax-exemption flow on PrestaShop looks like this:
- Collect the number early. Capture the VAT number at registration, not buried at the end of checkout, so the customer sees correct (net) prices from their first logged-in page load rather than a tax surprise that reverses at the last step.
- Validate against VIES in real time. On submit, call VIES (country code + number) and give the customer immediate visual feedback, a green confirmation with the returned company name, or a clear rejection. Format-check first to avoid wasting a VIES round-trip on an obviously malformed entry, then make the authoritative call.
- Check the country condition. Confirm the customer's country differs from your shop's country. A same-country B2B buyer is verified but not exempt, a step a naive automation skips and an auditor does not.
- Promote on success. Assign the verified customer to the net-pricing group so PrestaShop's own pricing engine renders net prices, that handles the display. Separately, apply the 0% VAT through compliant tax logic keyed to the delivery/invoice address, the seller's country, the VAT validation and the supply rules, so the order itself carries the exemption rather than just showing net figures.
- Annotate the invoice. The generated invoice must show the reverse-charge notation (below). Automatically, the moment VAT is exempted.
- Degrade safely. On a VIES timeout, don't block: take the order with VAT charged and flag it for manual re-check.
Verifying that a number is valid is not the same as deciding the applicant is a real trade customer you want to extend net pricing and accounts to. That vetting (company evidence, manual approval, fraud screening) is its own job, covered in trade account applications: verifying business customers before access.
Invoice requirements when you exempt
An exempt invoice is not just "the same invoice with €0 tax." Under the EU VAT Directive it must carry specific information, or the exemption isn't properly documented:
- Your own VAT number.
- The customer's VAT number (the one you verified).
- An explicit reverse-charge note, e.g. "Reverse charge. VAT to be accounted for by the recipient, Article 196, Council Directive 2006/112/EC" (use the local-language equivalent where required).
- The total stated without VAT.
In PrestaShop the invoice is generated by the OrderInvoice object and rendered through the HTMLTemplateInvoice class; the cleanest way to add a conditional reverse-charge line is via the invoice template / a hook rather than hand-editing PDFs after the fact. Manual annotation across dozens of orders is precisely where compliance errors creep in.
Edge cases that break naive automation
Same-country sales. A valid VAT number from a customer in your own country is still a domestic sale, charge normal VAT. The reverse charge is strictly intra-EU cross-border. Any automation that exempts on "valid number" alone is wrong here.
Northern Ireland (XI numbers). Post-Brexit, Northern Ireland stays inside the EU VAT system for goods and uses XI-prefixed VAT numbers, which VIES validates. The rest of Great Britain (GB) is a third country and outside this mechanism entirely. Your validation needs to treat XI as in-scope and GB as out.
New member states and format drift. When a country joins the EU its VAT format has to be recognised by your validation. Lean on VIES as the source of truth rather than a hard-coded regex table you'll forget to update.
Identity fraud. A determined fraudster enters a genuine VAT number belonging to a different company to dodge VAT. VIES says "valid", but the name and address it returns won't match the order. When VIES returns the registered company details, cross-check them against the order's company and address before exempting. A mismatch is a flag for review, not an automatic exemption.
EC Sales List reporting. Reverse-charge sales must be reported to your tax authority on an EC Sales List (typically quarterly). That means tracking which orders were exempted and to whom. A reason to keep the exemption decision as structured order data, not a free-text note.
Record-keeping: prove you checked
The exemption is only defensible if you can show you verified the number at the time of sale. For each exempted order, store: the VAT number, the validation timestamp, the raw VIES response (valid/invalid plus any returned name/address), and the order it belongs to. Retention requirements vary by member state, commonly several years, often up to ten, so check your local rule and keep the log that long. If an automation exempts tax but logs nothing, you have automated your way into an audit problem.
Frequently asked questions
Does PrestaShop validate VAT numbers against VIES out of the box?
No. Core stores the vat_number on the address and may apply light format checks, but it never calls VIES and never zeroes VAT because a number was entered. That bridge, live VIES validation plus the exemption it triggers, is the gap a module like the Automatic EU VAT Checker exists to close. Without it, an entered number is just text printed on the invoice.
VIES was down when my customer checked out, what should happen?
The order should go through with VAT charged, flagged for a manual re-check, never blocked. A VIES outage (a SoapFault in the code above) is a government-side failure, not an invalid customer, so treating it as "rejected" loses you a legitimate sale. Once VIES is back you re-validate and, if the number checks out, apply the exemption retroactively. The rule of thumb: a recoverable exemption beats an abandoned cart every time.
A customer in my own country entered a valid VAT number. Do I exempt them?
No. The reverse charge is strictly intra-EU cross-border. A German business buying from a German store pays full German VAT even with a perfectly valid number. Any automation that exempts on "valid" alone is wrong here. The country-difference check is a mandatory second condition, and it's the one naive setups skip.
What about UK and Northern Ireland VAT numbers?
Northern Ireland (XI-prefixed numbers) stays inside the EU VAT system for goods and validates through VIES, treat XI as in-scope. The rest of Great Britain (GB numbers) is a third country and falls outside the reverse-charge mechanism entirely; VIES won't validate a GB number for this purpose. Your validation has to distinguish the two, which a hard-coded regex table usually gets wrong over time.
Can I just put VAT-exempt customers in a net-pricing group and call it done?
That handles the display, the customer sees net prices, but a group does not zero the VAT actually charged. PrestaShop computes tax from the product's tax rule plus the delivery address, not from group membership. So you need both: the group for net display and a compliant 0% tax path keyed to the address and the verified number for the legal exemption. Conflating "shows net" with "is exempt" is the most common configuration mistake on this whole topic.
How mypresta.rocks fits in
The gap PrestaShop leaves, a stored VAT field that nobody calls VIES against, is exactly the kind of thing a focused module closes without forking your tax engine or your theme. The Automatic EU VAT Checker validates at registration and checkout, encodes the cross-border condition (so it never exempts a same-country buyer), degrades safely when VIES is down, and keeps the validation log an audit asks for. The benefit you're buying is twofold: the customer feels an instant green-light when their number checks out and net prices that appear immediately rather than reversing at the final step; you feel exemptions that fire automatically against the live VIES record, a reverse-charge line that lands on the invoice without manual editing, and a stored validation log ready if your tax authority ever asks. Because the right implementation promotes verified customers into a dedicated B2B/VAT-verified group for net display and access, and adds module logic for the legal exemption, rather than rewriting tax math, it rides the platform's pricing engine for display and survives upgrades. If you're standing up B2B from scratch, start with the overview of selling B2B on PrestaShop, then wire net pricing, group assignment, and, if you offer accounts, deferred payment terms on top of the verified-customer foundation this automation gives you.
The principle underneath all of it: a VAT number is not a checkbox, it's a claim you are legally choosing to act on. Automating the exemption is worth doing precisely because the manual version, eyeballing numbers, hand-editing invoices, remembering the same-country rule at 6pm on a Friday, is where the costly mistakes live. Let VIES be the authority, let PrestaShop's group engine do the pricing, and keep the log that proves you did it right.